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