1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2013-2016 Qlogic Corporation
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
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
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 * File: ql_hw.c
32 * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
33 * Content: Contains Hardware dependent functions
34 */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include "ql_os.h"
40 #include "ql_hw.h"
41 #include "ql_def.h"
42 #include "ql_inline.h"
43 #include "ql_ver.h"
44 #include "ql_glbl.h"
45 #include "ql_dbg.h"
46 #include "ql_minidump.h"
47
48 /*
49 * Static Functions
50 */
51
52 static void qla_del_rcv_cntxt(qla_host_t *ha);
53 static int qla_init_rcv_cntxt(qla_host_t *ha);
54 static int qla_del_xmt_cntxt(qla_host_t *ha);
55 static int qla_init_xmt_cntxt(qla_host_t *ha);
56 static int qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
57 uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause);
58 static int qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx,
59 uint32_t num_intrs, uint32_t create);
60 static int qla_config_rss(qla_host_t *ha, uint16_t cntxt_id);
61 static int qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id,
62 int tenable, int rcv);
63 static int qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode);
64 static int qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id);
65
66 static int qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd,
67 uint8_t *hdr);
68 static int qla_hw_add_all_mcast(qla_host_t *ha);
69 static int qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds);
70
71 static int qla_init_nic_func(qla_host_t *ha);
72 static int qla_stop_nic_func(qla_host_t *ha);
73 static int qla_query_fw_dcbx_caps(qla_host_t *ha);
74 static int qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits);
75 static int qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits);
76 static int qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode);
77 static int qla_get_cam_search_mode(qla_host_t *ha);
78
79 static void ql_minidump_free(qla_host_t *ha);
80
81 #ifdef QL_DBG
82
83 static void
qla_stop_pegs(qla_host_t * ha)84 qla_stop_pegs(qla_host_t *ha)
85 {
86 uint32_t val = 1;
87
88 ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0);
89 ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0);
90 ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0);
91 ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0);
92 ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0);
93 device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__);
94 }
95
96 static int
qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)97 qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)
98 {
99 int err, ret = 0;
100 qla_host_t *ha;
101
102 err = sysctl_handle_int(oidp, &ret, 0, req);
103
104 if (err || !req->newptr)
105 return (err);
106
107 if (ret == 1) {
108 ha = (qla_host_t *)arg1;
109 if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
110 qla_stop_pegs(ha);
111 QLA_UNLOCK(ha, __func__);
112 }
113 }
114
115 return err;
116 }
117 #endif /* #ifdef QL_DBG */
118
119 static int
qla_validate_set_port_cfg_bit(uint32_t bits)120 qla_validate_set_port_cfg_bit(uint32_t bits)
121 {
122 if ((bits & 0xF) > 1)
123 return (-1);
124
125 if (((bits >> 4) & 0xF) > 2)
126 return (-1);
127
128 if (((bits >> 8) & 0xF) > 2)
129 return (-1);
130
131 return (0);
132 }
133
134 static int
qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS)135 qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS)
136 {
137 int err, ret = 0;
138 qla_host_t *ha;
139 uint32_t cfg_bits;
140
141 err = sysctl_handle_int(oidp, &ret, 0, req);
142
143 if (err || !req->newptr)
144 return (err);
145
146 ha = (qla_host_t *)arg1;
147
148 if ((qla_validate_set_port_cfg_bit((uint32_t)ret) == 0)) {
149 err = qla_get_port_config(ha, &cfg_bits);
150
151 if (err)
152 goto qla_sysctl_set_port_cfg_exit;
153
154 if (ret & 0x1) {
155 cfg_bits |= Q8_PORT_CFG_BITS_DCBX_ENABLE;
156 } else {
157 cfg_bits &= ~Q8_PORT_CFG_BITS_DCBX_ENABLE;
158 }
159
160 ret = ret >> 4;
161 cfg_bits &= ~Q8_PORT_CFG_BITS_PAUSE_CFG_MASK;
162
163 if ((ret & 0xF) == 0) {
164 cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_DISABLED;
165 } else if ((ret & 0xF) == 1){
166 cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_STD;
167 } else {
168 cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_PPM;
169 }
170
171 ret = ret >> 4;
172 cfg_bits &= ~Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK;
173
174 if (ret == 0) {
175 cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT_RCV;
176 } else if (ret == 1){
177 cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT;
178 } else {
179 cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_RCV;
180 }
181
182 if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
183 err = qla_set_port_config(ha, cfg_bits);
184 QLA_UNLOCK(ha, __func__);
185 } else {
186 device_printf(ha->pci_dev, "%s: failed\n", __func__);
187 }
188 } else {
189 if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
190 err = qla_get_port_config(ha, &cfg_bits);
191 QLA_UNLOCK(ha, __func__);
192 } else {
193 device_printf(ha->pci_dev, "%s: failed\n", __func__);
194 }
195 }
196
197 qla_sysctl_set_port_cfg_exit:
198 return err;
199 }
200
201 static int
qla_sysctl_set_cam_search_mode(SYSCTL_HANDLER_ARGS)202 qla_sysctl_set_cam_search_mode(SYSCTL_HANDLER_ARGS)
203 {
204 int err, ret = 0;
205 qla_host_t *ha;
206
207 err = sysctl_handle_int(oidp, &ret, 0, req);
208
209 if (err || !req->newptr)
210 return (err);
211
212 ha = (qla_host_t *)arg1;
213
214 if ((ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_INTERNAL) ||
215 (ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_AUTO)) {
216 if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
217 err = qla_set_cam_search_mode(ha, (uint32_t)ret);
218 QLA_UNLOCK(ha, __func__);
219 } else {
220 device_printf(ha->pci_dev, "%s: failed\n", __func__);
221 }
222
223 } else {
224 device_printf(ha->pci_dev, "%s: ret = %d\n", __func__, ret);
225 }
226
227 return (err);
228 }
229
230 static int
qla_sysctl_get_cam_search_mode(SYSCTL_HANDLER_ARGS)231 qla_sysctl_get_cam_search_mode(SYSCTL_HANDLER_ARGS)
232 {
233 int err, ret = 0;
234 qla_host_t *ha;
235
236 err = sysctl_handle_int(oidp, &ret, 0, req);
237
238 if (err || !req->newptr)
239 return (err);
240
241 ha = (qla_host_t *)arg1;
242 if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
243 err = qla_get_cam_search_mode(ha);
244 QLA_UNLOCK(ha, __func__);
245 } else {
246 device_printf(ha->pci_dev, "%s: failed\n", __func__);
247 }
248
249 return (err);
250 }
251
252 static void
qlnx_add_hw_mac_stats_sysctls(qla_host_t * ha)253 qlnx_add_hw_mac_stats_sysctls(qla_host_t *ha)
254 {
255 struct sysctl_ctx_list *ctx;
256 struct sysctl_oid_list *children;
257 struct sysctl_oid *ctx_oid;
258
259 ctx = device_get_sysctl_ctx(ha->pci_dev);
260 children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
261
262 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_mac",
263 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_hw_mac");
264 children = SYSCTL_CHILDREN(ctx_oid);
265
266 SYSCTL_ADD_QUAD(ctx, children,
267 OID_AUTO, "xmt_frames",
268 CTLFLAG_RD, &ha->hw.mac.xmt_frames,
269 "xmt_frames");
270
271 SYSCTL_ADD_QUAD(ctx, children,
272 OID_AUTO, "xmt_bytes",
273 CTLFLAG_RD, &ha->hw.mac.xmt_bytes,
274 "xmt_frames");
275
276 SYSCTL_ADD_QUAD(ctx, children,
277 OID_AUTO, "xmt_mcast_pkts",
278 CTLFLAG_RD, &ha->hw.mac.xmt_mcast_pkts,
279 "xmt_mcast_pkts");
280
281 SYSCTL_ADD_QUAD(ctx, children,
282 OID_AUTO, "xmt_bcast_pkts",
283 CTLFLAG_RD, &ha->hw.mac.xmt_bcast_pkts,
284 "xmt_bcast_pkts");
285
286 SYSCTL_ADD_QUAD(ctx, children,
287 OID_AUTO, "xmt_pause_frames",
288 CTLFLAG_RD, &ha->hw.mac.xmt_pause_frames,
289 "xmt_pause_frames");
290
291 SYSCTL_ADD_QUAD(ctx, children,
292 OID_AUTO, "xmt_cntrl_pkts",
293 CTLFLAG_RD, &ha->hw.mac.xmt_cntrl_pkts,
294 "xmt_cntrl_pkts");
295
296 SYSCTL_ADD_QUAD(ctx, children,
297 OID_AUTO, "xmt_pkt_lt_64bytes",
298 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_64bytes,
299 "xmt_pkt_lt_64bytes");
300
301 SYSCTL_ADD_QUAD(ctx, children,
302 OID_AUTO, "xmt_pkt_lt_127bytes",
303 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_127bytes,
304 "xmt_pkt_lt_127bytes");
305
306 SYSCTL_ADD_QUAD(ctx, children,
307 OID_AUTO, "xmt_pkt_lt_255bytes",
308 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_255bytes,
309 "xmt_pkt_lt_255bytes");
310
311 SYSCTL_ADD_QUAD(ctx, children,
312 OID_AUTO, "xmt_pkt_lt_511bytes",
313 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_511bytes,
314 "xmt_pkt_lt_511bytes");
315
316 SYSCTL_ADD_QUAD(ctx, children,
317 OID_AUTO, "xmt_pkt_lt_1023bytes",
318 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_1023bytes,
319 "xmt_pkt_lt_1023bytes");
320
321 SYSCTL_ADD_QUAD(ctx, children,
322 OID_AUTO, "xmt_pkt_lt_1518bytes",
323 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_1518bytes,
324 "xmt_pkt_lt_1518bytes");
325
326 SYSCTL_ADD_QUAD(ctx, children,
327 OID_AUTO, "xmt_pkt_gt_1518bytes",
328 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_gt_1518bytes,
329 "xmt_pkt_gt_1518bytes");
330
331 SYSCTL_ADD_QUAD(ctx, children,
332 OID_AUTO, "rcv_frames",
333 CTLFLAG_RD, &ha->hw.mac.rcv_frames,
334 "rcv_frames");
335
336 SYSCTL_ADD_QUAD(ctx, children,
337 OID_AUTO, "rcv_bytes",
338 CTLFLAG_RD, &ha->hw.mac.rcv_bytes,
339 "rcv_bytes");
340
341 SYSCTL_ADD_QUAD(ctx, children,
342 OID_AUTO, "rcv_mcast_pkts",
343 CTLFLAG_RD, &ha->hw.mac.rcv_mcast_pkts,
344 "rcv_mcast_pkts");
345
346 SYSCTL_ADD_QUAD(ctx, children,
347 OID_AUTO, "rcv_bcast_pkts",
348 CTLFLAG_RD, &ha->hw.mac.rcv_bcast_pkts,
349 "rcv_bcast_pkts");
350
351 SYSCTL_ADD_QUAD(ctx, children,
352 OID_AUTO, "rcv_pause_frames",
353 CTLFLAG_RD, &ha->hw.mac.rcv_pause_frames,
354 "rcv_pause_frames");
355
356 SYSCTL_ADD_QUAD(ctx, children,
357 OID_AUTO, "rcv_cntrl_pkts",
358 CTLFLAG_RD, &ha->hw.mac.rcv_cntrl_pkts,
359 "rcv_cntrl_pkts");
360
361 SYSCTL_ADD_QUAD(ctx, children,
362 OID_AUTO, "rcv_pkt_lt_64bytes",
363 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_64bytes,
364 "rcv_pkt_lt_64bytes");
365
366 SYSCTL_ADD_QUAD(ctx, children,
367 OID_AUTO, "rcv_pkt_lt_127bytes",
368 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_127bytes,
369 "rcv_pkt_lt_127bytes");
370
371 SYSCTL_ADD_QUAD(ctx, children,
372 OID_AUTO, "rcv_pkt_lt_255bytes",
373 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_255bytes,
374 "rcv_pkt_lt_255bytes");
375
376 SYSCTL_ADD_QUAD(ctx, children,
377 OID_AUTO, "rcv_pkt_lt_511bytes",
378 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_511bytes,
379 "rcv_pkt_lt_511bytes");
380
381 SYSCTL_ADD_QUAD(ctx, children,
382 OID_AUTO, "rcv_pkt_lt_1023bytes",
383 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_1023bytes,
384 "rcv_pkt_lt_1023bytes");
385
386 SYSCTL_ADD_QUAD(ctx, children,
387 OID_AUTO, "rcv_pkt_lt_1518bytes",
388 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_1518bytes,
389 "rcv_pkt_lt_1518bytes");
390
391 SYSCTL_ADD_QUAD(ctx, children,
392 OID_AUTO, "rcv_pkt_gt_1518bytes",
393 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_gt_1518bytes,
394 "rcv_pkt_gt_1518bytes");
395
396 SYSCTL_ADD_QUAD(ctx, children,
397 OID_AUTO, "rcv_len_error",
398 CTLFLAG_RD, &ha->hw.mac.rcv_len_error,
399 "rcv_len_error");
400
401 SYSCTL_ADD_QUAD(ctx, children,
402 OID_AUTO, "rcv_len_small",
403 CTLFLAG_RD, &ha->hw.mac.rcv_len_small,
404 "rcv_len_small");
405
406 SYSCTL_ADD_QUAD(ctx, children,
407 OID_AUTO, "rcv_len_large",
408 CTLFLAG_RD, &ha->hw.mac.rcv_len_large,
409 "rcv_len_large");
410
411 SYSCTL_ADD_QUAD(ctx, children,
412 OID_AUTO, "rcv_jabber",
413 CTLFLAG_RD, &ha->hw.mac.rcv_jabber,
414 "rcv_jabber");
415
416 SYSCTL_ADD_QUAD(ctx, children,
417 OID_AUTO, "rcv_dropped",
418 CTLFLAG_RD, &ha->hw.mac.rcv_dropped,
419 "rcv_dropped");
420
421 SYSCTL_ADD_QUAD(ctx, children,
422 OID_AUTO, "fcs_error",
423 CTLFLAG_RD, &ha->hw.mac.fcs_error,
424 "fcs_error");
425
426 SYSCTL_ADD_QUAD(ctx, children,
427 OID_AUTO, "align_error",
428 CTLFLAG_RD, &ha->hw.mac.align_error,
429 "align_error");
430
431 SYSCTL_ADD_QUAD(ctx, children,
432 OID_AUTO, "eswitched_frames",
433 CTLFLAG_RD, &ha->hw.mac.eswitched_frames,
434 "eswitched_frames");
435
436 SYSCTL_ADD_QUAD(ctx, children,
437 OID_AUTO, "eswitched_bytes",
438 CTLFLAG_RD, &ha->hw.mac.eswitched_bytes,
439 "eswitched_bytes");
440
441 SYSCTL_ADD_QUAD(ctx, children,
442 OID_AUTO, "eswitched_mcast_frames",
443 CTLFLAG_RD, &ha->hw.mac.eswitched_mcast_frames,
444 "eswitched_mcast_frames");
445
446 SYSCTL_ADD_QUAD(ctx, children,
447 OID_AUTO, "eswitched_bcast_frames",
448 CTLFLAG_RD, &ha->hw.mac.eswitched_bcast_frames,
449 "eswitched_bcast_frames");
450
451 SYSCTL_ADD_QUAD(ctx, children,
452 OID_AUTO, "eswitched_ucast_frames",
453 CTLFLAG_RD, &ha->hw.mac.eswitched_ucast_frames,
454 "eswitched_ucast_frames");
455
456 SYSCTL_ADD_QUAD(ctx, children,
457 OID_AUTO, "eswitched_err_free_frames",
458 CTLFLAG_RD, &ha->hw.mac.eswitched_err_free_frames,
459 "eswitched_err_free_frames");
460
461 SYSCTL_ADD_QUAD(ctx, children,
462 OID_AUTO, "eswitched_err_free_bytes",
463 CTLFLAG_RD, &ha->hw.mac.eswitched_err_free_bytes,
464 "eswitched_err_free_bytes");
465
466 return;
467 }
468
469 static void
qlnx_add_hw_rcv_stats_sysctls(qla_host_t * ha)470 qlnx_add_hw_rcv_stats_sysctls(qla_host_t *ha)
471 {
472 struct sysctl_ctx_list *ctx;
473 struct sysctl_oid_list *children;
474 struct sysctl_oid *ctx_oid;
475
476 ctx = device_get_sysctl_ctx(ha->pci_dev);
477 children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
478
479 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_rcv",
480 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_hw_rcv");
481 children = SYSCTL_CHILDREN(ctx_oid);
482
483 SYSCTL_ADD_QUAD(ctx, children,
484 OID_AUTO, "total_bytes",
485 CTLFLAG_RD, &ha->hw.rcv.total_bytes,
486 "total_bytes");
487
488 SYSCTL_ADD_QUAD(ctx, children,
489 OID_AUTO, "total_pkts",
490 CTLFLAG_RD, &ha->hw.rcv.total_pkts,
491 "total_pkts");
492
493 SYSCTL_ADD_QUAD(ctx, children,
494 OID_AUTO, "lro_pkt_count",
495 CTLFLAG_RD, &ha->hw.rcv.lro_pkt_count,
496 "lro_pkt_count");
497
498 SYSCTL_ADD_QUAD(ctx, children,
499 OID_AUTO, "sw_pkt_count",
500 CTLFLAG_RD, &ha->hw.rcv.sw_pkt_count,
501 "sw_pkt_count");
502
503 SYSCTL_ADD_QUAD(ctx, children,
504 OID_AUTO, "ip_chksum_err",
505 CTLFLAG_RD, &ha->hw.rcv.ip_chksum_err,
506 "ip_chksum_err");
507
508 SYSCTL_ADD_QUAD(ctx, children,
509 OID_AUTO, "pkts_wo_acntxts",
510 CTLFLAG_RD, &ha->hw.rcv.pkts_wo_acntxts,
511 "pkts_wo_acntxts");
512
513 SYSCTL_ADD_QUAD(ctx, children,
514 OID_AUTO, "pkts_dropped_no_sds_card",
515 CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_sds_card,
516 "pkts_dropped_no_sds_card");
517
518 SYSCTL_ADD_QUAD(ctx, children,
519 OID_AUTO, "pkts_dropped_no_sds_host",
520 CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_sds_host,
521 "pkts_dropped_no_sds_host");
522
523 SYSCTL_ADD_QUAD(ctx, children,
524 OID_AUTO, "oversized_pkts",
525 CTLFLAG_RD, &ha->hw.rcv.oversized_pkts,
526 "oversized_pkts");
527
528 SYSCTL_ADD_QUAD(ctx, children,
529 OID_AUTO, "pkts_dropped_no_rds",
530 CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_rds,
531 "pkts_dropped_no_rds");
532
533 SYSCTL_ADD_QUAD(ctx, children,
534 OID_AUTO, "unxpctd_mcast_pkts",
535 CTLFLAG_RD, &ha->hw.rcv.unxpctd_mcast_pkts,
536 "unxpctd_mcast_pkts");
537
538 SYSCTL_ADD_QUAD(ctx, children,
539 OID_AUTO, "re1_fbq_error",
540 CTLFLAG_RD, &ha->hw.rcv.re1_fbq_error,
541 "re1_fbq_error");
542
543 SYSCTL_ADD_QUAD(ctx, children,
544 OID_AUTO, "invalid_mac_addr",
545 CTLFLAG_RD, &ha->hw.rcv.invalid_mac_addr,
546 "invalid_mac_addr");
547
548 SYSCTL_ADD_QUAD(ctx, children,
549 OID_AUTO, "rds_prime_trys",
550 CTLFLAG_RD, &ha->hw.rcv.rds_prime_trys,
551 "rds_prime_trys");
552
553 SYSCTL_ADD_QUAD(ctx, children,
554 OID_AUTO, "rds_prime_success",
555 CTLFLAG_RD, &ha->hw.rcv.rds_prime_success,
556 "rds_prime_success");
557
558 SYSCTL_ADD_QUAD(ctx, children,
559 OID_AUTO, "lro_flows_added",
560 CTLFLAG_RD, &ha->hw.rcv.lro_flows_added,
561 "lro_flows_added");
562
563 SYSCTL_ADD_QUAD(ctx, children,
564 OID_AUTO, "lro_flows_deleted",
565 CTLFLAG_RD, &ha->hw.rcv.lro_flows_deleted,
566 "lro_flows_deleted");
567
568 SYSCTL_ADD_QUAD(ctx, children,
569 OID_AUTO, "lro_flows_active",
570 CTLFLAG_RD, &ha->hw.rcv.lro_flows_active,
571 "lro_flows_active");
572
573 SYSCTL_ADD_QUAD(ctx, children,
574 OID_AUTO, "pkts_droped_unknown",
575 CTLFLAG_RD, &ha->hw.rcv.pkts_droped_unknown,
576 "pkts_droped_unknown");
577
578 SYSCTL_ADD_QUAD(ctx, children,
579 OID_AUTO, "pkts_cnt_oversized",
580 CTLFLAG_RD, &ha->hw.rcv.pkts_cnt_oversized,
581 "pkts_cnt_oversized");
582
583 return;
584 }
585
586 static void
qlnx_add_hw_xmt_stats_sysctls(qla_host_t * ha)587 qlnx_add_hw_xmt_stats_sysctls(qla_host_t *ha)
588 {
589 struct sysctl_ctx_list *ctx;
590 struct sysctl_oid_list *children;
591 struct sysctl_oid_list *node_children;
592 struct sysctl_oid *ctx_oid;
593 int i;
594 uint8_t name_str[16];
595
596 ctx = device_get_sysctl_ctx(ha->pci_dev);
597 children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
598
599 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_xmt",
600 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_hw_xmt");
601 children = SYSCTL_CHILDREN(ctx_oid);
602
603 for (i = 0; i < ha->hw.num_tx_rings; i++) {
604 bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
605 snprintf(name_str, sizeof(name_str), "%d", i);
606
607 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
608 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, name_str);
609 node_children = SYSCTL_CHILDREN(ctx_oid);
610
611 /* Tx Related */
612
613 SYSCTL_ADD_QUAD(ctx, node_children,
614 OID_AUTO, "total_bytes",
615 CTLFLAG_RD, &ha->hw.xmt[i].total_bytes,
616 "total_bytes");
617
618 SYSCTL_ADD_QUAD(ctx, node_children,
619 OID_AUTO, "total_pkts",
620 CTLFLAG_RD, &ha->hw.xmt[i].total_pkts,
621 "total_pkts");
622
623 SYSCTL_ADD_QUAD(ctx, node_children,
624 OID_AUTO, "errors",
625 CTLFLAG_RD, &ha->hw.xmt[i].errors,
626 "errors");
627
628 SYSCTL_ADD_QUAD(ctx, node_children,
629 OID_AUTO, "pkts_dropped",
630 CTLFLAG_RD, &ha->hw.xmt[i].pkts_dropped,
631 "pkts_dropped");
632
633 SYSCTL_ADD_QUAD(ctx, node_children,
634 OID_AUTO, "switch_pkts",
635 CTLFLAG_RD, &ha->hw.xmt[i].switch_pkts,
636 "switch_pkts");
637
638 SYSCTL_ADD_QUAD(ctx, node_children,
639 OID_AUTO, "num_buffers",
640 CTLFLAG_RD, &ha->hw.xmt[i].num_buffers,
641 "num_buffers");
642 }
643
644 return;
645 }
646
647 static void
qlnx_add_hw_mbx_cmpl_stats_sysctls(qla_host_t * ha)648 qlnx_add_hw_mbx_cmpl_stats_sysctls(qla_host_t *ha)
649 {
650 struct sysctl_ctx_list *ctx;
651 struct sysctl_oid_list *node_children;
652
653 ctx = device_get_sysctl_ctx(ha->pci_dev);
654 node_children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
655
656 SYSCTL_ADD_QUAD(ctx, node_children,
657 OID_AUTO, "mbx_completion_time_lt_200ms",
658 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[0],
659 "mbx_completion_time_lt_200ms");
660
661 SYSCTL_ADD_QUAD(ctx, node_children,
662 OID_AUTO, "mbx_completion_time_200ms_400ms",
663 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[1],
664 "mbx_completion_time_200ms_400ms");
665
666 SYSCTL_ADD_QUAD(ctx, node_children,
667 OID_AUTO, "mbx_completion_time_400ms_600ms",
668 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[2],
669 "mbx_completion_time_400ms_600ms");
670
671 SYSCTL_ADD_QUAD(ctx, node_children,
672 OID_AUTO, "mbx_completion_time_600ms_800ms",
673 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[3],
674 "mbx_completion_time_600ms_800ms");
675
676 SYSCTL_ADD_QUAD(ctx, node_children,
677 OID_AUTO, "mbx_completion_time_800ms_1000ms",
678 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[4],
679 "mbx_completion_time_800ms_1000ms");
680
681 SYSCTL_ADD_QUAD(ctx, node_children,
682 OID_AUTO, "mbx_completion_time_1000ms_1200ms",
683 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[5],
684 "mbx_completion_time_1000ms_1200ms");
685
686 SYSCTL_ADD_QUAD(ctx, node_children,
687 OID_AUTO, "mbx_completion_time_1200ms_1400ms",
688 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[6],
689 "mbx_completion_time_1200ms_1400ms");
690
691 SYSCTL_ADD_QUAD(ctx, node_children,
692 OID_AUTO, "mbx_completion_time_1400ms_1600ms",
693 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[7],
694 "mbx_completion_time_1400ms_1600ms");
695
696 SYSCTL_ADD_QUAD(ctx, node_children,
697 OID_AUTO, "mbx_completion_time_1600ms_1800ms",
698 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[8],
699 "mbx_completion_time_1600ms_1800ms");
700
701 SYSCTL_ADD_QUAD(ctx, node_children,
702 OID_AUTO, "mbx_completion_time_1800ms_2000ms",
703 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[9],
704 "mbx_completion_time_1800ms_2000ms");
705
706 SYSCTL_ADD_QUAD(ctx, node_children,
707 OID_AUTO, "mbx_completion_time_2000ms_2200ms",
708 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[10],
709 "mbx_completion_time_2000ms_2200ms");
710
711 SYSCTL_ADD_QUAD(ctx, node_children,
712 OID_AUTO, "mbx_completion_time_2200ms_2400ms",
713 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[11],
714 "mbx_completion_time_2200ms_2400ms");
715
716 SYSCTL_ADD_QUAD(ctx, node_children,
717 OID_AUTO, "mbx_completion_time_2400ms_2600ms",
718 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[12],
719 "mbx_completion_time_2400ms_2600ms");
720
721 SYSCTL_ADD_QUAD(ctx, node_children,
722 OID_AUTO, "mbx_completion_time_2600ms_2800ms",
723 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[13],
724 "mbx_completion_time_2600ms_2800ms");
725
726 SYSCTL_ADD_QUAD(ctx, node_children,
727 OID_AUTO, "mbx_completion_time_2800ms_3000ms",
728 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[14],
729 "mbx_completion_time_2800ms_3000ms");
730
731 SYSCTL_ADD_QUAD(ctx, node_children,
732 OID_AUTO, "mbx_completion_time_3000ms_4000ms",
733 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[15],
734 "mbx_completion_time_3000ms_4000ms");
735
736 SYSCTL_ADD_QUAD(ctx, node_children,
737 OID_AUTO, "mbx_completion_time_4000ms_5000ms",
738 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[16],
739 "mbx_completion_time_4000ms_5000ms");
740
741 SYSCTL_ADD_QUAD(ctx, node_children,
742 OID_AUTO, "mbx_completion_host_mbx_cntrl_timeout",
743 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[17],
744 "mbx_completion_host_mbx_cntrl_timeout");
745
746 SYSCTL_ADD_QUAD(ctx, node_children,
747 OID_AUTO, "mbx_completion_fw_mbx_cntrl_timeout",
748 CTLFLAG_RD, &ha->hw.mbx_comp_msecs[18],
749 "mbx_completion_fw_mbx_cntrl_timeout");
750 return;
751 }
752
753 static void
qlnx_add_hw_stats_sysctls(qla_host_t * ha)754 qlnx_add_hw_stats_sysctls(qla_host_t *ha)
755 {
756 qlnx_add_hw_mac_stats_sysctls(ha);
757 qlnx_add_hw_rcv_stats_sysctls(ha);
758 qlnx_add_hw_xmt_stats_sysctls(ha);
759 qlnx_add_hw_mbx_cmpl_stats_sysctls(ha);
760
761 return;
762 }
763
764 static void
qlnx_add_drvr_sds_stats(qla_host_t * ha)765 qlnx_add_drvr_sds_stats(qla_host_t *ha)
766 {
767 struct sysctl_ctx_list *ctx;
768 struct sysctl_oid_list *children;
769 struct sysctl_oid_list *node_children;
770 struct sysctl_oid *ctx_oid;
771 int i;
772 uint8_t name_str[16];
773
774 ctx = device_get_sysctl_ctx(ha->pci_dev);
775 children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
776
777 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_sds",
778 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_drvr_sds");
779 children = SYSCTL_CHILDREN(ctx_oid);
780
781 for (i = 0; i < ha->hw.num_sds_rings; i++) {
782 bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
783 snprintf(name_str, sizeof(name_str), "%d", i);
784
785 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
786 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, name_str);
787 node_children = SYSCTL_CHILDREN(ctx_oid);
788
789 SYSCTL_ADD_QUAD(ctx, node_children,
790 OID_AUTO, "intr_count",
791 CTLFLAG_RD, &ha->hw.sds[i].intr_count,
792 "intr_count");
793
794 SYSCTL_ADD_UINT(ctx, node_children,
795 OID_AUTO, "rx_free",
796 CTLFLAG_RD, &ha->hw.sds[i].rx_free,
797 ha->hw.sds[i].rx_free, "rx_free");
798 }
799
800 return;
801 }
802 static void
qlnx_add_drvr_rds_stats(qla_host_t * ha)803 qlnx_add_drvr_rds_stats(qla_host_t *ha)
804 {
805 struct sysctl_ctx_list *ctx;
806 struct sysctl_oid_list *children;
807 struct sysctl_oid_list *node_children;
808 struct sysctl_oid *ctx_oid;
809 int i;
810 uint8_t name_str[16];
811
812 ctx = device_get_sysctl_ctx(ha->pci_dev);
813 children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
814
815 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_rds",
816 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_drvr_rds");
817 children = SYSCTL_CHILDREN(ctx_oid);
818
819 for (i = 0; i < ha->hw.num_rds_rings; i++) {
820 bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
821 snprintf(name_str, sizeof(name_str), "%d", i);
822
823 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
824 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, name_str);
825 node_children = SYSCTL_CHILDREN(ctx_oid);
826
827 SYSCTL_ADD_QUAD(ctx, node_children,
828 OID_AUTO, "count",
829 CTLFLAG_RD, &ha->hw.rds[i].count,
830 "count");
831
832 SYSCTL_ADD_QUAD(ctx, node_children,
833 OID_AUTO, "lro_pkt_count",
834 CTLFLAG_RD, &ha->hw.rds[i].lro_pkt_count,
835 "lro_pkt_count");
836
837 SYSCTL_ADD_QUAD(ctx, node_children,
838 OID_AUTO, "lro_bytes",
839 CTLFLAG_RD, &ha->hw.rds[i].lro_bytes,
840 "lro_bytes");
841 }
842
843 return;
844 }
845
846 static void
qlnx_add_drvr_tx_stats(qla_host_t * ha)847 qlnx_add_drvr_tx_stats(qla_host_t *ha)
848 {
849 struct sysctl_ctx_list *ctx;
850 struct sysctl_oid_list *children;
851 struct sysctl_oid_list *node_children;
852 struct sysctl_oid *ctx_oid;
853 int i;
854 uint8_t name_str[16];
855
856 ctx = device_get_sysctl_ctx(ha->pci_dev);
857 children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
858
859 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_xmt",
860 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_drvr_xmt");
861 children = SYSCTL_CHILDREN(ctx_oid);
862
863 for (i = 0; i < ha->hw.num_tx_rings; i++) {
864 bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
865 snprintf(name_str, sizeof(name_str), "%d", i);
866
867 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
868 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, name_str);
869 node_children = SYSCTL_CHILDREN(ctx_oid);
870
871 SYSCTL_ADD_QUAD(ctx, node_children,
872 OID_AUTO, "count",
873 CTLFLAG_RD, &ha->tx_ring[i].count,
874 "count");
875
876 #ifdef QL_ENABLE_ISCSI_TLV
877 SYSCTL_ADD_QUAD(ctx, node_children,
878 OID_AUTO, "iscsi_pkt_count",
879 CTLFLAG_RD, &ha->tx_ring[i].iscsi_pkt_count,
880 "iscsi_pkt_count");
881 #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
882 }
883
884 return;
885 }
886
887 static void
qlnx_add_drvr_stats_sysctls(qla_host_t * ha)888 qlnx_add_drvr_stats_sysctls(qla_host_t *ha)
889 {
890 qlnx_add_drvr_sds_stats(ha);
891 qlnx_add_drvr_rds_stats(ha);
892 qlnx_add_drvr_tx_stats(ha);
893 return;
894 }
895
896 /*
897 * Name: ql_hw_add_sysctls
898 * Function: Add P3Plus specific sysctls
899 */
900 void
ql_hw_add_sysctls(qla_host_t * ha)901 ql_hw_add_sysctls(qla_host_t *ha)
902 {
903 device_t dev;
904
905 dev = ha->pci_dev;
906
907 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
908 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
909 OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings,
910 ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings");
911
912 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
913 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
914 OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings,
915 ha->hw.num_sds_rings, "Number of Status Descriptor Rings");
916
917 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
918 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
919 OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings,
920 ha->hw.num_tx_rings, "Number of Transmit Rings");
921
922 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
923 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
924 OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx,
925 ha->txr_idx, "Tx Ring Used");
926
927 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
928 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
929 OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs,
930 ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt");
931
932 ha->hw.sds_cidx_thres = 32;
933 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
934 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
935 OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres,
936 ha->hw.sds_cidx_thres,
937 "Number of SDS entries to process before updating"
938 " SDS Ring Consumer Index");
939
940 ha->hw.rds_pidx_thres = 32;
941 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
942 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
943 OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres,
944 ha->hw.rds_pidx_thres,
945 "Number of Rcv Rings Entries to post before updating"
946 " RDS Ring Producer Index");
947
948 ha->hw.rcv_intr_coalesce = (3 << 16) | 256;
949 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
950 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
951 OID_AUTO, "rcv_intr_coalesce", CTLFLAG_RW,
952 &ha->hw.rcv_intr_coalesce,
953 ha->hw.rcv_intr_coalesce,
954 "Rcv Intr Coalescing Parameters\n"
955 "\tbits 15:0 max packets\n"
956 "\tbits 31:16 max micro-seconds to wait\n"
957 "\tplease run\n"
958 "\tifconfig <if> down && ifconfig <if> up\n"
959 "\tto take effect \n");
960
961 ha->hw.xmt_intr_coalesce = (64 << 16) | 64;
962 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
963 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
964 OID_AUTO, "xmt_intr_coalesce", CTLFLAG_RW,
965 &ha->hw.xmt_intr_coalesce,
966 ha->hw.xmt_intr_coalesce,
967 "Xmt Intr Coalescing Parameters\n"
968 "\tbits 15:0 max packets\n"
969 "\tbits 31:16 max micro-seconds to wait\n"
970 "\tplease run\n"
971 "\tifconfig <if> down && ifconfig <if> up\n"
972 "\tto take effect \n");
973
974 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
975 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
976 "port_cfg", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
977 (void *)ha, 0, qla_sysctl_port_cfg, "I",
978 "Set Port Configuration if values below "
979 "otherwise Get Port Configuration\n"
980 "\tBits 0-3 ; 1 = DCBX Enable; 0 = DCBX Disable\n"
981 "\tBits 4-7 : 0 = no pause; 1 = std ; 2 = ppm \n"
982 "\tBits 8-11: std pause cfg; 0 = xmt and rcv;"
983 " 1 = xmt only; 2 = rcv only;\n");
984
985 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
986 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
987 "set_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
988 (void *)ha, 0, qla_sysctl_set_cam_search_mode, "I",
989 "Set CAM Search Mode"
990 "\t 1 = search mode internal\n"
991 "\t 2 = search mode auto\n");
992
993 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
994 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
995 "get_cam_search_mode",
996 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, (void *)ha, 0,
997 qla_sysctl_get_cam_search_mode, "I",
998 "Get CAM Search Mode"
999 "\t 1 = search mode internal\n"
1000 "\t 2 = search mode auto\n");
1001
1002 ha->hw.enable_9kb = 1;
1003
1004 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1005 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1006 OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb,
1007 ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000");
1008
1009 ha->hw.enable_hw_lro = 1;
1010
1011 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1012 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1013 OID_AUTO, "enable_hw_lro", CTLFLAG_RW, &ha->hw.enable_hw_lro,
1014 ha->hw.enable_hw_lro, "Enable Hardware LRO; Default is true \n"
1015 "\t 1 : Hardware LRO if LRO is enabled\n"
1016 "\t 0 : Software LRO if LRO is enabled\n"
1017 "\t Any change requires ifconfig down/up to take effect\n"
1018 "\t Note that LRO may be turned off/on via ifconfig\n");
1019
1020 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1021 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1022 OID_AUTO, "sp_log_index", CTLFLAG_RW, &ha->hw.sp_log_index,
1023 ha->hw.sp_log_index, "sp_log_index");
1024
1025 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1026 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1027 OID_AUTO, "sp_log_stop", CTLFLAG_RW, &ha->hw.sp_log_stop,
1028 ha->hw.sp_log_stop, "sp_log_stop");
1029
1030 ha->hw.sp_log_stop_events = 0;
1031
1032 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1033 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1034 OID_AUTO, "sp_log_stop_events", CTLFLAG_RW,
1035 &ha->hw.sp_log_stop_events,
1036 ha->hw.sp_log_stop_events, "Slow path event log is stopped"
1037 " when OR of the following events occur \n"
1038 "\t 0x01 : Heart beat Failure\n"
1039 "\t 0x02 : Temperature Failure\n"
1040 "\t 0x04 : HW Initialization Failure\n"
1041 "\t 0x08 : Interface Initialization Failure\n"
1042 "\t 0x10 : Error Recovery Failure\n");
1043
1044 ha->hw.mdump_active = 0;
1045 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1046 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1047 OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active,
1048 ha->hw.mdump_active,
1049 "Minidump retrieval is Active");
1050
1051 ha->hw.mdump_done = 0;
1052 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1053 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1054 OID_AUTO, "mdump_done", CTLFLAG_RW,
1055 &ha->hw.mdump_done, ha->hw.mdump_done,
1056 "Minidump has been done and available for retrieval");
1057
1058 ha->hw.mdump_capture_mask = 0xF;
1059 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1060 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1061 OID_AUTO, "minidump_capture_mask", CTLFLAG_RW,
1062 &ha->hw.mdump_capture_mask, ha->hw.mdump_capture_mask,
1063 "Minidump capture mask");
1064 #ifdef QL_DBG
1065
1066 ha->err_inject = 0;
1067 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1068 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1069 OID_AUTO, "err_inject",
1070 CTLFLAG_RW, &ha->err_inject, ha->err_inject,
1071 "Error to be injected\n"
1072 "\t\t\t 0: No Errors\n"
1073 "\t\t\t 1: rcv: rxb struct invalid\n"
1074 "\t\t\t 2: rcv: mp == NULL\n"
1075 "\t\t\t 3: lro: rxb struct invalid\n"
1076 "\t\t\t 4: lro: mp == NULL\n"
1077 "\t\t\t 5: rcv: num handles invalid\n"
1078 "\t\t\t 6: reg: indirect reg rd_wr failure\n"
1079 "\t\t\t 7: ocm: offchip memory rd_wr failure\n"
1080 "\t\t\t 8: mbx: mailbox command failure\n"
1081 "\t\t\t 9: heartbeat failure\n"
1082 "\t\t\t A: temperature failure\n"
1083 "\t\t\t 11: m_getcl or m_getjcl failure\n"
1084 "\t\t\t 13: Invalid Descriptor Count in SGL Receive\n"
1085 "\t\t\t 14: Invalid Descriptor Count in LRO Receive\n"
1086 "\t\t\t 15: peer port error recovery failure\n"
1087 "\t\t\t 16: tx_buf[next_prod_index].mbuf != NULL\n" );
1088
1089 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1090 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
1091 "peg_stop", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
1092 (void *)ha, 0, qla_sysctl_stop_pegs, "I", "Peg Stop");
1093
1094 #endif /* #ifdef QL_DBG */
1095
1096 ha->hw.user_pri_nic = 0;
1097 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1098 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1099 OID_AUTO, "user_pri_nic", CTLFLAG_RW, &ha->hw.user_pri_nic,
1100 ha->hw.user_pri_nic,
1101 "VLAN Tag User Priority for Normal Ethernet Packets");
1102
1103 ha->hw.user_pri_iscsi = 4;
1104 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1105 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1106 OID_AUTO, "user_pri_iscsi", CTLFLAG_RW, &ha->hw.user_pri_iscsi,
1107 ha->hw.user_pri_iscsi,
1108 "VLAN Tag User Priority for iSCSI Packets");
1109
1110 qlnx_add_hw_stats_sysctls(ha);
1111 qlnx_add_drvr_stats_sysctls(ha);
1112
1113 return;
1114 }
1115
1116 void
ql_hw_link_status(qla_host_t * ha)1117 ql_hw_link_status(qla_host_t *ha)
1118 {
1119 device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui);
1120
1121 if (ha->hw.link_up) {
1122 device_printf(ha->pci_dev, "link Up\n");
1123 } else {
1124 device_printf(ha->pci_dev, "link Down\n");
1125 }
1126
1127 if (ha->hw.fduplex) {
1128 device_printf(ha->pci_dev, "Full Duplex\n");
1129 } else {
1130 device_printf(ha->pci_dev, "Half Duplex\n");
1131 }
1132
1133 if (ha->hw.autoneg) {
1134 device_printf(ha->pci_dev, "Auto Negotiation Enabled\n");
1135 } else {
1136 device_printf(ha->pci_dev, "Auto Negotiation Disabled\n");
1137 }
1138
1139 switch (ha->hw.link_speed) {
1140 case 0x710:
1141 device_printf(ha->pci_dev, "link speed\t\t 10Gps\n");
1142 break;
1143
1144 case 0x3E8:
1145 device_printf(ha->pci_dev, "link speed\t\t 1Gps\n");
1146 break;
1147
1148 case 0x64:
1149 device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n");
1150 break;
1151
1152 default:
1153 device_printf(ha->pci_dev, "link speed\t\t Unknown\n");
1154 break;
1155 }
1156
1157 switch (ha->hw.module_type) {
1158 case 0x01:
1159 device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n");
1160 break;
1161
1162 case 0x02:
1163 device_printf(ha->pci_dev, "Module Type 10GBase-LR\n");
1164 break;
1165
1166 case 0x03:
1167 device_printf(ha->pci_dev, "Module Type 10GBase-SR\n");
1168 break;
1169
1170 case 0x04:
1171 device_printf(ha->pci_dev,
1172 "Module Type 10GE Passive Copper(Compliant)[%d m]\n",
1173 ha->hw.cable_length);
1174 break;
1175
1176 case 0x05:
1177 device_printf(ha->pci_dev, "Module Type 10GE Active"
1178 " Limiting Copper(Compliant)[%d m]\n",
1179 ha->hw.cable_length);
1180 break;
1181
1182 case 0x06:
1183 device_printf(ha->pci_dev,
1184 "Module Type 10GE Passive Copper"
1185 " (Legacy, Best Effort)[%d m]\n",
1186 ha->hw.cable_length);
1187 break;
1188
1189 case 0x07:
1190 device_printf(ha->pci_dev, "Module Type 1000Base-SX\n");
1191 break;
1192
1193 case 0x08:
1194 device_printf(ha->pci_dev, "Module Type 1000Base-LX\n");
1195 break;
1196
1197 case 0x09:
1198 device_printf(ha->pci_dev, "Module Type 1000Base-CX\n");
1199 break;
1200
1201 case 0x0A:
1202 device_printf(ha->pci_dev, "Module Type 1000Base-T\n");
1203 break;
1204
1205 case 0x0B:
1206 device_printf(ha->pci_dev, "Module Type 1GE Passive Copper"
1207 "(Legacy, Best Effort)\n");
1208 break;
1209
1210 default:
1211 device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n",
1212 ha->hw.module_type);
1213 break;
1214 }
1215
1216 if (ha->hw.link_faults == 1)
1217 device_printf(ha->pci_dev, "SFP Power Fault\n");
1218 }
1219
1220 /*
1221 * Name: ql_free_dma
1222 * Function: Frees the DMA'able memory allocated in ql_alloc_dma()
1223 */
1224 void
ql_free_dma(qla_host_t * ha)1225 ql_free_dma(qla_host_t *ha)
1226 {
1227 uint32_t i;
1228
1229 if (ha->hw.dma_buf.flags.sds_ring) {
1230 for (i = 0; i < ha->hw.num_sds_rings; i++) {
1231 ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]);
1232 }
1233 ha->hw.dma_buf.flags.sds_ring = 0;
1234 }
1235
1236 if (ha->hw.dma_buf.flags.rds_ring) {
1237 for (i = 0; i < ha->hw.num_rds_rings; i++) {
1238 ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]);
1239 }
1240 ha->hw.dma_buf.flags.rds_ring = 0;
1241 }
1242
1243 if (ha->hw.dma_buf.flags.tx_ring) {
1244 ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring);
1245 ha->hw.dma_buf.flags.tx_ring = 0;
1246 }
1247 ql_minidump_free(ha);
1248 }
1249
1250 /*
1251 * Name: ql_alloc_dma
1252 * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts.
1253 */
1254 int
ql_alloc_dma(qla_host_t * ha)1255 ql_alloc_dma(qla_host_t *ha)
1256 {
1257 device_t dev;
1258 uint32_t i, j, size, tx_ring_size;
1259 qla_hw_t *hw;
1260 qla_hw_tx_cntxt_t *tx_cntxt;
1261 uint8_t *vaddr;
1262 bus_addr_t paddr;
1263
1264 dev = ha->pci_dev;
1265
1266 QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
1267
1268 hw = &ha->hw;
1269 /*
1270 * Allocate Transmit Ring
1271 */
1272 tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS);
1273 size = (tx_ring_size * ha->hw.num_tx_rings);
1274
1275 hw->dma_buf.tx_ring.alignment = 8;
1276 hw->dma_buf.tx_ring.size = size + PAGE_SIZE;
1277
1278 if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) {
1279 device_printf(dev, "%s: tx ring alloc failed\n", __func__);
1280 goto ql_alloc_dma_exit;
1281 }
1282
1283 vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b;
1284 paddr = hw->dma_buf.tx_ring.dma_addr;
1285
1286 for (i = 0; i < ha->hw.num_tx_rings; i++) {
1287 tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
1288
1289 tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr;
1290 tx_cntxt->tx_ring_paddr = paddr;
1291
1292 vaddr += tx_ring_size;
1293 paddr += tx_ring_size;
1294 }
1295
1296 for (i = 0; i < ha->hw.num_tx_rings; i++) {
1297 tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
1298
1299 tx_cntxt->tx_cons = (uint32_t *)vaddr;
1300 tx_cntxt->tx_cons_paddr = paddr;
1301
1302 vaddr += sizeof (uint32_t);
1303 paddr += sizeof (uint32_t);
1304 }
1305
1306 ha->hw.dma_buf.flags.tx_ring = 1;
1307
1308 QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n",
1309 __func__, (void *)(hw->dma_buf.tx_ring.dma_addr),
1310 hw->dma_buf.tx_ring.dma_b));
1311 /*
1312 * Allocate Receive Descriptor Rings
1313 */
1314
1315 for (i = 0; i < hw->num_rds_rings; i++) {
1316 hw->dma_buf.rds_ring[i].alignment = 8;
1317 hw->dma_buf.rds_ring[i].size =
1318 (sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS;
1319
1320 if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) {
1321 device_printf(dev, "%s: rds ring[%d] alloc failed\n",
1322 __func__, i);
1323
1324 for (j = 0; j < i; j++)
1325 ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]);
1326
1327 goto ql_alloc_dma_exit;
1328 }
1329 QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n",
1330 __func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr),
1331 hw->dma_buf.rds_ring[i].dma_b));
1332 }
1333
1334 hw->dma_buf.flags.rds_ring = 1;
1335
1336 /*
1337 * Allocate Status Descriptor Rings
1338 */
1339
1340 for (i = 0; i < hw->num_sds_rings; i++) {
1341 hw->dma_buf.sds_ring[i].alignment = 8;
1342 hw->dma_buf.sds_ring[i].size =
1343 (sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS;
1344
1345 if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) {
1346 device_printf(dev, "%s: sds ring alloc failed\n",
1347 __func__);
1348
1349 for (j = 0; j < i; j++)
1350 ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]);
1351
1352 goto ql_alloc_dma_exit;
1353 }
1354 QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n",
1355 __func__, i,
1356 (void *)(hw->dma_buf.sds_ring[i].dma_addr),
1357 hw->dma_buf.sds_ring[i].dma_b));
1358 }
1359 for (i = 0; i < hw->num_sds_rings; i++) {
1360 hw->sds[i].sds_ring_base =
1361 (q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b;
1362 }
1363
1364 hw->dma_buf.flags.sds_ring = 1;
1365
1366 return 0;
1367
1368 ql_alloc_dma_exit:
1369 ql_free_dma(ha);
1370 return -1;
1371 }
1372
1373 #define Q8_MBX_MSEC_DELAY 5000
1374
1375 static int
qla_mbx_cmd(qla_host_t * ha,uint32_t * h_mbox,uint32_t n_hmbox,uint32_t * fw_mbox,uint32_t n_fwmbox,uint32_t no_pause)1376 qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
1377 uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause)
1378 {
1379 uint32_t i;
1380 uint32_t data;
1381 int ret = 0;
1382 uint64_t start_usecs;
1383 uint64_t end_usecs;
1384 uint64_t msecs_200;
1385
1386 ql_sp_log(ha, 0, 5, no_pause, h_mbox[0], h_mbox[1], h_mbox[2], h_mbox[3]);
1387
1388 if (ha->offline || ha->qla_initiate_recovery) {
1389 ql_sp_log(ha, 1, 2, ha->offline, ha->qla_initiate_recovery, 0, 0, 0);
1390 goto exit_qla_mbx_cmd;
1391 }
1392
1393 if (((ha->err_inject & 0xFFFF) == INJCT_MBX_CMD_FAILURE) &&
1394 (((ha->err_inject & ~0xFFFF) == ((h_mbox[0] & 0xFFFF) << 16))||
1395 !(ha->err_inject & ~0xFFFF))) {
1396 ret = -3;
1397 QL_INITIATE_RECOVERY(ha);
1398 goto exit_qla_mbx_cmd;
1399 }
1400
1401 start_usecs = qla_get_usec_timestamp();
1402
1403 if (no_pause)
1404 i = 1000;
1405 else
1406 i = Q8_MBX_MSEC_DELAY;
1407
1408 while (i) {
1409 if (ha->qla_initiate_recovery) {
1410 ql_sp_log(ha, 2, 1, ha->qla_initiate_recovery, 0, 0, 0, 0);
1411 return (-1);
1412 }
1413
1414 data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL);
1415 if (data == 0)
1416 break;
1417 if (no_pause) {
1418 DELAY(1000);
1419 } else {
1420 qla_mdelay(__func__, 1);
1421 }
1422 i--;
1423 }
1424
1425 if (i == 0) {
1426 device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n",
1427 __func__, data);
1428 ql_sp_log(ha, 3, 1, data, 0, 0, 0, 0);
1429 ret = -1;
1430 ha->hw.mbx_comp_msecs[(Q8_MBX_COMP_MSECS - 2)]++;
1431 QL_INITIATE_RECOVERY(ha);
1432 goto exit_qla_mbx_cmd;
1433 }
1434
1435 for (i = 0; i < n_hmbox; i++) {
1436 WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox);
1437 h_mbox++;
1438 }
1439
1440 WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1);
1441
1442 i = Q8_MBX_MSEC_DELAY;
1443 while (i) {
1444 if (ha->qla_initiate_recovery) {
1445 ql_sp_log(ha, 4, 1, ha->qla_initiate_recovery, 0, 0, 0, 0);
1446 return (-1);
1447 }
1448
1449 data = READ_REG32(ha, Q8_FW_MBOX_CNTRL);
1450
1451 if ((data & 0x3) == 1) {
1452 data = READ_REG32(ha, Q8_FW_MBOX0);
1453 if ((data & 0xF000) != 0x8000)
1454 break;
1455 }
1456 if (no_pause) {
1457 DELAY(1000);
1458 } else {
1459 qla_mdelay(__func__, 1);
1460 }
1461 i--;
1462 }
1463 if (i == 0) {
1464 device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n",
1465 __func__, data);
1466 ql_sp_log(ha, 5, 1, data, 0, 0, 0, 0);
1467 ret = -2;
1468 ha->hw.mbx_comp_msecs[(Q8_MBX_COMP_MSECS - 1)]++;
1469 QL_INITIATE_RECOVERY(ha);
1470 goto exit_qla_mbx_cmd;
1471 }
1472
1473 for (i = 0; i < n_fwmbox; i++) {
1474 if (ha->qla_initiate_recovery) {
1475 ql_sp_log(ha, 6, 1, ha->qla_initiate_recovery, 0, 0, 0, 0);
1476 return (-1);
1477 }
1478
1479 *fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2)));
1480 }
1481
1482 WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0);
1483 WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
1484
1485 end_usecs = qla_get_usec_timestamp();
1486
1487 if (end_usecs > start_usecs) {
1488 msecs_200 = (end_usecs - start_usecs)/(1000 * 200);
1489
1490 if (msecs_200 < 15)
1491 ha->hw.mbx_comp_msecs[msecs_200]++;
1492 else if (msecs_200 < 20)
1493 ha->hw.mbx_comp_msecs[15]++;
1494 else {
1495 device_printf(ha->pci_dev, "%s: [%ld, %ld] %ld\n", __func__,
1496 start_usecs, end_usecs, msecs_200);
1497 ha->hw.mbx_comp_msecs[16]++;
1498 }
1499 }
1500 ql_sp_log(ha, 7, 5, fw_mbox[0], fw_mbox[1], fw_mbox[2], fw_mbox[3], fw_mbox[4]);
1501
1502 exit_qla_mbx_cmd:
1503 return (ret);
1504 }
1505
1506 int
qla_get_nic_partition(qla_host_t * ha,uint32_t * supports_9kb,uint32_t * num_rcvq)1507 qla_get_nic_partition(qla_host_t *ha, uint32_t *supports_9kb,
1508 uint32_t *num_rcvq)
1509 {
1510 uint32_t *mbox, err;
1511 device_t dev = ha->pci_dev;
1512
1513 bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX));
1514
1515 mbox = ha->hw.mbox;
1516
1517 mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29);
1518
1519 if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) {
1520 device_printf(dev, "%s: failed0\n", __func__);
1521 return (-1);
1522 }
1523 err = mbox[0] >> 25;
1524
1525 if (supports_9kb != NULL) {
1526 if (mbox[16] & 0x80) /* bit 7 of mbox 16 */
1527 *supports_9kb = 1;
1528 else
1529 *supports_9kb = 0;
1530 }
1531
1532 if (num_rcvq != NULL)
1533 *num_rcvq = ((mbox[6] >> 16) & 0xFFFF);
1534
1535 if ((err != 1) && (err != 0)) {
1536 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1537 return (-1);
1538 }
1539 return 0;
1540 }
1541
1542 static int
qla_config_intr_cntxt(qla_host_t * ha,uint32_t start_idx,uint32_t num_intrs,uint32_t create)1543 qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, uint32_t num_intrs,
1544 uint32_t create)
1545 {
1546 uint32_t i, err;
1547 device_t dev = ha->pci_dev;
1548 q80_config_intr_t *c_intr;
1549 q80_config_intr_rsp_t *c_intr_rsp;
1550
1551 c_intr = (q80_config_intr_t *)ha->hw.mbox;
1552 bzero(c_intr, (sizeof (q80_config_intr_t)));
1553
1554 c_intr->opcode = Q8_MBX_CONFIG_INTR;
1555
1556 c_intr->count_version = (sizeof (q80_config_intr_t) >> 2);
1557 c_intr->count_version |= Q8_MBX_CMD_VERSION;
1558
1559 c_intr->nentries = num_intrs;
1560
1561 for (i = 0; i < num_intrs; i++) {
1562 if (create) {
1563 c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE;
1564 c_intr->intr[i].msix_index = start_idx + 1 + i;
1565 } else {
1566 c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE;
1567 c_intr->intr[i].msix_index =
1568 ha->hw.intr_id[(start_idx + i)];
1569 }
1570
1571 c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X;
1572 }
1573
1574 if (qla_mbx_cmd(ha, (uint32_t *)c_intr,
1575 (sizeof (q80_config_intr_t) >> 2),
1576 ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) {
1577 device_printf(dev, "%s: %s failed0\n", __func__,
1578 (create ? "create" : "delete"));
1579 return (-1);
1580 }
1581
1582 c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox;
1583
1584 err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status);
1585
1586 if (err) {
1587 device_printf(dev, "%s: %s failed1 [0x%08x, %d]\n", __func__,
1588 (create ? "create" : "delete"), err, c_intr_rsp->nentries);
1589
1590 for (i = 0; i < c_intr_rsp->nentries; i++) {
1591 device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n",
1592 __func__, i,
1593 c_intr_rsp->intr[i].status,
1594 c_intr_rsp->intr[i].intr_id,
1595 c_intr_rsp->intr[i].intr_src);
1596 }
1597
1598 return (-1);
1599 }
1600
1601 for (i = 0; ((i < num_intrs) && create); i++) {
1602 if (!c_intr_rsp->intr[i].status) {
1603 ha->hw.intr_id[(start_idx + i)] =
1604 c_intr_rsp->intr[i].intr_id;
1605 ha->hw.intr_src[(start_idx + i)] =
1606 c_intr_rsp->intr[i].intr_src;
1607 }
1608 }
1609
1610 return (0);
1611 }
1612
1613 /*
1614 * Name: qla_config_rss
1615 * Function: Configure RSS for the context/interface.
1616 */
1617 static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL,
1618 0x8030f20c77cb2da3ULL,
1619 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
1620 0x255b0ec26d5a56daULL };
1621
1622 static int
qla_config_rss(qla_host_t * ha,uint16_t cntxt_id)1623 qla_config_rss(qla_host_t *ha, uint16_t cntxt_id)
1624 {
1625 q80_config_rss_t *c_rss;
1626 q80_config_rss_rsp_t *c_rss_rsp;
1627 uint32_t err, i;
1628 device_t dev = ha->pci_dev;
1629
1630 c_rss = (q80_config_rss_t *)ha->hw.mbox;
1631 bzero(c_rss, (sizeof (q80_config_rss_t)));
1632
1633 c_rss->opcode = Q8_MBX_CONFIG_RSS;
1634
1635 c_rss->count_version = (sizeof (q80_config_rss_t) >> 2);
1636 c_rss->count_version |= Q8_MBX_CMD_VERSION;
1637
1638 c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP |
1639 Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP);
1640 //c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP |
1641 // Q8_MBX_RSS_HASH_TYPE_IPV6_TCP);
1642
1643 c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS;
1644 c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE;
1645
1646 c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK;
1647
1648 c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID;
1649 c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS;
1650
1651 c_rss->cntxt_id = cntxt_id;
1652
1653 for (i = 0; i < 5; i++) {
1654 c_rss->rss_key[i] = rss_key[i];
1655 }
1656
1657 if (qla_mbx_cmd(ha, (uint32_t *)c_rss,
1658 (sizeof (q80_config_rss_t) >> 2),
1659 ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) {
1660 device_printf(dev, "%s: failed0\n", __func__);
1661 return (-1);
1662 }
1663 c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox;
1664
1665 err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status);
1666
1667 if (err) {
1668 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1669 return (-1);
1670 }
1671 return 0;
1672 }
1673
1674 static int
qla_set_rss_ind_table(qla_host_t * ha,uint32_t start_idx,uint32_t count,uint16_t cntxt_id,uint8_t * ind_table)1675 qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count,
1676 uint16_t cntxt_id, uint8_t *ind_table)
1677 {
1678 q80_config_rss_ind_table_t *c_rss_ind;
1679 q80_config_rss_ind_table_rsp_t *c_rss_ind_rsp;
1680 uint32_t err;
1681 device_t dev = ha->pci_dev;
1682
1683 if ((count > Q8_RSS_IND_TBL_SIZE) ||
1684 ((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) {
1685 device_printf(dev, "%s: illegal count [%d, %d]\n", __func__,
1686 start_idx, count);
1687 return (-1);
1688 }
1689
1690 c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox;
1691 bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t));
1692
1693 c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE;
1694 c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2);
1695 c_rss_ind->count_version |= Q8_MBX_CMD_VERSION;
1696
1697 c_rss_ind->start_idx = start_idx;
1698 c_rss_ind->end_idx = start_idx + count - 1;
1699 c_rss_ind->cntxt_id = cntxt_id;
1700 bcopy(ind_table, c_rss_ind->ind_table, count);
1701
1702 if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind,
1703 (sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox,
1704 (sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) {
1705 device_printf(dev, "%s: failed0\n", __func__);
1706 return (-1);
1707 }
1708
1709 c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox;
1710 err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status);
1711
1712 if (err) {
1713 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1714 return (-1);
1715 }
1716 return 0;
1717 }
1718
1719 /*
1720 * Name: qla_config_intr_coalesce
1721 * Function: Configure Interrupt Coalescing.
1722 */
1723 static int
qla_config_intr_coalesce(qla_host_t * ha,uint16_t cntxt_id,int tenable,int rcv)1724 qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable,
1725 int rcv)
1726 {
1727 q80_config_intr_coalesc_t *intrc;
1728 q80_config_intr_coalesc_rsp_t *intrc_rsp;
1729 uint32_t err, i;
1730 device_t dev = ha->pci_dev;
1731
1732 intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox;
1733 bzero(intrc, (sizeof (q80_config_intr_coalesc_t)));
1734
1735 intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE;
1736 intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2);
1737 intrc->count_version |= Q8_MBX_CMD_VERSION;
1738
1739 if (rcv) {
1740 intrc->flags = Q8_MBX_INTRC_FLAGS_RCV;
1741 intrc->max_pkts = ha->hw.rcv_intr_coalesce & 0xFFFF;
1742 intrc->max_mswait = (ha->hw.rcv_intr_coalesce >> 16) & 0xFFFF;
1743 } else {
1744 intrc->flags = Q8_MBX_INTRC_FLAGS_XMT;
1745 intrc->max_pkts = ha->hw.xmt_intr_coalesce & 0xFFFF;
1746 intrc->max_mswait = (ha->hw.xmt_intr_coalesce >> 16) & 0xFFFF;
1747 }
1748
1749 intrc->cntxt_id = cntxt_id;
1750
1751 if (tenable) {
1752 intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC;
1753 intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC;
1754
1755 for (i = 0; i < ha->hw.num_sds_rings; i++) {
1756 intrc->sds_ring_mask |= (1 << i);
1757 }
1758 intrc->ms_timeout = 1000;
1759 }
1760
1761 if (qla_mbx_cmd(ha, (uint32_t *)intrc,
1762 (sizeof (q80_config_intr_coalesc_t) >> 2),
1763 ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) {
1764 device_printf(dev, "%s: failed0\n", __func__);
1765 return (-1);
1766 }
1767 intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox;
1768
1769 err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status);
1770
1771 if (err) {
1772 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1773 return (-1);
1774 }
1775
1776 return 0;
1777 }
1778
1779 /*
1780 * Name: qla_config_mac_addr
1781 * Function: binds a MAC address to the context/interface.
1782 * Can be unicast, multicast or broadcast.
1783 */
1784 static int
qla_config_mac_addr(qla_host_t * ha,uint8_t * mac_addr,uint32_t add_mac,uint32_t num_mac)1785 qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac,
1786 uint32_t num_mac)
1787 {
1788 q80_config_mac_addr_t *cmac;
1789 q80_config_mac_addr_rsp_t *cmac_rsp;
1790 uint32_t err;
1791 device_t dev = ha->pci_dev;
1792 int i;
1793 uint8_t *mac_cpy = mac_addr;
1794
1795 if (num_mac > Q8_MAX_MAC_ADDRS) {
1796 device_printf(dev, "%s: %s num_mac [0x%x] > Q8_MAX_MAC_ADDRS\n",
1797 __func__, (add_mac ? "Add" : "Del"), num_mac);
1798 return (-1);
1799 }
1800
1801 cmac = (q80_config_mac_addr_t *)ha->hw.mbox;
1802 bzero(cmac, (sizeof (q80_config_mac_addr_t)));
1803
1804 cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR;
1805 cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2;
1806 cmac->count_version |= Q8_MBX_CMD_VERSION;
1807
1808 if (add_mac)
1809 cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR;
1810 else
1811 cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR;
1812
1813 cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS;
1814
1815 cmac->nmac_entries = num_mac;
1816 cmac->cntxt_id = ha->hw.rcv_cntxt_id;
1817
1818 for (i = 0; i < num_mac; i++) {
1819 bcopy(mac_addr, cmac->mac_addr[i].addr, Q8_ETHER_ADDR_LEN);
1820 mac_addr = mac_addr + ETHER_ADDR_LEN;
1821 }
1822
1823 if (qla_mbx_cmd(ha, (uint32_t *)cmac,
1824 (sizeof (q80_config_mac_addr_t) >> 2),
1825 ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) {
1826 device_printf(dev, "%s: %s failed0\n", __func__,
1827 (add_mac ? "Add" : "Del"));
1828 return (-1);
1829 }
1830 cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox;
1831
1832 err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status);
1833
1834 if (err) {
1835 device_printf(dev, "%s: %s failed1 [0x%08x]\n", __func__,
1836 (add_mac ? "Add" : "Del"), err);
1837 for (i = 0; i < num_mac; i++) {
1838 device_printf(dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
1839 __func__, mac_cpy[0], mac_cpy[1], mac_cpy[2],
1840 mac_cpy[3], mac_cpy[4], mac_cpy[5]);
1841 mac_cpy += ETHER_ADDR_LEN;
1842 }
1843 return (-1);
1844 }
1845
1846 return 0;
1847 }
1848
1849 /*
1850 * Name: qla_set_mac_rcv_mode
1851 * Function: Enable/Disable AllMulticast and Promiscous Modes.
1852 */
1853 static int
qla_set_mac_rcv_mode(qla_host_t * ha,uint32_t mode)1854 qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode)
1855 {
1856 q80_config_mac_rcv_mode_t *rcv_mode;
1857 uint32_t err;
1858 q80_config_mac_rcv_mode_rsp_t *rcv_mode_rsp;
1859 device_t dev = ha->pci_dev;
1860
1861 rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox;
1862 bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t)));
1863
1864 rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE;
1865 rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2;
1866 rcv_mode->count_version |= Q8_MBX_CMD_VERSION;
1867
1868 rcv_mode->mode = mode;
1869
1870 rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id;
1871
1872 if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode,
1873 (sizeof (q80_config_mac_rcv_mode_t) >> 2),
1874 ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) {
1875 device_printf(dev, "%s: failed0\n", __func__);
1876 return (-1);
1877 }
1878 rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox;
1879
1880 err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status);
1881
1882 if (err) {
1883 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1884 return (-1);
1885 }
1886
1887 return 0;
1888 }
1889
1890 int
ql_set_promisc(qla_host_t * ha)1891 ql_set_promisc(qla_host_t *ha)
1892 {
1893 int ret;
1894
1895 ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1896 ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1897 return (ret);
1898 }
1899
1900 void
qla_reset_promisc(qla_host_t * ha)1901 qla_reset_promisc(qla_host_t *ha)
1902 {
1903 ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1904 (void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1905 }
1906
1907 int
ql_set_allmulti(qla_host_t * ha)1908 ql_set_allmulti(qla_host_t *ha)
1909 {
1910 int ret;
1911
1912 ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE;
1913 ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1914 return (ret);
1915 }
1916
1917 void
qla_reset_allmulti(qla_host_t * ha)1918 qla_reset_allmulti(qla_host_t *ha)
1919 {
1920 ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE;
1921 (void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1922 }
1923
1924 /*
1925 * Name: ql_set_max_mtu
1926 * Function:
1927 * Sets the maximum transfer unit size for the specified rcv context.
1928 */
1929 int
ql_set_max_mtu(qla_host_t * ha,uint32_t mtu,uint16_t cntxt_id)1930 ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id)
1931 {
1932 device_t dev;
1933 q80_set_max_mtu_t *max_mtu;
1934 q80_set_max_mtu_rsp_t *max_mtu_rsp;
1935 uint32_t err;
1936
1937 dev = ha->pci_dev;
1938
1939 max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox;
1940 bzero(max_mtu, (sizeof (q80_set_max_mtu_t)));
1941
1942 max_mtu->opcode = Q8_MBX_SET_MAX_MTU;
1943 max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2);
1944 max_mtu->count_version |= Q8_MBX_CMD_VERSION;
1945
1946 max_mtu->cntxt_id = cntxt_id;
1947 max_mtu->mtu = mtu;
1948
1949 if (qla_mbx_cmd(ha, (uint32_t *)max_mtu,
1950 (sizeof (q80_set_max_mtu_t) >> 2),
1951 ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) {
1952 device_printf(dev, "%s: failed\n", __func__);
1953 return -1;
1954 }
1955
1956 max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox;
1957
1958 err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status);
1959
1960 if (err) {
1961 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1962 }
1963
1964 return 0;
1965 }
1966
1967 static int
qla_link_event_req(qla_host_t * ha,uint16_t cntxt_id)1968 qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id)
1969 {
1970 device_t dev;
1971 q80_link_event_t *lnk;
1972 q80_link_event_rsp_t *lnk_rsp;
1973 uint32_t err;
1974
1975 dev = ha->pci_dev;
1976
1977 lnk = (q80_link_event_t *)ha->hw.mbox;
1978 bzero(lnk, (sizeof (q80_link_event_t)));
1979
1980 lnk->opcode = Q8_MBX_LINK_EVENT_REQ;
1981 lnk->count_version = (sizeof (q80_link_event_t) >> 2);
1982 lnk->count_version |= Q8_MBX_CMD_VERSION;
1983
1984 lnk->cntxt_id = cntxt_id;
1985 lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC;
1986
1987 if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2),
1988 ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) {
1989 device_printf(dev, "%s: failed\n", __func__);
1990 return -1;
1991 }
1992
1993 lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox;
1994
1995 err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status);
1996
1997 if (err) {
1998 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1999 }
2000
2001 return 0;
2002 }
2003
2004 static int
qla_config_fw_lro(qla_host_t * ha,uint16_t cntxt_id)2005 qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id)
2006 {
2007 device_t dev;
2008 q80_config_fw_lro_t *fw_lro;
2009 q80_config_fw_lro_rsp_t *fw_lro_rsp;
2010 uint32_t err;
2011
2012 dev = ha->pci_dev;
2013
2014 fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox;
2015 bzero(fw_lro, sizeof(q80_config_fw_lro_t));
2016
2017 fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO;
2018 fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2);
2019 fw_lro->count_version |= Q8_MBX_CMD_VERSION;
2020
2021 fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK;
2022 fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK;
2023
2024 fw_lro->cntxt_id = cntxt_id;
2025
2026 if (qla_mbx_cmd(ha, (uint32_t *)fw_lro,
2027 (sizeof (q80_config_fw_lro_t) >> 2),
2028 ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) {
2029 device_printf(dev, "%s: failed\n", __func__);
2030 return -1;
2031 }
2032
2033 fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox;
2034
2035 err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status);
2036
2037 if (err) {
2038 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
2039 }
2040
2041 return 0;
2042 }
2043
2044 static int
qla_set_cam_search_mode(qla_host_t * ha,uint32_t search_mode)2045 qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode)
2046 {
2047 device_t dev;
2048 q80_hw_config_t *hw_config;
2049 q80_hw_config_rsp_t *hw_config_rsp;
2050 uint32_t err;
2051
2052 dev = ha->pci_dev;
2053
2054 hw_config = (q80_hw_config_t *)ha->hw.mbox;
2055 bzero(hw_config, sizeof (q80_hw_config_t));
2056
2057 hw_config->opcode = Q8_MBX_HW_CONFIG;
2058 hw_config->count_version = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE_COUNT;
2059 hw_config->count_version |= Q8_MBX_CMD_VERSION;
2060
2061 hw_config->cmd = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE;
2062
2063 hw_config->u.set_cam_search_mode.mode = search_mode;
2064
2065 if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
2066 (sizeof (q80_hw_config_t) >> 2),
2067 ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
2068 device_printf(dev, "%s: failed\n", __func__);
2069 return -1;
2070 }
2071 hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
2072
2073 err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
2074
2075 if (err) {
2076 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
2077 }
2078
2079 return 0;
2080 }
2081
2082 static int
qla_get_cam_search_mode(qla_host_t * ha)2083 qla_get_cam_search_mode(qla_host_t *ha)
2084 {
2085 device_t dev;
2086 q80_hw_config_t *hw_config;
2087 q80_hw_config_rsp_t *hw_config_rsp;
2088 uint32_t err;
2089
2090 dev = ha->pci_dev;
2091
2092 hw_config = (q80_hw_config_t *)ha->hw.mbox;
2093 bzero(hw_config, sizeof (q80_hw_config_t));
2094
2095 hw_config->opcode = Q8_MBX_HW_CONFIG;
2096 hw_config->count_version = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE_COUNT;
2097 hw_config->count_version |= Q8_MBX_CMD_VERSION;
2098
2099 hw_config->cmd = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE;
2100
2101 if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
2102 (sizeof (q80_hw_config_t) >> 2),
2103 ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
2104 device_printf(dev, "%s: failed\n", __func__);
2105 return -1;
2106 }
2107 hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
2108
2109 err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
2110
2111 if (err) {
2112 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
2113 } else {
2114 device_printf(dev, "%s: cam search mode [0x%08x]\n", __func__,
2115 hw_config_rsp->u.get_cam_search_mode.mode);
2116 }
2117
2118 return 0;
2119 }
2120
2121 static int
qla_get_hw_stats(qla_host_t * ha,uint32_t cmd,uint32_t rsp_size)2122 qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size)
2123 {
2124 device_t dev;
2125 q80_get_stats_t *stat;
2126 q80_get_stats_rsp_t *stat_rsp;
2127 uint32_t err;
2128
2129 dev = ha->pci_dev;
2130
2131 stat = (q80_get_stats_t *)ha->hw.mbox;
2132 bzero(stat, (sizeof (q80_get_stats_t)));
2133
2134 stat->opcode = Q8_MBX_GET_STATS;
2135 stat->count_version = 2;
2136 stat->count_version |= Q8_MBX_CMD_VERSION;
2137
2138 stat->cmd = cmd;
2139
2140 if (qla_mbx_cmd(ha, (uint32_t *)stat, 2,
2141 ha->hw.mbox, (rsp_size >> 2), 0)) {
2142 device_printf(dev, "%s: failed\n", __func__);
2143 return -1;
2144 }
2145
2146 stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
2147
2148 err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status);
2149
2150 if (err) {
2151 return -1;
2152 }
2153
2154 return 0;
2155 }
2156
2157 void
ql_get_stats(qla_host_t * ha)2158 ql_get_stats(qla_host_t *ha)
2159 {
2160 q80_get_stats_rsp_t *stat_rsp;
2161 q80_mac_stats_t *mstat;
2162 q80_xmt_stats_t *xstat;
2163 q80_rcv_stats_t *rstat;
2164 uint32_t cmd;
2165 int i;
2166 struct ifnet *ifp = ha->ifp;
2167
2168 if (ifp == NULL)
2169 return;
2170
2171 if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) != 0) {
2172 device_printf(ha->pci_dev, "%s: failed\n", __func__);
2173 return;
2174 }
2175
2176 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
2177 QLA_UNLOCK(ha, __func__);
2178 return;
2179 }
2180
2181 stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
2182 /*
2183 * Get MAC Statistics
2184 */
2185 cmd = Q8_GET_STATS_CMD_TYPE_MAC;
2186 // cmd |= Q8_GET_STATS_CMD_CLEAR;
2187
2188 cmd |= ((ha->pci_func & 0x1) << 16);
2189
2190 if (ha->qla_watchdog_pause || (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
2191 ha->offline)
2192 goto ql_get_stats_exit;
2193
2194 if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
2195 mstat = (q80_mac_stats_t *)&stat_rsp->u.mac;
2196 bcopy(mstat, &ha->hw.mac, sizeof(q80_mac_stats_t));
2197 } else {
2198 device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n",
2199 __func__, ha->hw.mbox[0]);
2200 }
2201 /*
2202 * Get RCV Statistics
2203 */
2204 cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT;
2205 // cmd |= Q8_GET_STATS_CMD_CLEAR;
2206 cmd |= (ha->hw.rcv_cntxt_id << 16);
2207
2208 if (ha->qla_watchdog_pause || (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
2209 ha->offline)
2210 goto ql_get_stats_exit;
2211
2212 if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
2213 rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv;
2214 bcopy(rstat, &ha->hw.rcv, sizeof(q80_rcv_stats_t));
2215 } else {
2216 device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n",
2217 __func__, ha->hw.mbox[0]);
2218 }
2219
2220 if (ha->qla_watchdog_pause || (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
2221 ha->offline)
2222 goto ql_get_stats_exit;
2223 /*
2224 * Get XMT Statistics
2225 */
2226 for (i = 0 ; (i < ha->hw.num_tx_rings); i++) {
2227 if (ha->qla_watchdog_pause ||
2228 (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
2229 ha->offline)
2230 goto ql_get_stats_exit;
2231
2232 cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT;
2233 // cmd |= Q8_GET_STATS_CMD_CLEAR;
2234 cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16);
2235
2236 if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t))
2237 == 0) {
2238 xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt;
2239 bcopy(xstat, &ha->hw.xmt[i], sizeof(q80_xmt_stats_t));
2240 } else {
2241 device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n",
2242 __func__, ha->hw.mbox[0]);
2243 }
2244 }
2245
2246 ql_get_stats_exit:
2247 QLA_UNLOCK(ha, __func__);
2248
2249 return;
2250 }
2251
2252 /*
2253 * Name: qla_tx_tso
2254 * Function: Checks if the packet to be transmitted is a candidate for
2255 * Large TCP Segment Offload. If yes, the appropriate fields in the Tx
2256 * Ring Structure are plugged in.
2257 */
2258 static int
qla_tx_tso(qla_host_t * ha,struct mbuf * mp,q80_tx_cmd_t * tx_cmd,uint8_t * hdr)2259 qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
2260 {
2261 struct ether_vlan_header *eh;
2262 struct ip *ip = NULL;
2263 struct ip6_hdr *ip6 = NULL;
2264 struct tcphdr *th = NULL;
2265 uint32_t ehdrlen, hdrlen, ip_hlen, tcp_hlen, tcp_opt_off;
2266 uint16_t etype, opcode, offload = 1;
2267 device_t dev;
2268
2269 dev = ha->pci_dev;
2270
2271 eh = mtod(mp, struct ether_vlan_header *);
2272
2273 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2274 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
2275 etype = ntohs(eh->evl_proto);
2276 } else {
2277 ehdrlen = ETHER_HDR_LEN;
2278 etype = ntohs(eh->evl_encap_proto);
2279 }
2280
2281 hdrlen = 0;
2282
2283 switch (etype) {
2284 case ETHERTYPE_IP:
2285
2286 tcp_opt_off = ehdrlen + sizeof(struct ip) +
2287 sizeof(struct tcphdr);
2288
2289 if (mp->m_len < tcp_opt_off) {
2290 m_copydata(mp, 0, tcp_opt_off, hdr);
2291 ip = (struct ip *)(hdr + ehdrlen);
2292 } else {
2293 ip = (struct ip *)(mp->m_data + ehdrlen);
2294 }
2295
2296 ip_hlen = ip->ip_hl << 2;
2297 opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
2298
2299
2300 if ((ip->ip_p != IPPROTO_TCP) ||
2301 (ip_hlen != sizeof (struct ip))){
2302 /* IP Options are not supported */
2303
2304 offload = 0;
2305 } else
2306 th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
2307
2308 break;
2309
2310 case ETHERTYPE_IPV6:
2311
2312 tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) +
2313 sizeof (struct tcphdr);
2314
2315 if (mp->m_len < tcp_opt_off) {
2316 m_copydata(mp, 0, tcp_opt_off, hdr);
2317 ip6 = (struct ip6_hdr *)(hdr + ehdrlen);
2318 } else {
2319 ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
2320 }
2321
2322 ip_hlen = sizeof(struct ip6_hdr);
2323 opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6;
2324
2325 if (ip6->ip6_nxt != IPPROTO_TCP) {
2326 //device_printf(dev, "%s: ipv6\n", __func__);
2327 offload = 0;
2328 } else
2329 th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
2330 break;
2331
2332 default:
2333 QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__));
2334 offload = 0;
2335 break;
2336 }
2337
2338 if (!offload)
2339 return (-1);
2340
2341 tcp_hlen = th->th_off << 2;
2342 hdrlen = ehdrlen + ip_hlen + tcp_hlen;
2343
2344 if (mp->m_len < hdrlen) {
2345 if (mp->m_len < tcp_opt_off) {
2346 if (tcp_hlen > sizeof(struct tcphdr)) {
2347 m_copydata(mp, tcp_opt_off,
2348 (tcp_hlen - sizeof(struct tcphdr)),
2349 &hdr[tcp_opt_off]);
2350 }
2351 } else {
2352 m_copydata(mp, 0, hdrlen, hdr);
2353 }
2354 }
2355
2356 tx_cmd->mss = mp->m_pkthdr.tso_segsz;
2357
2358 tx_cmd->flags_opcode = opcode ;
2359 tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen;
2360 tx_cmd->total_hdr_len = hdrlen;
2361
2362 /* Check for Multicast least significant bit of MSB == 1 */
2363 if (eh->evl_dhost[0] & 0x01) {
2364 tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST;
2365 }
2366
2367 if (mp->m_len < hdrlen) {
2368 printf("%d\n", hdrlen);
2369 return (1);
2370 }
2371
2372 return (0);
2373 }
2374
2375 /*
2376 * Name: qla_tx_chksum
2377 * Function: Checks if the packet to be transmitted is a candidate for
2378 * TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx
2379 * Ring Structure are plugged in.
2380 */
2381 static int
qla_tx_chksum(qla_host_t * ha,struct mbuf * mp,uint32_t * op_code,uint32_t * tcp_hdr_off)2382 qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code,
2383 uint32_t *tcp_hdr_off)
2384 {
2385 struct ether_vlan_header *eh;
2386 struct ip *ip;
2387 struct ip6_hdr *ip6;
2388 uint32_t ehdrlen, ip_hlen;
2389 uint16_t etype, opcode, offload = 1;
2390 device_t dev;
2391 uint8_t buf[sizeof(struct ip6_hdr)];
2392
2393 dev = ha->pci_dev;
2394
2395 *op_code = 0;
2396
2397 if ((mp->m_pkthdr.csum_flags &
2398 (CSUM_TCP|CSUM_UDP|CSUM_TCP_IPV6 | CSUM_UDP_IPV6)) == 0)
2399 return (-1);
2400
2401 eh = mtod(mp, struct ether_vlan_header *);
2402
2403 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2404 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
2405 etype = ntohs(eh->evl_proto);
2406 } else {
2407 ehdrlen = ETHER_HDR_LEN;
2408 etype = ntohs(eh->evl_encap_proto);
2409 }
2410
2411
2412 switch (etype) {
2413 case ETHERTYPE_IP:
2414 ip = (struct ip *)(mp->m_data + ehdrlen);
2415
2416 ip_hlen = sizeof (struct ip);
2417
2418 if (mp->m_len < (ehdrlen + ip_hlen)) {
2419 m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
2420 ip = (struct ip *)buf;
2421 }
2422
2423 if (ip->ip_p == IPPROTO_TCP)
2424 opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM;
2425 else if (ip->ip_p == IPPROTO_UDP)
2426 opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM;
2427 else {
2428 //device_printf(dev, "%s: ipv4\n", __func__);
2429 offload = 0;
2430 }
2431 break;
2432
2433 case ETHERTYPE_IPV6:
2434 ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
2435
2436 ip_hlen = sizeof(struct ip6_hdr);
2437
2438 if (mp->m_len < (ehdrlen + ip_hlen)) {
2439 m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
2440 buf);
2441 ip6 = (struct ip6_hdr *)buf;
2442 }
2443
2444 if (ip6->ip6_nxt == IPPROTO_TCP)
2445 opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6;
2446 else if (ip6->ip6_nxt == IPPROTO_UDP)
2447 opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6;
2448 else {
2449 //device_printf(dev, "%s: ipv6\n", __func__);
2450 offload = 0;
2451 }
2452 break;
2453
2454 default:
2455 offload = 0;
2456 break;
2457 }
2458 if (!offload)
2459 return (-1);
2460
2461 *op_code = opcode;
2462 *tcp_hdr_off = (ip_hlen + ehdrlen);
2463
2464 return (0);
2465 }
2466
2467 #define QLA_TX_MIN_FREE 2
2468 /*
2469 * Name: ql_hw_send
2470 * Function: Transmits a packet. It first checks if the packet is a
2471 * candidate for Large TCP Segment Offload and then for UDP/TCP checksum
2472 * offload. If either of these creteria are not met, it is transmitted
2473 * as a regular ethernet frame.
2474 */
2475 int
ql_hw_send(qla_host_t * ha,bus_dma_segment_t * segs,int nsegs,uint32_t tx_idx,struct mbuf * mp,uint32_t txr_idx,uint32_t iscsi_pdu)2476 ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
2477 uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu)
2478 {
2479 struct ether_vlan_header *eh;
2480 qla_hw_t *hw = &ha->hw;
2481 q80_tx_cmd_t *tx_cmd, tso_cmd;
2482 bus_dma_segment_t *c_seg;
2483 uint32_t num_tx_cmds, hdr_len = 0;
2484 uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next;
2485 device_t dev;
2486 int i, ret;
2487 uint8_t *src = NULL, *dst = NULL;
2488 uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
2489 uint32_t op_code = 0;
2490 uint32_t tcp_hdr_off = 0;
2491
2492 dev = ha->pci_dev;
2493
2494 /*
2495 * Always make sure there is atleast one empty slot in the tx_ring
2496 * tx_ring is considered full when there only one entry available
2497 */
2498 num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2;
2499
2500 total_length = mp->m_pkthdr.len;
2501 if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
2502 device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
2503 __func__, total_length);
2504 return (EINVAL);
2505 }
2506 eh = mtod(mp, struct ether_vlan_header *);
2507
2508 if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2509 bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
2510
2511 src = frame_hdr;
2512 ret = qla_tx_tso(ha, mp, &tso_cmd, src);
2513
2514 if (!(ret & ~1)) {
2515 /* find the additional tx_cmd descriptors required */
2516
2517 if (mp->m_flags & M_VLANTAG)
2518 tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN;
2519
2520 hdr_len = tso_cmd.total_hdr_len;
2521
2522 bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2523 bytes = QL_MIN(bytes, hdr_len);
2524
2525 num_tx_cmds++;
2526 hdr_len -= bytes;
2527
2528 while (hdr_len) {
2529 bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2530 hdr_len -= bytes;
2531 num_tx_cmds++;
2532 }
2533 hdr_len = tso_cmd.total_hdr_len;
2534
2535 if (ret == 0)
2536 src = (uint8_t *)eh;
2537 } else
2538 return (EINVAL);
2539 } else {
2540 (void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off);
2541 }
2542
2543 if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
2544 ql_hw_tx_done_locked(ha, txr_idx);
2545 if (hw->tx_cntxt[txr_idx].txr_free <=
2546 (num_tx_cmds + QLA_TX_MIN_FREE)) {
2547 QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= "
2548 "(num_tx_cmds + QLA_TX_MIN_FREE))\n",
2549 __func__));
2550 return (-1);
2551 }
2552 }
2553
2554 for (i = 0; i < num_tx_cmds; i++) {
2555 int j;
2556
2557 j = (tx_idx+i) & (NUM_TX_DESCRIPTORS - 1);
2558
2559 if (NULL != ha->tx_ring[txr_idx].tx_buf[j].m_head) {
2560 QL_ASSERT(ha, 0, \
2561 ("%s [%d]: txr_idx = %d tx_idx = %d mbuf = %p\n",\
2562 __func__, __LINE__, txr_idx, j,\
2563 ha->tx_ring[txr_idx].tx_buf[j].m_head));
2564 return (EINVAL);
2565 }
2566 }
2567
2568 tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx];
2569
2570 if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) {
2571 if (nsegs > ha->hw.max_tx_segs)
2572 ha->hw.max_tx_segs = nsegs;
2573
2574 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2575
2576 if (op_code) {
2577 tx_cmd->flags_opcode = op_code;
2578 tx_cmd->tcp_hdr_off = tcp_hdr_off;
2579
2580 } else {
2581 tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER;
2582 }
2583 } else {
2584 bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
2585 ha->tx_tso_frames++;
2586 }
2587
2588 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2589 tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
2590
2591 if (iscsi_pdu)
2592 eh->evl_tag |= ha->hw.user_pri_iscsi << 13;
2593
2594 } else if (mp->m_flags & M_VLANTAG) {
2595 if (hdr_len) { /* TSO */
2596 tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED |
2597 Q8_TX_CMD_FLAGS_HW_VLAN_ID);
2598 tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN;
2599 } else
2600 tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID;
2601
2602 ha->hw_vlan_tx_frames++;
2603 tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag;
2604
2605 if (iscsi_pdu) {
2606 tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13;
2607 mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci;
2608 }
2609 }
2610
2611 tx_cmd->n_bufs = (uint8_t)nsegs;
2612 tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF);
2613 tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8)));
2614 tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func);
2615
2616 c_seg = segs;
2617
2618 while (1) {
2619 for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) {
2620 switch (i) {
2621 case 0:
2622 tx_cmd->buf1_addr = c_seg->ds_addr;
2623 tx_cmd->buf1_len = c_seg->ds_len;
2624 break;
2625
2626 case 1:
2627 tx_cmd->buf2_addr = c_seg->ds_addr;
2628 tx_cmd->buf2_len = c_seg->ds_len;
2629 break;
2630
2631 case 2:
2632 tx_cmd->buf3_addr = c_seg->ds_addr;
2633 tx_cmd->buf3_len = c_seg->ds_len;
2634 break;
2635
2636 case 3:
2637 tx_cmd->buf4_addr = c_seg->ds_addr;
2638 tx_cmd->buf4_len = c_seg->ds_len;
2639 break;
2640 }
2641
2642 c_seg++;
2643 nsegs--;
2644 }
2645
2646 txr_next = hw->tx_cntxt[txr_idx].txr_next =
2647 (hw->tx_cntxt[txr_idx].txr_next + 1) &
2648 (NUM_TX_DESCRIPTORS - 1);
2649 tx_cmd_count++;
2650
2651 if (!nsegs)
2652 break;
2653
2654 tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2655 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2656 }
2657
2658 if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2659 /* TSO : Copy the header in the following tx cmd descriptors */
2660
2661 txr_next = hw->tx_cntxt[txr_idx].txr_next;
2662
2663 tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2664 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2665
2666 bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2667 bytes = QL_MIN(bytes, hdr_len);
2668
2669 dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN;
2670
2671 if (mp->m_flags & M_VLANTAG) {
2672 /* first copy the src/dst MAC addresses */
2673 bcopy(src, dst, (ETHER_ADDR_LEN * 2));
2674 dst += (ETHER_ADDR_LEN * 2);
2675 src += (ETHER_ADDR_LEN * 2);
2676
2677 *((uint16_t *)dst) = htons(ETHERTYPE_VLAN);
2678 dst += 2;
2679 *((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag);
2680 dst += 2;
2681
2682 /* bytes left in src header */
2683 hdr_len -= ((ETHER_ADDR_LEN * 2) +
2684 ETHER_VLAN_ENCAP_LEN);
2685
2686 /* bytes left in TxCmd Entry */
2687 bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN);
2688
2689 bcopy(src, dst, bytes);
2690 src += bytes;
2691 hdr_len -= bytes;
2692 } else {
2693 bcopy(src, dst, bytes);
2694 src += bytes;
2695 hdr_len -= bytes;
2696 }
2697
2698 txr_next = hw->tx_cntxt[txr_idx].txr_next =
2699 (hw->tx_cntxt[txr_idx].txr_next + 1) &
2700 (NUM_TX_DESCRIPTORS - 1);
2701 tx_cmd_count++;
2702
2703 while (hdr_len) {
2704 tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2705 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2706
2707 bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2708
2709 bcopy(src, tx_cmd, bytes);
2710 src += bytes;
2711 hdr_len -= bytes;
2712
2713 txr_next = hw->tx_cntxt[txr_idx].txr_next =
2714 (hw->tx_cntxt[txr_idx].txr_next + 1) &
2715 (NUM_TX_DESCRIPTORS - 1);
2716 tx_cmd_count++;
2717 }
2718 }
2719
2720 hw->tx_cntxt[txr_idx].txr_free =
2721 hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count;
2722
2723 QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\
2724 txr_idx);
2725 QL_DPRINT8(ha, (dev, "%s: return\n", __func__));
2726
2727 return (0);
2728 }
2729
2730 #define Q8_CONFIG_IND_TBL_SIZE 32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */
2731 static int
qla_config_rss_ind_table(qla_host_t * ha)2732 qla_config_rss_ind_table(qla_host_t *ha)
2733 {
2734 uint32_t i, count;
2735 uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE];
2736
2737 for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) {
2738 rss_ind_tbl[i] = i % ha->hw.num_sds_rings;
2739 }
2740
2741 for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ;
2742 i = i + Q8_CONFIG_IND_TBL_SIZE) {
2743 if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) {
2744 count = Q8_RSS_IND_TBL_MAX_IDX - i + 1;
2745 } else {
2746 count = Q8_CONFIG_IND_TBL_SIZE;
2747 }
2748
2749 if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id,
2750 rss_ind_tbl))
2751 return (-1);
2752 }
2753
2754 return (0);
2755 }
2756
2757 static int
qla_config_soft_lro(qla_host_t * ha)2758 qla_config_soft_lro(qla_host_t *ha)
2759 {
2760 int i;
2761 qla_hw_t *hw = &ha->hw;
2762 struct lro_ctrl *lro;
2763
2764 for (i = 0; i < hw->num_sds_rings; i++) {
2765 lro = &hw->sds[i].lro;
2766
2767 bzero(lro, sizeof(struct lro_ctrl));
2768
2769 #if (__FreeBSD_version >= 1100101)
2770 if (tcp_lro_init_args(lro, ha->ifp, 0, NUM_RX_DESCRIPTORS)) {
2771 device_printf(ha->pci_dev,
2772 "%s: tcp_lro_init_args [%d] failed\n",
2773 __func__, i);
2774 return (-1);
2775 }
2776 #else
2777 if (tcp_lro_init(lro)) {
2778 device_printf(ha->pci_dev,
2779 "%s: tcp_lro_init [%d] failed\n",
2780 __func__, i);
2781 return (-1);
2782 }
2783 #endif /* #if (__FreeBSD_version >= 1100101) */
2784
2785 lro->ifp = ha->ifp;
2786 }
2787
2788 QL_DPRINT2(ha, (ha->pci_dev, "%s: LRO initialized\n", __func__));
2789 return (0);
2790 }
2791
2792 static void
qla_drain_soft_lro(qla_host_t * ha)2793 qla_drain_soft_lro(qla_host_t *ha)
2794 {
2795 int i;
2796 qla_hw_t *hw = &ha->hw;
2797 struct lro_ctrl *lro;
2798
2799 for (i = 0; i < hw->num_sds_rings; i++) {
2800 lro = &hw->sds[i].lro;
2801
2802 #if (__FreeBSD_version >= 1100101)
2803 tcp_lro_flush_all(lro);
2804 #else
2805 struct lro_entry *queued;
2806
2807 while ((!SLIST_EMPTY(&lro->lro_active))) {
2808 queued = SLIST_FIRST(&lro->lro_active);
2809 SLIST_REMOVE_HEAD(&lro->lro_active, next);
2810 tcp_lro_flush(lro, queued);
2811 }
2812 #endif /* #if (__FreeBSD_version >= 1100101) */
2813 }
2814
2815 return;
2816 }
2817
2818 static void
qla_free_soft_lro(qla_host_t * ha)2819 qla_free_soft_lro(qla_host_t *ha)
2820 {
2821 int i;
2822 qla_hw_t *hw = &ha->hw;
2823 struct lro_ctrl *lro;
2824
2825 for (i = 0; i < hw->num_sds_rings; i++) {
2826 lro = &hw->sds[i].lro;
2827 tcp_lro_free(lro);
2828 }
2829
2830 return;
2831 }
2832
2833 /*
2834 * Name: ql_del_hw_if
2835 * Function: Destroys the hardware specific entities corresponding to an
2836 * Ethernet Interface
2837 */
2838 void
ql_del_hw_if(qla_host_t * ha)2839 ql_del_hw_if(qla_host_t *ha)
2840 {
2841 uint32_t i;
2842 uint32_t num_msix;
2843
2844 (void)qla_stop_nic_func(ha);
2845
2846 qla_del_rcv_cntxt(ha);
2847
2848 if(qla_del_xmt_cntxt(ha))
2849 goto ql_del_hw_if_exit;
2850
2851 if (ha->hw.flags.init_intr_cnxt) {
2852 for (i = 0; i < ha->hw.num_sds_rings; ) {
2853 if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
2854 num_msix = Q8_MAX_INTR_VECTORS;
2855 else
2856 num_msix = ha->hw.num_sds_rings - i;
2857
2858 if (qla_config_intr_cntxt(ha, i, num_msix, 0))
2859 break;
2860
2861 i += num_msix;
2862 }
2863
2864 ha->hw.flags.init_intr_cnxt = 0;
2865 }
2866
2867 ql_del_hw_if_exit:
2868 if (ha->hw.enable_soft_lro) {
2869 qla_drain_soft_lro(ha);
2870 qla_free_soft_lro(ha);
2871 }
2872
2873 return;
2874 }
2875
2876 void
qla_confirm_9kb_enable(qla_host_t * ha)2877 qla_confirm_9kb_enable(qla_host_t *ha)
2878 {
2879 // uint32_t supports_9kb = 0;
2880
2881 ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX);
2882
2883 /* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */
2884 WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2);
2885 WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
2886
2887 #if 0
2888 qla_get_nic_partition(ha, &supports_9kb, NULL);
2889
2890 if (!supports_9kb)
2891 #endif
2892 ha->hw.enable_9kb = 0;
2893
2894 return;
2895 }
2896
2897 /*
2898 * Name: ql_init_hw_if
2899 * Function: Creates the hardware specific entities corresponding to an
2900 * Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
2901 * corresponding to the interface. Enables LRO if allowed.
2902 */
2903 int
ql_init_hw_if(qla_host_t * ha)2904 ql_init_hw_if(qla_host_t *ha)
2905 {
2906 device_t dev;
2907 uint32_t i;
2908 uint8_t bcast_mac[6];
2909 qla_rdesc_t *rdesc;
2910 uint32_t num_msix;
2911
2912 dev = ha->pci_dev;
2913
2914 for (i = 0; i < ha->hw.num_sds_rings; i++) {
2915 bzero(ha->hw.dma_buf.sds_ring[i].dma_b,
2916 ha->hw.dma_buf.sds_ring[i].size);
2917 }
2918
2919 for (i = 0; i < ha->hw.num_sds_rings; ) {
2920 if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
2921 num_msix = Q8_MAX_INTR_VECTORS;
2922 else
2923 num_msix = ha->hw.num_sds_rings - i;
2924
2925 if (qla_config_intr_cntxt(ha, i, num_msix, 1)) {
2926 if (i > 0) {
2927 num_msix = i;
2928
2929 for (i = 0; i < num_msix; ) {
2930 qla_config_intr_cntxt(ha, i,
2931 Q8_MAX_INTR_VECTORS, 0);
2932 i += Q8_MAX_INTR_VECTORS;
2933 }
2934 }
2935 return (-1);
2936 }
2937
2938 i = i + num_msix;
2939 }
2940
2941 ha->hw.flags.init_intr_cnxt = 1;
2942
2943 /*
2944 * Create Receive Context
2945 */
2946 if (qla_init_rcv_cntxt(ha)) {
2947 return (-1);
2948 }
2949
2950 for (i = 0; i < ha->hw.num_rds_rings; i++) {
2951 rdesc = &ha->hw.rds[i];
2952 rdesc->rx_next = NUM_RX_DESCRIPTORS - 2;
2953 rdesc->rx_in = 0;
2954 /* Update the RDS Producer Indices */
2955 QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\
2956 rdesc->rx_next);
2957 }
2958
2959 /*
2960 * Create Transmit Context
2961 */
2962 if (qla_init_xmt_cntxt(ha)) {
2963 qla_del_rcv_cntxt(ha);
2964 return (-1);
2965 }
2966 ha->hw.max_tx_segs = 0;
2967
2968 if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1, 1))
2969 return(-1);
2970
2971 ha->hw.flags.unicast_mac = 1;
2972
2973 bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2974 bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2975
2976 if (qla_config_mac_addr(ha, bcast_mac, 1, 1))
2977 return (-1);
2978
2979 ha->hw.flags.bcast_mac = 1;
2980
2981 /*
2982 * program any cached multicast addresses
2983 */
2984 if (qla_hw_add_all_mcast(ha))
2985 return (-1);
2986
2987 if (ql_set_max_mtu(ha, ha->max_frame_size, ha->hw.rcv_cntxt_id))
2988 return (-1);
2989
2990 if (qla_config_rss(ha, ha->hw.rcv_cntxt_id))
2991 return (-1);
2992
2993 if (qla_config_rss_ind_table(ha))
2994 return (-1);
2995
2996 if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1))
2997 return (-1);
2998
2999 if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
3000 return (-1);
3001
3002 if (ha->ifp->if_capenable & IFCAP_LRO) {
3003 if (ha->hw.enable_hw_lro) {
3004 ha->hw.enable_soft_lro = 0;
3005
3006 if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
3007 return (-1);
3008 } else {
3009 ha->hw.enable_soft_lro = 1;
3010
3011 if (qla_config_soft_lro(ha))
3012 return (-1);
3013 }
3014 }
3015
3016 if (qla_init_nic_func(ha))
3017 return (-1);
3018
3019 if (qla_query_fw_dcbx_caps(ha))
3020 return (-1);
3021
3022 for (i = 0; i < ha->hw.num_sds_rings; i++)
3023 QL_ENABLE_INTERRUPTS(ha, i);
3024
3025 return (0);
3026 }
3027
3028 static int
qla_map_sds_to_rds(qla_host_t * ha,uint32_t start_idx,uint32_t num_idx)3029 qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx)
3030 {
3031 device_t dev = ha->pci_dev;
3032 q80_rq_map_sds_to_rds_t *map_rings;
3033 q80_rsp_map_sds_to_rds_t *map_rings_rsp;
3034 uint32_t i, err;
3035 qla_hw_t *hw = &ha->hw;
3036
3037 map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox;
3038 bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t));
3039
3040 map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS;
3041 map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2);
3042 map_rings->count_version |= Q8_MBX_CMD_VERSION;
3043
3044 map_rings->cntxt_id = hw->rcv_cntxt_id;
3045 map_rings->num_rings = num_idx;
3046
3047 for (i = 0; i < num_idx; i++) {
3048 map_rings->sds_rds[i].sds_ring = i + start_idx;
3049 map_rings->sds_rds[i].rds_ring = i + start_idx;
3050 }
3051
3052 if (qla_mbx_cmd(ha, (uint32_t *)map_rings,
3053 (sizeof (q80_rq_map_sds_to_rds_t) >> 2),
3054 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
3055 device_printf(dev, "%s: failed0\n", __func__);
3056 return (-1);
3057 }
3058
3059 map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox;
3060
3061 err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status);
3062
3063 if (err) {
3064 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3065 return (-1);
3066 }
3067
3068 return (0);
3069 }
3070
3071 /*
3072 * Name: qla_init_rcv_cntxt
3073 * Function: Creates the Receive Context.
3074 */
3075 static int
qla_init_rcv_cntxt(qla_host_t * ha)3076 qla_init_rcv_cntxt(qla_host_t *ha)
3077 {
3078 q80_rq_rcv_cntxt_t *rcntxt;
3079 q80_rsp_rcv_cntxt_t *rcntxt_rsp;
3080 q80_stat_desc_t *sdesc;
3081 int i, j;
3082 qla_hw_t *hw = &ha->hw;
3083 device_t dev;
3084 uint32_t err;
3085 uint32_t rcntxt_sds_rings;
3086 uint32_t rcntxt_rds_rings;
3087 uint32_t max_idx;
3088
3089 dev = ha->pci_dev;
3090
3091 /*
3092 * Create Receive Context
3093 */
3094
3095 for (i = 0; i < hw->num_sds_rings; i++) {
3096 sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0];
3097
3098 for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) {
3099 sdesc->data[0] = 1ULL;
3100 sdesc->data[1] = 1ULL;
3101 }
3102 }
3103
3104 rcntxt_sds_rings = hw->num_sds_rings;
3105 if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS)
3106 rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS;
3107
3108 rcntxt_rds_rings = hw->num_rds_rings;
3109
3110 if (hw->num_rds_rings > MAX_RDS_RING_SETS)
3111 rcntxt_rds_rings = MAX_RDS_RING_SETS;
3112
3113 rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox;
3114 bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t)));
3115
3116 rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT;
3117 rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2);
3118 rcntxt->count_version |= Q8_MBX_CMD_VERSION;
3119
3120 rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW |
3121 Q8_RCV_CNTXT_CAP0_LRO |
3122 Q8_RCV_CNTXT_CAP0_HW_LRO |
3123 Q8_RCV_CNTXT_CAP0_RSS |
3124 Q8_RCV_CNTXT_CAP0_SGL_LRO;
3125
3126 if (ha->hw.enable_9kb)
3127 rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO;
3128 else
3129 rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO;
3130
3131 if (ha->hw.num_rds_rings > 1) {
3132 rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5);
3133 rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS;
3134 } else
3135 rcntxt->nrds_sets_rings = 0x1 | (1 << 5);
3136
3137 rcntxt->nsds_rings = rcntxt_sds_rings;
3138
3139 rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE;
3140
3141 rcntxt->rcv_vpid = 0;
3142
3143 for (i = 0; i < rcntxt_sds_rings; i++) {
3144 rcntxt->sds[i].paddr =
3145 qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr);
3146 rcntxt->sds[i].size =
3147 qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
3148 rcntxt->sds[i].intr_id = qla_host_to_le16(hw->intr_id[i]);
3149 rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0);
3150 }
3151
3152 for (i = 0; i < rcntxt_rds_rings; i++) {
3153 rcntxt->rds[i].paddr_std =
3154 qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr);
3155
3156 if (ha->hw.enable_9kb)
3157 rcntxt->rds[i].std_bsize =
3158 qla_host_to_le64(MJUM9BYTES);
3159 else
3160 rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
3161
3162 rcntxt->rds[i].std_nentries =
3163 qla_host_to_le32(NUM_RX_DESCRIPTORS);
3164 }
3165
3166 if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
3167 (sizeof (q80_rq_rcv_cntxt_t) >> 2),
3168 ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) {
3169 device_printf(dev, "%s: failed0\n", __func__);
3170 return (-1);
3171 }
3172
3173 rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox;
3174
3175 err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
3176
3177 if (err) {
3178 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3179 return (-1);
3180 }
3181
3182 for (i = 0; i < rcntxt_sds_rings; i++) {
3183 hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i];
3184 }
3185
3186 for (i = 0; i < rcntxt_rds_rings; i++) {
3187 hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std;
3188 }
3189
3190 hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id;
3191
3192 ha->hw.flags.init_rx_cnxt = 1;
3193
3194 if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) {
3195 for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) {
3196 if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings)
3197 max_idx = MAX_RCNTXT_SDS_RINGS;
3198 else
3199 max_idx = hw->num_sds_rings - i;
3200
3201 err = qla_add_rcv_rings(ha, i, max_idx);
3202 if (err)
3203 return -1;
3204
3205 i += max_idx;
3206 }
3207 }
3208
3209 if (hw->num_rds_rings > 1) {
3210 for (i = 0; i < hw->num_rds_rings; ) {
3211 if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings)
3212 max_idx = MAX_SDS_TO_RDS_MAP;
3213 else
3214 max_idx = hw->num_rds_rings - i;
3215
3216 err = qla_map_sds_to_rds(ha, i, max_idx);
3217 if (err)
3218 return -1;
3219
3220 i += max_idx;
3221 }
3222 }
3223
3224 return (0);
3225 }
3226
3227 static int
qla_add_rcv_rings(qla_host_t * ha,uint32_t sds_idx,uint32_t nsds)3228 qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds)
3229 {
3230 device_t dev = ha->pci_dev;
3231 q80_rq_add_rcv_rings_t *add_rcv;
3232 q80_rsp_add_rcv_rings_t *add_rcv_rsp;
3233 uint32_t i,j, err;
3234 qla_hw_t *hw = &ha->hw;
3235
3236 add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox;
3237 bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t));
3238
3239 add_rcv->opcode = Q8_MBX_ADD_RX_RINGS;
3240 add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2);
3241 add_rcv->count_version |= Q8_MBX_CMD_VERSION;
3242
3243 add_rcv->nrds_sets_rings = nsds | (1 << 5);
3244 add_rcv->nsds_rings = nsds;
3245 add_rcv->cntxt_id = hw->rcv_cntxt_id;
3246
3247 for (i = 0; i < nsds; i++) {
3248 j = i + sds_idx;
3249
3250 add_rcv->sds[i].paddr =
3251 qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr);
3252
3253 add_rcv->sds[i].size =
3254 qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
3255
3256 add_rcv->sds[i].intr_id = qla_host_to_le16(hw->intr_id[j]);
3257 add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0);
3258 }
3259
3260 for (i = 0; (i < nsds); i++) {
3261 j = i + sds_idx;
3262
3263 add_rcv->rds[i].paddr_std =
3264 qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr);
3265
3266 if (ha->hw.enable_9kb)
3267 add_rcv->rds[i].std_bsize =
3268 qla_host_to_le64(MJUM9BYTES);
3269 else
3270 add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
3271
3272 add_rcv->rds[i].std_nentries =
3273 qla_host_to_le32(NUM_RX_DESCRIPTORS);
3274 }
3275
3276 if (qla_mbx_cmd(ha, (uint32_t *)add_rcv,
3277 (sizeof (q80_rq_add_rcv_rings_t) >> 2),
3278 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
3279 device_printf(dev, "%s: failed0\n", __func__);
3280 return (-1);
3281 }
3282
3283 add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
3284
3285 err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status);
3286
3287 if (err) {
3288 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3289 return (-1);
3290 }
3291
3292 for (i = 0; i < nsds; i++) {
3293 hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i];
3294 }
3295
3296 for (i = 0; i < nsds; i++) {
3297 hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std;
3298 }
3299
3300 return (0);
3301 }
3302
3303 /*
3304 * Name: qla_del_rcv_cntxt
3305 * Function: Destroys the Receive Context.
3306 */
3307 static void
qla_del_rcv_cntxt(qla_host_t * ha)3308 qla_del_rcv_cntxt(qla_host_t *ha)
3309 {
3310 device_t dev = ha->pci_dev;
3311 q80_rcv_cntxt_destroy_t *rcntxt;
3312 q80_rcv_cntxt_destroy_rsp_t *rcntxt_rsp;
3313 uint32_t err;
3314 uint8_t bcast_mac[6];
3315
3316 if (!ha->hw.flags.init_rx_cnxt)
3317 return;
3318
3319 if (qla_hw_del_all_mcast(ha))
3320 return;
3321
3322 if (ha->hw.flags.bcast_mac) {
3323 bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
3324 bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
3325
3326 if (qla_config_mac_addr(ha, bcast_mac, 0, 1))
3327 return;
3328 ha->hw.flags.bcast_mac = 0;
3329 }
3330
3331 if (ha->hw.flags.unicast_mac) {
3332 if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0, 1))
3333 return;
3334 ha->hw.flags.unicast_mac = 0;
3335 }
3336
3337 rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox;
3338 bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t)));
3339
3340 rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT;
3341 rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2);
3342 rcntxt->count_version |= Q8_MBX_CMD_VERSION;
3343
3344 rcntxt->cntxt_id = ha->hw.rcv_cntxt_id;
3345
3346 if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
3347 (sizeof (q80_rcv_cntxt_destroy_t) >> 2),
3348 ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) {
3349 device_printf(dev, "%s: failed0\n", __func__);
3350 return;
3351 }
3352 rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox;
3353
3354 err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
3355
3356 if (err) {
3357 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3358 }
3359
3360 ha->hw.flags.init_rx_cnxt = 0;
3361 return;
3362 }
3363
3364 /*
3365 * Name: qla_init_xmt_cntxt
3366 * Function: Creates the Transmit Context.
3367 */
3368 static int
qla_init_xmt_cntxt_i(qla_host_t * ha,uint32_t txr_idx)3369 qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
3370 {
3371 device_t dev;
3372 qla_hw_t *hw = &ha->hw;
3373 q80_rq_tx_cntxt_t *tcntxt;
3374 q80_rsp_tx_cntxt_t *tcntxt_rsp;
3375 uint32_t err;
3376 qla_hw_tx_cntxt_t *hw_tx_cntxt;
3377 uint32_t intr_idx;
3378
3379 hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3380
3381 dev = ha->pci_dev;
3382
3383 /*
3384 * Create Transmit Context
3385 */
3386 tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox;
3387 bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t)));
3388
3389 tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT;
3390 tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2);
3391 tcntxt->count_version |= Q8_MBX_CMD_VERSION;
3392
3393 intr_idx = txr_idx;
3394
3395 #ifdef QL_ENABLE_ISCSI_TLV
3396
3397 tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO |
3398 Q8_TX_CNTXT_CAP0_TC;
3399
3400 if (txr_idx >= (ha->hw.num_tx_rings >> 1)) {
3401 tcntxt->traffic_class = 1;
3402 }
3403
3404 intr_idx = txr_idx % (ha->hw.num_tx_rings >> 1);
3405
3406 #else
3407 tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO;
3408
3409 #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
3410
3411 tcntxt->ntx_rings = 1;
3412
3413 tcntxt->tx_ring[0].paddr =
3414 qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr);
3415 tcntxt->tx_ring[0].tx_consumer =
3416 qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr);
3417 tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS);
3418
3419 tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[intr_idx]);
3420 tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0);
3421
3422 hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS;
3423 hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0;
3424 *(hw_tx_cntxt->tx_cons) = 0;
3425
3426 if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
3427 (sizeof (q80_rq_tx_cntxt_t) >> 2),
3428 ha->hw.mbox,
3429 (sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) {
3430 device_printf(dev, "%s: failed0\n", __func__);
3431 return (-1);
3432 }
3433 tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox;
3434
3435 err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
3436
3437 if (err) {
3438 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3439 return -1;
3440 }
3441
3442 hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index;
3443 hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id;
3444
3445 if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0))
3446 return (-1);
3447
3448 return (0);
3449 }
3450
3451 /*
3452 * Name: qla_del_xmt_cntxt
3453 * Function: Destroys the Transmit Context.
3454 */
3455 static int
qla_del_xmt_cntxt_i(qla_host_t * ha,uint32_t txr_idx)3456 qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
3457 {
3458 device_t dev = ha->pci_dev;
3459 q80_tx_cntxt_destroy_t *tcntxt;
3460 q80_tx_cntxt_destroy_rsp_t *tcntxt_rsp;
3461 uint32_t err;
3462
3463 tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox;
3464 bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t)));
3465
3466 tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT;
3467 tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2);
3468 tcntxt->count_version |= Q8_MBX_CMD_VERSION;
3469
3470 tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id;
3471
3472 if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
3473 (sizeof (q80_tx_cntxt_destroy_t) >> 2),
3474 ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) {
3475 device_printf(dev, "%s: failed0\n", __func__);
3476 return (-1);
3477 }
3478 tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox;
3479
3480 err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
3481
3482 if (err) {
3483 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3484 return (-1);
3485 }
3486
3487 return (0);
3488 }
3489 static int
qla_del_xmt_cntxt(qla_host_t * ha)3490 qla_del_xmt_cntxt(qla_host_t *ha)
3491 {
3492 uint32_t i;
3493 int ret = 0;
3494
3495 if (!ha->hw.flags.init_tx_cnxt)
3496 return (ret);
3497
3498 for (i = 0; i < ha->hw.num_tx_rings; i++) {
3499 if ((ret = qla_del_xmt_cntxt_i(ha, i)) != 0)
3500 break;
3501 }
3502 ha->hw.flags.init_tx_cnxt = 0;
3503
3504 return (ret);
3505 }
3506
3507 static int
qla_init_xmt_cntxt(qla_host_t * ha)3508 qla_init_xmt_cntxt(qla_host_t *ha)
3509 {
3510 uint32_t i, j;
3511
3512 for (i = 0; i < ha->hw.num_tx_rings; i++) {
3513 if (qla_init_xmt_cntxt_i(ha, i) != 0) {
3514 for (j = 0; j < i; j++) {
3515 if (qla_del_xmt_cntxt_i(ha, j))
3516 break;
3517 }
3518 return (-1);
3519 }
3520 }
3521 ha->hw.flags.init_tx_cnxt = 1;
3522 return (0);
3523 }
3524
3525 static int
qla_hw_all_mcast(qla_host_t * ha,uint32_t add_mcast)3526 qla_hw_all_mcast(qla_host_t *ha, uint32_t add_mcast)
3527 {
3528 int i, nmcast;
3529 uint32_t count = 0;
3530 uint8_t *mcast;
3531
3532 nmcast = ha->hw.nmcast;
3533
3534 QL_DPRINT2(ha, (ha->pci_dev,
3535 "%s:[0x%x] enter nmcast = %d \n", __func__, add_mcast, nmcast));
3536
3537 mcast = ha->hw.mac_addr_arr;
3538 memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3539
3540 for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
3541 if ((ha->hw.mcast[i].addr[0] != 0) ||
3542 (ha->hw.mcast[i].addr[1] != 0) ||
3543 (ha->hw.mcast[i].addr[2] != 0) ||
3544 (ha->hw.mcast[i].addr[3] != 0) ||
3545 (ha->hw.mcast[i].addr[4] != 0) ||
3546 (ha->hw.mcast[i].addr[5] != 0)) {
3547 bcopy(ha->hw.mcast[i].addr, mcast, ETHER_ADDR_LEN);
3548 mcast = mcast + ETHER_ADDR_LEN;
3549 count++;
3550
3551 device_printf(ha->pci_dev,
3552 "%s: %x:%x:%x:%x:%x:%x \n",
3553 __func__, ha->hw.mcast[i].addr[0],
3554 ha->hw.mcast[i].addr[1], ha->hw.mcast[i].addr[2],
3555 ha->hw.mcast[i].addr[3], ha->hw.mcast[i].addr[4],
3556 ha->hw.mcast[i].addr[5]);
3557
3558 if (count == Q8_MAX_MAC_ADDRS) {
3559 if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3560 add_mcast, count)) {
3561 device_printf(ha->pci_dev,
3562 "%s: failed\n", __func__);
3563 return (-1);
3564 }
3565
3566 count = 0;
3567 mcast = ha->hw.mac_addr_arr;
3568 memset(mcast, 0,
3569 (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3570 }
3571
3572 nmcast--;
3573 }
3574 }
3575
3576 if (count) {
3577 if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mcast,
3578 count)) {
3579 device_printf(ha->pci_dev, "%s: failed\n", __func__);
3580 return (-1);
3581 }
3582 }
3583 QL_DPRINT2(ha, (ha->pci_dev,
3584 "%s:[0x%x] exit nmcast = %d \n", __func__, add_mcast, nmcast));
3585
3586 return 0;
3587 }
3588
3589 static int
qla_hw_add_all_mcast(qla_host_t * ha)3590 qla_hw_add_all_mcast(qla_host_t *ha)
3591 {
3592 int ret;
3593
3594 ret = qla_hw_all_mcast(ha, 1);
3595
3596 return (ret);
3597 }
3598
3599 int
qla_hw_del_all_mcast(qla_host_t * ha)3600 qla_hw_del_all_mcast(qla_host_t *ha)
3601 {
3602 int ret;
3603
3604 ret = qla_hw_all_mcast(ha, 0);
3605
3606 bzero(ha->hw.mcast, (sizeof (qla_mcast_t) * Q8_MAX_NUM_MULTICAST_ADDRS));
3607 ha->hw.nmcast = 0;
3608
3609 return (ret);
3610 }
3611
3612 static int
qla_hw_mac_addr_present(qla_host_t * ha,uint8_t * mta)3613 qla_hw_mac_addr_present(qla_host_t *ha, uint8_t *mta)
3614 {
3615 int i;
3616
3617 for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3618 if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0)
3619 return (0); /* its been already added */
3620 }
3621 return (-1);
3622 }
3623
3624 static int
qla_hw_add_mcast(qla_host_t * ha,uint8_t * mta,uint32_t nmcast)3625 qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3626 {
3627 int i;
3628
3629 for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3630 if ((ha->hw.mcast[i].addr[0] == 0) &&
3631 (ha->hw.mcast[i].addr[1] == 0) &&
3632 (ha->hw.mcast[i].addr[2] == 0) &&
3633 (ha->hw.mcast[i].addr[3] == 0) &&
3634 (ha->hw.mcast[i].addr[4] == 0) &&
3635 (ha->hw.mcast[i].addr[5] == 0)) {
3636 bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN);
3637 ha->hw.nmcast++;
3638
3639 mta = mta + ETHER_ADDR_LEN;
3640 nmcast--;
3641
3642 if (nmcast == 0)
3643 break;
3644 }
3645 }
3646 return 0;
3647 }
3648
3649 static int
qla_hw_del_mcast(qla_host_t * ha,uint8_t * mta,uint32_t nmcast)3650 qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3651 {
3652 int i;
3653
3654 for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3655 if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) {
3656 ha->hw.mcast[i].addr[0] = 0;
3657 ha->hw.mcast[i].addr[1] = 0;
3658 ha->hw.mcast[i].addr[2] = 0;
3659 ha->hw.mcast[i].addr[3] = 0;
3660 ha->hw.mcast[i].addr[4] = 0;
3661 ha->hw.mcast[i].addr[5] = 0;
3662
3663 ha->hw.nmcast--;
3664
3665 mta = mta + ETHER_ADDR_LEN;
3666 nmcast--;
3667
3668 if (nmcast == 0)
3669 break;
3670 }
3671 }
3672 return 0;
3673 }
3674
3675 /*
3676 * Name: ql_hw_set_multi
3677 * Function: Sets the Multicast Addresses provided by the host O.S into the
3678 * hardware (for the given interface)
3679 */
3680 int
ql_hw_set_multi(qla_host_t * ha,uint8_t * mcast_addr,uint32_t mcnt,uint32_t add_mac)3681 ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast_addr, uint32_t mcnt,
3682 uint32_t add_mac)
3683 {
3684 uint8_t *mta = mcast_addr;
3685 int i;
3686 int ret = 0;
3687 uint32_t count = 0;
3688 uint8_t *mcast;
3689
3690 mcast = ha->hw.mac_addr_arr;
3691 memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3692
3693 for (i = 0; i < mcnt; i++) {
3694 if (mta[0] || mta[1] || mta[2] || mta[3] || mta[4] || mta[5]) {
3695 if (add_mac) {
3696 if (qla_hw_mac_addr_present(ha, mta) != 0) {
3697 bcopy(mta, mcast, ETHER_ADDR_LEN);
3698 mcast = mcast + ETHER_ADDR_LEN;
3699 count++;
3700 }
3701 } else {
3702 if (qla_hw_mac_addr_present(ha, mta) == 0) {
3703 bcopy(mta, mcast, ETHER_ADDR_LEN);
3704 mcast = mcast + ETHER_ADDR_LEN;
3705 count++;
3706 }
3707 }
3708 }
3709 if (count == Q8_MAX_MAC_ADDRS) {
3710 if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3711 add_mac, count)) {
3712 device_printf(ha->pci_dev, "%s: failed\n",
3713 __func__);
3714 return (-1);
3715 }
3716
3717 if (add_mac) {
3718 qla_hw_add_mcast(ha, ha->hw.mac_addr_arr,
3719 count);
3720 } else {
3721 qla_hw_del_mcast(ha, ha->hw.mac_addr_arr,
3722 count);
3723 }
3724
3725 count = 0;
3726 mcast = ha->hw.mac_addr_arr;
3727 memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3728 }
3729
3730 mta += Q8_MAC_ADDR_LEN;
3731 }
3732
3733 if (count) {
3734 if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mac,
3735 count)) {
3736 device_printf(ha->pci_dev, "%s: failed\n", __func__);
3737 return (-1);
3738 }
3739 if (add_mac) {
3740 qla_hw_add_mcast(ha, ha->hw.mac_addr_arr, count);
3741 } else {
3742 qla_hw_del_mcast(ha, ha->hw.mac_addr_arr, count);
3743 }
3744 }
3745
3746 return (ret);
3747 }
3748
3749 /*
3750 * Name: ql_hw_tx_done_locked
3751 * Function: Handle Transmit Completions
3752 */
3753 void
ql_hw_tx_done_locked(qla_host_t * ha,uint32_t txr_idx)3754 ql_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx)
3755 {
3756 qla_tx_buf_t *txb;
3757 qla_hw_t *hw = &ha->hw;
3758 uint32_t comp_idx, comp_count = 0;
3759 qla_hw_tx_cntxt_t *hw_tx_cntxt;
3760
3761 hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3762
3763 /* retrieve index of last entry in tx ring completed */
3764 comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons));
3765
3766 while (comp_idx != hw_tx_cntxt->txr_comp) {
3767 txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp];
3768
3769 hw_tx_cntxt->txr_comp++;
3770 if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS)
3771 hw_tx_cntxt->txr_comp = 0;
3772
3773 comp_count++;
3774
3775 if (txb->m_head) {
3776 if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1);
3777
3778 bus_dmamap_sync(ha->tx_tag, txb->map,
3779 BUS_DMASYNC_POSTWRITE);
3780 bus_dmamap_unload(ha->tx_tag, txb->map);
3781 m_freem(txb->m_head);
3782
3783 txb->m_head = NULL;
3784 }
3785 }
3786
3787 hw_tx_cntxt->txr_free += comp_count;
3788
3789 if (hw_tx_cntxt->txr_free > NUM_TX_DESCRIPTORS)
3790 device_printf(ha->pci_dev, "%s [%d]: txr_idx = %d txr_free = %d"
3791 "txr_next = %d txr_comp = %d\n", __func__, __LINE__,
3792 txr_idx, hw_tx_cntxt->txr_free,
3793 hw_tx_cntxt->txr_next, hw_tx_cntxt->txr_comp);
3794
3795 QL_ASSERT(ha, (hw_tx_cntxt->txr_free <= NUM_TX_DESCRIPTORS), \
3796 ("%s [%d]: txr_idx = %d txr_free = %d txr_next = %d txr_comp = %d\n",\
3797 __func__, __LINE__, txr_idx, hw_tx_cntxt->txr_free, \
3798 hw_tx_cntxt->txr_next, hw_tx_cntxt->txr_comp));
3799
3800 return;
3801 }
3802
3803 void
ql_update_link_state(qla_host_t * ha)3804 ql_update_link_state(qla_host_t *ha)
3805 {
3806 uint32_t link_state = 0;
3807 uint32_t prev_link_state;
3808
3809 prev_link_state = ha->hw.link_up;
3810
3811 if (ha->ifp->if_drv_flags & IFF_DRV_RUNNING) {
3812 link_state = READ_REG32(ha, Q8_LINK_STATE);
3813
3814 if (ha->pci_func == 0) {
3815 link_state = (((link_state & 0xF) == 1)? 1 : 0);
3816 } else {
3817 link_state = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
3818 }
3819 }
3820
3821 atomic_store_rel_8(&ha->hw.link_up, (uint8_t)link_state);
3822
3823 if (prev_link_state != ha->hw.link_up) {
3824 if (ha->hw.link_up) {
3825 if_link_state_change(ha->ifp, LINK_STATE_UP);
3826 } else {
3827 if_link_state_change(ha->ifp, LINK_STATE_DOWN);
3828 }
3829 }
3830 return;
3831 }
3832
3833 int
ql_hw_check_health(qla_host_t * ha)3834 ql_hw_check_health(qla_host_t *ha)
3835 {
3836 uint32_t val;
3837
3838 ha->hw.health_count++;
3839
3840 if (ha->hw.health_count < 500)
3841 return 0;
3842
3843 ha->hw.health_count = 0;
3844
3845 val = READ_REG32(ha, Q8_ASIC_TEMPERATURE);
3846
3847 if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) ||
3848 (QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) {
3849 device_printf(ha->pci_dev, "%s: Temperature Alert"
3850 " at ts_usecs %ld ts_reg = 0x%08x\n",
3851 __func__, qla_get_usec_timestamp(), val);
3852
3853 if (ha->hw.sp_log_stop_events & Q8_SP_LOG_STOP_TEMP_FAILURE)
3854 ha->hw.sp_log_stop = -1;
3855
3856 QL_INITIATE_RECOVERY(ha);
3857 return -1;
3858 }
3859
3860 val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
3861
3862 if ((val != ha->hw.hbeat_value) &&
3863 (!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) {
3864 ha->hw.hbeat_value = val;
3865 ha->hw.hbeat_failure = 0;
3866 return 0;
3867 }
3868
3869 ha->hw.hbeat_failure++;
3870
3871 if ((ha->dbg_level & 0x8000) && (ha->hw.hbeat_failure == 1))
3872 device_printf(ha->pci_dev, "%s: Heartbeat Failue 1[0x%08x]\n",
3873 __func__, val);
3874 if (ha->hw.hbeat_failure < 2) /* we ignore the first failure */
3875 return 0;
3876 else {
3877 uint32_t peg_halt_status1;
3878 uint32_t peg_halt_status2;
3879
3880 peg_halt_status1 = READ_REG32(ha, Q8_PEG_HALT_STATUS1);
3881 peg_halt_status2 = READ_REG32(ha, Q8_PEG_HALT_STATUS2);
3882
3883 device_printf(ha->pci_dev,
3884 "%s: Heartbeat Failue at ts_usecs = %ld "
3885 "fw_heart_beat = 0x%08x "
3886 "peg_halt_status1 = 0x%08x "
3887 "peg_halt_status2 = 0x%08x\n",
3888 __func__, qla_get_usec_timestamp(), val,
3889 peg_halt_status1, peg_halt_status2);
3890
3891 if (ha->hw.sp_log_stop_events & Q8_SP_LOG_STOP_HBEAT_FAILURE)
3892 ha->hw.sp_log_stop = -1;
3893 }
3894 QL_INITIATE_RECOVERY(ha);
3895
3896 return -1;
3897 }
3898
3899 static int
qla_init_nic_func(qla_host_t * ha)3900 qla_init_nic_func(qla_host_t *ha)
3901 {
3902 device_t dev;
3903 q80_init_nic_func_t *init_nic;
3904 q80_init_nic_func_rsp_t *init_nic_rsp;
3905 uint32_t err;
3906
3907 dev = ha->pci_dev;
3908
3909 init_nic = (q80_init_nic_func_t *)ha->hw.mbox;
3910 bzero(init_nic, sizeof(q80_init_nic_func_t));
3911
3912 init_nic->opcode = Q8_MBX_INIT_NIC_FUNC;
3913 init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2);
3914 init_nic->count_version |= Q8_MBX_CMD_VERSION;
3915
3916 init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN;
3917 init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN;
3918 init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN;
3919
3920 //qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t));
3921 if (qla_mbx_cmd(ha, (uint32_t *)init_nic,
3922 (sizeof (q80_init_nic_func_t) >> 2),
3923 ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) {
3924 device_printf(dev, "%s: failed\n", __func__);
3925 return -1;
3926 }
3927
3928 init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox;
3929 // qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t));
3930
3931 err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status);
3932
3933 if (err) {
3934 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3935 } else {
3936 device_printf(dev, "%s: successful\n", __func__);
3937 }
3938
3939 return 0;
3940 }
3941
3942 static int
qla_stop_nic_func(qla_host_t * ha)3943 qla_stop_nic_func(qla_host_t *ha)
3944 {
3945 device_t dev;
3946 q80_stop_nic_func_t *stop_nic;
3947 q80_stop_nic_func_rsp_t *stop_nic_rsp;
3948 uint32_t err;
3949
3950 dev = ha->pci_dev;
3951
3952 stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox;
3953 bzero(stop_nic, sizeof(q80_stop_nic_func_t));
3954
3955 stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC;
3956 stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2);
3957 stop_nic->count_version |= Q8_MBX_CMD_VERSION;
3958
3959 stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN;
3960 stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN;
3961
3962 //qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t));
3963 if (qla_mbx_cmd(ha, (uint32_t *)stop_nic,
3964 (sizeof (q80_stop_nic_func_t) >> 2),
3965 ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) {
3966 device_printf(dev, "%s: failed\n", __func__);
3967 return -1;
3968 }
3969
3970 stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox;
3971 //qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t));
3972
3973 err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status);
3974
3975 if (err) {
3976 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3977 }
3978
3979 return 0;
3980 }
3981
3982 static int
qla_query_fw_dcbx_caps(qla_host_t * ha)3983 qla_query_fw_dcbx_caps(qla_host_t *ha)
3984 {
3985 device_t dev;
3986 q80_query_fw_dcbx_caps_t *fw_dcbx;
3987 q80_query_fw_dcbx_caps_rsp_t *fw_dcbx_rsp;
3988 uint32_t err;
3989
3990 dev = ha->pci_dev;
3991
3992 fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox;
3993 bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t));
3994
3995 fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS;
3996 fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2);
3997 fw_dcbx->count_version |= Q8_MBX_CMD_VERSION;
3998
3999 ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t));
4000 if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx,
4001 (sizeof (q80_query_fw_dcbx_caps_t) >> 2),
4002 ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) {
4003 device_printf(dev, "%s: failed\n", __func__);
4004 return -1;
4005 }
4006
4007 fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox;
4008 ql_dump_buf8(ha, __func__, fw_dcbx_rsp,
4009 sizeof (q80_query_fw_dcbx_caps_rsp_t));
4010
4011 err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status);
4012
4013 if (err) {
4014 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4015 }
4016
4017 return 0;
4018 }
4019
4020 static int
qla_idc_ack(qla_host_t * ha,uint32_t aen_mb1,uint32_t aen_mb2,uint32_t aen_mb3,uint32_t aen_mb4)4021 qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2,
4022 uint32_t aen_mb3, uint32_t aen_mb4)
4023 {
4024 device_t dev;
4025 q80_idc_ack_t *idc_ack;
4026 q80_idc_ack_rsp_t *idc_ack_rsp;
4027 uint32_t err;
4028 int count = 300;
4029
4030 dev = ha->pci_dev;
4031
4032 idc_ack = (q80_idc_ack_t *)ha->hw.mbox;
4033 bzero(idc_ack, sizeof(q80_idc_ack_t));
4034
4035 idc_ack->opcode = Q8_MBX_IDC_ACK;
4036 idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2);
4037 idc_ack->count_version |= Q8_MBX_CMD_VERSION;
4038
4039 idc_ack->aen_mb1 = aen_mb1;
4040 idc_ack->aen_mb2 = aen_mb2;
4041 idc_ack->aen_mb3 = aen_mb3;
4042 idc_ack->aen_mb4 = aen_mb4;
4043
4044 ha->hw.imd_compl= 0;
4045
4046 if (qla_mbx_cmd(ha, (uint32_t *)idc_ack,
4047 (sizeof (q80_idc_ack_t) >> 2),
4048 ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) {
4049 device_printf(dev, "%s: failed\n", __func__);
4050 return -1;
4051 }
4052
4053 idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox;
4054
4055 err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status);
4056
4057 if (err) {
4058 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4059 return(-1);
4060 }
4061
4062 while (count && !ha->hw.imd_compl) {
4063 qla_mdelay(__func__, 100);
4064 count--;
4065 }
4066
4067 if (!count)
4068 return -1;
4069 else
4070 device_printf(dev, "%s: count %d\n", __func__, count);
4071
4072 return (0);
4073 }
4074
4075 static int
qla_set_port_config(qla_host_t * ha,uint32_t cfg_bits)4076 qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits)
4077 {
4078 device_t dev;
4079 q80_set_port_cfg_t *pcfg;
4080 q80_set_port_cfg_rsp_t *pfg_rsp;
4081 uint32_t err;
4082 int count = 300;
4083
4084 dev = ha->pci_dev;
4085
4086 pcfg = (q80_set_port_cfg_t *)ha->hw.mbox;
4087 bzero(pcfg, sizeof(q80_set_port_cfg_t));
4088
4089 pcfg->opcode = Q8_MBX_SET_PORT_CONFIG;
4090 pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2);
4091 pcfg->count_version |= Q8_MBX_CMD_VERSION;
4092
4093 pcfg->cfg_bits = cfg_bits;
4094
4095 device_printf(dev, "%s: cfg_bits"
4096 " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
4097 " [0x%x, 0x%x, 0x%x]\n", __func__,
4098 ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
4099 ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
4100 ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0));
4101
4102 ha->hw.imd_compl= 0;
4103
4104 if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
4105 (sizeof (q80_set_port_cfg_t) >> 2),
4106 ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) {
4107 device_printf(dev, "%s: failed\n", __func__);
4108 return -1;
4109 }
4110
4111 pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox;
4112
4113 err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status);
4114
4115 if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) {
4116 while (count && !ha->hw.imd_compl) {
4117 qla_mdelay(__func__, 100);
4118 count--;
4119 }
4120 if (count) {
4121 device_printf(dev, "%s: count %d\n", __func__, count);
4122
4123 err = 0;
4124 }
4125 }
4126
4127 if (err) {
4128 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4129 return(-1);
4130 }
4131
4132 return (0);
4133 }
4134
4135 static int
qla_get_minidump_tmplt_size(qla_host_t * ha,uint32_t * size)4136 qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size)
4137 {
4138 uint32_t err;
4139 device_t dev = ha->pci_dev;
4140 q80_config_md_templ_size_t *md_size;
4141 q80_config_md_templ_size_rsp_t *md_size_rsp;
4142
4143 #ifndef QL_LDFLASH_FW
4144
4145 ql_minidump_template_hdr_t *hdr;
4146
4147 hdr = (ql_minidump_template_hdr_t *)ql83xx_minidump;
4148 *size = hdr->size_of_template;
4149 return (0);
4150
4151 #endif /* #ifdef QL_LDFLASH_FW */
4152
4153 md_size = (q80_config_md_templ_size_t *) ha->hw.mbox;
4154 bzero(md_size, sizeof(q80_config_md_templ_size_t));
4155
4156 md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE;
4157 md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2);
4158 md_size->count_version |= Q8_MBX_CMD_VERSION;
4159
4160 if (qla_mbx_cmd(ha, (uint32_t *) md_size,
4161 (sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox,
4162 (sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) {
4163 device_printf(dev, "%s: failed\n", __func__);
4164
4165 return (-1);
4166 }
4167
4168 md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox;
4169
4170 err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status);
4171
4172 if (err) {
4173 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4174 return(-1);
4175 }
4176
4177 *size = md_size_rsp->templ_size;
4178
4179 return (0);
4180 }
4181
4182 static int
qla_get_port_config(qla_host_t * ha,uint32_t * cfg_bits)4183 qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits)
4184 {
4185 device_t dev;
4186 q80_get_port_cfg_t *pcfg;
4187 q80_get_port_cfg_rsp_t *pcfg_rsp;
4188 uint32_t err;
4189
4190 dev = ha->pci_dev;
4191
4192 pcfg = (q80_get_port_cfg_t *)ha->hw.mbox;
4193 bzero(pcfg, sizeof(q80_get_port_cfg_t));
4194
4195 pcfg->opcode = Q8_MBX_GET_PORT_CONFIG;
4196 pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2);
4197 pcfg->count_version |= Q8_MBX_CMD_VERSION;
4198
4199 if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
4200 (sizeof (q80_get_port_cfg_t) >> 2),
4201 ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) {
4202 device_printf(dev, "%s: failed\n", __func__);
4203 return -1;
4204 }
4205
4206 pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox;
4207
4208 err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status);
4209
4210 if (err) {
4211 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4212 return(-1);
4213 }
4214
4215 device_printf(dev, "%s: [cfg_bits, port type]"
4216 " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
4217 " [0x%x, 0x%x, 0x%x]\n", __func__,
4218 pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type,
4219 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
4220 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
4221 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)
4222 );
4223
4224 *cfg_bits = pcfg_rsp->cfg_bits;
4225
4226 return (0);
4227 }
4228
4229 int
ql_iscsi_pdu(qla_host_t * ha,struct mbuf * mp)4230 ql_iscsi_pdu(qla_host_t *ha, struct mbuf *mp)
4231 {
4232 struct ether_vlan_header *eh;
4233 uint16_t etype;
4234 struct ip *ip = NULL;
4235 struct ip6_hdr *ip6 = NULL;
4236 struct tcphdr *th = NULL;
4237 uint32_t hdrlen;
4238 uint32_t offset;
4239 uint8_t buf[sizeof(struct ip6_hdr)];
4240
4241 eh = mtod(mp, struct ether_vlan_header *);
4242
4243 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
4244 hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
4245 etype = ntohs(eh->evl_proto);
4246 } else {
4247 hdrlen = ETHER_HDR_LEN;
4248 etype = ntohs(eh->evl_encap_proto);
4249 }
4250
4251 if (etype == ETHERTYPE_IP) {
4252 offset = (hdrlen + sizeof (struct ip));
4253
4254 if (mp->m_len >= offset) {
4255 ip = (struct ip *)(mp->m_data + hdrlen);
4256 } else {
4257 m_copydata(mp, hdrlen, sizeof (struct ip), buf);
4258 ip = (struct ip *)buf;
4259 }
4260
4261 if (ip->ip_p == IPPROTO_TCP) {
4262 hdrlen += ip->ip_hl << 2;
4263 offset = hdrlen + 4;
4264
4265 if (mp->m_len >= offset) {
4266 th = (struct tcphdr *)(mp->m_data + hdrlen);
4267 } else {
4268 m_copydata(mp, hdrlen, 4, buf);
4269 th = (struct tcphdr *)buf;
4270 }
4271 }
4272
4273 } else if (etype == ETHERTYPE_IPV6) {
4274 offset = (hdrlen + sizeof (struct ip6_hdr));
4275
4276 if (mp->m_len >= offset) {
4277 ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen);
4278 } else {
4279 m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf);
4280 ip6 = (struct ip6_hdr *)buf;
4281 }
4282
4283 if (ip6->ip6_nxt == IPPROTO_TCP) {
4284 hdrlen += sizeof(struct ip6_hdr);
4285 offset = hdrlen + 4;
4286
4287 if (mp->m_len >= offset) {
4288 th = (struct tcphdr *)(mp->m_data + hdrlen);
4289 } else {
4290 m_copydata(mp, hdrlen, 4, buf);
4291 th = (struct tcphdr *)buf;
4292 }
4293 }
4294 }
4295
4296 if (th != NULL) {
4297 if ((th->th_sport == htons(3260)) ||
4298 (th->th_dport == htons(3260)))
4299 return 0;
4300 }
4301 return (-1);
4302 }
4303
4304 void
qla_hw_async_event(qla_host_t * ha)4305 qla_hw_async_event(qla_host_t *ha)
4306 {
4307 switch (ha->hw.aen_mb0) {
4308 case 0x8101:
4309 (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2,
4310 ha->hw.aen_mb3, ha->hw.aen_mb4);
4311
4312 break;
4313
4314 default:
4315 break;
4316 }
4317
4318 return;
4319 }
4320
4321 #ifdef QL_LDFLASH_FW
4322 static int
ql_get_minidump_template(qla_host_t * ha)4323 ql_get_minidump_template(qla_host_t *ha)
4324 {
4325 uint32_t err;
4326 device_t dev = ha->pci_dev;
4327 q80_config_md_templ_cmd_t *md_templ;
4328 q80_config_md_templ_cmd_rsp_t *md_templ_rsp;
4329
4330 md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox;
4331 bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t)));
4332
4333 md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT;
4334 md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2);
4335 md_templ->count_version |= Q8_MBX_CMD_VERSION;
4336
4337 md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr;
4338 md_templ->buff_size = ha->hw.dma_buf.minidump.size;
4339
4340 if (qla_mbx_cmd(ha, (uint32_t *) md_templ,
4341 (sizeof(q80_config_md_templ_cmd_t) >> 2),
4342 ha->hw.mbox,
4343 (sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) {
4344 device_printf(dev, "%s: failed\n", __func__);
4345
4346 return (-1);
4347 }
4348
4349 md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox;
4350
4351 err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status);
4352
4353 if (err) {
4354 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4355 return (-1);
4356 }
4357
4358 return (0);
4359
4360 }
4361 #endif /* #ifdef QL_LDFLASH_FW */
4362
4363 /*
4364 * Minidump related functionality
4365 */
4366
4367 static int ql_parse_template(qla_host_t *ha);
4368
4369 static uint32_t ql_rdcrb(qla_host_t *ha,
4370 ql_minidump_entry_rdcrb_t *crb_entry,
4371 uint32_t * data_buff);
4372
4373 static uint32_t ql_pollrd(qla_host_t *ha,
4374 ql_minidump_entry_pollrd_t *entry,
4375 uint32_t * data_buff);
4376
4377 static uint32_t ql_pollrd_modify_write(qla_host_t *ha,
4378 ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
4379 uint32_t *data_buff);
4380
4381 static uint32_t ql_L2Cache(qla_host_t *ha,
4382 ql_minidump_entry_cache_t *cacheEntry,
4383 uint32_t * data_buff);
4384
4385 static uint32_t ql_L1Cache(qla_host_t *ha,
4386 ql_minidump_entry_cache_t *cacheEntry,
4387 uint32_t *data_buff);
4388
4389 static uint32_t ql_rdocm(qla_host_t *ha,
4390 ql_minidump_entry_rdocm_t *ocmEntry,
4391 uint32_t *data_buff);
4392
4393 static uint32_t ql_rdmem(qla_host_t *ha,
4394 ql_minidump_entry_rdmem_t *mem_entry,
4395 uint32_t *data_buff);
4396
4397 static uint32_t ql_rdrom(qla_host_t *ha,
4398 ql_minidump_entry_rdrom_t *romEntry,
4399 uint32_t *data_buff);
4400
4401 static uint32_t ql_rdmux(qla_host_t *ha,
4402 ql_minidump_entry_mux_t *muxEntry,
4403 uint32_t *data_buff);
4404
4405 static uint32_t ql_rdmux2(qla_host_t *ha,
4406 ql_minidump_entry_mux2_t *muxEntry,
4407 uint32_t *data_buff);
4408
4409 static uint32_t ql_rdqueue(qla_host_t *ha,
4410 ql_minidump_entry_queue_t *queueEntry,
4411 uint32_t *data_buff);
4412
4413 static uint32_t ql_cntrl(qla_host_t *ha,
4414 ql_minidump_template_hdr_t *template_hdr,
4415 ql_minidump_entry_cntrl_t *crbEntry);
4416
4417 static uint32_t
ql_minidump_size(qla_host_t * ha)4418 ql_minidump_size(qla_host_t *ha)
4419 {
4420 uint32_t i, k;
4421 uint32_t size = 0;
4422 ql_minidump_template_hdr_t *hdr;
4423
4424 hdr = (ql_minidump_template_hdr_t *)ha->hw.dma_buf.minidump.dma_b;
4425
4426 i = 0x2;
4427
4428 for (k = 1; k < QL_DBG_CAP_SIZE_ARRAY_LEN; k++) {
4429 if (i & ha->hw.mdump_capture_mask)
4430 size += hdr->capture_size_array[k];
4431 i = i << 1;
4432 }
4433 return (size);
4434 }
4435
4436 static void
ql_free_minidump_buffer(qla_host_t * ha)4437 ql_free_minidump_buffer(qla_host_t *ha)
4438 {
4439 if (ha->hw.mdump_buffer != NULL) {
4440 free(ha->hw.mdump_buffer, M_QLA83XXBUF);
4441 ha->hw.mdump_buffer = NULL;
4442 ha->hw.mdump_buffer_size = 0;
4443 }
4444 return;
4445 }
4446
4447 static int
ql_alloc_minidump_buffer(qla_host_t * ha)4448 ql_alloc_minidump_buffer(qla_host_t *ha)
4449 {
4450 ha->hw.mdump_buffer_size = ql_minidump_size(ha);
4451
4452 if (!ha->hw.mdump_buffer_size)
4453 return (-1);
4454
4455 ha->hw.mdump_buffer = malloc(ha->hw.mdump_buffer_size, M_QLA83XXBUF,
4456 M_NOWAIT);
4457
4458 if (ha->hw.mdump_buffer == NULL)
4459 return (-1);
4460
4461 return (0);
4462 }
4463
4464 static void
ql_free_minidump_template_buffer(qla_host_t * ha)4465 ql_free_minidump_template_buffer(qla_host_t *ha)
4466 {
4467 if (ha->hw.mdump_template != NULL) {
4468 free(ha->hw.mdump_template, M_QLA83XXBUF);
4469 ha->hw.mdump_template = NULL;
4470 ha->hw.mdump_template_size = 0;
4471 }
4472 return;
4473 }
4474
4475 static int
ql_alloc_minidump_template_buffer(qla_host_t * ha)4476 ql_alloc_minidump_template_buffer(qla_host_t *ha)
4477 {
4478 ha->hw.mdump_template_size = ha->hw.dma_buf.minidump.size;
4479
4480 ha->hw.mdump_template = malloc(ha->hw.mdump_template_size,
4481 M_QLA83XXBUF, M_NOWAIT);
4482
4483 if (ha->hw.mdump_template == NULL)
4484 return (-1);
4485
4486 return (0);
4487 }
4488
4489 static int
ql_alloc_minidump_buffers(qla_host_t * ha)4490 ql_alloc_minidump_buffers(qla_host_t *ha)
4491 {
4492 int ret;
4493
4494 ret = ql_alloc_minidump_template_buffer(ha);
4495
4496 if (ret)
4497 return (ret);
4498
4499 ret = ql_alloc_minidump_buffer(ha);
4500
4501 if (ret)
4502 ql_free_minidump_template_buffer(ha);
4503
4504 return (ret);
4505 }
4506
4507 static uint32_t
ql_validate_minidump_checksum(qla_host_t * ha)4508 ql_validate_minidump_checksum(qla_host_t *ha)
4509 {
4510 uint64_t sum = 0;
4511 int count;
4512 uint32_t *template_buff;
4513
4514 count = ha->hw.dma_buf.minidump.size / sizeof (uint32_t);
4515 template_buff = ha->hw.dma_buf.minidump.dma_b;
4516
4517 while (count-- > 0) {
4518 sum += *template_buff++;
4519 }
4520
4521 while (sum >> 32) {
4522 sum = (sum & 0xFFFFFFFF) + (sum >> 32);
4523 }
4524
4525 return (~sum);
4526 }
4527
4528 int
ql_minidump_init(qla_host_t * ha)4529 ql_minidump_init(qla_host_t *ha)
4530 {
4531 int ret = 0;
4532 uint32_t template_size = 0;
4533 device_t dev = ha->pci_dev;
4534
4535 /*
4536 * Get Minidump Template Size
4537 */
4538 ret = qla_get_minidump_tmplt_size(ha, &template_size);
4539
4540 if (ret || (template_size == 0)) {
4541 device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret,
4542 template_size);
4543 return (-1);
4544 }
4545
4546 /*
4547 * Allocate Memory for Minidump Template
4548 */
4549
4550 ha->hw.dma_buf.minidump.alignment = 8;
4551 ha->hw.dma_buf.minidump.size = template_size;
4552
4553 #ifdef QL_LDFLASH_FW
4554 if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) {
4555 device_printf(dev, "%s: minidump dma alloc failed\n", __func__);
4556
4557 return (-1);
4558 }
4559 ha->hw.dma_buf.flags.minidump = 1;
4560
4561 /*
4562 * Retrieve Minidump Template
4563 */
4564 ret = ql_get_minidump_template(ha);
4565 #else
4566 ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump;
4567
4568 #endif /* #ifdef QL_LDFLASH_FW */
4569
4570 if (ret == 0) {
4571 ret = ql_validate_minidump_checksum(ha);
4572
4573 if (ret == 0) {
4574 ret = ql_alloc_minidump_buffers(ha);
4575
4576 if (ret == 0)
4577 ha->hw.mdump_init = 1;
4578 else
4579 device_printf(dev,
4580 "%s: ql_alloc_minidump_buffers"
4581 " failed\n", __func__);
4582 } else {
4583 device_printf(dev, "%s: ql_validate_minidump_checksum"
4584 " failed\n", __func__);
4585 }
4586 } else {
4587 device_printf(dev, "%s: ql_get_minidump_template failed\n",
4588 __func__);
4589 }
4590
4591 if (ret)
4592 ql_minidump_free(ha);
4593
4594 return (ret);
4595 }
4596
4597 static void
ql_minidump_free(qla_host_t * ha)4598 ql_minidump_free(qla_host_t *ha)
4599 {
4600 ha->hw.mdump_init = 0;
4601 if (ha->hw.dma_buf.flags.minidump) {
4602 ha->hw.dma_buf.flags.minidump = 0;
4603 ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump);
4604 }
4605
4606 ql_free_minidump_template_buffer(ha);
4607 ql_free_minidump_buffer(ha);
4608
4609 return;
4610 }
4611
4612 void
ql_minidump(qla_host_t * ha)4613 ql_minidump(qla_host_t *ha)
4614 {
4615 if (!ha->hw.mdump_init)
4616 return;
4617
4618 if (ha->hw.mdump_done)
4619 return;
4620 ha->hw.mdump_usec_ts = qla_get_usec_timestamp();
4621 ha->hw.mdump_start_seq_index = ql_stop_sequence(ha);
4622
4623 bzero(ha->hw.mdump_buffer, ha->hw.mdump_buffer_size);
4624 bzero(ha->hw.mdump_template, ha->hw.mdump_template_size);
4625
4626 bcopy(ha->hw.dma_buf.minidump.dma_b, ha->hw.mdump_template,
4627 ha->hw.mdump_template_size);
4628
4629 ql_parse_template(ha);
4630
4631 ql_start_sequence(ha, ha->hw.mdump_start_seq_index);
4632
4633 ha->hw.mdump_done = 1;
4634
4635 return;
4636 }
4637
4638 /*
4639 * helper routines
4640 */
4641 static void
ql_entry_err_chk(ql_minidump_entry_t * entry,uint32_t esize)4642 ql_entry_err_chk(ql_minidump_entry_t *entry, uint32_t esize)
4643 {
4644 if (esize != entry->hdr.entry_capture_size) {
4645 entry->hdr.entry_capture_size = esize;
4646 entry->hdr.driver_flags |= QL_DBG_SIZE_ERR_FLAG;
4647 }
4648 return;
4649 }
4650
4651 static int
ql_parse_template(qla_host_t * ha)4652 ql_parse_template(qla_host_t *ha)
4653 {
4654 uint32_t num_of_entries, buff_level, e_cnt, esize;
4655 uint32_t end_cnt, rv = 0;
4656 char *dump_buff, *dbuff;
4657 int sane_start = 0, sane_end = 0;
4658 ql_minidump_template_hdr_t *template_hdr;
4659 ql_minidump_entry_t *entry;
4660 uint32_t capture_mask;
4661 uint32_t dump_size;
4662
4663 /* Setup parameters */
4664 template_hdr = (ql_minidump_template_hdr_t *)ha->hw.mdump_template;
4665
4666 if (template_hdr->entry_type == TLHDR)
4667 sane_start = 1;
4668
4669 dump_buff = (char *) ha->hw.mdump_buffer;
4670
4671 num_of_entries = template_hdr->num_of_entries;
4672
4673 entry = (ql_minidump_entry_t *) ((char *)template_hdr
4674 + template_hdr->first_entry_offset );
4675
4676 template_hdr->saved_state_array[QL_OCM0_ADDR_INDX] =
4677 template_hdr->ocm_window_array[ha->pci_func];
4678 template_hdr->saved_state_array[QL_PCIE_FUNC_INDX] = ha->pci_func;
4679
4680 capture_mask = ha->hw.mdump_capture_mask;
4681 dump_size = ha->hw.mdump_buffer_size;
4682
4683 template_hdr->driver_capture_mask = capture_mask;
4684
4685 QL_DPRINT80(ha, (ha->pci_dev,
4686 "%s: sane_start = %d num_of_entries = %d "
4687 "capture_mask = 0x%x dump_size = %d \n",
4688 __func__, sane_start, num_of_entries, capture_mask, dump_size));
4689
4690 for (buff_level = 0, e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
4691 /*
4692 * If the capture_mask of the entry does not match capture mask
4693 * skip the entry after marking the driver_flags indicator.
4694 */
4695
4696 if (!(entry->hdr.entry_capture_mask & capture_mask)) {
4697 entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4698 entry = (ql_minidump_entry_t *) ((char *) entry
4699 + entry->hdr.entry_size);
4700 continue;
4701 }
4702
4703 /*
4704 * This is ONLY needed in implementations where
4705 * the capture buffer allocated is too small to capture
4706 * all of the required entries for a given capture mask.
4707 * We need to empty the buffer contents to a file
4708 * if possible, before processing the next entry
4709 * If the buff_full_flag is set, no further capture will happen
4710 * and all remaining non-control entries will be skipped.
4711 */
4712 if (entry->hdr.entry_capture_size != 0) {
4713 if ((buff_level + entry->hdr.entry_capture_size) >
4714 dump_size) {
4715 /* Try to recover by emptying buffer to file */
4716 entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4717 entry = (ql_minidump_entry_t *) ((char *) entry
4718 + entry->hdr.entry_size);
4719 continue;
4720 }
4721 }
4722
4723 /*
4724 * Decode the entry type and process it accordingly
4725 */
4726
4727 switch (entry->hdr.entry_type) {
4728 case RDNOP:
4729 break;
4730
4731 case RDEND:
4732 if (sane_end == 0) {
4733 end_cnt = e_cnt;
4734 }
4735 sane_end++;
4736 break;
4737
4738 case RDCRB:
4739 dbuff = dump_buff + buff_level;
4740 esize = ql_rdcrb(ha, (void *)entry, (void *)dbuff);
4741 ql_entry_err_chk(entry, esize);
4742 buff_level += esize;
4743 break;
4744
4745 case POLLRD:
4746 dbuff = dump_buff + buff_level;
4747 esize = ql_pollrd(ha, (void *)entry, (void *)dbuff);
4748 ql_entry_err_chk(entry, esize);
4749 buff_level += esize;
4750 break;
4751
4752 case POLLRDMWR:
4753 dbuff = dump_buff + buff_level;
4754 esize = ql_pollrd_modify_write(ha, (void *)entry,
4755 (void *)dbuff);
4756 ql_entry_err_chk(entry, esize);
4757 buff_level += esize;
4758 break;
4759
4760 case L2ITG:
4761 case L2DTG:
4762 case L2DAT:
4763 case L2INS:
4764 dbuff = dump_buff + buff_level;
4765 esize = ql_L2Cache(ha, (void *)entry, (void *)dbuff);
4766 if (esize == -1) {
4767 entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4768 } else {
4769 ql_entry_err_chk(entry, esize);
4770 buff_level += esize;
4771 }
4772 break;
4773
4774 case L1DAT:
4775 case L1INS:
4776 dbuff = dump_buff + buff_level;
4777 esize = ql_L1Cache(ha, (void *)entry, (void *)dbuff);
4778 ql_entry_err_chk(entry, esize);
4779 buff_level += esize;
4780 break;
4781
4782 case RDOCM:
4783 dbuff = dump_buff + buff_level;
4784 esize = ql_rdocm(ha, (void *)entry, (void *)dbuff);
4785 ql_entry_err_chk(entry, esize);
4786 buff_level += esize;
4787 break;
4788
4789 case RDMEM:
4790 dbuff = dump_buff + buff_level;
4791 esize = ql_rdmem(ha, (void *)entry, (void *)dbuff);
4792 ql_entry_err_chk(entry, esize);
4793 buff_level += esize;
4794 break;
4795
4796 case BOARD:
4797 case RDROM:
4798 dbuff = dump_buff + buff_level;
4799 esize = ql_rdrom(ha, (void *)entry, (void *)dbuff);
4800 ql_entry_err_chk(entry, esize);
4801 buff_level += esize;
4802 break;
4803
4804 case RDMUX:
4805 dbuff = dump_buff + buff_level;
4806 esize = ql_rdmux(ha, (void *)entry, (void *)dbuff);
4807 ql_entry_err_chk(entry, esize);
4808 buff_level += esize;
4809 break;
4810
4811 case RDMUX2:
4812 dbuff = dump_buff + buff_level;
4813 esize = ql_rdmux2(ha, (void *)entry, (void *)dbuff);
4814 ql_entry_err_chk(entry, esize);
4815 buff_level += esize;
4816 break;
4817
4818 case QUEUE:
4819 dbuff = dump_buff + buff_level;
4820 esize = ql_rdqueue(ha, (void *)entry, (void *)dbuff);
4821 ql_entry_err_chk(entry, esize);
4822 buff_level += esize;
4823 break;
4824
4825 case CNTRL:
4826 if ((rv = ql_cntrl(ha, template_hdr, (void *)entry))) {
4827 entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4828 }
4829 break;
4830 default:
4831 entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
4832 break;
4833 }
4834 /* next entry in the template */
4835 entry = (ql_minidump_entry_t *) ((char *) entry
4836 + entry->hdr.entry_size);
4837 }
4838
4839 if (!sane_start || (sane_end > 1)) {
4840 device_printf(ha->pci_dev,
4841 "\n%s: Template configuration error. Check Template\n",
4842 __func__);
4843 }
4844
4845 QL_DPRINT80(ha, (ha->pci_dev, "%s: Minidump num of entries = %d\n",
4846 __func__, template_hdr->num_of_entries));
4847
4848 return 0;
4849 }
4850
4851 /*
4852 * Read CRB operation.
4853 */
4854 static uint32_t
ql_rdcrb(qla_host_t * ha,ql_minidump_entry_rdcrb_t * crb_entry,uint32_t * data_buff)4855 ql_rdcrb(qla_host_t *ha, ql_minidump_entry_rdcrb_t * crb_entry,
4856 uint32_t * data_buff)
4857 {
4858 int loop_cnt;
4859 int ret;
4860 uint32_t op_count, addr, stride, value = 0;
4861
4862 addr = crb_entry->addr;
4863 op_count = crb_entry->op_count;
4864 stride = crb_entry->addr_stride;
4865
4866 for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
4867 ret = ql_rdwr_indreg32(ha, addr, &value, 1);
4868
4869 if (ret)
4870 return (0);
4871
4872 *data_buff++ = addr;
4873 *data_buff++ = value;
4874 addr = addr + stride;
4875 }
4876
4877 /*
4878 * for testing purpose we return amount of data written
4879 */
4880 return (op_count * (2 * sizeof(uint32_t)));
4881 }
4882
4883 /*
4884 * Handle L2 Cache.
4885 */
4886
4887 static uint32_t
ql_L2Cache(qla_host_t * ha,ql_minidump_entry_cache_t * cacheEntry,uint32_t * data_buff)4888 ql_L2Cache(qla_host_t *ha, ql_minidump_entry_cache_t *cacheEntry,
4889 uint32_t * data_buff)
4890 {
4891 int i, k;
4892 int loop_cnt;
4893 int ret;
4894
4895 uint32_t read_value;
4896 uint32_t addr, read_addr, cntrl_addr, tag_reg_addr, cntl_value_w;
4897 uint32_t tag_value, read_cnt;
4898 volatile uint8_t cntl_value_r;
4899 long timeout;
4900 uint32_t data;
4901
4902 loop_cnt = cacheEntry->op_count;
4903
4904 read_addr = cacheEntry->read_addr;
4905 cntrl_addr = cacheEntry->control_addr;
4906 cntl_value_w = (uint32_t) cacheEntry->write_value;
4907
4908 tag_reg_addr = cacheEntry->tag_reg_addr;
4909
4910 tag_value = cacheEntry->init_tag_value;
4911 read_cnt = cacheEntry->read_addr_cnt;
4912
4913 for (i = 0; i < loop_cnt; i++) {
4914 ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
4915 if (ret)
4916 return (0);
4917
4918 if (cacheEntry->write_value != 0) {
4919
4920 ret = ql_rdwr_indreg32(ha, cntrl_addr,
4921 &cntl_value_w, 0);
4922 if (ret)
4923 return (0);
4924 }
4925
4926 if (cacheEntry->poll_mask != 0) {
4927
4928 timeout = cacheEntry->poll_wait;
4929
4930 ret = ql_rdwr_indreg32(ha, cntrl_addr, &data, 1);
4931 if (ret)
4932 return (0);
4933
4934 cntl_value_r = (uint8_t)data;
4935
4936 while ((cntl_value_r & cacheEntry->poll_mask) != 0) {
4937 if (timeout) {
4938 qla_mdelay(__func__, 1);
4939 timeout--;
4940 } else
4941 break;
4942
4943 ret = ql_rdwr_indreg32(ha, cntrl_addr,
4944 &data, 1);
4945 if (ret)
4946 return (0);
4947
4948 cntl_value_r = (uint8_t)data;
4949 }
4950 if (!timeout) {
4951 /* Report timeout error.
4952 * core dump capture failed
4953 * Skip remaining entries.
4954 * Write buffer out to file
4955 * Use driver specific fields in template header
4956 * to report this error.
4957 */
4958 return (-1);
4959 }
4960 }
4961
4962 addr = read_addr;
4963 for (k = 0; k < read_cnt; k++) {
4964 ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
4965 if (ret)
4966 return (0);
4967
4968 *data_buff++ = read_value;
4969 addr += cacheEntry->read_addr_stride;
4970 }
4971
4972 tag_value += cacheEntry->tag_value_stride;
4973 }
4974
4975 return (read_cnt * loop_cnt * sizeof(uint32_t));
4976 }
4977
4978 /*
4979 * Handle L1 Cache.
4980 */
4981
4982 static uint32_t
ql_L1Cache(qla_host_t * ha,ql_minidump_entry_cache_t * cacheEntry,uint32_t * data_buff)4983 ql_L1Cache(qla_host_t *ha,
4984 ql_minidump_entry_cache_t *cacheEntry,
4985 uint32_t *data_buff)
4986 {
4987 int ret;
4988 int i, k;
4989 int loop_cnt;
4990
4991 uint32_t read_value;
4992 uint32_t addr, read_addr, cntrl_addr, tag_reg_addr;
4993 uint32_t tag_value, read_cnt;
4994 uint32_t cntl_value_w;
4995
4996 loop_cnt = cacheEntry->op_count;
4997
4998 read_addr = cacheEntry->read_addr;
4999 cntrl_addr = cacheEntry->control_addr;
5000 cntl_value_w = (uint32_t) cacheEntry->write_value;
5001
5002 tag_reg_addr = cacheEntry->tag_reg_addr;
5003
5004 tag_value = cacheEntry->init_tag_value;
5005 read_cnt = cacheEntry->read_addr_cnt;
5006
5007 for (i = 0; i < loop_cnt; i++) {
5008 ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
5009 if (ret)
5010 return (0);
5011
5012 ret = ql_rdwr_indreg32(ha, cntrl_addr, &cntl_value_w, 0);
5013 if (ret)
5014 return (0);
5015
5016 addr = read_addr;
5017 for (k = 0; k < read_cnt; k++) {
5018 ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
5019 if (ret)
5020 return (0);
5021
5022 *data_buff++ = read_value;
5023 addr += cacheEntry->read_addr_stride;
5024 }
5025
5026 tag_value += cacheEntry->tag_value_stride;
5027 }
5028
5029 return (read_cnt * loop_cnt * sizeof(uint32_t));
5030 }
5031
5032 /*
5033 * Reading OCM memory
5034 */
5035
5036 static uint32_t
ql_rdocm(qla_host_t * ha,ql_minidump_entry_rdocm_t * ocmEntry,uint32_t * data_buff)5037 ql_rdocm(qla_host_t *ha,
5038 ql_minidump_entry_rdocm_t *ocmEntry,
5039 uint32_t *data_buff)
5040 {
5041 int i, loop_cnt;
5042 volatile uint32_t addr;
5043 volatile uint32_t value;
5044
5045 addr = ocmEntry->read_addr;
5046 loop_cnt = ocmEntry->op_count;
5047
5048 for (i = 0; i < loop_cnt; i++) {
5049 value = READ_REG32(ha, addr);
5050 *data_buff++ = value;
5051 addr += ocmEntry->read_addr_stride;
5052 }
5053 return (loop_cnt * sizeof(value));
5054 }
5055
5056 /*
5057 * Read memory
5058 */
5059
5060 static uint32_t
ql_rdmem(qla_host_t * ha,ql_minidump_entry_rdmem_t * mem_entry,uint32_t * data_buff)5061 ql_rdmem(qla_host_t *ha,
5062 ql_minidump_entry_rdmem_t *mem_entry,
5063 uint32_t *data_buff)
5064 {
5065 int ret;
5066 int i, loop_cnt;
5067 volatile uint32_t addr;
5068 q80_offchip_mem_val_t val;
5069
5070 addr = mem_entry->read_addr;
5071
5072 /* size in bytes / 16 */
5073 loop_cnt = mem_entry->read_data_size / (sizeof(uint32_t) * 4);
5074
5075 for (i = 0; i < loop_cnt; i++) {
5076 ret = ql_rdwr_offchip_mem(ha, (addr & 0x0ffffffff), &val, 1);
5077 if (ret)
5078 return (0);
5079
5080 *data_buff++ = val.data_lo;
5081 *data_buff++ = val.data_hi;
5082 *data_buff++ = val.data_ulo;
5083 *data_buff++ = val.data_uhi;
5084
5085 addr += (sizeof(uint32_t) * 4);
5086 }
5087
5088 return (loop_cnt * (sizeof(uint32_t) * 4));
5089 }
5090
5091 /*
5092 * Read Rom
5093 */
5094
5095 static uint32_t
ql_rdrom(qla_host_t * ha,ql_minidump_entry_rdrom_t * romEntry,uint32_t * data_buff)5096 ql_rdrom(qla_host_t *ha,
5097 ql_minidump_entry_rdrom_t *romEntry,
5098 uint32_t *data_buff)
5099 {
5100 int ret;
5101 int i, loop_cnt;
5102 uint32_t addr;
5103 uint32_t value;
5104
5105 addr = romEntry->read_addr;
5106 loop_cnt = romEntry->read_data_size; /* This is size in bytes */
5107 loop_cnt /= sizeof(value);
5108
5109 for (i = 0; i < loop_cnt; i++) {
5110 ret = ql_rd_flash32(ha, addr, &value);
5111 if (ret)
5112 return (0);
5113
5114 *data_buff++ = value;
5115 addr += sizeof(value);
5116 }
5117
5118 return (loop_cnt * sizeof(value));
5119 }
5120
5121 /*
5122 * Read MUX data
5123 */
5124
5125 static uint32_t
ql_rdmux(qla_host_t * ha,ql_minidump_entry_mux_t * muxEntry,uint32_t * data_buff)5126 ql_rdmux(qla_host_t *ha,
5127 ql_minidump_entry_mux_t *muxEntry,
5128 uint32_t *data_buff)
5129 {
5130 int ret;
5131 int loop_cnt;
5132 uint32_t read_value, sel_value;
5133 uint32_t read_addr, select_addr;
5134
5135 select_addr = muxEntry->select_addr;
5136 sel_value = muxEntry->select_value;
5137 read_addr = muxEntry->read_addr;
5138
5139 for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
5140 ret = ql_rdwr_indreg32(ha, select_addr, &sel_value, 0);
5141 if (ret)
5142 return (0);
5143
5144 ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
5145 if (ret)
5146 return (0);
5147
5148 *data_buff++ = sel_value;
5149 *data_buff++ = read_value;
5150
5151 sel_value += muxEntry->select_value_stride;
5152 }
5153
5154 return (loop_cnt * (2 * sizeof(uint32_t)));
5155 }
5156
5157 static uint32_t
ql_rdmux2(qla_host_t * ha,ql_minidump_entry_mux2_t * muxEntry,uint32_t * data_buff)5158 ql_rdmux2(qla_host_t *ha,
5159 ql_minidump_entry_mux2_t *muxEntry,
5160 uint32_t *data_buff)
5161 {
5162 int ret;
5163 int loop_cnt;
5164
5165 uint32_t select_addr_1, select_addr_2;
5166 uint32_t select_value_1, select_value_2;
5167 uint32_t select_value_count, select_value_mask;
5168 uint32_t read_addr, read_value;
5169
5170 select_addr_1 = muxEntry->select_addr_1;
5171 select_addr_2 = muxEntry->select_addr_2;
5172 select_value_1 = muxEntry->select_value_1;
5173 select_value_2 = muxEntry->select_value_2;
5174 select_value_count = muxEntry->select_value_count;
5175 select_value_mask = muxEntry->select_value_mask;
5176
5177 read_addr = muxEntry->read_addr;
5178
5179 for (loop_cnt = 0; loop_cnt < muxEntry->select_value_count;
5180 loop_cnt++) {
5181 uint32_t temp_sel_val;
5182
5183 ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_1, 0);
5184 if (ret)
5185 return (0);
5186
5187 temp_sel_val = select_value_1 & select_value_mask;
5188
5189 ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
5190 if (ret)
5191 return (0);
5192
5193 ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
5194 if (ret)
5195 return (0);
5196
5197 *data_buff++ = temp_sel_val;
5198 *data_buff++ = read_value;
5199
5200 ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_2, 0);
5201 if (ret)
5202 return (0);
5203
5204 temp_sel_val = select_value_2 & select_value_mask;
5205
5206 ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
5207 if (ret)
5208 return (0);
5209
5210 ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
5211 if (ret)
5212 return (0);
5213
5214 *data_buff++ = temp_sel_val;
5215 *data_buff++ = read_value;
5216
5217 select_value_1 += muxEntry->select_value_stride;
5218 select_value_2 += muxEntry->select_value_stride;
5219 }
5220
5221 return (loop_cnt * (4 * sizeof(uint32_t)));
5222 }
5223
5224 /*
5225 * Handling Queue State Reads.
5226 */
5227
5228 static uint32_t
ql_rdqueue(qla_host_t * ha,ql_minidump_entry_queue_t * queueEntry,uint32_t * data_buff)5229 ql_rdqueue(qla_host_t *ha,
5230 ql_minidump_entry_queue_t *queueEntry,
5231 uint32_t *data_buff)
5232 {
5233 int ret;
5234 int loop_cnt, k;
5235 uint32_t read_value;
5236 uint32_t read_addr, read_stride, select_addr;
5237 uint32_t queue_id, read_cnt;
5238
5239 read_cnt = queueEntry->read_addr_cnt;
5240 read_stride = queueEntry->read_addr_stride;
5241 select_addr = queueEntry->select_addr;
5242
5243 for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
5244 loop_cnt++) {
5245 ret = ql_rdwr_indreg32(ha, select_addr, &queue_id, 0);
5246 if (ret)
5247 return (0);
5248
5249 read_addr = queueEntry->read_addr;
5250
5251 for (k = 0; k < read_cnt; k++) {
5252 ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
5253 if (ret)
5254 return (0);
5255
5256 *data_buff++ = read_value;
5257 read_addr += read_stride;
5258 }
5259
5260 queue_id += queueEntry->queue_id_stride;
5261 }
5262
5263 return (loop_cnt * (read_cnt * sizeof(uint32_t)));
5264 }
5265
5266 /*
5267 * Handling control entries.
5268 */
5269
5270 static uint32_t
ql_cntrl(qla_host_t * ha,ql_minidump_template_hdr_t * template_hdr,ql_minidump_entry_cntrl_t * crbEntry)5271 ql_cntrl(qla_host_t *ha,
5272 ql_minidump_template_hdr_t *template_hdr,
5273 ql_minidump_entry_cntrl_t *crbEntry)
5274 {
5275 int ret;
5276 int count;
5277 uint32_t opcode, read_value, addr, entry_addr;
5278 long timeout;
5279
5280 entry_addr = crbEntry->addr;
5281
5282 for (count = 0; count < crbEntry->op_count; count++) {
5283 opcode = crbEntry->opcode;
5284
5285 if (opcode & QL_DBG_OPCODE_WR) {
5286 ret = ql_rdwr_indreg32(ha, entry_addr,
5287 &crbEntry->value_1, 0);
5288 if (ret)
5289 return (0);
5290
5291 opcode &= ~QL_DBG_OPCODE_WR;
5292 }
5293
5294 if (opcode & QL_DBG_OPCODE_RW) {
5295 ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
5296 if (ret)
5297 return (0);
5298
5299 ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
5300 if (ret)
5301 return (0);
5302
5303 opcode &= ~QL_DBG_OPCODE_RW;
5304 }
5305
5306 if (opcode & QL_DBG_OPCODE_AND) {
5307 ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
5308 if (ret)
5309 return (0);
5310
5311 read_value &= crbEntry->value_2;
5312 opcode &= ~QL_DBG_OPCODE_AND;
5313
5314 if (opcode & QL_DBG_OPCODE_OR) {
5315 read_value |= crbEntry->value_3;
5316 opcode &= ~QL_DBG_OPCODE_OR;
5317 }
5318
5319 ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
5320 if (ret)
5321 return (0);
5322 }
5323
5324 if (opcode & QL_DBG_OPCODE_OR) {
5325 ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
5326 if (ret)
5327 return (0);
5328
5329 read_value |= crbEntry->value_3;
5330
5331 ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
5332 if (ret)
5333 return (0);
5334
5335 opcode &= ~QL_DBG_OPCODE_OR;
5336 }
5337
5338 if (opcode & QL_DBG_OPCODE_POLL) {
5339 opcode &= ~QL_DBG_OPCODE_POLL;
5340 timeout = crbEntry->poll_timeout;
5341 addr = entry_addr;
5342
5343 ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
5344 if (ret)
5345 return (0);
5346
5347 while ((read_value & crbEntry->value_2)
5348 != crbEntry->value_1) {
5349 if (timeout) {
5350 qla_mdelay(__func__, 1);
5351 timeout--;
5352 } else
5353 break;
5354
5355 ret = ql_rdwr_indreg32(ha, addr,
5356 &read_value, 1);
5357 if (ret)
5358 return (0);
5359 }
5360
5361 if (!timeout) {
5362 /*
5363 * Report timeout error.
5364 * core dump capture failed
5365 * Skip remaining entries.
5366 * Write buffer out to file
5367 * Use driver specific fields in template header
5368 * to report this error.
5369 */
5370 return (-1);
5371 }
5372 }
5373
5374 if (opcode & QL_DBG_OPCODE_RDSTATE) {
5375 /*
5376 * decide which address to use.
5377 */
5378 if (crbEntry->state_index_a) {
5379 addr = template_hdr->saved_state_array[
5380 crbEntry-> state_index_a];
5381 } else {
5382 addr = entry_addr;
5383 }
5384
5385 ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
5386 if (ret)
5387 return (0);
5388
5389 template_hdr->saved_state_array[crbEntry->state_index_v]
5390 = read_value;
5391 opcode &= ~QL_DBG_OPCODE_RDSTATE;
5392 }
5393
5394 if (opcode & QL_DBG_OPCODE_WRSTATE) {
5395 /*
5396 * decide which value to use.
5397 */
5398 if (crbEntry->state_index_v) {
5399 read_value = template_hdr->saved_state_array[
5400 crbEntry->state_index_v];
5401 } else {
5402 read_value = crbEntry->value_1;
5403 }
5404 /*
5405 * decide which address to use.
5406 */
5407 if (crbEntry->state_index_a) {
5408 addr = template_hdr->saved_state_array[
5409 crbEntry-> state_index_a];
5410 } else {
5411 addr = entry_addr;
5412 }
5413
5414 ret = ql_rdwr_indreg32(ha, addr, &read_value, 0);
5415 if (ret)
5416 return (0);
5417
5418 opcode &= ~QL_DBG_OPCODE_WRSTATE;
5419 }
5420
5421 if (opcode & QL_DBG_OPCODE_MDSTATE) {
5422 /* Read value from saved state using index */
5423 read_value = template_hdr->saved_state_array[
5424 crbEntry->state_index_v];
5425
5426 read_value <<= crbEntry->shl; /*Shift left operation */
5427 read_value >>= crbEntry->shr; /*Shift right operation */
5428
5429 if (crbEntry->value_2) {
5430 /* check if AND mask is provided */
5431 read_value &= crbEntry->value_2;
5432 }
5433
5434 read_value |= crbEntry->value_3; /* OR operation */
5435 read_value += crbEntry->value_1; /* increment op */
5436
5437 /* Write value back to state area. */
5438
5439 template_hdr->saved_state_array[crbEntry->state_index_v]
5440 = read_value;
5441 opcode &= ~QL_DBG_OPCODE_MDSTATE;
5442 }
5443
5444 entry_addr += crbEntry->addr_stride;
5445 }
5446
5447 return (0);
5448 }
5449
5450 /*
5451 * Handling rd poll entry.
5452 */
5453
5454 static uint32_t
ql_pollrd(qla_host_t * ha,ql_minidump_entry_pollrd_t * entry,uint32_t * data_buff)5455 ql_pollrd(qla_host_t *ha, ql_minidump_entry_pollrd_t *entry,
5456 uint32_t *data_buff)
5457 {
5458 int ret;
5459 int loop_cnt;
5460 uint32_t op_count, select_addr, select_value_stride, select_value;
5461 uint32_t read_addr, poll, mask, data_size, data;
5462 uint32_t wait_count = 0;
5463
5464 select_addr = entry->select_addr;
5465 read_addr = entry->read_addr;
5466 select_value = entry->select_value;
5467 select_value_stride = entry->select_value_stride;
5468 op_count = entry->op_count;
5469 poll = entry->poll;
5470 mask = entry->mask;
5471 data_size = entry->data_size;
5472
5473 for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
5474 ret = ql_rdwr_indreg32(ha, select_addr, &select_value, 0);
5475 if (ret)
5476 return (0);
5477
5478 wait_count = 0;
5479
5480 while (wait_count < poll) {
5481 uint32_t temp;
5482
5483 ret = ql_rdwr_indreg32(ha, select_addr, &temp, 1);
5484 if (ret)
5485 return (0);
5486
5487 if ( (temp & mask) != 0 ) {
5488 break;
5489 }
5490 wait_count++;
5491 }
5492
5493 if (wait_count == poll) {
5494 device_printf(ha->pci_dev,
5495 "%s: Error in processing entry\n", __func__);
5496 device_printf(ha->pci_dev,
5497 "%s: wait_count <0x%x> poll <0x%x>\n",
5498 __func__, wait_count, poll);
5499 return 0;
5500 }
5501
5502 ret = ql_rdwr_indreg32(ha, read_addr, &data, 1);
5503 if (ret)
5504 return (0);
5505
5506 *data_buff++ = select_value;
5507 *data_buff++ = data;
5508 select_value = select_value + select_value_stride;
5509 }
5510
5511 /*
5512 * for testing purpose we return amount of data written
5513 */
5514 return (loop_cnt * (2 * sizeof(uint32_t)));
5515 }
5516
5517 /*
5518 * Handling rd modify write poll entry.
5519 */
5520
5521 static uint32_t
ql_pollrd_modify_write(qla_host_t * ha,ql_minidump_entry_rd_modify_wr_with_poll_t * entry,uint32_t * data_buff)5522 ql_pollrd_modify_write(qla_host_t *ha,
5523 ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
5524 uint32_t *data_buff)
5525 {
5526 int ret;
5527 uint32_t addr_1, addr_2, value_1, value_2, data;
5528 uint32_t poll, mask, data_size, modify_mask;
5529 uint32_t wait_count = 0;
5530
5531 addr_1 = entry->addr_1;
5532 addr_2 = entry->addr_2;
5533 value_1 = entry->value_1;
5534 value_2 = entry->value_2;
5535
5536 poll = entry->poll;
5537 mask = entry->mask;
5538 modify_mask = entry->modify_mask;
5539 data_size = entry->data_size;
5540
5541 ret = ql_rdwr_indreg32(ha, addr_1, &value_1, 0);
5542 if (ret)
5543 return (0);
5544
5545 wait_count = 0;
5546 while (wait_count < poll) {
5547 uint32_t temp;
5548
5549 ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
5550 if (ret)
5551 return (0);
5552
5553 if ( (temp & mask) != 0 ) {
5554 break;
5555 }
5556 wait_count++;
5557 }
5558
5559 if (wait_count == poll) {
5560 device_printf(ha->pci_dev, "%s Error in processing entry\n",
5561 __func__);
5562 } else {
5563 ret = ql_rdwr_indreg32(ha, addr_2, &data, 1);
5564 if (ret)
5565 return (0);
5566
5567 data = (data & modify_mask);
5568
5569 ret = ql_rdwr_indreg32(ha, addr_2, &data, 0);
5570 if (ret)
5571 return (0);
5572
5573 ret = ql_rdwr_indreg32(ha, addr_1, &value_2, 0);
5574 if (ret)
5575 return (0);
5576
5577 /* Poll again */
5578 wait_count = 0;
5579 while (wait_count < poll) {
5580 uint32_t temp;
5581
5582 ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
5583 if (ret)
5584 return (0);
5585
5586 if ( (temp & mask) != 0 ) {
5587 break;
5588 }
5589 wait_count++;
5590 }
5591 *data_buff++ = addr_2;
5592 *data_buff++ = data;
5593 }
5594
5595 /*
5596 * for testing purpose we return amount of data written
5597 */
5598 return (2 * sizeof(uint32_t));
5599 }
5600