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