xref: /freebsd/sys/dev/qlxgbe/ql_hw.c (revision 453130d9)
1f10a77bbSDavid C Somayajulu /*
235291c22SDavid C Somayajulu  * Copyright (c) 2013-2016 Qlogic Corporation
3f10a77bbSDavid C Somayajulu  * All rights reserved.
4f10a77bbSDavid C Somayajulu  *
5f10a77bbSDavid C Somayajulu  *  Redistribution and use in source and binary forms, with or without
6f10a77bbSDavid C Somayajulu  *  modification, are permitted provided that the following conditions
7f10a77bbSDavid C Somayajulu  *  are met:
8f10a77bbSDavid C Somayajulu  *
9f10a77bbSDavid C Somayajulu  *  1. Redistributions of source code must retain the above copyright
10f10a77bbSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer.
11f10a77bbSDavid C Somayajulu  *  2. Redistributions in binary form must reproduce the above copyright
12f10a77bbSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer in the
13f10a77bbSDavid C Somayajulu  *     documentation and/or other materials provided with the distribution.
14f10a77bbSDavid C Somayajulu  *
15f10a77bbSDavid C Somayajulu  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16f10a77bbSDavid C Somayajulu  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17f10a77bbSDavid C Somayajulu  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18f10a77bbSDavid C Somayajulu  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19f10a77bbSDavid C Somayajulu  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20f10a77bbSDavid C Somayajulu  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21f10a77bbSDavid C Somayajulu  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22f10a77bbSDavid C Somayajulu  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23f10a77bbSDavid C Somayajulu  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24f10a77bbSDavid C Somayajulu  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25f10a77bbSDavid C Somayajulu  *  POSSIBILITY OF SUCH DAMAGE.
26f10a77bbSDavid C Somayajulu  */
27f10a77bbSDavid C Somayajulu 
28f10a77bbSDavid C Somayajulu /*
29f10a77bbSDavid C Somayajulu  * File: ql_hw.c
30f10a77bbSDavid C Somayajulu  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
31453130d9SPedro F. Giffuni  * Content: Contains Hardware dependent functions
32f10a77bbSDavid C Somayajulu  */
33f10a77bbSDavid C Somayajulu 
34f10a77bbSDavid C Somayajulu #include <sys/cdefs.h>
35f10a77bbSDavid C Somayajulu __FBSDID("$FreeBSD$");
36f10a77bbSDavid C Somayajulu 
37f10a77bbSDavid C Somayajulu #include "ql_os.h"
38f10a77bbSDavid C Somayajulu #include "ql_hw.h"
39f10a77bbSDavid C Somayajulu #include "ql_def.h"
40f10a77bbSDavid C Somayajulu #include "ql_inline.h"
41f10a77bbSDavid C Somayajulu #include "ql_ver.h"
42f10a77bbSDavid C Somayajulu #include "ql_glbl.h"
43f10a77bbSDavid C Somayajulu #include "ql_dbg.h"
44f10a77bbSDavid C Somayajulu 
45f10a77bbSDavid C Somayajulu /*
46f10a77bbSDavid C Somayajulu  * Static Functions
47f10a77bbSDavid C Somayajulu  */
48f10a77bbSDavid C Somayajulu 
49f10a77bbSDavid C Somayajulu static void qla_del_rcv_cntxt(qla_host_t *ha);
50f10a77bbSDavid C Somayajulu static int qla_init_rcv_cntxt(qla_host_t *ha);
51f10a77bbSDavid C Somayajulu static void qla_del_xmt_cntxt(qla_host_t *ha);
52f10a77bbSDavid C Somayajulu static int qla_init_xmt_cntxt(qla_host_t *ha);
53f10a77bbSDavid C Somayajulu static void qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx);
54f10a77bbSDavid C Somayajulu static int qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
55f10a77bbSDavid C Somayajulu 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause);
5635291c22SDavid C Somayajulu static int qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx,
5735291c22SDavid C Somayajulu 	uint32_t num_intrs, uint32_t create);
58f10a77bbSDavid C Somayajulu static int qla_config_rss(qla_host_t *ha, uint16_t cntxt_id);
59f10a77bbSDavid C Somayajulu static int qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id,
6035291c22SDavid C Somayajulu 	int tenable, int rcv);
61f10a77bbSDavid C Somayajulu static int qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode);
62f10a77bbSDavid C Somayajulu static int qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id);
63f10a77bbSDavid C Somayajulu 
64f10a77bbSDavid C Somayajulu static int qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd,
65f10a77bbSDavid C Somayajulu 		uint8_t *hdr);
66f10a77bbSDavid C Somayajulu static int qla_hw_add_all_mcast(qla_host_t *ha);
67f10a77bbSDavid C Somayajulu static int qla_hw_del_all_mcast(qla_host_t *ha);
6835291c22SDavid C Somayajulu static int qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds);
6935291c22SDavid C Somayajulu 
7035291c22SDavid C Somayajulu static int qla_init_nic_func(qla_host_t *ha);
7135291c22SDavid C Somayajulu static int qla_stop_nic_func(qla_host_t *ha);
7235291c22SDavid C Somayajulu static int qla_query_fw_dcbx_caps(qla_host_t *ha);
7335291c22SDavid C Somayajulu static int qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits);
7435291c22SDavid C Somayajulu static int qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits);
7535291c22SDavid C Somayajulu static void qla_get_quick_stats(qla_host_t *ha);
76f10a77bbSDavid C Somayajulu 
77f10a77bbSDavid C Somayajulu static int qla_minidump_init(qla_host_t *ha);
78f10a77bbSDavid C Somayajulu static void qla_minidump_free(qla_host_t *ha);
79f10a77bbSDavid C Somayajulu 
80f10a77bbSDavid C Somayajulu 
81f10a77bbSDavid C Somayajulu static int
82f10a77bbSDavid C Somayajulu qla_sysctl_get_drvr_stats(SYSCTL_HANDLER_ARGS)
83f10a77bbSDavid C Somayajulu {
84f10a77bbSDavid C Somayajulu         int err = 0, ret;
85f10a77bbSDavid C Somayajulu         qla_host_t *ha;
86f10a77bbSDavid C Somayajulu 	uint32_t i;
87f10a77bbSDavid C Somayajulu 
88f10a77bbSDavid C Somayajulu         err = sysctl_handle_int(oidp, &ret, 0, req);
89f10a77bbSDavid C Somayajulu 
90f10a77bbSDavid C Somayajulu         if (err || !req->newptr)
91f10a77bbSDavid C Somayajulu                 return (err);
92f10a77bbSDavid C Somayajulu 
93f10a77bbSDavid C Somayajulu         if (ret == 1) {
94f10a77bbSDavid C Somayajulu 
95f10a77bbSDavid C Somayajulu                 ha = (qla_host_t *)arg1;
96f10a77bbSDavid C Somayajulu 
97f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++)
98f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
99f10a77bbSDavid C Somayajulu 				"%s: sds_ring[%d] = %p\n", __func__,i,
100f10a77bbSDavid C Somayajulu 				(void *)ha->hw.sds[i].intr_count);
101f10a77bbSDavid C Somayajulu 
102f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_tx_rings; i++)
103f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
104f10a77bbSDavid C Somayajulu 				"%s: tx[%d] = %p\n", __func__,i,
105f10a77bbSDavid C Somayajulu 				(void *)ha->tx_ring[i].count);
106f10a77bbSDavid C Somayajulu 
107f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_rds_rings; i++)
108f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
109f10a77bbSDavid C Somayajulu 				"%s: rds_ring[%d] = %p\n", __func__,i,
110f10a77bbSDavid C Somayajulu 				(void *)ha->hw.rds[i].count);
111f10a77bbSDavid C Somayajulu 
112f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: lro_pkt_count = %p\n", __func__,
113f10a77bbSDavid C Somayajulu 			(void *)ha->lro_pkt_count);
114f10a77bbSDavid C Somayajulu 
115f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: lro_bytes = %p\n", __func__,
116f10a77bbSDavid C Somayajulu 			(void *)ha->lro_bytes);
11735291c22SDavid C Somayajulu 
11835291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV
11935291c22SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: iscsi_pkts = %p\n", __func__,
12035291c22SDavid C Somayajulu 			(void *)ha->hw.iscsi_pkt_count);
12135291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
12235291c22SDavid C Somayajulu 
12335291c22SDavid C Somayajulu 	}
12435291c22SDavid C Somayajulu 	return (err);
12535291c22SDavid C Somayajulu }
12635291c22SDavid C Somayajulu 
12735291c22SDavid C Somayajulu static int
12835291c22SDavid C Somayajulu qla_sysctl_get_quick_stats(SYSCTL_HANDLER_ARGS)
12935291c22SDavid C Somayajulu {
13035291c22SDavid C Somayajulu 	int err, ret = 0;
13135291c22SDavid C Somayajulu 	qla_host_t *ha;
13235291c22SDavid C Somayajulu 
13335291c22SDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
13435291c22SDavid C Somayajulu 
13535291c22SDavid C Somayajulu 	if (err || !req->newptr)
13635291c22SDavid C Somayajulu 		return (err);
13735291c22SDavid C Somayajulu 
13835291c22SDavid C Somayajulu 	if (ret == 1) {
13935291c22SDavid C Somayajulu 		ha = (qla_host_t *)arg1;
14035291c22SDavid C Somayajulu 		qla_get_quick_stats(ha);
141f10a77bbSDavid C Somayajulu 	}
142f10a77bbSDavid C Somayajulu 	return (err);
143f10a77bbSDavid C Somayajulu }
144f10a77bbSDavid C Somayajulu 
145f10a77bbSDavid C Somayajulu #ifdef QL_DBG
146f10a77bbSDavid C Somayajulu 
147f10a77bbSDavid C Somayajulu static void
148f10a77bbSDavid C Somayajulu qla_stop_pegs(qla_host_t *ha)
149f10a77bbSDavid C Somayajulu {
150f10a77bbSDavid C Somayajulu         uint32_t val = 1;
151f10a77bbSDavid C Somayajulu 
152f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0);
153f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0);
154f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0);
155f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0);
156f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0);
157f10a77bbSDavid C Somayajulu         device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__);
158f10a77bbSDavid C Somayajulu }
159f10a77bbSDavid C Somayajulu 
160f10a77bbSDavid C Somayajulu static int
161f10a77bbSDavid C Somayajulu qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)
162f10a77bbSDavid C Somayajulu {
163f10a77bbSDavid C Somayajulu 	int err, ret = 0;
164f10a77bbSDavid C Somayajulu 	qla_host_t *ha;
165f10a77bbSDavid C Somayajulu 
166f10a77bbSDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
167f10a77bbSDavid C Somayajulu 
168f10a77bbSDavid C Somayajulu 
169f10a77bbSDavid C Somayajulu 	if (err || !req->newptr)
170f10a77bbSDavid C Somayajulu 		return (err);
171f10a77bbSDavid C Somayajulu 
172f10a77bbSDavid C Somayajulu 	if (ret == 1) {
173f10a77bbSDavid C Somayajulu 		ha = (qla_host_t *)arg1;
174f10a77bbSDavid C Somayajulu 		(void)QLA_LOCK(ha, __func__, 0);
175f10a77bbSDavid C Somayajulu 		qla_stop_pegs(ha);
176f10a77bbSDavid C Somayajulu 		QLA_UNLOCK(ha, __func__);
177f10a77bbSDavid C Somayajulu 	}
178f10a77bbSDavid C Somayajulu 
179f10a77bbSDavid C Somayajulu 	return err;
180f10a77bbSDavid C Somayajulu }
181f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */
182f10a77bbSDavid C Somayajulu 
18335291c22SDavid C Somayajulu static int
18435291c22SDavid C Somayajulu qla_validate_set_port_cfg_bit(uint32_t bits)
18535291c22SDavid C Somayajulu {
18635291c22SDavid C Somayajulu         if ((bits & 0xF) > 1)
18735291c22SDavid C Somayajulu                 return (-1);
18835291c22SDavid C Somayajulu 
18935291c22SDavid C Somayajulu         if (((bits >> 4) & 0xF) > 2)
19035291c22SDavid C Somayajulu                 return (-1);
19135291c22SDavid C Somayajulu 
19235291c22SDavid C Somayajulu         if (((bits >> 8) & 0xF) > 2)
19335291c22SDavid C Somayajulu                 return (-1);
19435291c22SDavid C Somayajulu 
19535291c22SDavid C Somayajulu         return (0);
19635291c22SDavid C Somayajulu }
19735291c22SDavid C Somayajulu 
19835291c22SDavid C Somayajulu static int
19935291c22SDavid C Somayajulu qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS)
20035291c22SDavid C Somayajulu {
20135291c22SDavid C Somayajulu         int err, ret = 0;
20235291c22SDavid C Somayajulu         qla_host_t *ha;
20335291c22SDavid C Somayajulu         uint32_t cfg_bits;
20435291c22SDavid C Somayajulu 
20535291c22SDavid C Somayajulu         err = sysctl_handle_int(oidp, &ret, 0, req);
20635291c22SDavid C Somayajulu 
20735291c22SDavid C Somayajulu         if (err || !req->newptr)
20835291c22SDavid C Somayajulu                 return (err);
20935291c22SDavid C Somayajulu 
21035291c22SDavid C Somayajulu         if ((qla_validate_set_port_cfg_bit((uint32_t)ret) == 0)) {
21135291c22SDavid C Somayajulu 
21235291c22SDavid C Somayajulu                 ha = (qla_host_t *)arg1;
21335291c22SDavid C Somayajulu 
21435291c22SDavid C Somayajulu                 err = qla_get_port_config(ha, &cfg_bits);
21535291c22SDavid C Somayajulu 
21635291c22SDavid C Somayajulu                 if (err)
21735291c22SDavid C Somayajulu                         goto qla_sysctl_set_port_cfg_exit;
21835291c22SDavid C Somayajulu 
21935291c22SDavid C Somayajulu                 if (ret & 0x1) {
22035291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_DCBX_ENABLE;
22135291c22SDavid C Somayajulu                 } else {
22235291c22SDavid C Somayajulu                         cfg_bits &= ~Q8_PORT_CFG_BITS_DCBX_ENABLE;
22335291c22SDavid C Somayajulu                 }
22435291c22SDavid C Somayajulu 
22535291c22SDavid C Somayajulu                 ret = ret >> 4;
22635291c22SDavid C Somayajulu                 cfg_bits &= ~Q8_PORT_CFG_BITS_PAUSE_CFG_MASK;
22735291c22SDavid C Somayajulu 
22835291c22SDavid C Somayajulu                 if ((ret & 0xF) == 0) {
22935291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_DISABLED;
23035291c22SDavid C Somayajulu                 } else if ((ret & 0xF) == 1){
23135291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_STD;
23235291c22SDavid C Somayajulu                 } else {
23335291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_PPM;
23435291c22SDavid C Somayajulu                 }
23535291c22SDavid C Somayajulu 
23635291c22SDavid C Somayajulu                 ret = ret >> 4;
23735291c22SDavid C Somayajulu                 cfg_bits &= ~Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK;
23835291c22SDavid C Somayajulu 
23935291c22SDavid C Somayajulu                 if (ret == 0) {
24035291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT_RCV;
24135291c22SDavid C Somayajulu                 } else if (ret == 1){
24235291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT;
24335291c22SDavid C Somayajulu                 } else {
24435291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_RCV;
24535291c22SDavid C Somayajulu                 }
24635291c22SDavid C Somayajulu 
24735291c22SDavid C Somayajulu                 err = qla_set_port_config(ha, cfg_bits);
24835291c22SDavid C Somayajulu         } else {
24935291c22SDavid C Somayajulu                 ha = (qla_host_t *)arg1;
25035291c22SDavid C Somayajulu 
25135291c22SDavid C Somayajulu                 err = qla_get_port_config(ha, &cfg_bits);
25235291c22SDavid C Somayajulu         }
25335291c22SDavid C Somayajulu 
25435291c22SDavid C Somayajulu qla_sysctl_set_port_cfg_exit:
25535291c22SDavid C Somayajulu         return err;
25635291c22SDavid C Somayajulu }
25735291c22SDavid C Somayajulu 
258f10a77bbSDavid C Somayajulu /*
259f10a77bbSDavid C Somayajulu  * Name: ql_hw_add_sysctls
260f10a77bbSDavid C Somayajulu  * Function: Add P3Plus specific sysctls
261f10a77bbSDavid C Somayajulu  */
262f10a77bbSDavid C Somayajulu void
263f10a77bbSDavid C Somayajulu ql_hw_add_sysctls(qla_host_t *ha)
264f10a77bbSDavid C Somayajulu {
265f10a77bbSDavid C Somayajulu         device_t	dev;
266f10a77bbSDavid C Somayajulu 
267f10a77bbSDavid C Somayajulu         dev = ha->pci_dev;
268f10a77bbSDavid C Somayajulu 
269f10a77bbSDavid C Somayajulu 	ha->hw.num_sds_rings = MAX_SDS_RINGS;
270f10a77bbSDavid C Somayajulu 	ha->hw.num_rds_rings = MAX_RDS_RINGS;
271f10a77bbSDavid C Somayajulu 	ha->hw.num_tx_rings = NUM_TX_RINGS;
272f10a77bbSDavid C Somayajulu 
273f10a77bbSDavid C Somayajulu 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
274f10a77bbSDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
275f10a77bbSDavid C Somayajulu 		OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings,
276f10a77bbSDavid C Somayajulu 		ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings");
277f10a77bbSDavid C Somayajulu 
278f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
279f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
280f10a77bbSDavid C Somayajulu                 OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings,
281f10a77bbSDavid C Somayajulu 		ha->hw.num_sds_rings, "Number of Status Descriptor Rings");
282f10a77bbSDavid C Somayajulu 
283f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
284f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
285f10a77bbSDavid C Somayajulu                 OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings,
286f10a77bbSDavid C Somayajulu 		ha->hw.num_tx_rings, "Number of Transmit Rings");
287f10a77bbSDavid C Somayajulu 
288f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
289f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
290f10a77bbSDavid C Somayajulu                 OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx,
291f10a77bbSDavid C Somayajulu 		ha->txr_idx, "Tx Ring Used");
292f10a77bbSDavid C Somayajulu 
293f10a77bbSDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
294f10a77bbSDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
295f10a77bbSDavid C Somayajulu 		OID_AUTO, "drvr_stats", CTLTYPE_INT | CTLFLAG_RW,
296f10a77bbSDavid C Somayajulu 		(void *)ha, 0,
297f10a77bbSDavid C Somayajulu 		qla_sysctl_get_drvr_stats, "I", "Driver Maintained Statistics");
298f10a77bbSDavid C Somayajulu 
29935291c22SDavid C Somayajulu         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
30035291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
30135291c22SDavid C Somayajulu                 OID_AUTO, "quick_stats", CTLTYPE_INT | CTLFLAG_RW,
30235291c22SDavid C Somayajulu                 (void *)ha, 0,
30335291c22SDavid C Somayajulu                 qla_sysctl_get_quick_stats, "I", "Quick Statistics");
30435291c22SDavid C Somayajulu 
305f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
306f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
307f10a77bbSDavid C Somayajulu                 OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs,
308f10a77bbSDavid C Somayajulu 		ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt");
309f10a77bbSDavid C Somayajulu 
310f10a77bbSDavid C Somayajulu 	ha->hw.sds_cidx_thres = 32;
311f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
312f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
313f10a77bbSDavid C Somayajulu                 OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres,
314f10a77bbSDavid C Somayajulu 		ha->hw.sds_cidx_thres,
315f10a77bbSDavid C Somayajulu 		"Number of SDS entries to process before updating"
316f10a77bbSDavid C Somayajulu 		" SDS Ring Consumer Index");
317f10a77bbSDavid C Somayajulu 
318f10a77bbSDavid C Somayajulu 	ha->hw.rds_pidx_thres = 32;
319f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
320f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
321f10a77bbSDavid C Somayajulu                 OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres,
322f10a77bbSDavid C Somayajulu 		ha->hw.rds_pidx_thres,
323f10a77bbSDavid C Somayajulu 		"Number of Rcv Rings Entries to post before updating"
324f10a77bbSDavid C Somayajulu 		" RDS Ring Producer Index");
325f10a77bbSDavid C Somayajulu 
32635291c22SDavid C Somayajulu         ha->hw.rcv_intr_coalesce = (3 << 16) | 256;
327c12c5bfbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
328c12c5bfbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
32935291c22SDavid C Somayajulu                 OID_AUTO, "rcv_intr_coalesce", CTLFLAG_RW,
33035291c22SDavid C Somayajulu                 &ha->hw.rcv_intr_coalesce,
33135291c22SDavid C Somayajulu                 ha->hw.rcv_intr_coalesce,
33235291c22SDavid C Somayajulu                 "Rcv Intr Coalescing Parameters\n"
33335291c22SDavid C Somayajulu                 "\tbits 15:0 max packets\n"
33435291c22SDavid C Somayajulu                 "\tbits 31:16 max micro-seconds to wait\n"
33535291c22SDavid C Somayajulu                 "\tplease run\n"
33635291c22SDavid C Somayajulu                 "\tifconfig <if> down && ifconfig <if> up\n"
33735291c22SDavid C Somayajulu                 "\tto take effect \n");
33835291c22SDavid C Somayajulu 
33935291c22SDavid C Somayajulu         ha->hw.xmt_intr_coalesce = (64 << 16) | 64;
34035291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
34135291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
34235291c22SDavid C Somayajulu                 OID_AUTO, "xmt_intr_coalesce", CTLFLAG_RW,
34335291c22SDavid C Somayajulu                 &ha->hw.xmt_intr_coalesce,
34435291c22SDavid C Somayajulu                 ha->hw.xmt_intr_coalesce,
34535291c22SDavid C Somayajulu                 "Xmt Intr Coalescing Parameters\n"
34635291c22SDavid C Somayajulu                 "\tbits 15:0 max packets\n"
34735291c22SDavid C Somayajulu                 "\tbits 31:16 max micro-seconds to wait\n"
34835291c22SDavid C Somayajulu                 "\tplease run\n"
34935291c22SDavid C Somayajulu                 "\tifconfig <if> down && ifconfig <if> up\n"
35035291c22SDavid C Somayajulu                 "\tto take effect \n");
35135291c22SDavid C Somayajulu 
35235291c22SDavid C Somayajulu         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
35335291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
35435291c22SDavid C Somayajulu                 OID_AUTO, "port_cfg", CTLTYPE_INT | CTLFLAG_RW,
35535291c22SDavid C Somayajulu                 (void *)ha, 0,
35635291c22SDavid C Somayajulu                 qla_sysctl_port_cfg, "I",
35735291c22SDavid C Somayajulu                         "Set Port Configuration if values below "
35835291c22SDavid C Somayajulu                         "otherwise Get Port Configuration\n"
35935291c22SDavid C Somayajulu                         "\tBits 0-3 ; 1 = DCBX Enable; 0 = DCBX Disable\n"
36035291c22SDavid C Somayajulu                         "\tBits 4-7 : 0 = no pause; 1 = std ; 2 = ppm \n"
36135291c22SDavid C Somayajulu                         "\tBits 8-11: std pause cfg; 0 = xmt and rcv;"
36235291c22SDavid C Somayajulu                         " 1 = xmt only; 2 = rcv only;\n"
36335291c22SDavid C Somayajulu                 );
36435291c22SDavid C Somayajulu 
36535291c22SDavid C Somayajulu         ha->hw.enable_9kb = 1;
36635291c22SDavid C Somayajulu 
36735291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
36835291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
36935291c22SDavid C Somayajulu                 OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb,
37035291c22SDavid C Somayajulu                 ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000");
371c12c5bfbSDavid C Somayajulu 
372f10a77bbSDavid C Somayajulu 	ha->hw.mdump_active = 0;
373f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
374f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
375f10a77bbSDavid C Somayajulu                 OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active,
376f10a77bbSDavid C Somayajulu 		ha->hw.mdump_active,
377f10a77bbSDavid C Somayajulu 		"Minidump Utility is Active \n"
378f10a77bbSDavid C Somayajulu 		"\t 0 = Minidump Utility is not active\n"
379f10a77bbSDavid C Somayajulu 		"\t 1 = Minidump Utility is retrieved on this port\n"
380f10a77bbSDavid C Somayajulu 		"\t 2 = Minidump Utility is retrieved on the other port\n");
381f10a77bbSDavid C Somayajulu 
382f10a77bbSDavid C Somayajulu 	ha->hw.mdump_start = 0;
383f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
384f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
385f10a77bbSDavid C Somayajulu                 OID_AUTO, "minidump_start", CTLFLAG_RW,
386f10a77bbSDavid C Somayajulu 		&ha->hw.mdump_start, ha->hw.mdump_start,
387f10a77bbSDavid C Somayajulu 		"Minidump Utility can start minidump process");
388f10a77bbSDavid C Somayajulu #ifdef QL_DBG
389f10a77bbSDavid C Somayajulu 
390467dcb5aSDavid C Somayajulu 	ha->err_inject = 0;
391f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
392f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
393f10a77bbSDavid C Somayajulu                 OID_AUTO, "err_inject",
394f10a77bbSDavid C Somayajulu                 CTLFLAG_RW, &ha->err_inject, ha->err_inject,
395f10a77bbSDavid C Somayajulu                 "Error to be injected\n"
396f10a77bbSDavid C Somayajulu                 "\t\t\t 0: No Errors\n"
397f10a77bbSDavid C Somayajulu                 "\t\t\t 1: rcv: rxb struct invalid\n"
398f10a77bbSDavid C Somayajulu                 "\t\t\t 2: rcv: mp == NULL\n"
399f10a77bbSDavid C Somayajulu                 "\t\t\t 3: lro: rxb struct invalid\n"
400f10a77bbSDavid C Somayajulu                 "\t\t\t 4: lro: mp == NULL\n"
401f10a77bbSDavid C Somayajulu                 "\t\t\t 5: rcv: num handles invalid\n"
402f10a77bbSDavid C Somayajulu                 "\t\t\t 6: reg: indirect reg rd_wr failure\n"
403f10a77bbSDavid C Somayajulu                 "\t\t\t 7: ocm: offchip memory rd_wr failure\n"
404f10a77bbSDavid C Somayajulu                 "\t\t\t 8: mbx: mailbox command failure\n"
405f10a77bbSDavid C Somayajulu                 "\t\t\t 9: heartbeat failure\n"
406f10a77bbSDavid C Somayajulu                 "\t\t\t A: temperature failure\n" );
407f10a77bbSDavid C Somayajulu 
408f10a77bbSDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
409f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
410f10a77bbSDavid C Somayajulu                 OID_AUTO, "peg_stop", CTLTYPE_INT | CTLFLAG_RW,
411f10a77bbSDavid C Somayajulu                 (void *)ha, 0,
412f10a77bbSDavid C Somayajulu                 qla_sysctl_stop_pegs, "I", "Peg Stop");
413f10a77bbSDavid C Somayajulu 
414f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */
415f10a77bbSDavid C Somayajulu 
41635291c22SDavid C Somayajulu         ha->hw.user_pri_nic = 0;
41735291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
41835291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
41935291c22SDavid C Somayajulu                 OID_AUTO, "user_pri_nic", CTLFLAG_RW, &ha->hw.user_pri_nic,
42035291c22SDavid C Somayajulu                 ha->hw.user_pri_nic,
42135291c22SDavid C Somayajulu                 "VLAN Tag User Priority for Normal Ethernet Packets");
42235291c22SDavid C Somayajulu 
42335291c22SDavid C Somayajulu         ha->hw.user_pri_iscsi = 4;
42435291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
42535291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
42635291c22SDavid C Somayajulu                 OID_AUTO, "user_pri_iscsi", CTLFLAG_RW, &ha->hw.user_pri_iscsi,
42735291c22SDavid C Somayajulu                 ha->hw.user_pri_iscsi,
42835291c22SDavid C Somayajulu                 "VLAN Tag User Priority for iSCSI Packets");
42935291c22SDavid C Somayajulu 
430f10a77bbSDavid C Somayajulu }
431f10a77bbSDavid C Somayajulu 
432f10a77bbSDavid C Somayajulu void
433f10a77bbSDavid C Somayajulu ql_hw_link_status(qla_host_t *ha)
434f10a77bbSDavid C Somayajulu {
435f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui);
436f10a77bbSDavid C Somayajulu 
437f10a77bbSDavid C Somayajulu 	if (ha->hw.link_up) {
438f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link Up\n");
439f10a77bbSDavid C Somayajulu 	} else {
440f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link Down\n");
441f10a77bbSDavid C Somayajulu 	}
442f10a77bbSDavid C Somayajulu 
443f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.fduplex) {
444f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Full Duplex\n");
445f10a77bbSDavid C Somayajulu 	} else {
446f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Half Duplex\n");
447f10a77bbSDavid C Somayajulu 	}
448f10a77bbSDavid C Somayajulu 
449f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.autoneg) {
450f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Auto Negotiation Enabled\n");
451f10a77bbSDavid C Somayajulu 	} else {
452f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Auto Negotiation Disabled\n");
453f10a77bbSDavid C Somayajulu 	}
454f10a77bbSDavid C Somayajulu 
455f10a77bbSDavid C Somayajulu 	switch (ha->hw.link_speed) {
456f10a77bbSDavid C Somayajulu 	case 0x710:
457f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 10Gps\n");
458f10a77bbSDavid C Somayajulu 		break;
459f10a77bbSDavid C Somayajulu 
460f10a77bbSDavid C Somayajulu 	case 0x3E8:
461f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 1Gps\n");
462f10a77bbSDavid C Somayajulu 		break;
463f10a77bbSDavid C Somayajulu 
464f10a77bbSDavid C Somayajulu 	case 0x64:
465f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n");
466f10a77bbSDavid C Somayajulu 		break;
467f10a77bbSDavid C Somayajulu 
468f10a77bbSDavid C Somayajulu 	default:
469f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t Unknown\n");
470f10a77bbSDavid C Somayajulu 		break;
471f10a77bbSDavid C Somayajulu 	}
472f10a77bbSDavid C Somayajulu 
473f10a77bbSDavid C Somayajulu 	switch (ha->hw.module_type) {
474f10a77bbSDavid C Somayajulu 
475f10a77bbSDavid C Somayajulu 	case 0x01:
476f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n");
477f10a77bbSDavid C Somayajulu 		break;
478f10a77bbSDavid C Somayajulu 
479f10a77bbSDavid C Somayajulu 	case 0x02:
480f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-LR\n");
481f10a77bbSDavid C Somayajulu 		break;
482f10a77bbSDavid C Somayajulu 
483f10a77bbSDavid C Somayajulu 	case 0x03:
484f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-SR\n");
485f10a77bbSDavid C Somayajulu 		break;
486f10a77bbSDavid C Somayajulu 
487f10a77bbSDavid C Somayajulu 	case 0x04:
488f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
489f10a77bbSDavid C Somayajulu 			"Module Type 10GE Passive Copper(Compliant)[%d m]\n",
490f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
491f10a77bbSDavid C Somayajulu 		break;
492f10a77bbSDavid C Somayajulu 
493f10a77bbSDavid C Somayajulu 	case 0x05:
494f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GE Active"
495f10a77bbSDavid C Somayajulu 			" Limiting Copper(Compliant)[%d m]\n",
496f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
497f10a77bbSDavid C Somayajulu 		break;
498f10a77bbSDavid C Somayajulu 
499f10a77bbSDavid C Somayajulu 	case 0x06:
500f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
501f10a77bbSDavid C Somayajulu 			"Module Type 10GE Passive Copper"
502f10a77bbSDavid C Somayajulu 			" (Legacy, Best Effort)[%d m]\n",
503f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
504f10a77bbSDavid C Somayajulu 		break;
505f10a77bbSDavid C Somayajulu 
506f10a77bbSDavid C Somayajulu 	case 0x07:
507f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-SX\n");
508f10a77bbSDavid C Somayajulu 		break;
509f10a77bbSDavid C Somayajulu 
510f10a77bbSDavid C Somayajulu 	case 0x08:
511f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-LX\n");
512f10a77bbSDavid C Somayajulu 		break;
513f10a77bbSDavid C Somayajulu 
514f10a77bbSDavid C Somayajulu 	case 0x09:
515f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-CX\n");
516f10a77bbSDavid C Somayajulu 		break;
517f10a77bbSDavid C Somayajulu 
518f10a77bbSDavid C Somayajulu 	case 0x0A:
519f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-T\n");
520f10a77bbSDavid C Somayajulu 		break;
521f10a77bbSDavid C Somayajulu 
522f10a77bbSDavid C Somayajulu 	case 0x0B:
523f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1GE Passive Copper"
524f10a77bbSDavid C Somayajulu 			"(Legacy, Best Effort)\n");
525f10a77bbSDavid C Somayajulu 		break;
526f10a77bbSDavid C Somayajulu 
527f10a77bbSDavid C Somayajulu 	default:
528f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n",
529f10a77bbSDavid C Somayajulu 			ha->hw.module_type);
530f10a77bbSDavid C Somayajulu 		break;
531f10a77bbSDavid C Somayajulu 	}
532f10a77bbSDavid C Somayajulu 
533f10a77bbSDavid C Somayajulu 	if (ha->hw.link_faults == 1)
534f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "SFP Power Fault\n");
535f10a77bbSDavid C Somayajulu }
536f10a77bbSDavid C Somayajulu 
537f10a77bbSDavid C Somayajulu /*
538f10a77bbSDavid C Somayajulu  * Name: ql_free_dma
539f10a77bbSDavid C Somayajulu  * Function: Frees the DMA'able memory allocated in ql_alloc_dma()
540f10a77bbSDavid C Somayajulu  */
541f10a77bbSDavid C Somayajulu void
542f10a77bbSDavid C Somayajulu ql_free_dma(qla_host_t *ha)
543f10a77bbSDavid C Somayajulu {
544f10a77bbSDavid C Somayajulu 	uint32_t i;
545f10a77bbSDavid C Somayajulu 
546f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.sds_ring) {
547f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
548f10a77bbSDavid C Somayajulu 			ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]);
549f10a77bbSDavid C Somayajulu 		}
550f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.sds_ring = 0;
551f10a77bbSDavid C Somayajulu 	}
552f10a77bbSDavid C Somayajulu 
553f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.rds_ring) {
554f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_rds_rings; i++) {
555f10a77bbSDavid C Somayajulu 			ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]);
556f10a77bbSDavid C Somayajulu 		}
557f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.rds_ring = 0;
558f10a77bbSDavid C Somayajulu 	}
559f10a77bbSDavid C Somayajulu 
560f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.tx_ring) {
561f10a77bbSDavid C Somayajulu 		ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring);
562f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.tx_ring = 0;
563f10a77bbSDavid C Somayajulu 	}
564f10a77bbSDavid C Somayajulu 	qla_minidump_free(ha);
565f10a77bbSDavid C Somayajulu }
566f10a77bbSDavid C Somayajulu 
567f10a77bbSDavid C Somayajulu /*
568f10a77bbSDavid C Somayajulu  * Name: ql_alloc_dma
569f10a77bbSDavid C Somayajulu  * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts.
570f10a77bbSDavid C Somayajulu  */
571f10a77bbSDavid C Somayajulu int
572f10a77bbSDavid C Somayajulu ql_alloc_dma(qla_host_t *ha)
573f10a77bbSDavid C Somayajulu {
574f10a77bbSDavid C Somayajulu         device_t                dev;
575f10a77bbSDavid C Somayajulu 	uint32_t		i, j, size, tx_ring_size;
576f10a77bbSDavid C Somayajulu 	qla_hw_t		*hw;
577f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t	*tx_cntxt;
578f10a77bbSDavid C Somayajulu 	uint8_t			*vaddr;
579f10a77bbSDavid C Somayajulu 	bus_addr_t		paddr;
580f10a77bbSDavid C Somayajulu 
581f10a77bbSDavid C Somayajulu         dev = ha->pci_dev;
582f10a77bbSDavid C Somayajulu 
583f10a77bbSDavid C Somayajulu         QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
584f10a77bbSDavid C Somayajulu 
585f10a77bbSDavid C Somayajulu 	hw = &ha->hw;
586f10a77bbSDavid C Somayajulu 	/*
587f10a77bbSDavid C Somayajulu 	 * Allocate Transmit Ring
588f10a77bbSDavid C Somayajulu 	 */
589f10a77bbSDavid C Somayajulu 	tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS);
590f10a77bbSDavid C Somayajulu 	size = (tx_ring_size * ha->hw.num_tx_rings);
591f10a77bbSDavid C Somayajulu 
592f10a77bbSDavid C Somayajulu 	hw->dma_buf.tx_ring.alignment = 8;
593f10a77bbSDavid C Somayajulu 	hw->dma_buf.tx_ring.size = size + PAGE_SIZE;
594f10a77bbSDavid C Somayajulu 
595f10a77bbSDavid C Somayajulu         if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) {
596f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: tx ring alloc failed\n", __func__);
597f10a77bbSDavid C Somayajulu                 goto ql_alloc_dma_exit;
598f10a77bbSDavid C Somayajulu         }
599f10a77bbSDavid C Somayajulu 
600f10a77bbSDavid C Somayajulu 	vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b;
601f10a77bbSDavid C Somayajulu 	paddr = hw->dma_buf.tx_ring.dma_addr;
602f10a77bbSDavid C Somayajulu 
603f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
604f10a77bbSDavid C Somayajulu 		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
605f10a77bbSDavid C Somayajulu 
606f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr;
607f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_ring_paddr = paddr;
608f10a77bbSDavid C Somayajulu 
609f10a77bbSDavid C Somayajulu 		vaddr += tx_ring_size;
610f10a77bbSDavid C Somayajulu 		paddr += tx_ring_size;
611f10a77bbSDavid C Somayajulu 	}
612f10a77bbSDavid C Somayajulu 
613f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
614f10a77bbSDavid C Somayajulu 		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
615f10a77bbSDavid C Somayajulu 
616f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_cons = (uint32_t *)vaddr;
617f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_cons_paddr = paddr;
618f10a77bbSDavid C Somayajulu 
619f10a77bbSDavid C Somayajulu 		vaddr += sizeof (uint32_t);
620f10a77bbSDavid C Somayajulu 		paddr += sizeof (uint32_t);
621f10a77bbSDavid C Somayajulu 	}
622f10a77bbSDavid C Somayajulu 
623f10a77bbSDavid C Somayajulu         ha->hw.dma_buf.flags.tx_ring = 1;
624f10a77bbSDavid C Somayajulu 
625f10a77bbSDavid C Somayajulu 	QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n",
626f10a77bbSDavid C Somayajulu 		__func__, (void *)(hw->dma_buf.tx_ring.dma_addr),
627f10a77bbSDavid C Somayajulu 		hw->dma_buf.tx_ring.dma_b));
628f10a77bbSDavid C Somayajulu 	/*
629f10a77bbSDavid C Somayajulu 	 * Allocate Receive Descriptor Rings
630f10a77bbSDavid C Somayajulu 	 */
631f10a77bbSDavid C Somayajulu 
632f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_rds_rings; i++) {
633f10a77bbSDavid C Somayajulu 
634f10a77bbSDavid C Somayajulu 		hw->dma_buf.rds_ring[i].alignment = 8;
635f10a77bbSDavid C Somayajulu 		hw->dma_buf.rds_ring[i].size =
636f10a77bbSDavid C Somayajulu 			(sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS;
637f10a77bbSDavid C Somayajulu 
638f10a77bbSDavid C Somayajulu 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) {
639f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: rds ring[%d] alloc failed\n",
640f10a77bbSDavid C Somayajulu 				__func__, i);
641f10a77bbSDavid C Somayajulu 
642f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
643f10a77bbSDavid C Somayajulu 				ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]);
644f10a77bbSDavid C Somayajulu 
645f10a77bbSDavid C Somayajulu 			goto ql_alloc_dma_exit;
646f10a77bbSDavid C Somayajulu 		}
647f10a77bbSDavid C Somayajulu 		QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n",
648f10a77bbSDavid C Somayajulu 			__func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr),
649f10a77bbSDavid C Somayajulu 			hw->dma_buf.rds_ring[i].dma_b));
650f10a77bbSDavid C Somayajulu 	}
651f10a77bbSDavid C Somayajulu 
652f10a77bbSDavid C Somayajulu 	hw->dma_buf.flags.rds_ring = 1;
653f10a77bbSDavid C Somayajulu 
654f10a77bbSDavid C Somayajulu 	/*
655f10a77bbSDavid C Somayajulu 	 * Allocate Status Descriptor Rings
656f10a77bbSDavid C Somayajulu 	 */
657f10a77bbSDavid C Somayajulu 
658f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
659f10a77bbSDavid C Somayajulu 		hw->dma_buf.sds_ring[i].alignment = 8;
660f10a77bbSDavid C Somayajulu 		hw->dma_buf.sds_ring[i].size =
661f10a77bbSDavid C Somayajulu 			(sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS;
662f10a77bbSDavid C Somayajulu 
663f10a77bbSDavid C Somayajulu 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) {
664f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: sds ring alloc failed\n",
665f10a77bbSDavid C Somayajulu 				__func__);
666f10a77bbSDavid C Somayajulu 
667f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
668f10a77bbSDavid C Somayajulu 				ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]);
669f10a77bbSDavid C Somayajulu 
670f10a77bbSDavid C Somayajulu 			goto ql_alloc_dma_exit;
671f10a77bbSDavid C Somayajulu 		}
672f10a77bbSDavid C Somayajulu 		QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n",
673f10a77bbSDavid C Somayajulu 			__func__, i,
674f10a77bbSDavid C Somayajulu 			(void *)(hw->dma_buf.sds_ring[i].dma_addr),
675f10a77bbSDavid C Somayajulu 			hw->dma_buf.sds_ring[i].dma_b));
676f10a77bbSDavid C Somayajulu 	}
677f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
678f10a77bbSDavid C Somayajulu 		hw->sds[i].sds_ring_base =
679f10a77bbSDavid C Somayajulu 			(q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b;
680f10a77bbSDavid C Somayajulu 	}
681f10a77bbSDavid C Somayajulu 
682f10a77bbSDavid C Somayajulu 	hw->dma_buf.flags.sds_ring = 1;
683f10a77bbSDavid C Somayajulu 
684f10a77bbSDavid C Somayajulu 	return 0;
685f10a77bbSDavid C Somayajulu 
686f10a77bbSDavid C Somayajulu ql_alloc_dma_exit:
687f10a77bbSDavid C Somayajulu 	ql_free_dma(ha);
688f10a77bbSDavid C Somayajulu 	return -1;
689f10a77bbSDavid C Somayajulu }
690f10a77bbSDavid C Somayajulu 
691f10a77bbSDavid C Somayajulu #define Q8_MBX_MSEC_DELAY	5000
692f10a77bbSDavid C Somayajulu 
693f10a77bbSDavid C Somayajulu static int
694f10a77bbSDavid C Somayajulu qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
695f10a77bbSDavid C Somayajulu 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause)
696f10a77bbSDavid C Somayajulu {
697f10a77bbSDavid C Somayajulu 	uint32_t i;
698f10a77bbSDavid C Somayajulu 	uint32_t data;
699f10a77bbSDavid C Somayajulu 	int ret = 0;
700f10a77bbSDavid C Somayajulu 
701f10a77bbSDavid C Somayajulu 	if (QL_ERR_INJECT(ha, INJCT_MBX_CMD_FAILURE)) {
702f10a77bbSDavid C Somayajulu 		ret = -3;
703f10a77bbSDavid C Somayajulu 		ha->qla_initiate_recovery = 1;
704f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
705f10a77bbSDavid C Somayajulu 	}
706f10a77bbSDavid C Somayajulu 
707f10a77bbSDavid C Somayajulu 	if (no_pause)
708f10a77bbSDavid C Somayajulu 		i = 1000;
709f10a77bbSDavid C Somayajulu 	else
710f10a77bbSDavid C Somayajulu 		i = Q8_MBX_MSEC_DELAY;
711f10a77bbSDavid C Somayajulu 
712f10a77bbSDavid C Somayajulu 	while (i) {
713f10a77bbSDavid C Somayajulu 		data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL);
714f10a77bbSDavid C Somayajulu 		if (data == 0)
715f10a77bbSDavid C Somayajulu 			break;
716f10a77bbSDavid C Somayajulu 		if (no_pause) {
717f10a77bbSDavid C Somayajulu 			DELAY(1000);
718f10a77bbSDavid C Somayajulu 		} else {
719f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
720f10a77bbSDavid C Somayajulu 		}
721f10a77bbSDavid C Somayajulu 		i--;
722f10a77bbSDavid C Somayajulu 	}
723f10a77bbSDavid C Somayajulu 
724f10a77bbSDavid C Somayajulu 	if (i == 0) {
725f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n",
726f10a77bbSDavid C Somayajulu 			__func__, data);
727f10a77bbSDavid C Somayajulu 		ret = -1;
728f10a77bbSDavid C Somayajulu 		ha->qla_initiate_recovery = 1;
729f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
730f10a77bbSDavid C Somayajulu 	}
731f10a77bbSDavid C Somayajulu 
732f10a77bbSDavid C Somayajulu 	for (i = 0; i < n_hmbox; i++) {
733f10a77bbSDavid C Somayajulu 		WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox);
734f10a77bbSDavid C Somayajulu 		h_mbox++;
735f10a77bbSDavid C Somayajulu 	}
736f10a77bbSDavid C Somayajulu 
737f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1);
738f10a77bbSDavid C Somayajulu 
739f10a77bbSDavid C Somayajulu 
740f10a77bbSDavid C Somayajulu 	i = Q8_MBX_MSEC_DELAY;
741f10a77bbSDavid C Somayajulu 	while (i) {
742f10a77bbSDavid C Somayajulu 		data = READ_REG32(ha, Q8_FW_MBOX_CNTRL);
743f10a77bbSDavid C Somayajulu 
744f10a77bbSDavid C Somayajulu 		if ((data & 0x3) == 1) {
745f10a77bbSDavid C Somayajulu 			data = READ_REG32(ha, Q8_FW_MBOX0);
746f10a77bbSDavid C Somayajulu 			if ((data & 0xF000) != 0x8000)
747f10a77bbSDavid C Somayajulu 				break;
748f10a77bbSDavid C Somayajulu 		}
749f10a77bbSDavid C Somayajulu 		if (no_pause) {
750f10a77bbSDavid C Somayajulu 			DELAY(1000);
751f10a77bbSDavid C Somayajulu 		} else {
752f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
753f10a77bbSDavid C Somayajulu 		}
754f10a77bbSDavid C Somayajulu 		i--;
755f10a77bbSDavid C Somayajulu 	}
756f10a77bbSDavid C Somayajulu 	if (i == 0) {
757f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n",
758f10a77bbSDavid C Somayajulu 			__func__, data);
759f10a77bbSDavid C Somayajulu 		ret = -2;
760f10a77bbSDavid C Somayajulu 		ha->qla_initiate_recovery = 1;
761f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
762f10a77bbSDavid C Somayajulu 	}
763f10a77bbSDavid C Somayajulu 
764f10a77bbSDavid C Somayajulu 	for (i = 0; i < n_fwmbox; i++) {
765f10a77bbSDavid C Somayajulu 		*fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2)));
766f10a77bbSDavid C Somayajulu 	}
767f10a77bbSDavid C Somayajulu 
768f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0);
769f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
770f10a77bbSDavid C Somayajulu 
771f10a77bbSDavid C Somayajulu exit_qla_mbx_cmd:
772f10a77bbSDavid C Somayajulu 	return (ret);
773f10a77bbSDavid C Somayajulu }
774f10a77bbSDavid C Somayajulu 
77535291c22SDavid C Somayajulu int
77635291c22SDavid C Somayajulu qla_get_nic_partition(qla_host_t *ha, uint32_t *supports_9kb,
77735291c22SDavid C Somayajulu 	uint32_t *num_rcvq)
778f10a77bbSDavid C Somayajulu {
779f10a77bbSDavid C Somayajulu 	uint32_t *mbox, err;
780f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
781f10a77bbSDavid C Somayajulu 
782f10a77bbSDavid C Somayajulu 	bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX));
783f10a77bbSDavid C Somayajulu 
784f10a77bbSDavid C Somayajulu 	mbox = ha->hw.mbox;
785f10a77bbSDavid C Somayajulu 
786f10a77bbSDavid C Somayajulu 	mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29);
787f10a77bbSDavid C Somayajulu 
788f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) {
789f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
790f10a77bbSDavid C Somayajulu 		return (-1);
791f10a77bbSDavid C Somayajulu 	}
792f10a77bbSDavid C Somayajulu 	err = mbox[0] >> 25;
793f10a77bbSDavid C Somayajulu 
79435291c22SDavid C Somayajulu 	if (supports_9kb != NULL) {
79535291c22SDavid C Somayajulu 		if (mbox[16] & 0x80) /* bit 7 of mbox 16 */
79635291c22SDavid C Somayajulu 			*supports_9kb = 1;
79735291c22SDavid C Somayajulu 		else
79835291c22SDavid C Somayajulu 			*supports_9kb = 0;
79935291c22SDavid C Somayajulu 	}
80035291c22SDavid C Somayajulu 
80135291c22SDavid C Somayajulu 	if (num_rcvq != NULL)
80235291c22SDavid C Somayajulu 		*num_rcvq =  ((mbox[6] >> 16) & 0xFFFF);
80335291c22SDavid C Somayajulu 
804f10a77bbSDavid C Somayajulu 	if ((err != 1) && (err != 0)) {
805f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
806f10a77bbSDavid C Somayajulu 		return (-1);
807f10a77bbSDavid C Somayajulu 	}
808f10a77bbSDavid C Somayajulu 	return 0;
809f10a77bbSDavid C Somayajulu }
810f10a77bbSDavid C Somayajulu 
811f10a77bbSDavid C Somayajulu static int
81235291c22SDavid C Somayajulu qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, uint32_t num_intrs,
81335291c22SDavid C Somayajulu 	uint32_t create)
814f10a77bbSDavid C Somayajulu {
815f10a77bbSDavid C Somayajulu 	uint32_t i, err;
816f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
817f10a77bbSDavid C Somayajulu 	q80_config_intr_t *c_intr;
818f10a77bbSDavid C Somayajulu 	q80_config_intr_rsp_t *c_intr_rsp;
819f10a77bbSDavid C Somayajulu 
820f10a77bbSDavid C Somayajulu 	c_intr = (q80_config_intr_t *)ha->hw.mbox;
821f10a77bbSDavid C Somayajulu 	bzero(c_intr, (sizeof (q80_config_intr_t)));
822f10a77bbSDavid C Somayajulu 
823f10a77bbSDavid C Somayajulu 	c_intr->opcode = Q8_MBX_CONFIG_INTR;
824f10a77bbSDavid C Somayajulu 
825f10a77bbSDavid C Somayajulu 	c_intr->count_version = (sizeof (q80_config_intr_t) >> 2);
826f10a77bbSDavid C Somayajulu 	c_intr->count_version |= Q8_MBX_CMD_VERSION;
827f10a77bbSDavid C Somayajulu 
828f10a77bbSDavid C Somayajulu 	c_intr->nentries = num_intrs;
829f10a77bbSDavid C Somayajulu 
830f10a77bbSDavid C Somayajulu 	for (i = 0; i < num_intrs; i++) {
831f10a77bbSDavid C Somayajulu 		if (create) {
832f10a77bbSDavid C Somayajulu 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE;
83335291c22SDavid C Somayajulu 			c_intr->intr[i].msix_index = start_idx + 1 + i;
834f10a77bbSDavid C Somayajulu 		} else {
835f10a77bbSDavid C Somayajulu 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE;
83635291c22SDavid C Somayajulu 			c_intr->intr[i].msix_index =
83735291c22SDavid C Somayajulu 				ha->hw.intr_id[(start_idx + i)];
838f10a77bbSDavid C Somayajulu 		}
839f10a77bbSDavid C Somayajulu 
840f10a77bbSDavid C Somayajulu 		c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X;
841f10a77bbSDavid C Somayajulu 	}
842f10a77bbSDavid C Somayajulu 
843f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_intr,
844f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_intr_t) >> 2),
845f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) {
846f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
847f10a77bbSDavid C Somayajulu 		return (-1);
848f10a77bbSDavid C Somayajulu 	}
849f10a77bbSDavid C Somayajulu 
850f10a77bbSDavid C Somayajulu 	c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox;
851f10a77bbSDavid C Somayajulu 
852f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status);
853f10a77bbSDavid C Somayajulu 
854f10a77bbSDavid C Somayajulu 	if (err) {
855f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x, %d]\n", __func__, err,
856f10a77bbSDavid C Somayajulu 			c_intr_rsp->nentries);
857f10a77bbSDavid C Somayajulu 
858f10a77bbSDavid C Somayajulu 		for (i = 0; i < c_intr_rsp->nentries; i++) {
859f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n",
860f10a77bbSDavid C Somayajulu 				__func__, i,
861f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].status,
862f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].intr_id,
863f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].intr_src);
864f10a77bbSDavid C Somayajulu 		}
865f10a77bbSDavid C Somayajulu 
866f10a77bbSDavid C Somayajulu 		return (-1);
867f10a77bbSDavid C Somayajulu 	}
868f10a77bbSDavid C Somayajulu 
869f10a77bbSDavid C Somayajulu 	for (i = 0; ((i < num_intrs) && create); i++) {
870f10a77bbSDavid C Somayajulu 		if (!c_intr_rsp->intr[i].status) {
87135291c22SDavid C Somayajulu 			ha->hw.intr_id[(start_idx + i)] =
87235291c22SDavid C Somayajulu 				c_intr_rsp->intr[i].intr_id;
87335291c22SDavid C Somayajulu 			ha->hw.intr_src[(start_idx + i)] =
87435291c22SDavid C Somayajulu 				c_intr_rsp->intr[i].intr_src;
875f10a77bbSDavid C Somayajulu 		}
876f10a77bbSDavid C Somayajulu 	}
877f10a77bbSDavid C Somayajulu 
878f10a77bbSDavid C Somayajulu 	return (0);
879f10a77bbSDavid C Somayajulu }
880f10a77bbSDavid C Somayajulu 
881f10a77bbSDavid C Somayajulu /*
882f10a77bbSDavid C Somayajulu  * Name: qla_config_rss
883f10a77bbSDavid C Somayajulu  * Function: Configure RSS for the context/interface.
884f10a77bbSDavid C Somayajulu  */
885f10a77bbSDavid C Somayajulu static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL,
886f10a77bbSDavid C Somayajulu 			0x8030f20c77cb2da3ULL,
887f10a77bbSDavid C Somayajulu 			0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
888f10a77bbSDavid C Somayajulu 			0x255b0ec26d5a56daULL };
889f10a77bbSDavid C Somayajulu 
890f10a77bbSDavid C Somayajulu static int
891f10a77bbSDavid C Somayajulu qla_config_rss(qla_host_t *ha, uint16_t cntxt_id)
892f10a77bbSDavid C Somayajulu {
893f10a77bbSDavid C Somayajulu 	q80_config_rss_t	*c_rss;
894f10a77bbSDavid C Somayajulu 	q80_config_rss_rsp_t	*c_rss_rsp;
895f10a77bbSDavid C Somayajulu 	uint32_t		err, i;
896f10a77bbSDavid C Somayajulu 	device_t		dev = ha->pci_dev;
897f10a77bbSDavid C Somayajulu 
898f10a77bbSDavid C Somayajulu 	c_rss = (q80_config_rss_t *)ha->hw.mbox;
899f10a77bbSDavid C Somayajulu 	bzero(c_rss, (sizeof (q80_config_rss_t)));
900f10a77bbSDavid C Somayajulu 
901f10a77bbSDavid C Somayajulu 	c_rss->opcode = Q8_MBX_CONFIG_RSS;
902f10a77bbSDavid C Somayajulu 
903f10a77bbSDavid C Somayajulu 	c_rss->count_version = (sizeof (q80_config_rss_t) >> 2);
904f10a77bbSDavid C Somayajulu 	c_rss->count_version |= Q8_MBX_CMD_VERSION;
905f10a77bbSDavid C Somayajulu 
906f10a77bbSDavid C Somayajulu 	c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP |
907f10a77bbSDavid C Somayajulu 				Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP);
90835291c22SDavid C Somayajulu 	//c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP |
90935291c22SDavid C Somayajulu 	//			Q8_MBX_RSS_HASH_TYPE_IPV6_TCP);
910f10a77bbSDavid C Somayajulu 
911f10a77bbSDavid C Somayajulu 	c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS;
912f10a77bbSDavid C Somayajulu 	c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE;
913f10a77bbSDavid C Somayajulu 
914f10a77bbSDavid C Somayajulu 	c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK;
915f10a77bbSDavid C Somayajulu 
916f10a77bbSDavid C Somayajulu 	c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID;
917f10a77bbSDavid C Somayajulu 	c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS;
918f10a77bbSDavid C Somayajulu 
919f10a77bbSDavid C Somayajulu 	c_rss->cntxt_id = cntxt_id;
920f10a77bbSDavid C Somayajulu 
921f10a77bbSDavid C Somayajulu 	for (i = 0; i < 5; i++) {
922f10a77bbSDavid C Somayajulu 		c_rss->rss_key[i] = rss_key[i];
923f10a77bbSDavid C Somayajulu 	}
924f10a77bbSDavid C Somayajulu 
925f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss,
926f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_rss_t) >> 2),
927f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) {
928f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
929f10a77bbSDavid C Somayajulu 		return (-1);
930f10a77bbSDavid C Somayajulu 	}
931f10a77bbSDavid C Somayajulu 	c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox;
932f10a77bbSDavid C Somayajulu 
933f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status);
934f10a77bbSDavid C Somayajulu 
935f10a77bbSDavid C Somayajulu 	if (err) {
936f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
937f10a77bbSDavid C Somayajulu 		return (-1);
938f10a77bbSDavid C Somayajulu 	}
939f10a77bbSDavid C Somayajulu 	return 0;
940f10a77bbSDavid C Somayajulu }
941f10a77bbSDavid C Somayajulu 
942f10a77bbSDavid C Somayajulu static int
943f10a77bbSDavid C Somayajulu qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count,
944f10a77bbSDavid C Somayajulu         uint16_t cntxt_id, uint8_t *ind_table)
945f10a77bbSDavid C Somayajulu {
946f10a77bbSDavid C Somayajulu         q80_config_rss_ind_table_t      *c_rss_ind;
947f10a77bbSDavid C Somayajulu         q80_config_rss_ind_table_rsp_t  *c_rss_ind_rsp;
948f10a77bbSDavid C Somayajulu         uint32_t                        err;
949f10a77bbSDavid C Somayajulu         device_t                        dev = ha->pci_dev;
950f10a77bbSDavid C Somayajulu 
951f10a77bbSDavid C Somayajulu 	if ((count > Q8_RSS_IND_TBL_SIZE) ||
952f10a77bbSDavid C Somayajulu 		((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) {
953f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: illegal count [%d, %d]\n", __func__,
954f10a77bbSDavid C Somayajulu 			start_idx, count);
955f10a77bbSDavid C Somayajulu 		return (-1);
956f10a77bbSDavid C Somayajulu 	}
957f10a77bbSDavid C Somayajulu 
958f10a77bbSDavid C Somayajulu         c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox;
959f10a77bbSDavid C Somayajulu         bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t));
960f10a77bbSDavid C Somayajulu 
961f10a77bbSDavid C Somayajulu         c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE;
962f10a77bbSDavid C Somayajulu         c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2);
963f10a77bbSDavid C Somayajulu         c_rss_ind->count_version |= Q8_MBX_CMD_VERSION;
964f10a77bbSDavid C Somayajulu 
965f10a77bbSDavid C Somayajulu 	c_rss_ind->start_idx = start_idx;
966f10a77bbSDavid C Somayajulu 	c_rss_ind->end_idx = start_idx + count - 1;
967f10a77bbSDavid C Somayajulu 	c_rss_ind->cntxt_id = cntxt_id;
968f10a77bbSDavid C Somayajulu 	bcopy(ind_table, c_rss_ind->ind_table, count);
969f10a77bbSDavid C Somayajulu 
970f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind,
971f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox,
972f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) {
973f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
974f10a77bbSDavid C Somayajulu 		return (-1);
975f10a77bbSDavid C Somayajulu 	}
976f10a77bbSDavid C Somayajulu 
977f10a77bbSDavid C Somayajulu 	c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox;
978f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status);
979f10a77bbSDavid C Somayajulu 
980f10a77bbSDavid C Somayajulu 	if (err) {
981f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
982f10a77bbSDavid C Somayajulu 		return (-1);
983f10a77bbSDavid C Somayajulu 	}
984f10a77bbSDavid C Somayajulu 	return 0;
985f10a77bbSDavid C Somayajulu }
986f10a77bbSDavid C Somayajulu 
987f10a77bbSDavid C Somayajulu /*
988f10a77bbSDavid C Somayajulu  * Name: qla_config_intr_coalesce
989f10a77bbSDavid C Somayajulu  * Function: Configure Interrupt Coalescing.
990f10a77bbSDavid C Somayajulu  */
991f10a77bbSDavid C Somayajulu static int
99235291c22SDavid C Somayajulu qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable,
99335291c22SDavid C Somayajulu 	int rcv)
994f10a77bbSDavid C Somayajulu {
995f10a77bbSDavid C Somayajulu 	q80_config_intr_coalesc_t	*intrc;
996f10a77bbSDavid C Somayajulu 	q80_config_intr_coalesc_rsp_t	*intrc_rsp;
997f10a77bbSDavid C Somayajulu 	uint32_t			err, i;
998f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
999f10a77bbSDavid C Somayajulu 
1000f10a77bbSDavid C Somayajulu 	intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox;
1001f10a77bbSDavid C Somayajulu 	bzero(intrc, (sizeof (q80_config_intr_coalesc_t)));
1002f10a77bbSDavid C Somayajulu 
1003f10a77bbSDavid C Somayajulu 	intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE;
1004f10a77bbSDavid C Somayajulu 	intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2);
1005f10a77bbSDavid C Somayajulu 	intrc->count_version |= Q8_MBX_CMD_VERSION;
1006f10a77bbSDavid C Somayajulu 
100735291c22SDavid C Somayajulu 	if (rcv) {
1008f10a77bbSDavid C Somayajulu 		intrc->flags = Q8_MBX_INTRC_FLAGS_RCV;
100935291c22SDavid C Somayajulu 		intrc->max_pkts = ha->hw.rcv_intr_coalesce & 0xFFFF;
101035291c22SDavid C Somayajulu 		intrc->max_mswait = (ha->hw.rcv_intr_coalesce >> 16) & 0xFFFF;
101135291c22SDavid C Somayajulu 	} else {
101235291c22SDavid C Somayajulu 		intrc->flags = Q8_MBX_INTRC_FLAGS_XMT;
101335291c22SDavid C Somayajulu 		intrc->max_pkts = ha->hw.xmt_intr_coalesce & 0xFFFF;
101435291c22SDavid C Somayajulu 		intrc->max_mswait = (ha->hw.xmt_intr_coalesce >> 16) & 0xFFFF;
101535291c22SDavid C Somayajulu 	}
1016f10a77bbSDavid C Somayajulu 
101735291c22SDavid C Somayajulu 	intrc->cntxt_id = cntxt_id;
1018f10a77bbSDavid C Somayajulu 
1019f10a77bbSDavid C Somayajulu 	if (tenable) {
1020f10a77bbSDavid C Somayajulu 		intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC;
1021f10a77bbSDavid C Somayajulu 		intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC;
1022f10a77bbSDavid C Somayajulu 
1023f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
1024f10a77bbSDavid C Somayajulu 			intrc->sds_ring_mask |= (1 << i);
1025f10a77bbSDavid C Somayajulu 		}
1026f10a77bbSDavid C Somayajulu 		intrc->ms_timeout = 1000;
1027f10a77bbSDavid C Somayajulu 	}
1028f10a77bbSDavid C Somayajulu 
1029f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)intrc,
1030f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_intr_coalesc_t) >> 2),
1031f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) {
1032f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1033f10a77bbSDavid C Somayajulu 		return (-1);
1034f10a77bbSDavid C Somayajulu 	}
1035f10a77bbSDavid C Somayajulu 	intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox;
1036f10a77bbSDavid C Somayajulu 
1037f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status);
1038f10a77bbSDavid C Somayajulu 
1039f10a77bbSDavid C Somayajulu 	if (err) {
1040f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1041f10a77bbSDavid C Somayajulu 		return (-1);
1042f10a77bbSDavid C Somayajulu 	}
1043f10a77bbSDavid C Somayajulu 
1044f10a77bbSDavid C Somayajulu 	return 0;
1045f10a77bbSDavid C Somayajulu }
1046f10a77bbSDavid C Somayajulu 
1047f10a77bbSDavid C Somayajulu 
1048f10a77bbSDavid C Somayajulu /*
1049f10a77bbSDavid C Somayajulu  * Name: qla_config_mac_addr
1050f10a77bbSDavid C Somayajulu  * Function: binds a MAC address to the context/interface.
1051f10a77bbSDavid C Somayajulu  *	Can be unicast, multicast or broadcast.
1052f10a77bbSDavid C Somayajulu  */
1053f10a77bbSDavid C Somayajulu static int
1054f10a77bbSDavid C Somayajulu qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac)
1055f10a77bbSDavid C Somayajulu {
1056f10a77bbSDavid C Somayajulu 	q80_config_mac_addr_t		*cmac;
1057f10a77bbSDavid C Somayajulu 	q80_config_mac_addr_rsp_t	*cmac_rsp;
1058f10a77bbSDavid C Somayajulu 	uint32_t			err;
1059f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1060f10a77bbSDavid C Somayajulu 
1061f10a77bbSDavid C Somayajulu 	cmac = (q80_config_mac_addr_t *)ha->hw.mbox;
1062f10a77bbSDavid C Somayajulu 	bzero(cmac, (sizeof (q80_config_mac_addr_t)));
1063f10a77bbSDavid C Somayajulu 
1064f10a77bbSDavid C Somayajulu 	cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR;
1065f10a77bbSDavid C Somayajulu 	cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2;
1066f10a77bbSDavid C Somayajulu 	cmac->count_version |= Q8_MBX_CMD_VERSION;
1067f10a77bbSDavid C Somayajulu 
1068f10a77bbSDavid C Somayajulu 	if (add_mac)
1069f10a77bbSDavid C Somayajulu 		cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR;
1070f10a77bbSDavid C Somayajulu 	else
1071f10a77bbSDavid C Somayajulu 		cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR;
1072f10a77bbSDavid C Somayajulu 
1073f10a77bbSDavid C Somayajulu 	cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS;
1074f10a77bbSDavid C Somayajulu 
1075f10a77bbSDavid C Somayajulu 	cmac->nmac_entries = 1;
1076f10a77bbSDavid C Somayajulu 	cmac->cntxt_id = ha->hw.rcv_cntxt_id;
1077f10a77bbSDavid C Somayajulu 	bcopy(mac_addr, cmac->mac_addr[0].addr, 6);
1078f10a77bbSDavid C Somayajulu 
1079f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)cmac,
1080f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_mac_addr_t) >> 2),
1081f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) {
1082f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: %s failed0\n", __func__,
1083f10a77bbSDavid C Somayajulu 			(add_mac ? "Add" : "Del"));
1084f10a77bbSDavid C Somayajulu 		return (-1);
1085f10a77bbSDavid C Somayajulu 	}
1086f10a77bbSDavid C Somayajulu 	cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox;
1087f10a77bbSDavid C Somayajulu 
1088f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status);
1089f10a77bbSDavid C Somayajulu 
1090f10a77bbSDavid C Somayajulu 	if (err) {
1091f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: %s "
1092f10a77bbSDavid C Somayajulu 			"%02x:%02x:%02x:%02x:%02x:%02x failed1 [0x%08x]\n",
1093f10a77bbSDavid C Somayajulu 			__func__, (add_mac ? "Add" : "Del"),
1094f10a77bbSDavid C Somayajulu 			mac_addr[0], mac_addr[1], mac_addr[2],
1095f10a77bbSDavid C Somayajulu 			mac_addr[3], mac_addr[4], mac_addr[5], err);
1096f10a77bbSDavid C Somayajulu 		return (-1);
1097f10a77bbSDavid C Somayajulu 	}
1098f10a77bbSDavid C Somayajulu 
1099f10a77bbSDavid C Somayajulu 	return 0;
1100f10a77bbSDavid C Somayajulu }
1101f10a77bbSDavid C Somayajulu 
1102f10a77bbSDavid C Somayajulu 
1103f10a77bbSDavid C Somayajulu /*
1104f10a77bbSDavid C Somayajulu  * Name: qla_set_mac_rcv_mode
1105453130d9SPedro F. Giffuni  * Function: Enable/Disable AllMulticast and Promiscuous Modes.
1106f10a77bbSDavid C Somayajulu  */
1107f10a77bbSDavid C Somayajulu static int
1108f10a77bbSDavid C Somayajulu qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode)
1109f10a77bbSDavid C Somayajulu {
1110f10a77bbSDavid C Somayajulu 	q80_config_mac_rcv_mode_t	*rcv_mode;
1111f10a77bbSDavid C Somayajulu 	uint32_t			err;
1112f10a77bbSDavid C Somayajulu 	q80_config_mac_rcv_mode_rsp_t	*rcv_mode_rsp;
1113f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1114f10a77bbSDavid C Somayajulu 
1115f10a77bbSDavid C Somayajulu 	rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox;
1116f10a77bbSDavid C Somayajulu 	bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t)));
1117f10a77bbSDavid C Somayajulu 
1118f10a77bbSDavid C Somayajulu 	rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE;
1119f10a77bbSDavid C Somayajulu 	rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2;
1120f10a77bbSDavid C Somayajulu 	rcv_mode->count_version |= Q8_MBX_CMD_VERSION;
1121f10a77bbSDavid C Somayajulu 
1122f10a77bbSDavid C Somayajulu 	rcv_mode->mode = mode;
1123f10a77bbSDavid C Somayajulu 
1124f10a77bbSDavid C Somayajulu 	rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id;
1125f10a77bbSDavid C Somayajulu 
1126f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode,
1127f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_mac_rcv_mode_t) >> 2),
1128f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) {
1129f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1130f10a77bbSDavid C Somayajulu 		return (-1);
1131f10a77bbSDavid C Somayajulu 	}
1132f10a77bbSDavid C Somayajulu 	rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox;
1133f10a77bbSDavid C Somayajulu 
1134f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status);
1135f10a77bbSDavid C Somayajulu 
1136f10a77bbSDavid C Somayajulu 	if (err) {
1137f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1138f10a77bbSDavid C Somayajulu 		return (-1);
1139f10a77bbSDavid C Somayajulu 	}
1140f10a77bbSDavid C Somayajulu 
1141f10a77bbSDavid C Somayajulu 	return 0;
1142f10a77bbSDavid C Somayajulu }
1143f10a77bbSDavid C Somayajulu 
1144f10a77bbSDavid C Somayajulu int
1145f10a77bbSDavid C Somayajulu ql_set_promisc(qla_host_t *ha)
1146f10a77bbSDavid C Somayajulu {
1147f10a77bbSDavid C Somayajulu 	int ret;
1148f10a77bbSDavid C Somayajulu 
1149f10a77bbSDavid C Somayajulu 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1150f10a77bbSDavid C Somayajulu 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1151f10a77bbSDavid C Somayajulu 	return (ret);
1152f10a77bbSDavid C Somayajulu }
1153f10a77bbSDavid C Somayajulu 
115435291c22SDavid C Somayajulu void
115535291c22SDavid C Somayajulu qla_reset_promisc(qla_host_t *ha)
115635291c22SDavid C Somayajulu {
115735291c22SDavid C Somayajulu 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE;
115835291c22SDavid C Somayajulu 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
115935291c22SDavid C Somayajulu }
116035291c22SDavid C Somayajulu 
1161f10a77bbSDavid C Somayajulu int
1162f10a77bbSDavid C Somayajulu ql_set_allmulti(qla_host_t *ha)
1163f10a77bbSDavid C Somayajulu {
1164f10a77bbSDavid C Somayajulu 	int ret;
1165f10a77bbSDavid C Somayajulu 
1166f10a77bbSDavid C Somayajulu 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE;
1167f10a77bbSDavid C Somayajulu 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1168f10a77bbSDavid C Somayajulu 	return (ret);
1169f10a77bbSDavid C Somayajulu }
1170f10a77bbSDavid C Somayajulu 
117135291c22SDavid C Somayajulu void
117235291c22SDavid C Somayajulu qla_reset_allmulti(qla_host_t *ha)
117335291c22SDavid C Somayajulu {
117435291c22SDavid C Somayajulu 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE;
117535291c22SDavid C Somayajulu 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
117635291c22SDavid C Somayajulu }
1177f10a77bbSDavid C Somayajulu 
1178f10a77bbSDavid C Somayajulu /*
1179f10a77bbSDavid C Somayajulu  * Name: ql_set_max_mtu
1180f10a77bbSDavid C Somayajulu  * Function:
1181f10a77bbSDavid C Somayajulu  *	Sets the maximum transfer unit size for the specified rcv context.
1182f10a77bbSDavid C Somayajulu  */
1183f10a77bbSDavid C Somayajulu int
1184f10a77bbSDavid C Somayajulu ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id)
1185f10a77bbSDavid C Somayajulu {
1186f10a77bbSDavid C Somayajulu 	device_t		dev;
1187f10a77bbSDavid C Somayajulu 	q80_set_max_mtu_t	*max_mtu;
1188f10a77bbSDavid C Somayajulu 	q80_set_max_mtu_rsp_t	*max_mtu_rsp;
1189f10a77bbSDavid C Somayajulu 	uint32_t		err;
1190f10a77bbSDavid C Somayajulu 
1191f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1192f10a77bbSDavid C Somayajulu 
1193f10a77bbSDavid C Somayajulu 	max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox;
1194f10a77bbSDavid C Somayajulu 	bzero(max_mtu, (sizeof (q80_set_max_mtu_t)));
1195f10a77bbSDavid C Somayajulu 
1196f10a77bbSDavid C Somayajulu 	max_mtu->opcode = Q8_MBX_SET_MAX_MTU;
1197f10a77bbSDavid C Somayajulu 	max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2);
1198f10a77bbSDavid C Somayajulu 	max_mtu->count_version |= Q8_MBX_CMD_VERSION;
1199f10a77bbSDavid C Somayajulu 
1200f10a77bbSDavid C Somayajulu 	max_mtu->cntxt_id = cntxt_id;
1201f10a77bbSDavid C Somayajulu 	max_mtu->mtu = mtu;
1202f10a77bbSDavid C Somayajulu 
1203f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)max_mtu,
1204f10a77bbSDavid C Somayajulu 		(sizeof (q80_set_max_mtu_t) >> 2),
1205f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) {
1206f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1207f10a77bbSDavid C Somayajulu                 return -1;
1208f10a77bbSDavid C Somayajulu         }
1209f10a77bbSDavid C Somayajulu 
1210f10a77bbSDavid C Somayajulu 	max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox;
1211f10a77bbSDavid C Somayajulu 
1212f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status);
1213f10a77bbSDavid C Somayajulu 
1214f10a77bbSDavid C Somayajulu         if (err) {
1215f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1216f10a77bbSDavid C Somayajulu         }
1217f10a77bbSDavid C Somayajulu 
1218f10a77bbSDavid C Somayajulu 	return 0;
1219f10a77bbSDavid C Somayajulu }
1220f10a77bbSDavid C Somayajulu 
1221f10a77bbSDavid C Somayajulu static int
1222f10a77bbSDavid C Somayajulu qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id)
1223f10a77bbSDavid C Somayajulu {
1224f10a77bbSDavid C Somayajulu 	device_t		dev;
1225f10a77bbSDavid C Somayajulu 	q80_link_event_t	*lnk;
1226f10a77bbSDavid C Somayajulu 	q80_link_event_rsp_t	*lnk_rsp;
1227f10a77bbSDavid C Somayajulu 	uint32_t		err;
1228f10a77bbSDavid C Somayajulu 
1229f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1230f10a77bbSDavid C Somayajulu 
1231f10a77bbSDavid C Somayajulu 	lnk = (q80_link_event_t *)ha->hw.mbox;
1232f10a77bbSDavid C Somayajulu 	bzero(lnk, (sizeof (q80_link_event_t)));
1233f10a77bbSDavid C Somayajulu 
1234f10a77bbSDavid C Somayajulu 	lnk->opcode = Q8_MBX_LINK_EVENT_REQ;
1235f10a77bbSDavid C Somayajulu 	lnk->count_version = (sizeof (q80_link_event_t) >> 2);
1236f10a77bbSDavid C Somayajulu 	lnk->count_version |= Q8_MBX_CMD_VERSION;
1237f10a77bbSDavid C Somayajulu 
1238f10a77bbSDavid C Somayajulu 	lnk->cntxt_id = cntxt_id;
1239f10a77bbSDavid C Somayajulu 	lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC;
1240f10a77bbSDavid C Somayajulu 
1241f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2),
1242f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) {
1243f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1244f10a77bbSDavid C Somayajulu                 return -1;
1245f10a77bbSDavid C Somayajulu         }
1246f10a77bbSDavid C Somayajulu 
1247f10a77bbSDavid C Somayajulu 	lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox;
1248f10a77bbSDavid C Somayajulu 
1249f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status);
1250f10a77bbSDavid C Somayajulu 
1251f10a77bbSDavid C Somayajulu         if (err) {
1252f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1253f10a77bbSDavid C Somayajulu         }
1254f10a77bbSDavid C Somayajulu 
1255f10a77bbSDavid C Somayajulu 	return 0;
1256f10a77bbSDavid C Somayajulu }
1257f10a77bbSDavid C Somayajulu 
1258f10a77bbSDavid C Somayajulu static int
1259f10a77bbSDavid C Somayajulu qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id)
1260f10a77bbSDavid C Somayajulu {
1261f10a77bbSDavid C Somayajulu 	device_t		dev;
1262f10a77bbSDavid C Somayajulu 	q80_config_fw_lro_t	*fw_lro;
1263f10a77bbSDavid C Somayajulu 	q80_config_fw_lro_rsp_t	*fw_lro_rsp;
1264f10a77bbSDavid C Somayajulu 	uint32_t		err;
1265f10a77bbSDavid C Somayajulu 
1266f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1267f10a77bbSDavid C Somayajulu 
1268f10a77bbSDavid C Somayajulu 	fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox;
1269f10a77bbSDavid C Somayajulu 	bzero(fw_lro, sizeof(q80_config_fw_lro_t));
1270f10a77bbSDavid C Somayajulu 
1271f10a77bbSDavid C Somayajulu 	fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO;
1272f10a77bbSDavid C Somayajulu 	fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2);
1273f10a77bbSDavid C Somayajulu 	fw_lro->count_version |= Q8_MBX_CMD_VERSION;
1274f10a77bbSDavid C Somayajulu 
1275f10a77bbSDavid C Somayajulu 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK;
127635291c22SDavid C Somayajulu 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK;
1277f10a77bbSDavid C Somayajulu 
1278f10a77bbSDavid C Somayajulu 	fw_lro->cntxt_id = cntxt_id;
1279f10a77bbSDavid C Somayajulu 
1280f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)fw_lro,
1281f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_fw_lro_t) >> 2),
1282f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) {
1283f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
1284f10a77bbSDavid C Somayajulu 		return -1;
1285f10a77bbSDavid C Somayajulu 	}
1286f10a77bbSDavid C Somayajulu 
1287f10a77bbSDavid C Somayajulu 	fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox;
1288f10a77bbSDavid C Somayajulu 
1289f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status);
1290f10a77bbSDavid C Somayajulu 
1291f10a77bbSDavid C Somayajulu 	if (err) {
1292f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1293f10a77bbSDavid C Somayajulu 	}
1294f10a77bbSDavid C Somayajulu 
1295f10a77bbSDavid C Somayajulu 	return 0;
1296f10a77bbSDavid C Somayajulu }
1297f10a77bbSDavid C Somayajulu 
1298f10a77bbSDavid C Somayajulu static void
129935291c22SDavid C Somayajulu qla_xmt_stats(qla_host_t *ha, q80_xmt_stats_t *xstat, int i)
1300f10a77bbSDavid C Somayajulu {
1301f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1302f10a77bbSDavid C Somayajulu 
130335291c22SDavid C Somayajulu 	if (i < ha->hw.num_tx_rings) {
130435291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: total_bytes\t\t%" PRIu64 "\n",
130535291c22SDavid C Somayajulu 			__func__, i, xstat->total_bytes);
130635291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: total_pkts\t\t%" PRIu64 "\n",
130735291c22SDavid C Somayajulu 			__func__, i, xstat->total_pkts);
130835291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: errors\t\t%" PRIu64 "\n",
130935291c22SDavid C Somayajulu 			__func__, i, xstat->errors);
131035291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: pkts_dropped\t%" PRIu64 "\n",
131135291c22SDavid C Somayajulu 			__func__, i, xstat->pkts_dropped);
131235291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: switch_pkts\t\t%" PRIu64 "\n",
131335291c22SDavid C Somayajulu 			__func__, i, xstat->switch_pkts);
131435291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: num_buffers\t\t%" PRIu64 "\n",
131535291c22SDavid C Somayajulu 			__func__, i, xstat->num_buffers);
131635291c22SDavid C Somayajulu 	} else {
131735291c22SDavid C Somayajulu 		device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n",
131835291c22SDavid C Somayajulu 			__func__, xstat->total_bytes);
131935291c22SDavid C Somayajulu 		device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n",
132035291c22SDavid C Somayajulu 			__func__, xstat->total_pkts);
132135291c22SDavid C Somayajulu 		device_printf(dev, "%s: errors\t\t\t%" PRIu64 "\n",
132235291c22SDavid C Somayajulu 			__func__, xstat->errors);
132335291c22SDavid C Somayajulu 		device_printf(dev, "%s: pkts_dropped\t\t\t%" PRIu64 "\n",
132435291c22SDavid C Somayajulu 			__func__, xstat->pkts_dropped);
132535291c22SDavid C Somayajulu 		device_printf(dev, "%s: switch_pkts\t\t\t%" PRIu64 "\n",
132635291c22SDavid C Somayajulu 			__func__, xstat->switch_pkts);
132735291c22SDavid C Somayajulu 		device_printf(dev, "%s: num_buffers\t\t\t%" PRIu64 "\n",
132835291c22SDavid C Somayajulu 			__func__, xstat->num_buffers);
132935291c22SDavid C Somayajulu 	}
1330f10a77bbSDavid C Somayajulu }
1331f10a77bbSDavid C Somayajulu 
1332f10a77bbSDavid C Somayajulu static void
1333f10a77bbSDavid C Somayajulu qla_rcv_stats(qla_host_t *ha, q80_rcv_stats_t *rstat)
1334f10a77bbSDavid C Somayajulu {
1335f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1336f10a77bbSDavid C Somayajulu 
1337f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n", __func__,
1338f10a77bbSDavid C Somayajulu 		rstat->total_bytes);
1339f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n", __func__,
1340f10a77bbSDavid C Somayajulu 		rstat->total_pkts);
1341f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_pkt_count\t\t%" PRIu64 "\n", __func__,
1342f10a77bbSDavid C Somayajulu 		rstat->lro_pkt_count);
134335291c22SDavid C Somayajulu 	device_printf(dev, "%s: sw_pkt_count\t\t\t%" PRIu64 "\n", __func__,
1344f10a77bbSDavid C Somayajulu 		rstat->sw_pkt_count);
1345f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: ip_chksum_err\t\t%" PRIu64 "\n", __func__,
1346f10a77bbSDavid C Somayajulu 		rstat->ip_chksum_err);
1347f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_wo_acntxts\t\t%" PRIu64 "\n", __func__,
1348f10a77bbSDavid C Somayajulu 		rstat->pkts_wo_acntxts);
1349f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_sds_card\t%" PRIu64 "\n",
1350f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_sds_card);
1351f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_sds_host\t%" PRIu64 "\n",
1352f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_sds_host);
1353f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: oversized_pkts\t\t%" PRIu64 "\n", __func__,
1354f10a77bbSDavid C Somayajulu 		rstat->oversized_pkts);
1355f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_rds\t\t%" PRIu64 "\n",
1356f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_rds);
1357f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: unxpctd_mcast_pkts\t\t%" PRIu64 "\n",
1358f10a77bbSDavid C Somayajulu 		__func__, rstat->unxpctd_mcast_pkts);
1359f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: re1_fbq_error\t\t%" PRIu64 "\n", __func__,
1360f10a77bbSDavid C Somayajulu 		rstat->re1_fbq_error);
1361f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: invalid_mac_addr\t\t%" PRIu64 "\n", __func__,
1362f10a77bbSDavid C Somayajulu 		rstat->invalid_mac_addr);
1363f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rds_prime_trys\t\t%" PRIu64 "\n", __func__,
1364f10a77bbSDavid C Somayajulu 		rstat->rds_prime_trys);
1365f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rds_prime_success\t\t%" PRIu64 "\n", __func__,
1366f10a77bbSDavid C Somayajulu 		rstat->rds_prime_success);
1367f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_added\t\t%" PRIu64 "\n", __func__,
1368f10a77bbSDavid C Somayajulu 		rstat->lro_flows_added);
1369f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_deleted\t\t%" PRIu64 "\n", __func__,
1370f10a77bbSDavid C Somayajulu 		rstat->lro_flows_deleted);
1371f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_active\t\t%" PRIu64 "\n", __func__,
1372f10a77bbSDavid C Somayajulu 		rstat->lro_flows_active);
1373f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_droped_unknown\t\t%" PRIu64 "\n",
1374f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_droped_unknown);
1375f10a77bbSDavid C Somayajulu }
1376f10a77bbSDavid C Somayajulu 
1377f10a77bbSDavid C Somayajulu static void
1378f10a77bbSDavid C Somayajulu qla_mac_stats(qla_host_t *ha, q80_mac_stats_t *mstat)
1379f10a77bbSDavid C Somayajulu {
1380f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1381f10a77bbSDavid C Somayajulu 
1382f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_frames\t\t\t%" PRIu64 "\n", __func__,
1383f10a77bbSDavid C Somayajulu 		mstat->xmt_frames);
1384f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_bytes\t\t\t%" PRIu64 "\n", __func__,
1385f10a77bbSDavid C Somayajulu 		mstat->xmt_bytes);
1386f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1387f10a77bbSDavid C Somayajulu 		mstat->xmt_mcast_pkts);
1388f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1389f10a77bbSDavid C Somayajulu 		mstat->xmt_bcast_pkts);
1390f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pause_frames\t\t%" PRIu64 "\n", __func__,
1391f10a77bbSDavid C Somayajulu 		mstat->xmt_pause_frames);
1392f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1393f10a77bbSDavid C Somayajulu 		mstat->xmt_cntrl_pkts);
1394f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1395f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_64bytes);
1396f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1397f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_127bytes);
1398f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1399f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_255bytes);
1400f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1401f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_511bytes);
140235291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_1023bytes\t\t%" PRIu64 "\n",
1403f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_1023bytes);
140435291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_1518bytes\t\t%" PRIu64 "\n",
1405f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_1518bytes);
140635291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_gt_1518bytes\t\t%" PRIu64 "\n",
1407f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_gt_1518bytes);
1408f10a77bbSDavid C Somayajulu 
1409f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_frames\t\t\t%" PRIu64 "\n", __func__,
1410f10a77bbSDavid C Somayajulu 		mstat->rcv_frames);
1411f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_bytes\t\t\t%" PRIu64 "\n", __func__,
1412f10a77bbSDavid C Somayajulu 		mstat->rcv_bytes);
1413f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1414f10a77bbSDavid C Somayajulu 		mstat->rcv_mcast_pkts);
1415f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1416f10a77bbSDavid C Somayajulu 		mstat->rcv_bcast_pkts);
1417f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pause_frames\t\t%" PRIu64 "\n", __func__,
1418f10a77bbSDavid C Somayajulu 		mstat->rcv_pause_frames);
1419f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1420f10a77bbSDavid C Somayajulu 		mstat->rcv_cntrl_pkts);
1421f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1422f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_64bytes);
1423f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1424f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_127bytes);
1425f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1426f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_255bytes);
1427f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1428f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_511bytes);
142935291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_1023bytes\t\t%" PRIu64 "\n",
1430f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_1023bytes);
143135291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_1518bytes\t\t%" PRIu64 "\n",
1432f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_1518bytes);
143335291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_gt_1518bytes\t\t%" PRIu64 "\n",
1434f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_gt_1518bytes);
1435f10a77bbSDavid C Somayajulu 
1436f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_error\t\t%" PRIu64 "\n", __func__,
1437f10a77bbSDavid C Somayajulu 		mstat->rcv_len_error);
1438f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_small\t\t%" PRIu64 "\n", __func__,
1439f10a77bbSDavid C Somayajulu 		mstat->rcv_len_small);
1440f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_large\t\t%" PRIu64 "\n", __func__,
1441f10a77bbSDavid C Somayajulu 		mstat->rcv_len_large);
1442f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_jabber\t\t\t%" PRIu64 "\n", __func__,
1443f10a77bbSDavid C Somayajulu 		mstat->rcv_jabber);
1444f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_dropped\t\t\t%" PRIu64 "\n", __func__,
1445f10a77bbSDavid C Somayajulu 		mstat->rcv_dropped);
1446f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: fcs_error\t\t\t%" PRIu64 "\n", __func__,
1447f10a77bbSDavid C Somayajulu 		mstat->fcs_error);
1448f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: align_error\t\t\t%" PRIu64 "\n", __func__,
1449f10a77bbSDavid C Somayajulu 		mstat->align_error);
1450f10a77bbSDavid C Somayajulu }
1451f10a77bbSDavid C Somayajulu 
1452f10a77bbSDavid C Somayajulu 
1453f10a77bbSDavid C Somayajulu static int
145435291c22SDavid C Somayajulu qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size)
1455f10a77bbSDavid C Somayajulu {
1456f10a77bbSDavid C Somayajulu 	device_t		dev;
1457f10a77bbSDavid C Somayajulu 	q80_get_stats_t		*stat;
1458f10a77bbSDavid C Somayajulu 	q80_get_stats_rsp_t	*stat_rsp;
1459f10a77bbSDavid C Somayajulu 	uint32_t		err;
1460f10a77bbSDavid C Somayajulu 
1461f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1462f10a77bbSDavid C Somayajulu 
1463f10a77bbSDavid C Somayajulu 	stat = (q80_get_stats_t *)ha->hw.mbox;
1464f10a77bbSDavid C Somayajulu 	bzero(stat, (sizeof (q80_get_stats_t)));
1465f10a77bbSDavid C Somayajulu 
1466f10a77bbSDavid C Somayajulu 	stat->opcode = Q8_MBX_GET_STATS;
1467f10a77bbSDavid C Somayajulu 	stat->count_version = 2;
1468f10a77bbSDavid C Somayajulu 	stat->count_version |= Q8_MBX_CMD_VERSION;
1469f10a77bbSDavid C Somayajulu 
1470f10a77bbSDavid C Somayajulu 	stat->cmd = cmd;
1471f10a77bbSDavid C Somayajulu 
1472f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)stat, 2,
147335291c22SDavid C Somayajulu                 ha->hw.mbox, (rsp_size >> 2), 0)) {
1474f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1475f10a77bbSDavid C Somayajulu                 return -1;
1476f10a77bbSDavid C Somayajulu         }
1477f10a77bbSDavid C Somayajulu 
1478f10a77bbSDavid C Somayajulu 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1479f10a77bbSDavid C Somayajulu 
1480f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status);
1481f10a77bbSDavid C Somayajulu 
1482f10a77bbSDavid C Somayajulu         if (err) {
1483f10a77bbSDavid C Somayajulu                 return -1;
1484f10a77bbSDavid C Somayajulu         }
1485f10a77bbSDavid C Somayajulu 
1486f10a77bbSDavid C Somayajulu 	return 0;
1487f10a77bbSDavid C Somayajulu }
1488f10a77bbSDavid C Somayajulu 
1489f10a77bbSDavid C Somayajulu void
1490f10a77bbSDavid C Somayajulu ql_get_stats(qla_host_t *ha)
1491f10a77bbSDavid C Somayajulu {
1492f10a77bbSDavid C Somayajulu 	q80_get_stats_rsp_t	*stat_rsp;
1493f10a77bbSDavid C Somayajulu 	q80_mac_stats_t		*mstat;
1494f10a77bbSDavid C Somayajulu 	q80_xmt_stats_t		*xstat;
1495f10a77bbSDavid C Somayajulu 	q80_rcv_stats_t		*rstat;
1496f10a77bbSDavid C Somayajulu 	uint32_t		cmd;
149735291c22SDavid C Somayajulu 	int			i;
1498f10a77bbSDavid C Somayajulu 
1499f10a77bbSDavid C Somayajulu 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1500f10a77bbSDavid C Somayajulu 	/*
1501f10a77bbSDavid C Somayajulu 	 * Get MAC Statistics
1502f10a77bbSDavid C Somayajulu 	 */
1503f10a77bbSDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_TYPE_MAC;
150435291c22SDavid C Somayajulu //	cmd |= Q8_GET_STATS_CMD_CLEAR;
1505f10a77bbSDavid C Somayajulu 
1506f10a77bbSDavid C Somayajulu 	cmd |= ((ha->pci_func & 0x1) << 16);
1507f10a77bbSDavid C Somayajulu 
150835291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
1509f10a77bbSDavid C Somayajulu 		mstat = (q80_mac_stats_t *)&stat_rsp->u.mac;
1510f10a77bbSDavid C Somayajulu 		qla_mac_stats(ha, mstat);
1511f10a77bbSDavid C Somayajulu 	} else {
1512f10a77bbSDavid C Somayajulu                 device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n",
1513f10a77bbSDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
1514f10a77bbSDavid C Somayajulu 	}
1515f10a77bbSDavid C Somayajulu 	/*
1516f10a77bbSDavid C Somayajulu 	 * Get RCV Statistics
1517f10a77bbSDavid C Somayajulu 	 */
1518f10a77bbSDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT;
151935291c22SDavid C Somayajulu //	cmd |= Q8_GET_STATS_CMD_CLEAR;
1520f10a77bbSDavid C Somayajulu 	cmd |= (ha->hw.rcv_cntxt_id << 16);
1521f10a77bbSDavid C Somayajulu 
152235291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
1523f10a77bbSDavid C Somayajulu 		rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv;
1524f10a77bbSDavid C Somayajulu 		qla_rcv_stats(ha, rstat);
1525f10a77bbSDavid C Somayajulu 	} else {
1526f10a77bbSDavid C Somayajulu                 device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n",
1527f10a77bbSDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
1528f10a77bbSDavid C Somayajulu 	}
1529f10a77bbSDavid C Somayajulu 	/*
1530f10a77bbSDavid C Somayajulu 	 * Get XMT Statistics
1531f10a77bbSDavid C Somayajulu 	 */
153235291c22SDavid C Somayajulu 	for (i = 0 ; i < ha->hw.num_tx_rings; i++) {
1533f10a77bbSDavid C Somayajulu 		cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT;
153435291c22SDavid C Somayajulu //		cmd |= Q8_GET_STATS_CMD_CLEAR;
153535291c22SDavid C Somayajulu 		cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16);
1536f10a77bbSDavid C Somayajulu 
153735291c22SDavid C Somayajulu 		if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t))
153835291c22SDavid C Somayajulu 			== 0) {
1539f10a77bbSDavid C Somayajulu 			xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt;
154035291c22SDavid C Somayajulu 			qla_xmt_stats(ha, xstat, i);
1541f10a77bbSDavid C Somayajulu 		} else {
1542f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n",
1543f10a77bbSDavid C Somayajulu 				__func__, ha->hw.mbox[0]);
1544f10a77bbSDavid C Somayajulu 		}
1545f10a77bbSDavid C Somayajulu 	}
154635291c22SDavid C Somayajulu 	return;
154735291c22SDavid C Somayajulu }
154835291c22SDavid C Somayajulu 
154935291c22SDavid C Somayajulu static void
155035291c22SDavid C Somayajulu qla_get_quick_stats(qla_host_t *ha)
155135291c22SDavid C Somayajulu {
155235291c22SDavid C Somayajulu 	q80_get_mac_rcv_xmt_stats_rsp_t *stat_rsp;
155335291c22SDavid C Somayajulu 	q80_mac_stats_t         *mstat;
155435291c22SDavid C Somayajulu 	q80_xmt_stats_t         *xstat;
155535291c22SDavid C Somayajulu 	q80_rcv_stats_t         *rstat;
155635291c22SDavid C Somayajulu 	uint32_t                cmd;
155735291c22SDavid C Somayajulu 
155835291c22SDavid C Somayajulu 	stat_rsp = (q80_get_mac_rcv_xmt_stats_rsp_t *)ha->hw.mbox;
155935291c22SDavid C Somayajulu 
156035291c22SDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_TYPE_ALL;
156135291c22SDavid C Somayajulu //      cmd |= Q8_GET_STATS_CMD_CLEAR;
156235291c22SDavid C Somayajulu 
156335291c22SDavid C Somayajulu //      cmd |= ((ha->pci_func & 0x3) << 16);
156435291c22SDavid C Somayajulu 	cmd |= (0xFFFF << 16);
156535291c22SDavid C Somayajulu 
156635291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd,
156735291c22SDavid C Somayajulu 			sizeof (q80_get_mac_rcv_xmt_stats_rsp_t)) == 0) {
156835291c22SDavid C Somayajulu 
156935291c22SDavid C Somayajulu 		mstat = (q80_mac_stats_t *)&stat_rsp->mac;
157035291c22SDavid C Somayajulu 		rstat = (q80_rcv_stats_t *)&stat_rsp->rcv;
157135291c22SDavid C Somayajulu 		xstat = (q80_xmt_stats_t *)&stat_rsp->xmt;
157235291c22SDavid C Somayajulu 		qla_mac_stats(ha, mstat);
157335291c22SDavid C Somayajulu 		qla_rcv_stats(ha, rstat);
157435291c22SDavid C Somayajulu 		qla_xmt_stats(ha, xstat, ha->hw.num_tx_rings);
157535291c22SDavid C Somayajulu 	} else {
157635291c22SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: failed [0x%08x]\n",
157735291c22SDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
157835291c22SDavid C Somayajulu 	}
157935291c22SDavid C Somayajulu 	return;
158035291c22SDavid C Somayajulu }
1581f10a77bbSDavid C Somayajulu 
1582f10a77bbSDavid C Somayajulu /*
1583f10a77bbSDavid C Somayajulu  * Name: qla_tx_tso
1584f10a77bbSDavid C Somayajulu  * Function: Checks if the packet to be transmitted is a candidate for
1585f10a77bbSDavid C Somayajulu  *	Large TCP Segment Offload. If yes, the appropriate fields in the Tx
1586f10a77bbSDavid C Somayajulu  *	Ring Structure are plugged in.
1587f10a77bbSDavid C Somayajulu  */
1588f10a77bbSDavid C Somayajulu static int
1589f10a77bbSDavid C Somayajulu qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
1590f10a77bbSDavid C Somayajulu {
1591f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1592f10a77bbSDavid C Somayajulu 	struct ip *ip = NULL;
1593f10a77bbSDavid C Somayajulu 	struct ip6_hdr *ip6 = NULL;
1594f10a77bbSDavid C Somayajulu 	struct tcphdr *th = NULL;
1595f10a77bbSDavid C Somayajulu 	uint32_t ehdrlen,  hdrlen, ip_hlen, tcp_hlen, tcp_opt_off;
1596f10a77bbSDavid C Somayajulu 	uint16_t etype, opcode, offload = 1;
1597f10a77bbSDavid C Somayajulu 	device_t dev;
1598f10a77bbSDavid C Somayajulu 
1599f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1600f10a77bbSDavid C Somayajulu 
1601f10a77bbSDavid C Somayajulu 
1602f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
1603f10a77bbSDavid C Somayajulu 
1604f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1605f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1606f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_proto);
1607f10a77bbSDavid C Somayajulu 	} else {
1608f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN;
1609f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_encap_proto);
1610f10a77bbSDavid C Somayajulu 	}
1611f10a77bbSDavid C Somayajulu 
1612f10a77bbSDavid C Somayajulu 	hdrlen = 0;
1613f10a77bbSDavid C Somayajulu 
1614f10a77bbSDavid C Somayajulu 	switch (etype) {
1615f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IP:
1616f10a77bbSDavid C Somayajulu 
1617f10a77bbSDavid C Somayajulu 			tcp_opt_off = ehdrlen + sizeof(struct ip) +
1618f10a77bbSDavid C Somayajulu 					sizeof(struct tcphdr);
1619f10a77bbSDavid C Somayajulu 
1620f10a77bbSDavid C Somayajulu 			if (mp->m_len < tcp_opt_off) {
1621f10a77bbSDavid C Somayajulu 				m_copydata(mp, 0, tcp_opt_off, hdr);
1622f10a77bbSDavid C Somayajulu 				ip = (struct ip *)(hdr + ehdrlen);
1623f10a77bbSDavid C Somayajulu 			} else {
1624f10a77bbSDavid C Somayajulu 				ip = (struct ip *)(mp->m_data + ehdrlen);
1625f10a77bbSDavid C Somayajulu 			}
1626f10a77bbSDavid C Somayajulu 
1627f10a77bbSDavid C Somayajulu 			ip_hlen = ip->ip_hl << 2;
1628f10a77bbSDavid C Somayajulu 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
1629f10a77bbSDavid C Somayajulu 
1630f10a77bbSDavid C Somayajulu 
1631f10a77bbSDavid C Somayajulu 			if ((ip->ip_p != IPPROTO_TCP) ||
1632f10a77bbSDavid C Somayajulu 				(ip_hlen != sizeof (struct ip))){
1633f10a77bbSDavid C Somayajulu 				/* IP Options are not supported */
1634f10a77bbSDavid C Somayajulu 
1635f10a77bbSDavid C Somayajulu 				offload = 0;
1636f10a77bbSDavid C Somayajulu 			} else
1637f10a77bbSDavid C Somayajulu 				th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
1638f10a77bbSDavid C Somayajulu 
1639f10a77bbSDavid C Somayajulu 		break;
1640f10a77bbSDavid C Somayajulu 
1641f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IPV6:
1642f10a77bbSDavid C Somayajulu 
1643f10a77bbSDavid C Somayajulu 			tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) +
1644f10a77bbSDavid C Somayajulu 					sizeof (struct tcphdr);
1645f10a77bbSDavid C Somayajulu 
1646f10a77bbSDavid C Somayajulu 			if (mp->m_len < tcp_opt_off) {
1647f10a77bbSDavid C Somayajulu 				m_copydata(mp, 0, tcp_opt_off, hdr);
1648f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)(hdr + ehdrlen);
1649f10a77bbSDavid C Somayajulu 			} else {
1650f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1651f10a77bbSDavid C Somayajulu 			}
1652f10a77bbSDavid C Somayajulu 
1653f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof(struct ip6_hdr);
1654f10a77bbSDavid C Somayajulu 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6;
1655f10a77bbSDavid C Somayajulu 
1656f10a77bbSDavid C Somayajulu 			if (ip6->ip6_nxt != IPPROTO_TCP) {
1657f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv6\n", __func__);
1658f10a77bbSDavid C Somayajulu 				offload = 0;
1659f10a77bbSDavid C Somayajulu 			} else
1660f10a77bbSDavid C Somayajulu 				th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
1661f10a77bbSDavid C Somayajulu 		break;
1662f10a77bbSDavid C Somayajulu 
1663f10a77bbSDavid C Somayajulu 		default:
1664f10a77bbSDavid C Somayajulu 			QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__));
1665f10a77bbSDavid C Somayajulu 			offload = 0;
1666f10a77bbSDavid C Somayajulu 		break;
1667f10a77bbSDavid C Somayajulu 	}
1668f10a77bbSDavid C Somayajulu 
1669f10a77bbSDavid C Somayajulu 	if (!offload)
1670f10a77bbSDavid C Somayajulu 		return (-1);
1671f10a77bbSDavid C Somayajulu 
1672f10a77bbSDavid C Somayajulu 	tcp_hlen = th->th_off << 2;
1673f10a77bbSDavid C Somayajulu 	hdrlen = ehdrlen + ip_hlen + tcp_hlen;
1674f10a77bbSDavid C Somayajulu 
1675f10a77bbSDavid C Somayajulu         if (mp->m_len < hdrlen) {
1676f10a77bbSDavid C Somayajulu                 if (mp->m_len < tcp_opt_off) {
1677f10a77bbSDavid C Somayajulu                         if (tcp_hlen > sizeof(struct tcphdr)) {
1678f10a77bbSDavid C Somayajulu                                 m_copydata(mp, tcp_opt_off,
1679f10a77bbSDavid C Somayajulu                                         (tcp_hlen - sizeof(struct tcphdr)),
1680f10a77bbSDavid C Somayajulu                                         &hdr[tcp_opt_off]);
1681f10a77bbSDavid C Somayajulu                         }
1682f10a77bbSDavid C Somayajulu                 } else {
1683f10a77bbSDavid C Somayajulu                         m_copydata(mp, 0, hdrlen, hdr);
1684f10a77bbSDavid C Somayajulu                 }
1685f10a77bbSDavid C Somayajulu         }
1686f10a77bbSDavid C Somayajulu 
1687f10a77bbSDavid C Somayajulu 	tx_cmd->mss = mp->m_pkthdr.tso_segsz;
1688f10a77bbSDavid C Somayajulu 
1689f10a77bbSDavid C Somayajulu 	tx_cmd->flags_opcode = opcode ;
1690f10a77bbSDavid C Somayajulu 	tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen;
1691f10a77bbSDavid C Somayajulu 	tx_cmd->total_hdr_len = hdrlen;
1692f10a77bbSDavid C Somayajulu 
1693f10a77bbSDavid C Somayajulu 	/* Check for Multicast least significant bit of MSB == 1 */
1694f10a77bbSDavid C Somayajulu 	if (eh->evl_dhost[0] & 0x01) {
1695f10a77bbSDavid C Somayajulu 		tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST;
1696f10a77bbSDavid C Somayajulu 	}
1697f10a77bbSDavid C Somayajulu 
1698f10a77bbSDavid C Somayajulu 	if (mp->m_len < hdrlen) {
1699f10a77bbSDavid C Somayajulu 		printf("%d\n", hdrlen);
1700f10a77bbSDavid C Somayajulu 		return (1);
1701f10a77bbSDavid C Somayajulu 	}
1702f10a77bbSDavid C Somayajulu 
1703f10a77bbSDavid C Somayajulu 	return (0);
1704f10a77bbSDavid C Somayajulu }
1705f10a77bbSDavid C Somayajulu 
1706f10a77bbSDavid C Somayajulu /*
1707f10a77bbSDavid C Somayajulu  * Name: qla_tx_chksum
1708f10a77bbSDavid C Somayajulu  * Function: Checks if the packet to be transmitted is a candidate for
1709f10a77bbSDavid C Somayajulu  *	TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx
1710f10a77bbSDavid C Somayajulu  *	Ring Structure are plugged in.
1711f10a77bbSDavid C Somayajulu  */
1712f10a77bbSDavid C Somayajulu static int
1713f10a77bbSDavid C Somayajulu qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code,
1714f10a77bbSDavid C Somayajulu 	uint32_t *tcp_hdr_off)
1715f10a77bbSDavid C Somayajulu {
1716f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1717f10a77bbSDavid C Somayajulu 	struct ip *ip;
1718f10a77bbSDavid C Somayajulu 	struct ip6_hdr *ip6;
1719f10a77bbSDavid C Somayajulu 	uint32_t ehdrlen, ip_hlen;
1720f10a77bbSDavid C Somayajulu 	uint16_t etype, opcode, offload = 1;
1721f10a77bbSDavid C Somayajulu 	device_t dev;
1722f10a77bbSDavid C Somayajulu 	uint8_t buf[sizeof(struct ip6_hdr)];
1723f10a77bbSDavid C Somayajulu 
1724f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1725f10a77bbSDavid C Somayajulu 
1726f10a77bbSDavid C Somayajulu 	*op_code = 0;
1727f10a77bbSDavid C Somayajulu 
1728f10a77bbSDavid C Somayajulu 	if ((mp->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) == 0)
1729f10a77bbSDavid C Somayajulu 		return (-1);
1730f10a77bbSDavid C Somayajulu 
1731f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
1732f10a77bbSDavid C Somayajulu 
1733f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1734f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1735f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_proto);
1736f10a77bbSDavid C Somayajulu 	} else {
1737f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN;
1738f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_encap_proto);
1739f10a77bbSDavid C Somayajulu 	}
1740f10a77bbSDavid C Somayajulu 
1741f10a77bbSDavid C Somayajulu 
1742f10a77bbSDavid C Somayajulu 	switch (etype) {
1743f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IP:
1744f10a77bbSDavid C Somayajulu 			ip = (struct ip *)(mp->m_data + ehdrlen);
1745f10a77bbSDavid C Somayajulu 
1746f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof (struct ip);
1747f10a77bbSDavid C Somayajulu 
1748f10a77bbSDavid C Somayajulu 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1749f10a77bbSDavid C Somayajulu 				m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
1750f10a77bbSDavid C Somayajulu 				ip = (struct ip *)buf;
1751f10a77bbSDavid C Somayajulu 			}
1752f10a77bbSDavid C Somayajulu 
1753f10a77bbSDavid C Somayajulu 			if (ip->ip_p == IPPROTO_TCP)
1754f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM;
1755f10a77bbSDavid C Somayajulu 			else if (ip->ip_p == IPPROTO_UDP)
1756f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM;
1757f10a77bbSDavid C Somayajulu 			else {
1758f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv4\n", __func__);
1759f10a77bbSDavid C Somayajulu 				offload = 0;
1760f10a77bbSDavid C Somayajulu 			}
1761f10a77bbSDavid C Somayajulu 		break;
1762f10a77bbSDavid C Somayajulu 
1763f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IPV6:
1764f10a77bbSDavid C Somayajulu 			ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1765f10a77bbSDavid C Somayajulu 
1766f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof(struct ip6_hdr);
1767f10a77bbSDavid C Somayajulu 
1768f10a77bbSDavid C Somayajulu 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1769f10a77bbSDavid C Somayajulu 				m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
1770f10a77bbSDavid C Somayajulu 					buf);
1771f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)buf;
1772f10a77bbSDavid C Somayajulu 			}
1773f10a77bbSDavid C Somayajulu 
1774f10a77bbSDavid C Somayajulu 			if (ip6->ip6_nxt == IPPROTO_TCP)
1775f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6;
1776f10a77bbSDavid C Somayajulu 			else if (ip6->ip6_nxt == IPPROTO_UDP)
1777f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6;
1778f10a77bbSDavid C Somayajulu 			else {
1779f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv6\n", __func__);
1780f10a77bbSDavid C Somayajulu 				offload = 0;
1781f10a77bbSDavid C Somayajulu 			}
1782f10a77bbSDavid C Somayajulu 		break;
1783f10a77bbSDavid C Somayajulu 
1784f10a77bbSDavid C Somayajulu 		default:
1785f10a77bbSDavid C Somayajulu 			offload = 0;
1786f10a77bbSDavid C Somayajulu 		break;
1787f10a77bbSDavid C Somayajulu 	}
1788f10a77bbSDavid C Somayajulu 	if (!offload)
1789f10a77bbSDavid C Somayajulu 		return (-1);
1790f10a77bbSDavid C Somayajulu 
1791f10a77bbSDavid C Somayajulu 	*op_code = opcode;
1792f10a77bbSDavid C Somayajulu 	*tcp_hdr_off = (ip_hlen + ehdrlen);
1793f10a77bbSDavid C Somayajulu 
1794f10a77bbSDavid C Somayajulu 	return (0);
1795f10a77bbSDavid C Somayajulu }
1796f10a77bbSDavid C Somayajulu 
1797f10a77bbSDavid C Somayajulu #define QLA_TX_MIN_FREE 2
1798f10a77bbSDavid C Somayajulu /*
1799f10a77bbSDavid C Somayajulu  * Name: ql_hw_send
1800f10a77bbSDavid C Somayajulu  * Function: Transmits a packet. It first checks if the packet is a
1801f10a77bbSDavid C Somayajulu  *	candidate for Large TCP Segment Offload and then for UDP/TCP checksum
1802f10a77bbSDavid C Somayajulu  *	offload. If either of these creteria are not met, it is transmitted
1803f10a77bbSDavid C Somayajulu  *	as a regular ethernet frame.
1804f10a77bbSDavid C Somayajulu  */
1805f10a77bbSDavid C Somayajulu int
1806f10a77bbSDavid C Somayajulu ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
180735291c22SDavid C Somayajulu 	uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu)
1808f10a77bbSDavid C Somayajulu {
1809f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1810f10a77bbSDavid C Somayajulu 	qla_hw_t *hw = &ha->hw;
1811f10a77bbSDavid C Somayajulu 	q80_tx_cmd_t *tx_cmd, tso_cmd;
1812f10a77bbSDavid C Somayajulu 	bus_dma_segment_t *c_seg;
1813f10a77bbSDavid C Somayajulu 	uint32_t num_tx_cmds, hdr_len = 0;
1814f10a77bbSDavid C Somayajulu 	uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next;
1815f10a77bbSDavid C Somayajulu 	device_t dev;
1816f10a77bbSDavid C Somayajulu 	int i, ret;
1817f10a77bbSDavid C Somayajulu 	uint8_t *src = NULL, *dst = NULL;
1818f10a77bbSDavid C Somayajulu 	uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
1819f10a77bbSDavid C Somayajulu 	uint32_t op_code = 0;
1820f10a77bbSDavid C Somayajulu 	uint32_t tcp_hdr_off = 0;
1821f10a77bbSDavid C Somayajulu 
1822f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1823f10a77bbSDavid C Somayajulu 
1824f10a77bbSDavid C Somayajulu 	/*
1825f10a77bbSDavid C Somayajulu 	 * Always make sure there is atleast one empty slot in the tx_ring
1826f10a77bbSDavid C Somayajulu 	 * tx_ring is considered full when there only one entry available
1827f10a77bbSDavid C Somayajulu 	 */
1828f10a77bbSDavid C Somayajulu         num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2;
1829f10a77bbSDavid C Somayajulu 
1830f10a77bbSDavid C Somayajulu 	total_length = mp->m_pkthdr.len;
1831f10a77bbSDavid C Somayajulu 	if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
1832f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
1833f10a77bbSDavid C Somayajulu 			__func__, total_length);
1834f10a77bbSDavid C Somayajulu 		return (-1);
1835f10a77bbSDavid C Somayajulu 	}
1836f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
1837f10a77bbSDavid C Somayajulu 
1838f10a77bbSDavid C Somayajulu 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
1839f10a77bbSDavid C Somayajulu 
1840f10a77bbSDavid C Somayajulu 		bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
1841f10a77bbSDavid C Somayajulu 
1842f10a77bbSDavid C Somayajulu 		src = frame_hdr;
1843f10a77bbSDavid C Somayajulu 		ret = qla_tx_tso(ha, mp, &tso_cmd, src);
1844f10a77bbSDavid C Somayajulu 
1845f10a77bbSDavid C Somayajulu 		if (!(ret & ~1)) {
1846f10a77bbSDavid C Somayajulu 			/* find the additional tx_cmd descriptors required */
1847f10a77bbSDavid C Somayajulu 
1848f10a77bbSDavid C Somayajulu 			if (mp->m_flags & M_VLANTAG)
1849f10a77bbSDavid C Somayajulu 				tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN;
1850f10a77bbSDavid C Somayajulu 
1851f10a77bbSDavid C Somayajulu 			hdr_len = tso_cmd.total_hdr_len;
1852f10a77bbSDavid C Somayajulu 
1853f10a77bbSDavid C Somayajulu 			bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
1854f10a77bbSDavid C Somayajulu 			bytes = QL_MIN(bytes, hdr_len);
1855f10a77bbSDavid C Somayajulu 
1856f10a77bbSDavid C Somayajulu 			num_tx_cmds++;
1857f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
1858f10a77bbSDavid C Somayajulu 
1859f10a77bbSDavid C Somayajulu 			while (hdr_len) {
1860f10a77bbSDavid C Somayajulu 				bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
1861f10a77bbSDavid C Somayajulu 				hdr_len -= bytes;
1862f10a77bbSDavid C Somayajulu 				num_tx_cmds++;
1863f10a77bbSDavid C Somayajulu 			}
1864f10a77bbSDavid C Somayajulu 			hdr_len = tso_cmd.total_hdr_len;
1865f10a77bbSDavid C Somayajulu 
1866f10a77bbSDavid C Somayajulu 			if (ret == 0)
1867f10a77bbSDavid C Somayajulu 				src = (uint8_t *)eh;
1868f10a77bbSDavid C Somayajulu 		} else
1869f10a77bbSDavid C Somayajulu 			return (EINVAL);
1870f10a77bbSDavid C Somayajulu 	} else {
1871f10a77bbSDavid C Somayajulu 		(void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off);
1872f10a77bbSDavid C Somayajulu 	}
1873f10a77bbSDavid C Somayajulu 
187435291c22SDavid C Somayajulu 	if (iscsi_pdu)
187535291c22SDavid C Somayajulu 		ha->hw.iscsi_pkt_count++;
187635291c22SDavid C Somayajulu 
1877f10a77bbSDavid C Somayajulu 	if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
1878f10a77bbSDavid C Somayajulu 		qla_hw_tx_done_locked(ha, txr_idx);
1879f10a77bbSDavid C Somayajulu 		if (hw->tx_cntxt[txr_idx].txr_free <=
1880f10a77bbSDavid C Somayajulu 				(num_tx_cmds + QLA_TX_MIN_FREE)) {
1881f10a77bbSDavid C Somayajulu         		QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= "
1882f10a77bbSDavid C Somayajulu 				"(num_tx_cmds + QLA_TX_MIN_FREE))\n",
1883f10a77bbSDavid C Somayajulu 				__func__));
1884f10a77bbSDavid C Somayajulu 			return (-1);
1885f10a77bbSDavid C Somayajulu 		}
1886f10a77bbSDavid C Somayajulu 	}
1887f10a77bbSDavid C Somayajulu 
1888f10a77bbSDavid C Somayajulu 	tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx];
1889f10a77bbSDavid C Somayajulu 
1890f10a77bbSDavid C Somayajulu         if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) {
1891f10a77bbSDavid C Somayajulu 
1892f10a77bbSDavid C Somayajulu                 if (nsegs > ha->hw.max_tx_segs)
1893f10a77bbSDavid C Somayajulu                         ha->hw.max_tx_segs = nsegs;
1894f10a77bbSDavid C Somayajulu 
1895f10a77bbSDavid C Somayajulu                 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
1896f10a77bbSDavid C Somayajulu 
1897f10a77bbSDavid C Somayajulu                 if (op_code) {
1898f10a77bbSDavid C Somayajulu                         tx_cmd->flags_opcode = op_code;
1899f10a77bbSDavid C Somayajulu                         tx_cmd->tcp_hdr_off = tcp_hdr_off;
1900f10a77bbSDavid C Somayajulu 
1901f10a77bbSDavid C Somayajulu                 } else {
1902f10a77bbSDavid C Somayajulu                         tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER;
1903f10a77bbSDavid C Somayajulu                 }
1904f10a77bbSDavid C Somayajulu 	} else {
1905f10a77bbSDavid C Somayajulu 		bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
1906f10a77bbSDavid C Somayajulu 		ha->tx_tso_frames++;
1907f10a77bbSDavid C Somayajulu 	}
1908f10a77bbSDavid C Somayajulu 
1909f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1910f10a77bbSDavid C Somayajulu         	tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
191135291c22SDavid C Somayajulu 
191235291c22SDavid C Somayajulu 		if (iscsi_pdu)
191335291c22SDavid C Somayajulu 			eh->evl_tag |= ha->hw.user_pri_iscsi << 13;
191435291c22SDavid C Somayajulu 
1915f10a77bbSDavid C Somayajulu 	} else if (mp->m_flags & M_VLANTAG) {
1916f10a77bbSDavid C Somayajulu 
1917f10a77bbSDavid C Somayajulu 		if (hdr_len) { /* TSO */
1918f10a77bbSDavid C Somayajulu 			tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED |
1919f10a77bbSDavid C Somayajulu 						Q8_TX_CMD_FLAGS_HW_VLAN_ID);
1920f10a77bbSDavid C Somayajulu 			tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN;
1921f10a77bbSDavid C Somayajulu 		} else
1922f10a77bbSDavid C Somayajulu 			tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID;
1923f10a77bbSDavid C Somayajulu 
1924f10a77bbSDavid C Somayajulu 		ha->hw_vlan_tx_frames++;
1925f10a77bbSDavid C Somayajulu 		tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag;
192635291c22SDavid C Somayajulu 
192735291c22SDavid C Somayajulu 		if (iscsi_pdu) {
192835291c22SDavid C Somayajulu 			tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13;
192935291c22SDavid C Somayajulu 			mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci;
193035291c22SDavid C Somayajulu 		}
1931f10a77bbSDavid C Somayajulu 	}
1932f10a77bbSDavid C Somayajulu 
1933f10a77bbSDavid C Somayajulu 
1934f10a77bbSDavid C Somayajulu         tx_cmd->n_bufs = (uint8_t)nsegs;
1935f10a77bbSDavid C Somayajulu         tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF);
1936f10a77bbSDavid C Somayajulu         tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8)));
1937f10a77bbSDavid C Somayajulu 	tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func);
1938f10a77bbSDavid C Somayajulu 
1939f10a77bbSDavid C Somayajulu 	c_seg = segs;
1940f10a77bbSDavid C Somayajulu 
1941f10a77bbSDavid C Somayajulu 	while (1) {
1942f10a77bbSDavid C Somayajulu 		for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) {
1943f10a77bbSDavid C Somayajulu 
1944f10a77bbSDavid C Somayajulu 			switch (i) {
1945f10a77bbSDavid C Somayajulu 			case 0:
1946f10a77bbSDavid C Somayajulu 				tx_cmd->buf1_addr = c_seg->ds_addr;
1947f10a77bbSDavid C Somayajulu 				tx_cmd->buf1_len = c_seg->ds_len;
1948f10a77bbSDavid C Somayajulu 				break;
1949f10a77bbSDavid C Somayajulu 
1950f10a77bbSDavid C Somayajulu 			case 1:
1951f10a77bbSDavid C Somayajulu 				tx_cmd->buf2_addr = c_seg->ds_addr;
1952f10a77bbSDavid C Somayajulu 				tx_cmd->buf2_len = c_seg->ds_len;
1953f10a77bbSDavid C Somayajulu 				break;
1954f10a77bbSDavid C Somayajulu 
1955f10a77bbSDavid C Somayajulu 			case 2:
1956f10a77bbSDavid C Somayajulu 				tx_cmd->buf3_addr = c_seg->ds_addr;
1957f10a77bbSDavid C Somayajulu 				tx_cmd->buf3_len = c_seg->ds_len;
1958f10a77bbSDavid C Somayajulu 				break;
1959f10a77bbSDavid C Somayajulu 
1960f10a77bbSDavid C Somayajulu 			case 3:
1961f10a77bbSDavid C Somayajulu 				tx_cmd->buf4_addr = c_seg->ds_addr;
1962f10a77bbSDavid C Somayajulu 				tx_cmd->buf4_len = c_seg->ds_len;
1963f10a77bbSDavid C Somayajulu 				break;
1964f10a77bbSDavid C Somayajulu 			}
1965f10a77bbSDavid C Somayajulu 
1966f10a77bbSDavid C Somayajulu 			c_seg++;
1967f10a77bbSDavid C Somayajulu 			nsegs--;
1968f10a77bbSDavid C Somayajulu 		}
1969f10a77bbSDavid C Somayajulu 
1970f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
1971f10a77bbSDavid C Somayajulu 			(hw->tx_cntxt[txr_idx].txr_next + 1) &
1972f10a77bbSDavid C Somayajulu 				(NUM_TX_DESCRIPTORS - 1);
1973f10a77bbSDavid C Somayajulu 		tx_cmd_count++;
1974f10a77bbSDavid C Somayajulu 
1975f10a77bbSDavid C Somayajulu 		if (!nsegs)
1976f10a77bbSDavid C Somayajulu 			break;
1977f10a77bbSDavid C Somayajulu 
1978f10a77bbSDavid C Somayajulu 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
1979f10a77bbSDavid C Somayajulu 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
1980f10a77bbSDavid C Somayajulu 	}
1981f10a77bbSDavid C Somayajulu 
1982f10a77bbSDavid C Somayajulu 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
1983f10a77bbSDavid C Somayajulu 
1984f10a77bbSDavid C Somayajulu 		/* TSO : Copy the header in the following tx cmd descriptors */
1985f10a77bbSDavid C Somayajulu 
1986f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next;
1987f10a77bbSDavid C Somayajulu 
1988f10a77bbSDavid C Somayajulu 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
1989f10a77bbSDavid C Somayajulu 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
1990f10a77bbSDavid C Somayajulu 
1991f10a77bbSDavid C Somayajulu 		bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
1992f10a77bbSDavid C Somayajulu 		bytes = QL_MIN(bytes, hdr_len);
1993f10a77bbSDavid C Somayajulu 
1994f10a77bbSDavid C Somayajulu 		dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN;
1995f10a77bbSDavid C Somayajulu 
1996f10a77bbSDavid C Somayajulu 		if (mp->m_flags & M_VLANTAG) {
1997f10a77bbSDavid C Somayajulu 			/* first copy the src/dst MAC addresses */
1998f10a77bbSDavid C Somayajulu 			bcopy(src, dst, (ETHER_ADDR_LEN * 2));
1999f10a77bbSDavid C Somayajulu 			dst += (ETHER_ADDR_LEN * 2);
2000f10a77bbSDavid C Somayajulu 			src += (ETHER_ADDR_LEN * 2);
2001f10a77bbSDavid C Somayajulu 
2002f10a77bbSDavid C Somayajulu 			*((uint16_t *)dst) = htons(ETHERTYPE_VLAN);
2003f10a77bbSDavid C Somayajulu 			dst += 2;
2004f10a77bbSDavid C Somayajulu 			*((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag);
2005f10a77bbSDavid C Somayajulu 			dst += 2;
2006f10a77bbSDavid C Somayajulu 
2007f10a77bbSDavid C Somayajulu 			/* bytes left in src header */
2008f10a77bbSDavid C Somayajulu 			hdr_len -= ((ETHER_ADDR_LEN * 2) +
2009f10a77bbSDavid C Somayajulu 					ETHER_VLAN_ENCAP_LEN);
2010f10a77bbSDavid C Somayajulu 
2011f10a77bbSDavid C Somayajulu 			/* bytes left in TxCmd Entry */
2012f10a77bbSDavid C Somayajulu 			bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN);
2013f10a77bbSDavid C Somayajulu 
2014f10a77bbSDavid C Somayajulu 
2015f10a77bbSDavid C Somayajulu 			bcopy(src, dst, bytes);
2016f10a77bbSDavid C Somayajulu 			src += bytes;
2017f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2018f10a77bbSDavid C Somayajulu 		} else {
2019f10a77bbSDavid C Somayajulu 			bcopy(src, dst, bytes);
2020f10a77bbSDavid C Somayajulu 			src += bytes;
2021f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2022f10a77bbSDavid C Somayajulu 		}
2023f10a77bbSDavid C Somayajulu 
2024f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2025f10a77bbSDavid C Somayajulu 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2026f10a77bbSDavid C Somayajulu 					(NUM_TX_DESCRIPTORS - 1);
2027f10a77bbSDavid C Somayajulu 		tx_cmd_count++;
2028f10a77bbSDavid C Somayajulu 
2029f10a77bbSDavid C Somayajulu 		while (hdr_len) {
2030f10a77bbSDavid C Somayajulu 			tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2031f10a77bbSDavid C Somayajulu 			bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2032f10a77bbSDavid C Somayajulu 
2033f10a77bbSDavid C Somayajulu 			bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2034f10a77bbSDavid C Somayajulu 
2035f10a77bbSDavid C Somayajulu 			bcopy(src, tx_cmd, bytes);
2036f10a77bbSDavid C Somayajulu 			src += bytes;
2037f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2038f10a77bbSDavid C Somayajulu 
2039f10a77bbSDavid C Somayajulu 			txr_next = hw->tx_cntxt[txr_idx].txr_next =
2040f10a77bbSDavid C Somayajulu 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2041f10a77bbSDavid C Somayajulu 					(NUM_TX_DESCRIPTORS - 1);
2042f10a77bbSDavid C Somayajulu 			tx_cmd_count++;
2043f10a77bbSDavid C Somayajulu 		}
2044f10a77bbSDavid C Somayajulu 	}
2045f10a77bbSDavid C Somayajulu 
2046f10a77bbSDavid C Somayajulu 	hw->tx_cntxt[txr_idx].txr_free =
2047f10a77bbSDavid C Somayajulu 		hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count;
2048f10a77bbSDavid C Somayajulu 
2049f10a77bbSDavid C Somayajulu 	QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\
2050f10a77bbSDavid C Somayajulu 		txr_idx);
2051f10a77bbSDavid C Somayajulu        	QL_DPRINT8(ha, (dev, "%s: return\n", __func__));
2052f10a77bbSDavid C Somayajulu 
2053f10a77bbSDavid C Somayajulu 	return (0);
2054f10a77bbSDavid C Somayajulu }
2055f10a77bbSDavid C Somayajulu 
2056f10a77bbSDavid C Somayajulu 
205735291c22SDavid C Somayajulu 
205835291c22SDavid C Somayajulu #define Q8_CONFIG_IND_TBL_SIZE	32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */
2059f10a77bbSDavid C Somayajulu static int
2060f10a77bbSDavid C Somayajulu qla_config_rss_ind_table(qla_host_t *ha)
2061f10a77bbSDavid C Somayajulu {
2062f10a77bbSDavid C Somayajulu 	uint32_t i, count;
206335291c22SDavid C Somayajulu 	uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE];
2064f10a77bbSDavid C Somayajulu 
2065f10a77bbSDavid C Somayajulu 
206635291c22SDavid C Somayajulu 	for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) {
2067f10a77bbSDavid C Somayajulu 		rss_ind_tbl[i] = i % ha->hw.num_sds_rings;
2068f10a77bbSDavid C Somayajulu 	}
2069f10a77bbSDavid C Somayajulu 
207035291c22SDavid C Somayajulu 	for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ;
207135291c22SDavid C Somayajulu 		i = i + Q8_CONFIG_IND_TBL_SIZE) {
2072f10a77bbSDavid C Somayajulu 
207335291c22SDavid C Somayajulu 		if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) {
2074f10a77bbSDavid C Somayajulu 			count = Q8_RSS_IND_TBL_MAX_IDX - i + 1;
2075f10a77bbSDavid C Somayajulu 		} else {
207635291c22SDavid C Somayajulu 			count = Q8_CONFIG_IND_TBL_SIZE;
2077f10a77bbSDavid C Somayajulu 		}
2078f10a77bbSDavid C Somayajulu 
2079f10a77bbSDavid C Somayajulu 		if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id,
2080f10a77bbSDavid C Somayajulu 			rss_ind_tbl))
2081f10a77bbSDavid C Somayajulu 			return (-1);
2082f10a77bbSDavid C Somayajulu 	}
2083f10a77bbSDavid C Somayajulu 
2084f10a77bbSDavid C Somayajulu 	return (0);
2085f10a77bbSDavid C Somayajulu }
2086f10a77bbSDavid C Somayajulu 
2087f10a77bbSDavid C Somayajulu /*
2088f10a77bbSDavid C Somayajulu  * Name: ql_del_hw_if
2089f10a77bbSDavid C Somayajulu  * Function: Destroys the hardware specific entities corresponding to an
2090f10a77bbSDavid C Somayajulu  *	Ethernet Interface
2091f10a77bbSDavid C Somayajulu  */
2092f10a77bbSDavid C Somayajulu void
2093f10a77bbSDavid C Somayajulu ql_del_hw_if(qla_host_t *ha)
2094f10a77bbSDavid C Somayajulu {
209535291c22SDavid C Somayajulu 	uint32_t i;
209635291c22SDavid C Somayajulu 	uint32_t num_msix;
209735291c22SDavid C Somayajulu 
209835291c22SDavid C Somayajulu 	(void)qla_stop_nic_func(ha);
2099f10a77bbSDavid C Somayajulu 
2100f10a77bbSDavid C Somayajulu 	qla_del_rcv_cntxt(ha);
2101f10a77bbSDavid C Somayajulu 	qla_del_xmt_cntxt(ha);
2102f10a77bbSDavid C Somayajulu 
2103f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.init_intr_cnxt) {
210435291c22SDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; ) {
210535291c22SDavid C Somayajulu 
210635291c22SDavid C Somayajulu 			if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
210735291c22SDavid C Somayajulu 				num_msix = Q8_MAX_INTR_VECTORS;
210835291c22SDavid C Somayajulu 			else
210935291c22SDavid C Somayajulu 				num_msix = ha->hw.num_sds_rings - i;
211035291c22SDavid C Somayajulu 			qla_config_intr_cntxt(ha, i, num_msix, 0);
211135291c22SDavid C Somayajulu 
211235291c22SDavid C Somayajulu 			i += num_msix;
211335291c22SDavid C Somayajulu 		}
211435291c22SDavid C Somayajulu 
2115f10a77bbSDavid C Somayajulu 		ha->hw.flags.init_intr_cnxt = 0;
2116f10a77bbSDavid C Somayajulu 	}
211735291c22SDavid C Somayajulu 	return;
2118f10a77bbSDavid C Somayajulu }
2119f10a77bbSDavid C Somayajulu 
212035291c22SDavid C Somayajulu void
212135291c22SDavid C Somayajulu qla_confirm_9kb_enable(qla_host_t *ha)
212235291c22SDavid C Somayajulu {
212335291c22SDavid C Somayajulu 	uint32_t supports_9kb = 0;
212435291c22SDavid C Somayajulu 
212535291c22SDavid C Somayajulu 	ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX);
212635291c22SDavid C Somayajulu 
212735291c22SDavid C Somayajulu 	/* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */
212835291c22SDavid C Somayajulu 	WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2);
212935291c22SDavid C Somayajulu 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
213035291c22SDavid C Somayajulu 
213135291c22SDavid C Somayajulu 	qla_get_nic_partition(ha, &supports_9kb, NULL);
213235291c22SDavid C Somayajulu 
213335291c22SDavid C Somayajulu 	if (!supports_9kb)
213435291c22SDavid C Somayajulu 		ha->hw.enable_9kb = 0;
213535291c22SDavid C Somayajulu 
213635291c22SDavid C Somayajulu 	return;
213735291c22SDavid C Somayajulu }
213835291c22SDavid C Somayajulu 
213935291c22SDavid C Somayajulu 
2140f10a77bbSDavid C Somayajulu /*
2141f10a77bbSDavid C Somayajulu  * Name: ql_init_hw_if
2142f10a77bbSDavid C Somayajulu  * Function: Creates the hardware specific entities corresponding to an
2143f10a77bbSDavid C Somayajulu  *	Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
2144f10a77bbSDavid C Somayajulu  *	corresponding to the interface. Enables LRO if allowed.
2145f10a77bbSDavid C Somayajulu  */
2146f10a77bbSDavid C Somayajulu int
2147f10a77bbSDavid C Somayajulu ql_init_hw_if(qla_host_t *ha)
2148f10a77bbSDavid C Somayajulu {
2149f10a77bbSDavid C Somayajulu 	device_t	dev;
2150f10a77bbSDavid C Somayajulu 	uint32_t	i;
2151f10a77bbSDavid C Somayajulu 	uint8_t		bcast_mac[6];
2152f10a77bbSDavid C Somayajulu 	qla_rdesc_t	*rdesc;
215335291c22SDavid C Somayajulu 	uint32_t	num_msix;
2154f10a77bbSDavid C Somayajulu 
2155f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2156f10a77bbSDavid C Somayajulu 
2157f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; i++) {
2158f10a77bbSDavid C Somayajulu 		bzero(ha->hw.dma_buf.sds_ring[i].dma_b,
2159f10a77bbSDavid C Somayajulu 			ha->hw.dma_buf.sds_ring[i].size);
2160f10a77bbSDavid C Somayajulu 	}
2161f10a77bbSDavid C Somayajulu 
216235291c22SDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; ) {
2163f10a77bbSDavid C Somayajulu 
216435291c22SDavid C Somayajulu 		if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
216535291c22SDavid C Somayajulu 			num_msix = Q8_MAX_INTR_VECTORS;
216635291c22SDavid C Somayajulu 		else
216735291c22SDavid C Somayajulu 			num_msix = ha->hw.num_sds_rings - i;
2168f10a77bbSDavid C Somayajulu 
216935291c22SDavid C Somayajulu 		if (qla_config_intr_cntxt(ha, i, num_msix, 1)) {
217035291c22SDavid C Somayajulu 
217135291c22SDavid C Somayajulu 			if (i > 0) {
217235291c22SDavid C Somayajulu 
217335291c22SDavid C Somayajulu 				num_msix = i;
217435291c22SDavid C Somayajulu 
217535291c22SDavid C Somayajulu 				for (i = 0; i < num_msix; ) {
217635291c22SDavid C Somayajulu 					qla_config_intr_cntxt(ha, i,
217735291c22SDavid C Somayajulu 						Q8_MAX_INTR_VECTORS, 0);
217835291c22SDavid C Somayajulu 					i += Q8_MAX_INTR_VECTORS;
217935291c22SDavid C Somayajulu 				}
218035291c22SDavid C Somayajulu 			}
2181f10a77bbSDavid C Somayajulu 			return (-1);
218235291c22SDavid C Somayajulu 		}
218335291c22SDavid C Somayajulu 
218435291c22SDavid C Somayajulu 		i = i + num_msix;
218535291c22SDavid C Somayajulu 	}
218635291c22SDavid C Somayajulu 
218735291c22SDavid C Somayajulu         ha->hw.flags.init_intr_cnxt = 1;
2188f10a77bbSDavid C Somayajulu 
2189f10a77bbSDavid C Somayajulu 	if (ha->hw.mdump_init == 0) {
2190f10a77bbSDavid C Somayajulu 		qla_minidump_init(ha);
2191f10a77bbSDavid C Somayajulu 	}
2192f10a77bbSDavid C Somayajulu 
2193f10a77bbSDavid C Somayajulu 	/*
2194f10a77bbSDavid C Somayajulu 	 * Create Receive Context
2195f10a77bbSDavid C Somayajulu 	 */
2196f10a77bbSDavid C Somayajulu 	if (qla_init_rcv_cntxt(ha)) {
2197f10a77bbSDavid C Somayajulu 		return (-1);
2198f10a77bbSDavid C Somayajulu 	}
2199f10a77bbSDavid C Somayajulu 
2200f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_rds_rings; i++) {
2201f10a77bbSDavid C Somayajulu 		rdesc = &ha->hw.rds[i];
2202f10a77bbSDavid C Somayajulu 		rdesc->rx_next = NUM_RX_DESCRIPTORS - 2;
2203f10a77bbSDavid C Somayajulu 		rdesc->rx_in = 0;
2204f10a77bbSDavid C Somayajulu 		/* Update the RDS Producer Indices */
2205f10a77bbSDavid C Somayajulu 		QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\
2206f10a77bbSDavid C Somayajulu 			rdesc->rx_next);
2207f10a77bbSDavid C Somayajulu 	}
2208f10a77bbSDavid C Somayajulu 
2209f10a77bbSDavid C Somayajulu 
2210f10a77bbSDavid C Somayajulu 	/*
2211f10a77bbSDavid C Somayajulu 	 * Create Transmit Context
2212f10a77bbSDavid C Somayajulu 	 */
2213f10a77bbSDavid C Somayajulu 	if (qla_init_xmt_cntxt(ha)) {
2214f10a77bbSDavid C Somayajulu 		qla_del_rcv_cntxt(ha);
2215f10a77bbSDavid C Somayajulu 		return (-1);
2216f10a77bbSDavid C Somayajulu 	}
2217f10a77bbSDavid C Somayajulu 	ha->hw.max_tx_segs = 0;
2218f10a77bbSDavid C Somayajulu 
2219f10a77bbSDavid C Somayajulu 	if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1))
2220f10a77bbSDavid C Somayajulu 		return(-1);
2221f10a77bbSDavid C Somayajulu 
2222f10a77bbSDavid C Somayajulu 	ha->hw.flags.unicast_mac = 1;
2223f10a77bbSDavid C Somayajulu 
2224f10a77bbSDavid C Somayajulu 	bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2225f10a77bbSDavid C Somayajulu 	bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2226f10a77bbSDavid C Somayajulu 
2227f10a77bbSDavid C Somayajulu 	if (qla_config_mac_addr(ha, bcast_mac, 1))
2228f10a77bbSDavid C Somayajulu 		return (-1);
2229f10a77bbSDavid C Somayajulu 
2230f10a77bbSDavid C Somayajulu 	ha->hw.flags.bcast_mac = 1;
2231f10a77bbSDavid C Somayajulu 
2232f10a77bbSDavid C Somayajulu 	/*
2233f10a77bbSDavid C Somayajulu 	 * program any cached multicast addresses
2234f10a77bbSDavid C Somayajulu 	 */
2235f10a77bbSDavid C Somayajulu 	if (qla_hw_add_all_mcast(ha))
2236f10a77bbSDavid C Somayajulu 		return (-1);
2237f10a77bbSDavid C Somayajulu 
2238f10a77bbSDavid C Somayajulu 	if (qla_config_rss(ha, ha->hw.rcv_cntxt_id))
2239f10a77bbSDavid C Somayajulu 		return (-1);
2240f10a77bbSDavid C Somayajulu 
2241f10a77bbSDavid C Somayajulu 	if (qla_config_rss_ind_table(ha))
2242f10a77bbSDavid C Somayajulu 		return (-1);
2243f10a77bbSDavid C Somayajulu 
224435291c22SDavid C Somayajulu 	if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1))
2245f10a77bbSDavid C Somayajulu 		return (-1);
2246f10a77bbSDavid C Somayajulu 
2247f10a77bbSDavid C Somayajulu 	if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
2248f10a77bbSDavid C Somayajulu 		return (-1);
2249f10a77bbSDavid C Somayajulu 
2250f10a77bbSDavid C Somayajulu 	if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
2251f10a77bbSDavid C Somayajulu 		return (-1);
2252f10a77bbSDavid C Somayajulu 
225335291c22SDavid C Somayajulu         if (qla_init_nic_func(ha))
225435291c22SDavid C Somayajulu                 return (-1);
225535291c22SDavid C Somayajulu 
225635291c22SDavid C Somayajulu         if (qla_query_fw_dcbx_caps(ha))
225735291c22SDavid C Somayajulu                 return (-1);
225835291c22SDavid C Somayajulu 
2259f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; i++)
2260f10a77bbSDavid C Somayajulu 		QL_ENABLE_INTERRUPTS(ha, i);
2261f10a77bbSDavid C Somayajulu 
2262f10a77bbSDavid C Somayajulu 	return (0);
2263f10a77bbSDavid C Somayajulu }
2264f10a77bbSDavid C Somayajulu 
2265f10a77bbSDavid C Somayajulu static int
226635291c22SDavid C Somayajulu qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx)
2267f10a77bbSDavid C Somayajulu {
2268f10a77bbSDavid C Somayajulu         device_t                dev = ha->pci_dev;
2269f10a77bbSDavid C Somayajulu         q80_rq_map_sds_to_rds_t *map_rings;
227035291c22SDavid C Somayajulu 	q80_rsp_map_sds_to_rds_t *map_rings_rsp;
2271f10a77bbSDavid C Somayajulu         uint32_t                i, err;
2272f10a77bbSDavid C Somayajulu         qla_hw_t                *hw = &ha->hw;
2273f10a77bbSDavid C Somayajulu 
2274f10a77bbSDavid C Somayajulu         map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox;
2275f10a77bbSDavid C Somayajulu         bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t));
2276f10a77bbSDavid C Somayajulu 
2277f10a77bbSDavid C Somayajulu         map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS;
2278f10a77bbSDavid C Somayajulu         map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2);
2279f10a77bbSDavid C Somayajulu         map_rings->count_version |= Q8_MBX_CMD_VERSION;
2280f10a77bbSDavid C Somayajulu 
2281f10a77bbSDavid C Somayajulu         map_rings->cntxt_id = hw->rcv_cntxt_id;
228235291c22SDavid C Somayajulu         map_rings->num_rings = num_idx;
2283f10a77bbSDavid C Somayajulu 
228435291c22SDavid C Somayajulu 	for (i = 0; i < num_idx; i++) {
228535291c22SDavid C Somayajulu 		map_rings->sds_rds[i].sds_ring = i + start_idx;
228635291c22SDavid C Somayajulu 		map_rings->sds_rds[i].rds_ring = i + start_idx;
2287f10a77bbSDavid C Somayajulu 	}
2288f10a77bbSDavid C Somayajulu 
2289f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)map_rings,
2290f10a77bbSDavid C Somayajulu                 (sizeof (q80_rq_map_sds_to_rds_t) >> 2),
2291f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2292f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2293f10a77bbSDavid C Somayajulu                 return (-1);
2294f10a77bbSDavid C Somayajulu         }
2295f10a77bbSDavid C Somayajulu 
229635291c22SDavid C Somayajulu         map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox;
2297f10a77bbSDavid C Somayajulu 
2298f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status);
2299f10a77bbSDavid C Somayajulu 
2300f10a77bbSDavid C Somayajulu         if (err) {
2301f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2302f10a77bbSDavid C Somayajulu                 return (-1);
2303f10a77bbSDavid C Somayajulu         }
2304f10a77bbSDavid C Somayajulu 
2305f10a77bbSDavid C Somayajulu         return (0);
2306f10a77bbSDavid C Somayajulu }
2307f10a77bbSDavid C Somayajulu 
2308f10a77bbSDavid C Somayajulu /*
2309f10a77bbSDavid C Somayajulu  * Name: qla_init_rcv_cntxt
2310f10a77bbSDavid C Somayajulu  * Function: Creates the Receive Context.
2311f10a77bbSDavid C Somayajulu  */
2312f10a77bbSDavid C Somayajulu static int
2313f10a77bbSDavid C Somayajulu qla_init_rcv_cntxt(qla_host_t *ha)
2314f10a77bbSDavid C Somayajulu {
2315f10a77bbSDavid C Somayajulu 	q80_rq_rcv_cntxt_t	*rcntxt;
2316f10a77bbSDavid C Somayajulu 	q80_rsp_rcv_cntxt_t	*rcntxt_rsp;
2317f10a77bbSDavid C Somayajulu 	q80_stat_desc_t		*sdesc;
2318f10a77bbSDavid C Somayajulu 	int			i, j;
2319f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2320f10a77bbSDavid C Somayajulu 	device_t		dev;
2321f10a77bbSDavid C Somayajulu 	uint32_t		err;
2322f10a77bbSDavid C Somayajulu 	uint32_t		rcntxt_sds_rings;
2323f10a77bbSDavid C Somayajulu 	uint32_t		rcntxt_rds_rings;
232435291c22SDavid C Somayajulu 	uint32_t		max_idx;
2325f10a77bbSDavid C Somayajulu 
2326f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2327f10a77bbSDavid C Somayajulu 
2328f10a77bbSDavid C Somayajulu 	/*
2329f10a77bbSDavid C Somayajulu 	 * Create Receive Context
2330f10a77bbSDavid C Somayajulu 	 */
2331f10a77bbSDavid C Somayajulu 
2332f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
2333f10a77bbSDavid C Somayajulu 		sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0];
2334f10a77bbSDavid C Somayajulu 
2335f10a77bbSDavid C Somayajulu 		for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) {
2336f10a77bbSDavid C Somayajulu 			sdesc->data[0] = 1ULL;
2337f10a77bbSDavid C Somayajulu 			sdesc->data[1] = 1ULL;
2338f10a77bbSDavid C Somayajulu 		}
2339f10a77bbSDavid C Somayajulu 	}
2340f10a77bbSDavid C Somayajulu 
2341f10a77bbSDavid C Somayajulu 	rcntxt_sds_rings = hw->num_sds_rings;
2342f10a77bbSDavid C Somayajulu 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS)
2343f10a77bbSDavid C Somayajulu 		rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS;
2344f10a77bbSDavid C Somayajulu 
2345f10a77bbSDavid C Somayajulu 	rcntxt_rds_rings = hw->num_rds_rings;
2346f10a77bbSDavid C Somayajulu 
2347f10a77bbSDavid C Somayajulu 	if (hw->num_rds_rings > MAX_RDS_RING_SETS)
2348f10a77bbSDavid C Somayajulu 		rcntxt_rds_rings = MAX_RDS_RING_SETS;
2349f10a77bbSDavid C Somayajulu 
2350f10a77bbSDavid C Somayajulu 	rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox;
2351f10a77bbSDavid C Somayajulu 	bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t)));
2352f10a77bbSDavid C Somayajulu 
2353f10a77bbSDavid C Somayajulu 	rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT;
2354f10a77bbSDavid C Somayajulu 	rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2);
2355f10a77bbSDavid C Somayajulu 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2356f10a77bbSDavid C Somayajulu 
2357f10a77bbSDavid C Somayajulu 	rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW |
2358f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_LRO |
2359f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_HW_LRO |
2360f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_RSS |
2361f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_SGL_LRO;
2362f10a77bbSDavid C Somayajulu 
236335291c22SDavid C Somayajulu 	if (ha->hw.enable_9kb)
236435291c22SDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO;
236535291c22SDavid C Somayajulu 	else
236635291c22SDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO;
236735291c22SDavid C Somayajulu 
2368f10a77bbSDavid C Somayajulu 	if (ha->hw.num_rds_rings > 1) {
2369f10a77bbSDavid C Somayajulu 		rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5);
2370f10a77bbSDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS;
2371f10a77bbSDavid C Somayajulu 	} else
2372f10a77bbSDavid C Somayajulu 		rcntxt->nrds_sets_rings = 0x1 | (1 << 5);
2373f10a77bbSDavid C Somayajulu 
2374f10a77bbSDavid C Somayajulu 	rcntxt->nsds_rings = rcntxt_sds_rings;
2375f10a77bbSDavid C Somayajulu 
2376f10a77bbSDavid C Somayajulu 	rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE;
2377f10a77bbSDavid C Somayajulu 
2378f10a77bbSDavid C Somayajulu 	rcntxt->rcv_vpid = 0;
2379f10a77bbSDavid C Somayajulu 
2380f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2381f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].paddr =
2382f10a77bbSDavid C Somayajulu 			qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr);
2383f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].size =
2384f10a77bbSDavid C Somayajulu 			qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2385f10a77bbSDavid C Somayajulu 		if (ha->msix_count == 2) {
2386f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_id =
2387f10a77bbSDavid C Somayajulu 				qla_host_to_le16(hw->intr_id[0]);
2388f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_src_bit = qla_host_to_le16((i));
2389f10a77bbSDavid C Somayajulu 		} else {
2390f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_id =
2391f10a77bbSDavid C Somayajulu 				qla_host_to_le16(hw->intr_id[i]);
2392f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0);
2393f10a77bbSDavid C Somayajulu 		}
2394f10a77bbSDavid C Somayajulu 	}
2395f10a77bbSDavid C Somayajulu 
2396f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2397f10a77bbSDavid C Somayajulu 		rcntxt->rds[i].paddr_std =
2398f10a77bbSDavid C Somayajulu 			qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr);
239935291c22SDavid C Somayajulu 
240035291c22SDavid C Somayajulu 		if (ha->hw.enable_9kb)
240135291c22SDavid C Somayajulu 			rcntxt->rds[i].std_bsize =
240235291c22SDavid C Somayajulu 				qla_host_to_le64(MJUM9BYTES);
240335291c22SDavid C Somayajulu 		else
2404f10a77bbSDavid C Somayajulu 			rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
240535291c22SDavid C Somayajulu 
2406f10a77bbSDavid C Somayajulu 		rcntxt->rds[i].std_nentries =
2407f10a77bbSDavid C Somayajulu 			qla_host_to_le32(NUM_RX_DESCRIPTORS);
2408f10a77bbSDavid C Somayajulu 	}
2409f10a77bbSDavid C Somayajulu 
2410f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2411f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_rcv_cntxt_t) >> 2),
2412f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) {
2413f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2414f10a77bbSDavid C Somayajulu                 return (-1);
2415f10a77bbSDavid C Somayajulu         }
2416f10a77bbSDavid C Somayajulu 
2417f10a77bbSDavid C Somayajulu         rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox;
2418f10a77bbSDavid C Somayajulu 
2419f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2420f10a77bbSDavid C Somayajulu 
2421f10a77bbSDavid C Somayajulu         if (err) {
2422f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2423f10a77bbSDavid C Somayajulu                 return (-1);
2424f10a77bbSDavid C Somayajulu         }
2425f10a77bbSDavid C Somayajulu 
2426f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2427f10a77bbSDavid C Somayajulu 		hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i];
2428f10a77bbSDavid C Somayajulu 	}
2429f10a77bbSDavid C Somayajulu 
2430f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2431f10a77bbSDavid C Somayajulu 		hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std;
2432f10a77bbSDavid C Somayajulu 	}
2433f10a77bbSDavid C Somayajulu 
2434f10a77bbSDavid C Somayajulu 	hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id;
2435f10a77bbSDavid C Somayajulu 
2436f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_rx_cnxt = 1;
2437f10a77bbSDavid C Somayajulu 
2438f10a77bbSDavid C Somayajulu 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) {
243935291c22SDavid C Somayajulu 
244035291c22SDavid C Somayajulu 		for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) {
244135291c22SDavid C Somayajulu 
244235291c22SDavid C Somayajulu 			if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings)
244335291c22SDavid C Somayajulu 				max_idx = MAX_RCNTXT_SDS_RINGS;
244435291c22SDavid C Somayajulu 			else
244535291c22SDavid C Somayajulu 				max_idx = hw->num_sds_rings - i;
244635291c22SDavid C Somayajulu 
244735291c22SDavid C Somayajulu 			err = qla_add_rcv_rings(ha, i, max_idx);
2448f10a77bbSDavid C Somayajulu 			if (err)
2449f10a77bbSDavid C Somayajulu 				return -1;
245035291c22SDavid C Somayajulu 
245135291c22SDavid C Somayajulu 			i += max_idx;
245235291c22SDavid C Somayajulu 		}
2453f10a77bbSDavid C Somayajulu 	}
2454f10a77bbSDavid C Somayajulu 
2455f10a77bbSDavid C Somayajulu 	if (hw->num_rds_rings > 1) {
245635291c22SDavid C Somayajulu 
245735291c22SDavid C Somayajulu 		for (i = 0; i < hw->num_rds_rings; ) {
245835291c22SDavid C Somayajulu 
245935291c22SDavid C Somayajulu 			if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings)
246035291c22SDavid C Somayajulu 				max_idx = MAX_SDS_TO_RDS_MAP;
246135291c22SDavid C Somayajulu 			else
246235291c22SDavid C Somayajulu 				max_idx = hw->num_rds_rings - i;
246335291c22SDavid C Somayajulu 
246435291c22SDavid C Somayajulu 			err = qla_map_sds_to_rds(ha, i, max_idx);
2465f10a77bbSDavid C Somayajulu 			if (err)
2466f10a77bbSDavid C Somayajulu 				return -1;
246735291c22SDavid C Somayajulu 
246835291c22SDavid C Somayajulu 			i += max_idx;
246935291c22SDavid C Somayajulu 		}
2470f10a77bbSDavid C Somayajulu 	}
2471f10a77bbSDavid C Somayajulu 
2472f10a77bbSDavid C Somayajulu 	return (0);
2473f10a77bbSDavid C Somayajulu }
2474f10a77bbSDavid C Somayajulu 
2475f10a77bbSDavid C Somayajulu static int
247635291c22SDavid C Somayajulu qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds)
2477f10a77bbSDavid C Somayajulu {
2478f10a77bbSDavid C Somayajulu 	device_t		dev = ha->pci_dev;
2479f10a77bbSDavid C Somayajulu 	q80_rq_add_rcv_rings_t	*add_rcv;
2480f10a77bbSDavid C Somayajulu 	q80_rsp_add_rcv_rings_t	*add_rcv_rsp;
2481f10a77bbSDavid C Somayajulu 	uint32_t		i,j, err;
2482f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2483f10a77bbSDavid C Somayajulu 
2484f10a77bbSDavid C Somayajulu 	add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox;
2485f10a77bbSDavid C Somayajulu 	bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t));
2486f10a77bbSDavid C Somayajulu 
2487f10a77bbSDavid C Somayajulu 	add_rcv->opcode = Q8_MBX_ADD_RX_RINGS;
2488f10a77bbSDavid C Somayajulu 	add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2);
2489f10a77bbSDavid C Somayajulu 	add_rcv->count_version |= Q8_MBX_CMD_VERSION;
2490f10a77bbSDavid C Somayajulu 
2491f10a77bbSDavid C Somayajulu 	add_rcv->nrds_sets_rings = nsds | (1 << 5);
2492f10a77bbSDavid C Somayajulu 	add_rcv->nsds_rings = nsds;
2493f10a77bbSDavid C Somayajulu 	add_rcv->cntxt_id = hw->rcv_cntxt_id;
2494f10a77bbSDavid C Somayajulu 
2495f10a77bbSDavid C Somayajulu         for (i = 0; i <  nsds; i++) {
2496f10a77bbSDavid C Somayajulu 
2497f10a77bbSDavid C Somayajulu 		j = i + sds_idx;
2498f10a77bbSDavid C Somayajulu 
2499f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].paddr =
2500f10a77bbSDavid C Somayajulu                         qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr);
2501f10a77bbSDavid C Somayajulu 
2502f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].size =
2503f10a77bbSDavid C Somayajulu                         qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2504f10a77bbSDavid C Somayajulu 
2505f10a77bbSDavid C Somayajulu                 if (ha->msix_count == 2) {
2506f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_id =
2507f10a77bbSDavid C Somayajulu                                 qla_host_to_le16(hw->intr_id[0]);
2508f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(j);
2509f10a77bbSDavid C Somayajulu                 } else {
2510f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_id =
2511f10a77bbSDavid C Somayajulu                                 qla_host_to_le16(hw->intr_id[j]);
2512f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0);
2513f10a77bbSDavid C Somayajulu                 }
2514f10a77bbSDavid C Somayajulu 
2515f10a77bbSDavid C Somayajulu         }
251635291c22SDavid C Somayajulu         for (i = 0; (i <  nsds); i++) {
2517f10a77bbSDavid C Somayajulu                 j = i + sds_idx;
251835291c22SDavid C Somayajulu 
2519f10a77bbSDavid C Somayajulu                 add_rcv->rds[i].paddr_std =
2520f10a77bbSDavid C Somayajulu                         qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr);
252135291c22SDavid C Somayajulu 
252235291c22SDavid C Somayajulu 		if (ha->hw.enable_9kb)
252335291c22SDavid C Somayajulu 			add_rcv->rds[i].std_bsize =
252435291c22SDavid C Somayajulu 				qla_host_to_le64(MJUM9BYTES);
252535291c22SDavid C Somayajulu 		else
2526f10a77bbSDavid C Somayajulu                 	add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
252735291c22SDavid C Somayajulu 
2528f10a77bbSDavid C Somayajulu                 add_rcv->rds[i].std_nentries =
2529f10a77bbSDavid C Somayajulu                         qla_host_to_le32(NUM_RX_DESCRIPTORS);
2530f10a77bbSDavid C Somayajulu         }
2531f10a77bbSDavid C Somayajulu 
2532f10a77bbSDavid C Somayajulu 
2533f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)add_rcv,
2534f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_add_rcv_rings_t) >> 2),
2535f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2536f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2537f10a77bbSDavid C Somayajulu                 return (-1);
2538f10a77bbSDavid C Somayajulu         }
2539f10a77bbSDavid C Somayajulu 
2540f10a77bbSDavid C Somayajulu         add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
2541f10a77bbSDavid C Somayajulu 
2542f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status);
2543f10a77bbSDavid C Somayajulu 
2544f10a77bbSDavid C Somayajulu         if (err) {
2545f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2546f10a77bbSDavid C Somayajulu                 return (-1);
2547f10a77bbSDavid C Somayajulu         }
2548f10a77bbSDavid C Somayajulu 
254935291c22SDavid C Somayajulu 	for (i = 0; i < nsds; i++) {
255035291c22SDavid C Somayajulu 		hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i];
2551f10a77bbSDavid C Somayajulu 	}
255235291c22SDavid C Somayajulu 
255335291c22SDavid C Somayajulu 	for (i = 0; i < nsds; i++) {
255435291c22SDavid C Somayajulu 		hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std;
2555f10a77bbSDavid C Somayajulu 	}
255635291c22SDavid C Somayajulu 
2557f10a77bbSDavid C Somayajulu 	return (0);
2558f10a77bbSDavid C Somayajulu }
2559f10a77bbSDavid C Somayajulu 
2560f10a77bbSDavid C Somayajulu /*
2561f10a77bbSDavid C Somayajulu  * Name: qla_del_rcv_cntxt
2562f10a77bbSDavid C Somayajulu  * Function: Destroys the Receive Context.
2563f10a77bbSDavid C Somayajulu  */
2564f10a77bbSDavid C Somayajulu static void
2565f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(qla_host_t *ha)
2566f10a77bbSDavid C Somayajulu {
2567f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
2568f10a77bbSDavid C Somayajulu 	q80_rcv_cntxt_destroy_t		*rcntxt;
2569f10a77bbSDavid C Somayajulu 	q80_rcv_cntxt_destroy_rsp_t	*rcntxt_rsp;
2570f10a77bbSDavid C Somayajulu 	uint32_t			err;
2571f10a77bbSDavid C Somayajulu 	uint8_t				bcast_mac[6];
2572f10a77bbSDavid C Somayajulu 
2573f10a77bbSDavid C Somayajulu 	if (!ha->hw.flags.init_rx_cnxt)
2574f10a77bbSDavid C Somayajulu 		return;
2575f10a77bbSDavid C Somayajulu 
2576f10a77bbSDavid C Somayajulu 	if (qla_hw_del_all_mcast(ha))
2577f10a77bbSDavid C Somayajulu 		return;
2578f10a77bbSDavid C Somayajulu 
2579f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.bcast_mac) {
2580f10a77bbSDavid C Somayajulu 
2581f10a77bbSDavid C Somayajulu 		bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2582f10a77bbSDavid C Somayajulu 		bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2583f10a77bbSDavid C Somayajulu 
2584f10a77bbSDavid C Somayajulu 		if (qla_config_mac_addr(ha, bcast_mac, 0))
2585f10a77bbSDavid C Somayajulu 			return;
2586f10a77bbSDavid C Somayajulu 		ha->hw.flags.bcast_mac = 0;
2587f10a77bbSDavid C Somayajulu 
2588f10a77bbSDavid C Somayajulu 	}
2589f10a77bbSDavid C Somayajulu 
2590f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.unicast_mac) {
2591f10a77bbSDavid C Somayajulu 		if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0))
2592f10a77bbSDavid C Somayajulu 			return;
2593f10a77bbSDavid C Somayajulu 		ha->hw.flags.unicast_mac = 0;
2594f10a77bbSDavid C Somayajulu 	}
2595f10a77bbSDavid C Somayajulu 
2596f10a77bbSDavid C Somayajulu 	rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox;
2597f10a77bbSDavid C Somayajulu 	bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t)));
2598f10a77bbSDavid C Somayajulu 
2599f10a77bbSDavid C Somayajulu 	rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT;
2600f10a77bbSDavid C Somayajulu 	rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2);
2601f10a77bbSDavid C Somayajulu 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2602f10a77bbSDavid C Somayajulu 
2603f10a77bbSDavid C Somayajulu 	rcntxt->cntxt_id = ha->hw.rcv_cntxt_id;
2604f10a77bbSDavid C Somayajulu 
2605f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2606f10a77bbSDavid C Somayajulu 		(sizeof (q80_rcv_cntxt_destroy_t) >> 2),
2607f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) {
2608f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2609f10a77bbSDavid C Somayajulu                 return;
2610f10a77bbSDavid C Somayajulu         }
2611f10a77bbSDavid C Somayajulu         rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox;
2612f10a77bbSDavid C Somayajulu 
2613f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2614f10a77bbSDavid C Somayajulu 
2615f10a77bbSDavid C Somayajulu         if (err) {
2616f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2617f10a77bbSDavid C Somayajulu         }
2618f10a77bbSDavid C Somayajulu 
2619f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_rx_cnxt = 0;
2620f10a77bbSDavid C Somayajulu 	return;
2621f10a77bbSDavid C Somayajulu }
2622f10a77bbSDavid C Somayajulu 
2623f10a77bbSDavid C Somayajulu /*
2624f10a77bbSDavid C Somayajulu  * Name: qla_init_xmt_cntxt
2625f10a77bbSDavid C Somayajulu  * Function: Creates the Transmit Context.
2626f10a77bbSDavid C Somayajulu  */
2627f10a77bbSDavid C Somayajulu static int
2628f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2629f10a77bbSDavid C Somayajulu {
2630f10a77bbSDavid C Somayajulu 	device_t		dev;
2631f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2632f10a77bbSDavid C Somayajulu 	q80_rq_tx_cntxt_t	*tcntxt;
2633f10a77bbSDavid C Somayajulu 	q80_rsp_tx_cntxt_t	*tcntxt_rsp;
2634f10a77bbSDavid C Somayajulu 	uint32_t		err;
2635f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t       *hw_tx_cntxt;
2636f10a77bbSDavid C Somayajulu 
2637f10a77bbSDavid C Somayajulu 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
2638f10a77bbSDavid C Somayajulu 
2639f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2640f10a77bbSDavid C Somayajulu 
2641f10a77bbSDavid C Somayajulu 	/*
2642f10a77bbSDavid C Somayajulu 	 * Create Transmit Context
2643f10a77bbSDavid C Somayajulu 	 */
2644f10a77bbSDavid C Somayajulu 	tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox;
2645f10a77bbSDavid C Somayajulu 	bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t)));
2646f10a77bbSDavid C Somayajulu 
2647f10a77bbSDavid C Somayajulu 	tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT;
2648f10a77bbSDavid C Somayajulu 	tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2);
2649f10a77bbSDavid C Somayajulu 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2650f10a77bbSDavid C Somayajulu 
265135291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV
265235291c22SDavid C Somayajulu 
265335291c22SDavid C Somayajulu 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO |
265435291c22SDavid C Somayajulu 				Q8_TX_CNTXT_CAP0_TC;
265535291c22SDavid C Somayajulu 
265635291c22SDavid C Somayajulu 	if (txr_idx >= (ha->hw.num_tx_rings >> 1)) {
265735291c22SDavid C Somayajulu 		tcntxt->traffic_class = 1;
265835291c22SDavid C Somayajulu 	}
265935291c22SDavid C Somayajulu 
266035291c22SDavid C Somayajulu #else
266135291c22SDavid C Somayajulu 
2662f10a77bbSDavid C Somayajulu 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO;
2663f10a77bbSDavid C Somayajulu 
266435291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
266535291c22SDavid C Somayajulu 
2666f10a77bbSDavid C Somayajulu 	tcntxt->ntx_rings = 1;
2667f10a77bbSDavid C Somayajulu 
2668f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].paddr =
2669f10a77bbSDavid C Somayajulu 		qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr);
2670f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].tx_consumer =
2671f10a77bbSDavid C Somayajulu 		qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr);
2672f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS);
2673f10a77bbSDavid C Somayajulu 
2674f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[0]);
2675f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0);
2676f10a77bbSDavid C Somayajulu 
2677f10a77bbSDavid C Somayajulu 
2678f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS;
2679f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0;
2680f10a77bbSDavid C Somayajulu 
2681f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2682f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_tx_cntxt_t) >> 2),
2683f10a77bbSDavid C Somayajulu                 ha->hw.mbox,
2684f10a77bbSDavid C Somayajulu 		(sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) {
2685f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2686f10a77bbSDavid C Somayajulu                 return (-1);
2687f10a77bbSDavid C Somayajulu         }
2688f10a77bbSDavid C Somayajulu         tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox;
2689f10a77bbSDavid C Somayajulu 
2690f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2691f10a77bbSDavid C Somayajulu 
2692f10a77bbSDavid C Somayajulu         if (err) {
2693f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2694f10a77bbSDavid C Somayajulu 		return -1;
2695f10a77bbSDavid C Somayajulu         }
2696f10a77bbSDavid C Somayajulu 
2697f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index;
2698f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id;
2699f10a77bbSDavid C Somayajulu 
270035291c22SDavid C Somayajulu 	if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0))
270135291c22SDavid C Somayajulu 		return (-1);
270235291c22SDavid C Somayajulu 
2703f10a77bbSDavid C Somayajulu 	return (0);
2704f10a77bbSDavid C Somayajulu }
2705f10a77bbSDavid C Somayajulu 
2706f10a77bbSDavid C Somayajulu 
2707f10a77bbSDavid C Somayajulu /*
2708f10a77bbSDavid C Somayajulu  * Name: qla_del_xmt_cntxt
2709f10a77bbSDavid C Somayajulu  * Function: Destroys the Transmit Context.
2710f10a77bbSDavid C Somayajulu  */
2711f10a77bbSDavid C Somayajulu static int
2712f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2713f10a77bbSDavid C Somayajulu {
2714f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
2715f10a77bbSDavid C Somayajulu 	q80_tx_cntxt_destroy_t		*tcntxt;
2716f10a77bbSDavid C Somayajulu 	q80_tx_cntxt_destroy_rsp_t	*tcntxt_rsp;
2717f10a77bbSDavid C Somayajulu 	uint32_t			err;
2718f10a77bbSDavid C Somayajulu 
2719f10a77bbSDavid C Somayajulu 	tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox;
2720f10a77bbSDavid C Somayajulu 	bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t)));
2721f10a77bbSDavid C Somayajulu 
2722f10a77bbSDavid C Somayajulu 	tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT;
2723f10a77bbSDavid C Somayajulu 	tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2);
2724f10a77bbSDavid C Somayajulu 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2725f10a77bbSDavid C Somayajulu 
2726f10a77bbSDavid C Somayajulu 	tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id;
2727f10a77bbSDavid C Somayajulu 
2728f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2729f10a77bbSDavid C Somayajulu 		(sizeof (q80_tx_cntxt_destroy_t) >> 2),
2730f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) {
2731f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2732f10a77bbSDavid C Somayajulu                 return (-1);
2733f10a77bbSDavid C Somayajulu         }
2734f10a77bbSDavid C Somayajulu         tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox;
2735f10a77bbSDavid C Somayajulu 
2736f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2737f10a77bbSDavid C Somayajulu 
2738f10a77bbSDavid C Somayajulu         if (err) {
2739f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2740f10a77bbSDavid C Somayajulu 		return (-1);
2741f10a77bbSDavid C Somayajulu         }
2742f10a77bbSDavid C Somayajulu 
2743f10a77bbSDavid C Somayajulu 	return (0);
2744f10a77bbSDavid C Somayajulu }
2745f10a77bbSDavid C Somayajulu static void
2746f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt(qla_host_t *ha)
2747f10a77bbSDavid C Somayajulu {
2748f10a77bbSDavid C Somayajulu 	uint32_t i;
2749f10a77bbSDavid C Somayajulu 
2750f10a77bbSDavid C Somayajulu 	if (!ha->hw.flags.init_tx_cnxt)
2751f10a77bbSDavid C Somayajulu 		return;
2752f10a77bbSDavid C Somayajulu 
2753f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2754f10a77bbSDavid C Somayajulu 		if (qla_del_xmt_cntxt_i(ha, i))
2755f10a77bbSDavid C Somayajulu 			break;
2756f10a77bbSDavid C Somayajulu 	}
2757f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_tx_cnxt = 0;
2758f10a77bbSDavid C Somayajulu }
2759f10a77bbSDavid C Somayajulu 
2760f10a77bbSDavid C Somayajulu static int
2761f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt(qla_host_t *ha)
2762f10a77bbSDavid C Somayajulu {
2763f10a77bbSDavid C Somayajulu 	uint32_t i, j;
2764f10a77bbSDavid C Somayajulu 
2765f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2766f10a77bbSDavid C Somayajulu 		if (qla_init_xmt_cntxt_i(ha, i) != 0) {
2767f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
2768f10a77bbSDavid C Somayajulu 				qla_del_xmt_cntxt_i(ha, j);
2769f10a77bbSDavid C Somayajulu 			return (-1);
2770f10a77bbSDavid C Somayajulu 		}
2771f10a77bbSDavid C Somayajulu 	}
2772f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_tx_cnxt = 1;
2773f10a77bbSDavid C Somayajulu 	return (0);
2774f10a77bbSDavid C Somayajulu }
2775f10a77bbSDavid C Somayajulu 
2776f10a77bbSDavid C Somayajulu static int
2777f10a77bbSDavid C Somayajulu qla_hw_add_all_mcast(qla_host_t *ha)
2778f10a77bbSDavid C Somayajulu {
2779f10a77bbSDavid C Somayajulu 	int i, nmcast;
2780f10a77bbSDavid C Somayajulu 
2781f10a77bbSDavid C Somayajulu 	nmcast = ha->hw.nmcast;
2782f10a77bbSDavid C Somayajulu 
2783f10a77bbSDavid C Somayajulu 	for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
2784f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] != 0) ||
2785f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] != 0) ||
2786f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] != 0) ||
2787f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] != 0) ||
2788f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] != 0) ||
2789f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] != 0)) {
2790f10a77bbSDavid C Somayajulu 
2791f10a77bbSDavid C Somayajulu 			if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 1)) {
2792f10a77bbSDavid C Somayajulu                 		device_printf(ha->pci_dev, "%s: failed\n",
2793f10a77bbSDavid C Somayajulu 					__func__);
2794f10a77bbSDavid C Somayajulu 				return (-1);
2795f10a77bbSDavid C Somayajulu 			}
2796f10a77bbSDavid C Somayajulu 
2797f10a77bbSDavid C Somayajulu 			nmcast--;
2798f10a77bbSDavid C Somayajulu 		}
2799f10a77bbSDavid C Somayajulu 	}
2800f10a77bbSDavid C Somayajulu 	return 0;
2801f10a77bbSDavid C Somayajulu }
2802f10a77bbSDavid C Somayajulu 
2803f10a77bbSDavid C Somayajulu static int
2804f10a77bbSDavid C Somayajulu qla_hw_del_all_mcast(qla_host_t *ha)
2805f10a77bbSDavid C Somayajulu {
2806f10a77bbSDavid C Somayajulu 	int i, nmcast;
2807f10a77bbSDavid C Somayajulu 
2808f10a77bbSDavid C Somayajulu 	nmcast = ha->hw.nmcast;
2809f10a77bbSDavid C Somayajulu 
2810f10a77bbSDavid C Somayajulu 	for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
2811f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] != 0) ||
2812f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] != 0) ||
2813f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] != 0) ||
2814f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] != 0) ||
2815f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] != 0) ||
2816f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] != 0)) {
2817f10a77bbSDavid C Somayajulu 
2818f10a77bbSDavid C Somayajulu 			if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 0))
2819f10a77bbSDavid C Somayajulu 				return (-1);
2820f10a77bbSDavid C Somayajulu 
2821f10a77bbSDavid C Somayajulu 			nmcast--;
2822f10a77bbSDavid C Somayajulu 		}
2823f10a77bbSDavid C Somayajulu 	}
2824f10a77bbSDavid C Somayajulu 	return 0;
2825f10a77bbSDavid C Somayajulu }
2826f10a77bbSDavid C Somayajulu 
2827f10a77bbSDavid C Somayajulu static int
2828f10a77bbSDavid C Somayajulu qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta)
2829f10a77bbSDavid C Somayajulu {
2830f10a77bbSDavid C Somayajulu 	int i;
2831f10a77bbSDavid C Somayajulu 
2832f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
2833f10a77bbSDavid C Somayajulu 
2834f10a77bbSDavid C Somayajulu 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0)
2835f10a77bbSDavid C Somayajulu 			return 0; /* its been already added */
2836f10a77bbSDavid C Somayajulu 	}
2837f10a77bbSDavid C Somayajulu 
2838f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
2839f10a77bbSDavid C Somayajulu 
2840f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] == 0) &&
2841f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] == 0) &&
2842f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] == 0) &&
2843f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] == 0) &&
2844f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] == 0) &&
2845f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] == 0)) {
2846f10a77bbSDavid C Somayajulu 
2847f10a77bbSDavid C Somayajulu 			if (qla_config_mac_addr(ha, mta, 1))
2848f10a77bbSDavid C Somayajulu 				return (-1);
2849f10a77bbSDavid C Somayajulu 
2850f10a77bbSDavid C Somayajulu 			bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN);
2851f10a77bbSDavid C Somayajulu 			ha->hw.nmcast++;
2852f10a77bbSDavid C Somayajulu 
2853f10a77bbSDavid C Somayajulu 			return 0;
2854f10a77bbSDavid C Somayajulu 		}
2855f10a77bbSDavid C Somayajulu 	}
2856f10a77bbSDavid C Somayajulu 	return 0;
2857f10a77bbSDavid C Somayajulu }
2858f10a77bbSDavid C Somayajulu 
2859f10a77bbSDavid C Somayajulu static int
2860f10a77bbSDavid C Somayajulu qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta)
2861f10a77bbSDavid C Somayajulu {
2862f10a77bbSDavid C Somayajulu 	int i;
2863f10a77bbSDavid C Somayajulu 
2864f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
2865f10a77bbSDavid C Somayajulu 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) {
2866f10a77bbSDavid C Somayajulu 
2867f10a77bbSDavid C Somayajulu 			if (qla_config_mac_addr(ha, mta, 0))
2868f10a77bbSDavid C Somayajulu 				return (-1);
2869f10a77bbSDavid C Somayajulu 
2870f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[0] = 0;
2871f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[1] = 0;
2872f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[2] = 0;
2873f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[3] = 0;
2874f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[4] = 0;
2875f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[5] = 0;
2876f10a77bbSDavid C Somayajulu 
2877f10a77bbSDavid C Somayajulu 			ha->hw.nmcast--;
2878f10a77bbSDavid C Somayajulu 
2879f10a77bbSDavid C Somayajulu 			return 0;
2880f10a77bbSDavid C Somayajulu 		}
2881f10a77bbSDavid C Somayajulu 	}
2882f10a77bbSDavid C Somayajulu 	return 0;
2883f10a77bbSDavid C Somayajulu }
2884f10a77bbSDavid C Somayajulu 
2885f10a77bbSDavid C Somayajulu /*
2886f10a77bbSDavid C Somayajulu  * Name: ql_hw_set_multi
2887f10a77bbSDavid C Somayajulu  * Function: Sets the Multicast Addresses provided the host O.S into the
2888f10a77bbSDavid C Somayajulu  *	hardware (for the given interface)
2889f10a77bbSDavid C Somayajulu  */
2890f10a77bbSDavid C Somayajulu int
2891f10a77bbSDavid C Somayajulu ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast, uint32_t mcnt,
2892f10a77bbSDavid C Somayajulu 	uint32_t add_mac)
2893f10a77bbSDavid C Somayajulu {
2894f10a77bbSDavid C Somayajulu 	int i;
2895f10a77bbSDavid C Somayajulu 	uint8_t *mta = mcast;
2896f10a77bbSDavid C Somayajulu 	int ret = 0;
2897f10a77bbSDavid C Somayajulu 
2898f10a77bbSDavid C Somayajulu 	for (i = 0; i < mcnt; i++) {
2899f10a77bbSDavid C Somayajulu 		if (add_mac) {
2900f10a77bbSDavid C Somayajulu 			ret = qla_hw_add_mcast(ha, mta);
2901f10a77bbSDavid C Somayajulu 			if (ret)
2902f10a77bbSDavid C Somayajulu 				break;
2903f10a77bbSDavid C Somayajulu 		} else {
2904f10a77bbSDavid C Somayajulu 			ret = qla_hw_del_mcast(ha, mta);
2905f10a77bbSDavid C Somayajulu 			if (ret)
2906f10a77bbSDavid C Somayajulu 				break;
2907f10a77bbSDavid C Somayajulu 		}
2908f10a77bbSDavid C Somayajulu 
2909f10a77bbSDavid C Somayajulu 		mta += Q8_MAC_ADDR_LEN;
2910f10a77bbSDavid C Somayajulu 	}
2911f10a77bbSDavid C Somayajulu 	return (ret);
2912f10a77bbSDavid C Somayajulu }
2913f10a77bbSDavid C Somayajulu 
2914f10a77bbSDavid C Somayajulu /*
2915f10a77bbSDavid C Somayajulu  * Name: qla_hw_tx_done_locked
2916f10a77bbSDavid C Somayajulu  * Function: Handle Transmit Completions
2917f10a77bbSDavid C Somayajulu  */
2918f10a77bbSDavid C Somayajulu static void
2919f10a77bbSDavid C Somayajulu qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx)
2920f10a77bbSDavid C Somayajulu {
2921f10a77bbSDavid C Somayajulu 	qla_tx_buf_t *txb;
2922f10a77bbSDavid C Somayajulu         qla_hw_t *hw = &ha->hw;
2923f10a77bbSDavid C Somayajulu 	uint32_t comp_idx, comp_count = 0;
2924f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t *hw_tx_cntxt;
2925f10a77bbSDavid C Somayajulu 
2926f10a77bbSDavid C Somayajulu 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
2927f10a77bbSDavid C Somayajulu 
2928f10a77bbSDavid C Somayajulu 	/* retrieve index of last entry in tx ring completed */
2929f10a77bbSDavid C Somayajulu 	comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons));
2930f10a77bbSDavid C Somayajulu 
2931f10a77bbSDavid C Somayajulu 	while (comp_idx != hw_tx_cntxt->txr_comp) {
2932f10a77bbSDavid C Somayajulu 
2933f10a77bbSDavid C Somayajulu 		txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp];
2934f10a77bbSDavid C Somayajulu 
2935f10a77bbSDavid C Somayajulu 		hw_tx_cntxt->txr_comp++;
2936f10a77bbSDavid C Somayajulu 		if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS)
2937f10a77bbSDavid C Somayajulu 			hw_tx_cntxt->txr_comp = 0;
2938f10a77bbSDavid C Somayajulu 
2939f10a77bbSDavid C Somayajulu 		comp_count++;
2940f10a77bbSDavid C Somayajulu 
2941f10a77bbSDavid C Somayajulu 		if (txb->m_head) {
2942c8dfaf38SGleb Smirnoff 			if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1);
2943f10a77bbSDavid C Somayajulu 
2944f10a77bbSDavid C Somayajulu 			bus_dmamap_sync(ha->tx_tag, txb->map,
2945f10a77bbSDavid C Somayajulu 				BUS_DMASYNC_POSTWRITE);
2946f10a77bbSDavid C Somayajulu 			bus_dmamap_unload(ha->tx_tag, txb->map);
2947f10a77bbSDavid C Somayajulu 			m_freem(txb->m_head);
2948f10a77bbSDavid C Somayajulu 
2949f10a77bbSDavid C Somayajulu 			txb->m_head = NULL;
2950f10a77bbSDavid C Somayajulu 		}
2951f10a77bbSDavid C Somayajulu 	}
2952f10a77bbSDavid C Somayajulu 
2953f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_free += comp_count;
2954f10a77bbSDavid C Somayajulu 	return;
2955f10a77bbSDavid C Somayajulu }
2956f10a77bbSDavid C Somayajulu 
2957f10a77bbSDavid C Somayajulu /*
2958f10a77bbSDavid C Somayajulu  * Name: ql_hw_tx_done
2959f10a77bbSDavid C Somayajulu  * Function: Handle Transmit Completions
2960f10a77bbSDavid C Somayajulu  */
2961f10a77bbSDavid C Somayajulu void
2962f10a77bbSDavid C Somayajulu ql_hw_tx_done(qla_host_t *ha)
2963f10a77bbSDavid C Somayajulu {
2964f10a77bbSDavid C Somayajulu 	int i;
2965f10a77bbSDavid C Somayajulu 	uint32_t flag = 0;
2966f10a77bbSDavid C Somayajulu 
2967f10a77bbSDavid C Somayajulu 	if (!mtx_trylock(&ha->tx_lock)) {
2968f10a77bbSDavid C Somayajulu        		QL_DPRINT8(ha, (ha->pci_dev,
2969f10a77bbSDavid C Somayajulu 			"%s: !mtx_trylock(&ha->tx_lock)\n", __func__));
2970f10a77bbSDavid C Somayajulu 		return;
2971f10a77bbSDavid C Somayajulu 	}
2972f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2973f10a77bbSDavid C Somayajulu 		qla_hw_tx_done_locked(ha, i);
2974f10a77bbSDavid C Somayajulu 		if (ha->hw.tx_cntxt[i].txr_free <= (NUM_TX_DESCRIPTORS >> 1))
2975f10a77bbSDavid C Somayajulu 			flag = 1;
2976f10a77bbSDavid C Somayajulu 	}
2977f10a77bbSDavid C Somayajulu 
2978f10a77bbSDavid C Somayajulu 	if (!flag)
2979f10a77bbSDavid C Somayajulu 		ha->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2980f10a77bbSDavid C Somayajulu 
2981f10a77bbSDavid C Somayajulu 	QLA_TX_UNLOCK(ha);
2982f10a77bbSDavid C Somayajulu 	return;
2983f10a77bbSDavid C Somayajulu }
2984f10a77bbSDavid C Somayajulu 
2985f10a77bbSDavid C Somayajulu void
2986f10a77bbSDavid C Somayajulu ql_update_link_state(qla_host_t *ha)
2987f10a77bbSDavid C Somayajulu {
2988f10a77bbSDavid C Somayajulu 	uint32_t link_state;
2989f10a77bbSDavid C Somayajulu 	uint32_t prev_link_state;
2990f10a77bbSDavid C Somayajulu 
2991f10a77bbSDavid C Somayajulu 	if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
2992f10a77bbSDavid C Somayajulu 		ha->hw.link_up = 0;
2993f10a77bbSDavid C Somayajulu 		return;
2994f10a77bbSDavid C Somayajulu 	}
2995f10a77bbSDavid C Somayajulu 	link_state = READ_REG32(ha, Q8_LINK_STATE);
2996f10a77bbSDavid C Somayajulu 
2997f10a77bbSDavid C Somayajulu 	prev_link_state =  ha->hw.link_up;
2998f10a77bbSDavid C Somayajulu 
2999f10a77bbSDavid C Somayajulu 	if (ha->pci_func == 0)
3000f10a77bbSDavid C Somayajulu 		ha->hw.link_up = (((link_state & 0xF) == 1)? 1 : 0);
3001f10a77bbSDavid C Somayajulu 	else
3002f10a77bbSDavid C Somayajulu 		ha->hw.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
3003f10a77bbSDavid C Somayajulu 
3004f10a77bbSDavid C Somayajulu 	if (prev_link_state !=  ha->hw.link_up) {
3005f10a77bbSDavid C Somayajulu 		if (ha->hw.link_up) {
3006f10a77bbSDavid C Somayajulu 			if_link_state_change(ha->ifp, LINK_STATE_UP);
3007f10a77bbSDavid C Somayajulu 		} else {
3008f10a77bbSDavid C Somayajulu 			if_link_state_change(ha->ifp, LINK_STATE_DOWN);
3009f10a77bbSDavid C Somayajulu 		}
3010f10a77bbSDavid C Somayajulu 	}
3011f10a77bbSDavid C Somayajulu 	return;
3012f10a77bbSDavid C Somayajulu }
3013f10a77bbSDavid C Somayajulu 
3014f10a77bbSDavid C Somayajulu void
3015f10a77bbSDavid C Somayajulu ql_hw_stop_rcv(qla_host_t *ha)
3016f10a77bbSDavid C Somayajulu {
3017f10a77bbSDavid C Somayajulu 	int i, done, count = 100;
3018f10a77bbSDavid C Somayajulu 
301935291c22SDavid C Somayajulu 	while (count) {
3020f10a77bbSDavid C Somayajulu 		done = 1;
3021f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
3022f10a77bbSDavid C Somayajulu 			if (ha->hw.sds[i].rcv_active)
3023f10a77bbSDavid C Somayajulu 				done = 0;
3024f10a77bbSDavid C Somayajulu 		}
3025f10a77bbSDavid C Somayajulu 		if (done)
3026f10a77bbSDavid C Somayajulu 			break;
3027f10a77bbSDavid C Somayajulu 		else
3028f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 10);
302935291c22SDavid C Somayajulu 		count--;
3030f10a77bbSDavid C Somayajulu 	}
3031f10a77bbSDavid C Somayajulu 	if (!count)
3032f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Counter expired.\n", __func__);
3033f10a77bbSDavid C Somayajulu 
3034f10a77bbSDavid C Somayajulu 	return;
3035f10a77bbSDavid C Somayajulu }
3036f10a77bbSDavid C Somayajulu 
3037f10a77bbSDavid C Somayajulu int
3038f10a77bbSDavid C Somayajulu ql_hw_check_health(qla_host_t *ha)
3039f10a77bbSDavid C Somayajulu {
3040f10a77bbSDavid C Somayajulu 	uint32_t val;
3041f10a77bbSDavid C Somayajulu 
3042f10a77bbSDavid C Somayajulu 	ha->hw.health_count++;
3043f10a77bbSDavid C Somayajulu 
3044f10a77bbSDavid C Somayajulu 	if (ha->hw.health_count < 1000)
3045f10a77bbSDavid C Somayajulu 		return 0;
3046f10a77bbSDavid C Somayajulu 
3047f10a77bbSDavid C Somayajulu 	ha->hw.health_count = 0;
3048f10a77bbSDavid C Somayajulu 
3049f10a77bbSDavid C Somayajulu 	val = READ_REG32(ha, Q8_ASIC_TEMPERATURE);
3050f10a77bbSDavid C Somayajulu 
3051f10a77bbSDavid C Somayajulu 	if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) ||
3052f10a77bbSDavid C Somayajulu 		(QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) {
3053f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Temperature Alert [0x%08x]\n",
3054f10a77bbSDavid C Somayajulu 			__func__, val);
3055f10a77bbSDavid C Somayajulu 		return -1;
3056f10a77bbSDavid C Somayajulu 	}
3057f10a77bbSDavid C Somayajulu 
3058f10a77bbSDavid C Somayajulu 	val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
3059f10a77bbSDavid C Somayajulu 
3060f10a77bbSDavid C Somayajulu 	if ((val != ha->hw.hbeat_value) &&
3061467dcb5aSDavid C Somayajulu 		(!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) {
3062f10a77bbSDavid C Somayajulu 		ha->hw.hbeat_value = val;
3063f10a77bbSDavid C Somayajulu 		return 0;
3064f10a77bbSDavid C Somayajulu 	}
3065f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: Heartbeat Failue [0x%08x]\n",
3066f10a77bbSDavid C Somayajulu 		__func__, val);
3067f10a77bbSDavid C Somayajulu 
3068f10a77bbSDavid C Somayajulu 	return -1;
3069f10a77bbSDavid C Somayajulu }
3070f10a77bbSDavid C Somayajulu 
3071f10a77bbSDavid C Somayajulu static int
307235291c22SDavid C Somayajulu qla_init_nic_func(qla_host_t *ha)
307335291c22SDavid C Somayajulu {
307435291c22SDavid C Somayajulu         device_t                dev;
307535291c22SDavid C Somayajulu         q80_init_nic_func_t     *init_nic;
307635291c22SDavid C Somayajulu         q80_init_nic_func_rsp_t *init_nic_rsp;
307735291c22SDavid C Somayajulu         uint32_t                err;
307835291c22SDavid C Somayajulu 
307935291c22SDavid C Somayajulu         dev = ha->pci_dev;
308035291c22SDavid C Somayajulu 
308135291c22SDavid C Somayajulu         init_nic = (q80_init_nic_func_t *)ha->hw.mbox;
308235291c22SDavid C Somayajulu         bzero(init_nic, sizeof(q80_init_nic_func_t));
308335291c22SDavid C Somayajulu 
308435291c22SDavid C Somayajulu         init_nic->opcode = Q8_MBX_INIT_NIC_FUNC;
308535291c22SDavid C Somayajulu         init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2);
308635291c22SDavid C Somayajulu         init_nic->count_version |= Q8_MBX_CMD_VERSION;
308735291c22SDavid C Somayajulu 
308835291c22SDavid C Somayajulu         init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN;
308935291c22SDavid C Somayajulu         init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN;
309035291c22SDavid C Somayajulu         init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN;
309135291c22SDavid C Somayajulu 
309235291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t));
309335291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)init_nic,
309435291c22SDavid C Somayajulu                 (sizeof (q80_init_nic_func_t) >> 2),
309535291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) {
309635291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
309735291c22SDavid C Somayajulu                 return -1;
309835291c22SDavid C Somayajulu         }
309935291c22SDavid C Somayajulu 
310035291c22SDavid C Somayajulu         init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox;
310135291c22SDavid C Somayajulu // qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t));
310235291c22SDavid C Somayajulu 
310335291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status);
310435291c22SDavid C Somayajulu 
310535291c22SDavid C Somayajulu         if (err) {
310635291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
310735291c22SDavid C Somayajulu         }
310835291c22SDavid C Somayajulu 
310935291c22SDavid C Somayajulu         return 0;
311035291c22SDavid C Somayajulu }
311135291c22SDavid C Somayajulu 
311235291c22SDavid C Somayajulu static int
311335291c22SDavid C Somayajulu qla_stop_nic_func(qla_host_t *ha)
311435291c22SDavid C Somayajulu {
311535291c22SDavid C Somayajulu         device_t                dev;
311635291c22SDavid C Somayajulu         q80_stop_nic_func_t     *stop_nic;
311735291c22SDavid C Somayajulu         q80_stop_nic_func_rsp_t *stop_nic_rsp;
311835291c22SDavid C Somayajulu         uint32_t                err;
311935291c22SDavid C Somayajulu 
312035291c22SDavid C Somayajulu         dev = ha->pci_dev;
312135291c22SDavid C Somayajulu 
312235291c22SDavid C Somayajulu         stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox;
312335291c22SDavid C Somayajulu         bzero(stop_nic, sizeof(q80_stop_nic_func_t));
312435291c22SDavid C Somayajulu 
312535291c22SDavid C Somayajulu         stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC;
312635291c22SDavid C Somayajulu         stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2);
312735291c22SDavid C Somayajulu         stop_nic->count_version |= Q8_MBX_CMD_VERSION;
312835291c22SDavid C Somayajulu 
312935291c22SDavid C Somayajulu         stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN;
313035291c22SDavid C Somayajulu         stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN;
313135291c22SDavid C Somayajulu 
313235291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t));
313335291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)stop_nic,
313435291c22SDavid C Somayajulu                 (sizeof (q80_stop_nic_func_t) >> 2),
313535291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) {
313635291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
313735291c22SDavid C Somayajulu                 return -1;
313835291c22SDavid C Somayajulu         }
313935291c22SDavid C Somayajulu 
314035291c22SDavid C Somayajulu         stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox;
314135291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t));
314235291c22SDavid C Somayajulu 
314335291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status);
314435291c22SDavid C Somayajulu 
314535291c22SDavid C Somayajulu         if (err) {
314635291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
314735291c22SDavid C Somayajulu         }
314835291c22SDavid C Somayajulu 
314935291c22SDavid C Somayajulu         return 0;
315035291c22SDavid C Somayajulu }
315135291c22SDavid C Somayajulu 
315235291c22SDavid C Somayajulu static int
315335291c22SDavid C Somayajulu qla_query_fw_dcbx_caps(qla_host_t *ha)
315435291c22SDavid C Somayajulu {
315535291c22SDavid C Somayajulu         device_t                        dev;
315635291c22SDavid C Somayajulu         q80_query_fw_dcbx_caps_t        *fw_dcbx;
315735291c22SDavid C Somayajulu         q80_query_fw_dcbx_caps_rsp_t    *fw_dcbx_rsp;
315835291c22SDavid C Somayajulu         uint32_t                        err;
315935291c22SDavid C Somayajulu 
316035291c22SDavid C Somayajulu         dev = ha->pci_dev;
316135291c22SDavid C Somayajulu 
316235291c22SDavid C Somayajulu         fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox;
316335291c22SDavid C Somayajulu         bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t));
316435291c22SDavid C Somayajulu 
316535291c22SDavid C Somayajulu         fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS;
316635291c22SDavid C Somayajulu         fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2);
316735291c22SDavid C Somayajulu         fw_dcbx->count_version |= Q8_MBX_CMD_VERSION;
316835291c22SDavid C Somayajulu 
316935291c22SDavid C Somayajulu         ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t));
317035291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx,
317135291c22SDavid C Somayajulu                 (sizeof (q80_query_fw_dcbx_caps_t) >> 2),
317235291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) {
317335291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
317435291c22SDavid C Somayajulu                 return -1;
317535291c22SDavid C Somayajulu         }
317635291c22SDavid C Somayajulu 
317735291c22SDavid C Somayajulu         fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox;
317835291c22SDavid C Somayajulu         ql_dump_buf8(ha, __func__, fw_dcbx_rsp,
317935291c22SDavid C Somayajulu                 sizeof (q80_query_fw_dcbx_caps_rsp_t));
318035291c22SDavid C Somayajulu 
318135291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status);
318235291c22SDavid C Somayajulu 
318335291c22SDavid C Somayajulu         if (err) {
318435291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
318535291c22SDavid C Somayajulu         }
318635291c22SDavid C Somayajulu 
318735291c22SDavid C Somayajulu         return 0;
318835291c22SDavid C Somayajulu }
318935291c22SDavid C Somayajulu 
319035291c22SDavid C Somayajulu static int
319135291c22SDavid C Somayajulu qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2,
319235291c22SDavid C Somayajulu         uint32_t aen_mb3, uint32_t aen_mb4)
319335291c22SDavid C Somayajulu {
319435291c22SDavid C Somayajulu         device_t                dev;
319535291c22SDavid C Somayajulu         q80_idc_ack_t           *idc_ack;
319635291c22SDavid C Somayajulu         q80_idc_ack_rsp_t       *idc_ack_rsp;
319735291c22SDavid C Somayajulu         uint32_t                err;
319835291c22SDavid C Somayajulu         int                     count = 300;
319935291c22SDavid C Somayajulu 
320035291c22SDavid C Somayajulu         dev = ha->pci_dev;
320135291c22SDavid C Somayajulu 
320235291c22SDavid C Somayajulu         idc_ack = (q80_idc_ack_t *)ha->hw.mbox;
320335291c22SDavid C Somayajulu         bzero(idc_ack, sizeof(q80_idc_ack_t));
320435291c22SDavid C Somayajulu 
320535291c22SDavid C Somayajulu         idc_ack->opcode = Q8_MBX_IDC_ACK;
320635291c22SDavid C Somayajulu         idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2);
320735291c22SDavid C Somayajulu         idc_ack->count_version |= Q8_MBX_CMD_VERSION;
320835291c22SDavid C Somayajulu 
320935291c22SDavid C Somayajulu         idc_ack->aen_mb1 = aen_mb1;
321035291c22SDavid C Somayajulu         idc_ack->aen_mb2 = aen_mb2;
321135291c22SDavid C Somayajulu         idc_ack->aen_mb3 = aen_mb3;
321235291c22SDavid C Somayajulu         idc_ack->aen_mb4 = aen_mb4;
321335291c22SDavid C Somayajulu 
321435291c22SDavid C Somayajulu         ha->hw.imd_compl= 0;
321535291c22SDavid C Somayajulu 
321635291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)idc_ack,
321735291c22SDavid C Somayajulu                 (sizeof (q80_idc_ack_t) >> 2),
321835291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) {
321935291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
322035291c22SDavid C Somayajulu                 return -1;
322135291c22SDavid C Somayajulu         }
322235291c22SDavid C Somayajulu 
322335291c22SDavid C Somayajulu         idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox;
322435291c22SDavid C Somayajulu 
322535291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status);
322635291c22SDavid C Somayajulu 
322735291c22SDavid C Somayajulu         if (err) {
322835291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
322935291c22SDavid C Somayajulu                 return(-1);
323035291c22SDavid C Somayajulu         }
323135291c22SDavid C Somayajulu 
323235291c22SDavid C Somayajulu         while (count && !ha->hw.imd_compl) {
323335291c22SDavid C Somayajulu                 qla_mdelay(__func__, 100);
323435291c22SDavid C Somayajulu                 count--;
323535291c22SDavid C Somayajulu         }
323635291c22SDavid C Somayajulu 
323735291c22SDavid C Somayajulu         if (!count)
323835291c22SDavid C Somayajulu                 return -1;
323935291c22SDavid C Somayajulu         else
324035291c22SDavid C Somayajulu                 device_printf(dev, "%s: count %d\n", __func__, count);
324135291c22SDavid C Somayajulu 
324235291c22SDavid C Somayajulu         return (0);
324335291c22SDavid C Somayajulu }
324435291c22SDavid C Somayajulu 
324535291c22SDavid C Somayajulu static int
324635291c22SDavid C Somayajulu qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits)
324735291c22SDavid C Somayajulu {
324835291c22SDavid C Somayajulu         device_t                dev;
324935291c22SDavid C Somayajulu         q80_set_port_cfg_t      *pcfg;
325035291c22SDavid C Somayajulu         q80_set_port_cfg_rsp_t  *pfg_rsp;
325135291c22SDavid C Somayajulu         uint32_t                err;
325235291c22SDavid C Somayajulu         int                     count = 300;
325335291c22SDavid C Somayajulu 
325435291c22SDavid C Somayajulu         dev = ha->pci_dev;
325535291c22SDavid C Somayajulu 
325635291c22SDavid C Somayajulu         pcfg = (q80_set_port_cfg_t *)ha->hw.mbox;
325735291c22SDavid C Somayajulu         bzero(pcfg, sizeof(q80_set_port_cfg_t));
325835291c22SDavid C Somayajulu 
325935291c22SDavid C Somayajulu         pcfg->opcode = Q8_MBX_SET_PORT_CONFIG;
326035291c22SDavid C Somayajulu         pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2);
326135291c22SDavid C Somayajulu         pcfg->count_version |= Q8_MBX_CMD_VERSION;
326235291c22SDavid C Somayajulu 
326335291c22SDavid C Somayajulu         pcfg->cfg_bits = cfg_bits;
326435291c22SDavid C Somayajulu 
326535291c22SDavid C Somayajulu         device_printf(dev, "%s: cfg_bits"
326635291c22SDavid C Somayajulu                 " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
326735291c22SDavid C Somayajulu                 " [0x%x, 0x%x, 0x%x]\n", __func__,
326835291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
326935291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
327035291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0));
327135291c22SDavid C Somayajulu 
327235291c22SDavid C Somayajulu         ha->hw.imd_compl= 0;
327335291c22SDavid C Somayajulu 
327435291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
327535291c22SDavid C Somayajulu                 (sizeof (q80_set_port_cfg_t) >> 2),
327635291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) {
327735291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
327835291c22SDavid C Somayajulu                 return -1;
327935291c22SDavid C Somayajulu         }
328035291c22SDavid C Somayajulu 
328135291c22SDavid C Somayajulu         pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox;
328235291c22SDavid C Somayajulu 
328335291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status);
328435291c22SDavid C Somayajulu 
328535291c22SDavid C Somayajulu         if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) {
328635291c22SDavid C Somayajulu                 while (count && !ha->hw.imd_compl) {
328735291c22SDavid C Somayajulu                         qla_mdelay(__func__, 100);
328835291c22SDavid C Somayajulu                         count--;
328935291c22SDavid C Somayajulu                 }
329035291c22SDavid C Somayajulu                 if (count) {
329135291c22SDavid C Somayajulu                         device_printf(dev, "%s: count %d\n", __func__, count);
329235291c22SDavid C Somayajulu 
329335291c22SDavid C Somayajulu                         err = 0;
329435291c22SDavid C Somayajulu                 }
329535291c22SDavid C Somayajulu         }
329635291c22SDavid C Somayajulu 
329735291c22SDavid C Somayajulu         if (err) {
329835291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
329935291c22SDavid C Somayajulu                 return(-1);
330035291c22SDavid C Somayajulu         }
330135291c22SDavid C Somayajulu 
330235291c22SDavid C Somayajulu         return (0);
330335291c22SDavid C Somayajulu }
330435291c22SDavid C Somayajulu 
330535291c22SDavid C Somayajulu 
330635291c22SDavid C Somayajulu static int
3307f10a77bbSDavid C Somayajulu qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size)
3308f10a77bbSDavid C Somayajulu {
3309f10a77bbSDavid C Somayajulu 	uint32_t			err;
3310f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
3311f10a77bbSDavid C Somayajulu 	q80_config_md_templ_size_t	*md_size;
3312f10a77bbSDavid C Somayajulu 	q80_config_md_templ_size_rsp_t	*md_size_rsp;
3313f10a77bbSDavid C Somayajulu 
331435291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
331535291c22SDavid C Somayajulu 
331635291c22SDavid C Somayajulu 	*size = ql83xx_minidump_len;
331735291c22SDavid C Somayajulu 	return (0);
331835291c22SDavid C Somayajulu 
331935291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
332035291c22SDavid C Somayajulu 
3321f10a77bbSDavid C Somayajulu 	md_size = (q80_config_md_templ_size_t *) ha->hw.mbox;
3322f10a77bbSDavid C Somayajulu 	bzero(md_size, sizeof(q80_config_md_templ_size_t));
3323f10a77bbSDavid C Somayajulu 
3324f10a77bbSDavid C Somayajulu 	md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE;
3325f10a77bbSDavid C Somayajulu 	md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2);
3326f10a77bbSDavid C Somayajulu 	md_size->count_version |= Q8_MBX_CMD_VERSION;
3327f10a77bbSDavid C Somayajulu 
3328f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *) md_size,
3329f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox,
3330f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) {
3331f10a77bbSDavid C Somayajulu 
3332f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
3333f10a77bbSDavid C Somayajulu 
3334f10a77bbSDavid C Somayajulu 		return (-1);
3335f10a77bbSDavid C Somayajulu 	}
3336f10a77bbSDavid C Somayajulu 
3337f10a77bbSDavid C Somayajulu 	md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox;
3338f10a77bbSDavid C Somayajulu 
3339f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status);
3340f10a77bbSDavid C Somayajulu 
3341f10a77bbSDavid C Somayajulu         if (err) {
3342f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3343f10a77bbSDavid C Somayajulu 		return(-1);
3344f10a77bbSDavid C Somayajulu         }
3345f10a77bbSDavid C Somayajulu 
3346f10a77bbSDavid C Somayajulu 	*size = md_size_rsp->templ_size;
3347f10a77bbSDavid C Somayajulu 
3348f10a77bbSDavid C Somayajulu 	return (0);
3349f10a77bbSDavid C Somayajulu }
3350f10a77bbSDavid C Somayajulu 
3351f10a77bbSDavid C Somayajulu static int
335235291c22SDavid C Somayajulu qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits)
335335291c22SDavid C Somayajulu {
335435291c22SDavid C Somayajulu         device_t                dev;
335535291c22SDavid C Somayajulu         q80_get_port_cfg_t      *pcfg;
335635291c22SDavid C Somayajulu         q80_get_port_cfg_rsp_t  *pcfg_rsp;
335735291c22SDavid C Somayajulu         uint32_t                err;
335835291c22SDavid C Somayajulu 
335935291c22SDavid C Somayajulu         dev = ha->pci_dev;
336035291c22SDavid C Somayajulu 
336135291c22SDavid C Somayajulu         pcfg = (q80_get_port_cfg_t *)ha->hw.mbox;
336235291c22SDavid C Somayajulu         bzero(pcfg, sizeof(q80_get_port_cfg_t));
336335291c22SDavid C Somayajulu 
336435291c22SDavid C Somayajulu         pcfg->opcode = Q8_MBX_GET_PORT_CONFIG;
336535291c22SDavid C Somayajulu         pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2);
336635291c22SDavid C Somayajulu         pcfg->count_version |= Q8_MBX_CMD_VERSION;
336735291c22SDavid C Somayajulu 
336835291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
336935291c22SDavid C Somayajulu                 (sizeof (q80_get_port_cfg_t) >> 2),
337035291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) {
337135291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
337235291c22SDavid C Somayajulu                 return -1;
337335291c22SDavid C Somayajulu         }
337435291c22SDavid C Somayajulu 
337535291c22SDavid C Somayajulu         pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox;
337635291c22SDavid C Somayajulu 
337735291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status);
337835291c22SDavid C Somayajulu 
337935291c22SDavid C Somayajulu         if (err) {
338035291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
338135291c22SDavid C Somayajulu                 return(-1);
338235291c22SDavid C Somayajulu         }
338335291c22SDavid C Somayajulu 
338435291c22SDavid C Somayajulu         device_printf(dev, "%s: [cfg_bits, port type]"
338535291c22SDavid C Somayajulu                 " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
338635291c22SDavid C Somayajulu                 " [0x%x, 0x%x, 0x%x]\n", __func__,
338735291c22SDavid C Somayajulu                 pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type,
338835291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
338935291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
339035291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)
339135291c22SDavid C Somayajulu                 );
339235291c22SDavid C Somayajulu 
339335291c22SDavid C Somayajulu         *cfg_bits = pcfg_rsp->cfg_bits;
339435291c22SDavid C Somayajulu 
339535291c22SDavid C Somayajulu         return (0);
339635291c22SDavid C Somayajulu }
339735291c22SDavid C Somayajulu 
339835291c22SDavid C Somayajulu int
339935291c22SDavid C Somayajulu qla_iscsi_pdu(qla_host_t *ha, struct mbuf *mp)
340035291c22SDavid C Somayajulu {
340135291c22SDavid C Somayajulu         struct ether_vlan_header        *eh;
340235291c22SDavid C Somayajulu         uint16_t                        etype;
340335291c22SDavid C Somayajulu         struct ip                       *ip = NULL;
340435291c22SDavid C Somayajulu         struct ip6_hdr                  *ip6 = NULL;
340535291c22SDavid C Somayajulu         struct tcphdr                   *th = NULL;
340635291c22SDavid C Somayajulu         uint32_t                        hdrlen;
340735291c22SDavid C Somayajulu         uint32_t                        offset;
340835291c22SDavid C Somayajulu         uint8_t                         buf[sizeof(struct ip6_hdr)];
340935291c22SDavid C Somayajulu 
341035291c22SDavid C Somayajulu         eh = mtod(mp, struct ether_vlan_header *);
341135291c22SDavid C Somayajulu 
341235291c22SDavid C Somayajulu         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
341335291c22SDavid C Somayajulu                 hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
341435291c22SDavid C Somayajulu                 etype = ntohs(eh->evl_proto);
341535291c22SDavid C Somayajulu         } else {
341635291c22SDavid C Somayajulu                 hdrlen = ETHER_HDR_LEN;
341735291c22SDavid C Somayajulu                 etype = ntohs(eh->evl_encap_proto);
341835291c22SDavid C Somayajulu         }
341935291c22SDavid C Somayajulu 
342035291c22SDavid C Somayajulu 	if (etype == ETHERTYPE_IP) {
342135291c22SDavid C Somayajulu 
342235291c22SDavid C Somayajulu 		offset = (hdrlen + sizeof (struct ip));
342335291c22SDavid C Somayajulu 
342435291c22SDavid C Somayajulu 		if (mp->m_len >= offset) {
342535291c22SDavid C Somayajulu                         ip = (struct ip *)(mp->m_data + hdrlen);
342635291c22SDavid C Somayajulu 		} else {
342735291c22SDavid C Somayajulu 			m_copydata(mp, hdrlen, sizeof (struct ip), buf);
342835291c22SDavid C Somayajulu                         ip = (struct ip *)buf;
342935291c22SDavid C Somayajulu 		}
343035291c22SDavid C Somayajulu 
343135291c22SDavid C Somayajulu                 if (ip->ip_p == IPPROTO_TCP) {
343235291c22SDavid C Somayajulu 
343335291c22SDavid C Somayajulu 			hdrlen += ip->ip_hl << 2;
343435291c22SDavid C Somayajulu 			offset = hdrlen + 4;
343535291c22SDavid C Somayajulu 
343635291c22SDavid C Somayajulu 			if (mp->m_len >= offset) {
343774b8d63dSPedro F. Giffuni 				th = (struct tcphdr *)(mp->m_data + hdrlen);
343835291c22SDavid C Somayajulu 			} else {
343935291c22SDavid C Somayajulu                                 m_copydata(mp, hdrlen, 4, buf);
344035291c22SDavid C Somayajulu 				th = (struct tcphdr *)buf;
344135291c22SDavid C Somayajulu 			}
344235291c22SDavid C Somayajulu                 }
344335291c22SDavid C Somayajulu 
344435291c22SDavid C Somayajulu 	} else if (etype == ETHERTYPE_IPV6) {
344535291c22SDavid C Somayajulu 
344635291c22SDavid C Somayajulu 		offset = (hdrlen + sizeof (struct ip6_hdr));
344735291c22SDavid C Somayajulu 
344835291c22SDavid C Somayajulu 		if (mp->m_len >= offset) {
344935291c22SDavid C Somayajulu                         ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen);
345035291c22SDavid C Somayajulu 		} else {
345135291c22SDavid C Somayajulu                         m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf);
345235291c22SDavid C Somayajulu                         ip6 = (struct ip6_hdr *)buf;
345335291c22SDavid C Somayajulu 		}
345435291c22SDavid C Somayajulu 
345535291c22SDavid C Somayajulu                 if (ip6->ip6_nxt == IPPROTO_TCP) {
345635291c22SDavid C Somayajulu 
345735291c22SDavid C Somayajulu 			hdrlen += sizeof(struct ip6_hdr);
345835291c22SDavid C Somayajulu 			offset = hdrlen + 4;
345935291c22SDavid C Somayajulu 
346035291c22SDavid C Somayajulu 			if (mp->m_len >= offset) {
346174b8d63dSPedro F. Giffuni 				th = (struct tcphdr *)(mp->m_data + hdrlen);
346235291c22SDavid C Somayajulu 			} else {
346335291c22SDavid C Somayajulu 				m_copydata(mp, hdrlen, 4, buf);
346435291c22SDavid C Somayajulu 				th = (struct tcphdr *)buf;
346535291c22SDavid C Somayajulu 			}
346635291c22SDavid C Somayajulu                 }
346735291c22SDavid C Somayajulu 	}
346835291c22SDavid C Somayajulu 
346935291c22SDavid C Somayajulu         if (th != NULL) {
347035291c22SDavid C Somayajulu                 if ((th->th_sport == htons(3260)) ||
347135291c22SDavid C Somayajulu                         (th->th_dport == htons(3260)))
347235291c22SDavid C Somayajulu                         return 0;
347335291c22SDavid C Somayajulu         }
347435291c22SDavid C Somayajulu         return (-1);
347535291c22SDavid C Somayajulu }
347635291c22SDavid C Somayajulu 
347735291c22SDavid C Somayajulu void
347835291c22SDavid C Somayajulu qla_hw_async_event(qla_host_t *ha)
347935291c22SDavid C Somayajulu {
348035291c22SDavid C Somayajulu         switch (ha->hw.aen_mb0) {
348135291c22SDavid C Somayajulu         case 0x8101:
348235291c22SDavid C Somayajulu                 (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2,
348335291c22SDavid C Somayajulu                         ha->hw.aen_mb3, ha->hw.aen_mb4);
348435291c22SDavid C Somayajulu 
348535291c22SDavid C Somayajulu                 break;
348635291c22SDavid C Somayajulu 
348735291c22SDavid C Somayajulu         default:
348835291c22SDavid C Somayajulu                 break;
348935291c22SDavid C Somayajulu         }
349035291c22SDavid C Somayajulu 
349135291c22SDavid C Somayajulu         return;
349235291c22SDavid C Somayajulu }
349335291c22SDavid C Somayajulu 
349435291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
349535291c22SDavid C Somayajulu static int
3496f10a77bbSDavid C Somayajulu qla_get_minidump_template(qla_host_t *ha)
3497f10a77bbSDavid C Somayajulu {
3498f10a77bbSDavid C Somayajulu 	uint32_t			err;
3499f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
3500f10a77bbSDavid C Somayajulu 	q80_config_md_templ_cmd_t	*md_templ;
3501f10a77bbSDavid C Somayajulu 	q80_config_md_templ_cmd_rsp_t	*md_templ_rsp;
3502f10a77bbSDavid C Somayajulu 
3503f10a77bbSDavid C Somayajulu 	md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox;
3504f10a77bbSDavid C Somayajulu 	bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t)));
3505f10a77bbSDavid C Somayajulu 
3506f10a77bbSDavid C Somayajulu 	md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT;
3507f10a77bbSDavid C Somayajulu 	md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2);
3508f10a77bbSDavid C Somayajulu 	md_templ->count_version |= Q8_MBX_CMD_VERSION;
3509f10a77bbSDavid C Somayajulu 
3510f10a77bbSDavid C Somayajulu 	md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr;
3511f10a77bbSDavid C Somayajulu 	md_templ->buff_size = ha->hw.dma_buf.minidump.size;
3512f10a77bbSDavid C Somayajulu 
3513f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *) md_templ,
3514f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_cmd_t) >> 2),
3515f10a77bbSDavid C Somayajulu 		 ha->hw.mbox,
3516f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) {
3517f10a77bbSDavid C Somayajulu 
3518f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
3519f10a77bbSDavid C Somayajulu 
3520f10a77bbSDavid C Somayajulu 		return (-1);
3521f10a77bbSDavid C Somayajulu 	}
3522f10a77bbSDavid C Somayajulu 
3523f10a77bbSDavid C Somayajulu 	md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox;
3524f10a77bbSDavid C Somayajulu 
3525f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status);
3526f10a77bbSDavid C Somayajulu 
3527f10a77bbSDavid C Somayajulu 	if (err) {
3528f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3529f10a77bbSDavid C Somayajulu 		return (-1);
3530f10a77bbSDavid C Somayajulu 	}
3531f10a77bbSDavid C Somayajulu 
3532f10a77bbSDavid C Somayajulu 	return (0);
3533f10a77bbSDavid C Somayajulu 
3534f10a77bbSDavid C Somayajulu }
353535291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
3536f10a77bbSDavid C Somayajulu 
3537f10a77bbSDavid C Somayajulu static int
3538f10a77bbSDavid C Somayajulu qla_minidump_init(qla_host_t *ha)
3539f10a77bbSDavid C Somayajulu {
354035291c22SDavid C Somayajulu 	int		ret = 0;
3541f10a77bbSDavid C Somayajulu 	uint32_t	template_size = 0;
3542f10a77bbSDavid C Somayajulu 	device_t	dev = ha->pci_dev;
3543f10a77bbSDavid C Somayajulu 
3544f10a77bbSDavid C Somayajulu 	/*
3545f10a77bbSDavid C Somayajulu 	 * Get Minidump Template Size
3546f10a77bbSDavid C Somayajulu  	 */
3547f10a77bbSDavid C Somayajulu 	ret = qla_get_minidump_tmplt_size(ha, &template_size);
3548f10a77bbSDavid C Somayajulu 
3549f10a77bbSDavid C Somayajulu 	if (ret || (template_size == 0)) {
3550f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret,
3551f10a77bbSDavid C Somayajulu 			template_size);
3552f10a77bbSDavid C Somayajulu 		return (-1);
3553f10a77bbSDavid C Somayajulu 	}
3554f10a77bbSDavid C Somayajulu 
3555f10a77bbSDavid C Somayajulu 	/*
3556f10a77bbSDavid C Somayajulu 	 * Allocate Memory for Minidump Template
3557f10a77bbSDavid C Somayajulu 	 */
3558f10a77bbSDavid C Somayajulu 
3559f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.minidump.alignment = 8;
3560f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.minidump.size = template_size;
3561f10a77bbSDavid C Somayajulu 
356235291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
3563f10a77bbSDavid C Somayajulu 	if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) {
3564f10a77bbSDavid C Somayajulu 
3565f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: minidump dma alloc failed\n", __func__);
3566f10a77bbSDavid C Somayajulu 
3567f10a77bbSDavid C Somayajulu 		return (-1);
3568f10a77bbSDavid C Somayajulu 	}
3569f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.flags.minidump = 1;
3570f10a77bbSDavid C Somayajulu 
3571f10a77bbSDavid C Somayajulu 	/*
3572f10a77bbSDavid C Somayajulu 	 * Retrieve Minidump Template
3573f10a77bbSDavid C Somayajulu 	 */
3574f10a77bbSDavid C Somayajulu 	ret = qla_get_minidump_template(ha);
357535291c22SDavid C Somayajulu #else
357635291c22SDavid C Somayajulu 	ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump;
357735291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
3578f10a77bbSDavid C Somayajulu 
3579f10a77bbSDavid C Somayajulu 	if (ret) {
3580f10a77bbSDavid C Somayajulu 		qla_minidump_free(ha);
3581f10a77bbSDavid C Somayajulu 	} else {
3582f10a77bbSDavid C Somayajulu 		ha->hw.mdump_init = 1;
3583f10a77bbSDavid C Somayajulu 	}
3584f10a77bbSDavid C Somayajulu 
3585f10a77bbSDavid C Somayajulu 	return (ret);
3586f10a77bbSDavid C Somayajulu }
3587f10a77bbSDavid C Somayajulu 
3588f10a77bbSDavid C Somayajulu 
3589f10a77bbSDavid C Somayajulu static void
3590f10a77bbSDavid C Somayajulu qla_minidump_free(qla_host_t *ha)
3591f10a77bbSDavid C Somayajulu {
3592f10a77bbSDavid C Somayajulu 	ha->hw.mdump_init = 0;
3593f10a77bbSDavid C Somayajulu 	if (ha->hw.dma_buf.flags.minidump) {
3594f10a77bbSDavid C Somayajulu 		ha->hw.dma_buf.flags.minidump = 0;
3595f10a77bbSDavid C Somayajulu 		ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump);
3596f10a77bbSDavid C Somayajulu 	}
3597f10a77bbSDavid C Somayajulu 	return;
3598f10a77bbSDavid C Somayajulu }
3599f10a77bbSDavid C Somayajulu 
3600f10a77bbSDavid C Somayajulu void
3601f10a77bbSDavid C Somayajulu ql_minidump(qla_host_t *ha)
3602f10a77bbSDavid C Somayajulu {
3603f10a77bbSDavid C Somayajulu 	uint32_t delay = 6000;
3604f10a77bbSDavid C Somayajulu 
3605f10a77bbSDavid C Somayajulu 	if (!ha->hw.mdump_init)
3606f10a77bbSDavid C Somayajulu 		return;
3607f10a77bbSDavid C Somayajulu 
3608f10a77bbSDavid C Somayajulu 	if (!ha->hw.mdump_active)
3609f10a77bbSDavid C Somayajulu 		return;
3610f10a77bbSDavid C Somayajulu 
3611f10a77bbSDavid C Somayajulu 	if (ha->hw.mdump_active == 1) {
3612f10a77bbSDavid C Somayajulu 		ha->hw.mdump_start_seq_index = ql_stop_sequence(ha);
3613f10a77bbSDavid C Somayajulu 		ha->hw.mdump_start = 1;
3614f10a77bbSDavid C Somayajulu 	}
3615f10a77bbSDavid C Somayajulu 
3616f10a77bbSDavid C Somayajulu 	while (delay-- && ha->hw.mdump_active) {
3617f10a77bbSDavid C Somayajulu 		qla_mdelay(__func__, 100);
3618f10a77bbSDavid C Somayajulu 	}
3619f10a77bbSDavid C Somayajulu 	ha->hw.mdump_start = 0;
3620f10a77bbSDavid C Somayajulu 	ql_start_sequence(ha, ha->hw.mdump_start_seq_index);
3621f10a77bbSDavid C Somayajulu 
3622f10a77bbSDavid C Somayajulu 	return;
3623f10a77bbSDavid C Somayajulu }
3624