xref: /freebsd/sys/dev/cxgb/common/cxgb_mc5.c (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
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  */
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 
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 
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  */
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 
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 
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 
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. */
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. */
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  */
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  */
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  */
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  */
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