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