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