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