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