1 /**************************************************************************
2 SPDX-License-Identifier: BSD-2-Clause
3
4 Copyright (c) 2007, Chelsio Inc.
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12
13 2. Neither the name of the Chelsio Corporation nor the names of its
14 contributors may be used to endorse or promote products derived from
15 this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
28
29 ***************************************************************************/
30
31 #include <sys/cdefs.h>
32 #include <common/cxgb_common.h>
33 #include <common/cxgb_regs.h>
34
35 enum {
36 IDT75P52100 = 4,
37 IDT75N43102 = 5
38 };
39
40 /* DBGI command mode */
41 enum {
42 DBGI_MODE_MBUS = 0,
43 DBGI_MODE_IDT52100 = 5
44 };
45
46 /* IDT 75P52100 commands */
47 #define IDT_CMD_READ 0
48 #define IDT_CMD_WRITE 1
49 #define IDT_CMD_SEARCH 2
50 #define IDT_CMD_LEARN 3
51
52 /* IDT LAR register address and value for 144-bit mode (low 32 bits) */
53 #define IDT_LAR_ADR0 0x180006
54 #define IDT_LAR_MODE144 0xffff0000
55
56 /* IDT SCR and SSR addresses (low 32 bits) */
57 #define IDT_SCR_ADR0 0x180000
58 #define IDT_SSR0_ADR0 0x180002
59 #define IDT_SSR1_ADR0 0x180004
60
61 /* IDT GMR base address (low 32 bits) */
62 #define IDT_GMR_BASE_ADR0 0x180020
63
64 /* IDT data and mask array base addresses (low 32 bits) */
65 #define IDT_DATARY_BASE_ADR0 0
66 #define IDT_MSKARY_BASE_ADR0 0x80000
67
68 /* IDT 75N43102 commands */
69 #define IDT4_CMD_SEARCH144 3
70 #define IDT4_CMD_WRITE 4
71 #define IDT4_CMD_READ 5
72
73 /* IDT 75N43102 SCR address (low 32 bits) */
74 #define IDT4_SCR_ADR0 0x3
75
76 /* IDT 75N43102 GMR base addresses (low 32 bits) */
77 #define IDT4_GMR_BASE0 0x10
78 #define IDT4_GMR_BASE1 0x20
79 #define IDT4_GMR_BASE2 0x30
80
81 /* IDT 75N43102 data and mask array base addresses (low 32 bits) */
82 #define IDT4_DATARY_BASE_ADR0 0x1000000
83 #define IDT4_MSKARY_BASE_ADR0 0x2000000
84
85 #define MAX_WRITE_ATTEMPTS 5
86
87 #define MAX_ROUTES 2048
88
89 /*
90 * Issue a command to the TCAM and wait for its completion. The address and
91 * any data required by the command must have been setup by the caller.
92 */
mc5_cmd_write(adapter_t * adapter,u32 cmd)93 static int mc5_cmd_write(adapter_t *adapter, u32 cmd)
94 {
95 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd);
96 return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS,
97 F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1);
98 }
99
dbgi_wr_data3(adapter_t * adapter,u32 v1,u32 v2,u32 v3)100 static inline void dbgi_wr_data3(adapter_t *adapter, u32 v1, u32 v2, u32 v3)
101 {
102 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1);
103 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2);
104 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3);
105 }
106
dbgi_rd_rsp3(adapter_t * adapter,u32 * v1,u32 * v2,u32 * v3)107 static inline void dbgi_rd_rsp3(adapter_t *adapter, u32 *v1, u32 *v2, u32 *v3)
108 {
109 *v1 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA0);
110 *v2 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA1);
111 *v3 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA2);
112 }
113
114 /*
115 * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
116 * command cmd. The data to be written must have been set up by the caller.
117 * Returns -1 on failure, 0 on success.
118 */
mc5_write(adapter_t * adapter,u32 addr_lo,u32 cmd)119 static int mc5_write(adapter_t *adapter, u32 addr_lo, u32 cmd)
120 {
121 t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo);
122 if (mc5_cmd_write(adapter, cmd) == 0)
123 return 0;
124 CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n", addr_lo);
125 return -1;
126 }
127
init_mask_data_array(struct mc5 * mc5,u32 mask_array_base,u32 data_array_base,u32 write_cmd,int addr_shift)128 static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base,
129 u32 data_array_base, u32 write_cmd,
130 int addr_shift)
131 {
132 unsigned int i;
133 adapter_t *adap = mc5->adapter;
134
135 /*
136 * We need the size of the TCAM data and mask arrays in terms of
137 * 72-bit entries.
138 */
139 unsigned int size72 = mc5->tcam_size;
140 unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX);
141
142 if (mc5->mode == MC5_MODE_144_BIT) {
143 size72 *= 2; /* 1 144-bit entry is 2 72-bit entries */
144 server_base *= 2;
145 }
146
147 /* Clear the data array */
148 dbgi_wr_data3(adap, 0, 0, 0);
149 for (i = 0; i < size72; i++)
150 if (mc5_write(adap, data_array_base + (i << addr_shift),
151 write_cmd))
152 return -1;
153
154 /* Initialize the mask array. */
155 for (i = 0; i < server_base; i++) {
156 dbgi_wr_data3(adap, 0x3fffffff, 0xfff80000, 0xff);
157 if (mc5_write(adap, mask_array_base + (i << addr_shift),
158 write_cmd))
159 return -1;
160 i++;
161 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
162 if (mc5_write(adap, mask_array_base + (i << addr_shift),
163 write_cmd))
164 return -1;
165 }
166
167 dbgi_wr_data3(adap,
168 mc5->mode == MC5_MODE_144_BIT ? 0xfffffff9 : 0xfffffffd,
169 0xffffffff, 0xff);
170 for (; i < size72; i++)
171 if (mc5_write(adap, mask_array_base + (i << addr_shift),
172 write_cmd))
173 return -1;
174
175 return 0;
176 }
177
init_idt52100(struct mc5 * mc5)178 static int init_idt52100(struct mc5 *mc5)
179 {
180 int i;
181 adapter_t *adap = mc5->adapter;
182
183 t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
184 V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15));
185 t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2);
186
187 /*
188 * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and
189 * GMRs 8-9 for ACK- and AOPEN searches.
190 */
191 t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE);
192 t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE);
193 t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH);
194 t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN);
195 t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000);
196 t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN);
197 t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH);
198 t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN);
199 t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH);
200 t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000);
201 t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE);
202 t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ);
203
204 /* Set DBGI command mode for IDT TCAM. */
205 t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
206
207 /* Set up LAR */
208 dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0);
209 if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE))
210 goto err;
211
212 /* Set up SSRs */
213 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0);
214 if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) ||
215 mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE))
216 goto err;
217
218 /* Set up GMRs */
219 for (i = 0; i < 32; ++i) {
220 if (i >= 12 && i < 15)
221 dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
222 else if (i == 15)
223 dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
224 else
225 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
226
227 if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE))
228 goto err;
229 }
230
231 /* Set up SCR */
232 dbgi_wr_data3(adap, 1, 0, 0);
233 if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE))
234 goto err;
235
236 return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0,
237 IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0);
238 err:
239 return -EIO;
240 }
241
init_idt43102(struct mc5 * mc5)242 static int init_idt43102(struct mc5 *mc5)
243 {
244 int i;
245 adapter_t *adap = mc5->adapter;
246
247 t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
248 adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) :
249 V_RDLAT(0xd) | V_SRCHLAT(0x12));
250
251 /*
252 * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask
253 * for ACK- and AOPEN searches.
254 */
255 t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE);
256 t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE);
257 t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD,
258 IDT4_CMD_SEARCH144 | 0x3800);
259 t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144);
260 t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800);
261 t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800);
262 t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800);
263 t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE);
264 t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ);
265
266 t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3);
267
268 /* Set DBGI command mode for IDT TCAM. */
269 t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
270
271 /* Set up GMRs */
272 dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
273 for (i = 0; i < 7; ++i)
274 if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE))
275 goto err;
276
277 for (i = 0; i < 4; ++i)
278 if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE))
279 goto err;
280
281 dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
282 if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) ||
283 mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) ||
284 mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE))
285 goto err;
286
287 dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
288 if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE))
289 goto err;
290
291 /* Set up SCR */
292 dbgi_wr_data3(adap, 0xf0000000, 0, 0);
293 if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE))
294 goto err;
295
296 return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0,
297 IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1);
298 err:
299 return -EIO;
300 }
301
302 /* Put MC5 in DBGI mode. */
mc5_dbgi_mode_enable(const struct mc5 * mc5)303 static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5)
304 {
305 t3_set_reg_field(mc5->adapter, A_MC5_DB_CONFIG, F_PRTYEN | F_MBUSEN,
306 F_DBGIEN);
307 }
308
309 /* Put MC5 in M-Bus mode. */
mc5_dbgi_mode_disable(const struct mc5 * mc5)310 static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
311 {
312 t3_set_reg_field(mc5->adapter, A_MC5_DB_CONFIG, F_DBGIEN,
313 V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
314 }
315
316 /**
317 * t3_mc5_init - initialize MC5 and the TCAM
318 * @mc5: the MC5 handle
319 * @nservers: desired number the TCP servers (listening ports)
320 * @nfilters: desired number of HW filters (classifiers)
321 * @nroutes: desired number of routes
322 *
323 * Initialize MC5 and the TCAM and partition the TCAM for the requested
324 * number of servers, filters, and routes. The number of routes is
325 * typically 0 except for specialized uses of the T3 adapters.
326 */
t3_mc5_init(struct mc5 * mc5,unsigned int nservers,unsigned int nfilters,unsigned int nroutes)327 int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
328 unsigned int nroutes)
329 {
330 int err;
331 unsigned int tcam_size = mc5->tcam_size;
332 unsigned int mode72 = mc5->mode == MC5_MODE_72_BIT;
333 adapter_t *adap = mc5->adapter;
334
335 if (!tcam_size)
336 return 0;
337
338 if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
339 return -EINVAL;
340
341 if (nfilters)
342 mc5->parity_enabled = 0;
343
344 /* Reset the TCAM */
345 t3_set_reg_field(adap, A_MC5_DB_CONFIG, F_TMMODE | F_COMPEN,
346 V_COMPEN(mode72) | V_TMMODE(mode72) | F_TMRST);
347 if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
348 CH_ERR(adap, "TCAM reset timed out\n");
349 return -1;
350 }
351
352 t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes);
353 t3_write_reg(adap, A_MC5_DB_FILTER_TABLE,
354 tcam_size - nroutes - nfilters);
355 t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
356 tcam_size - nroutes - nfilters - nservers);
357
358 /* All the TCAM addresses we access have only the low 32 bits non 0 */
359 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
360 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
361
362 mc5_dbgi_mode_enable(mc5);
363
364 switch (mc5->part_type) {
365 case IDT75P52100:
366 err = init_idt52100(mc5);
367 break;
368 case IDT75N43102:
369 err = init_idt43102(mc5);
370 break;
371 default:
372 CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type);
373 err = -EINVAL;
374 break;
375 }
376
377 mc5_dbgi_mode_disable(mc5);
378 return err;
379 }
380
381 /**
382 * read_mc5_range - dump a part of the memory managed by MC5
383 * @mc5: the MC5 handle
384 * @start: the start address for the dump
385 * @n: number of 72-bit words to read
386 * @buf: result buffer
387 *
388 * Read n 72-bit words from MC5 memory from the given start location.
389 */
t3_read_mc5_range(const struct mc5 * mc5,unsigned int start,unsigned int n,u32 * buf)390 int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start,
391 unsigned int n, u32 *buf)
392 {
393 u32 read_cmd;
394 int err = 0;
395 adapter_t *adap = mc5->adapter;
396
397 if (mc5->part_type == IDT75P52100)
398 read_cmd = IDT_CMD_READ;
399 else if (mc5->part_type == IDT75N43102)
400 read_cmd = IDT4_CMD_READ;
401 else
402 return -EINVAL;
403
404 mc5_dbgi_mode_enable(mc5);
405
406 while (n--) {
407 t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR0, start++);
408 if (mc5_cmd_write(adap, read_cmd)) {
409 err = -EIO;
410 break;
411 }
412 dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf);
413 buf += 3;
414 }
415
416 mc5_dbgi_mode_disable(mc5);
417 return err;
418 }
419
420 #define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
421
422 /**
423 * t3_mc5_intr_handler - MC5 interrupt handler
424 * @mc5: the MC5 handle
425 *
426 * The MC5 interrupt handler.
427 */
t3_mc5_intr_handler(struct mc5 * mc5)428 void t3_mc5_intr_handler(struct mc5 *mc5)
429 {
430 adapter_t *adap = mc5->adapter;
431 u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE);
432
433 if ((cause & F_PARITYERR) && mc5->parity_enabled) {
434 CH_ALERT(adap, "MC5 parity error\n");
435 mc5->stats.parity_err++;
436 }
437
438 if (cause & F_REQQPARERR) {
439 CH_ALERT(adap, "MC5 request queue parity error\n");
440 mc5->stats.reqq_parity_err++;
441 }
442
443 if (cause & F_DISPQPARERR) {
444 CH_ALERT(adap, "MC5 dispatch queue parity error\n");
445 mc5->stats.dispq_parity_err++;
446 }
447
448 if (cause & F_ACTRGNFULL)
449 mc5->stats.active_rgn_full++;
450 if (cause & F_NFASRCHFAIL)
451 mc5->stats.nfa_srch_err++;
452 if (cause & F_UNKNOWNCMD)
453 mc5->stats.unknown_cmd++;
454 if (cause & F_DELACTEMPTY)
455 mc5->stats.del_act_empty++;
456 if (cause & MC5_INT_FATAL)
457 t3_fatal_err(adap);
458
459 t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
460 }
461
462 /**
463 * t3_mc5_prep - initialize the SW state for MC5
464 * @adapter: the adapter
465 * @mc5: the MC5 handle
466 * @mode: whether the TCAM will be in 72- or 144-bit mode
467 *
468 * Initialize the SW state associated with MC5. Among other things
469 * this determines the size of the attached TCAM.
470 */
t3_mc5_prep(adapter_t * adapter,struct mc5 * mc5,int mode)471 void __devinit t3_mc5_prep(adapter_t *adapter, struct mc5 *mc5, int mode)
472 {
473 #define K * 1024
474
475 static unsigned int tcam_part_size[] = { /* in K 72-bit entries */
476 64 K, 128 K, 256 K, 32 K
477 };
478
479 #undef K
480
481 u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
482
483 mc5->adapter = adapter;
484 mc5->parity_enabled = 1;
485 mc5->mode = (unsigned char) mode;
486 mc5->part_type = (unsigned char) G_TMTYPE(cfg);
487 if (cfg & F_TMTYPEHI)
488 mc5->part_type |= 4;
489
490 mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)];
491 if (mode == MC5_MODE_144_BIT)
492 mc5->tcam_size /= 2;
493 }
494