diff options
author | Divy Le Ray <divy@chelsio.com> | 2007-01-18 22:04:14 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-05 16:58:46 -0500 |
commit | 4d22de3e6cc4a09c369b504cd8bcde3385a974cd (patch) | |
tree | af13a2ee582105d961c79fc4e55fce0b5e043310 /drivers/net/cxgb3/mc5.c | |
parent | 0bf94faf64afaba6e7b49fd11541b59d2ba06d0e (diff) |
Add support for the latest 1G/10G Chelsio adapter, T3.
This driver is required by the Chelsio T3 RDMA driver posted by
Steve Wise.
Signed-off-by: Divy Le Ray <divy@chelsio.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/cxgb3/mc5.c')
-rw-r--r-- | drivers/net/cxgb3/mc5.c | 453 |
1 files changed, 453 insertions, 0 deletions
diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/cxgb3/mc5.c new file mode 100644 index 000000000000..44fa9eaedcc3 --- /dev/null +++ b/drivers/net/cxgb3/mc5.c | |||
@@ -0,0 +1,453 @@ | |||
1 | /* | ||
2 | * This file is part of the Chelsio T3 Ethernet driver. | ||
3 | * | ||
4 | * Copyright (C) 2003-2006 Chelsio Communications. All rights reserved. | ||
5 | * | ||
6 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
7 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
8 | * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this | ||
9 | * release for licensing terms and conditions. | ||
10 | */ | ||
11 | |||
12 | #include "common.h" | ||
13 | #include "regs.h" | ||
14 | |||
15 | enum { | ||
16 | IDT75P52100 = 4, | ||
17 | IDT75N43102 = 5 | ||
18 | }; | ||
19 | |||
20 | /* DBGI command mode */ | ||
21 | enum { | ||
22 | DBGI_MODE_MBUS = 0, | ||
23 | DBGI_MODE_IDT52100 = 5 | ||
24 | }; | ||
25 | |||
26 | /* IDT 75P52100 commands */ | ||
27 | #define IDT_CMD_READ 0 | ||
28 | #define IDT_CMD_WRITE 1 | ||
29 | #define IDT_CMD_SEARCH 2 | ||
30 | #define IDT_CMD_LEARN 3 | ||
31 | |||
32 | /* IDT LAR register address and value for 144-bit mode (low 32 bits) */ | ||
33 | #define IDT_LAR_ADR0 0x180006 | ||
34 | #define IDT_LAR_MODE144 0xffff0000 | ||
35 | |||
36 | /* IDT SCR and SSR addresses (low 32 bits) */ | ||
37 | #define IDT_SCR_ADR0 0x180000 | ||
38 | #define IDT_SSR0_ADR0 0x180002 | ||
39 | #define IDT_SSR1_ADR0 0x180004 | ||
40 | |||
41 | /* IDT GMR base address (low 32 bits) */ | ||
42 | #define IDT_GMR_BASE_ADR0 0x180020 | ||
43 | |||
44 | /* IDT data and mask array base addresses (low 32 bits) */ | ||
45 | #define IDT_DATARY_BASE_ADR0 0 | ||
46 | #define IDT_MSKARY_BASE_ADR0 0x80000 | ||
47 | |||
48 | /* IDT 75N43102 commands */ | ||
49 | #define IDT4_CMD_SEARCH144 3 | ||
50 | #define IDT4_CMD_WRITE 4 | ||
51 | #define IDT4_CMD_READ 5 | ||
52 | |||
53 | /* IDT 75N43102 SCR address (low 32 bits) */ | ||
54 | #define IDT4_SCR_ADR0 0x3 | ||
55 | |||
56 | /* IDT 75N43102 GMR base addresses (low 32 bits) */ | ||
57 | #define IDT4_GMR_BASE0 0x10 | ||
58 | #define IDT4_GMR_BASE1 0x20 | ||
59 | #define IDT4_GMR_BASE2 0x30 | ||
60 | |||
61 | /* IDT 75N43102 data and mask array base addresses (low 32 bits) */ | ||
62 | #define IDT4_DATARY_BASE_ADR0 0x1000000 | ||
63 | #define IDT4_MSKARY_BASE_ADR0 0x2000000 | ||
64 | |||
65 | #define MAX_WRITE_ATTEMPTS 5 | ||
66 | |||
67 | #define MAX_ROUTES 2048 | ||
68 | |||
69 | /* | ||
70 | * Issue a command to the TCAM and wait for its completion. The address and | ||
71 | * any data required by the command must have been setup by the caller. | ||
72 | */ | ||
73 | static int mc5_cmd_write(struct adapter *adapter, u32 cmd) | ||
74 | { | ||
75 | t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd); | ||
76 | return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS, | ||
77 | F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1); | ||
78 | } | ||
79 | |||
80 | static inline void dbgi_wr_addr3(struct adapter *adapter, u32 v1, u32 v2, | ||
81 | u32 v3) | ||
82 | { | ||
83 | t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, v1); | ||
84 | t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR1, v2); | ||
85 | t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR2, v3); | ||
86 | } | ||
87 | |||
88 | static inline void dbgi_wr_data3(struct adapter *adapter, u32 v1, u32 v2, | ||
89 | u32 v3) | ||
90 | { | ||
91 | t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1); | ||
92 | t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2); | ||
93 | t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3); | ||
94 | } | ||
95 | |||
96 | static inline void dbgi_rd_rsp3(struct adapter *adapter, u32 *v1, u32 *v2, | ||
97 | u32 *v3) | ||
98 | { | ||
99 | *v1 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA0); | ||
100 | *v2 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA1); | ||
101 | *v3 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA2); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM | ||
106 | * command cmd. The data to be written must have been set up by the caller. | ||
107 | * Returns -1 on failure, 0 on success. | ||
108 | */ | ||
109 | static int mc5_write(struct adapter *adapter, u32 addr_lo, u32 cmd) | ||
110 | { | ||
111 | t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo); | ||
112 | if (mc5_cmd_write(adapter, cmd) == 0) | ||
113 | return 0; | ||
114 | CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n", | ||
115 | addr_lo); | ||
116 | return -1; | ||
117 | } | ||
118 | |||
119 | static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base, | ||
120 | u32 data_array_base, u32 write_cmd, | ||
121 | int addr_shift) | ||
122 | { | ||
123 | unsigned int i; | ||
124 | struct adapter *adap = mc5->adapter; | ||
125 | |||
126 | /* | ||
127 | * We need the size of the TCAM data and mask arrays in terms of | ||
128 | * 72-bit entries. | ||
129 | */ | ||
130 | unsigned int size72 = mc5->tcam_size; | ||
131 | unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX); | ||
132 | |||
133 | if (mc5->mode == MC5_MODE_144_BIT) { | ||
134 | size72 *= 2; /* 1 144-bit entry is 2 72-bit entries */ | ||
135 | server_base *= 2; | ||
136 | } | ||
137 | |||
138 | /* Clear the data array */ | ||
139 | dbgi_wr_data3(adap, 0, 0, 0); | ||
140 | for (i = 0; i < size72; i++) | ||
141 | if (mc5_write(adap, data_array_base + (i << addr_shift), | ||
142 | write_cmd)) | ||
143 | return -1; | ||
144 | |||
145 | /* Initialize the mask array. */ | ||
146 | dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff); | ||
147 | for (i = 0; i < size72; i++) { | ||
148 | if (i == server_base) /* entering server or routing region */ | ||
149 | t3_write_reg(adap, A_MC5_DB_DBGI_REQ_DATA0, | ||
150 | mc5->mode == MC5_MODE_144_BIT ? | ||
151 | 0xfffffff9 : 0xfffffffd); | ||
152 | if (mc5_write(adap, mask_array_base + (i << addr_shift), | ||
153 | write_cmd)) | ||
154 | return -1; | ||
155 | } | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int init_idt52100(struct mc5 *mc5) | ||
160 | { | ||
161 | int i; | ||
162 | struct adapter *adap = mc5->adapter; | ||
163 | |||
164 | t3_write_reg(adap, A_MC5_DB_RSP_LATENCY, | ||
165 | V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15)); | ||
166 | t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2); | ||
167 | |||
168 | /* | ||
169 | * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and | ||
170 | * GMRs 8-9 for ACK- and AOPEN searches. | ||
171 | */ | ||
172 | t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE); | ||
173 | t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE); | ||
174 | t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH); | ||
175 | t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN); | ||
176 | t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000); | ||
177 | t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN); | ||
178 | t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH); | ||
179 | t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN); | ||
180 | t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH); | ||
181 | t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000); | ||
182 | t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE); | ||
183 | t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ); | ||
184 | |||
185 | /* Set DBGI command mode for IDT TCAM. */ | ||
186 | t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100); | ||
187 | |||
188 | /* Set up LAR */ | ||
189 | dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0); | ||
190 | if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE)) | ||
191 | goto err; | ||
192 | |||
193 | /* Set up SSRs */ | ||
194 | dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0); | ||
195 | if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) || | ||
196 | mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE)) | ||
197 | goto err; | ||
198 | |||
199 | /* Set up GMRs */ | ||
200 | for (i = 0; i < 32; ++i) { | ||
201 | if (i >= 12 && i < 15) | ||
202 | dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff); | ||
203 | else if (i == 15) | ||
204 | dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff); | ||
205 | else | ||
206 | dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff); | ||
207 | |||
208 | if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE)) | ||
209 | goto err; | ||
210 | } | ||
211 | |||
212 | /* Set up SCR */ | ||
213 | dbgi_wr_data3(adap, 1, 0, 0); | ||
214 | if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE)) | ||
215 | goto err; | ||
216 | |||
217 | return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0, | ||
218 | IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0); | ||
219 | err: | ||
220 | return -EIO; | ||
221 | } | ||
222 | |||
223 | static int init_idt43102(struct mc5 *mc5) | ||
224 | { | ||
225 | int i; | ||
226 | struct adapter *adap = mc5->adapter; | ||
227 | |||
228 | t3_write_reg(adap, A_MC5_DB_RSP_LATENCY, | ||
229 | adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) : | ||
230 | V_RDLAT(0xd) | V_SRCHLAT(0x12)); | ||
231 | |||
232 | /* | ||
233 | * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask | ||
234 | * for ACK- and AOPEN searches. | ||
235 | */ | ||
236 | t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE); | ||
237 | t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE); | ||
238 | t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, | ||
239 | IDT4_CMD_SEARCH144 | 0x3800); | ||
240 | t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144); | ||
241 | t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800); | ||
242 | t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800); | ||
243 | t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800); | ||
244 | t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE); | ||
245 | t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ); | ||
246 | |||
247 | t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3); | ||
248 | |||
249 | /* Set DBGI command mode for IDT TCAM. */ | ||
250 | t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100); | ||
251 | |||
252 | /* Set up GMRs */ | ||
253 | dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff); | ||
254 | for (i = 0; i < 7; ++i) | ||
255 | if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE)) | ||
256 | goto err; | ||
257 | |||
258 | for (i = 0; i < 4; ++i) | ||
259 | if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE)) | ||
260 | goto err; | ||
261 | |||
262 | dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff); | ||
263 | if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) || | ||
264 | mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) || | ||
265 | mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE)) | ||
266 | goto err; | ||
267 | |||
268 | dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff); | ||
269 | if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE)) | ||
270 | goto err; | ||
271 | |||
272 | /* Set up SCR */ | ||
273 | dbgi_wr_data3(adap, 0xf0000000, 0, 0); | ||
274 | if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE)) | ||
275 | goto err; | ||
276 | |||
277 | return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0, | ||
278 | IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1); | ||
279 | err: | ||
280 | return -EIO; | ||
281 | } | ||
282 | |||
283 | /* Put MC5 in DBGI mode. */ | ||
284 | static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5) | ||
285 | { | ||
286 | t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG, | ||
287 | V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_DBGIEN); | ||
288 | } | ||
289 | |||
290 | /* Put MC5 in M-Bus mode. */ | ||
291 | static void mc5_dbgi_mode_disable(const struct mc5 *mc5) | ||
292 | { | ||
293 | t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG, | ||
294 | V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | | ||
295 | V_COMPEN(mc5->mode == MC5_MODE_72_BIT) | | ||
296 | V_PRTYEN(mc5->parity_enabled) | F_MBUSEN); | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * Initialization that requires the OS and protocol layers to already | ||
301 | * be intialized goes here. | ||
302 | */ | ||
303 | int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters, | ||
304 | unsigned int nroutes) | ||
305 | { | ||
306 | u32 cfg; | ||
307 | int err; | ||
308 | unsigned int tcam_size = mc5->tcam_size; | ||
309 | struct adapter *adap = mc5->adapter; | ||
310 | |||
311 | if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size) | ||
312 | return -EINVAL; | ||
313 | |||
314 | /* Reset the TCAM */ | ||
315 | cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE; | ||
316 | cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST; | ||
317 | t3_write_reg(adap, A_MC5_DB_CONFIG, cfg); | ||
318 | if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) { | ||
319 | CH_ERR(adap, "TCAM reset timed out\n"); | ||
320 | return -1; | ||
321 | } | ||
322 | |||
323 | t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes); | ||
324 | t3_write_reg(adap, A_MC5_DB_FILTER_TABLE, | ||
325 | tcam_size - nroutes - nfilters); | ||
326 | t3_write_reg(adap, A_MC5_DB_SERVER_INDEX, | ||
327 | tcam_size - nroutes - nfilters - nservers); | ||
328 | |||
329 | mc5->parity_enabled = 1; | ||
330 | |||
331 | /* All the TCAM addresses we access have only the low 32 bits non 0 */ | ||
332 | t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0); | ||
333 | t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0); | ||
334 | |||
335 | mc5_dbgi_mode_enable(mc5); | ||
336 | |||
337 | switch (mc5->part_type) { | ||
338 | case IDT75P52100: | ||
339 | err = init_idt52100(mc5); | ||
340 | break; | ||
341 | case IDT75N43102: | ||
342 | err = init_idt43102(mc5); | ||
343 | break; | ||
344 | default: | ||
345 | CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type); | ||
346 | err = -EINVAL; | ||
347 | break; | ||
348 | } | ||
349 | |||
350 | mc5_dbgi_mode_disable(mc5); | ||
351 | return err; | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * read_mc5_range - dump a part of the memory managed by MC5 | ||
356 | * @mc5: the MC5 handle | ||
357 | * @start: the start address for the dump | ||
358 | * @n: number of 72-bit words to read | ||
359 | * @buf: result buffer | ||
360 | * | ||
361 | * Read n 72-bit words from MC5 memory from the given start location. | ||
362 | */ | ||
363 | int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start, | ||
364 | unsigned int n, u32 *buf) | ||
365 | { | ||
366 | u32 read_cmd; | ||
367 | int err = 0; | ||
368 | struct adapter *adap = mc5->adapter; | ||
369 | |||
370 | if (mc5->part_type == IDT75P52100) | ||
371 | read_cmd = IDT_CMD_READ; | ||
372 | else if (mc5->part_type == IDT75N43102) | ||
373 | read_cmd = IDT4_CMD_READ; | ||
374 | else | ||
375 | return -EINVAL; | ||
376 | |||
377 | mc5_dbgi_mode_enable(mc5); | ||
378 | |||
379 | while (n--) { | ||
380 | t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR0, start++); | ||
381 | if (mc5_cmd_write(adap, read_cmd)) { | ||
382 | err = -EIO; | ||
383 | break; | ||
384 | } | ||
385 | dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf); | ||
386 | buf += 3; | ||
387 | } | ||
388 | |||
389 | mc5_dbgi_mode_disable(mc5); | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | #define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR) | ||
394 | |||
395 | /* | ||
396 | * MC5 interrupt handler | ||
397 | */ | ||
398 | void t3_mc5_intr_handler(struct mc5 *mc5) | ||
399 | { | ||
400 | struct adapter *adap = mc5->adapter; | ||
401 | u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE); | ||
402 | |||
403 | if ((cause & F_PARITYERR) && mc5->parity_enabled) { | ||
404 | CH_ALERT(adap, "MC5 parity error\n"); | ||
405 | mc5->stats.parity_err++; | ||
406 | } | ||
407 | |||
408 | if (cause & F_REQQPARERR) { | ||
409 | CH_ALERT(adap, "MC5 request queue parity error\n"); | ||
410 | mc5->stats.reqq_parity_err++; | ||
411 | } | ||
412 | |||
413 | if (cause & F_DISPQPARERR) { | ||
414 | CH_ALERT(adap, "MC5 dispatch queue parity error\n"); | ||
415 | mc5->stats.dispq_parity_err++; | ||
416 | } | ||
417 | |||
418 | if (cause & F_ACTRGNFULL) | ||
419 | mc5->stats.active_rgn_full++; | ||
420 | if (cause & F_NFASRCHFAIL) | ||
421 | mc5->stats.nfa_srch_err++; | ||
422 | if (cause & F_UNKNOWNCMD) | ||
423 | mc5->stats.unknown_cmd++; | ||
424 | if (cause & F_DELACTEMPTY) | ||
425 | mc5->stats.del_act_empty++; | ||
426 | if (cause & MC5_INT_FATAL) | ||
427 | t3_fatal_err(adap); | ||
428 | |||
429 | t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause); | ||
430 | } | ||
431 | |||
432 | void __devinit t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode) | ||
433 | { | ||
434 | #define K * 1024 | ||
435 | |||
436 | static unsigned int tcam_part_size[] = { /* in K 72-bit entries */ | ||
437 | 64 K, 128 K, 256 K, 32 K | ||
438 | }; | ||
439 | |||
440 | #undef K | ||
441 | |||
442 | u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG); | ||
443 | |||
444 | mc5->adapter = adapter; | ||
445 | mc5->mode = (unsigned char)mode; | ||
446 | mc5->part_type = (unsigned char)G_TMTYPE(cfg); | ||
447 | if (cfg & F_TMTYPEHI) | ||
448 | mc5->part_type |= 4; | ||
449 | |||
450 | mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)]; | ||
451 | if (mode == MC5_MODE_144_BIT) | ||
452 | mc5->tcam_size /= 2; | ||
453 | } | ||