xref: /illumos-gate/usr/src/uts/common/io/chxge/com/tp.c (revision 2d6eb4a5e0a47d30189497241345dc5466bb68ab)
1*d39a76e7Sxw161283 /*
2*d39a76e7Sxw161283  * CDDL HEADER START
3*d39a76e7Sxw161283  *
4*d39a76e7Sxw161283  * The contents of this file are subject to the terms of the
5*d39a76e7Sxw161283  * Common Development and Distribution License (the "License").
6*d39a76e7Sxw161283  * You may not use this file except in compliance with the License.
7*d39a76e7Sxw161283  *
8*d39a76e7Sxw161283  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*d39a76e7Sxw161283  * or http://www.opensolaris.org/os/licensing.
10*d39a76e7Sxw161283  * See the License for the specific language governing permissions
11*d39a76e7Sxw161283  * and limitations under the License.
12*d39a76e7Sxw161283  *
13*d39a76e7Sxw161283  * When distributing Covered Code, include this CDDL HEADER in each
14*d39a76e7Sxw161283  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*d39a76e7Sxw161283  * If applicable, add the following below this CDDL HEADER, with the
16*d39a76e7Sxw161283  * fields enclosed by brackets "[]" replaced with your own identifying
17*d39a76e7Sxw161283  * information: Portions Copyright [yyyy] [name of copyright owner]
18*d39a76e7Sxw161283  *
19*d39a76e7Sxw161283  * CDDL HEADER END
20*d39a76e7Sxw161283  */
21*d39a76e7Sxw161283 
22*d39a76e7Sxw161283 /*
23*d39a76e7Sxw161283  * Copyright (C) 2003-2005 Chelsio Communications.  All rights reserved.
24*d39a76e7Sxw161283  */
25*d39a76e7Sxw161283 
26*d39a76e7Sxw161283 #include "common.h"
27*d39a76e7Sxw161283 #include "regs.h"
28*d39a76e7Sxw161283 #include "tp.h"
29*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
30*d39a76e7Sxw161283 #include "fpga_defs.h"
31*d39a76e7Sxw161283 #endif
32*d39a76e7Sxw161283 
33*d39a76e7Sxw161283 struct petp {
34*d39a76e7Sxw161283 	adapter_t *adapter;
35*d39a76e7Sxw161283 };
36*d39a76e7Sxw161283 
37*d39a76e7Sxw161283 /* Pause deadlock avoidance parameters */
38*d39a76e7Sxw161283 #define DROP_MSEC 16
39*d39a76e7Sxw161283 #define DROP_PKTS_CNT  1
40*d39a76e7Sxw161283 
41*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
42*d39a76e7Sxw161283 
pm_num_pages(u32 size,u32 pg_size)43*d39a76e7Sxw161283 static inline u32 pm_num_pages(u32 size, u32 pg_size)
44*d39a76e7Sxw161283 {
45*d39a76e7Sxw161283 	u32 num = size / pg_size;
46*d39a76e7Sxw161283 	num -= num % 24;
47*d39a76e7Sxw161283 	return num;
48*d39a76e7Sxw161283 }
49*d39a76e7Sxw161283 
tp_pm_configure(adapter_t * adapter,struct tp_params * p)50*d39a76e7Sxw161283 static void tp_pm_configure(adapter_t *adapter, struct tp_params *p)
51*d39a76e7Sxw161283 {
52*d39a76e7Sxw161283 	u32 num;
53*d39a76e7Sxw161283 
54*d39a76e7Sxw161283 	num = pm_num_pages(p->pm_size - p->pm_rx_base, p->pm_rx_pg_size);
55*d39a76e7Sxw161283 	if (p->pm_rx_num_pgs > num)
56*d39a76e7Sxw161283 		p->pm_rx_num_pgs = num;
57*d39a76e7Sxw161283 
58*d39a76e7Sxw161283 	num = pm_num_pages(p->pm_rx_base - p->pm_tx_base, p->pm_tx_pg_size);
59*d39a76e7Sxw161283 	if (p->pm_tx_num_pgs > num)
60*d39a76e7Sxw161283 		p->pm_tx_num_pgs = num;
61*d39a76e7Sxw161283 
62*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_PM_SIZE, p->pm_size);
63*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_PM_RX_BASE, p->pm_rx_base);
64*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_PM_TX_BASE, p->pm_tx_base);
65*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_PM_DEFRAG_BASE, p->pm_size);
66*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_PM_RX_PG_SIZE, p->pm_rx_pg_size);
67*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_PM_RX_MAX_PGS, p->pm_rx_num_pgs);
68*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_PM_TX_PG_SIZE, p->pm_tx_pg_size);
69*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_PM_TX_MAX_PGS, p->pm_tx_num_pgs);
70*d39a76e7Sxw161283 }
71*d39a76e7Sxw161283 
tp_cm_configure(adapter_t * adapter,u32 cm_size)72*d39a76e7Sxw161283 static void tp_cm_configure(adapter_t *adapter, u32 cm_size)
73*d39a76e7Sxw161283 {
74*d39a76e7Sxw161283 	u32 mm_base = (cm_size >> 1);
75*d39a76e7Sxw161283 	u32 mm_sub_size = (cm_size >> 5);
76*d39a76e7Sxw161283 
77*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_CM_SIZE, cm_size);
78*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_CM_MM_BASE, mm_base);
79*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_CM_TIMER_BASE, (cm_size >> 2) * 3);
80*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_CM_MM_P_FLST_BASE,
81*d39a76e7Sxw161283 		       mm_base + 5 * mm_sub_size);
82*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_CM_MM_TX_FLST_BASE,
83*d39a76e7Sxw161283 		       mm_base + 6 * mm_sub_size);
84*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_CM_MM_RX_FLST_BASE,
85*d39a76e7Sxw161283 		       mm_base + 7 * mm_sub_size);
86*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_CM_MM_MAX_P, 0x40000);
87*d39a76e7Sxw161283 }
88*d39a76e7Sxw161283 
tp_delayed_ack_ticks(adapter_t * adap,unsigned int tp_clk)89*d39a76e7Sxw161283 static unsigned int tp_delayed_ack_ticks(adapter_t *adap, unsigned int tp_clk)
90*d39a76e7Sxw161283 {
91*d39a76e7Sxw161283 	u32 tr = t1_read_reg_4(adap, A_TP_TIMER_RESOLUTION);
92*d39a76e7Sxw161283 
93*d39a76e7Sxw161283 	return tp_clk /	(1 << G_DELAYED_ACK_TIMER_RESOLUTION(tr));
94*d39a76e7Sxw161283 }
95*d39a76e7Sxw161283 
t1_tp_ticks_per_sec(adapter_t * adap,unsigned int tp_clk)96*d39a76e7Sxw161283 static unsigned int t1_tp_ticks_per_sec(adapter_t *adap, unsigned int tp_clk)
97*d39a76e7Sxw161283 {
98*d39a76e7Sxw161283 	u32 tr = t1_read_reg_4(adap, A_TP_TIMER_RESOLUTION);
99*d39a76e7Sxw161283 
100*d39a76e7Sxw161283 	return tp_clk /	(1 << G_GENERIC_TIMER_RESOLUTION(tr));
101*d39a76e7Sxw161283 }
102*d39a76e7Sxw161283 
tp_set_tcp_time_params(adapter_t * adapter,unsigned int tp_clk)103*d39a76e7Sxw161283 static void tp_set_tcp_time_params(adapter_t *adapter, unsigned int tp_clk)
104*d39a76e7Sxw161283 {
105*d39a76e7Sxw161283 	u32 tps = t1_tp_ticks_per_sec(adapter, tp_clk);
106*d39a76e7Sxw161283 	u32 tp_scnt;
107*d39a76e7Sxw161283 
108*d39a76e7Sxw161283 #define SECONDS * tps
109*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_2MSL, (1 SECONDS)/2);
110*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_RXT_MIN, (1 SECONDS)/4);
111*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_RXT_MAX, 64 SECONDS);
112*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_PERS_MIN, (1 SECONDS)/2);
113*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_PERS_MAX, 64 SECONDS);
114*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_KEEP_IDLE, 7200 SECONDS);
115*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_KEEP_INTVL, 75 SECONDS);
116*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_INIT_SRTT, 3 SECONDS);
117*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_FINWAIT2_TIME, 60 SECONDS);
118*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_FAST_FINWAIT2_TIME, 3 SECONDS);
119*d39a76e7Sxw161283 #undef SECONDS
120*d39a76e7Sxw161283 
121*d39a76e7Sxw161283 	/* Set Retransmission shift max */
122*d39a76e7Sxw161283 	tp_scnt = t1_read_reg_4(adapter, A_TP_SHIFT_CNT);
123*d39a76e7Sxw161283 	tp_scnt &= (~V_RETRANSMISSION_MAX(0x3f));
124*d39a76e7Sxw161283 	tp_scnt |= V_RETRANSMISSION_MAX(14);
125*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_SHIFT_CNT, tp_scnt);
126*d39a76e7Sxw161283 
127*d39a76e7Sxw161283 	/* Set DACK timer to 200ms */
128*d39a76e7Sxw161283 	t1_write_reg_4(adapter, A_TP_DACK_TIME,
129*d39a76e7Sxw161283 		       tp_delayed_ack_ticks(adapter, tp_clk) / 5);
130*d39a76e7Sxw161283 }
131*d39a76e7Sxw161283 
t1_tp_set_coalescing_size(struct petp * tp,unsigned int size)132*d39a76e7Sxw161283 int t1_tp_set_coalescing_size(struct petp *tp, unsigned int size)
133*d39a76e7Sxw161283 {
134*d39a76e7Sxw161283 	u32 val;
135*d39a76e7Sxw161283 
136*d39a76e7Sxw161283 	if (size > TP_MAX_RX_COALESCING_SIZE)
137*d39a76e7Sxw161283 		return -EINVAL;
138*d39a76e7Sxw161283 
139*d39a76e7Sxw161283 	val = t1_read_reg_4(tp->adapter, A_TP_PARA_REG3);
140*d39a76e7Sxw161283 
141*d39a76e7Sxw161283 	if (tp->adapter->params.nports > 1)
142*d39a76e7Sxw161283 		size = 9904;
143*d39a76e7Sxw161283 
144*d39a76e7Sxw161283 	if (size) {
145*d39a76e7Sxw161283 		u32 v = t1_is_T1B(tp->adapter) ? 0 : V_MAX_RX_SIZE(size);
146*d39a76e7Sxw161283 
147*d39a76e7Sxw161283 		/* Set coalescing size. */
148*d39a76e7Sxw161283 		t1_write_reg_4(tp->adapter, A_TP_PARA_REG2,
149*d39a76e7Sxw161283 			       V_RX_COALESCE_SIZE(size) | v);
150*d39a76e7Sxw161283 
151*d39a76e7Sxw161283 		val |= (F_RX_COALESCING_PSH_DELIVER | F_RX_COALESCING_ENABLE);
152*d39a76e7Sxw161283 	} else
153*d39a76e7Sxw161283 		val &= ~F_RX_COALESCING_ENABLE;
154*d39a76e7Sxw161283 
155*d39a76e7Sxw161283 	t1_write_reg_4(tp->adapter, A_TP_PARA_REG3, val);
156*d39a76e7Sxw161283 	return 0;
157*d39a76e7Sxw161283 }
158*d39a76e7Sxw161283 
t1_tp_get_mib_statistics(adapter_t * adap,struct tp_mib_statistics * tps)159*d39a76e7Sxw161283 void t1_tp_get_mib_statistics(adapter_t *adap, struct tp_mib_statistics *tps)
160*d39a76e7Sxw161283 {
161*d39a76e7Sxw161283 	u32 *data = (u32 *)tps;
162*d39a76e7Sxw161283 	int i;
163*d39a76e7Sxw161283 
164*d39a76e7Sxw161283 	t1_write_reg_4(adap, A_TP_MIB_INDEX, 0);
165*d39a76e7Sxw161283 
166*d39a76e7Sxw161283 	for (i = 0; i < sizeof(*tps) / sizeof(u32); i++)
167*d39a76e7Sxw161283 		*data++ = t1_read_reg_4(adap, A_TP_MIB_DATA);
168*d39a76e7Sxw161283 }
169*d39a76e7Sxw161283 #endif
170*d39a76e7Sxw161283 
tp_init(adapter_t * ap,const struct tp_params * p,unsigned int tp_clk)171*d39a76e7Sxw161283 static void tp_init(adapter_t *ap, const struct tp_params *p,
172*d39a76e7Sxw161283 		    unsigned int tp_clk)
173*d39a76e7Sxw161283 {
174*d39a76e7Sxw161283 	if (t1_is_asic(ap)) {
175*d39a76e7Sxw161283 		u32 val;
176*d39a76e7Sxw161283 
177*d39a76e7Sxw161283 		val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM |
178*d39a76e7Sxw161283 		      F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET;
179*d39a76e7Sxw161283 		if (!p->pm_size)
180*d39a76e7Sxw161283 			val |= F_OFFLOAD_DISABLE;
181*d39a76e7Sxw161283 		else
182*d39a76e7Sxw161283 			val |= F_TP_IN_ESPI_CHECK_IP_CSUM |
183*d39a76e7Sxw161283 				F_TP_IN_ESPI_CHECK_TCP_CSUM;
184*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_IN_CONFIG, val);
185*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_OUT_CONFIG, F_TP_OUT_CSPI_CPL |
186*d39a76e7Sxw161283 			       F_TP_OUT_ESPI_ETHERNET |
187*d39a76e7Sxw161283 			       F_TP_OUT_ESPI_GENERATE_IP_CSUM |
188*d39a76e7Sxw161283 			       F_TP_OUT_ESPI_GENERATE_TCP_CSUM);
189*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_GLOBAL_CONFIG, V_IP_TTL(64) |
190*d39a76e7Sxw161283 			       F_PATH_MTU /* IP DF bit */ |
191*d39a76e7Sxw161283 			       V_5TUPLE_LOOKUP(p->use_5tuple_mode) |
192*d39a76e7Sxw161283 			       V_SYN_COOKIE_PARAMETER(29));
193*d39a76e7Sxw161283 
194*d39a76e7Sxw161283                 /*
195*d39a76e7Sxw161283                  * Enable pause frame deadlock prevention.
196*d39a76e7Sxw161283                  */
197*d39a76e7Sxw161283                 if (is_T2(ap) && ap->params.nports > 1) {
198*d39a76e7Sxw161283                         u32 drop_ticks = DROP_MSEC * (tp_clk / 1000);
199*d39a76e7Sxw161283 
200*d39a76e7Sxw161283                         t1_write_reg_4(ap, A_TP_TX_DROP_CONFIG,
201*d39a76e7Sxw161283                                        F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR |
202*d39a76e7Sxw161283                                        V_DROP_TICKS_CNT(drop_ticks) |
203*d39a76e7Sxw161283                                        V_NUM_PKTS_DROPPED(DROP_PKTS_CNT));
204*d39a76e7Sxw161283                 }
205*d39a76e7Sxw161283 
206*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
207*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_GLOBAL_RX_CREDITS, 0xffffffff);
208*d39a76e7Sxw161283 		val = V_WINDOW_SCALE(1) | F_MSS | V_DEFAULT_PEER_MSS(576);
209*d39a76e7Sxw161283 
210*d39a76e7Sxw161283 		/* We don't want timestamps for T204, otherwise we don't know
211*d39a76e7Sxw161283 		 * the MSS.
212*d39a76e7Sxw161283 		 */
213*d39a76e7Sxw161283 		if (ap->params.nports == 1)
214*d39a76e7Sxw161283 			val |= V_TIMESTAMP(1);
215*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_TCP_OPTIONS, val);
216*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_DACK_CONFIG, V_DACK_MSS_SELECTOR(1) |
217*d39a76e7Sxw161283 			       F_DACK_AUTO_CAREFUL | V_DACK_MODE(1));
218*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_BACKOFF0, 0x3020100);
219*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_BACKOFF1, 0x7060504);
220*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_BACKOFF2, 0xb0a0908);
221*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_BACKOFF3, 0xf0e0d0c);
222*d39a76e7Sxw161283 
223*d39a76e7Sxw161283 		/* We do scheduling in software for T204, increase the cong.
224*d39a76e7Sxw161283 		 * window to avoid TP holding on to payload longer than we
225*d39a76e7Sxw161283 		 * expect.
226*d39a76e7Sxw161283 		 */
227*d39a76e7Sxw161283 		if (ap->params.nports == 1)
228*d39a76e7Sxw161283 			t1_write_reg_4(ap, A_TP_PARA_REG0, 0xd1269324);
229*d39a76e7Sxw161283 		else
230*d39a76e7Sxw161283 			t1_write_reg_4(ap, A_TP_PARA_REG0, 0xd6269324);
231*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_SYNC_TIME_HI, 0);
232*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_SYNC_TIME_LO, 0);
233*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_INT_ENABLE, 0);
234*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_CM_FC_MODE, 0);   /* Enable CM cache */
235*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_PC_CONGESTION_CNTL, 0x6186);
236*d39a76e7Sxw161283 
237*d39a76e7Sxw161283 		/*
238*d39a76e7Sxw161283 		 * Calculate the time between modulation events, which affects
239*d39a76e7Sxw161283 		 * both the Tx and Rx pipelines.  Larger values force the Tx
240*d39a76e7Sxw161283 		 * pipeline to wait before processing modulation events, thus
241*d39a76e7Sxw161283 		 * allowing Rx to use the pipeline.  A really small delay can
242*d39a76e7Sxw161283 		 * starve the Rx side from accessing the pipeline.
243*d39a76e7Sxw161283 		 *
244*d39a76e7Sxw161283 		 * A balanced value is optimal.  This is roughly 9us per 1G.
245*d39a76e7Sxw161283 		 * The Tx needs a low delay time for handling a lot of small
246*d39a76e7Sxw161283 		 * packets. Too big of a delay could cause Tx not to achieve
247*d39a76e7Sxw161283 		 * line rate.
248*d39a76e7Sxw161283 		 */
249*d39a76e7Sxw161283 		val = (9 * tp_clk) / 1000000;
250*d39a76e7Sxw161283 		/* adjust for multiple ports */
251*d39a76e7Sxw161283 		if (ap->params.nports > 1) {
252*d39a76e7Sxw161283 			val = 0;
253*d39a76e7Sxw161283 		}
254*d39a76e7Sxw161283 		if (is_10G(ap))               /* adjust for 10G */
255*d39a76e7Sxw161283 			val /= 10;
256*d39a76e7Sxw161283 		/*
257*d39a76e7Sxw161283 		 * Bit 0 must be 0 to keep the timer insertion property.
258*d39a76e7Sxw161283 		 */
259*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_TIMER_SEPARATOR, val & ~1);
260*d39a76e7Sxw161283 
261*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_TIMER_RESOLUTION, 0xF0011);
262*d39a76e7Sxw161283 		tp_set_tcp_time_params(ap, tp_clk);
263*d39a76e7Sxw161283 
264*d39a76e7Sxw161283 		/* PR3229 */
265*d39a76e7Sxw161283 		if (is_T2(ap)) {
266*d39a76e7Sxw161283 			val = t1_read_reg_4(ap, A_TP_PC_CONFIG);
267*d39a76e7Sxw161283 			val |= V_DIS_TX_FILL_WIN_PUSH(1);
268*d39a76e7Sxw161283 			t1_write_reg_4(ap, A_TP_PC_CONFIG, val);
269*d39a76e7Sxw161283 		}
270*d39a76e7Sxw161283 
271*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
272*d39a76e7Sxw161283 	} else {    /* FPGA */
273*d39a76e7Sxw161283 		t1_write_reg_4(ap, A_TP_TIMER_RESOLUTION, 0xD000A);
274*d39a76e7Sxw161283 #endif
275*d39a76e7Sxw161283 #endif
276*d39a76e7Sxw161283 	}
277*d39a76e7Sxw161283 }
278*d39a76e7Sxw161283 
t1_tp_destroy(struct petp * tp)279*d39a76e7Sxw161283 void t1_tp_destroy(struct petp *tp)
280*d39a76e7Sxw161283 {
281*d39a76e7Sxw161283 	t1_os_free((void *)tp, sizeof(*tp));
282*d39a76e7Sxw161283 }
283*d39a76e7Sxw161283 
t1_tp_create(adapter_t * adapter,struct tp_params * p)284*d39a76e7Sxw161283 struct petp * __devinit t1_tp_create(adapter_t *adapter, struct tp_params *p)
285*d39a76e7Sxw161283 {
286*d39a76e7Sxw161283 	struct petp *tp = t1_os_malloc_wait_zero(sizeof(*tp));
287*d39a76e7Sxw161283 	if (!tp)
288*d39a76e7Sxw161283 		return NULL;
289*d39a76e7Sxw161283 
290*d39a76e7Sxw161283 	tp->adapter = adapter;
291*d39a76e7Sxw161283 
292*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
293*d39a76e7Sxw161283 	if (p->pm_size) {                     /* Default PM partitioning */
294*d39a76e7Sxw161283 		p->pm_rx_base = p->pm_size >> 1;
295*d39a76e7Sxw161283 #ifdef TDI_SUPPORT
296*d39a76e7Sxw161283 		p->pm_tx_base = 2048 * 1024;    /* reserve 2 MByte for REGION MAP */
297*d39a76e7Sxw161283 #else
298*d39a76e7Sxw161283 		p->pm_tx_base = 64 * 1024;    /* reserve 64 kbytes for REGION MAP */
299*d39a76e7Sxw161283 #endif
300*d39a76e7Sxw161283 		p->pm_rx_pg_size = 64 * 1024;
301*d39a76e7Sxw161283 
302*d39a76e7Sxw161283 		if (adapter->params.nports == 1)
303*d39a76e7Sxw161283 			p->pm_tx_pg_size = 64 * 1024;
304*d39a76e7Sxw161283 		else
305*d39a76e7Sxw161283 			p->pm_tx_pg_size = 16 * 1024;
306*d39a76e7Sxw161283 		p->pm_rx_num_pgs = pm_num_pages(p->pm_size - p->pm_rx_base,
307*d39a76e7Sxw161283 						p->pm_rx_pg_size);
308*d39a76e7Sxw161283 		p->pm_tx_num_pgs = pm_num_pages(p->pm_rx_base - p->pm_tx_base,
309*d39a76e7Sxw161283 						p->pm_tx_pg_size);
310*d39a76e7Sxw161283 	}
311*d39a76e7Sxw161283 #endif
312*d39a76e7Sxw161283 	return tp;
313*d39a76e7Sxw161283 }
314*d39a76e7Sxw161283 
t1_tp_intr_enable(struct petp * tp)315*d39a76e7Sxw161283 void t1_tp_intr_enable(struct petp *tp)
316*d39a76e7Sxw161283 {
317*d39a76e7Sxw161283 	u32 tp_intr = t1_read_reg_4(tp->adapter, A_PL_ENABLE);
318*d39a76e7Sxw161283 
319*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
320*d39a76e7Sxw161283 	if (!t1_is_asic(tp->adapter)) {
321*d39a76e7Sxw161283 		/* FPGA */
322*d39a76e7Sxw161283 		t1_write_reg_4(tp->adapter, FPGA_TP_ADDR_INTERRUPT_ENABLE,
323*d39a76e7Sxw161283 			       0xffffffff);
324*d39a76e7Sxw161283 		t1_write_reg_4(tp->adapter, A_PL_ENABLE,
325*d39a76e7Sxw161283 			       tp_intr | FPGA_PCIX_INTERRUPT_TP);
326*d39a76e7Sxw161283 	} else
327*d39a76e7Sxw161283 #endif
328*d39a76e7Sxw161283 	{
329*d39a76e7Sxw161283 		/* We don't use any TP interrupts */
330*d39a76e7Sxw161283 		t1_write_reg_4(tp->adapter, A_TP_INT_ENABLE, 0);
331*d39a76e7Sxw161283 		t1_write_reg_4(tp->adapter, A_PL_ENABLE,
332*d39a76e7Sxw161283 			       tp_intr | F_PL_INTR_TP);
333*d39a76e7Sxw161283 	}
334*d39a76e7Sxw161283 }
335*d39a76e7Sxw161283 
t1_tp_intr_disable(struct petp * tp)336*d39a76e7Sxw161283 void t1_tp_intr_disable(struct petp *tp)
337*d39a76e7Sxw161283 {
338*d39a76e7Sxw161283 	u32 tp_intr = t1_read_reg_4(tp->adapter, A_PL_ENABLE);
339*d39a76e7Sxw161283 
340*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
341*d39a76e7Sxw161283 	if (!t1_is_asic(tp->adapter)) {
342*d39a76e7Sxw161283 		/* FPGA */
343*d39a76e7Sxw161283 		t1_write_reg_4(tp->adapter, FPGA_TP_ADDR_INTERRUPT_ENABLE, 0);
344*d39a76e7Sxw161283 		t1_write_reg_4(tp->adapter, A_PL_ENABLE,
345*d39a76e7Sxw161283 			       tp_intr & ~FPGA_PCIX_INTERRUPT_TP);
346*d39a76e7Sxw161283 	} else
347*d39a76e7Sxw161283 #endif
348*d39a76e7Sxw161283 	{
349*d39a76e7Sxw161283 		t1_write_reg_4(tp->adapter, A_TP_INT_ENABLE, 0);
350*d39a76e7Sxw161283 		t1_write_reg_4(tp->adapter, A_PL_ENABLE,
351*d39a76e7Sxw161283 			       tp_intr & ~F_PL_INTR_TP);
352*d39a76e7Sxw161283 	}
353*d39a76e7Sxw161283 }
354*d39a76e7Sxw161283 
t1_tp_intr_clear(struct petp * tp)355*d39a76e7Sxw161283 void t1_tp_intr_clear(struct petp *tp)
356*d39a76e7Sxw161283 {
357*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
358*d39a76e7Sxw161283 	if (!t1_is_asic(tp->adapter)) {
359*d39a76e7Sxw161283 		t1_write_reg_4(tp->adapter, FPGA_TP_ADDR_INTERRUPT_CAUSE,
360*d39a76e7Sxw161283 			       0xffffffff);
361*d39a76e7Sxw161283 		t1_write_reg_4(tp->adapter, A_PL_CAUSE, FPGA_PCIX_INTERRUPT_TP);
362*d39a76e7Sxw161283 		return;
363*d39a76e7Sxw161283 	}
364*d39a76e7Sxw161283 #endif
365*d39a76e7Sxw161283 	t1_write_reg_4(tp->adapter, A_TP_INT_CAUSE, 0xffffffff);
366*d39a76e7Sxw161283 	t1_write_reg_4(tp->adapter, A_PL_CAUSE, F_PL_INTR_TP);
367*d39a76e7Sxw161283 }
368*d39a76e7Sxw161283 
t1_tp_intr_handler(struct petp * tp)369*d39a76e7Sxw161283 int t1_tp_intr_handler(struct petp *tp)
370*d39a76e7Sxw161283 {
371*d39a76e7Sxw161283 	u32 cause;
372*d39a76e7Sxw161283 
373*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
374*d39a76e7Sxw161283 	/* FPGA doesn't support TP interrupts. */
375*d39a76e7Sxw161283 	if (!t1_is_asic(tp->adapter))
376*d39a76e7Sxw161283 		return 1;
377*d39a76e7Sxw161283 #endif
378*d39a76e7Sxw161283 
379*d39a76e7Sxw161283 	cause = t1_read_reg_4(tp->adapter, A_TP_INT_CAUSE);
380*d39a76e7Sxw161283 	t1_write_reg_4(tp->adapter, A_TP_INT_CAUSE, cause);
381*d39a76e7Sxw161283 	return 0;
382*d39a76e7Sxw161283 }
383*d39a76e7Sxw161283 
set_csum_offload(struct petp * tp,u32 csum_bit,int enable)384*d39a76e7Sxw161283 static void set_csum_offload(struct petp *tp, u32 csum_bit, int enable)
385*d39a76e7Sxw161283 {
386*d39a76e7Sxw161283 	u32 val = t1_read_reg_4(tp->adapter, A_TP_GLOBAL_CONFIG);
387*d39a76e7Sxw161283 
388*d39a76e7Sxw161283 	if (enable)
389*d39a76e7Sxw161283 		val |= csum_bit;
390*d39a76e7Sxw161283 	else
391*d39a76e7Sxw161283 		val &= ~csum_bit;
392*d39a76e7Sxw161283 	t1_write_reg_4(tp->adapter, A_TP_GLOBAL_CONFIG, val);
393*d39a76e7Sxw161283 }
394*d39a76e7Sxw161283 
t1_tp_set_ip_checksum_offload(struct petp * tp,int enable)395*d39a76e7Sxw161283 void t1_tp_set_ip_checksum_offload(struct petp *tp, int enable)
396*d39a76e7Sxw161283 {
397*d39a76e7Sxw161283 	set_csum_offload(tp, F_IP_CSUM, enable);
398*d39a76e7Sxw161283 }
399*d39a76e7Sxw161283 
t1_tp_set_udp_checksum_offload(struct petp * tp,int enable)400*d39a76e7Sxw161283 void t1_tp_set_udp_checksum_offload(struct petp *tp, int enable)
401*d39a76e7Sxw161283 {
402*d39a76e7Sxw161283 	set_csum_offload(tp, F_UDP_CSUM, enable);
403*d39a76e7Sxw161283 }
404*d39a76e7Sxw161283 
t1_tp_set_tcp_checksum_offload(struct petp * tp,int enable)405*d39a76e7Sxw161283 void t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable)
406*d39a76e7Sxw161283 {
407*d39a76e7Sxw161283 	set_csum_offload(tp, F_TCP_CSUM, enable);
408*d39a76e7Sxw161283 }
409*d39a76e7Sxw161283 
410*d39a76e7Sxw161283 /*
411*d39a76e7Sxw161283  * Initialize TP state.  tp_params contains initial settings for some TP
412*d39a76e7Sxw161283  * parameters, particularly the one-time PM and CM settings.
413*d39a76e7Sxw161283  */
t1_tp_reset(struct petp * tp,struct tp_params * p,unsigned int tp_clk)414*d39a76e7Sxw161283 int t1_tp_reset(struct petp *tp, struct tp_params *p, unsigned int tp_clk)
415*d39a76e7Sxw161283 {
416*d39a76e7Sxw161283 	int busy = 0;
417*d39a76e7Sxw161283 	adapter_t *adapter = tp->adapter;
418*d39a76e7Sxw161283 
419*d39a76e7Sxw161283 	tp_init(adapter, p, tp_clk);
420*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
421*d39a76e7Sxw161283 	if (p->pm_size) {
422*d39a76e7Sxw161283 		tp_pm_configure(adapter, p);
423*d39a76e7Sxw161283 		tp_cm_configure(adapter, p->cm_size);
424*d39a76e7Sxw161283 
425*d39a76e7Sxw161283 		t1_write_reg_4(adapter, A_TP_RESET, F_CM_MEMMGR_INIT);
426*d39a76e7Sxw161283 		busy = t1_wait_op_done(adapter, A_TP_RESET, F_CM_MEMMGR_INIT,
427*d39a76e7Sxw161283 				0, 1000, 5);
428*d39a76e7Sxw161283 	}
429*d39a76e7Sxw161283 #endif
430*d39a76e7Sxw161283 	if (!busy)
431*d39a76e7Sxw161283 		t1_write_reg_4(adapter, A_TP_RESET, F_TP_RESET);
432*d39a76e7Sxw161283 	else
433*d39a76e7Sxw161283 		CH_ERR("%s: TP initialization timed out\n",
434*d39a76e7Sxw161283 		       adapter_name(adapter));
435*d39a76e7Sxw161283 	return busy;
436*d39a76e7Sxw161283 }
437