xref: /freebsd/sys/dev/qlxgbe/ql_hw.c (revision 6b129086dcee14496517fae085b448e3edc69bc7)
1 /*
2  * Copyright (c) 2013-2014 Qlogic Corporation
3  * All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *  1. Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  *  POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * File: ql_hw.c
30  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
31  * Content: Contains Hardware dependant functions
32  */
33 
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36 
37 #include "ql_os.h"
38 #include "ql_hw.h"
39 #include "ql_def.h"
40 #include "ql_inline.h"
41 #include "ql_ver.h"
42 #include "ql_glbl.h"
43 #include "ql_dbg.h"
44 
45 /*
46  * Static Functions
47  */
48 
49 static void qla_del_rcv_cntxt(qla_host_t *ha);
50 static int qla_init_rcv_cntxt(qla_host_t *ha);
51 static void qla_del_xmt_cntxt(qla_host_t *ha);
52 static int qla_init_xmt_cntxt(qla_host_t *ha);
53 static void qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx);
54 static int qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
55 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause);
56 static int qla_config_intr_cntxt(qla_host_t *ha, uint32_t num_intrs,
57 	uint32_t create);
58 static int qla_get_nic_partition(qla_host_t *ha);
59 static int qla_config_rss(qla_host_t *ha, uint16_t cntxt_id);
60 static int qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id,
61 	int tenable);
62 static int qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode);
63 static int qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id);
64 
65 static int qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd,
66 		uint8_t *hdr);
67 static int qla_hw_add_all_mcast(qla_host_t *ha);
68 static int qla_hw_del_all_mcast(qla_host_t *ha);
69 static int qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx);
70 
71 static int qla_minidump_init(qla_host_t *ha);
72 static void qla_minidump_free(qla_host_t *ha);
73 
74 
75 static int
76 qla_sysctl_get_drvr_stats(SYSCTL_HANDLER_ARGS)
77 {
78         int err = 0, ret;
79         qla_host_t *ha;
80 	uint32_t i;
81 
82         err = sysctl_handle_int(oidp, &ret, 0, req);
83 
84         if (err || !req->newptr)
85                 return (err);
86 
87         if (ret == 1) {
88 
89                 ha = (qla_host_t *)arg1;
90 
91 		for (i = 0; i < ha->hw.num_sds_rings; i++)
92 			device_printf(ha->pci_dev,
93 				"%s: sds_ring[%d] = %p\n", __func__,i,
94 				(void *)ha->hw.sds[i].intr_count);
95 
96 		for (i = 0; i < ha->hw.num_tx_rings; i++)
97 			device_printf(ha->pci_dev,
98 				"%s: tx[%d] = %p\n", __func__,i,
99 				(void *)ha->tx_ring[i].count);
100 
101 		for (i = 0; i < ha->hw.num_rds_rings; i++)
102 			device_printf(ha->pci_dev,
103 				"%s: rds_ring[%d] = %p\n", __func__,i,
104 				(void *)ha->hw.rds[i].count);
105 
106 		device_printf(ha->pci_dev, "%s: lro_pkt_count = %p\n", __func__,
107 			(void *)ha->lro_pkt_count);
108 
109 		device_printf(ha->pci_dev, "%s: lro_bytes = %p\n", __func__,
110 			(void *)ha->lro_bytes);
111 	}
112 	return (err);
113 }
114 
115 #ifdef QL_DBG
116 
117 static void
118 qla_stop_pegs(qla_host_t *ha)
119 {
120         uint32_t val = 1;
121 
122         ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0);
123         ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0);
124         ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0);
125         ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0);
126         ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0);
127         device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__);
128 }
129 
130 static int
131 qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)
132 {
133 	int err, ret = 0;
134 	qla_host_t *ha;
135 
136 	err = sysctl_handle_int(oidp, &ret, 0, req);
137 
138 
139 	if (err || !req->newptr)
140 		return (err);
141 
142 	if (ret == 1) {
143 		ha = (qla_host_t *)arg1;
144 		(void)QLA_LOCK(ha, __func__, 0);
145 		qla_stop_pegs(ha);
146 		QLA_UNLOCK(ha, __func__);
147 	}
148 
149 	return err;
150 }
151 #endif /* #ifdef QL_DBG */
152 
153 /*
154  * Name: ql_hw_add_sysctls
155  * Function: Add P3Plus specific sysctls
156  */
157 void
158 ql_hw_add_sysctls(qla_host_t *ha)
159 {
160         device_t	dev;
161 
162         dev = ha->pci_dev;
163 
164 	ha->hw.num_sds_rings = MAX_SDS_RINGS;
165 	ha->hw.num_rds_rings = MAX_RDS_RINGS;
166 	ha->hw.num_tx_rings = NUM_TX_RINGS;
167 
168 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
169 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
170 		OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings,
171 		ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings");
172 
173         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
174                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
175                 OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings,
176 		ha->hw.num_sds_rings, "Number of Status Descriptor Rings");
177 
178         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
179                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
180                 OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings,
181 		ha->hw.num_tx_rings, "Number of Transmit Rings");
182 
183         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
184                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
185                 OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx,
186 		ha->txr_idx, "Tx Ring Used");
187 
188 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
189 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
190 		OID_AUTO, "drvr_stats", CTLTYPE_INT | CTLFLAG_RW,
191 		(void *)ha, 0,
192 		qla_sysctl_get_drvr_stats, "I", "Driver Maintained Statistics");
193 
194         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
195                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
196                 OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs,
197 		ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt");
198 
199 	ha->hw.sds_cidx_thres = 32;
200         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
201                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
202                 OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres,
203 		ha->hw.sds_cidx_thres,
204 		"Number of SDS entries to process before updating"
205 		" SDS Ring Consumer Index");
206 
207 	ha->hw.rds_pidx_thres = 32;
208         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
209                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
210                 OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres,
211 		ha->hw.rds_pidx_thres,
212 		"Number of Rcv Rings Entries to post before updating"
213 		" RDS Ring Producer Index");
214 
215 	ha->hw.min_lro_pkt_size = 512;
216 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
217 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
218 		OID_AUTO, "min_lro_pkt_size", CTLFLAG_RD, &ha->hw.min_lro_pkt_size,
219 		ha->hw.min_lro_pkt_size, "minimum packet size to trigger lro");
220 
221 	ha->hw.mdump_active = 0;
222         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
223                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
224                 OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active,
225 		ha->hw.mdump_active,
226 		"Minidump Utility is Active \n"
227 		"\t 0 = Minidump Utility is not active\n"
228 		"\t 1 = Minidump Utility is retrieved on this port\n"
229 		"\t 2 = Minidump Utility is retrieved on the other port\n");
230 
231 	ha->hw.mdump_start = 0;
232         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
233                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
234                 OID_AUTO, "minidump_start", CTLFLAG_RW,
235 		&ha->hw.mdump_start, ha->hw.mdump_start,
236 		"Minidump Utility can start minidump process");
237 #ifdef QL_DBG
238 
239         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
240                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
241                 OID_AUTO, "err_inject",
242                 CTLFLAG_RW, &ha->err_inject, ha->err_inject,
243                 "Error to be injected\n"
244                 "\t\t\t 0: No Errors\n"
245                 "\t\t\t 1: rcv: rxb struct invalid\n"
246                 "\t\t\t 2: rcv: mp == NULL\n"
247                 "\t\t\t 3: lro: rxb struct invalid\n"
248                 "\t\t\t 4: lro: mp == NULL\n"
249                 "\t\t\t 5: rcv: num handles invalid\n"
250                 "\t\t\t 6: reg: indirect reg rd_wr failure\n"
251                 "\t\t\t 7: ocm: offchip memory rd_wr failure\n"
252                 "\t\t\t 8: mbx: mailbox command failure\n"
253                 "\t\t\t 9: heartbeat failure\n"
254                 "\t\t\t A: temperature failure\n" );
255 
256 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
257                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
258                 OID_AUTO, "peg_stop", CTLTYPE_INT | CTLFLAG_RW,
259                 (void *)ha, 0,
260                 qla_sysctl_stop_pegs, "I", "Peg Stop");
261 
262 #endif /* #ifdef QL_DBG */
263 
264 }
265 
266 void
267 ql_hw_link_status(qla_host_t *ha)
268 {
269 	device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui);
270 
271 	if (ha->hw.link_up) {
272 		device_printf(ha->pci_dev, "link Up\n");
273 	} else {
274 		device_printf(ha->pci_dev, "link Down\n");
275 	}
276 
277 	if (ha->hw.flags.fduplex) {
278 		device_printf(ha->pci_dev, "Full Duplex\n");
279 	} else {
280 		device_printf(ha->pci_dev, "Half Duplex\n");
281 	}
282 
283 	if (ha->hw.flags.autoneg) {
284 		device_printf(ha->pci_dev, "Auto Negotiation Enabled\n");
285 	} else {
286 		device_printf(ha->pci_dev, "Auto Negotiation Disabled\n");
287 	}
288 
289 	switch (ha->hw.link_speed) {
290 	case 0x710:
291 		device_printf(ha->pci_dev, "link speed\t\t 10Gps\n");
292 		break;
293 
294 	case 0x3E8:
295 		device_printf(ha->pci_dev, "link speed\t\t 1Gps\n");
296 		break;
297 
298 	case 0x64:
299 		device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n");
300 		break;
301 
302 	default:
303 		device_printf(ha->pci_dev, "link speed\t\t Unknown\n");
304 		break;
305 	}
306 
307 	switch (ha->hw.module_type) {
308 
309 	case 0x01:
310 		device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n");
311 		break;
312 
313 	case 0x02:
314 		device_printf(ha->pci_dev, "Module Type 10GBase-LR\n");
315 		break;
316 
317 	case 0x03:
318 		device_printf(ha->pci_dev, "Module Type 10GBase-SR\n");
319 		break;
320 
321 	case 0x04:
322 		device_printf(ha->pci_dev,
323 			"Module Type 10GE Passive Copper(Compliant)[%d m]\n",
324 			ha->hw.cable_length);
325 		break;
326 
327 	case 0x05:
328 		device_printf(ha->pci_dev, "Module Type 10GE Active"
329 			" Limiting Copper(Compliant)[%d m]\n",
330 			ha->hw.cable_length);
331 		break;
332 
333 	case 0x06:
334 		device_printf(ha->pci_dev,
335 			"Module Type 10GE Passive Copper"
336 			" (Legacy, Best Effort)[%d m]\n",
337 			ha->hw.cable_length);
338 		break;
339 
340 	case 0x07:
341 		device_printf(ha->pci_dev, "Module Type 1000Base-SX\n");
342 		break;
343 
344 	case 0x08:
345 		device_printf(ha->pci_dev, "Module Type 1000Base-LX\n");
346 		break;
347 
348 	case 0x09:
349 		device_printf(ha->pci_dev, "Module Type 1000Base-CX\n");
350 		break;
351 
352 	case 0x0A:
353 		device_printf(ha->pci_dev, "Module Type 1000Base-T\n");
354 		break;
355 
356 	case 0x0B:
357 		device_printf(ha->pci_dev, "Module Type 1GE Passive Copper"
358 			"(Legacy, Best Effort)\n");
359 		break;
360 
361 	default:
362 		device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n",
363 			ha->hw.module_type);
364 		break;
365 	}
366 
367 	if (ha->hw.link_faults == 1)
368 		device_printf(ha->pci_dev, "SFP Power Fault\n");
369 }
370 
371 /*
372  * Name: ql_free_dma
373  * Function: Frees the DMA'able memory allocated in ql_alloc_dma()
374  */
375 void
376 ql_free_dma(qla_host_t *ha)
377 {
378 	uint32_t i;
379 
380         if (ha->hw.dma_buf.flags.sds_ring) {
381 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
382 			ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]);
383 		}
384         	ha->hw.dma_buf.flags.sds_ring = 0;
385 	}
386 
387         if (ha->hw.dma_buf.flags.rds_ring) {
388 		for (i = 0; i < ha->hw.num_rds_rings; i++) {
389 			ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]);
390 		}
391         	ha->hw.dma_buf.flags.rds_ring = 0;
392 	}
393 
394         if (ha->hw.dma_buf.flags.tx_ring) {
395 		ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring);
396         	ha->hw.dma_buf.flags.tx_ring = 0;
397 	}
398 	qla_minidump_free(ha);
399 }
400 
401 /*
402  * Name: ql_alloc_dma
403  * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts.
404  */
405 int
406 ql_alloc_dma(qla_host_t *ha)
407 {
408         device_t                dev;
409 	uint32_t		i, j, size, tx_ring_size;
410 	qla_hw_t		*hw;
411 	qla_hw_tx_cntxt_t	*tx_cntxt;
412 	uint8_t			*vaddr;
413 	bus_addr_t		paddr;
414 
415         dev = ha->pci_dev;
416 
417         QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
418 
419 	hw = &ha->hw;
420 	/*
421 	 * Allocate Transmit Ring
422 	 */
423 	tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS);
424 	size = (tx_ring_size * ha->hw.num_tx_rings);
425 
426 	hw->dma_buf.tx_ring.alignment = 8;
427 	hw->dma_buf.tx_ring.size = size + PAGE_SIZE;
428 
429         if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) {
430                 device_printf(dev, "%s: tx ring alloc failed\n", __func__);
431                 goto ql_alloc_dma_exit;
432         }
433 
434 	vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b;
435 	paddr = hw->dma_buf.tx_ring.dma_addr;
436 
437 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
438 		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
439 
440 		tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr;
441 		tx_cntxt->tx_ring_paddr = paddr;
442 
443 		vaddr += tx_ring_size;
444 		paddr += tx_ring_size;
445 	}
446 
447 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
448 		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
449 
450 		tx_cntxt->tx_cons = (uint32_t *)vaddr;
451 		tx_cntxt->tx_cons_paddr = paddr;
452 
453 		vaddr += sizeof (uint32_t);
454 		paddr += sizeof (uint32_t);
455 	}
456 
457         ha->hw.dma_buf.flags.tx_ring = 1;
458 
459 	QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n",
460 		__func__, (void *)(hw->dma_buf.tx_ring.dma_addr),
461 		hw->dma_buf.tx_ring.dma_b));
462 	/*
463 	 * Allocate Receive Descriptor Rings
464 	 */
465 
466 	for (i = 0; i < hw->num_rds_rings; i++) {
467 
468 		hw->dma_buf.rds_ring[i].alignment = 8;
469 		hw->dma_buf.rds_ring[i].size =
470 			(sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS;
471 
472 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) {
473 			device_printf(dev, "%s: rds ring[%d] alloc failed\n",
474 				__func__, i);
475 
476 			for (j = 0; j < i; j++)
477 				ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]);
478 
479 			goto ql_alloc_dma_exit;
480 		}
481 		QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n",
482 			__func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr),
483 			hw->dma_buf.rds_ring[i].dma_b));
484 	}
485 
486 	hw->dma_buf.flags.rds_ring = 1;
487 
488 	/*
489 	 * Allocate Status Descriptor Rings
490 	 */
491 
492 	for (i = 0; i < hw->num_sds_rings; i++) {
493 		hw->dma_buf.sds_ring[i].alignment = 8;
494 		hw->dma_buf.sds_ring[i].size =
495 			(sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS;
496 
497 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) {
498 			device_printf(dev, "%s: sds ring alloc failed\n",
499 				__func__);
500 
501 			for (j = 0; j < i; j++)
502 				ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]);
503 
504 			goto ql_alloc_dma_exit;
505 		}
506 		QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n",
507 			__func__, i,
508 			(void *)(hw->dma_buf.sds_ring[i].dma_addr),
509 			hw->dma_buf.sds_ring[i].dma_b));
510 	}
511 	for (i = 0; i < hw->num_sds_rings; i++) {
512 		hw->sds[i].sds_ring_base =
513 			(q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b;
514 	}
515 
516 	hw->dma_buf.flags.sds_ring = 1;
517 
518 	return 0;
519 
520 ql_alloc_dma_exit:
521 	ql_free_dma(ha);
522 	return -1;
523 }
524 
525 #define Q8_MBX_MSEC_DELAY	5000
526 
527 static int
528 qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
529 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause)
530 {
531 	uint32_t i;
532 	uint32_t data;
533 	int ret = 0;
534 
535 	if (QL_ERR_INJECT(ha, INJCT_MBX_CMD_FAILURE)) {
536 		ret = -3;
537 		ha->qla_initiate_recovery = 1;
538 		goto exit_qla_mbx_cmd;
539 	}
540 
541 	if (no_pause)
542 		i = 1000;
543 	else
544 		i = Q8_MBX_MSEC_DELAY;
545 
546 	while (i) {
547 		data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL);
548 		if (data == 0)
549 			break;
550 		if (no_pause) {
551 			DELAY(1000);
552 		} else {
553 			qla_mdelay(__func__, 1);
554 		}
555 		i--;
556 	}
557 
558 	if (i == 0) {
559 		device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n",
560 			__func__, data);
561 		ret = -1;
562 		ha->qla_initiate_recovery = 1;
563 		goto exit_qla_mbx_cmd;
564 	}
565 
566 	for (i = 0; i < n_hmbox; i++) {
567 		WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox);
568 		h_mbox++;
569 	}
570 
571 	WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1);
572 
573 
574 	i = Q8_MBX_MSEC_DELAY;
575 	while (i) {
576 		data = READ_REG32(ha, Q8_FW_MBOX_CNTRL);
577 
578 		if ((data & 0x3) == 1) {
579 			data = READ_REG32(ha, Q8_FW_MBOX0);
580 			if ((data & 0xF000) != 0x8000)
581 				break;
582 		}
583 		if (no_pause) {
584 			DELAY(1000);
585 		} else {
586 			qla_mdelay(__func__, 1);
587 		}
588 		i--;
589 	}
590 	if (i == 0) {
591 		device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n",
592 			__func__, data);
593 		ret = -2;
594 		ha->qla_initiate_recovery = 1;
595 		goto exit_qla_mbx_cmd;
596 	}
597 
598 	for (i = 0; i < n_fwmbox; i++) {
599 		*fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2)));
600 	}
601 
602 	WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0);
603 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
604 
605 exit_qla_mbx_cmd:
606 	return (ret);
607 }
608 
609 static int
610 qla_get_nic_partition(qla_host_t *ha)
611 {
612 	uint32_t *mbox, err;
613 	device_t dev = ha->pci_dev;
614 
615 	bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX));
616 
617 	mbox = ha->hw.mbox;
618 
619 	mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29);
620 
621 	if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) {
622 		device_printf(dev, "%s: failed0\n", __func__);
623 		return (-1);
624 	}
625 	err = mbox[0] >> 25;
626 
627 	if ((err != 1) && (err != 0)) {
628 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
629 		return (-1);
630 	}
631 	return 0;
632 }
633 
634 static int
635 qla_config_intr_cntxt(qla_host_t *ha, uint32_t num_intrs, uint32_t create)
636 {
637 	uint32_t i, err;
638 	device_t dev = ha->pci_dev;
639 	q80_config_intr_t *c_intr;
640 	q80_config_intr_rsp_t *c_intr_rsp;
641 
642 	c_intr = (q80_config_intr_t *)ha->hw.mbox;
643 	bzero(c_intr, (sizeof (q80_config_intr_t)));
644 
645 	c_intr->opcode = Q8_MBX_CONFIG_INTR;
646 
647 	c_intr->count_version = (sizeof (q80_config_intr_t) >> 2);
648 	c_intr->count_version |= Q8_MBX_CMD_VERSION;
649 
650 	c_intr->nentries = num_intrs;
651 
652 	for (i = 0; i < num_intrs; i++) {
653 		if (create) {
654 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE;
655 			c_intr->intr[i].msix_index = i + 1;
656 		} else {
657 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE;
658 			c_intr->intr[i].msix_index = ha->hw.intr_id[i];
659 		}
660 
661 		c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X;
662 	}
663 
664 	if (qla_mbx_cmd(ha, (uint32_t *)c_intr,
665 		(sizeof (q80_config_intr_t) >> 2),
666 		ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) {
667 		device_printf(dev, "%s: failed0\n", __func__);
668 		return (-1);
669 	}
670 
671 	c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox;
672 
673 	err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status);
674 
675 	if (err) {
676 		device_printf(dev, "%s: failed1 [0x%08x, %d]\n", __func__, err,
677 			c_intr_rsp->nentries);
678 
679 		for (i = 0; i < c_intr_rsp->nentries; i++) {
680 			device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n",
681 				__func__, i,
682 				c_intr_rsp->intr[i].status,
683 				c_intr_rsp->intr[i].intr_id,
684 				c_intr_rsp->intr[i].intr_src);
685 		}
686 
687 		return (-1);
688 	}
689 
690 	for (i = 0; ((i < num_intrs) && create); i++) {
691 		if (!c_intr_rsp->intr[i].status) {
692 			ha->hw.intr_id[i] = c_intr_rsp->intr[i].intr_id;
693 			ha->hw.intr_src[i] = c_intr_rsp->intr[i].intr_src;
694 		}
695 	}
696 
697 	return (0);
698 }
699 
700 /*
701  * Name: qla_config_rss
702  * Function: Configure RSS for the context/interface.
703  */
704 static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL,
705 			0x8030f20c77cb2da3ULL,
706 			0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
707 			0x255b0ec26d5a56daULL };
708 
709 static int
710 qla_config_rss(qla_host_t *ha, uint16_t cntxt_id)
711 {
712 	q80_config_rss_t	*c_rss;
713 	q80_config_rss_rsp_t	*c_rss_rsp;
714 	uint32_t		err, i;
715 	device_t		dev = ha->pci_dev;
716 
717 	c_rss = (q80_config_rss_t *)ha->hw.mbox;
718 	bzero(c_rss, (sizeof (q80_config_rss_t)));
719 
720 	c_rss->opcode = Q8_MBX_CONFIG_RSS;
721 
722 	c_rss->count_version = (sizeof (q80_config_rss_t) >> 2);
723 	c_rss->count_version |= Q8_MBX_CMD_VERSION;
724 
725 	c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP |
726 				Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP);
727 
728 	c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS;
729 	c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE;
730 
731 	c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK;
732 
733 	c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID;
734 	c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS;
735 
736 	c_rss->cntxt_id = cntxt_id;
737 
738 	for (i = 0; i < 5; i++) {
739 		c_rss->rss_key[i] = rss_key[i];
740 	}
741 
742 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss,
743 		(sizeof (q80_config_rss_t) >> 2),
744 		ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) {
745 		device_printf(dev, "%s: failed0\n", __func__);
746 		return (-1);
747 	}
748 	c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox;
749 
750 	err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status);
751 
752 	if (err) {
753 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
754 		return (-1);
755 	}
756 	return 0;
757 }
758 
759 static uint8_t rss_ind_default_table[Q8_RSS_IND_TBL_SIZE];
760 
761 static int
762 qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count,
763         uint16_t cntxt_id, uint8_t *ind_table)
764 {
765         q80_config_rss_ind_table_t      *c_rss_ind;
766         q80_config_rss_ind_table_rsp_t  *c_rss_ind_rsp;
767         uint32_t                        err;
768         device_t                        dev = ha->pci_dev;
769 
770 	if ((count > Q8_RSS_IND_TBL_SIZE) ||
771 		((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) {
772 		device_printf(dev, "%s: illegal count [%d, %d]\n", __func__,
773 			start_idx, count);
774 		return (-1);
775 	}
776 
777         c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox;
778         bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t));
779 
780         c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE;
781         c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2);
782         c_rss_ind->count_version |= Q8_MBX_CMD_VERSION;
783 
784 	c_rss_ind->start_idx = start_idx;
785 	c_rss_ind->end_idx = start_idx + count - 1;
786 	c_rss_ind->cntxt_id = cntxt_id;
787 	bcopy(ind_table, c_rss_ind->ind_table, count);
788 
789 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind,
790 		(sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox,
791 		(sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) {
792 		device_printf(dev, "%s: failed0\n", __func__);
793 		return (-1);
794 	}
795 
796 	c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox;
797 	err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status);
798 
799 	if (err) {
800 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
801 		return (-1);
802 	}
803 	return 0;
804 }
805 
806 /*
807  * Name: qla_config_intr_coalesce
808  * Function: Configure Interrupt Coalescing.
809  */
810 static int
811 qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable)
812 {
813 	q80_config_intr_coalesc_t	*intrc;
814 	q80_config_intr_coalesc_rsp_t	*intrc_rsp;
815 	uint32_t			err, i;
816 	device_t			dev = ha->pci_dev;
817 
818 	intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox;
819 	bzero(intrc, (sizeof (q80_config_intr_coalesc_t)));
820 
821 	intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE;
822 	intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2);
823 	intrc->count_version |= Q8_MBX_CMD_VERSION;
824 
825 	intrc->flags = Q8_MBX_INTRC_FLAGS_RCV;
826 	intrc->cntxt_id = cntxt_id;
827 
828 	intrc->max_pkts = 256;
829 	intrc->max_mswait = 3;
830 
831 	if (tenable) {
832 		intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC;
833 		intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC;
834 
835 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
836 			intrc->sds_ring_mask |= (1 << i);
837 		}
838 		intrc->ms_timeout = 1000;
839 	}
840 
841 	if (qla_mbx_cmd(ha, (uint32_t *)intrc,
842 		(sizeof (q80_config_intr_coalesc_t) >> 2),
843 		ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) {
844 		device_printf(dev, "%s: failed0\n", __func__);
845 		return (-1);
846 	}
847 	intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox;
848 
849 	err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status);
850 
851 	if (err) {
852 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
853 		return (-1);
854 	}
855 
856 	return 0;
857 }
858 
859 
860 /*
861  * Name: qla_config_mac_addr
862  * Function: binds a MAC address to the context/interface.
863  *	Can be unicast, multicast or broadcast.
864  */
865 static int
866 qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac)
867 {
868 	q80_config_mac_addr_t		*cmac;
869 	q80_config_mac_addr_rsp_t	*cmac_rsp;
870 	uint32_t			err;
871 	device_t			dev = ha->pci_dev;
872 
873 	cmac = (q80_config_mac_addr_t *)ha->hw.mbox;
874 	bzero(cmac, (sizeof (q80_config_mac_addr_t)));
875 
876 	cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR;
877 	cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2;
878 	cmac->count_version |= Q8_MBX_CMD_VERSION;
879 
880 	if (add_mac)
881 		cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR;
882 	else
883 		cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR;
884 
885 	cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS;
886 
887 	cmac->nmac_entries = 1;
888 	cmac->cntxt_id = ha->hw.rcv_cntxt_id;
889 	bcopy(mac_addr, cmac->mac_addr[0].addr, 6);
890 
891 	if (qla_mbx_cmd(ha, (uint32_t *)cmac,
892 		(sizeof (q80_config_mac_addr_t) >> 2),
893 		ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) {
894 		device_printf(dev, "%s: %s failed0\n", __func__,
895 			(add_mac ? "Add" : "Del"));
896 		return (-1);
897 	}
898 	cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox;
899 
900 	err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status);
901 
902 	if (err) {
903 		device_printf(dev, "%s: %s "
904 			"%02x:%02x:%02x:%02x:%02x:%02x failed1 [0x%08x]\n",
905 			__func__, (add_mac ? "Add" : "Del"),
906 			mac_addr[0], mac_addr[1], mac_addr[2],
907 			mac_addr[3], mac_addr[4], mac_addr[5], err);
908 		return (-1);
909 	}
910 
911 	return 0;
912 }
913 
914 
915 /*
916  * Name: qla_set_mac_rcv_mode
917  * Function: Enable/Disable AllMulticast and Promiscous Modes.
918  */
919 static int
920 qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode)
921 {
922 	q80_config_mac_rcv_mode_t	*rcv_mode;
923 	uint32_t			err;
924 	q80_config_mac_rcv_mode_rsp_t	*rcv_mode_rsp;
925 	device_t			dev = ha->pci_dev;
926 
927 	rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox;
928 	bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t)));
929 
930 	rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE;
931 	rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2;
932 	rcv_mode->count_version |= Q8_MBX_CMD_VERSION;
933 
934 	rcv_mode->mode = mode;
935 
936 	rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id;
937 
938 	if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode,
939 		(sizeof (q80_config_mac_rcv_mode_t) >> 2),
940 		ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) {
941 		device_printf(dev, "%s: failed0\n", __func__);
942 		return (-1);
943 	}
944 	rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox;
945 
946 	err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status);
947 
948 	if (err) {
949 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
950 		return (-1);
951 	}
952 
953 	return 0;
954 }
955 
956 int
957 ql_set_promisc(qla_host_t *ha)
958 {
959 	int ret;
960 
961 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE;
962 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
963 	return (ret);
964 }
965 
966 int
967 ql_set_allmulti(qla_host_t *ha)
968 {
969 	int ret;
970 
971 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE;
972 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
973 	return (ret);
974 }
975 
976 
977 /*
978  * Name: ql_set_max_mtu
979  * Function:
980  *	Sets the maximum transfer unit size for the specified rcv context.
981  */
982 int
983 ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id)
984 {
985 	device_t		dev;
986 	q80_set_max_mtu_t	*max_mtu;
987 	q80_set_max_mtu_rsp_t	*max_mtu_rsp;
988 	uint32_t		err;
989 
990 	dev = ha->pci_dev;
991 
992 	max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox;
993 	bzero(max_mtu, (sizeof (q80_set_max_mtu_t)));
994 
995 	max_mtu->opcode = Q8_MBX_SET_MAX_MTU;
996 	max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2);
997 	max_mtu->count_version |= Q8_MBX_CMD_VERSION;
998 
999 	max_mtu->cntxt_id = cntxt_id;
1000 	max_mtu->mtu = mtu;
1001 
1002         if (qla_mbx_cmd(ha, (uint32_t *)max_mtu,
1003 		(sizeof (q80_set_max_mtu_t) >> 2),
1004                 ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) {
1005                 device_printf(dev, "%s: failed\n", __func__);
1006                 return -1;
1007         }
1008 
1009 	max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox;
1010 
1011         err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status);
1012 
1013         if (err) {
1014                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1015         }
1016 
1017 	return 0;
1018 }
1019 
1020 static int
1021 qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id)
1022 {
1023 	device_t		dev;
1024 	q80_link_event_t	*lnk;
1025 	q80_link_event_rsp_t	*lnk_rsp;
1026 	uint32_t		err;
1027 
1028 	dev = ha->pci_dev;
1029 
1030 	lnk = (q80_link_event_t *)ha->hw.mbox;
1031 	bzero(lnk, (sizeof (q80_link_event_t)));
1032 
1033 	lnk->opcode = Q8_MBX_LINK_EVENT_REQ;
1034 	lnk->count_version = (sizeof (q80_link_event_t) >> 2);
1035 	lnk->count_version |= Q8_MBX_CMD_VERSION;
1036 
1037 	lnk->cntxt_id = cntxt_id;
1038 	lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC;
1039 
1040         if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2),
1041                 ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) {
1042                 device_printf(dev, "%s: failed\n", __func__);
1043                 return -1;
1044         }
1045 
1046 	lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox;
1047 
1048         err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status);
1049 
1050         if (err) {
1051                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1052         }
1053 
1054 	return 0;
1055 }
1056 
1057 static int
1058 qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id)
1059 {
1060 	device_t		dev;
1061 	q80_config_fw_lro_t	*fw_lro;
1062 	q80_config_fw_lro_rsp_t	*fw_lro_rsp;
1063 	uint32_t		err;
1064 
1065 	dev = ha->pci_dev;
1066 
1067 	fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox;
1068 	bzero(fw_lro, sizeof(q80_config_fw_lro_t));
1069 
1070 	fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO;
1071 	fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2);
1072 	fw_lro->count_version |= Q8_MBX_CMD_VERSION;
1073 
1074 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK;
1075 
1076 	fw_lro->cntxt_id = cntxt_id;
1077 
1078 	if (ha->hw.min_lro_pkt_size) {
1079 		fw_lro->flags |= Q8_MBX_FW_LRO_LOW_THRESHOLD;
1080 		fw_lro->low_threshold = ha->hw.min_lro_pkt_size;
1081 	}
1082 
1083 	if (qla_mbx_cmd(ha, (uint32_t *)fw_lro,
1084 		(sizeof (q80_config_fw_lro_t) >> 2),
1085 		ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) {
1086 		device_printf(dev, "%s: failed\n", __func__);
1087 		return -1;
1088 	}
1089 
1090 	fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox;
1091 
1092 	err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status);
1093 
1094 	if (err) {
1095 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1096 	}
1097 
1098 	return 0;
1099 }
1100 
1101 static void
1102 qla_xmt_stats(qla_host_t *ha, q80_xmt_stats_t *xstat)
1103 {
1104 	device_t dev = ha->pci_dev;
1105 
1106 	device_printf(dev, "%s: total_bytes\t\t%" PRIu64 "\n", __func__,
1107 		xstat->total_bytes);
1108 	device_printf(dev, "%s: total_pkts\t\t%" PRIu64 "\n", __func__,
1109 		xstat->total_pkts);
1110 	device_printf(dev, "%s: errors\t\t%" PRIu64 "\n", __func__,
1111 		xstat->errors);
1112 	device_printf(dev, "%s: pkts_dropped\t%" PRIu64 "\n", __func__,
1113 		xstat->pkts_dropped);
1114 	device_printf(dev, "%s: switch_pkts\t\t%" PRIu64 "\n", __func__,
1115 		xstat->switch_pkts);
1116 	device_printf(dev, "%s: num_buffers\t\t%" PRIu64 "\n", __func__,
1117 		xstat->num_buffers);
1118 }
1119 
1120 static void
1121 qla_rcv_stats(qla_host_t *ha, q80_rcv_stats_t *rstat)
1122 {
1123 	device_t dev = ha->pci_dev;
1124 
1125 	device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n", __func__,
1126 		rstat->total_bytes);
1127 	device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n", __func__,
1128 		rstat->total_pkts);
1129 	device_printf(dev, "%s: lro_pkt_count\t\t%" PRIu64 "\n", __func__,
1130 		rstat->lro_pkt_count);
1131 	device_printf(dev, "%s: sw_pkt_count\t\t%" PRIu64 "\n", __func__,
1132 		rstat->sw_pkt_count);
1133 	device_printf(dev, "%s: ip_chksum_err\t\t%" PRIu64 "\n", __func__,
1134 		rstat->ip_chksum_err);
1135 	device_printf(dev, "%s: pkts_wo_acntxts\t\t%" PRIu64 "\n", __func__,
1136 		rstat->pkts_wo_acntxts);
1137 	device_printf(dev, "%s: pkts_dropped_no_sds_card\t%" PRIu64 "\n",
1138 		__func__, rstat->pkts_dropped_no_sds_card);
1139 	device_printf(dev, "%s: pkts_dropped_no_sds_host\t%" PRIu64 "\n",
1140 		__func__, rstat->pkts_dropped_no_sds_host);
1141 	device_printf(dev, "%s: oversized_pkts\t\t%" PRIu64 "\n", __func__,
1142 		rstat->oversized_pkts);
1143 	device_printf(dev, "%s: pkts_dropped_no_rds\t\t%" PRIu64 "\n",
1144 		__func__, rstat->pkts_dropped_no_rds);
1145 	device_printf(dev, "%s: unxpctd_mcast_pkts\t\t%" PRIu64 "\n",
1146 		__func__, rstat->unxpctd_mcast_pkts);
1147 	device_printf(dev, "%s: re1_fbq_error\t\t%" PRIu64 "\n", __func__,
1148 		rstat->re1_fbq_error);
1149 	device_printf(dev, "%s: invalid_mac_addr\t\t%" PRIu64 "\n", __func__,
1150 		rstat->invalid_mac_addr);
1151 	device_printf(dev, "%s: rds_prime_trys\t\t%" PRIu64 "\n", __func__,
1152 		rstat->rds_prime_trys);
1153 	device_printf(dev, "%s: rds_prime_success\t\t%" PRIu64 "\n", __func__,
1154 		rstat->rds_prime_success);
1155 	device_printf(dev, "%s: lro_flows_added\t\t%" PRIu64 "\n", __func__,
1156 		rstat->lro_flows_added);
1157 	device_printf(dev, "%s: lro_flows_deleted\t\t%" PRIu64 "\n", __func__,
1158 		rstat->lro_flows_deleted);
1159 	device_printf(dev, "%s: lro_flows_active\t\t%" PRIu64 "\n", __func__,
1160 		rstat->lro_flows_active);
1161 	device_printf(dev, "%s: pkts_droped_unknown\t\t%" PRIu64 "\n",
1162 		__func__, rstat->pkts_droped_unknown);
1163 }
1164 
1165 static void
1166 qla_mac_stats(qla_host_t *ha, q80_mac_stats_t *mstat)
1167 {
1168 	device_t dev = ha->pci_dev;
1169 
1170 	device_printf(dev, "%s: xmt_frames\t\t\t%" PRIu64 "\n", __func__,
1171 		mstat->xmt_frames);
1172 	device_printf(dev, "%s: xmt_bytes\t\t\t%" PRIu64 "\n", __func__,
1173 		mstat->xmt_bytes);
1174 	device_printf(dev, "%s: xmt_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1175 		mstat->xmt_mcast_pkts);
1176 	device_printf(dev, "%s: xmt_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1177 		mstat->xmt_bcast_pkts);
1178 	device_printf(dev, "%s: xmt_pause_frames\t\t%" PRIu64 "\n", __func__,
1179 		mstat->xmt_pause_frames);
1180 	device_printf(dev, "%s: xmt_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1181 		mstat->xmt_cntrl_pkts);
1182 	device_printf(dev, "%s: xmt_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1183 		__func__, mstat->xmt_pkt_lt_64bytes);
1184 	device_printf(dev, "%s: xmt_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1185 		__func__, mstat->xmt_pkt_lt_127bytes);
1186 	device_printf(dev, "%s: xmt_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1187 		__func__, mstat->xmt_pkt_lt_255bytes);
1188 	device_printf(dev, "%s: xmt_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1189 		__func__, mstat->xmt_pkt_lt_511bytes);
1190 	device_printf(dev, "%s: xmt_pkt_lt_1023bytes\t%" PRIu64 "\n",
1191 		__func__, mstat->xmt_pkt_lt_1023bytes);
1192 	device_printf(dev, "%s: xmt_pkt_lt_1518bytes\t%" PRIu64 "\n",
1193 		__func__, mstat->xmt_pkt_lt_1518bytes);
1194 	device_printf(dev, "%s: xmt_pkt_gt_1518bytes\t%" PRIu64 "\n",
1195 		__func__, mstat->xmt_pkt_gt_1518bytes);
1196 
1197 	device_printf(dev, "%s: rcv_frames\t\t\t%" PRIu64 "\n", __func__,
1198 		mstat->rcv_frames);
1199 	device_printf(dev, "%s: rcv_bytes\t\t\t%" PRIu64 "\n", __func__,
1200 		mstat->rcv_bytes);
1201 	device_printf(dev, "%s: rcv_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1202 		mstat->rcv_mcast_pkts);
1203 	device_printf(dev, "%s: rcv_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1204 		mstat->rcv_bcast_pkts);
1205 	device_printf(dev, "%s: rcv_pause_frames\t\t%" PRIu64 "\n", __func__,
1206 		mstat->rcv_pause_frames);
1207 	device_printf(dev, "%s: rcv_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1208 		mstat->rcv_cntrl_pkts);
1209 	device_printf(dev, "%s: rcv_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1210 		__func__, mstat->rcv_pkt_lt_64bytes);
1211 	device_printf(dev, "%s: rcv_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1212 		__func__, mstat->rcv_pkt_lt_127bytes);
1213 	device_printf(dev, "%s: rcv_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1214 		__func__, mstat->rcv_pkt_lt_255bytes);
1215 	device_printf(dev, "%s: rcv_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1216 		__func__, mstat->rcv_pkt_lt_511bytes);
1217 	device_printf(dev, "%s: rcv_pkt_lt_1023bytes\t%" PRIu64 "\n",
1218 		__func__, mstat->rcv_pkt_lt_1023bytes);
1219 	device_printf(dev, "%s: rcv_pkt_lt_1518bytes\t%" PRIu64 "\n",
1220 		__func__, mstat->rcv_pkt_lt_1518bytes);
1221 	device_printf(dev, "%s: rcv_pkt_gt_1518bytes\t%" PRIu64 "\n",
1222 		__func__, mstat->rcv_pkt_gt_1518bytes);
1223 
1224 	device_printf(dev, "%s: rcv_len_error\t\t%" PRIu64 "\n", __func__,
1225 		mstat->rcv_len_error);
1226 	device_printf(dev, "%s: rcv_len_small\t\t%" PRIu64 "\n", __func__,
1227 		mstat->rcv_len_small);
1228 	device_printf(dev, "%s: rcv_len_large\t\t%" PRIu64 "\n", __func__,
1229 		mstat->rcv_len_large);
1230 	device_printf(dev, "%s: rcv_jabber\t\t\t%" PRIu64 "\n", __func__,
1231 		mstat->rcv_jabber);
1232 	device_printf(dev, "%s: rcv_dropped\t\t\t%" PRIu64 "\n", __func__,
1233 		mstat->rcv_dropped);
1234 	device_printf(dev, "%s: fcs_error\t\t\t%" PRIu64 "\n", __func__,
1235 		mstat->fcs_error);
1236 	device_printf(dev, "%s: align_error\t\t\t%" PRIu64 "\n", __func__,
1237 		mstat->align_error);
1238 }
1239 
1240 
1241 static int
1242 qla_get_hw_stats(qla_host_t *ha, uint32_t cmd)
1243 {
1244 	device_t		dev;
1245 	q80_get_stats_t		*stat;
1246 	q80_get_stats_rsp_t	*stat_rsp;
1247 	uint32_t		err;
1248 
1249 	dev = ha->pci_dev;
1250 
1251 	stat = (q80_get_stats_t *)ha->hw.mbox;
1252 	bzero(stat, (sizeof (q80_get_stats_t)));
1253 
1254 	stat->opcode = Q8_MBX_GET_STATS;
1255 	stat->count_version = 2;
1256 	stat->count_version |= Q8_MBX_CMD_VERSION;
1257 
1258 	stat->cmd = cmd;
1259 
1260         if (qla_mbx_cmd(ha, (uint32_t *)stat, 2,
1261                 ha->hw.mbox, (sizeof (q80_get_stats_rsp_t) >> 2), 0)) {
1262                 device_printf(dev, "%s: failed\n", __func__);
1263                 return -1;
1264         }
1265 
1266 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1267 
1268         err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status);
1269 
1270         if (err) {
1271                 return -1;
1272         }
1273 
1274 	return 0;
1275 }
1276 
1277 void
1278 ql_get_stats(qla_host_t *ha)
1279 {
1280 	q80_get_stats_rsp_t	*stat_rsp;
1281 	q80_mac_stats_t		*mstat;
1282 	q80_xmt_stats_t		*xstat;
1283 	q80_rcv_stats_t		*rstat;
1284 	uint32_t		cmd;
1285 
1286 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1287 	/*
1288 	 * Get MAC Statistics
1289 	 */
1290 	cmd = Q8_GET_STATS_CMD_TYPE_MAC;
1291 
1292 	cmd |= ((ha->pci_func & 0x1) << 16);
1293 
1294 	if (qla_get_hw_stats(ha, cmd) == 0) {
1295 		mstat = (q80_mac_stats_t *)&stat_rsp->u.mac;
1296 		qla_mac_stats(ha, mstat);
1297 	} else {
1298                 device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n",
1299 			__func__, ha->hw.mbox[0]);
1300 	}
1301 	/*
1302 	 * Get RCV Statistics
1303 	 */
1304 	cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT;
1305 	cmd |= (ha->hw.rcv_cntxt_id << 16);
1306 
1307 	if (qla_get_hw_stats(ha, cmd) == 0) {
1308 		rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv;
1309 		qla_rcv_stats(ha, rstat);
1310 	} else {
1311                 device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n",
1312 			__func__, ha->hw.mbox[0]);
1313 	}
1314 	/*
1315 	 * Get XMT Statistics
1316 	 */
1317 	cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT;
1318 	cmd |= (ha->hw.tx_cntxt[ha->txr_idx].tx_cntxt_id << 16);
1319 
1320 
1321 	if (qla_get_hw_stats(ha, cmd) == 0) {
1322 		xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt;
1323 		qla_xmt_stats(ha, xstat);
1324 	} else {
1325                 device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n",
1326 			__func__, ha->hw.mbox[0]);
1327 	}
1328 }
1329 
1330 /*
1331  * Name: qla_tx_tso
1332  * Function: Checks if the packet to be transmitted is a candidate for
1333  *	Large TCP Segment Offload. If yes, the appropriate fields in the Tx
1334  *	Ring Structure are plugged in.
1335  */
1336 static int
1337 qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
1338 {
1339 	struct ether_vlan_header *eh;
1340 	struct ip *ip = NULL;
1341 	struct ip6_hdr *ip6 = NULL;
1342 	struct tcphdr *th = NULL;
1343 	uint32_t ehdrlen,  hdrlen, ip_hlen, tcp_hlen, tcp_opt_off;
1344 	uint16_t etype, opcode, offload = 1;
1345 	device_t dev;
1346 
1347 	dev = ha->pci_dev;
1348 
1349 
1350 	eh = mtod(mp, struct ether_vlan_header *);
1351 
1352 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1353 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1354 		etype = ntohs(eh->evl_proto);
1355 	} else {
1356 		ehdrlen = ETHER_HDR_LEN;
1357 		etype = ntohs(eh->evl_encap_proto);
1358 	}
1359 
1360 	hdrlen = 0;
1361 
1362 	switch (etype) {
1363 		case ETHERTYPE_IP:
1364 
1365 			tcp_opt_off = ehdrlen + sizeof(struct ip) +
1366 					sizeof(struct tcphdr);
1367 
1368 			if (mp->m_len < tcp_opt_off) {
1369 				m_copydata(mp, 0, tcp_opt_off, hdr);
1370 				ip = (struct ip *)(hdr + ehdrlen);
1371 			} else {
1372 				ip = (struct ip *)(mp->m_data + ehdrlen);
1373 			}
1374 
1375 			ip_hlen = ip->ip_hl << 2;
1376 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
1377 
1378 
1379 			if ((ip->ip_p != IPPROTO_TCP) ||
1380 				(ip_hlen != sizeof (struct ip))){
1381 				/* IP Options are not supported */
1382 
1383 				offload = 0;
1384 			} else
1385 				th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
1386 
1387 		break;
1388 
1389 		case ETHERTYPE_IPV6:
1390 
1391 			tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) +
1392 					sizeof (struct tcphdr);
1393 
1394 			if (mp->m_len < tcp_opt_off) {
1395 				m_copydata(mp, 0, tcp_opt_off, hdr);
1396 				ip6 = (struct ip6_hdr *)(hdr + ehdrlen);
1397 			} else {
1398 				ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1399 			}
1400 
1401 			ip_hlen = sizeof(struct ip6_hdr);
1402 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6;
1403 
1404 			if (ip6->ip6_nxt != IPPROTO_TCP) {
1405 				//device_printf(dev, "%s: ipv6\n", __func__);
1406 				offload = 0;
1407 			} else
1408 				th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
1409 		break;
1410 
1411 		default:
1412 			QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__));
1413 			offload = 0;
1414 		break;
1415 	}
1416 
1417 	if (!offload)
1418 		return (-1);
1419 
1420 	tcp_hlen = th->th_off << 2;
1421 	hdrlen = ehdrlen + ip_hlen + tcp_hlen;
1422 
1423         if (mp->m_len < hdrlen) {
1424                 if (mp->m_len < tcp_opt_off) {
1425                         if (tcp_hlen > sizeof(struct tcphdr)) {
1426                                 m_copydata(mp, tcp_opt_off,
1427                                         (tcp_hlen - sizeof(struct tcphdr)),
1428                                         &hdr[tcp_opt_off]);
1429                         }
1430                 } else {
1431                         m_copydata(mp, 0, hdrlen, hdr);
1432                 }
1433         }
1434 
1435 	tx_cmd->mss = mp->m_pkthdr.tso_segsz;
1436 
1437 	tx_cmd->flags_opcode = opcode ;
1438 	tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen;
1439 	tx_cmd->total_hdr_len = hdrlen;
1440 
1441 	/* Check for Multicast least significant bit of MSB == 1 */
1442 	if (eh->evl_dhost[0] & 0x01) {
1443 		tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST;
1444 	}
1445 
1446 	if (mp->m_len < hdrlen) {
1447 		printf("%d\n", hdrlen);
1448 		return (1);
1449 	}
1450 
1451 	return (0);
1452 }
1453 
1454 /*
1455  * Name: qla_tx_chksum
1456  * Function: Checks if the packet to be transmitted is a candidate for
1457  *	TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx
1458  *	Ring Structure are plugged in.
1459  */
1460 static int
1461 qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code,
1462 	uint32_t *tcp_hdr_off)
1463 {
1464 	struct ether_vlan_header *eh;
1465 	struct ip *ip;
1466 	struct ip6_hdr *ip6;
1467 	uint32_t ehdrlen, ip_hlen;
1468 	uint16_t etype, opcode, offload = 1;
1469 	device_t dev;
1470 	uint8_t buf[sizeof(struct ip6_hdr)];
1471 
1472 	dev = ha->pci_dev;
1473 
1474 	*op_code = 0;
1475 
1476 	if ((mp->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) == 0)
1477 		return (-1);
1478 
1479 	eh = mtod(mp, struct ether_vlan_header *);
1480 
1481 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1482 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1483 		etype = ntohs(eh->evl_proto);
1484 	} else {
1485 		ehdrlen = ETHER_HDR_LEN;
1486 		etype = ntohs(eh->evl_encap_proto);
1487 	}
1488 
1489 
1490 	switch (etype) {
1491 		case ETHERTYPE_IP:
1492 			ip = (struct ip *)(mp->m_data + ehdrlen);
1493 
1494 			ip_hlen = sizeof (struct ip);
1495 
1496 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1497 				m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
1498 				ip = (struct ip *)buf;
1499 			}
1500 
1501 			if (ip->ip_p == IPPROTO_TCP)
1502 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM;
1503 			else if (ip->ip_p == IPPROTO_UDP)
1504 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM;
1505 			else {
1506 				//device_printf(dev, "%s: ipv4\n", __func__);
1507 				offload = 0;
1508 			}
1509 		break;
1510 
1511 		case ETHERTYPE_IPV6:
1512 			ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1513 
1514 			ip_hlen = sizeof(struct ip6_hdr);
1515 
1516 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1517 				m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
1518 					buf);
1519 				ip6 = (struct ip6_hdr *)buf;
1520 			}
1521 
1522 			if (ip6->ip6_nxt == IPPROTO_TCP)
1523 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6;
1524 			else if (ip6->ip6_nxt == IPPROTO_UDP)
1525 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6;
1526 			else {
1527 				//device_printf(dev, "%s: ipv6\n", __func__);
1528 				offload = 0;
1529 			}
1530 		break;
1531 
1532 		default:
1533 			offload = 0;
1534 		break;
1535 	}
1536 	if (!offload)
1537 		return (-1);
1538 
1539 	*op_code = opcode;
1540 	*tcp_hdr_off = (ip_hlen + ehdrlen);
1541 
1542 	return (0);
1543 }
1544 
1545 #define QLA_TX_MIN_FREE 2
1546 /*
1547  * Name: ql_hw_send
1548  * Function: Transmits a packet. It first checks if the packet is a
1549  *	candidate for Large TCP Segment Offload and then for UDP/TCP checksum
1550  *	offload. If either of these creteria are not met, it is transmitted
1551  *	as a regular ethernet frame.
1552  */
1553 int
1554 ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
1555 	uint32_t tx_idx,  struct mbuf *mp, uint32_t txr_idx)
1556 {
1557 	struct ether_vlan_header *eh;
1558 	qla_hw_t *hw = &ha->hw;
1559 	q80_tx_cmd_t *tx_cmd, tso_cmd;
1560 	bus_dma_segment_t *c_seg;
1561 	uint32_t num_tx_cmds, hdr_len = 0;
1562 	uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next;
1563 	device_t dev;
1564 	int i, ret;
1565 	uint8_t *src = NULL, *dst = NULL;
1566 	uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
1567 	uint32_t op_code = 0;
1568 	uint32_t tcp_hdr_off = 0;
1569 
1570 	dev = ha->pci_dev;
1571 
1572 	/*
1573 	 * Always make sure there is atleast one empty slot in the tx_ring
1574 	 * tx_ring is considered full when there only one entry available
1575 	 */
1576         num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2;
1577 
1578 	total_length = mp->m_pkthdr.len;
1579 	if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
1580 		device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
1581 			__func__, total_length);
1582 		return (-1);
1583 	}
1584 	eh = mtod(mp, struct ether_vlan_header *);
1585 
1586 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
1587 
1588 		bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
1589 
1590 		src = frame_hdr;
1591 		ret = qla_tx_tso(ha, mp, &tso_cmd, src);
1592 
1593 		if (!(ret & ~1)) {
1594 			/* find the additional tx_cmd descriptors required */
1595 
1596 			if (mp->m_flags & M_VLANTAG)
1597 				tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN;
1598 
1599 			hdr_len = tso_cmd.total_hdr_len;
1600 
1601 			bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
1602 			bytes = QL_MIN(bytes, hdr_len);
1603 
1604 			num_tx_cmds++;
1605 			hdr_len -= bytes;
1606 
1607 			while (hdr_len) {
1608 				bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
1609 				hdr_len -= bytes;
1610 				num_tx_cmds++;
1611 			}
1612 			hdr_len = tso_cmd.total_hdr_len;
1613 
1614 			if (ret == 0)
1615 				src = (uint8_t *)eh;
1616 		} else
1617 			return (EINVAL);
1618 	} else {
1619 		(void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off);
1620 	}
1621 
1622 	if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
1623 		qla_hw_tx_done_locked(ha, txr_idx);
1624 		if (hw->tx_cntxt[txr_idx].txr_free <=
1625 				(num_tx_cmds + QLA_TX_MIN_FREE)) {
1626         		QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= "
1627 				"(num_tx_cmds + QLA_TX_MIN_FREE))\n",
1628 				__func__));
1629 			return (-1);
1630 		}
1631 	}
1632 
1633 	tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx];
1634 
1635         if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) {
1636 
1637                 if (nsegs > ha->hw.max_tx_segs)
1638                         ha->hw.max_tx_segs = nsegs;
1639 
1640                 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
1641 
1642                 if (op_code) {
1643                         tx_cmd->flags_opcode = op_code;
1644                         tx_cmd->tcp_hdr_off = tcp_hdr_off;
1645 
1646                 } else {
1647                         tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER;
1648                 }
1649 	} else {
1650 		bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
1651 		ha->tx_tso_frames++;
1652 	}
1653 
1654 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1655         	tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
1656 	} else if (mp->m_flags & M_VLANTAG) {
1657 
1658 		if (hdr_len) { /* TSO */
1659 			tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED |
1660 						Q8_TX_CMD_FLAGS_HW_VLAN_ID);
1661 			tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN;
1662 		} else
1663 			tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID;
1664 
1665 		ha->hw_vlan_tx_frames++;
1666 		tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag;
1667 	}
1668 
1669 
1670         tx_cmd->n_bufs = (uint8_t)nsegs;
1671         tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF);
1672         tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8)));
1673 	tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func);
1674 
1675 	c_seg = segs;
1676 
1677 	while (1) {
1678 		for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) {
1679 
1680 			switch (i) {
1681 			case 0:
1682 				tx_cmd->buf1_addr = c_seg->ds_addr;
1683 				tx_cmd->buf1_len = c_seg->ds_len;
1684 				break;
1685 
1686 			case 1:
1687 				tx_cmd->buf2_addr = c_seg->ds_addr;
1688 				tx_cmd->buf2_len = c_seg->ds_len;
1689 				break;
1690 
1691 			case 2:
1692 				tx_cmd->buf3_addr = c_seg->ds_addr;
1693 				tx_cmd->buf3_len = c_seg->ds_len;
1694 				break;
1695 
1696 			case 3:
1697 				tx_cmd->buf4_addr = c_seg->ds_addr;
1698 				tx_cmd->buf4_len = c_seg->ds_len;
1699 				break;
1700 			}
1701 
1702 			c_seg++;
1703 			nsegs--;
1704 		}
1705 
1706 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
1707 			(hw->tx_cntxt[txr_idx].txr_next + 1) &
1708 				(NUM_TX_DESCRIPTORS - 1);
1709 		tx_cmd_count++;
1710 
1711 		if (!nsegs)
1712 			break;
1713 
1714 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
1715 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
1716 	}
1717 
1718 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
1719 
1720 		/* TSO : Copy the header in the following tx cmd descriptors */
1721 
1722 		txr_next = hw->tx_cntxt[txr_idx].txr_next;
1723 
1724 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
1725 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
1726 
1727 		bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
1728 		bytes = QL_MIN(bytes, hdr_len);
1729 
1730 		dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN;
1731 
1732 		if (mp->m_flags & M_VLANTAG) {
1733 			/* first copy the src/dst MAC addresses */
1734 			bcopy(src, dst, (ETHER_ADDR_LEN * 2));
1735 			dst += (ETHER_ADDR_LEN * 2);
1736 			src += (ETHER_ADDR_LEN * 2);
1737 
1738 			*((uint16_t *)dst) = htons(ETHERTYPE_VLAN);
1739 			dst += 2;
1740 			*((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag);
1741 			dst += 2;
1742 
1743 			/* bytes left in src header */
1744 			hdr_len -= ((ETHER_ADDR_LEN * 2) +
1745 					ETHER_VLAN_ENCAP_LEN);
1746 
1747 			/* bytes left in TxCmd Entry */
1748 			bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN);
1749 
1750 
1751 			bcopy(src, dst, bytes);
1752 			src += bytes;
1753 			hdr_len -= bytes;
1754 		} else {
1755 			bcopy(src, dst, bytes);
1756 			src += bytes;
1757 			hdr_len -= bytes;
1758 		}
1759 
1760 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
1761 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
1762 					(NUM_TX_DESCRIPTORS - 1);
1763 		tx_cmd_count++;
1764 
1765 		while (hdr_len) {
1766 			tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
1767 			bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
1768 
1769 			bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
1770 
1771 			bcopy(src, tx_cmd, bytes);
1772 			src += bytes;
1773 			hdr_len -= bytes;
1774 
1775 			txr_next = hw->tx_cntxt[txr_idx].txr_next =
1776 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
1777 					(NUM_TX_DESCRIPTORS - 1);
1778 			tx_cmd_count++;
1779 		}
1780 	}
1781 
1782 	hw->tx_cntxt[txr_idx].txr_free =
1783 		hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count;
1784 
1785 	QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\
1786 		txr_idx);
1787        	QL_DPRINT8(ha, (dev, "%s: return\n", __func__));
1788 
1789 	return (0);
1790 }
1791 
1792 
1793 static int
1794 qla_config_rss_ind_table(qla_host_t *ha)
1795 {
1796 	uint32_t i, count;
1797 	uint8_t rss_ind_tbl[16];
1798 
1799 	bzero(rss_ind_default_table, sizeof(rss_ind_default_table));
1800 
1801 
1802 	for (i = 0; i < 16; i++) {
1803 		rss_ind_tbl[i] = i % ha->hw.num_sds_rings;
1804 	}
1805 
1806 	for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ; i = i + 16) {
1807 
1808 		if ((i + 16) > Q8_RSS_IND_TBL_MAX_IDX) {
1809 			count = Q8_RSS_IND_TBL_MAX_IDX - i + 1;
1810 		} else {
1811 			count = 16;
1812 		}
1813 
1814 		if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id,
1815 			rss_ind_tbl))
1816 			return (-1);
1817 	}
1818 
1819 	return (0);
1820 }
1821 
1822 /*
1823  * Name: ql_del_hw_if
1824  * Function: Destroys the hardware specific entities corresponding to an
1825  *	Ethernet Interface
1826  */
1827 void
1828 ql_del_hw_if(qla_host_t *ha)
1829 {
1830 
1831 	qla_del_rcv_cntxt(ha);
1832 	qla_del_xmt_cntxt(ha);
1833 
1834 	if (ha->hw.flags.init_intr_cnxt) {
1835 		qla_config_intr_cntxt(ha, ha->hw.num_sds_rings, 0);
1836 		ha->hw.flags.init_intr_cnxt = 0;
1837 	}
1838 }
1839 
1840 /*
1841  * Name: ql_init_hw_if
1842  * Function: Creates the hardware specific entities corresponding to an
1843  *	Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
1844  *	corresponding to the interface. Enables LRO if allowed.
1845  */
1846 int
1847 ql_init_hw_if(qla_host_t *ha)
1848 {
1849 	device_t	dev;
1850 	uint32_t	i;
1851 	uint8_t		bcast_mac[6];
1852 	qla_rdesc_t	*rdesc;
1853 
1854 	dev = ha->pci_dev;
1855 
1856 	for (i = 0; i < ha->hw.num_sds_rings; i++) {
1857 		bzero(ha->hw.dma_buf.sds_ring[i].dma_b,
1858 			ha->hw.dma_buf.sds_ring[i].size);
1859 	}
1860 	ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX);
1861 
1862 	/* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */
1863 	WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2);
1864 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
1865 
1866 	qla_get_nic_partition(ha);
1867 
1868 	if (qla_config_intr_cntxt(ha, ha->hw.num_sds_rings, 1) == 0) {
1869 		ha->hw.flags.init_intr_cnxt = 1;
1870 	} else
1871 		return (-1);
1872 
1873 	if (ha->hw.mdump_init == 0) {
1874 		qla_minidump_init(ha);
1875 	}
1876 
1877 	/*
1878 	 * Create Receive Context
1879 	 */
1880 	if (qla_init_rcv_cntxt(ha)) {
1881 		return (-1);
1882 	}
1883 
1884 	for (i = 0; i < ha->hw.num_rds_rings; i++) {
1885 		rdesc = &ha->hw.rds[i];
1886 		rdesc->rx_next = NUM_RX_DESCRIPTORS - 2;
1887 		rdesc->rx_in = 0;
1888 		/* Update the RDS Producer Indices */
1889 		QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\
1890 			rdesc->rx_next);
1891 	}
1892 
1893 
1894 	/*
1895 	 * Create Transmit Context
1896 	 */
1897 	if (qla_init_xmt_cntxt(ha)) {
1898 		qla_del_rcv_cntxt(ha);
1899 		return (-1);
1900 	}
1901 	ha->hw.max_tx_segs = 0;
1902 
1903 	if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1))
1904 		return(-1);
1905 
1906 	ha->hw.flags.unicast_mac = 1;
1907 
1908 	bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
1909 	bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
1910 
1911 	if (qla_config_mac_addr(ha, bcast_mac, 1))
1912 		return (-1);
1913 
1914 	ha->hw.flags.bcast_mac = 1;
1915 
1916 	/*
1917 	 * program any cached multicast addresses
1918 	 */
1919 	if (qla_hw_add_all_mcast(ha))
1920 		return (-1);
1921 
1922 	if (qla_config_rss(ha, ha->hw.rcv_cntxt_id))
1923 		return (-1);
1924 
1925 	if (qla_config_rss_ind_table(ha))
1926 		return (-1);
1927 
1928 	if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0))
1929 		return (-1);
1930 
1931 	if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
1932 		return (-1);
1933 
1934 	if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
1935 		return (-1);
1936 
1937 	for (i = 0; i < ha->hw.num_sds_rings; i++)
1938 		QL_ENABLE_INTERRUPTS(ha, i);
1939 
1940 	return (0);
1941 }
1942 
1943 static int
1944 qla_map_sds_to_rds(qla_host_t *ha)
1945 {
1946         device_t                dev = ha->pci_dev;
1947         q80_rq_map_sds_to_rds_t *map_rings;
1948         q80_rsp_add_rcv_rings_t *map_rings_rsp;
1949         uint32_t                i, err;
1950         qla_hw_t                *hw = &ha->hw;
1951 
1952         map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox;
1953         bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t));
1954 
1955         map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS;
1956         map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2);
1957         map_rings->count_version |= Q8_MBX_CMD_VERSION;
1958 
1959         map_rings->cntxt_id = hw->rcv_cntxt_id;
1960         map_rings->num_rings = hw->num_sds_rings;
1961 
1962         for (i = 0; i < hw->num_sds_rings; i++) {
1963                 map_rings->sds_rds[i].sds_ring = i;
1964                 map_rings->sds_rds[i].rds_ring = i;
1965         }
1966 
1967         if (qla_mbx_cmd(ha, (uint32_t *)map_rings,
1968                 (sizeof (q80_rq_map_sds_to_rds_t) >> 2),
1969                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
1970                 device_printf(dev, "%s: failed0\n", __func__);
1971                 return (-1);
1972         }
1973 
1974         map_rings_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
1975 
1976         err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status);
1977 
1978         if (err) {
1979                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1980                 return (-1);
1981         }
1982 
1983         return (0);
1984 }
1985 
1986 /*
1987  * Name: qla_init_rcv_cntxt
1988  * Function: Creates the Receive Context.
1989  */
1990 static int
1991 qla_init_rcv_cntxt(qla_host_t *ha)
1992 {
1993 	q80_rq_rcv_cntxt_t	*rcntxt;
1994 	q80_rsp_rcv_cntxt_t	*rcntxt_rsp;
1995 	q80_stat_desc_t		*sdesc;
1996 	int			i, j;
1997         qla_hw_t		*hw = &ha->hw;
1998 	device_t		dev;
1999 	uint32_t		err;
2000 	uint32_t		rcntxt_sds_rings;
2001 	uint32_t		rcntxt_rds_rings;
2002 
2003 	dev = ha->pci_dev;
2004 
2005 	/*
2006 	 * Create Receive Context
2007 	 */
2008 
2009 	for (i = 0; i < hw->num_sds_rings; i++) {
2010 		sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0];
2011 
2012 		for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) {
2013 			sdesc->data[0] = 1ULL;
2014 			sdesc->data[1] = 1ULL;
2015 		}
2016 	}
2017 
2018 	rcntxt_sds_rings = hw->num_sds_rings;
2019 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS)
2020 		rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS;
2021 
2022 	rcntxt_rds_rings = hw->num_rds_rings;
2023 
2024 	if (hw->num_rds_rings > MAX_RDS_RING_SETS)
2025 		rcntxt_rds_rings = MAX_RDS_RING_SETS;
2026 
2027 	rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox;
2028 	bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t)));
2029 
2030 	rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT;
2031 	rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2);
2032 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2033 
2034 	rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW |
2035 			Q8_RCV_CNTXT_CAP0_LRO |
2036 			Q8_RCV_CNTXT_CAP0_HW_LRO |
2037 			Q8_RCV_CNTXT_CAP0_RSS |
2038 			Q8_RCV_CNTXT_CAP0_SGL_JUMBO |
2039 			Q8_RCV_CNTXT_CAP0_SGL_LRO;
2040 
2041 	if (ha->hw.num_rds_rings > 1) {
2042 		rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5);
2043 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS;
2044 	} else
2045 		rcntxt->nrds_sets_rings = 0x1 | (1 << 5);
2046 
2047 	rcntxt->nsds_rings = rcntxt_sds_rings;
2048 
2049 	rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE;
2050 
2051 	rcntxt->rcv_vpid = 0;
2052 
2053 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2054 		rcntxt->sds[i].paddr =
2055 			qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr);
2056 		rcntxt->sds[i].size =
2057 			qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2058 		if (ha->msix_count == 2) {
2059 			rcntxt->sds[i].intr_id =
2060 				qla_host_to_le16(hw->intr_id[0]);
2061 			rcntxt->sds[i].intr_src_bit = qla_host_to_le16((i));
2062 		} else {
2063 			rcntxt->sds[i].intr_id =
2064 				qla_host_to_le16(hw->intr_id[i]);
2065 			rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0);
2066 		}
2067 	}
2068 
2069 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2070 		rcntxt->rds[i].paddr_std =
2071 			qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr);
2072 		rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
2073 		rcntxt->rds[i].std_nentries =
2074 			qla_host_to_le32(NUM_RX_DESCRIPTORS);
2075 	}
2076 
2077         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2078 		(sizeof (q80_rq_rcv_cntxt_t) >> 2),
2079                 ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) {
2080                 device_printf(dev, "%s: failed0\n", __func__);
2081                 return (-1);
2082         }
2083 
2084         rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox;
2085 
2086         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2087 
2088         if (err) {
2089                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2090                 return (-1);
2091         }
2092 
2093 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2094 		hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i];
2095 	}
2096 
2097 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2098 		hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std;
2099 	}
2100 
2101 	hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id;
2102 
2103 	ha->hw.flags.init_rx_cnxt = 1;
2104 
2105 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) {
2106 		err = qla_add_rcv_rings(ha, MAX_RCNTXT_SDS_RINGS);
2107 		if (err)
2108 			return -1;
2109 	}
2110 
2111         if (hw->num_rds_rings > 1) {
2112 		err = qla_map_sds_to_rds(ha);
2113 		if (err)
2114 			return -1;
2115 	}
2116 
2117 	return (0);
2118 }
2119 
2120 static int
2121 qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx)
2122 {
2123 	device_t		dev = ha->pci_dev;
2124 	q80_rq_add_rcv_rings_t	*add_rcv;
2125 	q80_rsp_add_rcv_rings_t	*add_rcv_rsp;
2126 	uint32_t		i,j, err;
2127 	uint8_t			nsds;
2128         qla_hw_t		*hw = &ha->hw;
2129 
2130 	nsds = hw->num_sds_rings - MAX_RCNTXT_SDS_RINGS;
2131 
2132 	add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox;
2133 	bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t));
2134 
2135 	add_rcv->opcode = Q8_MBX_ADD_RX_RINGS;
2136 	add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2);
2137 	add_rcv->count_version |= Q8_MBX_CMD_VERSION;
2138 
2139         if (hw->num_rds_rings > 1)
2140                 add_rcv->nrds_sets_rings = nsds | (1 << 5);
2141         else
2142                 add_rcv->nrds_sets_rings = 0;
2143 
2144 	add_rcv->nsds_rings = nsds;
2145 	add_rcv->cntxt_id = hw->rcv_cntxt_id;
2146 
2147         for (i = 0; i <  nsds; i++) {
2148 
2149 		j = i + sds_idx;
2150 
2151                 add_rcv->sds[i].paddr =
2152                         qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr);
2153 
2154                 add_rcv->sds[i].size =
2155                         qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2156 
2157                 if (ha->msix_count == 2) {
2158                         add_rcv->sds[i].intr_id =
2159                                 qla_host_to_le16(hw->intr_id[0]);
2160                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(j);
2161                 } else {
2162                         add_rcv->sds[i].intr_id =
2163                                 qla_host_to_le16(hw->intr_id[j]);
2164                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0);
2165                 }
2166 
2167         }
2168         for (i = 0; ((i <  nsds) && (hw->num_rds_rings > 1)); i++) {
2169                 j = i + sds_idx;
2170                 add_rcv->rds[i].paddr_std =
2171                         qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr);
2172                 add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
2173                 add_rcv->rds[i].std_nentries =
2174                         qla_host_to_le32(NUM_RX_DESCRIPTORS);
2175         }
2176 
2177 
2178         if (qla_mbx_cmd(ha, (uint32_t *)add_rcv,
2179 		(sizeof (q80_rq_add_rcv_rings_t) >> 2),
2180                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2181                 device_printf(dev, "%s: failed0\n", __func__);
2182                 return (-1);
2183         }
2184 
2185         add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
2186 
2187         err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status);
2188 
2189         if (err) {
2190                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2191                 return (-1);
2192         }
2193 
2194 	for (i = sds_idx; i < hw->num_sds_rings; i++) {
2195 		hw->sds[i].sds_consumer = add_rcv_rsp->sds_cons[(i - sds_idx)];
2196 	}
2197 	for (i = sds_idx; i < hw->num_rds_rings; i++) {
2198 		hw->rds[i].prod_std = add_rcv_rsp->rds[(i - sds_idx)].prod_std;
2199 	}
2200 	return (0);
2201 }
2202 
2203 /*
2204  * Name: qla_del_rcv_cntxt
2205  * Function: Destroys the Receive Context.
2206  */
2207 static void
2208 qla_del_rcv_cntxt(qla_host_t *ha)
2209 {
2210 	device_t			dev = ha->pci_dev;
2211 	q80_rcv_cntxt_destroy_t		*rcntxt;
2212 	q80_rcv_cntxt_destroy_rsp_t	*rcntxt_rsp;
2213 	uint32_t			err;
2214 	uint8_t				bcast_mac[6];
2215 
2216 	if (!ha->hw.flags.init_rx_cnxt)
2217 		return;
2218 
2219 	if (qla_hw_del_all_mcast(ha))
2220 		return;
2221 
2222 	if (ha->hw.flags.bcast_mac) {
2223 
2224 		bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2225 		bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2226 
2227 		if (qla_config_mac_addr(ha, bcast_mac, 0))
2228 			return;
2229 		ha->hw.flags.bcast_mac = 0;
2230 
2231 	}
2232 
2233 	if (ha->hw.flags.unicast_mac) {
2234 		if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0))
2235 			return;
2236 		ha->hw.flags.unicast_mac = 0;
2237 	}
2238 
2239 	rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox;
2240 	bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t)));
2241 
2242 	rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT;
2243 	rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2);
2244 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2245 
2246 	rcntxt->cntxt_id = ha->hw.rcv_cntxt_id;
2247 
2248         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2249 		(sizeof (q80_rcv_cntxt_destroy_t) >> 2),
2250                 ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) {
2251                 device_printf(dev, "%s: failed0\n", __func__);
2252                 return;
2253         }
2254         rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox;
2255 
2256         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2257 
2258         if (err) {
2259                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2260         }
2261 
2262 	ha->hw.flags.init_rx_cnxt = 0;
2263 	return;
2264 }
2265 
2266 /*
2267  * Name: qla_init_xmt_cntxt
2268  * Function: Creates the Transmit Context.
2269  */
2270 static int
2271 qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2272 {
2273 	device_t		dev;
2274         qla_hw_t		*hw = &ha->hw;
2275 	q80_rq_tx_cntxt_t	*tcntxt;
2276 	q80_rsp_tx_cntxt_t	*tcntxt_rsp;
2277 	uint32_t		err;
2278 	qla_hw_tx_cntxt_t       *hw_tx_cntxt;
2279 
2280 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
2281 
2282 	dev = ha->pci_dev;
2283 
2284 	/*
2285 	 * Create Transmit Context
2286 	 */
2287 	tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox;
2288 	bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t)));
2289 
2290 	tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT;
2291 	tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2);
2292 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2293 
2294 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO;
2295 
2296 	tcntxt->ntx_rings = 1;
2297 
2298 	tcntxt->tx_ring[0].paddr =
2299 		qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr);
2300 	tcntxt->tx_ring[0].tx_consumer =
2301 		qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr);
2302 	tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS);
2303 
2304 	tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[0]);
2305 	tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0);
2306 
2307 
2308 	hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS;
2309 	hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0;
2310 
2311         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2312 		(sizeof (q80_rq_tx_cntxt_t) >> 2),
2313                 ha->hw.mbox,
2314 		(sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) {
2315                 device_printf(dev, "%s: failed0\n", __func__);
2316                 return (-1);
2317         }
2318         tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox;
2319 
2320         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2321 
2322         if (err) {
2323                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2324 		return -1;
2325         }
2326 
2327 	hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index;
2328 	hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id;
2329 
2330 	return (0);
2331 }
2332 
2333 
2334 /*
2335  * Name: qla_del_xmt_cntxt
2336  * Function: Destroys the Transmit Context.
2337  */
2338 static int
2339 qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2340 {
2341 	device_t			dev = ha->pci_dev;
2342 	q80_tx_cntxt_destroy_t		*tcntxt;
2343 	q80_tx_cntxt_destroy_rsp_t	*tcntxt_rsp;
2344 	uint32_t			err;
2345 
2346 	tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox;
2347 	bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t)));
2348 
2349 	tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT;
2350 	tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2);
2351 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2352 
2353 	tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id;
2354 
2355         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2356 		(sizeof (q80_tx_cntxt_destroy_t) >> 2),
2357                 ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) {
2358                 device_printf(dev, "%s: failed0\n", __func__);
2359                 return (-1);
2360         }
2361         tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox;
2362 
2363         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2364 
2365         if (err) {
2366                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2367 		return (-1);
2368         }
2369 
2370 	return (0);
2371 }
2372 static void
2373 qla_del_xmt_cntxt(qla_host_t *ha)
2374 {
2375 	uint32_t i;
2376 
2377 	if (!ha->hw.flags.init_tx_cnxt)
2378 		return;
2379 
2380 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2381 		if (qla_del_xmt_cntxt_i(ha, i))
2382 			break;
2383 	}
2384 	ha->hw.flags.init_tx_cnxt = 0;
2385 }
2386 
2387 static int
2388 qla_init_xmt_cntxt(qla_host_t *ha)
2389 {
2390 	uint32_t i, j;
2391 
2392 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2393 		if (qla_init_xmt_cntxt_i(ha, i) != 0) {
2394 			for (j = 0; j < i; j++)
2395 				qla_del_xmt_cntxt_i(ha, j);
2396 			return (-1);
2397 		}
2398 	}
2399 	ha->hw.flags.init_tx_cnxt = 1;
2400 	return (0);
2401 }
2402 
2403 static int
2404 qla_hw_add_all_mcast(qla_host_t *ha)
2405 {
2406 	int i, nmcast;
2407 
2408 	nmcast = ha->hw.nmcast;
2409 
2410 	for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
2411 		if ((ha->hw.mcast[i].addr[0] != 0) ||
2412 			(ha->hw.mcast[i].addr[1] != 0) ||
2413 			(ha->hw.mcast[i].addr[2] != 0) ||
2414 			(ha->hw.mcast[i].addr[3] != 0) ||
2415 			(ha->hw.mcast[i].addr[4] != 0) ||
2416 			(ha->hw.mcast[i].addr[5] != 0)) {
2417 
2418 			if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 1)) {
2419                 		device_printf(ha->pci_dev, "%s: failed\n",
2420 					__func__);
2421 				return (-1);
2422 			}
2423 
2424 			nmcast--;
2425 		}
2426 	}
2427 	return 0;
2428 }
2429 
2430 static int
2431 qla_hw_del_all_mcast(qla_host_t *ha)
2432 {
2433 	int i, nmcast;
2434 
2435 	nmcast = ha->hw.nmcast;
2436 
2437 	for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
2438 		if ((ha->hw.mcast[i].addr[0] != 0) ||
2439 			(ha->hw.mcast[i].addr[1] != 0) ||
2440 			(ha->hw.mcast[i].addr[2] != 0) ||
2441 			(ha->hw.mcast[i].addr[3] != 0) ||
2442 			(ha->hw.mcast[i].addr[4] != 0) ||
2443 			(ha->hw.mcast[i].addr[5] != 0)) {
2444 
2445 			if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 0))
2446 				return (-1);
2447 
2448 			nmcast--;
2449 		}
2450 	}
2451 	return 0;
2452 }
2453 
2454 static int
2455 qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta)
2456 {
2457 	int i;
2458 
2459 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
2460 
2461 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0)
2462 			return 0; /* its been already added */
2463 	}
2464 
2465 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
2466 
2467 		if ((ha->hw.mcast[i].addr[0] == 0) &&
2468 			(ha->hw.mcast[i].addr[1] == 0) &&
2469 			(ha->hw.mcast[i].addr[2] == 0) &&
2470 			(ha->hw.mcast[i].addr[3] == 0) &&
2471 			(ha->hw.mcast[i].addr[4] == 0) &&
2472 			(ha->hw.mcast[i].addr[5] == 0)) {
2473 
2474 			if (qla_config_mac_addr(ha, mta, 1))
2475 				return (-1);
2476 
2477 			bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN);
2478 			ha->hw.nmcast++;
2479 
2480 			return 0;
2481 		}
2482 	}
2483 	return 0;
2484 }
2485 
2486 static int
2487 qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta)
2488 {
2489 	int i;
2490 
2491 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
2492 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) {
2493 
2494 			if (qla_config_mac_addr(ha, mta, 0))
2495 				return (-1);
2496 
2497 			ha->hw.mcast[i].addr[0] = 0;
2498 			ha->hw.mcast[i].addr[1] = 0;
2499 			ha->hw.mcast[i].addr[2] = 0;
2500 			ha->hw.mcast[i].addr[3] = 0;
2501 			ha->hw.mcast[i].addr[4] = 0;
2502 			ha->hw.mcast[i].addr[5] = 0;
2503 
2504 			ha->hw.nmcast--;
2505 
2506 			return 0;
2507 		}
2508 	}
2509 	return 0;
2510 }
2511 
2512 /*
2513  * Name: ql_hw_set_multi
2514  * Function: Sets the Multicast Addresses provided the host O.S into the
2515  *	hardware (for the given interface)
2516  */
2517 int
2518 ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast, uint32_t mcnt,
2519 	uint32_t add_mac)
2520 {
2521 	int i;
2522 	uint8_t *mta = mcast;
2523 	int ret = 0;
2524 
2525 	for (i = 0; i < mcnt; i++) {
2526 		if (add_mac) {
2527 			ret = qla_hw_add_mcast(ha, mta);
2528 			if (ret)
2529 				break;
2530 		} else {
2531 			ret = qla_hw_del_mcast(ha, mta);
2532 			if (ret)
2533 				break;
2534 		}
2535 
2536 		mta += Q8_MAC_ADDR_LEN;
2537 	}
2538 	return (ret);
2539 }
2540 
2541 /*
2542  * Name: qla_hw_tx_done_locked
2543  * Function: Handle Transmit Completions
2544  */
2545 static void
2546 qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx)
2547 {
2548 	qla_tx_buf_t *txb;
2549         qla_hw_t *hw = &ha->hw;
2550 	uint32_t comp_idx, comp_count = 0;
2551 	qla_hw_tx_cntxt_t *hw_tx_cntxt;
2552 
2553 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
2554 
2555 	/* retrieve index of last entry in tx ring completed */
2556 	comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons));
2557 
2558 	while (comp_idx != hw_tx_cntxt->txr_comp) {
2559 
2560 		txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp];
2561 
2562 		hw_tx_cntxt->txr_comp++;
2563 		if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS)
2564 			hw_tx_cntxt->txr_comp = 0;
2565 
2566 		comp_count++;
2567 
2568 		if (txb->m_head) {
2569 			if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1);
2570 
2571 			bus_dmamap_sync(ha->tx_tag, txb->map,
2572 				BUS_DMASYNC_POSTWRITE);
2573 			bus_dmamap_unload(ha->tx_tag, txb->map);
2574 			m_freem(txb->m_head);
2575 
2576 			txb->m_head = NULL;
2577 		}
2578 	}
2579 
2580 	hw_tx_cntxt->txr_free += comp_count;
2581 	return;
2582 }
2583 
2584 /*
2585  * Name: ql_hw_tx_done
2586  * Function: Handle Transmit Completions
2587  */
2588 void
2589 ql_hw_tx_done(qla_host_t *ha)
2590 {
2591 	int i;
2592 	uint32_t flag = 0;
2593 
2594 	if (!mtx_trylock(&ha->tx_lock)) {
2595        		QL_DPRINT8(ha, (ha->pci_dev,
2596 			"%s: !mtx_trylock(&ha->tx_lock)\n", __func__));
2597 		return;
2598 	}
2599 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2600 		qla_hw_tx_done_locked(ha, i);
2601 		if (ha->hw.tx_cntxt[i].txr_free <= (NUM_TX_DESCRIPTORS >> 1))
2602 			flag = 1;
2603 	}
2604 
2605 	if (!flag)
2606 		ha->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2607 
2608 	QLA_TX_UNLOCK(ha);
2609 	return;
2610 }
2611 
2612 void
2613 ql_update_link_state(qla_host_t *ha)
2614 {
2615 	uint32_t link_state;
2616 	uint32_t prev_link_state;
2617 
2618 	if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
2619 		ha->hw.link_up = 0;
2620 		return;
2621 	}
2622 	link_state = READ_REG32(ha, Q8_LINK_STATE);
2623 
2624 	prev_link_state =  ha->hw.link_up;
2625 
2626 	if (ha->pci_func == 0)
2627 		ha->hw.link_up = (((link_state & 0xF) == 1)? 1 : 0);
2628 	else
2629 		ha->hw.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
2630 
2631 	if (prev_link_state !=  ha->hw.link_up) {
2632 		if (ha->hw.link_up) {
2633 			if_link_state_change(ha->ifp, LINK_STATE_UP);
2634 		} else {
2635 			if_link_state_change(ha->ifp, LINK_STATE_DOWN);
2636 		}
2637 	}
2638 	return;
2639 }
2640 
2641 void
2642 ql_hw_stop_rcv(qla_host_t *ha)
2643 {
2644 	int i, done, count = 100;
2645 
2646 	while (count--) {
2647 		done = 1;
2648 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
2649 			if (ha->hw.sds[i].rcv_active)
2650 				done = 0;
2651 		}
2652 		if (done)
2653 			break;
2654 		else
2655 			qla_mdelay(__func__, 10);
2656 	}
2657 	if (!count)
2658 		device_printf(ha->pci_dev, "%s: Counter expired.\n", __func__);
2659 
2660 	return;
2661 }
2662 
2663 int
2664 ql_hw_check_health(qla_host_t *ha)
2665 {
2666 	uint32_t val;
2667 
2668 	ha->hw.health_count++;
2669 
2670 	if (ha->hw.health_count < 1000)
2671 		return 0;
2672 
2673 	ha->hw.health_count = 0;
2674 
2675 	val = READ_REG32(ha, Q8_ASIC_TEMPERATURE);
2676 
2677 	if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) ||
2678 		(QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) {
2679 		device_printf(ha->pci_dev, "%s: Temperature Alert [0x%08x]\n",
2680 			__func__, val);
2681 		return -1;
2682 	}
2683 
2684 	val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
2685 
2686 	if ((val != ha->hw.hbeat_value) &&
2687 		(!(QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE)))) {
2688 		ha->hw.hbeat_value = val;
2689 		return 0;
2690 	}
2691 	device_printf(ha->pci_dev, "%s: Heartbeat Failue [0x%08x]\n",
2692 		__func__, val);
2693 
2694 	return -1;
2695 }
2696 
2697 static int
2698 qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size)
2699 {
2700 	uint32_t			err;
2701 	device_t			dev = ha->pci_dev;
2702 	q80_config_md_templ_size_t	*md_size;
2703 	q80_config_md_templ_size_rsp_t	*md_size_rsp;
2704 
2705 	md_size = (q80_config_md_templ_size_t *) ha->hw.mbox;
2706 	bzero(md_size, sizeof(q80_config_md_templ_size_t));
2707 
2708 	md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE;
2709 	md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2);
2710 	md_size->count_version |= Q8_MBX_CMD_VERSION;
2711 
2712 	if (qla_mbx_cmd(ha, (uint32_t *) md_size,
2713 		(sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox,
2714 		(sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) {
2715 
2716 		device_printf(dev, "%s: failed\n", __func__);
2717 
2718 		return (-1);
2719 	}
2720 
2721 	md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox;
2722 
2723 	err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status);
2724 
2725         if (err) {
2726 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
2727 		return(-1);
2728         }
2729 
2730 	*size = md_size_rsp->templ_size;
2731 
2732 	return (0);
2733 }
2734 
2735 static int
2736 qla_get_minidump_template(qla_host_t *ha)
2737 {
2738 	uint32_t			err;
2739 	device_t			dev = ha->pci_dev;
2740 	q80_config_md_templ_cmd_t	*md_templ;
2741 	q80_config_md_templ_cmd_rsp_t	*md_templ_rsp;
2742 
2743 	md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox;
2744 	bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t)));
2745 
2746 	md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT;
2747 	md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2);
2748 	md_templ->count_version |= Q8_MBX_CMD_VERSION;
2749 
2750 	md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr;
2751 	md_templ->buff_size = ha->hw.dma_buf.minidump.size;
2752 
2753 	if (qla_mbx_cmd(ha, (uint32_t *) md_templ,
2754 		(sizeof(q80_config_md_templ_cmd_t) >> 2),
2755 		 ha->hw.mbox,
2756 		(sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) {
2757 
2758 		device_printf(dev, "%s: failed\n", __func__);
2759 
2760 		return (-1);
2761 	}
2762 
2763 	md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox;
2764 
2765 	err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status);
2766 
2767 	if (err) {
2768 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
2769 		return (-1);
2770 	}
2771 
2772 	return (0);
2773 
2774 }
2775 
2776 static int
2777 qla_minidump_init(qla_host_t *ha)
2778 {
2779 	int		ret;
2780 	uint32_t	template_size = 0;
2781 	device_t	dev = ha->pci_dev;
2782 
2783 	/*
2784 	 * Get Minidump Template Size
2785  	 */
2786 	ret = qla_get_minidump_tmplt_size(ha, &template_size);
2787 
2788 	if (ret || (template_size == 0)) {
2789 		device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret,
2790 			template_size);
2791 		return (-1);
2792 	}
2793 
2794 	/*
2795 	 * Allocate Memory for Minidump Template
2796 	 */
2797 
2798 	ha->hw.dma_buf.minidump.alignment = 8;
2799 	ha->hw.dma_buf.minidump.size = template_size;
2800 
2801 	if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) {
2802 
2803 		device_printf(dev, "%s: minidump dma alloc failed\n", __func__);
2804 
2805 		return (-1);
2806 	}
2807 	ha->hw.dma_buf.flags.minidump = 1;
2808 
2809 	/*
2810 	 * Retrieve Minidump Template
2811 	 */
2812 	ret = qla_get_minidump_template(ha);
2813 
2814 	if (ret) {
2815 		qla_minidump_free(ha);
2816 	} else {
2817 		ha->hw.mdump_init = 1;
2818 	}
2819 
2820 	return (ret);
2821 }
2822 
2823 
2824 static void
2825 qla_minidump_free(qla_host_t *ha)
2826 {
2827 	ha->hw.mdump_init = 0;
2828 	if (ha->hw.dma_buf.flags.minidump) {
2829 		ha->hw.dma_buf.flags.minidump = 0;
2830 		ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump);
2831 	}
2832 	return;
2833 }
2834 
2835 void
2836 ql_minidump(qla_host_t *ha)
2837 {
2838 	uint32_t delay = 6000;
2839 
2840 	if (!ha->hw.mdump_init)
2841 		return;
2842 
2843 	if (!ha->hw.mdump_active)
2844 		return;
2845 
2846 	if (ha->hw.mdump_active == 1) {
2847 		ha->hw.mdump_start_seq_index = ql_stop_sequence(ha);
2848 		ha->hw.mdump_start = 1;
2849 	}
2850 
2851 	while (delay-- && ha->hw.mdump_active) {
2852 		qla_mdelay(__func__, 100);
2853 	}
2854 	ha->hw.mdump_start = 0;
2855 	ql_start_sequence(ha, ha->hw.mdump_start_seq_index);
2856 
2857 	return;
2858 }
2859