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