xref: /freebsd/sys/dev/qlxgbe/ql_hw.c (revision da834d52)
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"
446a62bec0SDavid C Somayajulu #include "ql_minidump.h"
45f10a77bbSDavid C Somayajulu 
46f10a77bbSDavid C Somayajulu /*
47f10a77bbSDavid C Somayajulu  * Static Functions
48f10a77bbSDavid C Somayajulu  */
49f10a77bbSDavid C Somayajulu 
50f10a77bbSDavid C Somayajulu static void qla_del_rcv_cntxt(qla_host_t *ha);
51f10a77bbSDavid C Somayajulu static int qla_init_rcv_cntxt(qla_host_t *ha);
52f10a77bbSDavid C Somayajulu static void qla_del_xmt_cntxt(qla_host_t *ha);
53f10a77bbSDavid C Somayajulu static int qla_init_xmt_cntxt(qla_host_t *ha);
54f10a77bbSDavid C Somayajulu static void qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx);
55f10a77bbSDavid C Somayajulu static int qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
56f10a77bbSDavid C Somayajulu 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause);
5735291c22SDavid C Somayajulu static int qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx,
5835291c22SDavid C Somayajulu 	uint32_t num_intrs, uint32_t create);
59f10a77bbSDavid C Somayajulu static int qla_config_rss(qla_host_t *ha, uint16_t cntxt_id);
60f10a77bbSDavid C Somayajulu static int qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id,
6135291c22SDavid C Somayajulu 	int tenable, int rcv);
62f10a77bbSDavid C Somayajulu static int qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode);
63f10a77bbSDavid C Somayajulu static int qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id);
64f10a77bbSDavid C Somayajulu 
65f10a77bbSDavid C Somayajulu static int qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd,
66f10a77bbSDavid C Somayajulu 		uint8_t *hdr);
67f10a77bbSDavid C Somayajulu static int qla_hw_add_all_mcast(qla_host_t *ha);
68f10a77bbSDavid C Somayajulu static int qla_hw_del_all_mcast(qla_host_t *ha);
6935291c22SDavid C Somayajulu static int qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds);
7035291c22SDavid C Somayajulu 
7135291c22SDavid C Somayajulu static int qla_init_nic_func(qla_host_t *ha);
7235291c22SDavid C Somayajulu static int qla_stop_nic_func(qla_host_t *ha);
7335291c22SDavid C Somayajulu static int qla_query_fw_dcbx_caps(qla_host_t *ha);
7435291c22SDavid C Somayajulu static int qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits);
7535291c22SDavid C Somayajulu static int qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits);
7635291c22SDavid C Somayajulu static void qla_get_quick_stats(qla_host_t *ha);
7700caeec7SDavid C Somayajulu static int qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode);
7800caeec7SDavid C Somayajulu static int qla_get_cam_search_mode(qla_host_t *ha);
79f10a77bbSDavid C Somayajulu 
806a62bec0SDavid C Somayajulu static void ql_minidump_free(qla_host_t *ha);
81f10a77bbSDavid C Somayajulu 
82f10a77bbSDavid C Somayajulu 
83f10a77bbSDavid C Somayajulu static int
84f10a77bbSDavid C Somayajulu qla_sysctl_get_drvr_stats(SYSCTL_HANDLER_ARGS)
85f10a77bbSDavid C Somayajulu {
86f10a77bbSDavid C Somayajulu         int err = 0, ret;
87f10a77bbSDavid C Somayajulu         qla_host_t *ha;
88f10a77bbSDavid C Somayajulu 	uint32_t i;
89f10a77bbSDavid C Somayajulu 
90f10a77bbSDavid C Somayajulu         err = sysctl_handle_int(oidp, &ret, 0, req);
91f10a77bbSDavid C Somayajulu 
92f10a77bbSDavid C Somayajulu         if (err || !req->newptr)
93f10a77bbSDavid C Somayajulu                 return (err);
94f10a77bbSDavid C Somayajulu 
95f10a77bbSDavid C Somayajulu         if (ret == 1) {
96f10a77bbSDavid C Somayajulu 
97f10a77bbSDavid C Somayajulu                 ha = (qla_host_t *)arg1;
98f10a77bbSDavid C Somayajulu 
9900caeec7SDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
10000caeec7SDavid C Somayajulu 
101f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
102f10a77bbSDavid C Somayajulu 				"%s: sds_ring[%d] = %p\n", __func__,i,
103f10a77bbSDavid C Somayajulu 				(void *)ha->hw.sds[i].intr_count);
104f10a77bbSDavid C Somayajulu 
10500caeec7SDavid C Somayajulu 			device_printf(ha->pci_dev,
10600caeec7SDavid C Somayajulu 				"%s: sds_ring[%d].spurious_intr_count = %p\n",
10700caeec7SDavid C Somayajulu 				__func__,
10800caeec7SDavid C Somayajulu 				i, (void *)ha->hw.sds[i].spurious_intr_count);
10900caeec7SDavid C Somayajulu 
11000caeec7SDavid C Somayajulu 			device_printf(ha->pci_dev,
11100caeec7SDavid C Somayajulu 				"%s: sds_ring[%d].rx_free = %d\n", __func__,i,
11200caeec7SDavid C Somayajulu 				ha->hw.sds[i].rx_free);
11300caeec7SDavid C Somayajulu 		}
11400caeec7SDavid C Somayajulu 
115f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_tx_rings; i++)
116f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
117f10a77bbSDavid C Somayajulu 				"%s: tx[%d] = %p\n", __func__,i,
118f10a77bbSDavid C Somayajulu 				(void *)ha->tx_ring[i].count);
119f10a77bbSDavid C Somayajulu 
120f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_rds_rings; i++)
121f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
122f10a77bbSDavid C Somayajulu 				"%s: rds_ring[%d] = %p\n", __func__,i,
123f10a77bbSDavid C Somayajulu 				(void *)ha->hw.rds[i].count);
124f10a77bbSDavid C Somayajulu 
125f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: lro_pkt_count = %p\n", __func__,
126f10a77bbSDavid C Somayajulu 			(void *)ha->lro_pkt_count);
127f10a77bbSDavid C Somayajulu 
128f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: lro_bytes = %p\n", __func__,
129f10a77bbSDavid C Somayajulu 			(void *)ha->lro_bytes);
13035291c22SDavid C Somayajulu 
13135291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV
13235291c22SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: iscsi_pkts = %p\n", __func__,
13335291c22SDavid C Somayajulu 			(void *)ha->hw.iscsi_pkt_count);
13435291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
13535291c22SDavid C Somayajulu 
13635291c22SDavid C Somayajulu 	}
13735291c22SDavid C Somayajulu 	return (err);
13835291c22SDavid C Somayajulu }
13935291c22SDavid C Somayajulu 
14035291c22SDavid C Somayajulu static int
14135291c22SDavid C Somayajulu qla_sysctl_get_quick_stats(SYSCTL_HANDLER_ARGS)
14235291c22SDavid C Somayajulu {
14335291c22SDavid C Somayajulu 	int err, ret = 0;
14435291c22SDavid C Somayajulu 	qla_host_t *ha;
14535291c22SDavid C Somayajulu 
14635291c22SDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
14735291c22SDavid C Somayajulu 
14835291c22SDavid C Somayajulu 	if (err || !req->newptr)
14935291c22SDavid C Somayajulu 		return (err);
15035291c22SDavid C Somayajulu 
15135291c22SDavid C Somayajulu 	if (ret == 1) {
15235291c22SDavid C Somayajulu 		ha = (qla_host_t *)arg1;
15335291c22SDavid C Somayajulu 		qla_get_quick_stats(ha);
154f10a77bbSDavid C Somayajulu 	}
155f10a77bbSDavid C Somayajulu 	return (err);
156f10a77bbSDavid C Somayajulu }
157f10a77bbSDavid C Somayajulu 
158f10a77bbSDavid C Somayajulu #ifdef QL_DBG
159f10a77bbSDavid C Somayajulu 
160f10a77bbSDavid C Somayajulu static void
161f10a77bbSDavid C Somayajulu qla_stop_pegs(qla_host_t *ha)
162f10a77bbSDavid C Somayajulu {
163f10a77bbSDavid C Somayajulu         uint32_t val = 1;
164f10a77bbSDavid C Somayajulu 
165f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0);
166f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0);
167f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0);
168f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0);
169f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0);
170f10a77bbSDavid C Somayajulu         device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__);
171f10a77bbSDavid C Somayajulu }
172f10a77bbSDavid C Somayajulu 
173f10a77bbSDavid C Somayajulu static int
174f10a77bbSDavid C Somayajulu qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)
175f10a77bbSDavid C Somayajulu {
176f10a77bbSDavid C Somayajulu 	int err, ret = 0;
177f10a77bbSDavid C Somayajulu 	qla_host_t *ha;
178f10a77bbSDavid C Somayajulu 
179f10a77bbSDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
180f10a77bbSDavid C Somayajulu 
181f10a77bbSDavid C Somayajulu 
182f10a77bbSDavid C Somayajulu 	if (err || !req->newptr)
183f10a77bbSDavid C Somayajulu 		return (err);
184f10a77bbSDavid C Somayajulu 
185f10a77bbSDavid C Somayajulu 	if (ret == 1) {
186f10a77bbSDavid C Somayajulu 		ha = (qla_host_t *)arg1;
187f10a77bbSDavid C Somayajulu 		(void)QLA_LOCK(ha, __func__, 0);
188f10a77bbSDavid C Somayajulu 		qla_stop_pegs(ha);
189f10a77bbSDavid C Somayajulu 		QLA_UNLOCK(ha, __func__);
190f10a77bbSDavid C Somayajulu 	}
191f10a77bbSDavid C Somayajulu 
192f10a77bbSDavid C Somayajulu 	return err;
193f10a77bbSDavid C Somayajulu }
194f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */
195f10a77bbSDavid C Somayajulu 
19635291c22SDavid C Somayajulu static int
19735291c22SDavid C Somayajulu qla_validate_set_port_cfg_bit(uint32_t bits)
19835291c22SDavid C Somayajulu {
19935291c22SDavid C Somayajulu         if ((bits & 0xF) > 1)
20035291c22SDavid C Somayajulu                 return (-1);
20135291c22SDavid C Somayajulu 
20235291c22SDavid C Somayajulu         if (((bits >> 4) & 0xF) > 2)
20335291c22SDavid C Somayajulu                 return (-1);
20435291c22SDavid C Somayajulu 
20535291c22SDavid C Somayajulu         if (((bits >> 8) & 0xF) > 2)
20635291c22SDavid C Somayajulu                 return (-1);
20735291c22SDavid C Somayajulu 
20835291c22SDavid C Somayajulu         return (0);
20935291c22SDavid C Somayajulu }
21035291c22SDavid C Somayajulu 
21135291c22SDavid C Somayajulu static int
21235291c22SDavid C Somayajulu qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS)
21335291c22SDavid C Somayajulu {
21435291c22SDavid C Somayajulu         int err, ret = 0;
21535291c22SDavid C Somayajulu         qla_host_t *ha;
21635291c22SDavid C Somayajulu         uint32_t cfg_bits;
21735291c22SDavid C Somayajulu 
21835291c22SDavid C Somayajulu         err = sysctl_handle_int(oidp, &ret, 0, req);
21935291c22SDavid C Somayajulu 
22035291c22SDavid C Somayajulu         if (err || !req->newptr)
22135291c22SDavid C Somayajulu                 return (err);
22235291c22SDavid C Somayajulu 
22335291c22SDavid C Somayajulu         if ((qla_validate_set_port_cfg_bit((uint32_t)ret) == 0)) {
22435291c22SDavid C Somayajulu 
22535291c22SDavid C Somayajulu                 ha = (qla_host_t *)arg1;
22635291c22SDavid C Somayajulu 
22735291c22SDavid C Somayajulu                 err = qla_get_port_config(ha, &cfg_bits);
22835291c22SDavid C Somayajulu 
22935291c22SDavid C Somayajulu                 if (err)
23035291c22SDavid C Somayajulu                         goto qla_sysctl_set_port_cfg_exit;
23135291c22SDavid C Somayajulu 
23235291c22SDavid C Somayajulu                 if (ret & 0x1) {
23335291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_DCBX_ENABLE;
23435291c22SDavid C Somayajulu                 } else {
23535291c22SDavid C Somayajulu                         cfg_bits &= ~Q8_PORT_CFG_BITS_DCBX_ENABLE;
23635291c22SDavid C Somayajulu                 }
23735291c22SDavid C Somayajulu 
23835291c22SDavid C Somayajulu                 ret = ret >> 4;
23935291c22SDavid C Somayajulu                 cfg_bits &= ~Q8_PORT_CFG_BITS_PAUSE_CFG_MASK;
24035291c22SDavid C Somayajulu 
24135291c22SDavid C Somayajulu                 if ((ret & 0xF) == 0) {
24235291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_DISABLED;
24335291c22SDavid C Somayajulu                 } else if ((ret & 0xF) == 1){
24435291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_STD;
24535291c22SDavid C Somayajulu                 } else {
24635291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_PPM;
24735291c22SDavid C Somayajulu                 }
24835291c22SDavid C Somayajulu 
24935291c22SDavid C Somayajulu                 ret = ret >> 4;
25035291c22SDavid C Somayajulu                 cfg_bits &= ~Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK;
25135291c22SDavid C Somayajulu 
25235291c22SDavid C Somayajulu                 if (ret == 0) {
25335291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT_RCV;
25435291c22SDavid C Somayajulu                 } else if (ret == 1){
25535291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT;
25635291c22SDavid C Somayajulu                 } else {
25735291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_RCV;
25835291c22SDavid C Somayajulu                 }
25935291c22SDavid C Somayajulu 
26035291c22SDavid C Somayajulu                 err = qla_set_port_config(ha, cfg_bits);
26135291c22SDavid C Somayajulu         } else {
26235291c22SDavid C Somayajulu                 ha = (qla_host_t *)arg1;
26335291c22SDavid C Somayajulu 
26435291c22SDavid C Somayajulu                 err = qla_get_port_config(ha, &cfg_bits);
26535291c22SDavid C Somayajulu         }
26635291c22SDavid C Somayajulu 
26735291c22SDavid C Somayajulu qla_sysctl_set_port_cfg_exit:
26835291c22SDavid C Somayajulu         return err;
26935291c22SDavid C Somayajulu }
27035291c22SDavid C Somayajulu 
27100caeec7SDavid C Somayajulu static int
27200caeec7SDavid C Somayajulu qla_sysctl_set_cam_search_mode(SYSCTL_HANDLER_ARGS)
27300caeec7SDavid C Somayajulu {
27400caeec7SDavid C Somayajulu 	int err, ret = 0;
27500caeec7SDavid C Somayajulu 	qla_host_t *ha;
27600caeec7SDavid C Somayajulu 
27700caeec7SDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
27800caeec7SDavid C Somayajulu 
27900caeec7SDavid C Somayajulu 	if (err || !req->newptr)
28000caeec7SDavid C Somayajulu 		return (err);
28100caeec7SDavid C Somayajulu 
28200caeec7SDavid C Somayajulu 	ha = (qla_host_t *)arg1;
28300caeec7SDavid C Somayajulu 
28400caeec7SDavid C Somayajulu 	if ((ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_INTERNAL) ||
28500caeec7SDavid C Somayajulu 		(ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_AUTO)) {
28600caeec7SDavid C Somayajulu 		err = qla_set_cam_search_mode(ha, (uint32_t)ret);
28700caeec7SDavid C Somayajulu 	} else {
28800caeec7SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: ret = %d\n", __func__, ret);
28900caeec7SDavid C Somayajulu 	}
29000caeec7SDavid C Somayajulu 
29100caeec7SDavid C Somayajulu 	return (err);
29200caeec7SDavid C Somayajulu }
29300caeec7SDavid C Somayajulu 
29400caeec7SDavid C Somayajulu static int
29500caeec7SDavid C Somayajulu qla_sysctl_get_cam_search_mode(SYSCTL_HANDLER_ARGS)
29600caeec7SDavid C Somayajulu {
29700caeec7SDavid C Somayajulu 	int err, ret = 0;
29800caeec7SDavid C Somayajulu 	qla_host_t *ha;
29900caeec7SDavid C Somayajulu 
30000caeec7SDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
30100caeec7SDavid C Somayajulu 
30200caeec7SDavid C Somayajulu 	if (err || !req->newptr)
30300caeec7SDavid C Somayajulu 		return (err);
30400caeec7SDavid C Somayajulu 
30500caeec7SDavid C Somayajulu 	ha = (qla_host_t *)arg1;
30600caeec7SDavid C Somayajulu 	err = qla_get_cam_search_mode(ha);
30700caeec7SDavid C Somayajulu 
30800caeec7SDavid C Somayajulu 	return (err);
30900caeec7SDavid C Somayajulu }
31000caeec7SDavid C Somayajulu 
31100caeec7SDavid C Somayajulu 
312f10a77bbSDavid C Somayajulu /*
313f10a77bbSDavid C Somayajulu  * Name: ql_hw_add_sysctls
314f10a77bbSDavid C Somayajulu  * Function: Add P3Plus specific sysctls
315f10a77bbSDavid C Somayajulu  */
316f10a77bbSDavid C Somayajulu void
317f10a77bbSDavid C Somayajulu ql_hw_add_sysctls(qla_host_t *ha)
318f10a77bbSDavid C Somayajulu {
319f10a77bbSDavid C Somayajulu         device_t	dev;
320f10a77bbSDavid C Somayajulu 
321f10a77bbSDavid C Somayajulu         dev = ha->pci_dev;
322f10a77bbSDavid C Somayajulu 
323f10a77bbSDavid C Somayajulu 	ha->hw.num_sds_rings = MAX_SDS_RINGS;
324f10a77bbSDavid C Somayajulu 	ha->hw.num_rds_rings = MAX_RDS_RINGS;
325f10a77bbSDavid C Somayajulu 	ha->hw.num_tx_rings = NUM_TX_RINGS;
326f10a77bbSDavid C Somayajulu 
327f10a77bbSDavid C Somayajulu 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
328f10a77bbSDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
329f10a77bbSDavid C Somayajulu 		OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings,
330f10a77bbSDavid C Somayajulu 		ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings");
331f10a77bbSDavid C Somayajulu 
332f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
333f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
334f10a77bbSDavid C Somayajulu                 OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings,
335f10a77bbSDavid C Somayajulu 		ha->hw.num_sds_rings, "Number of Status Descriptor Rings");
336f10a77bbSDavid C Somayajulu 
337f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
338f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
339f10a77bbSDavid C Somayajulu                 OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings,
340f10a77bbSDavid C Somayajulu 		ha->hw.num_tx_rings, "Number of Transmit Rings");
341f10a77bbSDavid C Somayajulu 
342f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
343f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
344f10a77bbSDavid C Somayajulu                 OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx,
345f10a77bbSDavid C Somayajulu 		ha->txr_idx, "Tx Ring Used");
346f10a77bbSDavid C Somayajulu 
347f10a77bbSDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
348f10a77bbSDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
349f10a77bbSDavid C Somayajulu 		OID_AUTO, "drvr_stats", CTLTYPE_INT | CTLFLAG_RW,
350f10a77bbSDavid C Somayajulu 		(void *)ha, 0,
351f10a77bbSDavid C Somayajulu 		qla_sysctl_get_drvr_stats, "I", "Driver Maintained Statistics");
352f10a77bbSDavid C Somayajulu 
35335291c22SDavid C Somayajulu         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
35435291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
35535291c22SDavid C Somayajulu                 OID_AUTO, "quick_stats", CTLTYPE_INT | CTLFLAG_RW,
35635291c22SDavid C Somayajulu                 (void *)ha, 0,
35735291c22SDavid C Somayajulu                 qla_sysctl_get_quick_stats, "I", "Quick Statistics");
35835291c22SDavid C Somayajulu 
359f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
360f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
361f10a77bbSDavid C Somayajulu                 OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs,
362f10a77bbSDavid C Somayajulu 		ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt");
363f10a77bbSDavid C Somayajulu 
364f10a77bbSDavid C Somayajulu 	ha->hw.sds_cidx_thres = 32;
365f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
366f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
367f10a77bbSDavid C Somayajulu                 OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres,
368f10a77bbSDavid C Somayajulu 		ha->hw.sds_cidx_thres,
369f10a77bbSDavid C Somayajulu 		"Number of SDS entries to process before updating"
370f10a77bbSDavid C Somayajulu 		" SDS Ring Consumer Index");
371f10a77bbSDavid C Somayajulu 
372f10a77bbSDavid C Somayajulu 	ha->hw.rds_pidx_thres = 32;
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, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres,
376f10a77bbSDavid C Somayajulu 		ha->hw.rds_pidx_thres,
377f10a77bbSDavid C Somayajulu 		"Number of Rcv Rings Entries to post before updating"
378f10a77bbSDavid C Somayajulu 		" RDS Ring Producer Index");
379f10a77bbSDavid C Somayajulu 
38035291c22SDavid C Somayajulu         ha->hw.rcv_intr_coalesce = (3 << 16) | 256;
381c12c5bfbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
382c12c5bfbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
38335291c22SDavid C Somayajulu                 OID_AUTO, "rcv_intr_coalesce", CTLFLAG_RW,
38435291c22SDavid C Somayajulu                 &ha->hw.rcv_intr_coalesce,
38535291c22SDavid C Somayajulu                 ha->hw.rcv_intr_coalesce,
38635291c22SDavid C Somayajulu                 "Rcv Intr Coalescing Parameters\n"
38735291c22SDavid C Somayajulu                 "\tbits 15:0 max packets\n"
38835291c22SDavid C Somayajulu                 "\tbits 31:16 max micro-seconds to wait\n"
38935291c22SDavid C Somayajulu                 "\tplease run\n"
39035291c22SDavid C Somayajulu                 "\tifconfig <if> down && ifconfig <if> up\n"
39135291c22SDavid C Somayajulu                 "\tto take effect \n");
39235291c22SDavid C Somayajulu 
39335291c22SDavid C Somayajulu         ha->hw.xmt_intr_coalesce = (64 << 16) | 64;
39435291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
39535291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
39635291c22SDavid C Somayajulu                 OID_AUTO, "xmt_intr_coalesce", CTLFLAG_RW,
39735291c22SDavid C Somayajulu                 &ha->hw.xmt_intr_coalesce,
39835291c22SDavid C Somayajulu                 ha->hw.xmt_intr_coalesce,
39935291c22SDavid C Somayajulu                 "Xmt Intr Coalescing Parameters\n"
40035291c22SDavid C Somayajulu                 "\tbits 15:0 max packets\n"
40135291c22SDavid C Somayajulu                 "\tbits 31:16 max micro-seconds to wait\n"
40235291c22SDavid C Somayajulu                 "\tplease run\n"
40335291c22SDavid C Somayajulu                 "\tifconfig <if> down && ifconfig <if> up\n"
40435291c22SDavid C Somayajulu                 "\tto take effect \n");
40535291c22SDavid C Somayajulu 
40635291c22SDavid C Somayajulu         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
40735291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
40835291c22SDavid C Somayajulu                 OID_AUTO, "port_cfg", CTLTYPE_INT | CTLFLAG_RW,
40935291c22SDavid C Somayajulu                 (void *)ha, 0,
41035291c22SDavid C Somayajulu                 qla_sysctl_port_cfg, "I",
41135291c22SDavid C Somayajulu                         "Set Port Configuration if values below "
41235291c22SDavid C Somayajulu                         "otherwise Get Port Configuration\n"
41335291c22SDavid C Somayajulu                         "\tBits 0-3 ; 1 = DCBX Enable; 0 = DCBX Disable\n"
41435291c22SDavid C Somayajulu                         "\tBits 4-7 : 0 = no pause; 1 = std ; 2 = ppm \n"
41535291c22SDavid C Somayajulu                         "\tBits 8-11: std pause cfg; 0 = xmt and rcv;"
41635291c22SDavid C Somayajulu                         " 1 = xmt only; 2 = rcv only;\n"
41735291c22SDavid C Somayajulu                 );
41835291c22SDavid C Somayajulu 
41900caeec7SDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
42000caeec7SDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
42100caeec7SDavid C Somayajulu 		OID_AUTO, "set_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW,
42200caeec7SDavid C Somayajulu 		(void *)ha, 0,
42300caeec7SDavid C Somayajulu 		qla_sysctl_set_cam_search_mode, "I",
42400caeec7SDavid C Somayajulu 			"Set CAM Search Mode"
42500caeec7SDavid C Somayajulu 			"\t 1 = search mode internal\n"
42600caeec7SDavid C Somayajulu 			"\t 2 = search mode auto\n");
42700caeec7SDavid C Somayajulu 
42800caeec7SDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
42900caeec7SDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
43000caeec7SDavid C Somayajulu 		OID_AUTO, "get_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW,
43100caeec7SDavid C Somayajulu 		(void *)ha, 0,
43200caeec7SDavid C Somayajulu 		qla_sysctl_get_cam_search_mode, "I",
43300caeec7SDavid C Somayajulu 			"Get CAM Search Mode"
43400caeec7SDavid C Somayajulu 			"\t 1 = search mode internal\n"
43500caeec7SDavid C Somayajulu 			"\t 2 = search mode auto\n");
43600caeec7SDavid C Somayajulu 
43735291c22SDavid C Somayajulu         ha->hw.enable_9kb = 1;
43835291c22SDavid C Somayajulu 
43935291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
44035291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
44135291c22SDavid C Somayajulu                 OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb,
44235291c22SDavid C Somayajulu                 ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000");
443c12c5bfbSDavid C Somayajulu 
444f10a77bbSDavid C Somayajulu 	ha->hw.mdump_active = 0;
445f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
446f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
447f10a77bbSDavid C Somayajulu                 OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active,
448f10a77bbSDavid C Somayajulu 		ha->hw.mdump_active,
4496a62bec0SDavid C Somayajulu 		"Minidump retrieval is Active");
450f10a77bbSDavid C Somayajulu 
4516a62bec0SDavid C Somayajulu 	ha->hw.mdump_done = 0;
452f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
453f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
4546a62bec0SDavid C Somayajulu                 OID_AUTO, "mdump_done", CTLFLAG_RW,
4556a62bec0SDavid C Somayajulu 		&ha->hw.mdump_done, ha->hw.mdump_done,
4566a62bec0SDavid C Somayajulu 		"Minidump has been done and available for retrieval");
4576a62bec0SDavid C Somayajulu 
4586a62bec0SDavid C Somayajulu 	ha->hw.mdump_capture_mask = 0xF;
4596a62bec0SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
4606a62bec0SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
4616a62bec0SDavid C Somayajulu                 OID_AUTO, "minidump_capture_mask", CTLFLAG_RW,
4626a62bec0SDavid C Somayajulu 		&ha->hw.mdump_capture_mask, ha->hw.mdump_capture_mask,
4636a62bec0SDavid C Somayajulu 		"Minidump capture mask");
464f10a77bbSDavid C Somayajulu #ifdef QL_DBG
465f10a77bbSDavid C Somayajulu 
466467dcb5aSDavid C Somayajulu 	ha->err_inject = 0;
467f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
468f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
469f10a77bbSDavid C Somayajulu                 OID_AUTO, "err_inject",
470f10a77bbSDavid C Somayajulu                 CTLFLAG_RW, &ha->err_inject, ha->err_inject,
471f10a77bbSDavid C Somayajulu                 "Error to be injected\n"
472f10a77bbSDavid C Somayajulu                 "\t\t\t 0: No Errors\n"
473f10a77bbSDavid C Somayajulu                 "\t\t\t 1: rcv: rxb struct invalid\n"
474f10a77bbSDavid C Somayajulu                 "\t\t\t 2: rcv: mp == NULL\n"
475f10a77bbSDavid C Somayajulu                 "\t\t\t 3: lro: rxb struct invalid\n"
476f10a77bbSDavid C Somayajulu                 "\t\t\t 4: lro: mp == NULL\n"
477f10a77bbSDavid C Somayajulu                 "\t\t\t 5: rcv: num handles invalid\n"
478f10a77bbSDavid C Somayajulu                 "\t\t\t 6: reg: indirect reg rd_wr failure\n"
479f10a77bbSDavid C Somayajulu                 "\t\t\t 7: ocm: offchip memory rd_wr failure\n"
480f10a77bbSDavid C Somayajulu                 "\t\t\t 8: mbx: mailbox command failure\n"
481f10a77bbSDavid C Somayajulu                 "\t\t\t 9: heartbeat failure\n"
48200caeec7SDavid C Somayajulu                 "\t\t\t A: temperature failure\n"
48300caeec7SDavid C Somayajulu 		"\t\t\t 11: m_getcl or m_getjcl failure\n" );
484f10a77bbSDavid C Somayajulu 
485f10a77bbSDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
486f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
487f10a77bbSDavid C Somayajulu                 OID_AUTO, "peg_stop", CTLTYPE_INT | CTLFLAG_RW,
488f10a77bbSDavid C Somayajulu                 (void *)ha, 0,
489f10a77bbSDavid C Somayajulu                 qla_sysctl_stop_pegs, "I", "Peg Stop");
490f10a77bbSDavid C Somayajulu 
491f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */
492f10a77bbSDavid C Somayajulu 
49335291c22SDavid C Somayajulu         ha->hw.user_pri_nic = 0;
49435291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
49535291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
49635291c22SDavid C Somayajulu                 OID_AUTO, "user_pri_nic", CTLFLAG_RW, &ha->hw.user_pri_nic,
49735291c22SDavid C Somayajulu                 ha->hw.user_pri_nic,
49835291c22SDavid C Somayajulu                 "VLAN Tag User Priority for Normal Ethernet Packets");
49935291c22SDavid C Somayajulu 
50035291c22SDavid C Somayajulu         ha->hw.user_pri_iscsi = 4;
50135291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
50235291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
50335291c22SDavid C Somayajulu                 OID_AUTO, "user_pri_iscsi", CTLFLAG_RW, &ha->hw.user_pri_iscsi,
50435291c22SDavid C Somayajulu                 ha->hw.user_pri_iscsi,
50535291c22SDavid C Somayajulu                 "VLAN Tag User Priority for iSCSI Packets");
50635291c22SDavid C Somayajulu 
507f10a77bbSDavid C Somayajulu }
508f10a77bbSDavid C Somayajulu 
509f10a77bbSDavid C Somayajulu void
510f10a77bbSDavid C Somayajulu ql_hw_link_status(qla_host_t *ha)
511f10a77bbSDavid C Somayajulu {
512f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui);
513f10a77bbSDavid C Somayajulu 
514f10a77bbSDavid C Somayajulu 	if (ha->hw.link_up) {
515f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link Up\n");
516f10a77bbSDavid C Somayajulu 	} else {
517f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link Down\n");
518f10a77bbSDavid C Somayajulu 	}
519f10a77bbSDavid C Somayajulu 
520f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.fduplex) {
521f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Full Duplex\n");
522f10a77bbSDavid C Somayajulu 	} else {
523f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Half Duplex\n");
524f10a77bbSDavid C Somayajulu 	}
525f10a77bbSDavid C Somayajulu 
526f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.autoneg) {
527f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Auto Negotiation Enabled\n");
528f10a77bbSDavid C Somayajulu 	} else {
529f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Auto Negotiation Disabled\n");
530f10a77bbSDavid C Somayajulu 	}
531f10a77bbSDavid C Somayajulu 
532f10a77bbSDavid C Somayajulu 	switch (ha->hw.link_speed) {
533f10a77bbSDavid C Somayajulu 	case 0x710:
534f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 10Gps\n");
535f10a77bbSDavid C Somayajulu 		break;
536f10a77bbSDavid C Somayajulu 
537f10a77bbSDavid C Somayajulu 	case 0x3E8:
538f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 1Gps\n");
539f10a77bbSDavid C Somayajulu 		break;
540f10a77bbSDavid C Somayajulu 
541f10a77bbSDavid C Somayajulu 	case 0x64:
542f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n");
543f10a77bbSDavid C Somayajulu 		break;
544f10a77bbSDavid C Somayajulu 
545f10a77bbSDavid C Somayajulu 	default:
546f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t Unknown\n");
547f10a77bbSDavid C Somayajulu 		break;
548f10a77bbSDavid C Somayajulu 	}
549f10a77bbSDavid C Somayajulu 
550f10a77bbSDavid C Somayajulu 	switch (ha->hw.module_type) {
551f10a77bbSDavid C Somayajulu 
552f10a77bbSDavid C Somayajulu 	case 0x01:
553f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n");
554f10a77bbSDavid C Somayajulu 		break;
555f10a77bbSDavid C Somayajulu 
556f10a77bbSDavid C Somayajulu 	case 0x02:
557f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-LR\n");
558f10a77bbSDavid C Somayajulu 		break;
559f10a77bbSDavid C Somayajulu 
560f10a77bbSDavid C Somayajulu 	case 0x03:
561f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-SR\n");
562f10a77bbSDavid C Somayajulu 		break;
563f10a77bbSDavid C Somayajulu 
564f10a77bbSDavid C Somayajulu 	case 0x04:
565f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
566f10a77bbSDavid C Somayajulu 			"Module Type 10GE Passive Copper(Compliant)[%d m]\n",
567f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
568f10a77bbSDavid C Somayajulu 		break;
569f10a77bbSDavid C Somayajulu 
570f10a77bbSDavid C Somayajulu 	case 0x05:
571f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GE Active"
572f10a77bbSDavid C Somayajulu 			" Limiting Copper(Compliant)[%d m]\n",
573f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
574f10a77bbSDavid C Somayajulu 		break;
575f10a77bbSDavid C Somayajulu 
576f10a77bbSDavid C Somayajulu 	case 0x06:
577f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
578f10a77bbSDavid C Somayajulu 			"Module Type 10GE Passive Copper"
579f10a77bbSDavid C Somayajulu 			" (Legacy, Best Effort)[%d m]\n",
580f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
581f10a77bbSDavid C Somayajulu 		break;
582f10a77bbSDavid C Somayajulu 
583f10a77bbSDavid C Somayajulu 	case 0x07:
584f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-SX\n");
585f10a77bbSDavid C Somayajulu 		break;
586f10a77bbSDavid C Somayajulu 
587f10a77bbSDavid C Somayajulu 	case 0x08:
588f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-LX\n");
589f10a77bbSDavid C Somayajulu 		break;
590f10a77bbSDavid C Somayajulu 
591f10a77bbSDavid C Somayajulu 	case 0x09:
592f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-CX\n");
593f10a77bbSDavid C Somayajulu 		break;
594f10a77bbSDavid C Somayajulu 
595f10a77bbSDavid C Somayajulu 	case 0x0A:
596f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-T\n");
597f10a77bbSDavid C Somayajulu 		break;
598f10a77bbSDavid C Somayajulu 
599f10a77bbSDavid C Somayajulu 	case 0x0B:
600f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1GE Passive Copper"
601f10a77bbSDavid C Somayajulu 			"(Legacy, Best Effort)\n");
602f10a77bbSDavid C Somayajulu 		break;
603f10a77bbSDavid C Somayajulu 
604f10a77bbSDavid C Somayajulu 	default:
605f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n",
606f10a77bbSDavid C Somayajulu 			ha->hw.module_type);
607f10a77bbSDavid C Somayajulu 		break;
608f10a77bbSDavid C Somayajulu 	}
609f10a77bbSDavid C Somayajulu 
610f10a77bbSDavid C Somayajulu 	if (ha->hw.link_faults == 1)
611f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "SFP Power Fault\n");
612f10a77bbSDavid C Somayajulu }
613f10a77bbSDavid C Somayajulu 
614f10a77bbSDavid C Somayajulu /*
615f10a77bbSDavid C Somayajulu  * Name: ql_free_dma
616f10a77bbSDavid C Somayajulu  * Function: Frees the DMA'able memory allocated in ql_alloc_dma()
617f10a77bbSDavid C Somayajulu  */
618f10a77bbSDavid C Somayajulu void
619f10a77bbSDavid C Somayajulu ql_free_dma(qla_host_t *ha)
620f10a77bbSDavid C Somayajulu {
621f10a77bbSDavid C Somayajulu 	uint32_t i;
622f10a77bbSDavid C Somayajulu 
623f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.sds_ring) {
624f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
625f10a77bbSDavid C Somayajulu 			ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]);
626f10a77bbSDavid C Somayajulu 		}
627f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.sds_ring = 0;
628f10a77bbSDavid C Somayajulu 	}
629f10a77bbSDavid C Somayajulu 
630f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.rds_ring) {
631f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_rds_rings; i++) {
632f10a77bbSDavid C Somayajulu 			ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]);
633f10a77bbSDavid C Somayajulu 		}
634f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.rds_ring = 0;
635f10a77bbSDavid C Somayajulu 	}
636f10a77bbSDavid C Somayajulu 
637f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.tx_ring) {
638f10a77bbSDavid C Somayajulu 		ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring);
639f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.tx_ring = 0;
640f10a77bbSDavid C Somayajulu 	}
6416a62bec0SDavid C Somayajulu 	ql_minidump_free(ha);
642f10a77bbSDavid C Somayajulu }
643f10a77bbSDavid C Somayajulu 
644f10a77bbSDavid C Somayajulu /*
645f10a77bbSDavid C Somayajulu  * Name: ql_alloc_dma
646f10a77bbSDavid C Somayajulu  * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts.
647f10a77bbSDavid C Somayajulu  */
648f10a77bbSDavid C Somayajulu int
649f10a77bbSDavid C Somayajulu ql_alloc_dma(qla_host_t *ha)
650f10a77bbSDavid C Somayajulu {
651f10a77bbSDavid C Somayajulu         device_t                dev;
652f10a77bbSDavid C Somayajulu 	uint32_t		i, j, size, tx_ring_size;
653f10a77bbSDavid C Somayajulu 	qla_hw_t		*hw;
654f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t	*tx_cntxt;
655f10a77bbSDavid C Somayajulu 	uint8_t			*vaddr;
656f10a77bbSDavid C Somayajulu 	bus_addr_t		paddr;
657f10a77bbSDavid C Somayajulu 
658f10a77bbSDavid C Somayajulu         dev = ha->pci_dev;
659f10a77bbSDavid C Somayajulu 
660f10a77bbSDavid C Somayajulu         QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
661f10a77bbSDavid C Somayajulu 
662f10a77bbSDavid C Somayajulu 	hw = &ha->hw;
663f10a77bbSDavid C Somayajulu 	/*
664f10a77bbSDavid C Somayajulu 	 * Allocate Transmit Ring
665f10a77bbSDavid C Somayajulu 	 */
666f10a77bbSDavid C Somayajulu 	tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS);
667f10a77bbSDavid C Somayajulu 	size = (tx_ring_size * ha->hw.num_tx_rings);
668f10a77bbSDavid C Somayajulu 
669f10a77bbSDavid C Somayajulu 	hw->dma_buf.tx_ring.alignment = 8;
670f10a77bbSDavid C Somayajulu 	hw->dma_buf.tx_ring.size = size + PAGE_SIZE;
671f10a77bbSDavid C Somayajulu 
672f10a77bbSDavid C Somayajulu         if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) {
673f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: tx ring alloc failed\n", __func__);
674f10a77bbSDavid C Somayajulu                 goto ql_alloc_dma_exit;
675f10a77bbSDavid C Somayajulu         }
676f10a77bbSDavid C Somayajulu 
677f10a77bbSDavid C Somayajulu 	vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b;
678f10a77bbSDavid C Somayajulu 	paddr = hw->dma_buf.tx_ring.dma_addr;
679f10a77bbSDavid C Somayajulu 
680f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
681f10a77bbSDavid C Somayajulu 		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
682f10a77bbSDavid C Somayajulu 
683f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr;
684f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_ring_paddr = paddr;
685f10a77bbSDavid C Somayajulu 
686f10a77bbSDavid C Somayajulu 		vaddr += tx_ring_size;
687f10a77bbSDavid C Somayajulu 		paddr += tx_ring_size;
688f10a77bbSDavid C Somayajulu 	}
689f10a77bbSDavid C Somayajulu 
690f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
691f10a77bbSDavid C Somayajulu 		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
692f10a77bbSDavid C Somayajulu 
693f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_cons = (uint32_t *)vaddr;
694f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_cons_paddr = paddr;
695f10a77bbSDavid C Somayajulu 
696f10a77bbSDavid C Somayajulu 		vaddr += sizeof (uint32_t);
697f10a77bbSDavid C Somayajulu 		paddr += sizeof (uint32_t);
698f10a77bbSDavid C Somayajulu 	}
699f10a77bbSDavid C Somayajulu 
700f10a77bbSDavid C Somayajulu         ha->hw.dma_buf.flags.tx_ring = 1;
701f10a77bbSDavid C Somayajulu 
702f10a77bbSDavid C Somayajulu 	QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n",
703f10a77bbSDavid C Somayajulu 		__func__, (void *)(hw->dma_buf.tx_ring.dma_addr),
704f10a77bbSDavid C Somayajulu 		hw->dma_buf.tx_ring.dma_b));
705f10a77bbSDavid C Somayajulu 	/*
706f10a77bbSDavid C Somayajulu 	 * Allocate Receive Descriptor Rings
707f10a77bbSDavid C Somayajulu 	 */
708f10a77bbSDavid C Somayajulu 
709f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_rds_rings; i++) {
710f10a77bbSDavid C Somayajulu 
711f10a77bbSDavid C Somayajulu 		hw->dma_buf.rds_ring[i].alignment = 8;
712f10a77bbSDavid C Somayajulu 		hw->dma_buf.rds_ring[i].size =
713f10a77bbSDavid C Somayajulu 			(sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS;
714f10a77bbSDavid C Somayajulu 
715f10a77bbSDavid C Somayajulu 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) {
716f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: rds ring[%d] alloc failed\n",
717f10a77bbSDavid C Somayajulu 				__func__, i);
718f10a77bbSDavid C Somayajulu 
719f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
720f10a77bbSDavid C Somayajulu 				ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]);
721f10a77bbSDavid C Somayajulu 
722f10a77bbSDavid C Somayajulu 			goto ql_alloc_dma_exit;
723f10a77bbSDavid C Somayajulu 		}
724f10a77bbSDavid C Somayajulu 		QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n",
725f10a77bbSDavid C Somayajulu 			__func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr),
726f10a77bbSDavid C Somayajulu 			hw->dma_buf.rds_ring[i].dma_b));
727f10a77bbSDavid C Somayajulu 	}
728f10a77bbSDavid C Somayajulu 
729f10a77bbSDavid C Somayajulu 	hw->dma_buf.flags.rds_ring = 1;
730f10a77bbSDavid C Somayajulu 
731f10a77bbSDavid C Somayajulu 	/*
732f10a77bbSDavid C Somayajulu 	 * Allocate Status Descriptor Rings
733f10a77bbSDavid C Somayajulu 	 */
734f10a77bbSDavid C Somayajulu 
735f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
736f10a77bbSDavid C Somayajulu 		hw->dma_buf.sds_ring[i].alignment = 8;
737f10a77bbSDavid C Somayajulu 		hw->dma_buf.sds_ring[i].size =
738f10a77bbSDavid C Somayajulu 			(sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS;
739f10a77bbSDavid C Somayajulu 
740f10a77bbSDavid C Somayajulu 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) {
741f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: sds ring alloc failed\n",
742f10a77bbSDavid C Somayajulu 				__func__);
743f10a77bbSDavid C Somayajulu 
744f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
745f10a77bbSDavid C Somayajulu 				ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]);
746f10a77bbSDavid C Somayajulu 
747f10a77bbSDavid C Somayajulu 			goto ql_alloc_dma_exit;
748f10a77bbSDavid C Somayajulu 		}
749f10a77bbSDavid C Somayajulu 		QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n",
750f10a77bbSDavid C Somayajulu 			__func__, i,
751f10a77bbSDavid C Somayajulu 			(void *)(hw->dma_buf.sds_ring[i].dma_addr),
752f10a77bbSDavid C Somayajulu 			hw->dma_buf.sds_ring[i].dma_b));
753f10a77bbSDavid C Somayajulu 	}
754f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
755f10a77bbSDavid C Somayajulu 		hw->sds[i].sds_ring_base =
756f10a77bbSDavid C Somayajulu 			(q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b;
757f10a77bbSDavid C Somayajulu 	}
758f10a77bbSDavid C Somayajulu 
759f10a77bbSDavid C Somayajulu 	hw->dma_buf.flags.sds_ring = 1;
760f10a77bbSDavid C Somayajulu 
761f10a77bbSDavid C Somayajulu 	return 0;
762f10a77bbSDavid C Somayajulu 
763f10a77bbSDavid C Somayajulu ql_alloc_dma_exit:
764f10a77bbSDavid C Somayajulu 	ql_free_dma(ha);
765f10a77bbSDavid C Somayajulu 	return -1;
766f10a77bbSDavid C Somayajulu }
767f10a77bbSDavid C Somayajulu 
768f10a77bbSDavid C Somayajulu #define Q8_MBX_MSEC_DELAY	5000
769f10a77bbSDavid C Somayajulu 
770f10a77bbSDavid C Somayajulu static int
771f10a77bbSDavid C Somayajulu qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
772f10a77bbSDavid C Somayajulu 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause)
773f10a77bbSDavid C Somayajulu {
774f10a77bbSDavid C Somayajulu 	uint32_t i;
775f10a77bbSDavid C Somayajulu 	uint32_t data;
776f10a77bbSDavid C Somayajulu 	int ret = 0;
777f10a77bbSDavid C Somayajulu 
778f10a77bbSDavid C Somayajulu 	if (QL_ERR_INJECT(ha, INJCT_MBX_CMD_FAILURE)) {
779f10a77bbSDavid C Somayajulu 		ret = -3;
780f10a77bbSDavid C Somayajulu 		ha->qla_initiate_recovery = 1;
781f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
782f10a77bbSDavid C Somayajulu 	}
783f10a77bbSDavid C Somayajulu 
784f10a77bbSDavid C Somayajulu 	if (no_pause)
785f10a77bbSDavid C Somayajulu 		i = 1000;
786f10a77bbSDavid C Somayajulu 	else
787f10a77bbSDavid C Somayajulu 		i = Q8_MBX_MSEC_DELAY;
788f10a77bbSDavid C Somayajulu 
789f10a77bbSDavid C Somayajulu 	while (i) {
790f10a77bbSDavid C Somayajulu 		data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL);
791f10a77bbSDavid C Somayajulu 		if (data == 0)
792f10a77bbSDavid C Somayajulu 			break;
793f10a77bbSDavid C Somayajulu 		if (no_pause) {
794f10a77bbSDavid C Somayajulu 			DELAY(1000);
795f10a77bbSDavid C Somayajulu 		} else {
796f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
797f10a77bbSDavid C Somayajulu 		}
798f10a77bbSDavid C Somayajulu 		i--;
799f10a77bbSDavid C Somayajulu 	}
800f10a77bbSDavid C Somayajulu 
801f10a77bbSDavid C Somayajulu 	if (i == 0) {
802f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n",
803f10a77bbSDavid C Somayajulu 			__func__, data);
804f10a77bbSDavid C Somayajulu 		ret = -1;
805f10a77bbSDavid C Somayajulu 		ha->qla_initiate_recovery = 1;
806f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
807f10a77bbSDavid C Somayajulu 	}
808f10a77bbSDavid C Somayajulu 
809f10a77bbSDavid C Somayajulu 	for (i = 0; i < n_hmbox; i++) {
810f10a77bbSDavid C Somayajulu 		WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox);
811f10a77bbSDavid C Somayajulu 		h_mbox++;
812f10a77bbSDavid C Somayajulu 	}
813f10a77bbSDavid C Somayajulu 
814f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1);
815f10a77bbSDavid C Somayajulu 
816f10a77bbSDavid C Somayajulu 
817f10a77bbSDavid C Somayajulu 	i = Q8_MBX_MSEC_DELAY;
818f10a77bbSDavid C Somayajulu 	while (i) {
819f10a77bbSDavid C Somayajulu 		data = READ_REG32(ha, Q8_FW_MBOX_CNTRL);
820f10a77bbSDavid C Somayajulu 
821f10a77bbSDavid C Somayajulu 		if ((data & 0x3) == 1) {
822f10a77bbSDavid C Somayajulu 			data = READ_REG32(ha, Q8_FW_MBOX0);
823f10a77bbSDavid C Somayajulu 			if ((data & 0xF000) != 0x8000)
824f10a77bbSDavid C Somayajulu 				break;
825f10a77bbSDavid C Somayajulu 		}
826f10a77bbSDavid C Somayajulu 		if (no_pause) {
827f10a77bbSDavid C Somayajulu 			DELAY(1000);
828f10a77bbSDavid C Somayajulu 		} else {
829f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
830f10a77bbSDavid C Somayajulu 		}
831f10a77bbSDavid C Somayajulu 		i--;
832f10a77bbSDavid C Somayajulu 	}
833f10a77bbSDavid C Somayajulu 	if (i == 0) {
834f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n",
835f10a77bbSDavid C Somayajulu 			__func__, data);
836f10a77bbSDavid C Somayajulu 		ret = -2;
837f10a77bbSDavid C Somayajulu 		ha->qla_initiate_recovery = 1;
838f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
839f10a77bbSDavid C Somayajulu 	}
840f10a77bbSDavid C Somayajulu 
841f10a77bbSDavid C Somayajulu 	for (i = 0; i < n_fwmbox; i++) {
842f10a77bbSDavid C Somayajulu 		*fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2)));
843f10a77bbSDavid C Somayajulu 	}
844f10a77bbSDavid C Somayajulu 
845f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0);
846f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
847f10a77bbSDavid C Somayajulu 
848f10a77bbSDavid C Somayajulu exit_qla_mbx_cmd:
849f10a77bbSDavid C Somayajulu 	return (ret);
850f10a77bbSDavid C Somayajulu }
851f10a77bbSDavid C Somayajulu 
85235291c22SDavid C Somayajulu int
85335291c22SDavid C Somayajulu qla_get_nic_partition(qla_host_t *ha, uint32_t *supports_9kb,
85435291c22SDavid C Somayajulu 	uint32_t *num_rcvq)
855f10a77bbSDavid C Somayajulu {
856f10a77bbSDavid C Somayajulu 	uint32_t *mbox, err;
857f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
858f10a77bbSDavid C Somayajulu 
859f10a77bbSDavid C Somayajulu 	bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX));
860f10a77bbSDavid C Somayajulu 
861f10a77bbSDavid C Somayajulu 	mbox = ha->hw.mbox;
862f10a77bbSDavid C Somayajulu 
863f10a77bbSDavid C Somayajulu 	mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29);
864f10a77bbSDavid C Somayajulu 
865f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) {
866f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
867f10a77bbSDavid C Somayajulu 		return (-1);
868f10a77bbSDavid C Somayajulu 	}
869f10a77bbSDavid C Somayajulu 	err = mbox[0] >> 25;
870f10a77bbSDavid C Somayajulu 
87135291c22SDavid C Somayajulu 	if (supports_9kb != NULL) {
87235291c22SDavid C Somayajulu 		if (mbox[16] & 0x80) /* bit 7 of mbox 16 */
87335291c22SDavid C Somayajulu 			*supports_9kb = 1;
87435291c22SDavid C Somayajulu 		else
87535291c22SDavid C Somayajulu 			*supports_9kb = 0;
87635291c22SDavid C Somayajulu 	}
87735291c22SDavid C Somayajulu 
87835291c22SDavid C Somayajulu 	if (num_rcvq != NULL)
87935291c22SDavid C Somayajulu 		*num_rcvq =  ((mbox[6] >> 16) & 0xFFFF);
88035291c22SDavid C Somayajulu 
881f10a77bbSDavid C Somayajulu 	if ((err != 1) && (err != 0)) {
882f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
883f10a77bbSDavid C Somayajulu 		return (-1);
884f10a77bbSDavid C Somayajulu 	}
885f10a77bbSDavid C Somayajulu 	return 0;
886f10a77bbSDavid C Somayajulu }
887f10a77bbSDavid C Somayajulu 
888f10a77bbSDavid C Somayajulu static int
88935291c22SDavid C Somayajulu qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, uint32_t num_intrs,
89035291c22SDavid C Somayajulu 	uint32_t create)
891f10a77bbSDavid C Somayajulu {
892f10a77bbSDavid C Somayajulu 	uint32_t i, err;
893f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
894f10a77bbSDavid C Somayajulu 	q80_config_intr_t *c_intr;
895f10a77bbSDavid C Somayajulu 	q80_config_intr_rsp_t *c_intr_rsp;
896f10a77bbSDavid C Somayajulu 
897f10a77bbSDavid C Somayajulu 	c_intr = (q80_config_intr_t *)ha->hw.mbox;
898f10a77bbSDavid C Somayajulu 	bzero(c_intr, (sizeof (q80_config_intr_t)));
899f10a77bbSDavid C Somayajulu 
900f10a77bbSDavid C Somayajulu 	c_intr->opcode = Q8_MBX_CONFIG_INTR;
901f10a77bbSDavid C Somayajulu 
902f10a77bbSDavid C Somayajulu 	c_intr->count_version = (sizeof (q80_config_intr_t) >> 2);
903f10a77bbSDavid C Somayajulu 	c_intr->count_version |= Q8_MBX_CMD_VERSION;
904f10a77bbSDavid C Somayajulu 
905f10a77bbSDavid C Somayajulu 	c_intr->nentries = num_intrs;
906f10a77bbSDavid C Somayajulu 
907f10a77bbSDavid C Somayajulu 	for (i = 0; i < num_intrs; i++) {
908f10a77bbSDavid C Somayajulu 		if (create) {
909f10a77bbSDavid C Somayajulu 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE;
91035291c22SDavid C Somayajulu 			c_intr->intr[i].msix_index = start_idx + 1 + i;
911f10a77bbSDavid C Somayajulu 		} else {
912f10a77bbSDavid C Somayajulu 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE;
91335291c22SDavid C Somayajulu 			c_intr->intr[i].msix_index =
91435291c22SDavid C Somayajulu 				ha->hw.intr_id[(start_idx + i)];
915f10a77bbSDavid C Somayajulu 		}
916f10a77bbSDavid C Somayajulu 
917f10a77bbSDavid C Somayajulu 		c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X;
918f10a77bbSDavid C Somayajulu 	}
919f10a77bbSDavid C Somayajulu 
920f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_intr,
921f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_intr_t) >> 2),
922f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) {
923f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
924f10a77bbSDavid C Somayajulu 		return (-1);
925f10a77bbSDavid C Somayajulu 	}
926f10a77bbSDavid C Somayajulu 
927f10a77bbSDavid C Somayajulu 	c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox;
928f10a77bbSDavid C Somayajulu 
929f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status);
930f10a77bbSDavid C Somayajulu 
931f10a77bbSDavid C Somayajulu 	if (err) {
932f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x, %d]\n", __func__, err,
933f10a77bbSDavid C Somayajulu 			c_intr_rsp->nentries);
934f10a77bbSDavid C Somayajulu 
935f10a77bbSDavid C Somayajulu 		for (i = 0; i < c_intr_rsp->nentries; i++) {
936f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n",
937f10a77bbSDavid C Somayajulu 				__func__, i,
938f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].status,
939f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].intr_id,
940f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].intr_src);
941f10a77bbSDavid C Somayajulu 		}
942f10a77bbSDavid C Somayajulu 
943f10a77bbSDavid C Somayajulu 		return (-1);
944f10a77bbSDavid C Somayajulu 	}
945f10a77bbSDavid C Somayajulu 
946f10a77bbSDavid C Somayajulu 	for (i = 0; ((i < num_intrs) && create); i++) {
947f10a77bbSDavid C Somayajulu 		if (!c_intr_rsp->intr[i].status) {
94835291c22SDavid C Somayajulu 			ha->hw.intr_id[(start_idx + i)] =
94935291c22SDavid C Somayajulu 				c_intr_rsp->intr[i].intr_id;
95035291c22SDavid C Somayajulu 			ha->hw.intr_src[(start_idx + i)] =
95135291c22SDavid C Somayajulu 				c_intr_rsp->intr[i].intr_src;
952f10a77bbSDavid C Somayajulu 		}
953f10a77bbSDavid C Somayajulu 	}
954f10a77bbSDavid C Somayajulu 
955f10a77bbSDavid C Somayajulu 	return (0);
956f10a77bbSDavid C Somayajulu }
957f10a77bbSDavid C Somayajulu 
958f10a77bbSDavid C Somayajulu /*
959f10a77bbSDavid C Somayajulu  * Name: qla_config_rss
960f10a77bbSDavid C Somayajulu  * Function: Configure RSS for the context/interface.
961f10a77bbSDavid C Somayajulu  */
962f10a77bbSDavid C Somayajulu static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL,
963f10a77bbSDavid C Somayajulu 			0x8030f20c77cb2da3ULL,
964f10a77bbSDavid C Somayajulu 			0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
965f10a77bbSDavid C Somayajulu 			0x255b0ec26d5a56daULL };
966f10a77bbSDavid C Somayajulu 
967f10a77bbSDavid C Somayajulu static int
968f10a77bbSDavid C Somayajulu qla_config_rss(qla_host_t *ha, uint16_t cntxt_id)
969f10a77bbSDavid C Somayajulu {
970f10a77bbSDavid C Somayajulu 	q80_config_rss_t	*c_rss;
971f10a77bbSDavid C Somayajulu 	q80_config_rss_rsp_t	*c_rss_rsp;
972f10a77bbSDavid C Somayajulu 	uint32_t		err, i;
973f10a77bbSDavid C Somayajulu 	device_t		dev = ha->pci_dev;
974f10a77bbSDavid C Somayajulu 
975f10a77bbSDavid C Somayajulu 	c_rss = (q80_config_rss_t *)ha->hw.mbox;
976f10a77bbSDavid C Somayajulu 	bzero(c_rss, (sizeof (q80_config_rss_t)));
977f10a77bbSDavid C Somayajulu 
978f10a77bbSDavid C Somayajulu 	c_rss->opcode = Q8_MBX_CONFIG_RSS;
979f10a77bbSDavid C Somayajulu 
980f10a77bbSDavid C Somayajulu 	c_rss->count_version = (sizeof (q80_config_rss_t) >> 2);
981f10a77bbSDavid C Somayajulu 	c_rss->count_version |= Q8_MBX_CMD_VERSION;
982f10a77bbSDavid C Somayajulu 
983f10a77bbSDavid C Somayajulu 	c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP |
984f10a77bbSDavid C Somayajulu 				Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP);
98535291c22SDavid C Somayajulu 	//c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP |
98635291c22SDavid C Somayajulu 	//			Q8_MBX_RSS_HASH_TYPE_IPV6_TCP);
987f10a77bbSDavid C Somayajulu 
988f10a77bbSDavid C Somayajulu 	c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS;
989f10a77bbSDavid C Somayajulu 	c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE;
990f10a77bbSDavid C Somayajulu 
991f10a77bbSDavid C Somayajulu 	c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK;
992f10a77bbSDavid C Somayajulu 
993f10a77bbSDavid C Somayajulu 	c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID;
994f10a77bbSDavid C Somayajulu 	c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS;
995f10a77bbSDavid C Somayajulu 
996f10a77bbSDavid C Somayajulu 	c_rss->cntxt_id = cntxt_id;
997f10a77bbSDavid C Somayajulu 
998f10a77bbSDavid C Somayajulu 	for (i = 0; i < 5; i++) {
999f10a77bbSDavid C Somayajulu 		c_rss->rss_key[i] = rss_key[i];
1000f10a77bbSDavid C Somayajulu 	}
1001f10a77bbSDavid C Somayajulu 
1002f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss,
1003f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_rss_t) >> 2),
1004f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) {
1005f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1006f10a77bbSDavid C Somayajulu 		return (-1);
1007f10a77bbSDavid C Somayajulu 	}
1008f10a77bbSDavid C Somayajulu 	c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox;
1009f10a77bbSDavid C Somayajulu 
1010f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status);
1011f10a77bbSDavid C Somayajulu 
1012f10a77bbSDavid C Somayajulu 	if (err) {
1013f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1014f10a77bbSDavid C Somayajulu 		return (-1);
1015f10a77bbSDavid C Somayajulu 	}
1016f10a77bbSDavid C Somayajulu 	return 0;
1017f10a77bbSDavid C Somayajulu }
1018f10a77bbSDavid C Somayajulu 
1019f10a77bbSDavid C Somayajulu static int
1020f10a77bbSDavid C Somayajulu qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count,
1021f10a77bbSDavid C Somayajulu         uint16_t cntxt_id, uint8_t *ind_table)
1022f10a77bbSDavid C Somayajulu {
1023f10a77bbSDavid C Somayajulu         q80_config_rss_ind_table_t      *c_rss_ind;
1024f10a77bbSDavid C Somayajulu         q80_config_rss_ind_table_rsp_t  *c_rss_ind_rsp;
1025f10a77bbSDavid C Somayajulu         uint32_t                        err;
1026f10a77bbSDavid C Somayajulu         device_t                        dev = ha->pci_dev;
1027f10a77bbSDavid C Somayajulu 
1028f10a77bbSDavid C Somayajulu 	if ((count > Q8_RSS_IND_TBL_SIZE) ||
1029f10a77bbSDavid C Somayajulu 		((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) {
1030f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: illegal count [%d, %d]\n", __func__,
1031f10a77bbSDavid C Somayajulu 			start_idx, count);
1032f10a77bbSDavid C Somayajulu 		return (-1);
1033f10a77bbSDavid C Somayajulu 	}
1034f10a77bbSDavid C Somayajulu 
1035f10a77bbSDavid C Somayajulu         c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox;
1036f10a77bbSDavid C Somayajulu         bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t));
1037f10a77bbSDavid C Somayajulu 
1038f10a77bbSDavid C Somayajulu         c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE;
1039f10a77bbSDavid C Somayajulu         c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2);
1040f10a77bbSDavid C Somayajulu         c_rss_ind->count_version |= Q8_MBX_CMD_VERSION;
1041f10a77bbSDavid C Somayajulu 
1042f10a77bbSDavid C Somayajulu 	c_rss_ind->start_idx = start_idx;
1043f10a77bbSDavid C Somayajulu 	c_rss_ind->end_idx = start_idx + count - 1;
1044f10a77bbSDavid C Somayajulu 	c_rss_ind->cntxt_id = cntxt_id;
1045f10a77bbSDavid C Somayajulu 	bcopy(ind_table, c_rss_ind->ind_table, count);
1046f10a77bbSDavid C Somayajulu 
1047f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind,
1048f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox,
1049f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) {
1050f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1051f10a77bbSDavid C Somayajulu 		return (-1);
1052f10a77bbSDavid C Somayajulu 	}
1053f10a77bbSDavid C Somayajulu 
1054f10a77bbSDavid C Somayajulu 	c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox;
1055f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status);
1056f10a77bbSDavid C Somayajulu 
1057f10a77bbSDavid C Somayajulu 	if (err) {
1058f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1059f10a77bbSDavid C Somayajulu 		return (-1);
1060f10a77bbSDavid C Somayajulu 	}
1061f10a77bbSDavid C Somayajulu 	return 0;
1062f10a77bbSDavid C Somayajulu }
1063f10a77bbSDavid C Somayajulu 
1064f10a77bbSDavid C Somayajulu /*
1065f10a77bbSDavid C Somayajulu  * Name: qla_config_intr_coalesce
1066f10a77bbSDavid C Somayajulu  * Function: Configure Interrupt Coalescing.
1067f10a77bbSDavid C Somayajulu  */
1068f10a77bbSDavid C Somayajulu static int
106935291c22SDavid C Somayajulu qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable,
107035291c22SDavid C Somayajulu 	int rcv)
1071f10a77bbSDavid C Somayajulu {
1072f10a77bbSDavid C Somayajulu 	q80_config_intr_coalesc_t	*intrc;
1073f10a77bbSDavid C Somayajulu 	q80_config_intr_coalesc_rsp_t	*intrc_rsp;
1074f10a77bbSDavid C Somayajulu 	uint32_t			err, i;
1075f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1076f10a77bbSDavid C Somayajulu 
1077f10a77bbSDavid C Somayajulu 	intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox;
1078f10a77bbSDavid C Somayajulu 	bzero(intrc, (sizeof (q80_config_intr_coalesc_t)));
1079f10a77bbSDavid C Somayajulu 
1080f10a77bbSDavid C Somayajulu 	intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE;
1081f10a77bbSDavid C Somayajulu 	intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2);
1082f10a77bbSDavid C Somayajulu 	intrc->count_version |= Q8_MBX_CMD_VERSION;
1083f10a77bbSDavid C Somayajulu 
108435291c22SDavid C Somayajulu 	if (rcv) {
1085f10a77bbSDavid C Somayajulu 		intrc->flags = Q8_MBX_INTRC_FLAGS_RCV;
108635291c22SDavid C Somayajulu 		intrc->max_pkts = ha->hw.rcv_intr_coalesce & 0xFFFF;
108735291c22SDavid C Somayajulu 		intrc->max_mswait = (ha->hw.rcv_intr_coalesce >> 16) & 0xFFFF;
108835291c22SDavid C Somayajulu 	} else {
108935291c22SDavid C Somayajulu 		intrc->flags = Q8_MBX_INTRC_FLAGS_XMT;
109035291c22SDavid C Somayajulu 		intrc->max_pkts = ha->hw.xmt_intr_coalesce & 0xFFFF;
109135291c22SDavid C Somayajulu 		intrc->max_mswait = (ha->hw.xmt_intr_coalesce >> 16) & 0xFFFF;
109235291c22SDavid C Somayajulu 	}
1093f10a77bbSDavid C Somayajulu 
109435291c22SDavid C Somayajulu 	intrc->cntxt_id = cntxt_id;
1095f10a77bbSDavid C Somayajulu 
1096f10a77bbSDavid C Somayajulu 	if (tenable) {
1097f10a77bbSDavid C Somayajulu 		intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC;
1098f10a77bbSDavid C Somayajulu 		intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC;
1099f10a77bbSDavid C Somayajulu 
1100f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
1101f10a77bbSDavid C Somayajulu 			intrc->sds_ring_mask |= (1 << i);
1102f10a77bbSDavid C Somayajulu 		}
1103f10a77bbSDavid C Somayajulu 		intrc->ms_timeout = 1000;
1104f10a77bbSDavid C Somayajulu 	}
1105f10a77bbSDavid C Somayajulu 
1106f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)intrc,
1107f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_intr_coalesc_t) >> 2),
1108f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) {
1109f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1110f10a77bbSDavid C Somayajulu 		return (-1);
1111f10a77bbSDavid C Somayajulu 	}
1112f10a77bbSDavid C Somayajulu 	intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox;
1113f10a77bbSDavid C Somayajulu 
1114f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status);
1115f10a77bbSDavid C Somayajulu 
1116f10a77bbSDavid C Somayajulu 	if (err) {
1117f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1118f10a77bbSDavid C Somayajulu 		return (-1);
1119f10a77bbSDavid C Somayajulu 	}
1120f10a77bbSDavid C Somayajulu 
1121f10a77bbSDavid C Somayajulu 	return 0;
1122f10a77bbSDavid C Somayajulu }
1123f10a77bbSDavid C Somayajulu 
1124f10a77bbSDavid C Somayajulu 
1125f10a77bbSDavid C Somayajulu /*
1126f10a77bbSDavid C Somayajulu  * Name: qla_config_mac_addr
1127f10a77bbSDavid C Somayajulu  * Function: binds a MAC address to the context/interface.
1128f10a77bbSDavid C Somayajulu  *	Can be unicast, multicast or broadcast.
1129f10a77bbSDavid C Somayajulu  */
1130f10a77bbSDavid C Somayajulu static int
1131da834d52SDavid C Somayajulu qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac,
1132da834d52SDavid C Somayajulu 	uint32_t num_mac)
1133f10a77bbSDavid C Somayajulu {
1134f10a77bbSDavid C Somayajulu 	q80_config_mac_addr_t		*cmac;
1135f10a77bbSDavid C Somayajulu 	q80_config_mac_addr_rsp_t	*cmac_rsp;
1136f10a77bbSDavid C Somayajulu 	uint32_t			err;
1137f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1138da834d52SDavid C Somayajulu 	int				i;
1139da834d52SDavid C Somayajulu 	uint8_t				*mac_cpy = mac_addr;
1140da834d52SDavid C Somayajulu 
1141da834d52SDavid C Somayajulu 	if (num_mac > Q8_MAX_MAC_ADDRS) {
1142da834d52SDavid C Somayajulu 		device_printf(dev, "%s: %s num_mac [0x%x] > Q8_MAX_MAC_ADDRS\n",
1143da834d52SDavid C Somayajulu 			__func__, (add_mac ? "Add" : "Del"), num_mac);
1144da834d52SDavid C Somayajulu 		return (-1);
1145da834d52SDavid C Somayajulu 	}
1146f10a77bbSDavid C Somayajulu 
1147f10a77bbSDavid C Somayajulu 	cmac = (q80_config_mac_addr_t *)ha->hw.mbox;
1148f10a77bbSDavid C Somayajulu 	bzero(cmac, (sizeof (q80_config_mac_addr_t)));
1149f10a77bbSDavid C Somayajulu 
1150f10a77bbSDavid C Somayajulu 	cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR;
1151f10a77bbSDavid C Somayajulu 	cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2;
1152f10a77bbSDavid C Somayajulu 	cmac->count_version |= Q8_MBX_CMD_VERSION;
1153f10a77bbSDavid C Somayajulu 
1154f10a77bbSDavid C Somayajulu 	if (add_mac)
1155f10a77bbSDavid C Somayajulu 		cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR;
1156f10a77bbSDavid C Somayajulu 	else
1157f10a77bbSDavid C Somayajulu 		cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR;
1158f10a77bbSDavid C Somayajulu 
1159f10a77bbSDavid C Somayajulu 	cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS;
1160f10a77bbSDavid C Somayajulu 
1161da834d52SDavid C Somayajulu 	cmac->nmac_entries = num_mac;
1162f10a77bbSDavid C Somayajulu 	cmac->cntxt_id = ha->hw.rcv_cntxt_id;
1163da834d52SDavid C Somayajulu 
1164da834d52SDavid C Somayajulu 	for (i = 0; i < num_mac; i++) {
1165da834d52SDavid C Somayajulu 		bcopy(mac_addr, cmac->mac_addr[i].addr, Q8_ETHER_ADDR_LEN);
1166da834d52SDavid C Somayajulu 		mac_addr = mac_addr + ETHER_ADDR_LEN;
1167da834d52SDavid C Somayajulu 	}
1168f10a77bbSDavid C Somayajulu 
1169f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)cmac,
1170f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_mac_addr_t) >> 2),
1171f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) {
1172f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: %s failed0\n", __func__,
1173f10a77bbSDavid C Somayajulu 			(add_mac ? "Add" : "Del"));
1174f10a77bbSDavid C Somayajulu 		return (-1);
1175f10a77bbSDavid C Somayajulu 	}
1176f10a77bbSDavid C Somayajulu 	cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox;
1177f10a77bbSDavid C Somayajulu 
1178f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status);
1179f10a77bbSDavid C Somayajulu 
1180f10a77bbSDavid C Somayajulu 	if (err) {
1181da834d52SDavid C Somayajulu 		device_printf(dev, "%s: %s failed1 [0x%08x]\n", __func__,
1182da834d52SDavid C Somayajulu 			(add_mac ? "Add" : "Del"), err);
1183da834d52SDavid C Somayajulu 		for (i = 0; i < num_mac; i++) {
1184da834d52SDavid C Somayajulu 			device_printf(dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
1185da834d52SDavid C Somayajulu 				__func__, mac_cpy[0], mac_cpy[1], mac_cpy[2],
1186da834d52SDavid C Somayajulu 				mac_cpy[3], mac_cpy[4], mac_cpy[5]);
1187da834d52SDavid C Somayajulu 			mac_cpy += ETHER_ADDR_LEN;
1188da834d52SDavid C Somayajulu 		}
1189f10a77bbSDavid C Somayajulu 		return (-1);
1190f10a77bbSDavid C Somayajulu 	}
1191f10a77bbSDavid C Somayajulu 
1192f10a77bbSDavid C Somayajulu 	return 0;
1193f10a77bbSDavid C Somayajulu }
1194f10a77bbSDavid C Somayajulu 
1195f10a77bbSDavid C Somayajulu 
1196f10a77bbSDavid C Somayajulu /*
1197f10a77bbSDavid C Somayajulu  * Name: qla_set_mac_rcv_mode
11986a62bec0SDavid C Somayajulu  * Function: Enable/Disable AllMulticast and Promiscous Modes.
1199f10a77bbSDavid C Somayajulu  */
1200f10a77bbSDavid C Somayajulu static int
1201f10a77bbSDavid C Somayajulu qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode)
1202f10a77bbSDavid C Somayajulu {
1203f10a77bbSDavid C Somayajulu 	q80_config_mac_rcv_mode_t	*rcv_mode;
1204f10a77bbSDavid C Somayajulu 	uint32_t			err;
1205f10a77bbSDavid C Somayajulu 	q80_config_mac_rcv_mode_rsp_t	*rcv_mode_rsp;
1206f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1207f10a77bbSDavid C Somayajulu 
1208f10a77bbSDavid C Somayajulu 	rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox;
1209f10a77bbSDavid C Somayajulu 	bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t)));
1210f10a77bbSDavid C Somayajulu 
1211f10a77bbSDavid C Somayajulu 	rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE;
1212f10a77bbSDavid C Somayajulu 	rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2;
1213f10a77bbSDavid C Somayajulu 	rcv_mode->count_version |= Q8_MBX_CMD_VERSION;
1214f10a77bbSDavid C Somayajulu 
1215f10a77bbSDavid C Somayajulu 	rcv_mode->mode = mode;
1216f10a77bbSDavid C Somayajulu 
1217f10a77bbSDavid C Somayajulu 	rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id;
1218f10a77bbSDavid C Somayajulu 
1219f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode,
1220f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_mac_rcv_mode_t) >> 2),
1221f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) {
1222f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1223f10a77bbSDavid C Somayajulu 		return (-1);
1224f10a77bbSDavid C Somayajulu 	}
1225f10a77bbSDavid C Somayajulu 	rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox;
1226f10a77bbSDavid C Somayajulu 
1227f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status);
1228f10a77bbSDavid C Somayajulu 
1229f10a77bbSDavid C Somayajulu 	if (err) {
1230f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1231f10a77bbSDavid C Somayajulu 		return (-1);
1232f10a77bbSDavid C Somayajulu 	}
1233f10a77bbSDavid C Somayajulu 
1234f10a77bbSDavid C Somayajulu 	return 0;
1235f10a77bbSDavid C Somayajulu }
1236f10a77bbSDavid C Somayajulu 
1237f10a77bbSDavid C Somayajulu int
1238f10a77bbSDavid C Somayajulu ql_set_promisc(qla_host_t *ha)
1239f10a77bbSDavid C Somayajulu {
1240f10a77bbSDavid C Somayajulu 	int ret;
1241f10a77bbSDavid C Somayajulu 
1242f10a77bbSDavid C Somayajulu 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1243f10a77bbSDavid C Somayajulu 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1244f10a77bbSDavid C Somayajulu 	return (ret);
1245f10a77bbSDavid C Somayajulu }
1246f10a77bbSDavid C Somayajulu 
124735291c22SDavid C Somayajulu void
124835291c22SDavid C Somayajulu qla_reset_promisc(qla_host_t *ha)
124935291c22SDavid C Somayajulu {
125035291c22SDavid C Somayajulu 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE;
125135291c22SDavid C Somayajulu 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
125235291c22SDavid C Somayajulu }
125335291c22SDavid C Somayajulu 
1254f10a77bbSDavid C Somayajulu int
1255f10a77bbSDavid C Somayajulu ql_set_allmulti(qla_host_t *ha)
1256f10a77bbSDavid C Somayajulu {
1257f10a77bbSDavid C Somayajulu 	int ret;
1258f10a77bbSDavid C Somayajulu 
1259f10a77bbSDavid C Somayajulu 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE;
1260f10a77bbSDavid C Somayajulu 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1261f10a77bbSDavid C Somayajulu 	return (ret);
1262f10a77bbSDavid C Somayajulu }
1263f10a77bbSDavid C Somayajulu 
126435291c22SDavid C Somayajulu void
126535291c22SDavid C Somayajulu qla_reset_allmulti(qla_host_t *ha)
126635291c22SDavid C Somayajulu {
126735291c22SDavid C Somayajulu 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE;
126835291c22SDavid C Somayajulu 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
126935291c22SDavid C Somayajulu }
1270f10a77bbSDavid C Somayajulu 
1271f10a77bbSDavid C Somayajulu /*
1272f10a77bbSDavid C Somayajulu  * Name: ql_set_max_mtu
1273f10a77bbSDavid C Somayajulu  * Function:
1274f10a77bbSDavid C Somayajulu  *	Sets the maximum transfer unit size for the specified rcv context.
1275f10a77bbSDavid C Somayajulu  */
1276f10a77bbSDavid C Somayajulu int
1277f10a77bbSDavid C Somayajulu ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id)
1278f10a77bbSDavid C Somayajulu {
1279f10a77bbSDavid C Somayajulu 	device_t		dev;
1280f10a77bbSDavid C Somayajulu 	q80_set_max_mtu_t	*max_mtu;
1281f10a77bbSDavid C Somayajulu 	q80_set_max_mtu_rsp_t	*max_mtu_rsp;
1282f10a77bbSDavid C Somayajulu 	uint32_t		err;
1283f10a77bbSDavid C Somayajulu 
1284f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1285f10a77bbSDavid C Somayajulu 
1286f10a77bbSDavid C Somayajulu 	max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox;
1287f10a77bbSDavid C Somayajulu 	bzero(max_mtu, (sizeof (q80_set_max_mtu_t)));
1288f10a77bbSDavid C Somayajulu 
1289f10a77bbSDavid C Somayajulu 	max_mtu->opcode = Q8_MBX_SET_MAX_MTU;
1290f10a77bbSDavid C Somayajulu 	max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2);
1291f10a77bbSDavid C Somayajulu 	max_mtu->count_version |= Q8_MBX_CMD_VERSION;
1292f10a77bbSDavid C Somayajulu 
1293f10a77bbSDavid C Somayajulu 	max_mtu->cntxt_id = cntxt_id;
1294f10a77bbSDavid C Somayajulu 	max_mtu->mtu = mtu;
1295f10a77bbSDavid C Somayajulu 
1296f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)max_mtu,
1297f10a77bbSDavid C Somayajulu 		(sizeof (q80_set_max_mtu_t) >> 2),
1298f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) {
1299f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1300f10a77bbSDavid C Somayajulu                 return -1;
1301f10a77bbSDavid C Somayajulu         }
1302f10a77bbSDavid C Somayajulu 
1303f10a77bbSDavid C Somayajulu 	max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox;
1304f10a77bbSDavid C Somayajulu 
1305f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status);
1306f10a77bbSDavid C Somayajulu 
1307f10a77bbSDavid C Somayajulu         if (err) {
1308f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1309f10a77bbSDavid C Somayajulu         }
1310f10a77bbSDavid C Somayajulu 
1311f10a77bbSDavid C Somayajulu 	return 0;
1312f10a77bbSDavid C Somayajulu }
1313f10a77bbSDavid C Somayajulu 
1314f10a77bbSDavid C Somayajulu static int
1315f10a77bbSDavid C Somayajulu qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id)
1316f10a77bbSDavid C Somayajulu {
1317f10a77bbSDavid C Somayajulu 	device_t		dev;
1318f10a77bbSDavid C Somayajulu 	q80_link_event_t	*lnk;
1319f10a77bbSDavid C Somayajulu 	q80_link_event_rsp_t	*lnk_rsp;
1320f10a77bbSDavid C Somayajulu 	uint32_t		err;
1321f10a77bbSDavid C Somayajulu 
1322f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1323f10a77bbSDavid C Somayajulu 
1324f10a77bbSDavid C Somayajulu 	lnk = (q80_link_event_t *)ha->hw.mbox;
1325f10a77bbSDavid C Somayajulu 	bzero(lnk, (sizeof (q80_link_event_t)));
1326f10a77bbSDavid C Somayajulu 
1327f10a77bbSDavid C Somayajulu 	lnk->opcode = Q8_MBX_LINK_EVENT_REQ;
1328f10a77bbSDavid C Somayajulu 	lnk->count_version = (sizeof (q80_link_event_t) >> 2);
1329f10a77bbSDavid C Somayajulu 	lnk->count_version |= Q8_MBX_CMD_VERSION;
1330f10a77bbSDavid C Somayajulu 
1331f10a77bbSDavid C Somayajulu 	lnk->cntxt_id = cntxt_id;
1332f10a77bbSDavid C Somayajulu 	lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC;
1333f10a77bbSDavid C Somayajulu 
1334f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2),
1335f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) {
1336f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1337f10a77bbSDavid C Somayajulu                 return -1;
1338f10a77bbSDavid C Somayajulu         }
1339f10a77bbSDavid C Somayajulu 
1340f10a77bbSDavid C Somayajulu 	lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox;
1341f10a77bbSDavid C Somayajulu 
1342f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status);
1343f10a77bbSDavid C Somayajulu 
1344f10a77bbSDavid C Somayajulu         if (err) {
1345f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1346f10a77bbSDavid C Somayajulu         }
1347f10a77bbSDavid C Somayajulu 
1348f10a77bbSDavid C Somayajulu 	return 0;
1349f10a77bbSDavid C Somayajulu }
1350f10a77bbSDavid C Somayajulu 
1351f10a77bbSDavid C Somayajulu static int
1352f10a77bbSDavid C Somayajulu qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id)
1353f10a77bbSDavid C Somayajulu {
1354f10a77bbSDavid C Somayajulu 	device_t		dev;
1355f10a77bbSDavid C Somayajulu 	q80_config_fw_lro_t	*fw_lro;
1356f10a77bbSDavid C Somayajulu 	q80_config_fw_lro_rsp_t	*fw_lro_rsp;
1357f10a77bbSDavid C Somayajulu 	uint32_t		err;
1358f10a77bbSDavid C Somayajulu 
1359f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1360f10a77bbSDavid C Somayajulu 
1361f10a77bbSDavid C Somayajulu 	fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox;
1362f10a77bbSDavid C Somayajulu 	bzero(fw_lro, sizeof(q80_config_fw_lro_t));
1363f10a77bbSDavid C Somayajulu 
1364f10a77bbSDavid C Somayajulu 	fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO;
1365f10a77bbSDavid C Somayajulu 	fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2);
1366f10a77bbSDavid C Somayajulu 	fw_lro->count_version |= Q8_MBX_CMD_VERSION;
1367f10a77bbSDavid C Somayajulu 
1368f10a77bbSDavid C Somayajulu 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK;
136935291c22SDavid C Somayajulu 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK;
1370f10a77bbSDavid C Somayajulu 
1371f10a77bbSDavid C Somayajulu 	fw_lro->cntxt_id = cntxt_id;
1372f10a77bbSDavid C Somayajulu 
1373f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)fw_lro,
1374f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_fw_lro_t) >> 2),
1375f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) {
1376f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
1377f10a77bbSDavid C Somayajulu 		return -1;
1378f10a77bbSDavid C Somayajulu 	}
1379f10a77bbSDavid C Somayajulu 
1380f10a77bbSDavid C Somayajulu 	fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox;
1381f10a77bbSDavid C Somayajulu 
1382f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status);
1383f10a77bbSDavid C Somayajulu 
1384f10a77bbSDavid C Somayajulu 	if (err) {
1385f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1386f10a77bbSDavid C Somayajulu 	}
1387f10a77bbSDavid C Somayajulu 
1388f10a77bbSDavid C Somayajulu 	return 0;
1389f10a77bbSDavid C Somayajulu }
1390f10a77bbSDavid C Somayajulu 
139100caeec7SDavid C Somayajulu static int
139200caeec7SDavid C Somayajulu qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode)
139300caeec7SDavid C Somayajulu {
139400caeec7SDavid C Somayajulu 	device_t                dev;
139500caeec7SDavid C Somayajulu 	q80_hw_config_t         *hw_config;
139600caeec7SDavid C Somayajulu 	q80_hw_config_rsp_t     *hw_config_rsp;
139700caeec7SDavid C Somayajulu 	uint32_t                err;
139800caeec7SDavid C Somayajulu 
139900caeec7SDavid C Somayajulu 	dev = ha->pci_dev;
140000caeec7SDavid C Somayajulu 
140100caeec7SDavid C Somayajulu 	hw_config = (q80_hw_config_t *)ha->hw.mbox;
140200caeec7SDavid C Somayajulu 	bzero(hw_config, sizeof (q80_hw_config_t));
140300caeec7SDavid C Somayajulu 
140400caeec7SDavid C Somayajulu 	hw_config->opcode = Q8_MBX_HW_CONFIG;
140500caeec7SDavid C Somayajulu 	hw_config->count_version = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE_COUNT;
140600caeec7SDavid C Somayajulu 	hw_config->count_version |= Q8_MBX_CMD_VERSION;
140700caeec7SDavid C Somayajulu 
140800caeec7SDavid C Somayajulu 	hw_config->cmd = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE;
140900caeec7SDavid C Somayajulu 
141000caeec7SDavid C Somayajulu 	hw_config->u.set_cam_search_mode.mode = search_mode;
141100caeec7SDavid C Somayajulu 
141200caeec7SDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
141300caeec7SDavid C Somayajulu 		(sizeof (q80_hw_config_t) >> 2),
141400caeec7SDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
141500caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
141600caeec7SDavid C Somayajulu 		return -1;
141700caeec7SDavid C Somayajulu 	}
141800caeec7SDavid C Somayajulu 	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
141900caeec7SDavid C Somayajulu 
142000caeec7SDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
142100caeec7SDavid C Somayajulu 
142200caeec7SDavid C Somayajulu 	if (err) {
142300caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
142400caeec7SDavid C Somayajulu 	}
142500caeec7SDavid C Somayajulu 
142600caeec7SDavid C Somayajulu 	return 0;
142700caeec7SDavid C Somayajulu }
142800caeec7SDavid C Somayajulu 
142900caeec7SDavid C Somayajulu static int
143000caeec7SDavid C Somayajulu qla_get_cam_search_mode(qla_host_t *ha)
143100caeec7SDavid C Somayajulu {
143200caeec7SDavid C Somayajulu 	device_t                dev;
143300caeec7SDavid C Somayajulu 	q80_hw_config_t         *hw_config;
143400caeec7SDavid C Somayajulu 	q80_hw_config_rsp_t     *hw_config_rsp;
143500caeec7SDavid C Somayajulu 	uint32_t                err;
143600caeec7SDavid C Somayajulu 
143700caeec7SDavid C Somayajulu 	dev = ha->pci_dev;
143800caeec7SDavid C Somayajulu 
143900caeec7SDavid C Somayajulu 	hw_config = (q80_hw_config_t *)ha->hw.mbox;
144000caeec7SDavid C Somayajulu 	bzero(hw_config, sizeof (q80_hw_config_t));
144100caeec7SDavid C Somayajulu 
144200caeec7SDavid C Somayajulu 	hw_config->opcode = Q8_MBX_HW_CONFIG;
144300caeec7SDavid C Somayajulu 	hw_config->count_version = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE_COUNT;
144400caeec7SDavid C Somayajulu 	hw_config->count_version |= Q8_MBX_CMD_VERSION;
144500caeec7SDavid C Somayajulu 
144600caeec7SDavid C Somayajulu 	hw_config->cmd = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE;
144700caeec7SDavid C Somayajulu 
144800caeec7SDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
144900caeec7SDavid C Somayajulu 		(sizeof (q80_hw_config_t) >> 2),
145000caeec7SDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
145100caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
145200caeec7SDavid C Somayajulu 		return -1;
145300caeec7SDavid C Somayajulu 	}
145400caeec7SDavid C Somayajulu 	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
145500caeec7SDavid C Somayajulu 
145600caeec7SDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
145700caeec7SDavid C Somayajulu 
145800caeec7SDavid C Somayajulu 	if (err) {
145900caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
146000caeec7SDavid C Somayajulu 	} else {
146100caeec7SDavid C Somayajulu 		device_printf(dev, "%s: cam search mode [0x%08x]\n", __func__,
146200caeec7SDavid C Somayajulu 			hw_config_rsp->u.get_cam_search_mode.mode);
146300caeec7SDavid C Somayajulu 	}
146400caeec7SDavid C Somayajulu 
146500caeec7SDavid C Somayajulu 	return 0;
146600caeec7SDavid C Somayajulu }
146700caeec7SDavid C Somayajulu 
146800caeec7SDavid C Somayajulu 
146900caeec7SDavid C Somayajulu 
1470f10a77bbSDavid C Somayajulu static void
147135291c22SDavid C Somayajulu qla_xmt_stats(qla_host_t *ha, q80_xmt_stats_t *xstat, int i)
1472f10a77bbSDavid C Somayajulu {
1473f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1474f10a77bbSDavid C Somayajulu 
147535291c22SDavid C Somayajulu 	if (i < ha->hw.num_tx_rings) {
147635291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: total_bytes\t\t%" PRIu64 "\n",
147735291c22SDavid C Somayajulu 			__func__, i, xstat->total_bytes);
147835291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: total_pkts\t\t%" PRIu64 "\n",
147935291c22SDavid C Somayajulu 			__func__, i, xstat->total_pkts);
148035291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: errors\t\t%" PRIu64 "\n",
148135291c22SDavid C Somayajulu 			__func__, i, xstat->errors);
148235291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: pkts_dropped\t%" PRIu64 "\n",
148335291c22SDavid C Somayajulu 			__func__, i, xstat->pkts_dropped);
148435291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: switch_pkts\t\t%" PRIu64 "\n",
148535291c22SDavid C Somayajulu 			__func__, i, xstat->switch_pkts);
148635291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: num_buffers\t\t%" PRIu64 "\n",
148735291c22SDavid C Somayajulu 			__func__, i, xstat->num_buffers);
148835291c22SDavid C Somayajulu 	} else {
148935291c22SDavid C Somayajulu 		device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n",
149035291c22SDavid C Somayajulu 			__func__, xstat->total_bytes);
149135291c22SDavid C Somayajulu 		device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n",
149235291c22SDavid C Somayajulu 			__func__, xstat->total_pkts);
149335291c22SDavid C Somayajulu 		device_printf(dev, "%s: errors\t\t\t%" PRIu64 "\n",
149435291c22SDavid C Somayajulu 			__func__, xstat->errors);
149535291c22SDavid C Somayajulu 		device_printf(dev, "%s: pkts_dropped\t\t\t%" PRIu64 "\n",
149635291c22SDavid C Somayajulu 			__func__, xstat->pkts_dropped);
149735291c22SDavid C Somayajulu 		device_printf(dev, "%s: switch_pkts\t\t\t%" PRIu64 "\n",
149835291c22SDavid C Somayajulu 			__func__, xstat->switch_pkts);
149935291c22SDavid C Somayajulu 		device_printf(dev, "%s: num_buffers\t\t\t%" PRIu64 "\n",
150035291c22SDavid C Somayajulu 			__func__, xstat->num_buffers);
150135291c22SDavid C Somayajulu 	}
1502f10a77bbSDavid C Somayajulu }
1503f10a77bbSDavid C Somayajulu 
1504f10a77bbSDavid C Somayajulu static void
1505f10a77bbSDavid C Somayajulu qla_rcv_stats(qla_host_t *ha, q80_rcv_stats_t *rstat)
1506f10a77bbSDavid C Somayajulu {
1507f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1508f10a77bbSDavid C Somayajulu 
1509f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n", __func__,
1510f10a77bbSDavid C Somayajulu 		rstat->total_bytes);
1511f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n", __func__,
1512f10a77bbSDavid C Somayajulu 		rstat->total_pkts);
1513f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_pkt_count\t\t%" PRIu64 "\n", __func__,
1514f10a77bbSDavid C Somayajulu 		rstat->lro_pkt_count);
151535291c22SDavid C Somayajulu 	device_printf(dev, "%s: sw_pkt_count\t\t\t%" PRIu64 "\n", __func__,
1516f10a77bbSDavid C Somayajulu 		rstat->sw_pkt_count);
1517f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: ip_chksum_err\t\t%" PRIu64 "\n", __func__,
1518f10a77bbSDavid C Somayajulu 		rstat->ip_chksum_err);
1519f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_wo_acntxts\t\t%" PRIu64 "\n", __func__,
1520f10a77bbSDavid C Somayajulu 		rstat->pkts_wo_acntxts);
1521f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_sds_card\t%" PRIu64 "\n",
1522f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_sds_card);
1523f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_sds_host\t%" PRIu64 "\n",
1524f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_sds_host);
1525f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: oversized_pkts\t\t%" PRIu64 "\n", __func__,
1526f10a77bbSDavid C Somayajulu 		rstat->oversized_pkts);
1527f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_rds\t\t%" PRIu64 "\n",
1528f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_rds);
1529f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: unxpctd_mcast_pkts\t\t%" PRIu64 "\n",
1530f10a77bbSDavid C Somayajulu 		__func__, rstat->unxpctd_mcast_pkts);
1531f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: re1_fbq_error\t\t%" PRIu64 "\n", __func__,
1532f10a77bbSDavid C Somayajulu 		rstat->re1_fbq_error);
1533f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: invalid_mac_addr\t\t%" PRIu64 "\n", __func__,
1534f10a77bbSDavid C Somayajulu 		rstat->invalid_mac_addr);
1535f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rds_prime_trys\t\t%" PRIu64 "\n", __func__,
1536f10a77bbSDavid C Somayajulu 		rstat->rds_prime_trys);
1537f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rds_prime_success\t\t%" PRIu64 "\n", __func__,
1538f10a77bbSDavid C Somayajulu 		rstat->rds_prime_success);
1539f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_added\t\t%" PRIu64 "\n", __func__,
1540f10a77bbSDavid C Somayajulu 		rstat->lro_flows_added);
1541f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_deleted\t\t%" PRIu64 "\n", __func__,
1542f10a77bbSDavid C Somayajulu 		rstat->lro_flows_deleted);
1543f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_active\t\t%" PRIu64 "\n", __func__,
1544f10a77bbSDavid C Somayajulu 		rstat->lro_flows_active);
1545f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_droped_unknown\t\t%" PRIu64 "\n",
1546f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_droped_unknown);
1547f10a77bbSDavid C Somayajulu }
1548f10a77bbSDavid C Somayajulu 
1549f10a77bbSDavid C Somayajulu static void
1550f10a77bbSDavid C Somayajulu qla_mac_stats(qla_host_t *ha, q80_mac_stats_t *mstat)
1551f10a77bbSDavid C Somayajulu {
1552f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1553f10a77bbSDavid C Somayajulu 
1554f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_frames\t\t\t%" PRIu64 "\n", __func__,
1555f10a77bbSDavid C Somayajulu 		mstat->xmt_frames);
1556f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_bytes\t\t\t%" PRIu64 "\n", __func__,
1557f10a77bbSDavid C Somayajulu 		mstat->xmt_bytes);
1558f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1559f10a77bbSDavid C Somayajulu 		mstat->xmt_mcast_pkts);
1560f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1561f10a77bbSDavid C Somayajulu 		mstat->xmt_bcast_pkts);
1562f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pause_frames\t\t%" PRIu64 "\n", __func__,
1563f10a77bbSDavid C Somayajulu 		mstat->xmt_pause_frames);
1564f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1565f10a77bbSDavid C Somayajulu 		mstat->xmt_cntrl_pkts);
1566f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1567f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_64bytes);
1568f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1569f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_127bytes);
1570f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1571f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_255bytes);
1572f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1573f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_511bytes);
157435291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_1023bytes\t\t%" PRIu64 "\n",
1575f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_1023bytes);
157635291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_1518bytes\t\t%" PRIu64 "\n",
1577f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_1518bytes);
157835291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_gt_1518bytes\t\t%" PRIu64 "\n",
1579f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_gt_1518bytes);
1580f10a77bbSDavid C Somayajulu 
1581f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_frames\t\t\t%" PRIu64 "\n", __func__,
1582f10a77bbSDavid C Somayajulu 		mstat->rcv_frames);
1583f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_bytes\t\t\t%" PRIu64 "\n", __func__,
1584f10a77bbSDavid C Somayajulu 		mstat->rcv_bytes);
1585f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1586f10a77bbSDavid C Somayajulu 		mstat->rcv_mcast_pkts);
1587f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1588f10a77bbSDavid C Somayajulu 		mstat->rcv_bcast_pkts);
1589f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pause_frames\t\t%" PRIu64 "\n", __func__,
1590f10a77bbSDavid C Somayajulu 		mstat->rcv_pause_frames);
1591f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1592f10a77bbSDavid C Somayajulu 		mstat->rcv_cntrl_pkts);
1593f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1594f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_64bytes);
1595f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1596f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_127bytes);
1597f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1598f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_255bytes);
1599f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1600f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_511bytes);
160135291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_1023bytes\t\t%" PRIu64 "\n",
1602f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_1023bytes);
160335291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_1518bytes\t\t%" PRIu64 "\n",
1604f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_1518bytes);
160535291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_gt_1518bytes\t\t%" PRIu64 "\n",
1606f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_gt_1518bytes);
1607f10a77bbSDavid C Somayajulu 
1608f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_error\t\t%" PRIu64 "\n", __func__,
1609f10a77bbSDavid C Somayajulu 		mstat->rcv_len_error);
1610f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_small\t\t%" PRIu64 "\n", __func__,
1611f10a77bbSDavid C Somayajulu 		mstat->rcv_len_small);
1612f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_large\t\t%" PRIu64 "\n", __func__,
1613f10a77bbSDavid C Somayajulu 		mstat->rcv_len_large);
1614f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_jabber\t\t\t%" PRIu64 "\n", __func__,
1615f10a77bbSDavid C Somayajulu 		mstat->rcv_jabber);
1616f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_dropped\t\t\t%" PRIu64 "\n", __func__,
1617f10a77bbSDavid C Somayajulu 		mstat->rcv_dropped);
1618f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: fcs_error\t\t\t%" PRIu64 "\n", __func__,
1619f10a77bbSDavid C Somayajulu 		mstat->fcs_error);
1620f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: align_error\t\t\t%" PRIu64 "\n", __func__,
1621f10a77bbSDavid C Somayajulu 		mstat->align_error);
1622f10a77bbSDavid C Somayajulu }
1623f10a77bbSDavid C Somayajulu 
1624f10a77bbSDavid C Somayajulu 
1625f10a77bbSDavid C Somayajulu static int
162635291c22SDavid C Somayajulu qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size)
1627f10a77bbSDavid C Somayajulu {
1628f10a77bbSDavid C Somayajulu 	device_t		dev;
1629f10a77bbSDavid C Somayajulu 	q80_get_stats_t		*stat;
1630f10a77bbSDavid C Somayajulu 	q80_get_stats_rsp_t	*stat_rsp;
1631f10a77bbSDavid C Somayajulu 	uint32_t		err;
1632f10a77bbSDavid C Somayajulu 
1633f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1634f10a77bbSDavid C Somayajulu 
1635f10a77bbSDavid C Somayajulu 	stat = (q80_get_stats_t *)ha->hw.mbox;
1636f10a77bbSDavid C Somayajulu 	bzero(stat, (sizeof (q80_get_stats_t)));
1637f10a77bbSDavid C Somayajulu 
1638f10a77bbSDavid C Somayajulu 	stat->opcode = Q8_MBX_GET_STATS;
1639f10a77bbSDavid C Somayajulu 	stat->count_version = 2;
1640f10a77bbSDavid C Somayajulu 	stat->count_version |= Q8_MBX_CMD_VERSION;
1641f10a77bbSDavid C Somayajulu 
1642f10a77bbSDavid C Somayajulu 	stat->cmd = cmd;
1643f10a77bbSDavid C Somayajulu 
1644f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)stat, 2,
164535291c22SDavid C Somayajulu                 ha->hw.mbox, (rsp_size >> 2), 0)) {
1646f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1647f10a77bbSDavid C Somayajulu                 return -1;
1648f10a77bbSDavid C Somayajulu         }
1649f10a77bbSDavid C Somayajulu 
1650f10a77bbSDavid C Somayajulu 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1651f10a77bbSDavid C Somayajulu 
1652f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status);
1653f10a77bbSDavid C Somayajulu 
1654f10a77bbSDavid C Somayajulu         if (err) {
1655f10a77bbSDavid C Somayajulu                 return -1;
1656f10a77bbSDavid C Somayajulu         }
1657f10a77bbSDavid C Somayajulu 
1658f10a77bbSDavid C Somayajulu 	return 0;
1659f10a77bbSDavid C Somayajulu }
1660f10a77bbSDavid C Somayajulu 
1661f10a77bbSDavid C Somayajulu void
1662f10a77bbSDavid C Somayajulu ql_get_stats(qla_host_t *ha)
1663f10a77bbSDavid C Somayajulu {
1664f10a77bbSDavid C Somayajulu 	q80_get_stats_rsp_t	*stat_rsp;
1665f10a77bbSDavid C Somayajulu 	q80_mac_stats_t		*mstat;
1666f10a77bbSDavid C Somayajulu 	q80_xmt_stats_t		*xstat;
1667f10a77bbSDavid C Somayajulu 	q80_rcv_stats_t		*rstat;
1668f10a77bbSDavid C Somayajulu 	uint32_t		cmd;
166935291c22SDavid C Somayajulu 	int			i;
1670f10a77bbSDavid C Somayajulu 
1671f10a77bbSDavid C Somayajulu 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1672f10a77bbSDavid C Somayajulu 	/*
1673f10a77bbSDavid C Somayajulu 	 * Get MAC Statistics
1674f10a77bbSDavid C Somayajulu 	 */
1675f10a77bbSDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_TYPE_MAC;
167635291c22SDavid C Somayajulu //	cmd |= Q8_GET_STATS_CMD_CLEAR;
1677f10a77bbSDavid C Somayajulu 
1678f10a77bbSDavid C Somayajulu 	cmd |= ((ha->pci_func & 0x1) << 16);
1679f10a77bbSDavid C Somayajulu 
168035291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
1681f10a77bbSDavid C Somayajulu 		mstat = (q80_mac_stats_t *)&stat_rsp->u.mac;
1682f10a77bbSDavid C Somayajulu 		qla_mac_stats(ha, mstat);
1683f10a77bbSDavid C Somayajulu 	} else {
1684f10a77bbSDavid C Somayajulu                 device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n",
1685f10a77bbSDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
1686f10a77bbSDavid C Somayajulu 	}
1687f10a77bbSDavid C Somayajulu 	/*
1688f10a77bbSDavid C Somayajulu 	 * Get RCV Statistics
1689f10a77bbSDavid C Somayajulu 	 */
1690f10a77bbSDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT;
169135291c22SDavid C Somayajulu //	cmd |= Q8_GET_STATS_CMD_CLEAR;
1692f10a77bbSDavid C Somayajulu 	cmd |= (ha->hw.rcv_cntxt_id << 16);
1693f10a77bbSDavid C Somayajulu 
169435291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
1695f10a77bbSDavid C Somayajulu 		rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv;
1696f10a77bbSDavid C Somayajulu 		qla_rcv_stats(ha, rstat);
1697f10a77bbSDavid C Somayajulu 	} else {
1698f10a77bbSDavid C Somayajulu                 device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n",
1699f10a77bbSDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
1700f10a77bbSDavid C Somayajulu 	}
1701f10a77bbSDavid C Somayajulu 	/*
1702f10a77bbSDavid C Somayajulu 	 * Get XMT Statistics
1703f10a77bbSDavid C Somayajulu 	 */
170435291c22SDavid C Somayajulu 	for (i = 0 ; i < ha->hw.num_tx_rings; i++) {
1705f10a77bbSDavid C Somayajulu 		cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT;
170635291c22SDavid C Somayajulu //		cmd |= Q8_GET_STATS_CMD_CLEAR;
170735291c22SDavid C Somayajulu 		cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16);
1708f10a77bbSDavid C Somayajulu 
170935291c22SDavid C Somayajulu 		if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t))
171035291c22SDavid C Somayajulu 			== 0) {
1711f10a77bbSDavid C Somayajulu 			xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt;
171235291c22SDavid C Somayajulu 			qla_xmt_stats(ha, xstat, i);
1713f10a77bbSDavid C Somayajulu 		} else {
1714f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n",
1715f10a77bbSDavid C Somayajulu 				__func__, ha->hw.mbox[0]);
1716f10a77bbSDavid C Somayajulu 		}
1717f10a77bbSDavid C Somayajulu 	}
171835291c22SDavid C Somayajulu 	return;
171935291c22SDavid C Somayajulu }
172035291c22SDavid C Somayajulu 
172135291c22SDavid C Somayajulu static void
172235291c22SDavid C Somayajulu qla_get_quick_stats(qla_host_t *ha)
172335291c22SDavid C Somayajulu {
172435291c22SDavid C Somayajulu 	q80_get_mac_rcv_xmt_stats_rsp_t *stat_rsp;
172535291c22SDavid C Somayajulu 	q80_mac_stats_t         *mstat;
172635291c22SDavid C Somayajulu 	q80_xmt_stats_t         *xstat;
172735291c22SDavid C Somayajulu 	q80_rcv_stats_t         *rstat;
172835291c22SDavid C Somayajulu 	uint32_t                cmd;
172935291c22SDavid C Somayajulu 
173035291c22SDavid C Somayajulu 	stat_rsp = (q80_get_mac_rcv_xmt_stats_rsp_t *)ha->hw.mbox;
173135291c22SDavid C Somayajulu 
173235291c22SDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_TYPE_ALL;
173335291c22SDavid C Somayajulu //      cmd |= Q8_GET_STATS_CMD_CLEAR;
173435291c22SDavid C Somayajulu 
173535291c22SDavid C Somayajulu //      cmd |= ((ha->pci_func & 0x3) << 16);
173635291c22SDavid C Somayajulu 	cmd |= (0xFFFF << 16);
173735291c22SDavid C Somayajulu 
173835291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd,
173935291c22SDavid C Somayajulu 			sizeof (q80_get_mac_rcv_xmt_stats_rsp_t)) == 0) {
174035291c22SDavid C Somayajulu 
174135291c22SDavid C Somayajulu 		mstat = (q80_mac_stats_t *)&stat_rsp->mac;
174235291c22SDavid C Somayajulu 		rstat = (q80_rcv_stats_t *)&stat_rsp->rcv;
174335291c22SDavid C Somayajulu 		xstat = (q80_xmt_stats_t *)&stat_rsp->xmt;
174435291c22SDavid C Somayajulu 		qla_mac_stats(ha, mstat);
174535291c22SDavid C Somayajulu 		qla_rcv_stats(ha, rstat);
174635291c22SDavid C Somayajulu 		qla_xmt_stats(ha, xstat, ha->hw.num_tx_rings);
174735291c22SDavid C Somayajulu 	} else {
174835291c22SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: failed [0x%08x]\n",
174935291c22SDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
175035291c22SDavid C Somayajulu 	}
175135291c22SDavid C Somayajulu 	return;
175235291c22SDavid C Somayajulu }
1753f10a77bbSDavid C Somayajulu 
1754f10a77bbSDavid C Somayajulu /*
1755f10a77bbSDavid C Somayajulu  * Name: qla_tx_tso
1756f10a77bbSDavid C Somayajulu  * Function: Checks if the packet to be transmitted is a candidate for
1757f10a77bbSDavid C Somayajulu  *	Large TCP Segment Offload. If yes, the appropriate fields in the Tx
1758f10a77bbSDavid C Somayajulu  *	Ring Structure are plugged in.
1759f10a77bbSDavid C Somayajulu  */
1760f10a77bbSDavid C Somayajulu static int
1761f10a77bbSDavid C Somayajulu qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
1762f10a77bbSDavid C Somayajulu {
1763f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1764f10a77bbSDavid C Somayajulu 	struct ip *ip = NULL;
1765f10a77bbSDavid C Somayajulu 	struct ip6_hdr *ip6 = NULL;
1766f10a77bbSDavid C Somayajulu 	struct tcphdr *th = NULL;
1767f10a77bbSDavid C Somayajulu 	uint32_t ehdrlen,  hdrlen, ip_hlen, tcp_hlen, tcp_opt_off;
1768f10a77bbSDavid C Somayajulu 	uint16_t etype, opcode, offload = 1;
1769f10a77bbSDavid C Somayajulu 	device_t dev;
1770f10a77bbSDavid C Somayajulu 
1771f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1772f10a77bbSDavid C Somayajulu 
1773f10a77bbSDavid C Somayajulu 
1774f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
1775f10a77bbSDavid C Somayajulu 
1776f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1777f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1778f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_proto);
1779f10a77bbSDavid C Somayajulu 	} else {
1780f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN;
1781f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_encap_proto);
1782f10a77bbSDavid C Somayajulu 	}
1783f10a77bbSDavid C Somayajulu 
1784f10a77bbSDavid C Somayajulu 	hdrlen = 0;
1785f10a77bbSDavid C Somayajulu 
1786f10a77bbSDavid C Somayajulu 	switch (etype) {
1787f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IP:
1788f10a77bbSDavid C Somayajulu 
1789f10a77bbSDavid C Somayajulu 			tcp_opt_off = ehdrlen + sizeof(struct ip) +
1790f10a77bbSDavid C Somayajulu 					sizeof(struct tcphdr);
1791f10a77bbSDavid C Somayajulu 
1792f10a77bbSDavid C Somayajulu 			if (mp->m_len < tcp_opt_off) {
1793f10a77bbSDavid C Somayajulu 				m_copydata(mp, 0, tcp_opt_off, hdr);
1794f10a77bbSDavid C Somayajulu 				ip = (struct ip *)(hdr + ehdrlen);
1795f10a77bbSDavid C Somayajulu 			} else {
1796f10a77bbSDavid C Somayajulu 				ip = (struct ip *)(mp->m_data + ehdrlen);
1797f10a77bbSDavid C Somayajulu 			}
1798f10a77bbSDavid C Somayajulu 
1799f10a77bbSDavid C Somayajulu 			ip_hlen = ip->ip_hl << 2;
1800f10a77bbSDavid C Somayajulu 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
1801f10a77bbSDavid C Somayajulu 
1802f10a77bbSDavid C Somayajulu 
1803f10a77bbSDavid C Somayajulu 			if ((ip->ip_p != IPPROTO_TCP) ||
1804f10a77bbSDavid C Somayajulu 				(ip_hlen != sizeof (struct ip))){
1805f10a77bbSDavid C Somayajulu 				/* IP Options are not supported */
1806f10a77bbSDavid C Somayajulu 
1807f10a77bbSDavid C Somayajulu 				offload = 0;
1808f10a77bbSDavid C Somayajulu 			} else
1809f10a77bbSDavid C Somayajulu 				th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
1810f10a77bbSDavid C Somayajulu 
1811f10a77bbSDavid C Somayajulu 		break;
1812f10a77bbSDavid C Somayajulu 
1813f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IPV6:
1814f10a77bbSDavid C Somayajulu 
1815f10a77bbSDavid C Somayajulu 			tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) +
1816f10a77bbSDavid C Somayajulu 					sizeof (struct tcphdr);
1817f10a77bbSDavid C Somayajulu 
1818f10a77bbSDavid C Somayajulu 			if (mp->m_len < tcp_opt_off) {
1819f10a77bbSDavid C Somayajulu 				m_copydata(mp, 0, tcp_opt_off, hdr);
1820f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)(hdr + ehdrlen);
1821f10a77bbSDavid C Somayajulu 			} else {
1822f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1823f10a77bbSDavid C Somayajulu 			}
1824f10a77bbSDavid C Somayajulu 
1825f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof(struct ip6_hdr);
1826f10a77bbSDavid C Somayajulu 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6;
1827f10a77bbSDavid C Somayajulu 
1828f10a77bbSDavid C Somayajulu 			if (ip6->ip6_nxt != IPPROTO_TCP) {
1829f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv6\n", __func__);
1830f10a77bbSDavid C Somayajulu 				offload = 0;
1831f10a77bbSDavid C Somayajulu 			} else
1832f10a77bbSDavid C Somayajulu 				th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
1833f10a77bbSDavid C Somayajulu 		break;
1834f10a77bbSDavid C Somayajulu 
1835f10a77bbSDavid C Somayajulu 		default:
1836f10a77bbSDavid C Somayajulu 			QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__));
1837f10a77bbSDavid C Somayajulu 			offload = 0;
1838f10a77bbSDavid C Somayajulu 		break;
1839f10a77bbSDavid C Somayajulu 	}
1840f10a77bbSDavid C Somayajulu 
1841f10a77bbSDavid C Somayajulu 	if (!offload)
1842f10a77bbSDavid C Somayajulu 		return (-1);
1843f10a77bbSDavid C Somayajulu 
1844f10a77bbSDavid C Somayajulu 	tcp_hlen = th->th_off << 2;
1845f10a77bbSDavid C Somayajulu 	hdrlen = ehdrlen + ip_hlen + tcp_hlen;
1846f10a77bbSDavid C Somayajulu 
1847f10a77bbSDavid C Somayajulu         if (mp->m_len < hdrlen) {
1848f10a77bbSDavid C Somayajulu                 if (mp->m_len < tcp_opt_off) {
1849f10a77bbSDavid C Somayajulu                         if (tcp_hlen > sizeof(struct tcphdr)) {
1850f10a77bbSDavid C Somayajulu                                 m_copydata(mp, tcp_opt_off,
1851f10a77bbSDavid C Somayajulu                                         (tcp_hlen - sizeof(struct tcphdr)),
1852f10a77bbSDavid C Somayajulu                                         &hdr[tcp_opt_off]);
1853f10a77bbSDavid C Somayajulu                         }
1854f10a77bbSDavid C Somayajulu                 } else {
1855f10a77bbSDavid C Somayajulu                         m_copydata(mp, 0, hdrlen, hdr);
1856f10a77bbSDavid C Somayajulu                 }
1857f10a77bbSDavid C Somayajulu         }
1858f10a77bbSDavid C Somayajulu 
1859f10a77bbSDavid C Somayajulu 	tx_cmd->mss = mp->m_pkthdr.tso_segsz;
1860f10a77bbSDavid C Somayajulu 
1861f10a77bbSDavid C Somayajulu 	tx_cmd->flags_opcode = opcode ;
1862f10a77bbSDavid C Somayajulu 	tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen;
1863f10a77bbSDavid C Somayajulu 	tx_cmd->total_hdr_len = hdrlen;
1864f10a77bbSDavid C Somayajulu 
1865f10a77bbSDavid C Somayajulu 	/* Check for Multicast least significant bit of MSB == 1 */
1866f10a77bbSDavid C Somayajulu 	if (eh->evl_dhost[0] & 0x01) {
1867f10a77bbSDavid C Somayajulu 		tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST;
1868f10a77bbSDavid C Somayajulu 	}
1869f10a77bbSDavid C Somayajulu 
1870f10a77bbSDavid C Somayajulu 	if (mp->m_len < hdrlen) {
1871f10a77bbSDavid C Somayajulu 		printf("%d\n", hdrlen);
1872f10a77bbSDavid C Somayajulu 		return (1);
1873f10a77bbSDavid C Somayajulu 	}
1874f10a77bbSDavid C Somayajulu 
1875f10a77bbSDavid C Somayajulu 	return (0);
1876f10a77bbSDavid C Somayajulu }
1877f10a77bbSDavid C Somayajulu 
1878f10a77bbSDavid C Somayajulu /*
1879f10a77bbSDavid C Somayajulu  * Name: qla_tx_chksum
1880f10a77bbSDavid C Somayajulu  * Function: Checks if the packet to be transmitted is a candidate for
1881f10a77bbSDavid C Somayajulu  *	TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx
1882f10a77bbSDavid C Somayajulu  *	Ring Structure are plugged in.
1883f10a77bbSDavid C Somayajulu  */
1884f10a77bbSDavid C Somayajulu static int
1885f10a77bbSDavid C Somayajulu qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code,
1886f10a77bbSDavid C Somayajulu 	uint32_t *tcp_hdr_off)
1887f10a77bbSDavid C Somayajulu {
1888f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1889f10a77bbSDavid C Somayajulu 	struct ip *ip;
1890f10a77bbSDavid C Somayajulu 	struct ip6_hdr *ip6;
1891f10a77bbSDavid C Somayajulu 	uint32_t ehdrlen, ip_hlen;
1892f10a77bbSDavid C Somayajulu 	uint16_t etype, opcode, offload = 1;
1893f10a77bbSDavid C Somayajulu 	device_t dev;
1894f10a77bbSDavid C Somayajulu 	uint8_t buf[sizeof(struct ip6_hdr)];
1895f10a77bbSDavid C Somayajulu 
1896f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1897f10a77bbSDavid C Somayajulu 
1898f10a77bbSDavid C Somayajulu 	*op_code = 0;
1899f10a77bbSDavid C Somayajulu 
1900f10a77bbSDavid C Somayajulu 	if ((mp->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) == 0)
1901f10a77bbSDavid C Somayajulu 		return (-1);
1902f10a77bbSDavid C Somayajulu 
1903f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
1904f10a77bbSDavid C Somayajulu 
1905f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1906f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1907f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_proto);
1908f10a77bbSDavid C Somayajulu 	} else {
1909f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN;
1910f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_encap_proto);
1911f10a77bbSDavid C Somayajulu 	}
1912f10a77bbSDavid C Somayajulu 
1913f10a77bbSDavid C Somayajulu 
1914f10a77bbSDavid C Somayajulu 	switch (etype) {
1915f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IP:
1916f10a77bbSDavid C Somayajulu 			ip = (struct ip *)(mp->m_data + ehdrlen);
1917f10a77bbSDavid C Somayajulu 
1918f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof (struct ip);
1919f10a77bbSDavid C Somayajulu 
1920f10a77bbSDavid C Somayajulu 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1921f10a77bbSDavid C Somayajulu 				m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
1922f10a77bbSDavid C Somayajulu 				ip = (struct ip *)buf;
1923f10a77bbSDavid C Somayajulu 			}
1924f10a77bbSDavid C Somayajulu 
1925f10a77bbSDavid C Somayajulu 			if (ip->ip_p == IPPROTO_TCP)
1926f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM;
1927f10a77bbSDavid C Somayajulu 			else if (ip->ip_p == IPPROTO_UDP)
1928f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM;
1929f10a77bbSDavid C Somayajulu 			else {
1930f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv4\n", __func__);
1931f10a77bbSDavid C Somayajulu 				offload = 0;
1932f10a77bbSDavid C Somayajulu 			}
1933f10a77bbSDavid C Somayajulu 		break;
1934f10a77bbSDavid C Somayajulu 
1935f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IPV6:
1936f10a77bbSDavid C Somayajulu 			ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1937f10a77bbSDavid C Somayajulu 
1938f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof(struct ip6_hdr);
1939f10a77bbSDavid C Somayajulu 
1940f10a77bbSDavid C Somayajulu 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1941f10a77bbSDavid C Somayajulu 				m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
1942f10a77bbSDavid C Somayajulu 					buf);
1943f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)buf;
1944f10a77bbSDavid C Somayajulu 			}
1945f10a77bbSDavid C Somayajulu 
1946f10a77bbSDavid C Somayajulu 			if (ip6->ip6_nxt == IPPROTO_TCP)
1947f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6;
1948f10a77bbSDavid C Somayajulu 			else if (ip6->ip6_nxt == IPPROTO_UDP)
1949f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6;
1950f10a77bbSDavid C Somayajulu 			else {
1951f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv6\n", __func__);
1952f10a77bbSDavid C Somayajulu 				offload = 0;
1953f10a77bbSDavid C Somayajulu 			}
1954f10a77bbSDavid C Somayajulu 		break;
1955f10a77bbSDavid C Somayajulu 
1956f10a77bbSDavid C Somayajulu 		default:
1957f10a77bbSDavid C Somayajulu 			offload = 0;
1958f10a77bbSDavid C Somayajulu 		break;
1959f10a77bbSDavid C Somayajulu 	}
1960f10a77bbSDavid C Somayajulu 	if (!offload)
1961f10a77bbSDavid C Somayajulu 		return (-1);
1962f10a77bbSDavid C Somayajulu 
1963f10a77bbSDavid C Somayajulu 	*op_code = opcode;
1964f10a77bbSDavid C Somayajulu 	*tcp_hdr_off = (ip_hlen + ehdrlen);
1965f10a77bbSDavid C Somayajulu 
1966f10a77bbSDavid C Somayajulu 	return (0);
1967f10a77bbSDavid C Somayajulu }
1968f10a77bbSDavid C Somayajulu 
1969f10a77bbSDavid C Somayajulu #define QLA_TX_MIN_FREE 2
1970f10a77bbSDavid C Somayajulu /*
1971f10a77bbSDavid C Somayajulu  * Name: ql_hw_send
1972f10a77bbSDavid C Somayajulu  * Function: Transmits a packet. It first checks if the packet is a
1973f10a77bbSDavid C Somayajulu  *	candidate for Large TCP Segment Offload and then for UDP/TCP checksum
1974f10a77bbSDavid C Somayajulu  *	offload. If either of these creteria are not met, it is transmitted
1975f10a77bbSDavid C Somayajulu  *	as a regular ethernet frame.
1976f10a77bbSDavid C Somayajulu  */
1977f10a77bbSDavid C Somayajulu int
1978f10a77bbSDavid C Somayajulu ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
197935291c22SDavid C Somayajulu 	uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu)
1980f10a77bbSDavid C Somayajulu {
1981f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1982f10a77bbSDavid C Somayajulu 	qla_hw_t *hw = &ha->hw;
1983f10a77bbSDavid C Somayajulu 	q80_tx_cmd_t *tx_cmd, tso_cmd;
1984f10a77bbSDavid C Somayajulu 	bus_dma_segment_t *c_seg;
1985f10a77bbSDavid C Somayajulu 	uint32_t num_tx_cmds, hdr_len = 0;
1986f10a77bbSDavid C Somayajulu 	uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next;
1987f10a77bbSDavid C Somayajulu 	device_t dev;
1988f10a77bbSDavid C Somayajulu 	int i, ret;
1989f10a77bbSDavid C Somayajulu 	uint8_t *src = NULL, *dst = NULL;
1990f10a77bbSDavid C Somayajulu 	uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
1991f10a77bbSDavid C Somayajulu 	uint32_t op_code = 0;
1992f10a77bbSDavid C Somayajulu 	uint32_t tcp_hdr_off = 0;
1993f10a77bbSDavid C Somayajulu 
1994f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1995f10a77bbSDavid C Somayajulu 
1996f10a77bbSDavid C Somayajulu 	/*
1997f10a77bbSDavid C Somayajulu 	 * Always make sure there is atleast one empty slot in the tx_ring
1998f10a77bbSDavid C Somayajulu 	 * tx_ring is considered full when there only one entry available
1999f10a77bbSDavid C Somayajulu 	 */
2000f10a77bbSDavid C Somayajulu         num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2;
2001f10a77bbSDavid C Somayajulu 
2002f10a77bbSDavid C Somayajulu 	total_length = mp->m_pkthdr.len;
2003f10a77bbSDavid C Somayajulu 	if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
2004f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
2005f10a77bbSDavid C Somayajulu 			__func__, total_length);
2006f10a77bbSDavid C Somayajulu 		return (-1);
2007f10a77bbSDavid C Somayajulu 	}
2008f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
2009f10a77bbSDavid C Somayajulu 
2010f10a77bbSDavid C Somayajulu 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2011f10a77bbSDavid C Somayajulu 
2012f10a77bbSDavid C Somayajulu 		bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
2013f10a77bbSDavid C Somayajulu 
2014f10a77bbSDavid C Somayajulu 		src = frame_hdr;
2015f10a77bbSDavid C Somayajulu 		ret = qla_tx_tso(ha, mp, &tso_cmd, src);
2016f10a77bbSDavid C Somayajulu 
2017f10a77bbSDavid C Somayajulu 		if (!(ret & ~1)) {
2018f10a77bbSDavid C Somayajulu 			/* find the additional tx_cmd descriptors required */
2019f10a77bbSDavid C Somayajulu 
2020f10a77bbSDavid C Somayajulu 			if (mp->m_flags & M_VLANTAG)
2021f10a77bbSDavid C Somayajulu 				tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN;
2022f10a77bbSDavid C Somayajulu 
2023f10a77bbSDavid C Somayajulu 			hdr_len = tso_cmd.total_hdr_len;
2024f10a77bbSDavid C Somayajulu 
2025f10a77bbSDavid C Somayajulu 			bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2026f10a77bbSDavid C Somayajulu 			bytes = QL_MIN(bytes, hdr_len);
2027f10a77bbSDavid C Somayajulu 
2028f10a77bbSDavid C Somayajulu 			num_tx_cmds++;
2029f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2030f10a77bbSDavid C Somayajulu 
2031f10a77bbSDavid C Somayajulu 			while (hdr_len) {
2032f10a77bbSDavid C Somayajulu 				bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2033f10a77bbSDavid C Somayajulu 				hdr_len -= bytes;
2034f10a77bbSDavid C Somayajulu 				num_tx_cmds++;
2035f10a77bbSDavid C Somayajulu 			}
2036f10a77bbSDavid C Somayajulu 			hdr_len = tso_cmd.total_hdr_len;
2037f10a77bbSDavid C Somayajulu 
2038f10a77bbSDavid C Somayajulu 			if (ret == 0)
2039f10a77bbSDavid C Somayajulu 				src = (uint8_t *)eh;
2040f10a77bbSDavid C Somayajulu 		} else
2041f10a77bbSDavid C Somayajulu 			return (EINVAL);
2042f10a77bbSDavid C Somayajulu 	} else {
2043f10a77bbSDavid C Somayajulu 		(void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off);
2044f10a77bbSDavid C Somayajulu 	}
2045f10a77bbSDavid C Somayajulu 
204635291c22SDavid C Somayajulu 	if (iscsi_pdu)
204735291c22SDavid C Somayajulu 		ha->hw.iscsi_pkt_count++;
204835291c22SDavid C Somayajulu 
2049f10a77bbSDavid C Somayajulu 	if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
2050f10a77bbSDavid C Somayajulu 		qla_hw_tx_done_locked(ha, txr_idx);
2051f10a77bbSDavid C Somayajulu 		if (hw->tx_cntxt[txr_idx].txr_free <=
2052f10a77bbSDavid C Somayajulu 				(num_tx_cmds + QLA_TX_MIN_FREE)) {
2053f10a77bbSDavid C Somayajulu         		QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= "
2054f10a77bbSDavid C Somayajulu 				"(num_tx_cmds + QLA_TX_MIN_FREE))\n",
2055f10a77bbSDavid C Somayajulu 				__func__));
2056f10a77bbSDavid C Somayajulu 			return (-1);
2057f10a77bbSDavid C Somayajulu 		}
2058f10a77bbSDavid C Somayajulu 	}
2059f10a77bbSDavid C Somayajulu 
2060f10a77bbSDavid C Somayajulu 	tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx];
2061f10a77bbSDavid C Somayajulu 
2062f10a77bbSDavid C Somayajulu         if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) {
2063f10a77bbSDavid C Somayajulu 
2064f10a77bbSDavid C Somayajulu                 if (nsegs > ha->hw.max_tx_segs)
2065f10a77bbSDavid C Somayajulu                         ha->hw.max_tx_segs = nsegs;
2066f10a77bbSDavid C Somayajulu 
2067f10a77bbSDavid C Somayajulu                 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2068f10a77bbSDavid C Somayajulu 
2069f10a77bbSDavid C Somayajulu                 if (op_code) {
2070f10a77bbSDavid C Somayajulu                         tx_cmd->flags_opcode = op_code;
2071f10a77bbSDavid C Somayajulu                         tx_cmd->tcp_hdr_off = tcp_hdr_off;
2072f10a77bbSDavid C Somayajulu 
2073f10a77bbSDavid C Somayajulu                 } else {
2074f10a77bbSDavid C Somayajulu                         tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER;
2075f10a77bbSDavid C Somayajulu                 }
2076f10a77bbSDavid C Somayajulu 	} else {
2077f10a77bbSDavid C Somayajulu 		bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
2078f10a77bbSDavid C Somayajulu 		ha->tx_tso_frames++;
2079f10a77bbSDavid C Somayajulu 	}
2080f10a77bbSDavid C Somayajulu 
2081f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2082f10a77bbSDavid C Somayajulu         	tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
208335291c22SDavid C Somayajulu 
208435291c22SDavid C Somayajulu 		if (iscsi_pdu)
208535291c22SDavid C Somayajulu 			eh->evl_tag |= ha->hw.user_pri_iscsi << 13;
208635291c22SDavid C Somayajulu 
2087f10a77bbSDavid C Somayajulu 	} else if (mp->m_flags & M_VLANTAG) {
2088f10a77bbSDavid C Somayajulu 
2089f10a77bbSDavid C Somayajulu 		if (hdr_len) { /* TSO */
2090f10a77bbSDavid C Somayajulu 			tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED |
2091f10a77bbSDavid C Somayajulu 						Q8_TX_CMD_FLAGS_HW_VLAN_ID);
2092f10a77bbSDavid C Somayajulu 			tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN;
2093f10a77bbSDavid C Somayajulu 		} else
2094f10a77bbSDavid C Somayajulu 			tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID;
2095f10a77bbSDavid C Somayajulu 
2096f10a77bbSDavid C Somayajulu 		ha->hw_vlan_tx_frames++;
2097f10a77bbSDavid C Somayajulu 		tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag;
209835291c22SDavid C Somayajulu 
209935291c22SDavid C Somayajulu 		if (iscsi_pdu) {
210035291c22SDavid C Somayajulu 			tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13;
210135291c22SDavid C Somayajulu 			mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci;
210235291c22SDavid C Somayajulu 		}
2103f10a77bbSDavid C Somayajulu 	}
2104f10a77bbSDavid C Somayajulu 
2105f10a77bbSDavid C Somayajulu 
2106f10a77bbSDavid C Somayajulu         tx_cmd->n_bufs = (uint8_t)nsegs;
2107f10a77bbSDavid C Somayajulu         tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF);
2108f10a77bbSDavid C Somayajulu         tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8)));
2109f10a77bbSDavid C Somayajulu 	tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func);
2110f10a77bbSDavid C Somayajulu 
2111f10a77bbSDavid C Somayajulu 	c_seg = segs;
2112f10a77bbSDavid C Somayajulu 
2113f10a77bbSDavid C Somayajulu 	while (1) {
2114f10a77bbSDavid C Somayajulu 		for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) {
2115f10a77bbSDavid C Somayajulu 
2116f10a77bbSDavid C Somayajulu 			switch (i) {
2117f10a77bbSDavid C Somayajulu 			case 0:
2118f10a77bbSDavid C Somayajulu 				tx_cmd->buf1_addr = c_seg->ds_addr;
2119f10a77bbSDavid C Somayajulu 				tx_cmd->buf1_len = c_seg->ds_len;
2120f10a77bbSDavid C Somayajulu 				break;
2121f10a77bbSDavid C Somayajulu 
2122f10a77bbSDavid C Somayajulu 			case 1:
2123f10a77bbSDavid C Somayajulu 				tx_cmd->buf2_addr = c_seg->ds_addr;
2124f10a77bbSDavid C Somayajulu 				tx_cmd->buf2_len = c_seg->ds_len;
2125f10a77bbSDavid C Somayajulu 				break;
2126f10a77bbSDavid C Somayajulu 
2127f10a77bbSDavid C Somayajulu 			case 2:
2128f10a77bbSDavid C Somayajulu 				tx_cmd->buf3_addr = c_seg->ds_addr;
2129f10a77bbSDavid C Somayajulu 				tx_cmd->buf3_len = c_seg->ds_len;
2130f10a77bbSDavid C Somayajulu 				break;
2131f10a77bbSDavid C Somayajulu 
2132f10a77bbSDavid C Somayajulu 			case 3:
2133f10a77bbSDavid C Somayajulu 				tx_cmd->buf4_addr = c_seg->ds_addr;
2134f10a77bbSDavid C Somayajulu 				tx_cmd->buf4_len = c_seg->ds_len;
2135f10a77bbSDavid C Somayajulu 				break;
2136f10a77bbSDavid C Somayajulu 			}
2137f10a77bbSDavid C Somayajulu 
2138f10a77bbSDavid C Somayajulu 			c_seg++;
2139f10a77bbSDavid C Somayajulu 			nsegs--;
2140f10a77bbSDavid C Somayajulu 		}
2141f10a77bbSDavid C Somayajulu 
2142f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2143f10a77bbSDavid C Somayajulu 			(hw->tx_cntxt[txr_idx].txr_next + 1) &
2144f10a77bbSDavid C Somayajulu 				(NUM_TX_DESCRIPTORS - 1);
2145f10a77bbSDavid C Somayajulu 		tx_cmd_count++;
2146f10a77bbSDavid C Somayajulu 
2147f10a77bbSDavid C Somayajulu 		if (!nsegs)
2148f10a77bbSDavid C Somayajulu 			break;
2149f10a77bbSDavid C Somayajulu 
2150f10a77bbSDavid C Somayajulu 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2151f10a77bbSDavid C Somayajulu 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2152f10a77bbSDavid C Somayajulu 	}
2153f10a77bbSDavid C Somayajulu 
2154f10a77bbSDavid C Somayajulu 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2155f10a77bbSDavid C Somayajulu 
2156f10a77bbSDavid C Somayajulu 		/* TSO : Copy the header in the following tx cmd descriptors */
2157f10a77bbSDavid C Somayajulu 
2158f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next;
2159f10a77bbSDavid C Somayajulu 
2160f10a77bbSDavid C Somayajulu 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2161f10a77bbSDavid C Somayajulu 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2162f10a77bbSDavid C Somayajulu 
2163f10a77bbSDavid C Somayajulu 		bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2164f10a77bbSDavid C Somayajulu 		bytes = QL_MIN(bytes, hdr_len);
2165f10a77bbSDavid C Somayajulu 
2166f10a77bbSDavid C Somayajulu 		dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN;
2167f10a77bbSDavid C Somayajulu 
2168f10a77bbSDavid C Somayajulu 		if (mp->m_flags & M_VLANTAG) {
2169f10a77bbSDavid C Somayajulu 			/* first copy the src/dst MAC addresses */
2170f10a77bbSDavid C Somayajulu 			bcopy(src, dst, (ETHER_ADDR_LEN * 2));
2171f10a77bbSDavid C Somayajulu 			dst += (ETHER_ADDR_LEN * 2);
2172f10a77bbSDavid C Somayajulu 			src += (ETHER_ADDR_LEN * 2);
2173f10a77bbSDavid C Somayajulu 
2174f10a77bbSDavid C Somayajulu 			*((uint16_t *)dst) = htons(ETHERTYPE_VLAN);
2175f10a77bbSDavid C Somayajulu 			dst += 2;
2176f10a77bbSDavid C Somayajulu 			*((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag);
2177f10a77bbSDavid C Somayajulu 			dst += 2;
2178f10a77bbSDavid C Somayajulu 
2179f10a77bbSDavid C Somayajulu 			/* bytes left in src header */
2180f10a77bbSDavid C Somayajulu 			hdr_len -= ((ETHER_ADDR_LEN * 2) +
2181f10a77bbSDavid C Somayajulu 					ETHER_VLAN_ENCAP_LEN);
2182f10a77bbSDavid C Somayajulu 
2183f10a77bbSDavid C Somayajulu 			/* bytes left in TxCmd Entry */
2184f10a77bbSDavid C Somayajulu 			bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN);
2185f10a77bbSDavid C Somayajulu 
2186f10a77bbSDavid C Somayajulu 
2187f10a77bbSDavid C Somayajulu 			bcopy(src, dst, bytes);
2188f10a77bbSDavid C Somayajulu 			src += bytes;
2189f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2190f10a77bbSDavid C Somayajulu 		} else {
2191f10a77bbSDavid C Somayajulu 			bcopy(src, dst, bytes);
2192f10a77bbSDavid C Somayajulu 			src += bytes;
2193f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2194f10a77bbSDavid C Somayajulu 		}
2195f10a77bbSDavid C Somayajulu 
2196f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2197f10a77bbSDavid C Somayajulu 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2198f10a77bbSDavid C Somayajulu 					(NUM_TX_DESCRIPTORS - 1);
2199f10a77bbSDavid C Somayajulu 		tx_cmd_count++;
2200f10a77bbSDavid C Somayajulu 
2201f10a77bbSDavid C Somayajulu 		while (hdr_len) {
2202f10a77bbSDavid C Somayajulu 			tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2203f10a77bbSDavid C Somayajulu 			bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2204f10a77bbSDavid C Somayajulu 
2205f10a77bbSDavid C Somayajulu 			bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2206f10a77bbSDavid C Somayajulu 
2207f10a77bbSDavid C Somayajulu 			bcopy(src, tx_cmd, bytes);
2208f10a77bbSDavid C Somayajulu 			src += bytes;
2209f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2210f10a77bbSDavid C Somayajulu 
2211f10a77bbSDavid C Somayajulu 			txr_next = hw->tx_cntxt[txr_idx].txr_next =
2212f10a77bbSDavid C Somayajulu 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2213f10a77bbSDavid C Somayajulu 					(NUM_TX_DESCRIPTORS - 1);
2214f10a77bbSDavid C Somayajulu 			tx_cmd_count++;
2215f10a77bbSDavid C Somayajulu 		}
2216f10a77bbSDavid C Somayajulu 	}
2217f10a77bbSDavid C Somayajulu 
2218f10a77bbSDavid C Somayajulu 	hw->tx_cntxt[txr_idx].txr_free =
2219f10a77bbSDavid C Somayajulu 		hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count;
2220f10a77bbSDavid C Somayajulu 
2221f10a77bbSDavid C Somayajulu 	QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\
2222f10a77bbSDavid C Somayajulu 		txr_idx);
2223f10a77bbSDavid C Somayajulu        	QL_DPRINT8(ha, (dev, "%s: return\n", __func__));
2224f10a77bbSDavid C Somayajulu 
2225f10a77bbSDavid C Somayajulu 	return (0);
2226f10a77bbSDavid C Somayajulu }
2227f10a77bbSDavid C Somayajulu 
2228f10a77bbSDavid C Somayajulu 
222935291c22SDavid C Somayajulu 
223035291c22SDavid C Somayajulu #define Q8_CONFIG_IND_TBL_SIZE	32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */
2231f10a77bbSDavid C Somayajulu static int
2232f10a77bbSDavid C Somayajulu qla_config_rss_ind_table(qla_host_t *ha)
2233f10a77bbSDavid C Somayajulu {
2234f10a77bbSDavid C Somayajulu 	uint32_t i, count;
223535291c22SDavid C Somayajulu 	uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE];
2236f10a77bbSDavid C Somayajulu 
2237f10a77bbSDavid C Somayajulu 
223835291c22SDavid C Somayajulu 	for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) {
2239f10a77bbSDavid C Somayajulu 		rss_ind_tbl[i] = i % ha->hw.num_sds_rings;
2240f10a77bbSDavid C Somayajulu 	}
2241f10a77bbSDavid C Somayajulu 
224235291c22SDavid C Somayajulu 	for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ;
224335291c22SDavid C Somayajulu 		i = i + Q8_CONFIG_IND_TBL_SIZE) {
2244f10a77bbSDavid C Somayajulu 
224535291c22SDavid C Somayajulu 		if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) {
2246f10a77bbSDavid C Somayajulu 			count = Q8_RSS_IND_TBL_MAX_IDX - i + 1;
2247f10a77bbSDavid C Somayajulu 		} else {
224835291c22SDavid C Somayajulu 			count = Q8_CONFIG_IND_TBL_SIZE;
2249f10a77bbSDavid C Somayajulu 		}
2250f10a77bbSDavid C Somayajulu 
2251f10a77bbSDavid C Somayajulu 		if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id,
2252f10a77bbSDavid C Somayajulu 			rss_ind_tbl))
2253f10a77bbSDavid C Somayajulu 			return (-1);
2254f10a77bbSDavid C Somayajulu 	}
2255f10a77bbSDavid C Somayajulu 
2256f10a77bbSDavid C Somayajulu 	return (0);
2257f10a77bbSDavid C Somayajulu }
2258f10a77bbSDavid C Somayajulu 
2259f10a77bbSDavid C Somayajulu /*
2260f10a77bbSDavid C Somayajulu  * Name: ql_del_hw_if
2261f10a77bbSDavid C Somayajulu  * Function: Destroys the hardware specific entities corresponding to an
2262f10a77bbSDavid C Somayajulu  *	Ethernet Interface
2263f10a77bbSDavid C Somayajulu  */
2264f10a77bbSDavid C Somayajulu void
2265f10a77bbSDavid C Somayajulu ql_del_hw_if(qla_host_t *ha)
2266f10a77bbSDavid C Somayajulu {
226735291c22SDavid C Somayajulu 	uint32_t i;
226835291c22SDavid C Somayajulu 	uint32_t num_msix;
226935291c22SDavid C Somayajulu 
227035291c22SDavid C Somayajulu 	(void)qla_stop_nic_func(ha);
2271f10a77bbSDavid C Somayajulu 
2272f10a77bbSDavid C Somayajulu 	qla_del_rcv_cntxt(ha);
2273da834d52SDavid C Somayajulu 
2274f10a77bbSDavid C Somayajulu 	qla_del_xmt_cntxt(ha);
2275f10a77bbSDavid C Somayajulu 
2276f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.init_intr_cnxt) {
227735291c22SDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; ) {
227835291c22SDavid C Somayajulu 
227935291c22SDavid C Somayajulu 			if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
228035291c22SDavid C Somayajulu 				num_msix = Q8_MAX_INTR_VECTORS;
228135291c22SDavid C Somayajulu 			else
228235291c22SDavid C Somayajulu 				num_msix = ha->hw.num_sds_rings - i;
228335291c22SDavid C Somayajulu 			qla_config_intr_cntxt(ha, i, num_msix, 0);
228435291c22SDavid C Somayajulu 
228535291c22SDavid C Somayajulu 			i += num_msix;
228635291c22SDavid C Somayajulu 		}
228735291c22SDavid C Somayajulu 
2288f10a77bbSDavid C Somayajulu 		ha->hw.flags.init_intr_cnxt = 0;
2289f10a77bbSDavid C Somayajulu 	}
2290da834d52SDavid C Somayajulu 
229135291c22SDavid C Somayajulu 	return;
2292f10a77bbSDavid C Somayajulu }
2293f10a77bbSDavid C Somayajulu 
229435291c22SDavid C Somayajulu void
229535291c22SDavid C Somayajulu qla_confirm_9kb_enable(qla_host_t *ha)
229635291c22SDavid C Somayajulu {
229735291c22SDavid C Somayajulu 	uint32_t supports_9kb = 0;
229835291c22SDavid C Somayajulu 
229935291c22SDavid C Somayajulu 	ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX);
230035291c22SDavid C Somayajulu 
230135291c22SDavid C Somayajulu 	/* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */
230235291c22SDavid C Somayajulu 	WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2);
230335291c22SDavid C Somayajulu 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
230435291c22SDavid C Somayajulu 
230535291c22SDavid C Somayajulu 	qla_get_nic_partition(ha, &supports_9kb, NULL);
230635291c22SDavid C Somayajulu 
230735291c22SDavid C Somayajulu 	if (!supports_9kb)
230835291c22SDavid C Somayajulu 		ha->hw.enable_9kb = 0;
230935291c22SDavid C Somayajulu 
231035291c22SDavid C Somayajulu 	return;
231135291c22SDavid C Somayajulu }
231235291c22SDavid C Somayajulu 
231335291c22SDavid C Somayajulu 
2314f10a77bbSDavid C Somayajulu /*
2315f10a77bbSDavid C Somayajulu  * Name: ql_init_hw_if
2316f10a77bbSDavid C Somayajulu  * Function: Creates the hardware specific entities corresponding to an
2317f10a77bbSDavid C Somayajulu  *	Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
2318f10a77bbSDavid C Somayajulu  *	corresponding to the interface. Enables LRO if allowed.
2319f10a77bbSDavid C Somayajulu  */
2320f10a77bbSDavid C Somayajulu int
2321f10a77bbSDavid C Somayajulu ql_init_hw_if(qla_host_t *ha)
2322f10a77bbSDavid C Somayajulu {
2323f10a77bbSDavid C Somayajulu 	device_t	dev;
2324f10a77bbSDavid C Somayajulu 	uint32_t	i;
2325f10a77bbSDavid C Somayajulu 	uint8_t		bcast_mac[6];
2326f10a77bbSDavid C Somayajulu 	qla_rdesc_t	*rdesc;
232735291c22SDavid C Somayajulu 	uint32_t	num_msix;
2328f10a77bbSDavid C Somayajulu 
2329f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2330f10a77bbSDavid C Somayajulu 
2331f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; i++) {
2332f10a77bbSDavid C Somayajulu 		bzero(ha->hw.dma_buf.sds_ring[i].dma_b,
2333f10a77bbSDavid C Somayajulu 			ha->hw.dma_buf.sds_ring[i].size);
2334f10a77bbSDavid C Somayajulu 	}
2335f10a77bbSDavid C Somayajulu 
233635291c22SDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; ) {
2337f10a77bbSDavid C Somayajulu 
233835291c22SDavid C Somayajulu 		if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
233935291c22SDavid C Somayajulu 			num_msix = Q8_MAX_INTR_VECTORS;
234035291c22SDavid C Somayajulu 		else
234135291c22SDavid C Somayajulu 			num_msix = ha->hw.num_sds_rings - i;
2342f10a77bbSDavid C Somayajulu 
234335291c22SDavid C Somayajulu 		if (qla_config_intr_cntxt(ha, i, num_msix, 1)) {
234435291c22SDavid C Somayajulu 
234535291c22SDavid C Somayajulu 			if (i > 0) {
234635291c22SDavid C Somayajulu 
234735291c22SDavid C Somayajulu 				num_msix = i;
234835291c22SDavid C Somayajulu 
234935291c22SDavid C Somayajulu 				for (i = 0; i < num_msix; ) {
235035291c22SDavid C Somayajulu 					qla_config_intr_cntxt(ha, i,
235135291c22SDavid C Somayajulu 						Q8_MAX_INTR_VECTORS, 0);
235235291c22SDavid C Somayajulu 					i += Q8_MAX_INTR_VECTORS;
235335291c22SDavid C Somayajulu 				}
235435291c22SDavid C Somayajulu 			}
2355f10a77bbSDavid C Somayajulu 			return (-1);
235635291c22SDavid C Somayajulu 		}
235735291c22SDavid C Somayajulu 
235835291c22SDavid C Somayajulu 		i = i + num_msix;
235935291c22SDavid C Somayajulu 	}
236035291c22SDavid C Somayajulu 
236135291c22SDavid C Somayajulu         ha->hw.flags.init_intr_cnxt = 1;
2362f10a77bbSDavid C Somayajulu 
2363f10a77bbSDavid C Somayajulu 	/*
2364f10a77bbSDavid C Somayajulu 	 * Create Receive Context
2365f10a77bbSDavid C Somayajulu 	 */
2366f10a77bbSDavid C Somayajulu 	if (qla_init_rcv_cntxt(ha)) {
2367f10a77bbSDavid C Somayajulu 		return (-1);
2368f10a77bbSDavid C Somayajulu 	}
2369f10a77bbSDavid C Somayajulu 
2370f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_rds_rings; i++) {
2371f10a77bbSDavid C Somayajulu 		rdesc = &ha->hw.rds[i];
2372f10a77bbSDavid C Somayajulu 		rdesc->rx_next = NUM_RX_DESCRIPTORS - 2;
2373f10a77bbSDavid C Somayajulu 		rdesc->rx_in = 0;
2374f10a77bbSDavid C Somayajulu 		/* Update the RDS Producer Indices */
2375f10a77bbSDavid C Somayajulu 		QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\
2376f10a77bbSDavid C Somayajulu 			rdesc->rx_next);
2377f10a77bbSDavid C Somayajulu 	}
2378f10a77bbSDavid C Somayajulu 
2379f10a77bbSDavid C Somayajulu 
2380f10a77bbSDavid C Somayajulu 	/*
2381f10a77bbSDavid C Somayajulu 	 * Create Transmit Context
2382f10a77bbSDavid C Somayajulu 	 */
2383f10a77bbSDavid C Somayajulu 	if (qla_init_xmt_cntxt(ha)) {
2384f10a77bbSDavid C Somayajulu 		qla_del_rcv_cntxt(ha);
2385f10a77bbSDavid C Somayajulu 		return (-1);
2386f10a77bbSDavid C Somayajulu 	}
2387f10a77bbSDavid C Somayajulu 	ha->hw.max_tx_segs = 0;
2388f10a77bbSDavid C Somayajulu 
2389da834d52SDavid C Somayajulu 	if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1, 1))
2390f10a77bbSDavid C Somayajulu 		return(-1);
2391f10a77bbSDavid C Somayajulu 
2392f10a77bbSDavid C Somayajulu 	ha->hw.flags.unicast_mac = 1;
2393f10a77bbSDavid C Somayajulu 
2394f10a77bbSDavid C Somayajulu 	bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2395f10a77bbSDavid C Somayajulu 	bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2396f10a77bbSDavid C Somayajulu 
2397da834d52SDavid C Somayajulu 	if (qla_config_mac_addr(ha, bcast_mac, 1, 1))
2398f10a77bbSDavid C Somayajulu 		return (-1);
2399f10a77bbSDavid C Somayajulu 
2400f10a77bbSDavid C Somayajulu 	ha->hw.flags.bcast_mac = 1;
2401f10a77bbSDavid C Somayajulu 
2402f10a77bbSDavid C Somayajulu 	/*
2403f10a77bbSDavid C Somayajulu 	 * program any cached multicast addresses
2404f10a77bbSDavid C Somayajulu 	 */
2405f10a77bbSDavid C Somayajulu 	if (qla_hw_add_all_mcast(ha))
2406f10a77bbSDavid C Somayajulu 		return (-1);
2407f10a77bbSDavid C Somayajulu 
2408f10a77bbSDavid C Somayajulu 	if (qla_config_rss(ha, ha->hw.rcv_cntxt_id))
2409f10a77bbSDavid C Somayajulu 		return (-1);
2410f10a77bbSDavid C Somayajulu 
2411f10a77bbSDavid C Somayajulu 	if (qla_config_rss_ind_table(ha))
2412f10a77bbSDavid C Somayajulu 		return (-1);
2413f10a77bbSDavid C Somayajulu 
241435291c22SDavid C Somayajulu 	if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1))
2415f10a77bbSDavid C Somayajulu 		return (-1);
2416f10a77bbSDavid C Somayajulu 
2417f10a77bbSDavid C Somayajulu 	if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
2418f10a77bbSDavid C Somayajulu 		return (-1);
2419f10a77bbSDavid C Somayajulu 
2420f10a77bbSDavid C Somayajulu 	if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
2421f10a77bbSDavid C Somayajulu 		return (-1);
2422f10a77bbSDavid C Somayajulu 
242335291c22SDavid C Somayajulu         if (qla_init_nic_func(ha))
242435291c22SDavid C Somayajulu                 return (-1);
242535291c22SDavid C Somayajulu 
242635291c22SDavid C Somayajulu         if (qla_query_fw_dcbx_caps(ha))
242735291c22SDavid C Somayajulu                 return (-1);
242835291c22SDavid C Somayajulu 
2429f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; i++)
2430f10a77bbSDavid C Somayajulu 		QL_ENABLE_INTERRUPTS(ha, i);
2431f10a77bbSDavid C Somayajulu 
2432f10a77bbSDavid C Somayajulu 	return (0);
2433f10a77bbSDavid C Somayajulu }
2434f10a77bbSDavid C Somayajulu 
2435f10a77bbSDavid C Somayajulu static int
243635291c22SDavid C Somayajulu qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx)
2437f10a77bbSDavid C Somayajulu {
2438f10a77bbSDavid C Somayajulu         device_t                dev = ha->pci_dev;
2439f10a77bbSDavid C Somayajulu         q80_rq_map_sds_to_rds_t *map_rings;
244035291c22SDavid C Somayajulu 	q80_rsp_map_sds_to_rds_t *map_rings_rsp;
2441f10a77bbSDavid C Somayajulu         uint32_t                i, err;
2442f10a77bbSDavid C Somayajulu         qla_hw_t                *hw = &ha->hw;
2443f10a77bbSDavid C Somayajulu 
2444f10a77bbSDavid C Somayajulu         map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox;
2445f10a77bbSDavid C Somayajulu         bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t));
2446f10a77bbSDavid C Somayajulu 
2447f10a77bbSDavid C Somayajulu         map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS;
2448f10a77bbSDavid C Somayajulu         map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2);
2449f10a77bbSDavid C Somayajulu         map_rings->count_version |= Q8_MBX_CMD_VERSION;
2450f10a77bbSDavid C Somayajulu 
2451f10a77bbSDavid C Somayajulu         map_rings->cntxt_id = hw->rcv_cntxt_id;
245235291c22SDavid C Somayajulu         map_rings->num_rings = num_idx;
2453f10a77bbSDavid C Somayajulu 
245435291c22SDavid C Somayajulu 	for (i = 0; i < num_idx; i++) {
245535291c22SDavid C Somayajulu 		map_rings->sds_rds[i].sds_ring = i + start_idx;
245635291c22SDavid C Somayajulu 		map_rings->sds_rds[i].rds_ring = i + start_idx;
2457f10a77bbSDavid C Somayajulu 	}
2458f10a77bbSDavid C Somayajulu 
2459f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)map_rings,
2460f10a77bbSDavid C Somayajulu                 (sizeof (q80_rq_map_sds_to_rds_t) >> 2),
2461f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2462f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2463f10a77bbSDavid C Somayajulu                 return (-1);
2464f10a77bbSDavid C Somayajulu         }
2465f10a77bbSDavid C Somayajulu 
246635291c22SDavid C Somayajulu         map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox;
2467f10a77bbSDavid C Somayajulu 
2468f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status);
2469f10a77bbSDavid C Somayajulu 
2470f10a77bbSDavid C Somayajulu         if (err) {
2471f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2472f10a77bbSDavid C Somayajulu                 return (-1);
2473f10a77bbSDavid C Somayajulu         }
2474f10a77bbSDavid C Somayajulu 
2475f10a77bbSDavid C Somayajulu         return (0);
2476f10a77bbSDavid C Somayajulu }
2477f10a77bbSDavid C Somayajulu 
2478f10a77bbSDavid C Somayajulu /*
2479f10a77bbSDavid C Somayajulu  * Name: qla_init_rcv_cntxt
2480f10a77bbSDavid C Somayajulu  * Function: Creates the Receive Context.
2481f10a77bbSDavid C Somayajulu  */
2482f10a77bbSDavid C Somayajulu static int
2483f10a77bbSDavid C Somayajulu qla_init_rcv_cntxt(qla_host_t *ha)
2484f10a77bbSDavid C Somayajulu {
2485f10a77bbSDavid C Somayajulu 	q80_rq_rcv_cntxt_t	*rcntxt;
2486f10a77bbSDavid C Somayajulu 	q80_rsp_rcv_cntxt_t	*rcntxt_rsp;
2487f10a77bbSDavid C Somayajulu 	q80_stat_desc_t		*sdesc;
2488f10a77bbSDavid C Somayajulu 	int			i, j;
2489f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2490f10a77bbSDavid C Somayajulu 	device_t		dev;
2491f10a77bbSDavid C Somayajulu 	uint32_t		err;
2492f10a77bbSDavid C Somayajulu 	uint32_t		rcntxt_sds_rings;
2493f10a77bbSDavid C Somayajulu 	uint32_t		rcntxt_rds_rings;
249435291c22SDavid C Somayajulu 	uint32_t		max_idx;
2495f10a77bbSDavid C Somayajulu 
2496f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2497f10a77bbSDavid C Somayajulu 
2498f10a77bbSDavid C Somayajulu 	/*
2499f10a77bbSDavid C Somayajulu 	 * Create Receive Context
2500f10a77bbSDavid C Somayajulu 	 */
2501f10a77bbSDavid C Somayajulu 
2502f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
2503f10a77bbSDavid C Somayajulu 		sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0];
2504f10a77bbSDavid C Somayajulu 
2505f10a77bbSDavid C Somayajulu 		for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) {
2506f10a77bbSDavid C Somayajulu 			sdesc->data[0] = 1ULL;
2507f10a77bbSDavid C Somayajulu 			sdesc->data[1] = 1ULL;
2508f10a77bbSDavid C Somayajulu 		}
2509f10a77bbSDavid C Somayajulu 	}
2510f10a77bbSDavid C Somayajulu 
2511f10a77bbSDavid C Somayajulu 	rcntxt_sds_rings = hw->num_sds_rings;
2512f10a77bbSDavid C Somayajulu 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS)
2513f10a77bbSDavid C Somayajulu 		rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS;
2514f10a77bbSDavid C Somayajulu 
2515f10a77bbSDavid C Somayajulu 	rcntxt_rds_rings = hw->num_rds_rings;
2516f10a77bbSDavid C Somayajulu 
2517f10a77bbSDavid C Somayajulu 	if (hw->num_rds_rings > MAX_RDS_RING_SETS)
2518f10a77bbSDavid C Somayajulu 		rcntxt_rds_rings = MAX_RDS_RING_SETS;
2519f10a77bbSDavid C Somayajulu 
2520f10a77bbSDavid C Somayajulu 	rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox;
2521f10a77bbSDavid C Somayajulu 	bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t)));
2522f10a77bbSDavid C Somayajulu 
2523f10a77bbSDavid C Somayajulu 	rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT;
2524f10a77bbSDavid C Somayajulu 	rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2);
2525f10a77bbSDavid C Somayajulu 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2526f10a77bbSDavid C Somayajulu 
2527f10a77bbSDavid C Somayajulu 	rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW |
2528f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_LRO |
2529f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_HW_LRO |
2530f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_RSS |
2531f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_SGL_LRO;
2532f10a77bbSDavid C Somayajulu 
253335291c22SDavid C Somayajulu 	if (ha->hw.enable_9kb)
253435291c22SDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO;
253535291c22SDavid C Somayajulu 	else
253635291c22SDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO;
253735291c22SDavid C Somayajulu 
2538f10a77bbSDavid C Somayajulu 	if (ha->hw.num_rds_rings > 1) {
2539f10a77bbSDavid C Somayajulu 		rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5);
2540f10a77bbSDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS;
2541f10a77bbSDavid C Somayajulu 	} else
2542f10a77bbSDavid C Somayajulu 		rcntxt->nrds_sets_rings = 0x1 | (1 << 5);
2543f10a77bbSDavid C Somayajulu 
2544f10a77bbSDavid C Somayajulu 	rcntxt->nsds_rings = rcntxt_sds_rings;
2545f10a77bbSDavid C Somayajulu 
2546f10a77bbSDavid C Somayajulu 	rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE;
2547f10a77bbSDavid C Somayajulu 
2548f10a77bbSDavid C Somayajulu 	rcntxt->rcv_vpid = 0;
2549f10a77bbSDavid C Somayajulu 
2550f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2551f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].paddr =
2552f10a77bbSDavid C Somayajulu 			qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr);
2553f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].size =
2554f10a77bbSDavid C Somayajulu 			qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2555f10a77bbSDavid C Somayajulu 		if (ha->msix_count == 2) {
2556f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_id =
2557f10a77bbSDavid C Somayajulu 				qla_host_to_le16(hw->intr_id[0]);
2558f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_src_bit = qla_host_to_le16((i));
2559f10a77bbSDavid C Somayajulu 		} else {
2560f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_id =
2561f10a77bbSDavid C Somayajulu 				qla_host_to_le16(hw->intr_id[i]);
2562f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0);
2563f10a77bbSDavid C Somayajulu 		}
2564f10a77bbSDavid C Somayajulu 	}
2565f10a77bbSDavid C Somayajulu 
2566f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2567f10a77bbSDavid C Somayajulu 		rcntxt->rds[i].paddr_std =
2568f10a77bbSDavid C Somayajulu 			qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr);
256935291c22SDavid C Somayajulu 
257035291c22SDavid C Somayajulu 		if (ha->hw.enable_9kb)
257135291c22SDavid C Somayajulu 			rcntxt->rds[i].std_bsize =
257235291c22SDavid C Somayajulu 				qla_host_to_le64(MJUM9BYTES);
257335291c22SDavid C Somayajulu 		else
2574f10a77bbSDavid C Somayajulu 			rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
257535291c22SDavid C Somayajulu 
2576f10a77bbSDavid C Somayajulu 		rcntxt->rds[i].std_nentries =
2577f10a77bbSDavid C Somayajulu 			qla_host_to_le32(NUM_RX_DESCRIPTORS);
2578f10a77bbSDavid C Somayajulu 	}
2579f10a77bbSDavid C Somayajulu 
2580f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2581f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_rcv_cntxt_t) >> 2),
2582f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) {
2583f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2584f10a77bbSDavid C Somayajulu                 return (-1);
2585f10a77bbSDavid C Somayajulu         }
2586f10a77bbSDavid C Somayajulu 
2587f10a77bbSDavid C Somayajulu         rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox;
2588f10a77bbSDavid C Somayajulu 
2589f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2590f10a77bbSDavid C Somayajulu 
2591f10a77bbSDavid C Somayajulu         if (err) {
2592f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2593f10a77bbSDavid C Somayajulu                 return (-1);
2594f10a77bbSDavid C Somayajulu         }
2595f10a77bbSDavid C Somayajulu 
2596f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2597f10a77bbSDavid C Somayajulu 		hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i];
2598f10a77bbSDavid C Somayajulu 	}
2599f10a77bbSDavid C Somayajulu 
2600f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2601f10a77bbSDavid C Somayajulu 		hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std;
2602f10a77bbSDavid C Somayajulu 	}
2603f10a77bbSDavid C Somayajulu 
2604f10a77bbSDavid C Somayajulu 	hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id;
2605f10a77bbSDavid C Somayajulu 
2606f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_rx_cnxt = 1;
2607f10a77bbSDavid C Somayajulu 
2608f10a77bbSDavid C Somayajulu 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) {
260935291c22SDavid C Somayajulu 
261035291c22SDavid C Somayajulu 		for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) {
261135291c22SDavid C Somayajulu 
261235291c22SDavid C Somayajulu 			if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings)
261335291c22SDavid C Somayajulu 				max_idx = MAX_RCNTXT_SDS_RINGS;
261435291c22SDavid C Somayajulu 			else
261535291c22SDavid C Somayajulu 				max_idx = hw->num_sds_rings - i;
261635291c22SDavid C Somayajulu 
261735291c22SDavid C Somayajulu 			err = qla_add_rcv_rings(ha, i, max_idx);
2618f10a77bbSDavid C Somayajulu 			if (err)
2619f10a77bbSDavid C Somayajulu 				return -1;
262035291c22SDavid C Somayajulu 
262135291c22SDavid C Somayajulu 			i += max_idx;
262235291c22SDavid C Somayajulu 		}
2623f10a77bbSDavid C Somayajulu 	}
2624f10a77bbSDavid C Somayajulu 
2625f10a77bbSDavid C Somayajulu 	if (hw->num_rds_rings > 1) {
262635291c22SDavid C Somayajulu 
262735291c22SDavid C Somayajulu 		for (i = 0; i < hw->num_rds_rings; ) {
262835291c22SDavid C Somayajulu 
262935291c22SDavid C Somayajulu 			if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings)
263035291c22SDavid C Somayajulu 				max_idx = MAX_SDS_TO_RDS_MAP;
263135291c22SDavid C Somayajulu 			else
263235291c22SDavid C Somayajulu 				max_idx = hw->num_rds_rings - i;
263335291c22SDavid C Somayajulu 
263435291c22SDavid C Somayajulu 			err = qla_map_sds_to_rds(ha, i, max_idx);
2635f10a77bbSDavid C Somayajulu 			if (err)
2636f10a77bbSDavid C Somayajulu 				return -1;
263735291c22SDavid C Somayajulu 
263835291c22SDavid C Somayajulu 			i += max_idx;
263935291c22SDavid C Somayajulu 		}
2640f10a77bbSDavid C Somayajulu 	}
2641f10a77bbSDavid C Somayajulu 
2642f10a77bbSDavid C Somayajulu 	return (0);
2643f10a77bbSDavid C Somayajulu }
2644f10a77bbSDavid C Somayajulu 
2645f10a77bbSDavid C Somayajulu static int
264635291c22SDavid C Somayajulu qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds)
2647f10a77bbSDavid C Somayajulu {
2648f10a77bbSDavid C Somayajulu 	device_t		dev = ha->pci_dev;
2649f10a77bbSDavid C Somayajulu 	q80_rq_add_rcv_rings_t	*add_rcv;
2650f10a77bbSDavid C Somayajulu 	q80_rsp_add_rcv_rings_t	*add_rcv_rsp;
2651f10a77bbSDavid C Somayajulu 	uint32_t		i,j, err;
2652f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2653f10a77bbSDavid C Somayajulu 
2654f10a77bbSDavid C Somayajulu 	add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox;
2655f10a77bbSDavid C Somayajulu 	bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t));
2656f10a77bbSDavid C Somayajulu 
2657f10a77bbSDavid C Somayajulu 	add_rcv->opcode = Q8_MBX_ADD_RX_RINGS;
2658f10a77bbSDavid C Somayajulu 	add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2);
2659f10a77bbSDavid C Somayajulu 	add_rcv->count_version |= Q8_MBX_CMD_VERSION;
2660f10a77bbSDavid C Somayajulu 
2661f10a77bbSDavid C Somayajulu 	add_rcv->nrds_sets_rings = nsds | (1 << 5);
2662f10a77bbSDavid C Somayajulu 	add_rcv->nsds_rings = nsds;
2663f10a77bbSDavid C Somayajulu 	add_rcv->cntxt_id = hw->rcv_cntxt_id;
2664f10a77bbSDavid C Somayajulu 
2665f10a77bbSDavid C Somayajulu         for (i = 0; i <  nsds; i++) {
2666f10a77bbSDavid C Somayajulu 
2667f10a77bbSDavid C Somayajulu 		j = i + sds_idx;
2668f10a77bbSDavid C Somayajulu 
2669f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].paddr =
2670f10a77bbSDavid C Somayajulu                         qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr);
2671f10a77bbSDavid C Somayajulu 
2672f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].size =
2673f10a77bbSDavid C Somayajulu                         qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2674f10a77bbSDavid C Somayajulu 
2675f10a77bbSDavid C Somayajulu                 if (ha->msix_count == 2) {
2676f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_id =
2677f10a77bbSDavid C Somayajulu                                 qla_host_to_le16(hw->intr_id[0]);
2678f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(j);
2679f10a77bbSDavid C Somayajulu                 } else {
2680f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_id =
2681f10a77bbSDavid C Somayajulu                                 qla_host_to_le16(hw->intr_id[j]);
2682f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0);
2683f10a77bbSDavid C Somayajulu                 }
2684f10a77bbSDavid C Somayajulu 
2685f10a77bbSDavid C Somayajulu         }
268635291c22SDavid C Somayajulu         for (i = 0; (i <  nsds); i++) {
2687f10a77bbSDavid C Somayajulu                 j = i + sds_idx;
268835291c22SDavid C Somayajulu 
2689f10a77bbSDavid C Somayajulu                 add_rcv->rds[i].paddr_std =
2690f10a77bbSDavid C Somayajulu                         qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr);
269135291c22SDavid C Somayajulu 
269235291c22SDavid C Somayajulu 		if (ha->hw.enable_9kb)
269335291c22SDavid C Somayajulu 			add_rcv->rds[i].std_bsize =
269435291c22SDavid C Somayajulu 				qla_host_to_le64(MJUM9BYTES);
269535291c22SDavid C Somayajulu 		else
2696f10a77bbSDavid C Somayajulu                 	add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
269735291c22SDavid C Somayajulu 
2698f10a77bbSDavid C Somayajulu                 add_rcv->rds[i].std_nentries =
2699f10a77bbSDavid C Somayajulu                         qla_host_to_le32(NUM_RX_DESCRIPTORS);
2700f10a77bbSDavid C Somayajulu         }
2701f10a77bbSDavid C Somayajulu 
2702f10a77bbSDavid C Somayajulu 
2703f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)add_rcv,
2704f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_add_rcv_rings_t) >> 2),
2705f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2706f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2707f10a77bbSDavid C Somayajulu                 return (-1);
2708f10a77bbSDavid C Somayajulu         }
2709f10a77bbSDavid C Somayajulu 
2710f10a77bbSDavid C Somayajulu         add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
2711f10a77bbSDavid C Somayajulu 
2712f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status);
2713f10a77bbSDavid C Somayajulu 
2714f10a77bbSDavid C Somayajulu         if (err) {
2715f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2716f10a77bbSDavid C Somayajulu                 return (-1);
2717f10a77bbSDavid C Somayajulu         }
2718f10a77bbSDavid C Somayajulu 
271935291c22SDavid C Somayajulu 	for (i = 0; i < nsds; i++) {
272035291c22SDavid C Somayajulu 		hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i];
2721f10a77bbSDavid C Somayajulu 	}
272235291c22SDavid C Somayajulu 
272335291c22SDavid C Somayajulu 	for (i = 0; i < nsds; i++) {
272435291c22SDavid C Somayajulu 		hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std;
2725f10a77bbSDavid C Somayajulu 	}
272635291c22SDavid C Somayajulu 
2727f10a77bbSDavid C Somayajulu 	return (0);
2728f10a77bbSDavid C Somayajulu }
2729f10a77bbSDavid C Somayajulu 
2730f10a77bbSDavid C Somayajulu /*
2731f10a77bbSDavid C Somayajulu  * Name: qla_del_rcv_cntxt
2732f10a77bbSDavid C Somayajulu  * Function: Destroys the Receive Context.
2733f10a77bbSDavid C Somayajulu  */
2734f10a77bbSDavid C Somayajulu static void
2735f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(qla_host_t *ha)
2736f10a77bbSDavid C Somayajulu {
2737f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
2738f10a77bbSDavid C Somayajulu 	q80_rcv_cntxt_destroy_t		*rcntxt;
2739f10a77bbSDavid C Somayajulu 	q80_rcv_cntxt_destroy_rsp_t	*rcntxt_rsp;
2740f10a77bbSDavid C Somayajulu 	uint32_t			err;
2741f10a77bbSDavid C Somayajulu 	uint8_t				bcast_mac[6];
2742f10a77bbSDavid C Somayajulu 
2743f10a77bbSDavid C Somayajulu 	if (!ha->hw.flags.init_rx_cnxt)
2744f10a77bbSDavid C Somayajulu 		return;
2745f10a77bbSDavid C Somayajulu 
2746f10a77bbSDavid C Somayajulu 	if (qla_hw_del_all_mcast(ha))
2747f10a77bbSDavid C Somayajulu 		return;
2748f10a77bbSDavid C Somayajulu 
2749f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.bcast_mac) {
2750f10a77bbSDavid C Somayajulu 
2751f10a77bbSDavid C Somayajulu 		bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2752f10a77bbSDavid C Somayajulu 		bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2753f10a77bbSDavid C Somayajulu 
2754da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, bcast_mac, 0, 1))
2755f10a77bbSDavid C Somayajulu 			return;
2756f10a77bbSDavid C Somayajulu 		ha->hw.flags.bcast_mac = 0;
2757f10a77bbSDavid C Somayajulu 
2758f10a77bbSDavid C Somayajulu 	}
2759f10a77bbSDavid C Somayajulu 
2760f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.unicast_mac) {
2761da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0, 1))
2762f10a77bbSDavid C Somayajulu 			return;
2763f10a77bbSDavid C Somayajulu 		ha->hw.flags.unicast_mac = 0;
2764f10a77bbSDavid C Somayajulu 	}
2765f10a77bbSDavid C Somayajulu 
2766f10a77bbSDavid C Somayajulu 	rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox;
2767f10a77bbSDavid C Somayajulu 	bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t)));
2768f10a77bbSDavid C Somayajulu 
2769f10a77bbSDavid C Somayajulu 	rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT;
2770f10a77bbSDavid C Somayajulu 	rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2);
2771f10a77bbSDavid C Somayajulu 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2772f10a77bbSDavid C Somayajulu 
2773f10a77bbSDavid C Somayajulu 	rcntxt->cntxt_id = ha->hw.rcv_cntxt_id;
2774f10a77bbSDavid C Somayajulu 
2775f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2776f10a77bbSDavid C Somayajulu 		(sizeof (q80_rcv_cntxt_destroy_t) >> 2),
2777f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) {
2778f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2779f10a77bbSDavid C Somayajulu                 return;
2780f10a77bbSDavid C Somayajulu         }
2781f10a77bbSDavid C Somayajulu         rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox;
2782f10a77bbSDavid C Somayajulu 
2783f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2784f10a77bbSDavid C Somayajulu 
2785f10a77bbSDavid C Somayajulu         if (err) {
2786f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2787f10a77bbSDavid C Somayajulu         }
2788f10a77bbSDavid C Somayajulu 
2789f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_rx_cnxt = 0;
2790f10a77bbSDavid C Somayajulu 	return;
2791f10a77bbSDavid C Somayajulu }
2792f10a77bbSDavid C Somayajulu 
2793f10a77bbSDavid C Somayajulu /*
2794f10a77bbSDavid C Somayajulu  * Name: qla_init_xmt_cntxt
2795f10a77bbSDavid C Somayajulu  * Function: Creates the Transmit Context.
2796f10a77bbSDavid C Somayajulu  */
2797f10a77bbSDavid C Somayajulu static int
2798f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2799f10a77bbSDavid C Somayajulu {
2800f10a77bbSDavid C Somayajulu 	device_t		dev;
2801f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2802f10a77bbSDavid C Somayajulu 	q80_rq_tx_cntxt_t	*tcntxt;
2803f10a77bbSDavid C Somayajulu 	q80_rsp_tx_cntxt_t	*tcntxt_rsp;
2804f10a77bbSDavid C Somayajulu 	uint32_t		err;
2805f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t       *hw_tx_cntxt;
2806f10a77bbSDavid C Somayajulu 
2807f10a77bbSDavid C Somayajulu 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
2808f10a77bbSDavid C Somayajulu 
2809f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2810f10a77bbSDavid C Somayajulu 
2811f10a77bbSDavid C Somayajulu 	/*
2812f10a77bbSDavid C Somayajulu 	 * Create Transmit Context
2813f10a77bbSDavid C Somayajulu 	 */
2814f10a77bbSDavid C Somayajulu 	tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox;
2815f10a77bbSDavid C Somayajulu 	bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t)));
2816f10a77bbSDavid C Somayajulu 
2817f10a77bbSDavid C Somayajulu 	tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT;
2818f10a77bbSDavid C Somayajulu 	tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2);
2819f10a77bbSDavid C Somayajulu 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2820f10a77bbSDavid C Somayajulu 
282135291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV
282235291c22SDavid C Somayajulu 
282335291c22SDavid C Somayajulu 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO |
282435291c22SDavid C Somayajulu 				Q8_TX_CNTXT_CAP0_TC;
282535291c22SDavid C Somayajulu 
282635291c22SDavid C Somayajulu 	if (txr_idx >= (ha->hw.num_tx_rings >> 1)) {
282735291c22SDavid C Somayajulu 		tcntxt->traffic_class = 1;
282835291c22SDavid C Somayajulu 	}
282935291c22SDavid C Somayajulu 
283035291c22SDavid C Somayajulu #else
283135291c22SDavid C Somayajulu 
2832f10a77bbSDavid C Somayajulu 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO;
2833f10a77bbSDavid C Somayajulu 
283435291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
283535291c22SDavid C Somayajulu 
2836f10a77bbSDavid C Somayajulu 	tcntxt->ntx_rings = 1;
2837f10a77bbSDavid C Somayajulu 
2838f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].paddr =
2839f10a77bbSDavid C Somayajulu 		qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr);
2840f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].tx_consumer =
2841f10a77bbSDavid C Somayajulu 		qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr);
2842f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS);
2843f10a77bbSDavid C Somayajulu 
2844f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[0]);
2845f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0);
2846f10a77bbSDavid C Somayajulu 
2847f10a77bbSDavid C Somayajulu 
2848f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS;
2849f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0;
2850f10a77bbSDavid C Somayajulu 
2851f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2852f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_tx_cntxt_t) >> 2),
2853f10a77bbSDavid C Somayajulu                 ha->hw.mbox,
2854f10a77bbSDavid C Somayajulu 		(sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) {
2855f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2856f10a77bbSDavid C Somayajulu                 return (-1);
2857f10a77bbSDavid C Somayajulu         }
2858f10a77bbSDavid C Somayajulu         tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox;
2859f10a77bbSDavid C Somayajulu 
2860f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2861f10a77bbSDavid C Somayajulu 
2862f10a77bbSDavid C Somayajulu         if (err) {
2863f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2864f10a77bbSDavid C Somayajulu 		return -1;
2865f10a77bbSDavid C Somayajulu         }
2866f10a77bbSDavid C Somayajulu 
2867f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index;
2868f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id;
2869f10a77bbSDavid C Somayajulu 
287035291c22SDavid C Somayajulu 	if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0))
287135291c22SDavid C Somayajulu 		return (-1);
287235291c22SDavid C Somayajulu 
2873f10a77bbSDavid C Somayajulu 	return (0);
2874f10a77bbSDavid C Somayajulu }
2875f10a77bbSDavid C Somayajulu 
2876f10a77bbSDavid C Somayajulu 
2877f10a77bbSDavid C Somayajulu /*
2878f10a77bbSDavid C Somayajulu  * Name: qla_del_xmt_cntxt
2879f10a77bbSDavid C Somayajulu  * Function: Destroys the Transmit Context.
2880f10a77bbSDavid C Somayajulu  */
2881f10a77bbSDavid C Somayajulu static int
2882f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2883f10a77bbSDavid C Somayajulu {
2884f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
2885f10a77bbSDavid C Somayajulu 	q80_tx_cntxt_destroy_t		*tcntxt;
2886f10a77bbSDavid C Somayajulu 	q80_tx_cntxt_destroy_rsp_t	*tcntxt_rsp;
2887f10a77bbSDavid C Somayajulu 	uint32_t			err;
2888f10a77bbSDavid C Somayajulu 
2889f10a77bbSDavid C Somayajulu 	tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox;
2890f10a77bbSDavid C Somayajulu 	bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t)));
2891f10a77bbSDavid C Somayajulu 
2892f10a77bbSDavid C Somayajulu 	tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT;
2893f10a77bbSDavid C Somayajulu 	tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2);
2894f10a77bbSDavid C Somayajulu 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2895f10a77bbSDavid C Somayajulu 
2896f10a77bbSDavid C Somayajulu 	tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id;
2897f10a77bbSDavid C Somayajulu 
2898f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2899f10a77bbSDavid C Somayajulu 		(sizeof (q80_tx_cntxt_destroy_t) >> 2),
2900f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) {
2901f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2902f10a77bbSDavid C Somayajulu                 return (-1);
2903f10a77bbSDavid C Somayajulu         }
2904f10a77bbSDavid C Somayajulu         tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox;
2905f10a77bbSDavid C Somayajulu 
2906f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2907f10a77bbSDavid C Somayajulu 
2908f10a77bbSDavid C Somayajulu         if (err) {
2909f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2910f10a77bbSDavid C Somayajulu 		return (-1);
2911f10a77bbSDavid C Somayajulu         }
2912f10a77bbSDavid C Somayajulu 
2913f10a77bbSDavid C Somayajulu 	return (0);
2914f10a77bbSDavid C Somayajulu }
2915f10a77bbSDavid C Somayajulu static void
2916f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt(qla_host_t *ha)
2917f10a77bbSDavid C Somayajulu {
2918f10a77bbSDavid C Somayajulu 	uint32_t i;
2919f10a77bbSDavid C Somayajulu 
2920f10a77bbSDavid C Somayajulu 	if (!ha->hw.flags.init_tx_cnxt)
2921f10a77bbSDavid C Somayajulu 		return;
2922f10a77bbSDavid C Somayajulu 
2923f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2924f10a77bbSDavid C Somayajulu 		if (qla_del_xmt_cntxt_i(ha, i))
2925f10a77bbSDavid C Somayajulu 			break;
2926f10a77bbSDavid C Somayajulu 	}
2927f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_tx_cnxt = 0;
2928f10a77bbSDavid C Somayajulu }
2929f10a77bbSDavid C Somayajulu 
2930f10a77bbSDavid C Somayajulu static int
2931f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt(qla_host_t *ha)
2932f10a77bbSDavid C Somayajulu {
2933f10a77bbSDavid C Somayajulu 	uint32_t i, j;
2934f10a77bbSDavid C Somayajulu 
2935f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2936f10a77bbSDavid C Somayajulu 		if (qla_init_xmt_cntxt_i(ha, i) != 0) {
2937f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
2938f10a77bbSDavid C Somayajulu 				qla_del_xmt_cntxt_i(ha, j);
2939f10a77bbSDavid C Somayajulu 			return (-1);
2940f10a77bbSDavid C Somayajulu 		}
2941f10a77bbSDavid C Somayajulu 	}
2942f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_tx_cnxt = 1;
2943f10a77bbSDavid C Somayajulu 	return (0);
2944f10a77bbSDavid C Somayajulu }
2945f10a77bbSDavid C Somayajulu 
2946f10a77bbSDavid C Somayajulu static int
2947da834d52SDavid C Somayajulu qla_hw_all_mcast(qla_host_t *ha, uint32_t add_mcast)
2948f10a77bbSDavid C Somayajulu {
2949f10a77bbSDavid C Somayajulu 	int i, nmcast;
2950da834d52SDavid C Somayajulu 	uint32_t count = 0;
2951da834d52SDavid C Somayajulu 	uint8_t *mcast;
2952f10a77bbSDavid C Somayajulu 
2953f10a77bbSDavid C Somayajulu 	nmcast = ha->hw.nmcast;
2954f10a77bbSDavid C Somayajulu 
2955da834d52SDavid C Somayajulu 	QL_DPRINT2(ha, (ha->pci_dev,
2956da834d52SDavid C Somayajulu 		"%s:[0x%x] enter nmcast = %d \n", __func__, add_mcast, nmcast));
2957da834d52SDavid C Somayajulu 
2958da834d52SDavid C Somayajulu 	mcast = ha->hw.mac_addr_arr;
2959da834d52SDavid C Somayajulu 	memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
2960da834d52SDavid C Somayajulu 
2961f10a77bbSDavid C Somayajulu 	for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
2962f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] != 0) ||
2963f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] != 0) ||
2964f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] != 0) ||
2965f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] != 0) ||
2966f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] != 0) ||
2967f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] != 0)) {
2968f10a77bbSDavid C Somayajulu 
2969da834d52SDavid C Somayajulu 			bcopy(ha->hw.mcast[i].addr, mcast, ETHER_ADDR_LEN);
2970da834d52SDavid C Somayajulu 			mcast = mcast + ETHER_ADDR_LEN;
2971da834d52SDavid C Somayajulu 			count++;
2972da834d52SDavid C Somayajulu 
2973da834d52SDavid C Somayajulu 			if (count == Q8_MAX_MAC_ADDRS) {
2974da834d52SDavid C Somayajulu 				if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
2975da834d52SDavid C Somayajulu 					add_mcast, count)) {
2976da834d52SDavid C Somayajulu                 			device_printf(ha->pci_dev,
2977da834d52SDavid C Somayajulu 						"%s: failed\n", __func__);
2978f10a77bbSDavid C Somayajulu 					return (-1);
2979f10a77bbSDavid C Somayajulu 				}
2980f10a77bbSDavid C Somayajulu 
2981da834d52SDavid C Somayajulu 				count = 0;
2982da834d52SDavid C Somayajulu 				mcast = ha->hw.mac_addr_arr;
2983da834d52SDavid C Somayajulu 				memset(mcast, 0,
2984da834d52SDavid C Somayajulu 					(Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
2985da834d52SDavid C Somayajulu 			}
2986da834d52SDavid C Somayajulu 
2987f10a77bbSDavid C Somayajulu 			nmcast--;
2988f10a77bbSDavid C Somayajulu 		}
2989f10a77bbSDavid C Somayajulu 	}
2990da834d52SDavid C Somayajulu 
2991da834d52SDavid C Somayajulu 	if (count) {
2992da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mcast,
2993da834d52SDavid C Somayajulu 			count)) {
2994da834d52SDavid C Somayajulu                 	device_printf(ha->pci_dev, "%s: failed\n", __func__);
2995da834d52SDavid C Somayajulu 			return (-1);
2996da834d52SDavid C Somayajulu 		}
2997da834d52SDavid C Somayajulu 	}
2998da834d52SDavid C Somayajulu 	QL_DPRINT2(ha, (ha->pci_dev,
2999da834d52SDavid C Somayajulu 		"%s:[0x%x] exit nmcast = %d \n", __func__, add_mcast, nmcast));
3000da834d52SDavid C Somayajulu 
3001f10a77bbSDavid C Somayajulu 	return 0;
3002f10a77bbSDavid C Somayajulu }
3003f10a77bbSDavid C Somayajulu 
3004f10a77bbSDavid C Somayajulu static int
3005da834d52SDavid C Somayajulu qla_hw_add_all_mcast(qla_host_t *ha)
3006da834d52SDavid C Somayajulu {
3007da834d52SDavid C Somayajulu 	int ret;
3008da834d52SDavid C Somayajulu 
3009da834d52SDavid C Somayajulu 	ret = qla_hw_all_mcast(ha, 1);
3010da834d52SDavid C Somayajulu 
3011da834d52SDavid C Somayajulu 	return (ret);
3012da834d52SDavid C Somayajulu }
3013da834d52SDavid C Somayajulu 
3014da834d52SDavid C Somayajulu static int
3015f10a77bbSDavid C Somayajulu qla_hw_del_all_mcast(qla_host_t *ha)
3016f10a77bbSDavid C Somayajulu {
3017da834d52SDavid C Somayajulu 	int ret;
3018f10a77bbSDavid C Somayajulu 
3019da834d52SDavid C Somayajulu 	ret = qla_hw_all_mcast(ha, 0);
3020f10a77bbSDavid C Somayajulu 
3021da834d52SDavid C Somayajulu 	bzero(ha->hw.mcast, (sizeof (qla_mcast_t) * Q8_MAX_NUM_MULTICAST_ADDRS));
3022da834d52SDavid C Somayajulu 	ha->hw.nmcast = 0;
3023f10a77bbSDavid C Somayajulu 
3024da834d52SDavid C Somayajulu 	return (ret);
3025f10a77bbSDavid C Somayajulu }
3026f10a77bbSDavid C Somayajulu 
3027f10a77bbSDavid C Somayajulu static int
3028da834d52SDavid C Somayajulu qla_hw_mac_addr_present(qla_host_t *ha, uint8_t *mta)
3029f10a77bbSDavid C Somayajulu {
3030f10a77bbSDavid C Somayajulu 	int i;
3031f10a77bbSDavid C Somayajulu 
3032f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3033f10a77bbSDavid C Somayajulu 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0)
3034da834d52SDavid C Somayajulu 			return (0); /* its been already added */
3035f10a77bbSDavid C Somayajulu 	}
3036da834d52SDavid C Somayajulu 	return (-1);
3037da834d52SDavid C Somayajulu }
3038da834d52SDavid C Somayajulu 
3039da834d52SDavid C Somayajulu static int
3040da834d52SDavid C Somayajulu qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3041da834d52SDavid C Somayajulu {
3042da834d52SDavid C Somayajulu 	int i;
3043f10a77bbSDavid C Somayajulu 
3044f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3045f10a77bbSDavid C Somayajulu 
3046f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] == 0) &&
3047f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] == 0) &&
3048f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] == 0) &&
3049f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] == 0) &&
3050f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] == 0) &&
3051f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] == 0)) {
3052f10a77bbSDavid C Somayajulu 
3053f10a77bbSDavid C Somayajulu 			bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN);
3054f10a77bbSDavid C Somayajulu 			ha->hw.nmcast++;
3055f10a77bbSDavid C Somayajulu 
3056da834d52SDavid C Somayajulu 			mta = mta + ETHER_ADDR_LEN;
3057da834d52SDavid C Somayajulu 			nmcast--;
3058da834d52SDavid C Somayajulu 
3059da834d52SDavid C Somayajulu 			if (nmcast == 0)
3060da834d52SDavid C Somayajulu 				break;
3061f10a77bbSDavid C Somayajulu 		}
3062da834d52SDavid C Somayajulu 
3063f10a77bbSDavid C Somayajulu 	}
3064f10a77bbSDavid C Somayajulu 	return 0;
3065f10a77bbSDavid C Somayajulu }
3066f10a77bbSDavid C Somayajulu 
3067f10a77bbSDavid C Somayajulu static int
3068da834d52SDavid C Somayajulu qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3069f10a77bbSDavid C Somayajulu {
3070f10a77bbSDavid C Somayajulu 	int i;
3071f10a77bbSDavid C Somayajulu 
3072f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3073f10a77bbSDavid C Somayajulu 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) {
3074f10a77bbSDavid C Somayajulu 
3075f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[0] = 0;
3076f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[1] = 0;
3077f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[2] = 0;
3078f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[3] = 0;
3079f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[4] = 0;
3080f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[5] = 0;
3081f10a77bbSDavid C Somayajulu 
3082f10a77bbSDavid C Somayajulu 			ha->hw.nmcast--;
3083f10a77bbSDavid C Somayajulu 
3084da834d52SDavid C Somayajulu 			mta = mta + ETHER_ADDR_LEN;
3085da834d52SDavid C Somayajulu 			nmcast--;
3086da834d52SDavid C Somayajulu 
3087da834d52SDavid C Somayajulu 			if (nmcast == 0)
3088da834d52SDavid C Somayajulu 				break;
3089f10a77bbSDavid C Somayajulu 		}
3090f10a77bbSDavid C Somayajulu 	}
3091f10a77bbSDavid C Somayajulu 	return 0;
3092f10a77bbSDavid C Somayajulu }
3093f10a77bbSDavid C Somayajulu 
3094f10a77bbSDavid C Somayajulu /*
3095f10a77bbSDavid C Somayajulu  * Name: ql_hw_set_multi
3096da834d52SDavid C Somayajulu  * Function: Sets the Multicast Addresses provided by the host O.S into the
3097f10a77bbSDavid C Somayajulu  *	hardware (for the given interface)
3098f10a77bbSDavid C Somayajulu  */
3099f10a77bbSDavid C Somayajulu int
3100da834d52SDavid C Somayajulu ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast_addr, uint32_t mcnt,
3101f10a77bbSDavid C Somayajulu 	uint32_t add_mac)
3102f10a77bbSDavid C Somayajulu {
3103da834d52SDavid C Somayajulu 	uint8_t *mta = mcast_addr;
3104f10a77bbSDavid C Somayajulu 	int i;
3105f10a77bbSDavid C Somayajulu 	int ret = 0;
3106da834d52SDavid C Somayajulu 	uint32_t count = 0;
3107da834d52SDavid C Somayajulu 	uint8_t *mcast;
3108da834d52SDavid C Somayajulu 
3109da834d52SDavid C Somayajulu 	mcast = ha->hw.mac_addr_arr;
3110da834d52SDavid C Somayajulu 	memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3111f10a77bbSDavid C Somayajulu 
3112f10a77bbSDavid C Somayajulu 	for (i = 0; i < mcnt; i++) {
3113da834d52SDavid C Somayajulu 		if (mta[0] || mta[1] || mta[2] || mta[3] || mta[4] || mta[5]) {
3114f10a77bbSDavid C Somayajulu 			if (add_mac) {
3115da834d52SDavid C Somayajulu 				if (qla_hw_mac_addr_present(ha, mta) != 0) {
3116da834d52SDavid C Somayajulu 					bcopy(mta, mcast, ETHER_ADDR_LEN);
3117da834d52SDavid C Somayajulu 					mcast = mcast + ETHER_ADDR_LEN;
3118da834d52SDavid C Somayajulu 					count++;
3119da834d52SDavid C Somayajulu 				}
3120f10a77bbSDavid C Somayajulu 			} else {
3121da834d52SDavid C Somayajulu 				if (qla_hw_mac_addr_present(ha, mta) == 0) {
3122da834d52SDavid C Somayajulu 					bcopy(mta, mcast, ETHER_ADDR_LEN);
3123da834d52SDavid C Somayajulu 					mcast = mcast + ETHER_ADDR_LEN;
3124da834d52SDavid C Somayajulu 					count++;
3125da834d52SDavid C Somayajulu 				}
3126da834d52SDavid C Somayajulu 			}
3127da834d52SDavid C Somayajulu 		}
3128da834d52SDavid C Somayajulu 		if (count == Q8_MAX_MAC_ADDRS) {
3129da834d52SDavid C Somayajulu 			if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3130da834d52SDavid C Somayajulu 				add_mac, count)) {
3131da834d52SDavid C Somayajulu                 		device_printf(ha->pci_dev, "%s: failed\n",
3132da834d52SDavid C Somayajulu 					__func__);
3133da834d52SDavid C Somayajulu 				return (-1);
3134da834d52SDavid C Somayajulu 			}
3135da834d52SDavid C Somayajulu 
3136da834d52SDavid C Somayajulu 			if (add_mac) {
3137da834d52SDavid C Somayajulu 				qla_hw_add_mcast(ha, ha->hw.mac_addr_arr,
3138da834d52SDavid C Somayajulu 					count);
3139da834d52SDavid C Somayajulu 			} else {
3140da834d52SDavid C Somayajulu 				qla_hw_del_mcast(ha, ha->hw.mac_addr_arr,
3141da834d52SDavid C Somayajulu 					count);
3142da834d52SDavid C Somayajulu 			}
3143da834d52SDavid C Somayajulu 
3144da834d52SDavid C Somayajulu 			count = 0;
3145da834d52SDavid C Somayajulu 			mcast = ha->hw.mac_addr_arr;
3146da834d52SDavid C Somayajulu 			memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3147f10a77bbSDavid C Somayajulu 		}
3148f10a77bbSDavid C Somayajulu 
3149f10a77bbSDavid C Somayajulu 		mta += Q8_MAC_ADDR_LEN;
3150f10a77bbSDavid C Somayajulu 	}
3151da834d52SDavid C Somayajulu 
3152da834d52SDavid C Somayajulu 	if (count) {
3153da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mac,
3154da834d52SDavid C Somayajulu 			count)) {
3155da834d52SDavid C Somayajulu                 	device_printf(ha->pci_dev, "%s: failed\n", __func__);
3156da834d52SDavid C Somayajulu 			return (-1);
3157da834d52SDavid C Somayajulu 		}
3158da834d52SDavid C Somayajulu 		if (add_mac) {
3159da834d52SDavid C Somayajulu 			qla_hw_add_mcast(ha, ha->hw.mac_addr_arr, count);
3160da834d52SDavid C Somayajulu 		} else {
3161da834d52SDavid C Somayajulu 			qla_hw_del_mcast(ha, ha->hw.mac_addr_arr, count);
3162da834d52SDavid C Somayajulu 		}
3163da834d52SDavid C Somayajulu 	}
3164da834d52SDavid C Somayajulu 
3165f10a77bbSDavid C Somayajulu 	return (ret);
3166f10a77bbSDavid C Somayajulu }
3167f10a77bbSDavid C Somayajulu 
3168f10a77bbSDavid C Somayajulu /*
3169f10a77bbSDavid C Somayajulu  * Name: qla_hw_tx_done_locked
3170f10a77bbSDavid C Somayajulu  * Function: Handle Transmit Completions
3171f10a77bbSDavid C Somayajulu  */
3172f10a77bbSDavid C Somayajulu static void
3173f10a77bbSDavid C Somayajulu qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx)
3174f10a77bbSDavid C Somayajulu {
3175f10a77bbSDavid C Somayajulu 	qla_tx_buf_t *txb;
3176f10a77bbSDavid C Somayajulu         qla_hw_t *hw = &ha->hw;
3177f10a77bbSDavid C Somayajulu 	uint32_t comp_idx, comp_count = 0;
3178f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t *hw_tx_cntxt;
3179f10a77bbSDavid C Somayajulu 
3180f10a77bbSDavid C Somayajulu 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3181f10a77bbSDavid C Somayajulu 
3182f10a77bbSDavid C Somayajulu 	/* retrieve index of last entry in tx ring completed */
3183f10a77bbSDavid C Somayajulu 	comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons));
3184f10a77bbSDavid C Somayajulu 
3185f10a77bbSDavid C Somayajulu 	while (comp_idx != hw_tx_cntxt->txr_comp) {
3186f10a77bbSDavid C Somayajulu 
3187f10a77bbSDavid C Somayajulu 		txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp];
3188f10a77bbSDavid C Somayajulu 
3189f10a77bbSDavid C Somayajulu 		hw_tx_cntxt->txr_comp++;
3190f10a77bbSDavid C Somayajulu 		if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS)
3191f10a77bbSDavid C Somayajulu 			hw_tx_cntxt->txr_comp = 0;
3192f10a77bbSDavid C Somayajulu 
3193f10a77bbSDavid C Somayajulu 		comp_count++;
3194f10a77bbSDavid C Somayajulu 
3195f10a77bbSDavid C Somayajulu 		if (txb->m_head) {
3196c8dfaf38SGleb Smirnoff 			if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1);
3197f10a77bbSDavid C Somayajulu 
3198f10a77bbSDavid C Somayajulu 			bus_dmamap_sync(ha->tx_tag, txb->map,
3199f10a77bbSDavid C Somayajulu 				BUS_DMASYNC_POSTWRITE);
3200f10a77bbSDavid C Somayajulu 			bus_dmamap_unload(ha->tx_tag, txb->map);
3201f10a77bbSDavid C Somayajulu 			m_freem(txb->m_head);
3202f10a77bbSDavid C Somayajulu 
3203f10a77bbSDavid C Somayajulu 			txb->m_head = NULL;
3204f10a77bbSDavid C Somayajulu 		}
3205f10a77bbSDavid C Somayajulu 	}
3206f10a77bbSDavid C Somayajulu 
3207f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_free += comp_count;
3208f10a77bbSDavid C Somayajulu 	return;
3209f10a77bbSDavid C Somayajulu }
3210f10a77bbSDavid C Somayajulu 
3211f10a77bbSDavid C Somayajulu /*
3212f10a77bbSDavid C Somayajulu  * Name: ql_hw_tx_done
3213f10a77bbSDavid C Somayajulu  * Function: Handle Transmit Completions
3214f10a77bbSDavid C Somayajulu  */
3215f10a77bbSDavid C Somayajulu void
3216f10a77bbSDavid C Somayajulu ql_hw_tx_done(qla_host_t *ha)
3217f10a77bbSDavid C Somayajulu {
3218f10a77bbSDavid C Somayajulu 	int i;
3219f10a77bbSDavid C Somayajulu 	uint32_t flag = 0;
3220f10a77bbSDavid C Somayajulu 
3221f10a77bbSDavid C Somayajulu 	if (!mtx_trylock(&ha->tx_lock)) {
3222f10a77bbSDavid C Somayajulu        		QL_DPRINT8(ha, (ha->pci_dev,
3223f10a77bbSDavid C Somayajulu 			"%s: !mtx_trylock(&ha->tx_lock)\n", __func__));
3224f10a77bbSDavid C Somayajulu 		return;
3225f10a77bbSDavid C Somayajulu 	}
3226f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
3227f10a77bbSDavid C Somayajulu 		qla_hw_tx_done_locked(ha, i);
3228f10a77bbSDavid C Somayajulu 		if (ha->hw.tx_cntxt[i].txr_free <= (NUM_TX_DESCRIPTORS >> 1))
3229f10a77bbSDavid C Somayajulu 			flag = 1;
3230f10a77bbSDavid C Somayajulu 	}
3231f10a77bbSDavid C Somayajulu 
3232f10a77bbSDavid C Somayajulu 	if (!flag)
3233f10a77bbSDavid C Somayajulu 		ha->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
3234f10a77bbSDavid C Somayajulu 
3235f10a77bbSDavid C Somayajulu 	QLA_TX_UNLOCK(ha);
3236f10a77bbSDavid C Somayajulu 	return;
3237f10a77bbSDavid C Somayajulu }
3238f10a77bbSDavid C Somayajulu 
3239f10a77bbSDavid C Somayajulu void
3240f10a77bbSDavid C Somayajulu ql_update_link_state(qla_host_t *ha)
3241f10a77bbSDavid C Somayajulu {
3242f10a77bbSDavid C Somayajulu 	uint32_t link_state;
3243f10a77bbSDavid C Somayajulu 	uint32_t prev_link_state;
3244f10a77bbSDavid C Somayajulu 
3245f10a77bbSDavid C Somayajulu 	if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
3246f10a77bbSDavid C Somayajulu 		ha->hw.link_up = 0;
3247f10a77bbSDavid C Somayajulu 		return;
3248f10a77bbSDavid C Somayajulu 	}
3249f10a77bbSDavid C Somayajulu 	link_state = READ_REG32(ha, Q8_LINK_STATE);
3250f10a77bbSDavid C Somayajulu 
3251f10a77bbSDavid C Somayajulu 	prev_link_state =  ha->hw.link_up;
3252f10a77bbSDavid C Somayajulu 
3253f10a77bbSDavid C Somayajulu 	if (ha->pci_func == 0)
3254f10a77bbSDavid C Somayajulu 		ha->hw.link_up = (((link_state & 0xF) == 1)? 1 : 0);
3255f10a77bbSDavid C Somayajulu 	else
3256f10a77bbSDavid C Somayajulu 		ha->hw.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
3257f10a77bbSDavid C Somayajulu 
3258f10a77bbSDavid C Somayajulu 	if (prev_link_state !=  ha->hw.link_up) {
3259f10a77bbSDavid C Somayajulu 		if (ha->hw.link_up) {
3260f10a77bbSDavid C Somayajulu 			if_link_state_change(ha->ifp, LINK_STATE_UP);
3261f10a77bbSDavid C Somayajulu 		} else {
3262f10a77bbSDavid C Somayajulu 			if_link_state_change(ha->ifp, LINK_STATE_DOWN);
3263f10a77bbSDavid C Somayajulu 		}
3264f10a77bbSDavid C Somayajulu 	}
3265f10a77bbSDavid C Somayajulu 	return;
3266f10a77bbSDavid C Somayajulu }
3267f10a77bbSDavid C Somayajulu 
3268f10a77bbSDavid C Somayajulu void
3269f10a77bbSDavid C Somayajulu ql_hw_stop_rcv(qla_host_t *ha)
3270f10a77bbSDavid C Somayajulu {
3271f10a77bbSDavid C Somayajulu 	int i, done, count = 100;
3272f10a77bbSDavid C Somayajulu 
32736a62bec0SDavid C Somayajulu 	ha->flags.stop_rcv = 1;
32746a62bec0SDavid C Somayajulu 
327535291c22SDavid C Somayajulu 	while (count) {
3276f10a77bbSDavid C Somayajulu 		done = 1;
3277f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
3278f10a77bbSDavid C Somayajulu 			if (ha->hw.sds[i].rcv_active)
3279f10a77bbSDavid C Somayajulu 				done = 0;
3280f10a77bbSDavid C Somayajulu 		}
3281f10a77bbSDavid C Somayajulu 		if (done)
3282f10a77bbSDavid C Somayajulu 			break;
3283f10a77bbSDavid C Somayajulu 		else
3284f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 10);
328535291c22SDavid C Somayajulu 		count--;
3286f10a77bbSDavid C Somayajulu 	}
3287f10a77bbSDavid C Somayajulu 	if (!count)
3288f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Counter expired.\n", __func__);
3289f10a77bbSDavid C Somayajulu 
3290f10a77bbSDavid C Somayajulu 	return;
3291f10a77bbSDavid C Somayajulu }
3292f10a77bbSDavid C Somayajulu 
3293f10a77bbSDavid C Somayajulu int
3294f10a77bbSDavid C Somayajulu ql_hw_check_health(qla_host_t *ha)
3295f10a77bbSDavid C Somayajulu {
3296f10a77bbSDavid C Somayajulu 	uint32_t val;
3297f10a77bbSDavid C Somayajulu 
3298f10a77bbSDavid C Somayajulu 	ha->hw.health_count++;
3299f10a77bbSDavid C Somayajulu 
3300f10a77bbSDavid C Somayajulu 	if (ha->hw.health_count < 1000)
3301f10a77bbSDavid C Somayajulu 		return 0;
3302f10a77bbSDavid C Somayajulu 
3303f10a77bbSDavid C Somayajulu 	ha->hw.health_count = 0;
3304f10a77bbSDavid C Somayajulu 
3305f10a77bbSDavid C Somayajulu 	val = READ_REG32(ha, Q8_ASIC_TEMPERATURE);
3306f10a77bbSDavid C Somayajulu 
3307f10a77bbSDavid C Somayajulu 	if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) ||
3308f10a77bbSDavid C Somayajulu 		(QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) {
3309f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Temperature Alert [0x%08x]\n",
3310f10a77bbSDavid C Somayajulu 			__func__, val);
3311f10a77bbSDavid C Somayajulu 		return -1;
3312f10a77bbSDavid C Somayajulu 	}
3313f10a77bbSDavid C Somayajulu 
3314f10a77bbSDavid C Somayajulu 	val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
3315f10a77bbSDavid C Somayajulu 
3316f10a77bbSDavid C Somayajulu 	if ((val != ha->hw.hbeat_value) &&
3317467dcb5aSDavid C Somayajulu 		(!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) {
3318f10a77bbSDavid C Somayajulu 		ha->hw.hbeat_value = val;
3319f10a77bbSDavid C Somayajulu 		return 0;
3320f10a77bbSDavid C Somayajulu 	}
3321f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: Heartbeat Failue [0x%08x]\n",
3322f10a77bbSDavid C Somayajulu 		__func__, val);
3323f10a77bbSDavid C Somayajulu 
3324f10a77bbSDavid C Somayajulu 	return -1;
3325f10a77bbSDavid C Somayajulu }
3326f10a77bbSDavid C Somayajulu 
3327f10a77bbSDavid C Somayajulu static int
332835291c22SDavid C Somayajulu qla_init_nic_func(qla_host_t *ha)
332935291c22SDavid C Somayajulu {
333035291c22SDavid C Somayajulu         device_t                dev;
333135291c22SDavid C Somayajulu         q80_init_nic_func_t     *init_nic;
333235291c22SDavid C Somayajulu         q80_init_nic_func_rsp_t *init_nic_rsp;
333335291c22SDavid C Somayajulu         uint32_t                err;
333435291c22SDavid C Somayajulu 
333535291c22SDavid C Somayajulu         dev = ha->pci_dev;
333635291c22SDavid C Somayajulu 
333735291c22SDavid C Somayajulu         init_nic = (q80_init_nic_func_t *)ha->hw.mbox;
333835291c22SDavid C Somayajulu         bzero(init_nic, sizeof(q80_init_nic_func_t));
333935291c22SDavid C Somayajulu 
334035291c22SDavid C Somayajulu         init_nic->opcode = Q8_MBX_INIT_NIC_FUNC;
334135291c22SDavid C Somayajulu         init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2);
334235291c22SDavid C Somayajulu         init_nic->count_version |= Q8_MBX_CMD_VERSION;
334335291c22SDavid C Somayajulu 
334435291c22SDavid C Somayajulu         init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN;
334535291c22SDavid C Somayajulu         init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN;
334635291c22SDavid C Somayajulu         init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN;
334735291c22SDavid C Somayajulu 
334835291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t));
334935291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)init_nic,
335035291c22SDavid C Somayajulu                 (sizeof (q80_init_nic_func_t) >> 2),
335135291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) {
335235291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
335335291c22SDavid C Somayajulu                 return -1;
335435291c22SDavid C Somayajulu         }
335535291c22SDavid C Somayajulu 
335635291c22SDavid C Somayajulu         init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox;
335735291c22SDavid C Somayajulu // qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t));
335835291c22SDavid C Somayajulu 
335935291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status);
336035291c22SDavid C Somayajulu 
336135291c22SDavid C Somayajulu         if (err) {
336235291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
336335291c22SDavid C Somayajulu         }
336435291c22SDavid C Somayajulu 
336535291c22SDavid C Somayajulu         return 0;
336635291c22SDavid C Somayajulu }
336735291c22SDavid C Somayajulu 
336835291c22SDavid C Somayajulu static int
336935291c22SDavid C Somayajulu qla_stop_nic_func(qla_host_t *ha)
337035291c22SDavid C Somayajulu {
337135291c22SDavid C Somayajulu         device_t                dev;
337235291c22SDavid C Somayajulu         q80_stop_nic_func_t     *stop_nic;
337335291c22SDavid C Somayajulu         q80_stop_nic_func_rsp_t *stop_nic_rsp;
337435291c22SDavid C Somayajulu         uint32_t                err;
337535291c22SDavid C Somayajulu 
337635291c22SDavid C Somayajulu         dev = ha->pci_dev;
337735291c22SDavid C Somayajulu 
337835291c22SDavid C Somayajulu         stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox;
337935291c22SDavid C Somayajulu         bzero(stop_nic, sizeof(q80_stop_nic_func_t));
338035291c22SDavid C Somayajulu 
338135291c22SDavid C Somayajulu         stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC;
338235291c22SDavid C Somayajulu         stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2);
338335291c22SDavid C Somayajulu         stop_nic->count_version |= Q8_MBX_CMD_VERSION;
338435291c22SDavid C Somayajulu 
338535291c22SDavid C Somayajulu         stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN;
338635291c22SDavid C Somayajulu         stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN;
338735291c22SDavid C Somayajulu 
338835291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t));
338935291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)stop_nic,
339035291c22SDavid C Somayajulu                 (sizeof (q80_stop_nic_func_t) >> 2),
339135291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) {
339235291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
339335291c22SDavid C Somayajulu                 return -1;
339435291c22SDavid C Somayajulu         }
339535291c22SDavid C Somayajulu 
339635291c22SDavid C Somayajulu         stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox;
339735291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t));
339835291c22SDavid C Somayajulu 
339935291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status);
340035291c22SDavid C Somayajulu 
340135291c22SDavid C Somayajulu         if (err) {
340235291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
340335291c22SDavid C Somayajulu         }
340435291c22SDavid C Somayajulu 
340535291c22SDavid C Somayajulu         return 0;
340635291c22SDavid C Somayajulu }
340735291c22SDavid C Somayajulu 
340835291c22SDavid C Somayajulu static int
340935291c22SDavid C Somayajulu qla_query_fw_dcbx_caps(qla_host_t *ha)
341035291c22SDavid C Somayajulu {
341135291c22SDavid C Somayajulu         device_t                        dev;
341235291c22SDavid C Somayajulu         q80_query_fw_dcbx_caps_t        *fw_dcbx;
341335291c22SDavid C Somayajulu         q80_query_fw_dcbx_caps_rsp_t    *fw_dcbx_rsp;
341435291c22SDavid C Somayajulu         uint32_t                        err;
341535291c22SDavid C Somayajulu 
341635291c22SDavid C Somayajulu         dev = ha->pci_dev;
341735291c22SDavid C Somayajulu 
341835291c22SDavid C Somayajulu         fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox;
341935291c22SDavid C Somayajulu         bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t));
342035291c22SDavid C Somayajulu 
342135291c22SDavid C Somayajulu         fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS;
342235291c22SDavid C Somayajulu         fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2);
342335291c22SDavid C Somayajulu         fw_dcbx->count_version |= Q8_MBX_CMD_VERSION;
342435291c22SDavid C Somayajulu 
342535291c22SDavid C Somayajulu         ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t));
342635291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx,
342735291c22SDavid C Somayajulu                 (sizeof (q80_query_fw_dcbx_caps_t) >> 2),
342835291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) {
342935291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
343035291c22SDavid C Somayajulu                 return -1;
343135291c22SDavid C Somayajulu         }
343235291c22SDavid C Somayajulu 
343335291c22SDavid C Somayajulu         fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox;
343435291c22SDavid C Somayajulu         ql_dump_buf8(ha, __func__, fw_dcbx_rsp,
343535291c22SDavid C Somayajulu                 sizeof (q80_query_fw_dcbx_caps_rsp_t));
343635291c22SDavid C Somayajulu 
343735291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status);
343835291c22SDavid C Somayajulu 
343935291c22SDavid C Somayajulu         if (err) {
344035291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
344135291c22SDavid C Somayajulu         }
344235291c22SDavid C Somayajulu 
344335291c22SDavid C Somayajulu         return 0;
344435291c22SDavid C Somayajulu }
344535291c22SDavid C Somayajulu 
344635291c22SDavid C Somayajulu static int
344735291c22SDavid C Somayajulu qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2,
344835291c22SDavid C Somayajulu         uint32_t aen_mb3, uint32_t aen_mb4)
344935291c22SDavid C Somayajulu {
345035291c22SDavid C Somayajulu         device_t                dev;
345135291c22SDavid C Somayajulu         q80_idc_ack_t           *idc_ack;
345235291c22SDavid C Somayajulu         q80_idc_ack_rsp_t       *idc_ack_rsp;
345335291c22SDavid C Somayajulu         uint32_t                err;
345435291c22SDavid C Somayajulu         int                     count = 300;
345535291c22SDavid C Somayajulu 
345635291c22SDavid C Somayajulu         dev = ha->pci_dev;
345735291c22SDavid C Somayajulu 
345835291c22SDavid C Somayajulu         idc_ack = (q80_idc_ack_t *)ha->hw.mbox;
345935291c22SDavid C Somayajulu         bzero(idc_ack, sizeof(q80_idc_ack_t));
346035291c22SDavid C Somayajulu 
346135291c22SDavid C Somayajulu         idc_ack->opcode = Q8_MBX_IDC_ACK;
346235291c22SDavid C Somayajulu         idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2);
346335291c22SDavid C Somayajulu         idc_ack->count_version |= Q8_MBX_CMD_VERSION;
346435291c22SDavid C Somayajulu 
346535291c22SDavid C Somayajulu         idc_ack->aen_mb1 = aen_mb1;
346635291c22SDavid C Somayajulu         idc_ack->aen_mb2 = aen_mb2;
346735291c22SDavid C Somayajulu         idc_ack->aen_mb3 = aen_mb3;
346835291c22SDavid C Somayajulu         idc_ack->aen_mb4 = aen_mb4;
346935291c22SDavid C Somayajulu 
347035291c22SDavid C Somayajulu         ha->hw.imd_compl= 0;
347135291c22SDavid C Somayajulu 
347235291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)idc_ack,
347335291c22SDavid C Somayajulu                 (sizeof (q80_idc_ack_t) >> 2),
347435291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) {
347535291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
347635291c22SDavid C Somayajulu                 return -1;
347735291c22SDavid C Somayajulu         }
347835291c22SDavid C Somayajulu 
347935291c22SDavid C Somayajulu         idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox;
348035291c22SDavid C Somayajulu 
348135291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status);
348235291c22SDavid C Somayajulu 
348335291c22SDavid C Somayajulu         if (err) {
348435291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
348535291c22SDavid C Somayajulu                 return(-1);
348635291c22SDavid C Somayajulu         }
348735291c22SDavid C Somayajulu 
348835291c22SDavid C Somayajulu         while (count && !ha->hw.imd_compl) {
348935291c22SDavid C Somayajulu                 qla_mdelay(__func__, 100);
349035291c22SDavid C Somayajulu                 count--;
349135291c22SDavid C Somayajulu         }
349235291c22SDavid C Somayajulu 
349335291c22SDavid C Somayajulu         if (!count)
349435291c22SDavid C Somayajulu                 return -1;
349535291c22SDavid C Somayajulu         else
349635291c22SDavid C Somayajulu                 device_printf(dev, "%s: count %d\n", __func__, count);
349735291c22SDavid C Somayajulu 
349835291c22SDavid C Somayajulu         return (0);
349935291c22SDavid C Somayajulu }
350035291c22SDavid C Somayajulu 
350135291c22SDavid C Somayajulu static int
350235291c22SDavid C Somayajulu qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits)
350335291c22SDavid C Somayajulu {
350435291c22SDavid C Somayajulu         device_t                dev;
350535291c22SDavid C Somayajulu         q80_set_port_cfg_t      *pcfg;
350635291c22SDavid C Somayajulu         q80_set_port_cfg_rsp_t  *pfg_rsp;
350735291c22SDavid C Somayajulu         uint32_t                err;
350835291c22SDavid C Somayajulu         int                     count = 300;
350935291c22SDavid C Somayajulu 
351035291c22SDavid C Somayajulu         dev = ha->pci_dev;
351135291c22SDavid C Somayajulu 
351235291c22SDavid C Somayajulu         pcfg = (q80_set_port_cfg_t *)ha->hw.mbox;
351335291c22SDavid C Somayajulu         bzero(pcfg, sizeof(q80_set_port_cfg_t));
351435291c22SDavid C Somayajulu 
351535291c22SDavid C Somayajulu         pcfg->opcode = Q8_MBX_SET_PORT_CONFIG;
351635291c22SDavid C Somayajulu         pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2);
351735291c22SDavid C Somayajulu         pcfg->count_version |= Q8_MBX_CMD_VERSION;
351835291c22SDavid C Somayajulu 
351935291c22SDavid C Somayajulu         pcfg->cfg_bits = cfg_bits;
352035291c22SDavid C Somayajulu 
352135291c22SDavid C Somayajulu         device_printf(dev, "%s: cfg_bits"
352235291c22SDavid C Somayajulu                 " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
352335291c22SDavid C Somayajulu                 " [0x%x, 0x%x, 0x%x]\n", __func__,
352435291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
352535291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
352635291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0));
352735291c22SDavid C Somayajulu 
352835291c22SDavid C Somayajulu         ha->hw.imd_compl= 0;
352935291c22SDavid C Somayajulu 
353035291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
353135291c22SDavid C Somayajulu                 (sizeof (q80_set_port_cfg_t) >> 2),
353235291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) {
353335291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
353435291c22SDavid C Somayajulu                 return -1;
353535291c22SDavid C Somayajulu         }
353635291c22SDavid C Somayajulu 
353735291c22SDavid C Somayajulu         pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox;
353835291c22SDavid C Somayajulu 
353935291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status);
354035291c22SDavid C Somayajulu 
354135291c22SDavid C Somayajulu         if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) {
354235291c22SDavid C Somayajulu                 while (count && !ha->hw.imd_compl) {
354335291c22SDavid C Somayajulu                         qla_mdelay(__func__, 100);
354435291c22SDavid C Somayajulu                         count--;
354535291c22SDavid C Somayajulu                 }
354635291c22SDavid C Somayajulu                 if (count) {
354735291c22SDavid C Somayajulu                         device_printf(dev, "%s: count %d\n", __func__, count);
354835291c22SDavid C Somayajulu 
354935291c22SDavid C Somayajulu                         err = 0;
355035291c22SDavid C Somayajulu                 }
355135291c22SDavid C Somayajulu         }
355235291c22SDavid C Somayajulu 
355335291c22SDavid C Somayajulu         if (err) {
355435291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
355535291c22SDavid C Somayajulu                 return(-1);
355635291c22SDavid C Somayajulu         }
355735291c22SDavid C Somayajulu 
355835291c22SDavid C Somayajulu         return (0);
355935291c22SDavid C Somayajulu }
356035291c22SDavid C Somayajulu 
356135291c22SDavid C Somayajulu 
356235291c22SDavid C Somayajulu static int
3563f10a77bbSDavid C Somayajulu qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size)
3564f10a77bbSDavid C Somayajulu {
3565f10a77bbSDavid C Somayajulu 	uint32_t			err;
3566f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
3567f10a77bbSDavid C Somayajulu 	q80_config_md_templ_size_t	*md_size;
3568f10a77bbSDavid C Somayajulu 	q80_config_md_templ_size_rsp_t	*md_size_rsp;
3569f10a77bbSDavid C Somayajulu 
35706a62bec0SDavid C Somayajulu #ifndef QL_LDFLASH_FW
357135291c22SDavid C Somayajulu 
35726a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *hdr;
35736a62bec0SDavid C Somayajulu 
35746a62bec0SDavid C Somayajulu 	hdr = (ql_minidump_template_hdr_t *)ql83xx_minidump;
35756a62bec0SDavid C Somayajulu 	*size = hdr->size_of_template;
357635291c22SDavid C Somayajulu 	return (0);
357735291c22SDavid C Somayajulu 
357835291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
357935291c22SDavid C Somayajulu 
3580f10a77bbSDavid C Somayajulu 	md_size = (q80_config_md_templ_size_t *) ha->hw.mbox;
3581f10a77bbSDavid C Somayajulu 	bzero(md_size, sizeof(q80_config_md_templ_size_t));
3582f10a77bbSDavid C Somayajulu 
3583f10a77bbSDavid C Somayajulu 	md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE;
3584f10a77bbSDavid C Somayajulu 	md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2);
3585f10a77bbSDavid C Somayajulu 	md_size->count_version |= Q8_MBX_CMD_VERSION;
3586f10a77bbSDavid C Somayajulu 
3587f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *) md_size,
3588f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox,
3589f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) {
3590f10a77bbSDavid C Somayajulu 
3591f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
3592f10a77bbSDavid C Somayajulu 
3593f10a77bbSDavid C Somayajulu 		return (-1);
3594f10a77bbSDavid C Somayajulu 	}
3595f10a77bbSDavid C Somayajulu 
3596f10a77bbSDavid C Somayajulu 	md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox;
3597f10a77bbSDavid C Somayajulu 
3598f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status);
3599f10a77bbSDavid C Somayajulu 
3600f10a77bbSDavid C Somayajulu         if (err) {
3601f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3602f10a77bbSDavid C Somayajulu 		return(-1);
3603f10a77bbSDavid C Somayajulu         }
3604f10a77bbSDavid C Somayajulu 
3605f10a77bbSDavid C Somayajulu 	*size = md_size_rsp->templ_size;
3606f10a77bbSDavid C Somayajulu 
3607f10a77bbSDavid C Somayajulu 	return (0);
3608f10a77bbSDavid C Somayajulu }
3609f10a77bbSDavid C Somayajulu 
3610f10a77bbSDavid C Somayajulu static int
361135291c22SDavid C Somayajulu qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits)
361235291c22SDavid C Somayajulu {
361335291c22SDavid C Somayajulu         device_t                dev;
361435291c22SDavid C Somayajulu         q80_get_port_cfg_t      *pcfg;
361535291c22SDavid C Somayajulu         q80_get_port_cfg_rsp_t  *pcfg_rsp;
361635291c22SDavid C Somayajulu         uint32_t                err;
361735291c22SDavid C Somayajulu 
361835291c22SDavid C Somayajulu         dev = ha->pci_dev;
361935291c22SDavid C Somayajulu 
362035291c22SDavid C Somayajulu         pcfg = (q80_get_port_cfg_t *)ha->hw.mbox;
362135291c22SDavid C Somayajulu         bzero(pcfg, sizeof(q80_get_port_cfg_t));
362235291c22SDavid C Somayajulu 
362335291c22SDavid C Somayajulu         pcfg->opcode = Q8_MBX_GET_PORT_CONFIG;
362435291c22SDavid C Somayajulu         pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2);
362535291c22SDavid C Somayajulu         pcfg->count_version |= Q8_MBX_CMD_VERSION;
362635291c22SDavid C Somayajulu 
362735291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
362835291c22SDavid C Somayajulu                 (sizeof (q80_get_port_cfg_t) >> 2),
362935291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) {
363035291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
363135291c22SDavid C Somayajulu                 return -1;
363235291c22SDavid C Somayajulu         }
363335291c22SDavid C Somayajulu 
363435291c22SDavid C Somayajulu         pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox;
363535291c22SDavid C Somayajulu 
363635291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status);
363735291c22SDavid C Somayajulu 
363835291c22SDavid C Somayajulu         if (err) {
363935291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
364035291c22SDavid C Somayajulu                 return(-1);
364135291c22SDavid C Somayajulu         }
364235291c22SDavid C Somayajulu 
364335291c22SDavid C Somayajulu         device_printf(dev, "%s: [cfg_bits, port type]"
364435291c22SDavid C Somayajulu                 " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
364535291c22SDavid C Somayajulu                 " [0x%x, 0x%x, 0x%x]\n", __func__,
364635291c22SDavid C Somayajulu                 pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type,
364735291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
364835291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
364935291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)
365035291c22SDavid C Somayajulu                 );
365135291c22SDavid C Somayajulu 
365235291c22SDavid C Somayajulu         *cfg_bits = pcfg_rsp->cfg_bits;
365335291c22SDavid C Somayajulu 
365435291c22SDavid C Somayajulu         return (0);
365535291c22SDavid C Somayajulu }
365635291c22SDavid C Somayajulu 
365735291c22SDavid C Somayajulu int
365835291c22SDavid C Somayajulu qla_iscsi_pdu(qla_host_t *ha, struct mbuf *mp)
365935291c22SDavid C Somayajulu {
366035291c22SDavid C Somayajulu         struct ether_vlan_header        *eh;
366135291c22SDavid C Somayajulu         uint16_t                        etype;
366235291c22SDavid C Somayajulu         struct ip                       *ip = NULL;
366335291c22SDavid C Somayajulu         struct ip6_hdr                  *ip6 = NULL;
366435291c22SDavid C Somayajulu         struct tcphdr                   *th = NULL;
366535291c22SDavid C Somayajulu         uint32_t                        hdrlen;
366635291c22SDavid C Somayajulu         uint32_t                        offset;
366735291c22SDavid C Somayajulu         uint8_t                         buf[sizeof(struct ip6_hdr)];
366835291c22SDavid C Somayajulu 
366935291c22SDavid C Somayajulu         eh = mtod(mp, struct ether_vlan_header *);
367035291c22SDavid C Somayajulu 
367135291c22SDavid C Somayajulu         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
367235291c22SDavid C Somayajulu                 hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
367335291c22SDavid C Somayajulu                 etype = ntohs(eh->evl_proto);
367435291c22SDavid C Somayajulu         } else {
367535291c22SDavid C Somayajulu                 hdrlen = ETHER_HDR_LEN;
367635291c22SDavid C Somayajulu                 etype = ntohs(eh->evl_encap_proto);
367735291c22SDavid C Somayajulu         }
367835291c22SDavid C Somayajulu 
367935291c22SDavid C Somayajulu 	if (etype == ETHERTYPE_IP) {
368035291c22SDavid C Somayajulu 
368135291c22SDavid C Somayajulu 		offset = (hdrlen + sizeof (struct ip));
368235291c22SDavid C Somayajulu 
368335291c22SDavid C Somayajulu 		if (mp->m_len >= offset) {
368435291c22SDavid C Somayajulu                         ip = (struct ip *)(mp->m_data + hdrlen);
368535291c22SDavid C Somayajulu 		} else {
368635291c22SDavid C Somayajulu 			m_copydata(mp, hdrlen, sizeof (struct ip), buf);
368735291c22SDavid C Somayajulu                         ip = (struct ip *)buf;
368835291c22SDavid C Somayajulu 		}
368935291c22SDavid C Somayajulu 
369035291c22SDavid C Somayajulu                 if (ip->ip_p == IPPROTO_TCP) {
369135291c22SDavid C Somayajulu 
369235291c22SDavid C Somayajulu 			hdrlen += ip->ip_hl << 2;
369335291c22SDavid C Somayajulu 			offset = hdrlen + 4;
369435291c22SDavid C Somayajulu 
369535291c22SDavid C Somayajulu 			if (mp->m_len >= offset) {
36966a62bec0SDavid C Somayajulu 				th = (struct tcphdr *)(mp->m_data + hdrlen);;
369735291c22SDavid C Somayajulu 			} else {
369835291c22SDavid C Somayajulu                                 m_copydata(mp, hdrlen, 4, buf);
369935291c22SDavid C Somayajulu 				th = (struct tcphdr *)buf;
370035291c22SDavid C Somayajulu 			}
370135291c22SDavid C Somayajulu                 }
370235291c22SDavid C Somayajulu 
370335291c22SDavid C Somayajulu 	} else if (etype == ETHERTYPE_IPV6) {
370435291c22SDavid C Somayajulu 
370535291c22SDavid C Somayajulu 		offset = (hdrlen + sizeof (struct ip6_hdr));
370635291c22SDavid C Somayajulu 
370735291c22SDavid C Somayajulu 		if (mp->m_len >= offset) {
370835291c22SDavid C Somayajulu                         ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen);
370935291c22SDavid C Somayajulu 		} else {
371035291c22SDavid C Somayajulu                         m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf);
371135291c22SDavid C Somayajulu                         ip6 = (struct ip6_hdr *)buf;
371235291c22SDavid C Somayajulu 		}
371335291c22SDavid C Somayajulu 
371435291c22SDavid C Somayajulu                 if (ip6->ip6_nxt == IPPROTO_TCP) {
371535291c22SDavid C Somayajulu 
371635291c22SDavid C Somayajulu 			hdrlen += sizeof(struct ip6_hdr);
371735291c22SDavid C Somayajulu 			offset = hdrlen + 4;
371835291c22SDavid C Somayajulu 
371935291c22SDavid C Somayajulu 			if (mp->m_len >= offset) {
37206a62bec0SDavid C Somayajulu 				th = (struct tcphdr *)(mp->m_data + hdrlen);;
372135291c22SDavid C Somayajulu 			} else {
372235291c22SDavid C Somayajulu 				m_copydata(mp, hdrlen, 4, buf);
372335291c22SDavid C Somayajulu 				th = (struct tcphdr *)buf;
372435291c22SDavid C Somayajulu 			}
372535291c22SDavid C Somayajulu                 }
372635291c22SDavid C Somayajulu 	}
372735291c22SDavid C Somayajulu 
372835291c22SDavid C Somayajulu         if (th != NULL) {
372935291c22SDavid C Somayajulu                 if ((th->th_sport == htons(3260)) ||
373035291c22SDavid C Somayajulu                         (th->th_dport == htons(3260)))
373135291c22SDavid C Somayajulu                         return 0;
373235291c22SDavid C Somayajulu         }
373335291c22SDavid C Somayajulu         return (-1);
373435291c22SDavid C Somayajulu }
373535291c22SDavid C Somayajulu 
373635291c22SDavid C Somayajulu void
373735291c22SDavid C Somayajulu qla_hw_async_event(qla_host_t *ha)
373835291c22SDavid C Somayajulu {
373935291c22SDavid C Somayajulu         switch (ha->hw.aen_mb0) {
374035291c22SDavid C Somayajulu         case 0x8101:
374135291c22SDavid C Somayajulu                 (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2,
374235291c22SDavid C Somayajulu                         ha->hw.aen_mb3, ha->hw.aen_mb4);
374335291c22SDavid C Somayajulu 
374435291c22SDavid C Somayajulu                 break;
374535291c22SDavid C Somayajulu 
374635291c22SDavid C Somayajulu         default:
374735291c22SDavid C Somayajulu                 break;
374835291c22SDavid C Somayajulu         }
374935291c22SDavid C Somayajulu 
375035291c22SDavid C Somayajulu         return;
375135291c22SDavid C Somayajulu }
375235291c22SDavid C Somayajulu 
375335291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
375435291c22SDavid C Somayajulu static int
37556a62bec0SDavid C Somayajulu ql_get_minidump_template(qla_host_t *ha)
3756f10a77bbSDavid C Somayajulu {
3757f10a77bbSDavid C Somayajulu 	uint32_t			err;
3758f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
3759f10a77bbSDavid C Somayajulu 	q80_config_md_templ_cmd_t	*md_templ;
3760f10a77bbSDavid C Somayajulu 	q80_config_md_templ_cmd_rsp_t	*md_templ_rsp;
3761f10a77bbSDavid C Somayajulu 
3762f10a77bbSDavid C Somayajulu 	md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox;
3763f10a77bbSDavid C Somayajulu 	bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t)));
3764f10a77bbSDavid C Somayajulu 
3765f10a77bbSDavid C Somayajulu 	md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT;
3766f10a77bbSDavid C Somayajulu 	md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2);
3767f10a77bbSDavid C Somayajulu 	md_templ->count_version |= Q8_MBX_CMD_VERSION;
3768f10a77bbSDavid C Somayajulu 
3769f10a77bbSDavid C Somayajulu 	md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr;
3770f10a77bbSDavid C Somayajulu 	md_templ->buff_size = ha->hw.dma_buf.minidump.size;
3771f10a77bbSDavid C Somayajulu 
3772f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *) md_templ,
3773f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_cmd_t) >> 2),
3774f10a77bbSDavid C Somayajulu 		 ha->hw.mbox,
3775f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) {
3776f10a77bbSDavid C Somayajulu 
3777f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
3778f10a77bbSDavid C Somayajulu 
3779f10a77bbSDavid C Somayajulu 		return (-1);
3780f10a77bbSDavid C Somayajulu 	}
3781f10a77bbSDavid C Somayajulu 
3782f10a77bbSDavid C Somayajulu 	md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox;
3783f10a77bbSDavid C Somayajulu 
3784f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status);
3785f10a77bbSDavid C Somayajulu 
3786f10a77bbSDavid C Somayajulu 	if (err) {
3787f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3788f10a77bbSDavid C Somayajulu 		return (-1);
3789f10a77bbSDavid C Somayajulu 	}
3790f10a77bbSDavid C Somayajulu 
3791f10a77bbSDavid C Somayajulu 	return (0);
3792f10a77bbSDavid C Somayajulu 
3793f10a77bbSDavid C Somayajulu }
379435291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
3795f10a77bbSDavid C Somayajulu 
37966a62bec0SDavid C Somayajulu /*
37976a62bec0SDavid C Somayajulu  * Minidump related functionality
37986a62bec0SDavid C Somayajulu  */
37996a62bec0SDavid C Somayajulu 
38006a62bec0SDavid C Somayajulu static int ql_parse_template(qla_host_t *ha);
38016a62bec0SDavid C Somayajulu 
38026a62bec0SDavid C Somayajulu static uint32_t ql_rdcrb(qla_host_t *ha,
38036a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdcrb_t *crb_entry,
38046a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
38056a62bec0SDavid C Somayajulu 
38066a62bec0SDavid C Somayajulu static uint32_t ql_pollrd(qla_host_t *ha,
38076a62bec0SDavid C Somayajulu 			ql_minidump_entry_pollrd_t *entry,
38086a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
38096a62bec0SDavid C Somayajulu 
38106a62bec0SDavid C Somayajulu static uint32_t ql_pollrd_modify_write(qla_host_t *ha,
38116a62bec0SDavid C Somayajulu 			ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
38126a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38136a62bec0SDavid C Somayajulu 
38146a62bec0SDavid C Somayajulu static uint32_t ql_L2Cache(qla_host_t *ha,
38156a62bec0SDavid C Somayajulu 			ql_minidump_entry_cache_t *cacheEntry,
38166a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
38176a62bec0SDavid C Somayajulu 
38186a62bec0SDavid C Somayajulu static uint32_t ql_L1Cache(qla_host_t *ha,
38196a62bec0SDavid C Somayajulu 			ql_minidump_entry_cache_t *cacheEntry,
38206a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38216a62bec0SDavid C Somayajulu 
38226a62bec0SDavid C Somayajulu static uint32_t ql_rdocm(qla_host_t *ha,
38236a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdocm_t *ocmEntry,
38246a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38256a62bec0SDavid C Somayajulu 
38266a62bec0SDavid C Somayajulu static uint32_t ql_rdmem(qla_host_t *ha,
38276a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdmem_t *mem_entry,
38286a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38296a62bec0SDavid C Somayajulu 
38306a62bec0SDavid C Somayajulu static uint32_t ql_rdrom(qla_host_t *ha,
38316a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdrom_t *romEntry,
38326a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38336a62bec0SDavid C Somayajulu 
38346a62bec0SDavid C Somayajulu static uint32_t ql_rdmux(qla_host_t *ha,
38356a62bec0SDavid C Somayajulu 			ql_minidump_entry_mux_t *muxEntry,
38366a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38376a62bec0SDavid C Somayajulu 
38386a62bec0SDavid C Somayajulu static uint32_t ql_rdmux2(qla_host_t *ha,
38396a62bec0SDavid C Somayajulu 			ql_minidump_entry_mux2_t *muxEntry,
38406a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38416a62bec0SDavid C Somayajulu 
38426a62bec0SDavid C Somayajulu static uint32_t ql_rdqueue(qla_host_t *ha,
38436a62bec0SDavid C Somayajulu 			ql_minidump_entry_queue_t *queueEntry,
38446a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38456a62bec0SDavid C Somayajulu 
38466a62bec0SDavid C Somayajulu static uint32_t ql_cntrl(qla_host_t *ha,
38476a62bec0SDavid C Somayajulu 			ql_minidump_template_hdr_t *template_hdr,
38486a62bec0SDavid C Somayajulu 			ql_minidump_entry_cntrl_t *crbEntry);
38496a62bec0SDavid C Somayajulu 
38506a62bec0SDavid C Somayajulu 
38516a62bec0SDavid C Somayajulu static uint32_t
38526a62bec0SDavid C Somayajulu ql_minidump_size(qla_host_t *ha)
38536a62bec0SDavid C Somayajulu {
38546a62bec0SDavid C Somayajulu 	uint32_t i, k;
38556a62bec0SDavid C Somayajulu 	uint32_t size = 0;
38566a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *hdr;
38576a62bec0SDavid C Somayajulu 
38586a62bec0SDavid C Somayajulu 	hdr = (ql_minidump_template_hdr_t *)ha->hw.dma_buf.minidump.dma_b;
38596a62bec0SDavid C Somayajulu 
38606a62bec0SDavid C Somayajulu 	i = 0x2;
38616a62bec0SDavid C Somayajulu 
38626a62bec0SDavid C Somayajulu 	for (k = 1; k < QL_DBG_CAP_SIZE_ARRAY_LEN; k++) {
38636a62bec0SDavid C Somayajulu 		if (i & ha->hw.mdump_capture_mask)
38646a62bec0SDavid C Somayajulu 			size += hdr->capture_size_array[k];
38656a62bec0SDavid C Somayajulu 		i = i << 1;
38666a62bec0SDavid C Somayajulu 	}
38676a62bec0SDavid C Somayajulu 	return (size);
38686a62bec0SDavid C Somayajulu }
38696a62bec0SDavid C Somayajulu 
38706a62bec0SDavid C Somayajulu static void
38716a62bec0SDavid C Somayajulu ql_free_minidump_buffer(qla_host_t *ha)
38726a62bec0SDavid C Somayajulu {
38736a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_buffer != NULL) {
38746a62bec0SDavid C Somayajulu 		free(ha->hw.mdump_buffer, M_QLA83XXBUF);
38756a62bec0SDavid C Somayajulu 		ha->hw.mdump_buffer = NULL;
38766a62bec0SDavid C Somayajulu 		ha->hw.mdump_buffer_size = 0;
38776a62bec0SDavid C Somayajulu 	}
38786a62bec0SDavid C Somayajulu 	return;
38796a62bec0SDavid C Somayajulu }
38806a62bec0SDavid C Somayajulu 
3881f10a77bbSDavid C Somayajulu static int
38826a62bec0SDavid C Somayajulu ql_alloc_minidump_buffer(qla_host_t *ha)
38836a62bec0SDavid C Somayajulu {
38846a62bec0SDavid C Somayajulu 	ha->hw.mdump_buffer_size = ql_minidump_size(ha);
38856a62bec0SDavid C Somayajulu 
38866a62bec0SDavid C Somayajulu 	if (!ha->hw.mdump_buffer_size)
38876a62bec0SDavid C Somayajulu 		return (-1);
38886a62bec0SDavid C Somayajulu 
38896a62bec0SDavid C Somayajulu 	ha->hw.mdump_buffer = malloc(ha->hw.mdump_buffer_size, M_QLA83XXBUF,
38906a62bec0SDavid C Somayajulu 					M_NOWAIT);
38916a62bec0SDavid C Somayajulu 
38926a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_buffer == NULL)
38936a62bec0SDavid C Somayajulu 		return (-1);
38946a62bec0SDavid C Somayajulu 
38956a62bec0SDavid C Somayajulu 	return (0);
38966a62bec0SDavid C Somayajulu }
38976a62bec0SDavid C Somayajulu 
38986a62bec0SDavid C Somayajulu static void
38996a62bec0SDavid C Somayajulu ql_free_minidump_template_buffer(qla_host_t *ha)
39006a62bec0SDavid C Somayajulu {
39016a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_template != NULL) {
39026a62bec0SDavid C Somayajulu 		free(ha->hw.mdump_template, M_QLA83XXBUF);
39036a62bec0SDavid C Somayajulu 		ha->hw.mdump_template = NULL;
39046a62bec0SDavid C Somayajulu 		ha->hw.mdump_template_size = 0;
39056a62bec0SDavid C Somayajulu 	}
39066a62bec0SDavid C Somayajulu 	return;
39076a62bec0SDavid C Somayajulu }
39086a62bec0SDavid C Somayajulu 
39096a62bec0SDavid C Somayajulu static int
39106a62bec0SDavid C Somayajulu ql_alloc_minidump_template_buffer(qla_host_t *ha)
39116a62bec0SDavid C Somayajulu {
39126a62bec0SDavid C Somayajulu 	ha->hw.mdump_template_size = ha->hw.dma_buf.minidump.size;
39136a62bec0SDavid C Somayajulu 
39146a62bec0SDavid C Somayajulu 	ha->hw.mdump_template = malloc(ha->hw.mdump_template_size,
39156a62bec0SDavid C Somayajulu 					M_QLA83XXBUF, M_NOWAIT);
39166a62bec0SDavid C Somayajulu 
39176a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_template == NULL)
39186a62bec0SDavid C Somayajulu 		return (-1);
39196a62bec0SDavid C Somayajulu 
39206a62bec0SDavid C Somayajulu 	return (0);
39216a62bec0SDavid C Somayajulu }
39226a62bec0SDavid C Somayajulu 
39236a62bec0SDavid C Somayajulu static int
39246a62bec0SDavid C Somayajulu ql_alloc_minidump_buffers(qla_host_t *ha)
39256a62bec0SDavid C Somayajulu {
39266a62bec0SDavid C Somayajulu 	int ret;
39276a62bec0SDavid C Somayajulu 
39286a62bec0SDavid C Somayajulu 	ret = ql_alloc_minidump_template_buffer(ha);
39296a62bec0SDavid C Somayajulu 
39306a62bec0SDavid C Somayajulu 	if (ret)
39316a62bec0SDavid C Somayajulu 		return (ret);
39326a62bec0SDavid C Somayajulu 
39336a62bec0SDavid C Somayajulu 	ret = ql_alloc_minidump_buffer(ha);
39346a62bec0SDavid C Somayajulu 
39356a62bec0SDavid C Somayajulu 	if (ret)
39366a62bec0SDavid C Somayajulu 		ql_free_minidump_template_buffer(ha);
39376a62bec0SDavid C Somayajulu 
39386a62bec0SDavid C Somayajulu 	return (ret);
39396a62bec0SDavid C Somayajulu }
39406a62bec0SDavid C Somayajulu 
39416a62bec0SDavid C Somayajulu 
39426a62bec0SDavid C Somayajulu static uint32_t
39436a62bec0SDavid C Somayajulu ql_validate_minidump_checksum(qla_host_t *ha)
39446a62bec0SDavid C Somayajulu {
39456a62bec0SDavid C Somayajulu         uint64_t sum = 0;
39466a62bec0SDavid C Somayajulu 	int count;
39476a62bec0SDavid C Somayajulu 	uint32_t *template_buff;
39486a62bec0SDavid C Somayajulu 
39496a62bec0SDavid C Somayajulu 	count = ha->hw.dma_buf.minidump.size / sizeof (uint32_t);
39506a62bec0SDavid C Somayajulu 	template_buff = ha->hw.dma_buf.minidump.dma_b;
39516a62bec0SDavid C Somayajulu 
39526a62bec0SDavid C Somayajulu 	while (count-- > 0) {
39536a62bec0SDavid C Somayajulu 		sum += *template_buff++;
39546a62bec0SDavid C Somayajulu 	}
39556a62bec0SDavid C Somayajulu 
39566a62bec0SDavid C Somayajulu 	while (sum >> 32) {
39576a62bec0SDavid C Somayajulu 		sum = (sum & 0xFFFFFFFF) + (sum >> 32);
39586a62bec0SDavid C Somayajulu 	}
39596a62bec0SDavid C Somayajulu 
39606a62bec0SDavid C Somayajulu 	return (~sum);
39616a62bec0SDavid C Somayajulu }
39626a62bec0SDavid C Somayajulu 
39636a62bec0SDavid C Somayajulu int
39646a62bec0SDavid C Somayajulu ql_minidump_init(qla_host_t *ha)
3965f10a77bbSDavid C Somayajulu {
396635291c22SDavid C Somayajulu 	int		ret = 0;
3967f10a77bbSDavid C Somayajulu 	uint32_t	template_size = 0;
3968f10a77bbSDavid C Somayajulu 	device_t	dev = ha->pci_dev;
3969f10a77bbSDavid C Somayajulu 
3970f10a77bbSDavid C Somayajulu 	/*
3971f10a77bbSDavid C Somayajulu 	 * Get Minidump Template Size
3972f10a77bbSDavid C Somayajulu  	 */
3973f10a77bbSDavid C Somayajulu 	ret = qla_get_minidump_tmplt_size(ha, &template_size);
3974f10a77bbSDavid C Somayajulu 
3975f10a77bbSDavid C Somayajulu 	if (ret || (template_size == 0)) {
3976f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret,
3977f10a77bbSDavid C Somayajulu 			template_size);
3978f10a77bbSDavid C Somayajulu 		return (-1);
3979f10a77bbSDavid C Somayajulu 	}
3980f10a77bbSDavid C Somayajulu 
3981f10a77bbSDavid C Somayajulu 	/*
3982f10a77bbSDavid C Somayajulu 	 * Allocate Memory for Minidump Template
3983f10a77bbSDavid C Somayajulu 	 */
3984f10a77bbSDavid C Somayajulu 
3985f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.minidump.alignment = 8;
3986f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.minidump.size = template_size;
3987f10a77bbSDavid C Somayajulu 
398835291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
3989f10a77bbSDavid C Somayajulu 	if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) {
3990f10a77bbSDavid C Somayajulu 
3991f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: minidump dma alloc failed\n", __func__);
3992f10a77bbSDavid C Somayajulu 
3993f10a77bbSDavid C Somayajulu 		return (-1);
3994f10a77bbSDavid C Somayajulu 	}
3995f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.flags.minidump = 1;
3996f10a77bbSDavid C Somayajulu 
3997f10a77bbSDavid C Somayajulu 	/*
3998f10a77bbSDavid C Somayajulu 	 * Retrieve Minidump Template
3999f10a77bbSDavid C Somayajulu 	 */
40006a62bec0SDavid C Somayajulu 	ret = ql_get_minidump_template(ha);
400135291c22SDavid C Somayajulu #else
400235291c22SDavid C Somayajulu 	ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump;
40036a62bec0SDavid C Somayajulu 
400435291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
4005f10a77bbSDavid C Somayajulu 
40066a62bec0SDavid C Somayajulu 	if (ret == 0) {
40076a62bec0SDavid C Somayajulu 
40086a62bec0SDavid C Somayajulu 		ret = ql_validate_minidump_checksum(ha);
40096a62bec0SDavid C Somayajulu 
40106a62bec0SDavid C Somayajulu 		if (ret == 0) {
40116a62bec0SDavid C Somayajulu 
40126a62bec0SDavid C Somayajulu 			ret = ql_alloc_minidump_buffers(ha);
40136a62bec0SDavid C Somayajulu 
40146a62bec0SDavid C Somayajulu 			if (ret == 0)
4015f10a77bbSDavid C Somayajulu 		ha->hw.mdump_init = 1;
40166a62bec0SDavid C Somayajulu 			else
40176a62bec0SDavid C Somayajulu 				device_printf(dev,
40186a62bec0SDavid C Somayajulu 					"%s: ql_alloc_minidump_buffers"
40196a62bec0SDavid C Somayajulu 					" failed\n", __func__);
40206a62bec0SDavid C Somayajulu 		} else {
40216a62bec0SDavid C Somayajulu 			device_printf(dev, "%s: ql_validate_minidump_checksum"
40226a62bec0SDavid C Somayajulu 				" failed\n", __func__);
4023f10a77bbSDavid C Somayajulu 		}
40246a62bec0SDavid C Somayajulu 	} else {
40256a62bec0SDavid C Somayajulu 		device_printf(dev, "%s: ql_get_minidump_template failed\n",
40266a62bec0SDavid C Somayajulu 			 __func__);
40276a62bec0SDavid C Somayajulu 	}
40286a62bec0SDavid C Somayajulu 
40296a62bec0SDavid C Somayajulu 	if (ret)
40306a62bec0SDavid C Somayajulu 		ql_minidump_free(ha);
4031f10a77bbSDavid C Somayajulu 
4032f10a77bbSDavid C Somayajulu 	return (ret);
4033f10a77bbSDavid C Somayajulu }
4034f10a77bbSDavid C Somayajulu 
4035f10a77bbSDavid C Somayajulu static void
40366a62bec0SDavid C Somayajulu ql_minidump_free(qla_host_t *ha)
4037f10a77bbSDavid C Somayajulu {
4038f10a77bbSDavid C Somayajulu 	ha->hw.mdump_init = 0;
4039f10a77bbSDavid C Somayajulu 	if (ha->hw.dma_buf.flags.minidump) {
4040f10a77bbSDavid C Somayajulu 		ha->hw.dma_buf.flags.minidump = 0;
4041f10a77bbSDavid C Somayajulu 		ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump);
4042f10a77bbSDavid C Somayajulu 	}
40436a62bec0SDavid C Somayajulu 
40446a62bec0SDavid C Somayajulu 	ql_free_minidump_template_buffer(ha);
40456a62bec0SDavid C Somayajulu 	ql_free_minidump_buffer(ha);
40466a62bec0SDavid C Somayajulu 
4047f10a77bbSDavid C Somayajulu 	return;
4048f10a77bbSDavid C Somayajulu }
4049f10a77bbSDavid C Somayajulu 
4050f10a77bbSDavid C Somayajulu void
4051f10a77bbSDavid C Somayajulu ql_minidump(qla_host_t *ha)
4052f10a77bbSDavid C Somayajulu {
4053f10a77bbSDavid C Somayajulu 	if (!ha->hw.mdump_init)
4054f10a77bbSDavid C Somayajulu 		return;
4055f10a77bbSDavid C Somayajulu 
40566a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_done)
4057f10a77bbSDavid C Somayajulu 		return;
4058f10a77bbSDavid C Somayajulu 
4059f10a77bbSDavid C Somayajulu 		ha->hw.mdump_start_seq_index = ql_stop_sequence(ha);
4060f10a77bbSDavid C Somayajulu 
40616a62bec0SDavid C Somayajulu 	bzero(ha->hw.mdump_buffer, ha->hw.mdump_buffer_size);
40626a62bec0SDavid C Somayajulu 	bzero(ha->hw.mdump_template, ha->hw.mdump_template_size);
40636a62bec0SDavid C Somayajulu 
40646a62bec0SDavid C Somayajulu 	bcopy(ha->hw.dma_buf.minidump.dma_b, ha->hw.mdump_template,
40656a62bec0SDavid C Somayajulu 		ha->hw.mdump_template_size);
40666a62bec0SDavid C Somayajulu 
40676a62bec0SDavid C Somayajulu 	ql_parse_template(ha);
40686a62bec0SDavid C Somayajulu 
4069f10a77bbSDavid C Somayajulu 	ql_start_sequence(ha, ha->hw.mdump_start_seq_index);
4070f10a77bbSDavid C Somayajulu 
40716a62bec0SDavid C Somayajulu 	ha->hw.mdump_done = 1;
40726a62bec0SDavid C Somayajulu 
4073f10a77bbSDavid C Somayajulu 	return;
4074f10a77bbSDavid C Somayajulu }
40756a62bec0SDavid C Somayajulu 
40766a62bec0SDavid C Somayajulu 
40776a62bec0SDavid C Somayajulu /*
40786a62bec0SDavid C Somayajulu  * helper routines
40796a62bec0SDavid C Somayajulu  */
40806a62bec0SDavid C Somayajulu static void
40816a62bec0SDavid C Somayajulu ql_entry_err_chk(ql_minidump_entry_t *entry, uint32_t esize)
40826a62bec0SDavid C Somayajulu {
40836a62bec0SDavid C Somayajulu 	if (esize != entry->hdr.entry_capture_size) {
40846a62bec0SDavid C Somayajulu 		entry->hdr.entry_capture_size = esize;
40856a62bec0SDavid C Somayajulu 		entry->hdr.driver_flags |= QL_DBG_SIZE_ERR_FLAG;
40866a62bec0SDavid C Somayajulu 	}
40876a62bec0SDavid C Somayajulu 	return;
40886a62bec0SDavid C Somayajulu }
40896a62bec0SDavid C Somayajulu 
40906a62bec0SDavid C Somayajulu 
40916a62bec0SDavid C Somayajulu static int
40926a62bec0SDavid C Somayajulu ql_parse_template(qla_host_t *ha)
40936a62bec0SDavid C Somayajulu {
40946a62bec0SDavid C Somayajulu 	uint32_t num_of_entries, buff_level, e_cnt, esize;
40956a62bec0SDavid C Somayajulu 	uint32_t end_cnt, rv = 0;
40966a62bec0SDavid C Somayajulu 	char *dump_buff, *dbuff;
40976a62bec0SDavid C Somayajulu 	int sane_start = 0, sane_end = 0;
40986a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *template_hdr;
40996a62bec0SDavid C Somayajulu 	ql_minidump_entry_t *entry;
41006a62bec0SDavid C Somayajulu 	uint32_t capture_mask;
41016a62bec0SDavid C Somayajulu 	uint32_t dump_size;
41026a62bec0SDavid C Somayajulu 
41036a62bec0SDavid C Somayajulu 	/* Setup parameters */
41046a62bec0SDavid C Somayajulu 	template_hdr = (ql_minidump_template_hdr_t *)ha->hw.mdump_template;
41056a62bec0SDavid C Somayajulu 
41066a62bec0SDavid C Somayajulu 	if (template_hdr->entry_type == TLHDR)
41076a62bec0SDavid C Somayajulu 		sane_start = 1;
41086a62bec0SDavid C Somayajulu 
41096a62bec0SDavid C Somayajulu 	dump_buff = (char *) ha->hw.mdump_buffer;
41106a62bec0SDavid C Somayajulu 
41116a62bec0SDavid C Somayajulu 	num_of_entries = template_hdr->num_of_entries;
41126a62bec0SDavid C Somayajulu 
41136a62bec0SDavid C Somayajulu 	entry = (ql_minidump_entry_t *) ((char *)template_hdr
41146a62bec0SDavid C Somayajulu 			+ template_hdr->first_entry_offset );
41156a62bec0SDavid C Somayajulu 
41166a62bec0SDavid C Somayajulu 	template_hdr->saved_state_array[QL_OCM0_ADDR_INDX] =
41176a62bec0SDavid C Somayajulu 		template_hdr->ocm_window_array[ha->pci_func];
41186a62bec0SDavid C Somayajulu 	template_hdr->saved_state_array[QL_PCIE_FUNC_INDX] = ha->pci_func;
41196a62bec0SDavid C Somayajulu 
41206a62bec0SDavid C Somayajulu 	capture_mask = ha->hw.mdump_capture_mask;
41216a62bec0SDavid C Somayajulu 	dump_size = ha->hw.mdump_buffer_size;
41226a62bec0SDavid C Somayajulu 
41236a62bec0SDavid C Somayajulu 	template_hdr->driver_capture_mask = capture_mask;
41246a62bec0SDavid C Somayajulu 
41256a62bec0SDavid C Somayajulu 	QL_DPRINT80(ha, (ha->pci_dev,
41266a62bec0SDavid C Somayajulu 		"%s: sane_start = %d num_of_entries = %d "
41276a62bec0SDavid C Somayajulu 		"capture_mask = 0x%x dump_size = %d \n",
41286a62bec0SDavid C Somayajulu 		__func__, sane_start, num_of_entries, capture_mask, dump_size));
41296a62bec0SDavid C Somayajulu 
41306a62bec0SDavid C Somayajulu 	for (buff_level = 0, e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
41316a62bec0SDavid C Somayajulu 
41326a62bec0SDavid C Somayajulu 		/*
41336a62bec0SDavid C Somayajulu 		 * If the capture_mask of the entry does not match capture mask
41346a62bec0SDavid C Somayajulu 		 * skip the entry after marking the driver_flags indicator.
41356a62bec0SDavid C Somayajulu 		 */
41366a62bec0SDavid C Somayajulu 
41376a62bec0SDavid C Somayajulu 		if (!(entry->hdr.entry_capture_mask & capture_mask)) {
41386a62bec0SDavid C Somayajulu 
41396a62bec0SDavid C Somayajulu 			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
41406a62bec0SDavid C Somayajulu 			entry = (ql_minidump_entry_t *) ((char *) entry
41416a62bec0SDavid C Somayajulu 					+ entry->hdr.entry_size);
41426a62bec0SDavid C Somayajulu 			continue;
41436a62bec0SDavid C Somayajulu 		}
41446a62bec0SDavid C Somayajulu 
41456a62bec0SDavid C Somayajulu 		/*
41466a62bec0SDavid C Somayajulu 		 * This is ONLY needed in implementations where
41476a62bec0SDavid C Somayajulu 		 * the capture buffer allocated is too small to capture
41486a62bec0SDavid C Somayajulu 		 * all of the required entries for a given capture mask.
41496a62bec0SDavid C Somayajulu 		 * We need to empty the buffer contents to a file
41506a62bec0SDavid C Somayajulu 		 * if possible, before processing the next entry
41516a62bec0SDavid C Somayajulu 		 * If the buff_full_flag is set, no further capture will happen
41526a62bec0SDavid C Somayajulu 		 * and all remaining non-control entries will be skipped.
41536a62bec0SDavid C Somayajulu 		 */
41546a62bec0SDavid C Somayajulu 		if (entry->hdr.entry_capture_size != 0) {
41556a62bec0SDavid C Somayajulu 			if ((buff_level + entry->hdr.entry_capture_size) >
41566a62bec0SDavid C Somayajulu 				dump_size) {
41576a62bec0SDavid C Somayajulu 				/*  Try to recover by emptying buffer to file */
41586a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
41596a62bec0SDavid C Somayajulu 				entry = (ql_minidump_entry_t *) ((char *) entry
41606a62bec0SDavid C Somayajulu 						+ entry->hdr.entry_size);
41616a62bec0SDavid C Somayajulu 				continue;
41626a62bec0SDavid C Somayajulu 			}
41636a62bec0SDavid C Somayajulu 		}
41646a62bec0SDavid C Somayajulu 
41656a62bec0SDavid C Somayajulu 		/*
41666a62bec0SDavid C Somayajulu 		 * Decode the entry type and process it accordingly
41676a62bec0SDavid C Somayajulu 		 */
41686a62bec0SDavid C Somayajulu 
41696a62bec0SDavid C Somayajulu 		switch (entry->hdr.entry_type) {
41706a62bec0SDavid C Somayajulu 		case RDNOP:
41716a62bec0SDavid C Somayajulu 			break;
41726a62bec0SDavid C Somayajulu 
41736a62bec0SDavid C Somayajulu 		case RDEND:
41746a62bec0SDavid C Somayajulu 			if (sane_end == 0) {
41756a62bec0SDavid C Somayajulu 				end_cnt = e_cnt;
41766a62bec0SDavid C Somayajulu 			}
41776a62bec0SDavid C Somayajulu 			sane_end++;
41786a62bec0SDavid C Somayajulu 			break;
41796a62bec0SDavid C Somayajulu 
41806a62bec0SDavid C Somayajulu 		case RDCRB:
41816a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
41826a62bec0SDavid C Somayajulu 			esize = ql_rdcrb(ha, (void *)entry, (void *)dbuff);
41836a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
41846a62bec0SDavid C Somayajulu 			buff_level += esize;
41856a62bec0SDavid C Somayajulu 			break;
41866a62bec0SDavid C Somayajulu 
41876a62bec0SDavid C Somayajulu                 case POLLRD:
41886a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
41896a62bec0SDavid C Somayajulu                         esize = ql_pollrd(ha, (void *)entry, (void *)dbuff);
41906a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
41916a62bec0SDavid C Somayajulu                         buff_level += esize;
41926a62bec0SDavid C Somayajulu                         break;
41936a62bec0SDavid C Somayajulu 
41946a62bec0SDavid C Somayajulu                 case POLLRDMWR:
41956a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
41966a62bec0SDavid C Somayajulu                         esize = ql_pollrd_modify_write(ha, (void *)entry,
41976a62bec0SDavid C Somayajulu 					(void *)dbuff);
41986a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
41996a62bec0SDavid C Somayajulu                         buff_level += esize;
42006a62bec0SDavid C Somayajulu                         break;
42016a62bec0SDavid C Somayajulu 
42026a62bec0SDavid C Somayajulu 		case L2ITG:
42036a62bec0SDavid C Somayajulu 		case L2DTG:
42046a62bec0SDavid C Somayajulu 		case L2DAT:
42056a62bec0SDavid C Somayajulu 		case L2INS:
42066a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
42076a62bec0SDavid C Somayajulu 			esize = ql_L2Cache(ha, (void *)entry, (void *)dbuff);
42086a62bec0SDavid C Somayajulu 			if (esize == -1) {
42096a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
42106a62bec0SDavid C Somayajulu 			} else {
42116a62bec0SDavid C Somayajulu 				ql_entry_err_chk(entry, esize);
42126a62bec0SDavid C Somayajulu 				buff_level += esize;
42136a62bec0SDavid C Somayajulu 			}
42146a62bec0SDavid C Somayajulu 			break;
42156a62bec0SDavid C Somayajulu 
42166a62bec0SDavid C Somayajulu 		case L1DAT:
42176a62bec0SDavid C Somayajulu 		case L1INS:
42186a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
42196a62bec0SDavid C Somayajulu 			esize = ql_L1Cache(ha, (void *)entry, (void *)dbuff);
42206a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
42216a62bec0SDavid C Somayajulu 			buff_level += esize;
42226a62bec0SDavid C Somayajulu 			break;
42236a62bec0SDavid C Somayajulu 
42246a62bec0SDavid C Somayajulu 		case RDOCM:
42256a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
42266a62bec0SDavid C Somayajulu 			esize = ql_rdocm(ha, (void *)entry, (void *)dbuff);
42276a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
42286a62bec0SDavid C Somayajulu 			buff_level += esize;
42296a62bec0SDavid C Somayajulu 			break;
42306a62bec0SDavid C Somayajulu 
42316a62bec0SDavid C Somayajulu 		case RDMEM:
42326a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
42336a62bec0SDavid C Somayajulu 			esize = ql_rdmem(ha, (void *)entry, (void *)dbuff);
42346a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
42356a62bec0SDavid C Somayajulu 			buff_level += esize;
42366a62bec0SDavid C Somayajulu 			break;
42376a62bec0SDavid C Somayajulu 
42386a62bec0SDavid C Somayajulu 		case BOARD:
42396a62bec0SDavid C Somayajulu 		case RDROM:
42406a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
42416a62bec0SDavid C Somayajulu 			esize = ql_rdrom(ha, (void *)entry, (void *)dbuff);
42426a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
42436a62bec0SDavid C Somayajulu 			buff_level += esize;
42446a62bec0SDavid C Somayajulu 			break;
42456a62bec0SDavid C Somayajulu 
42466a62bec0SDavid C Somayajulu 		case RDMUX:
42476a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
42486a62bec0SDavid C Somayajulu 			esize = ql_rdmux(ha, (void *)entry, (void *)dbuff);
42496a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
42506a62bec0SDavid C Somayajulu 			buff_level += esize;
42516a62bec0SDavid C Somayajulu 			break;
42526a62bec0SDavid C Somayajulu 
42536a62bec0SDavid C Somayajulu                 case RDMUX2:
42546a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
42556a62bec0SDavid C Somayajulu                         esize = ql_rdmux2(ha, (void *)entry, (void *)dbuff);
42566a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
42576a62bec0SDavid C Somayajulu                         buff_level += esize;
42586a62bec0SDavid C Somayajulu                         break;
42596a62bec0SDavid C Somayajulu 
42606a62bec0SDavid C Somayajulu 		case QUEUE:
42616a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
42626a62bec0SDavid C Somayajulu 			esize = ql_rdqueue(ha, (void *)entry, (void *)dbuff);
42636a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
42646a62bec0SDavid C Somayajulu 			buff_level += esize;
42656a62bec0SDavid C Somayajulu 			break;
42666a62bec0SDavid C Somayajulu 
42676a62bec0SDavid C Somayajulu 		case CNTRL:
42686a62bec0SDavid C Somayajulu 			if ((rv = ql_cntrl(ha, template_hdr, (void *)entry))) {
42696a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
42706a62bec0SDavid C Somayajulu 			}
42716a62bec0SDavid C Somayajulu 			break;
42726a62bec0SDavid C Somayajulu 		default:
42736a62bec0SDavid C Somayajulu 			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
42746a62bec0SDavid C Somayajulu 			break;
42756a62bec0SDavid C Somayajulu 		}
42766a62bec0SDavid C Somayajulu 		/*  next entry in the template */
42776a62bec0SDavid C Somayajulu 		entry = (ql_minidump_entry_t *) ((char *) entry
42786a62bec0SDavid C Somayajulu 						+ entry->hdr.entry_size);
42796a62bec0SDavid C Somayajulu 	}
42806a62bec0SDavid C Somayajulu 
42816a62bec0SDavid C Somayajulu 	if (!sane_start || (sane_end > 1)) {
42826a62bec0SDavid C Somayajulu 		device_printf(ha->pci_dev,
42836a62bec0SDavid C Somayajulu 			"\n%s: Template configuration error. Check Template\n",
42846a62bec0SDavid C Somayajulu 			__func__);
42856a62bec0SDavid C Somayajulu 	}
42866a62bec0SDavid C Somayajulu 
42876a62bec0SDavid C Somayajulu 	QL_DPRINT80(ha, (ha->pci_dev, "%s: Minidump num of entries = %d\n",
42886a62bec0SDavid C Somayajulu 		__func__, template_hdr->num_of_entries));
42896a62bec0SDavid C Somayajulu 
42906a62bec0SDavid C Somayajulu 	return 0;
42916a62bec0SDavid C Somayajulu }
42926a62bec0SDavid C Somayajulu 
42936a62bec0SDavid C Somayajulu /*
42946a62bec0SDavid C Somayajulu  * Read CRB operation.
42956a62bec0SDavid C Somayajulu  */
42966a62bec0SDavid C Somayajulu static uint32_t
42976a62bec0SDavid C Somayajulu ql_rdcrb(qla_host_t *ha, ql_minidump_entry_rdcrb_t * crb_entry,
42986a62bec0SDavid C Somayajulu 	uint32_t * data_buff)
42996a62bec0SDavid C Somayajulu {
43006a62bec0SDavid C Somayajulu 	int loop_cnt;
43016a62bec0SDavid C Somayajulu 	int ret;
43026a62bec0SDavid C Somayajulu 	uint32_t op_count, addr, stride, value = 0;
43036a62bec0SDavid C Somayajulu 
43046a62bec0SDavid C Somayajulu 	addr = crb_entry->addr;
43056a62bec0SDavid C Somayajulu 	op_count = crb_entry->op_count;
43066a62bec0SDavid C Somayajulu 	stride = crb_entry->addr_stride;
43076a62bec0SDavid C Somayajulu 
43086a62bec0SDavid C Somayajulu 	for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
43096a62bec0SDavid C Somayajulu 
43106a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr, &value, 1);
43116a62bec0SDavid C Somayajulu 
43126a62bec0SDavid C Somayajulu 		if (ret)
43136a62bec0SDavid C Somayajulu 			return (0);
43146a62bec0SDavid C Somayajulu 
43156a62bec0SDavid C Somayajulu 		*data_buff++ = addr;
43166a62bec0SDavid C Somayajulu 		*data_buff++ = value;
43176a62bec0SDavid C Somayajulu 		addr = addr + stride;
43186a62bec0SDavid C Somayajulu 	}
43196a62bec0SDavid C Somayajulu 
43206a62bec0SDavid C Somayajulu 	/*
43216a62bec0SDavid C Somayajulu 	 * for testing purpose we return amount of data written
43226a62bec0SDavid C Somayajulu 	 */
43236a62bec0SDavid C Somayajulu 	return (op_count * (2 * sizeof(uint32_t)));
43246a62bec0SDavid C Somayajulu }
43256a62bec0SDavid C Somayajulu 
43266a62bec0SDavid C Somayajulu /*
43276a62bec0SDavid C Somayajulu  * Handle L2 Cache.
43286a62bec0SDavid C Somayajulu  */
43296a62bec0SDavid C Somayajulu 
43306a62bec0SDavid C Somayajulu static uint32_t
43316a62bec0SDavid C Somayajulu ql_L2Cache(qla_host_t *ha, ql_minidump_entry_cache_t *cacheEntry,
43326a62bec0SDavid C Somayajulu 	uint32_t * data_buff)
43336a62bec0SDavid C Somayajulu {
43346a62bec0SDavid C Somayajulu 	int i, k;
43356a62bec0SDavid C Somayajulu 	int loop_cnt;
43366a62bec0SDavid C Somayajulu 	int ret;
43376a62bec0SDavid C Somayajulu 
43386a62bec0SDavid C Somayajulu 	uint32_t read_value;
43396a62bec0SDavid C Somayajulu 	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr, cntl_value_w;
43406a62bec0SDavid C Somayajulu 	uint32_t tag_value, read_cnt;
43416a62bec0SDavid C Somayajulu 	volatile uint8_t cntl_value_r;
43426a62bec0SDavid C Somayajulu 	long timeout;
43436a62bec0SDavid C Somayajulu 	uint32_t data;
43446a62bec0SDavid C Somayajulu 
43456a62bec0SDavid C Somayajulu 	loop_cnt = cacheEntry->op_count;
43466a62bec0SDavid C Somayajulu 
43476a62bec0SDavid C Somayajulu 	read_addr = cacheEntry->read_addr;
43486a62bec0SDavid C Somayajulu 	cntrl_addr = cacheEntry->control_addr;
43496a62bec0SDavid C Somayajulu 	cntl_value_w = (uint32_t) cacheEntry->write_value;
43506a62bec0SDavid C Somayajulu 
43516a62bec0SDavid C Somayajulu 	tag_reg_addr = cacheEntry->tag_reg_addr;
43526a62bec0SDavid C Somayajulu 
43536a62bec0SDavid C Somayajulu 	tag_value = cacheEntry->init_tag_value;
43546a62bec0SDavid C Somayajulu 	read_cnt = cacheEntry->read_addr_cnt;
43556a62bec0SDavid C Somayajulu 
43566a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
43576a62bec0SDavid C Somayajulu 
43586a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
43596a62bec0SDavid C Somayajulu 		if (ret)
43606a62bec0SDavid C Somayajulu 			return (0);
43616a62bec0SDavid C Somayajulu 
43626a62bec0SDavid C Somayajulu 		if (cacheEntry->write_value != 0) {
43636a62bec0SDavid C Somayajulu 
43646a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, cntrl_addr,
43656a62bec0SDavid C Somayajulu 					&cntl_value_w, 0);
43666a62bec0SDavid C Somayajulu 			if (ret)
43676a62bec0SDavid C Somayajulu 				return (0);
43686a62bec0SDavid C Somayajulu 		}
43696a62bec0SDavid C Somayajulu 
43706a62bec0SDavid C Somayajulu 		if (cacheEntry->poll_mask != 0) {
43716a62bec0SDavid C Somayajulu 
43726a62bec0SDavid C Somayajulu 			timeout = cacheEntry->poll_wait;
43736a62bec0SDavid C Somayajulu 
43746a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, cntrl_addr, &data, 1);
43756a62bec0SDavid C Somayajulu 			if (ret)
43766a62bec0SDavid C Somayajulu 				return (0);
43776a62bec0SDavid C Somayajulu 
43786a62bec0SDavid C Somayajulu 			cntl_value_r = (uint8_t)data;
43796a62bec0SDavid C Somayajulu 
43806a62bec0SDavid C Somayajulu 			while ((cntl_value_r & cacheEntry->poll_mask) != 0) {
43816a62bec0SDavid C Somayajulu 
43826a62bec0SDavid C Somayajulu 				if (timeout) {
43836a62bec0SDavid C Somayajulu 					qla_mdelay(__func__, 1);
43846a62bec0SDavid C Somayajulu 					timeout--;
43856a62bec0SDavid C Somayajulu 				} else
43866a62bec0SDavid C Somayajulu 					break;
43876a62bec0SDavid C Somayajulu 
43886a62bec0SDavid C Somayajulu 				ret = ql_rdwr_indreg32(ha, cntrl_addr,
43896a62bec0SDavid C Somayajulu 						&data, 1);
43906a62bec0SDavid C Somayajulu 				if (ret)
43916a62bec0SDavid C Somayajulu 					return (0);
43926a62bec0SDavid C Somayajulu 
43936a62bec0SDavid C Somayajulu 				cntl_value_r = (uint8_t)data;
43946a62bec0SDavid C Somayajulu 			}
43956a62bec0SDavid C Somayajulu 			if (!timeout) {
43966a62bec0SDavid C Somayajulu 				/* Report timeout error.
43976a62bec0SDavid C Somayajulu 				 * core dump capture failed
43986a62bec0SDavid C Somayajulu 				 * Skip remaining entries.
43996a62bec0SDavid C Somayajulu 				 * Write buffer out to file
44006a62bec0SDavid C Somayajulu 				 * Use driver specific fields in template header
44016a62bec0SDavid C Somayajulu 				 * to report this error.
44026a62bec0SDavid C Somayajulu 				 */
44036a62bec0SDavid C Somayajulu 				return (-1);
44046a62bec0SDavid C Somayajulu 			}
44056a62bec0SDavid C Somayajulu 		}
44066a62bec0SDavid C Somayajulu 
44076a62bec0SDavid C Somayajulu 		addr = read_addr;
44086a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
44096a62bec0SDavid C Somayajulu 
44106a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
44116a62bec0SDavid C Somayajulu 			if (ret)
44126a62bec0SDavid C Somayajulu 				return (0);
44136a62bec0SDavid C Somayajulu 
44146a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
44156a62bec0SDavid C Somayajulu 			addr += cacheEntry->read_addr_stride;
44166a62bec0SDavid C Somayajulu 		}
44176a62bec0SDavid C Somayajulu 
44186a62bec0SDavid C Somayajulu 		tag_value += cacheEntry->tag_value_stride;
44196a62bec0SDavid C Somayajulu 	}
44206a62bec0SDavid C Somayajulu 
44216a62bec0SDavid C Somayajulu 	return (read_cnt * loop_cnt * sizeof(uint32_t));
44226a62bec0SDavid C Somayajulu }
44236a62bec0SDavid C Somayajulu 
44246a62bec0SDavid C Somayajulu /*
44256a62bec0SDavid C Somayajulu  * Handle L1 Cache.
44266a62bec0SDavid C Somayajulu  */
44276a62bec0SDavid C Somayajulu 
44286a62bec0SDavid C Somayajulu static uint32_t
44296a62bec0SDavid C Somayajulu ql_L1Cache(qla_host_t *ha,
44306a62bec0SDavid C Somayajulu 	ql_minidump_entry_cache_t *cacheEntry,
44316a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
44326a62bec0SDavid C Somayajulu {
44336a62bec0SDavid C Somayajulu 	int ret;
44346a62bec0SDavid C Somayajulu 	int i, k;
44356a62bec0SDavid C Somayajulu 	int loop_cnt;
44366a62bec0SDavid C Somayajulu 
44376a62bec0SDavid C Somayajulu 	uint32_t read_value;
44386a62bec0SDavid C Somayajulu 	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr;
44396a62bec0SDavid C Somayajulu 	uint32_t tag_value, read_cnt;
44406a62bec0SDavid C Somayajulu 	uint32_t cntl_value_w;
44416a62bec0SDavid C Somayajulu 
44426a62bec0SDavid C Somayajulu 	loop_cnt = cacheEntry->op_count;
44436a62bec0SDavid C Somayajulu 
44446a62bec0SDavid C Somayajulu 	read_addr = cacheEntry->read_addr;
44456a62bec0SDavid C Somayajulu 	cntrl_addr = cacheEntry->control_addr;
44466a62bec0SDavid C Somayajulu 	cntl_value_w = (uint32_t) cacheEntry->write_value;
44476a62bec0SDavid C Somayajulu 
44486a62bec0SDavid C Somayajulu 	tag_reg_addr = cacheEntry->tag_reg_addr;
44496a62bec0SDavid C Somayajulu 
44506a62bec0SDavid C Somayajulu 	tag_value = cacheEntry->init_tag_value;
44516a62bec0SDavid C Somayajulu 	read_cnt = cacheEntry->read_addr_cnt;
44526a62bec0SDavid C Somayajulu 
44536a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
44546a62bec0SDavid C Somayajulu 
44556a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
44566a62bec0SDavid C Somayajulu 		if (ret)
44576a62bec0SDavid C Somayajulu 			return (0);
44586a62bec0SDavid C Somayajulu 
44596a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, cntrl_addr, &cntl_value_w, 0);
44606a62bec0SDavid C Somayajulu 		if (ret)
44616a62bec0SDavid C Somayajulu 			return (0);
44626a62bec0SDavid C Somayajulu 
44636a62bec0SDavid C Somayajulu 		addr = read_addr;
44646a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
44656a62bec0SDavid C Somayajulu 
44666a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
44676a62bec0SDavid C Somayajulu 			if (ret)
44686a62bec0SDavid C Somayajulu 				return (0);
44696a62bec0SDavid C Somayajulu 
44706a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
44716a62bec0SDavid C Somayajulu 			addr += cacheEntry->read_addr_stride;
44726a62bec0SDavid C Somayajulu 		}
44736a62bec0SDavid C Somayajulu 
44746a62bec0SDavid C Somayajulu 		tag_value += cacheEntry->tag_value_stride;
44756a62bec0SDavid C Somayajulu 	}
44766a62bec0SDavid C Somayajulu 
44776a62bec0SDavid C Somayajulu 	return (read_cnt * loop_cnt * sizeof(uint32_t));
44786a62bec0SDavid C Somayajulu }
44796a62bec0SDavid C Somayajulu 
44806a62bec0SDavid C Somayajulu /*
44816a62bec0SDavid C Somayajulu  * Reading OCM memory
44826a62bec0SDavid C Somayajulu  */
44836a62bec0SDavid C Somayajulu 
44846a62bec0SDavid C Somayajulu static uint32_t
44856a62bec0SDavid C Somayajulu ql_rdocm(qla_host_t *ha,
44866a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdocm_t *ocmEntry,
44876a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
44886a62bec0SDavid C Somayajulu {
44896a62bec0SDavid C Somayajulu 	int i, loop_cnt;
44906a62bec0SDavid C Somayajulu 	volatile uint32_t addr;
44916a62bec0SDavid C Somayajulu 	volatile uint32_t value;
44926a62bec0SDavid C Somayajulu 
44936a62bec0SDavid C Somayajulu 	addr = ocmEntry->read_addr;
44946a62bec0SDavid C Somayajulu 	loop_cnt = ocmEntry->op_count;
44956a62bec0SDavid C Somayajulu 
44966a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
44976a62bec0SDavid C Somayajulu 		value = READ_REG32(ha, addr);
44986a62bec0SDavid C Somayajulu 		*data_buff++ = value;
44996a62bec0SDavid C Somayajulu 		addr += ocmEntry->read_addr_stride;
45006a62bec0SDavid C Somayajulu 	}
45016a62bec0SDavid C Somayajulu 	return (loop_cnt * sizeof(value));
45026a62bec0SDavid C Somayajulu }
45036a62bec0SDavid C Somayajulu 
45046a62bec0SDavid C Somayajulu /*
45056a62bec0SDavid C Somayajulu  * Read memory
45066a62bec0SDavid C Somayajulu  */
45076a62bec0SDavid C Somayajulu 
45086a62bec0SDavid C Somayajulu static uint32_t
45096a62bec0SDavid C Somayajulu ql_rdmem(qla_host_t *ha,
45106a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdmem_t *mem_entry,
45116a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
45126a62bec0SDavid C Somayajulu {
45136a62bec0SDavid C Somayajulu 	int ret;
45146a62bec0SDavid C Somayajulu         int i, loop_cnt;
45156a62bec0SDavid C Somayajulu         volatile uint32_t addr;
45166a62bec0SDavid C Somayajulu 	q80_offchip_mem_val_t val;
45176a62bec0SDavid C Somayajulu 
45186a62bec0SDavid C Somayajulu         addr = mem_entry->read_addr;
45196a62bec0SDavid C Somayajulu 
45206a62bec0SDavid C Somayajulu 	/* size in bytes / 16 */
45216a62bec0SDavid C Somayajulu         loop_cnt = mem_entry->read_data_size / (sizeof(uint32_t) * 4);
45226a62bec0SDavid C Somayajulu 
45236a62bec0SDavid C Somayajulu         for (i = 0; i < loop_cnt; i++) {
45246a62bec0SDavid C Somayajulu 
45256a62bec0SDavid C Somayajulu 		ret = ql_rdwr_offchip_mem(ha, (addr & 0x0ffffffff), &val, 1);
45266a62bec0SDavid C Somayajulu 		if (ret)
45276a62bec0SDavid C Somayajulu 			return (0);
45286a62bec0SDavid C Somayajulu 
45296a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_lo;
45306a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_hi;
45316a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_ulo;
45326a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_uhi;
45336a62bec0SDavid C Somayajulu 
45346a62bec0SDavid C Somayajulu                 addr += (sizeof(uint32_t) * 4);
45356a62bec0SDavid C Somayajulu         }
45366a62bec0SDavid C Somayajulu 
45376a62bec0SDavid C Somayajulu         return (loop_cnt * (sizeof(uint32_t) * 4));
45386a62bec0SDavid C Somayajulu }
45396a62bec0SDavid C Somayajulu 
45406a62bec0SDavid C Somayajulu /*
45416a62bec0SDavid C Somayajulu  * Read Rom
45426a62bec0SDavid C Somayajulu  */
45436a62bec0SDavid C Somayajulu 
45446a62bec0SDavid C Somayajulu static uint32_t
45456a62bec0SDavid C Somayajulu ql_rdrom(qla_host_t *ha,
45466a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdrom_t *romEntry,
45476a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
45486a62bec0SDavid C Somayajulu {
45496a62bec0SDavid C Somayajulu 	int ret;
45506a62bec0SDavid C Somayajulu 	int i, loop_cnt;
45516a62bec0SDavid C Somayajulu 	uint32_t addr;
45526a62bec0SDavid C Somayajulu 	uint32_t value;
45536a62bec0SDavid C Somayajulu 
45546a62bec0SDavid C Somayajulu 	addr = romEntry->read_addr;
45556a62bec0SDavid C Somayajulu 	loop_cnt = romEntry->read_data_size; /* This is size in bytes */
45566a62bec0SDavid C Somayajulu 	loop_cnt /= sizeof(value);
45576a62bec0SDavid C Somayajulu 
45586a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
45596a62bec0SDavid C Somayajulu 
45606a62bec0SDavid C Somayajulu 		ret = ql_rd_flash32(ha, addr, &value);
45616a62bec0SDavid C Somayajulu 		if (ret)
45626a62bec0SDavid C Somayajulu 			return (0);
45636a62bec0SDavid C Somayajulu 
45646a62bec0SDavid C Somayajulu 		*data_buff++ = value;
45656a62bec0SDavid C Somayajulu 		addr += sizeof(value);
45666a62bec0SDavid C Somayajulu 	}
45676a62bec0SDavid C Somayajulu 
45686a62bec0SDavid C Somayajulu 	return (loop_cnt * sizeof(value));
45696a62bec0SDavid C Somayajulu }
45706a62bec0SDavid C Somayajulu 
45716a62bec0SDavid C Somayajulu /*
45726a62bec0SDavid C Somayajulu  * Read MUX data
45736a62bec0SDavid C Somayajulu  */
45746a62bec0SDavid C Somayajulu 
45756a62bec0SDavid C Somayajulu static uint32_t
45766a62bec0SDavid C Somayajulu ql_rdmux(qla_host_t *ha,
45776a62bec0SDavid C Somayajulu 	ql_minidump_entry_mux_t *muxEntry,
45786a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
45796a62bec0SDavid C Somayajulu {
45806a62bec0SDavid C Somayajulu 	int ret;
45816a62bec0SDavid C Somayajulu 	int loop_cnt;
45826a62bec0SDavid C Somayajulu 	uint32_t read_value, sel_value;
45836a62bec0SDavid C Somayajulu 	uint32_t read_addr, select_addr;
45846a62bec0SDavid C Somayajulu 
45856a62bec0SDavid C Somayajulu 	select_addr = muxEntry->select_addr;
45866a62bec0SDavid C Somayajulu 	sel_value = muxEntry->select_value;
45876a62bec0SDavid C Somayajulu 	read_addr = muxEntry->read_addr;
45886a62bec0SDavid C Somayajulu 
45896a62bec0SDavid C Somayajulu 	for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
45906a62bec0SDavid C Somayajulu 
45916a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr, &sel_value, 0);
45926a62bec0SDavid C Somayajulu 		if (ret)
45936a62bec0SDavid C Somayajulu 			return (0);
45946a62bec0SDavid C Somayajulu 
45956a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
45966a62bec0SDavid C Somayajulu 		if (ret)
45976a62bec0SDavid C Somayajulu 			return (0);
45986a62bec0SDavid C Somayajulu 
45996a62bec0SDavid C Somayajulu 		*data_buff++ = sel_value;
46006a62bec0SDavid C Somayajulu 		*data_buff++ = read_value;
46016a62bec0SDavid C Somayajulu 
46026a62bec0SDavid C Somayajulu 		sel_value += muxEntry->select_value_stride;
46036a62bec0SDavid C Somayajulu 	}
46046a62bec0SDavid C Somayajulu 
46056a62bec0SDavid C Somayajulu 	return (loop_cnt * (2 * sizeof(uint32_t)));
46066a62bec0SDavid C Somayajulu }
46076a62bec0SDavid C Somayajulu 
46086a62bec0SDavid C Somayajulu static uint32_t
46096a62bec0SDavid C Somayajulu ql_rdmux2(qla_host_t *ha,
46106a62bec0SDavid C Somayajulu 	ql_minidump_entry_mux2_t *muxEntry,
46116a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
46126a62bec0SDavid C Somayajulu {
46136a62bec0SDavid C Somayajulu 	int ret;
46146a62bec0SDavid C Somayajulu         int loop_cnt;
46156a62bec0SDavid C Somayajulu 
46166a62bec0SDavid C Somayajulu         uint32_t select_addr_1, select_addr_2;
46176a62bec0SDavid C Somayajulu         uint32_t select_value_1, select_value_2;
46186a62bec0SDavid C Somayajulu         uint32_t select_value_count, select_value_mask;
46196a62bec0SDavid C Somayajulu         uint32_t read_addr, read_value;
46206a62bec0SDavid C Somayajulu 
46216a62bec0SDavid C Somayajulu         select_addr_1 = muxEntry->select_addr_1;
46226a62bec0SDavid C Somayajulu         select_addr_2 = muxEntry->select_addr_2;
46236a62bec0SDavid C Somayajulu         select_value_1 = muxEntry->select_value_1;
46246a62bec0SDavid C Somayajulu         select_value_2 = muxEntry->select_value_2;
46256a62bec0SDavid C Somayajulu         select_value_count = muxEntry->select_value_count;
46266a62bec0SDavid C Somayajulu         select_value_mask  = muxEntry->select_value_mask;
46276a62bec0SDavid C Somayajulu 
46286a62bec0SDavid C Somayajulu         read_addr = muxEntry->read_addr;
46296a62bec0SDavid C Somayajulu 
46306a62bec0SDavid C Somayajulu         for (loop_cnt = 0; loop_cnt < muxEntry->select_value_count;
46316a62bec0SDavid C Somayajulu 		loop_cnt++) {
46326a62bec0SDavid C Somayajulu 
46336a62bec0SDavid C Somayajulu                 uint32_t temp_sel_val;
46346a62bec0SDavid C Somayajulu 
46356a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_1, 0);
46366a62bec0SDavid C Somayajulu 		if (ret)
46376a62bec0SDavid C Somayajulu 			return (0);
46386a62bec0SDavid C Somayajulu 
46396a62bec0SDavid C Somayajulu                 temp_sel_val = select_value_1 & select_value_mask;
46406a62bec0SDavid C Somayajulu 
46416a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
46426a62bec0SDavid C Somayajulu 		if (ret)
46436a62bec0SDavid C Somayajulu 			return (0);
46446a62bec0SDavid C Somayajulu 
46456a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
46466a62bec0SDavid C Somayajulu 		if (ret)
46476a62bec0SDavid C Somayajulu 			return (0);
46486a62bec0SDavid C Somayajulu 
46496a62bec0SDavid C Somayajulu                 *data_buff++ = temp_sel_val;
46506a62bec0SDavid C Somayajulu                 *data_buff++ = read_value;
46516a62bec0SDavid C Somayajulu 
46526a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_2, 0);
46536a62bec0SDavid C Somayajulu 		if (ret)
46546a62bec0SDavid C Somayajulu 			return (0);
46556a62bec0SDavid C Somayajulu 
46566a62bec0SDavid C Somayajulu                 temp_sel_val = select_value_2 & select_value_mask;
46576a62bec0SDavid C Somayajulu 
46586a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
46596a62bec0SDavid C Somayajulu 		if (ret)
46606a62bec0SDavid C Somayajulu 			return (0);
46616a62bec0SDavid C Somayajulu 
46626a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
46636a62bec0SDavid C Somayajulu 		if (ret)
46646a62bec0SDavid C Somayajulu 			return (0);
46656a62bec0SDavid C Somayajulu 
46666a62bec0SDavid C Somayajulu                 *data_buff++ = temp_sel_val;
46676a62bec0SDavid C Somayajulu                 *data_buff++ = read_value;
46686a62bec0SDavid C Somayajulu 
46696a62bec0SDavid C Somayajulu                 select_value_1 += muxEntry->select_value_stride;
46706a62bec0SDavid C Somayajulu                 select_value_2 += muxEntry->select_value_stride;
46716a62bec0SDavid C Somayajulu         }
46726a62bec0SDavid C Somayajulu 
46736a62bec0SDavid C Somayajulu         return (loop_cnt * (4 * sizeof(uint32_t)));
46746a62bec0SDavid C Somayajulu }
46756a62bec0SDavid C Somayajulu 
46766a62bec0SDavid C Somayajulu /*
46776a62bec0SDavid C Somayajulu  * Handling Queue State Reads.
46786a62bec0SDavid C Somayajulu  */
46796a62bec0SDavid C Somayajulu 
46806a62bec0SDavid C Somayajulu static uint32_t
46816a62bec0SDavid C Somayajulu ql_rdqueue(qla_host_t *ha,
46826a62bec0SDavid C Somayajulu 	ql_minidump_entry_queue_t *queueEntry,
46836a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
46846a62bec0SDavid C Somayajulu {
46856a62bec0SDavid C Somayajulu 	int ret;
46866a62bec0SDavid C Somayajulu 	int loop_cnt, k;
46876a62bec0SDavid C Somayajulu 	uint32_t read_value;
46886a62bec0SDavid C Somayajulu 	uint32_t read_addr, read_stride, select_addr;
46896a62bec0SDavid C Somayajulu 	uint32_t queue_id, read_cnt;
46906a62bec0SDavid C Somayajulu 
46916a62bec0SDavid C Somayajulu 	read_cnt = queueEntry->read_addr_cnt;
46926a62bec0SDavid C Somayajulu 	read_stride = queueEntry->read_addr_stride;
46936a62bec0SDavid C Somayajulu 	select_addr = queueEntry->select_addr;
46946a62bec0SDavid C Somayajulu 
46956a62bec0SDavid C Somayajulu 	for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
46966a62bec0SDavid C Somayajulu 		loop_cnt++) {
46976a62bec0SDavid C Somayajulu 
46986a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr, &queue_id, 0);
46996a62bec0SDavid C Somayajulu 		if (ret)
47006a62bec0SDavid C Somayajulu 			return (0);
47016a62bec0SDavid C Somayajulu 
47026a62bec0SDavid C Somayajulu 		read_addr = queueEntry->read_addr;
47036a62bec0SDavid C Somayajulu 
47046a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
47056a62bec0SDavid C Somayajulu 
47066a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
47076a62bec0SDavid C Somayajulu 			if (ret)
47086a62bec0SDavid C Somayajulu 				return (0);
47096a62bec0SDavid C Somayajulu 
47106a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
47116a62bec0SDavid C Somayajulu 			read_addr += read_stride;
47126a62bec0SDavid C Somayajulu 		}
47136a62bec0SDavid C Somayajulu 
47146a62bec0SDavid C Somayajulu 		queue_id += queueEntry->queue_id_stride;
47156a62bec0SDavid C Somayajulu 	}
47166a62bec0SDavid C Somayajulu 
47176a62bec0SDavid C Somayajulu 	return (loop_cnt * (read_cnt * sizeof(uint32_t)));
47186a62bec0SDavid C Somayajulu }
47196a62bec0SDavid C Somayajulu 
47206a62bec0SDavid C Somayajulu /*
47216a62bec0SDavid C Somayajulu  * Handling control entries.
47226a62bec0SDavid C Somayajulu  */
47236a62bec0SDavid C Somayajulu 
47246a62bec0SDavid C Somayajulu static uint32_t
47256a62bec0SDavid C Somayajulu ql_cntrl(qla_host_t *ha,
47266a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *template_hdr,
47276a62bec0SDavid C Somayajulu 	ql_minidump_entry_cntrl_t *crbEntry)
47286a62bec0SDavid C Somayajulu {
47296a62bec0SDavid C Somayajulu 	int ret;
47306a62bec0SDavid C Somayajulu 	int count;
47316a62bec0SDavid C Somayajulu 	uint32_t opcode, read_value, addr, entry_addr;
47326a62bec0SDavid C Somayajulu 	long timeout;
47336a62bec0SDavid C Somayajulu 
47346a62bec0SDavid C Somayajulu 	entry_addr = crbEntry->addr;
47356a62bec0SDavid C Somayajulu 
47366a62bec0SDavid C Somayajulu 	for (count = 0; count < crbEntry->op_count; count++) {
47376a62bec0SDavid C Somayajulu 		opcode = crbEntry->opcode;
47386a62bec0SDavid C Somayajulu 
47396a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_WR) {
47406a62bec0SDavid C Somayajulu 
47416a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr,
47426a62bec0SDavid C Somayajulu 					&crbEntry->value_1, 0);
47436a62bec0SDavid C Somayajulu 			if (ret)
47446a62bec0SDavid C Somayajulu 				return (0);
47456a62bec0SDavid C Somayajulu 
47466a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_WR;
47476a62bec0SDavid C Somayajulu 		}
47486a62bec0SDavid C Somayajulu 
47496a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_RW) {
47506a62bec0SDavid C Somayajulu 
47516a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
47526a62bec0SDavid C Somayajulu 			if (ret)
47536a62bec0SDavid C Somayajulu 				return (0);
47546a62bec0SDavid C Somayajulu 
47556a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
47566a62bec0SDavid C Somayajulu 			if (ret)
47576a62bec0SDavid C Somayajulu 				return (0);
47586a62bec0SDavid C Somayajulu 
47596a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_RW;
47606a62bec0SDavid C Somayajulu 		}
47616a62bec0SDavid C Somayajulu 
47626a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_AND) {
47636a62bec0SDavid C Somayajulu 
47646a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
47656a62bec0SDavid C Somayajulu 			if (ret)
47666a62bec0SDavid C Somayajulu 				return (0);
47676a62bec0SDavid C Somayajulu 
47686a62bec0SDavid C Somayajulu 			read_value &= crbEntry->value_2;
47696a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_AND;
47706a62bec0SDavid C Somayajulu 
47716a62bec0SDavid C Somayajulu 			if (opcode & QL_DBG_OPCODE_OR) {
47726a62bec0SDavid C Somayajulu 				read_value |= crbEntry->value_3;
47736a62bec0SDavid C Somayajulu 				opcode &= ~QL_DBG_OPCODE_OR;
47746a62bec0SDavid C Somayajulu 			}
47756a62bec0SDavid C Somayajulu 
47766a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
47776a62bec0SDavid C Somayajulu 			if (ret)
47786a62bec0SDavid C Somayajulu 				return (0);
47796a62bec0SDavid C Somayajulu 		}
47806a62bec0SDavid C Somayajulu 
47816a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_OR) {
47826a62bec0SDavid C Somayajulu 
47836a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
47846a62bec0SDavid C Somayajulu 			if (ret)
47856a62bec0SDavid C Somayajulu 				return (0);
47866a62bec0SDavid C Somayajulu 
47876a62bec0SDavid C Somayajulu 			read_value |= crbEntry->value_3;
47886a62bec0SDavid C Somayajulu 
47896a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
47906a62bec0SDavid C Somayajulu 			if (ret)
47916a62bec0SDavid C Somayajulu 				return (0);
47926a62bec0SDavid C Somayajulu 
47936a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_OR;
47946a62bec0SDavid C Somayajulu 		}
47956a62bec0SDavid C Somayajulu 
47966a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_POLL) {
47976a62bec0SDavid C Somayajulu 
47986a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_POLL;
47996a62bec0SDavid C Somayajulu 			timeout = crbEntry->poll_timeout;
48006a62bec0SDavid C Somayajulu 			addr = entry_addr;
48016a62bec0SDavid C Somayajulu 
48026a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
48036a62bec0SDavid C Somayajulu 			if (ret)
48046a62bec0SDavid C Somayajulu 				return (0);
48056a62bec0SDavid C Somayajulu 
48066a62bec0SDavid C Somayajulu 			while ((read_value & crbEntry->value_2)
48076a62bec0SDavid C Somayajulu 				!= crbEntry->value_1) {
48086a62bec0SDavid C Somayajulu 
48096a62bec0SDavid C Somayajulu 				if (timeout) {
48106a62bec0SDavid C Somayajulu 					qla_mdelay(__func__, 1);
48116a62bec0SDavid C Somayajulu 					timeout--;
48126a62bec0SDavid C Somayajulu 				} else
48136a62bec0SDavid C Somayajulu 					break;
48146a62bec0SDavid C Somayajulu 
48156a62bec0SDavid C Somayajulu                 		ret = ql_rdwr_indreg32(ha, addr,
48166a62bec0SDavid C Somayajulu 						&read_value, 1);
48176a62bec0SDavid C Somayajulu 				if (ret)
48186a62bec0SDavid C Somayajulu 					return (0);
48196a62bec0SDavid C Somayajulu 			}
48206a62bec0SDavid C Somayajulu 
48216a62bec0SDavid C Somayajulu 			if (!timeout) {
48226a62bec0SDavid C Somayajulu 				/*
48236a62bec0SDavid C Somayajulu 				 * Report timeout error.
48246a62bec0SDavid C Somayajulu 				 * core dump capture failed
48256a62bec0SDavid C Somayajulu 				 * Skip remaining entries.
48266a62bec0SDavid C Somayajulu 				 * Write buffer out to file
48276a62bec0SDavid C Somayajulu 				 * Use driver specific fields in template header
48286a62bec0SDavid C Somayajulu 				 * to report this error.
48296a62bec0SDavid C Somayajulu 				 */
48306a62bec0SDavid C Somayajulu 				return (-1);
48316a62bec0SDavid C Somayajulu 			}
48326a62bec0SDavid C Somayajulu 		}
48336a62bec0SDavid C Somayajulu 
48346a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_RDSTATE) {
48356a62bec0SDavid C Somayajulu 			/*
48366a62bec0SDavid C Somayajulu 			 * decide which address to use.
48376a62bec0SDavid C Somayajulu 			 */
48386a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_a) {
48396a62bec0SDavid C Somayajulu 				addr = template_hdr->saved_state_array[
48406a62bec0SDavid C Somayajulu 						crbEntry-> state_index_a];
48416a62bec0SDavid C Somayajulu 			} else {
48426a62bec0SDavid C Somayajulu 				addr = entry_addr;
48436a62bec0SDavid C Somayajulu 			}
48446a62bec0SDavid C Somayajulu 
48456a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
48466a62bec0SDavid C Somayajulu 			if (ret)
48476a62bec0SDavid C Somayajulu 				return (0);
48486a62bec0SDavid C Somayajulu 
48496a62bec0SDavid C Somayajulu 			template_hdr->saved_state_array[crbEntry->state_index_v]
48506a62bec0SDavid C Somayajulu 					= read_value;
48516a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_RDSTATE;
48526a62bec0SDavid C Somayajulu 		}
48536a62bec0SDavid C Somayajulu 
48546a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_WRSTATE) {
48556a62bec0SDavid C Somayajulu 			/*
48566a62bec0SDavid C Somayajulu 			 * decide which value to use.
48576a62bec0SDavid C Somayajulu 			 */
48586a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_v) {
48596a62bec0SDavid C Somayajulu 				read_value = template_hdr->saved_state_array[
48606a62bec0SDavid C Somayajulu 						crbEntry->state_index_v];
48616a62bec0SDavid C Somayajulu 			} else {
48626a62bec0SDavid C Somayajulu 				read_value = crbEntry->value_1;
48636a62bec0SDavid C Somayajulu 			}
48646a62bec0SDavid C Somayajulu 			/*
48656a62bec0SDavid C Somayajulu 			 * decide which address to use.
48666a62bec0SDavid C Somayajulu 			 */
48676a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_a) {
48686a62bec0SDavid C Somayajulu 				addr = template_hdr->saved_state_array[
48696a62bec0SDavid C Somayajulu 						crbEntry-> state_index_a];
48706a62bec0SDavid C Somayajulu 			} else {
48716a62bec0SDavid C Somayajulu 				addr = entry_addr;
48726a62bec0SDavid C Somayajulu 			}
48736a62bec0SDavid C Somayajulu 
48746a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 0);
48756a62bec0SDavid C Somayajulu 			if (ret)
48766a62bec0SDavid C Somayajulu 				return (0);
48776a62bec0SDavid C Somayajulu 
48786a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_WRSTATE;
48796a62bec0SDavid C Somayajulu 		}
48806a62bec0SDavid C Somayajulu 
48816a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_MDSTATE) {
48826a62bec0SDavid C Somayajulu 			/*  Read value from saved state using index */
48836a62bec0SDavid C Somayajulu 			read_value = template_hdr->saved_state_array[
48846a62bec0SDavid C Somayajulu 						crbEntry->state_index_v];
48856a62bec0SDavid C Somayajulu 
48866a62bec0SDavid C Somayajulu 			read_value <<= crbEntry->shl; /*Shift left operation */
48876a62bec0SDavid C Somayajulu 			read_value >>= crbEntry->shr; /*Shift right operation */
48886a62bec0SDavid C Somayajulu 
48896a62bec0SDavid C Somayajulu 			if (crbEntry->value_2) {
48906a62bec0SDavid C Somayajulu 				/* check if AND mask is provided */
48916a62bec0SDavid C Somayajulu 				read_value &= crbEntry->value_2;
48926a62bec0SDavid C Somayajulu 			}
48936a62bec0SDavid C Somayajulu 
48946a62bec0SDavid C Somayajulu 			read_value |= crbEntry->value_3; /* OR operation */
48956a62bec0SDavid C Somayajulu 			read_value += crbEntry->value_1; /* increment op */
48966a62bec0SDavid C Somayajulu 
48976a62bec0SDavid C Somayajulu 			/* Write value back to state area. */
48986a62bec0SDavid C Somayajulu 
48996a62bec0SDavid C Somayajulu 			template_hdr->saved_state_array[crbEntry->state_index_v]
49006a62bec0SDavid C Somayajulu 					= read_value;
49016a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_MDSTATE;
49026a62bec0SDavid C Somayajulu 		}
49036a62bec0SDavid C Somayajulu 
49046a62bec0SDavid C Somayajulu 		entry_addr += crbEntry->addr_stride;
49056a62bec0SDavid C Somayajulu 	}
49066a62bec0SDavid C Somayajulu 
49076a62bec0SDavid C Somayajulu 	return (0);
49086a62bec0SDavid C Somayajulu }
49096a62bec0SDavid C Somayajulu 
49106a62bec0SDavid C Somayajulu /*
49116a62bec0SDavid C Somayajulu  * Handling rd poll entry.
49126a62bec0SDavid C Somayajulu  */
49136a62bec0SDavid C Somayajulu 
49146a62bec0SDavid C Somayajulu static uint32_t
49156a62bec0SDavid C Somayajulu ql_pollrd(qla_host_t *ha, ql_minidump_entry_pollrd_t *entry,
49166a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
49176a62bec0SDavid C Somayajulu {
49186a62bec0SDavid C Somayajulu         int ret;
49196a62bec0SDavid C Somayajulu         int loop_cnt;
49206a62bec0SDavid C Somayajulu         uint32_t op_count, select_addr, select_value_stride, select_value;
49216a62bec0SDavid C Somayajulu         uint32_t read_addr, poll, mask, data_size, data;
49226a62bec0SDavid C Somayajulu         uint32_t wait_count = 0;
49236a62bec0SDavid C Somayajulu 
49246a62bec0SDavid C Somayajulu         select_addr            = entry->select_addr;
49256a62bec0SDavid C Somayajulu         read_addr              = entry->read_addr;
49266a62bec0SDavid C Somayajulu         select_value           = entry->select_value;
49276a62bec0SDavid C Somayajulu         select_value_stride    = entry->select_value_stride;
49286a62bec0SDavid C Somayajulu         op_count               = entry->op_count;
49296a62bec0SDavid C Somayajulu         poll                   = entry->poll;
49306a62bec0SDavid C Somayajulu         mask                   = entry->mask;
49316a62bec0SDavid C Somayajulu         data_size              = entry->data_size;
49326a62bec0SDavid C Somayajulu 
49336a62bec0SDavid C Somayajulu         for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
49346a62bec0SDavid C Somayajulu 
49356a62bec0SDavid C Somayajulu                 ret = ql_rdwr_indreg32(ha, select_addr, &select_value, 0);
49366a62bec0SDavid C Somayajulu 		if (ret)
49376a62bec0SDavid C Somayajulu 			return (0);
49386a62bec0SDavid C Somayajulu 
49396a62bec0SDavid C Somayajulu                 wait_count = 0;
49406a62bec0SDavid C Somayajulu 
49416a62bec0SDavid C Somayajulu                 while (wait_count < poll) {
49426a62bec0SDavid C Somayajulu 
49436a62bec0SDavid C Somayajulu                         uint32_t temp;
49446a62bec0SDavid C Somayajulu 
49456a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, select_addr, &temp, 1);
49466a62bec0SDavid C Somayajulu 			if (ret)
49476a62bec0SDavid C Somayajulu 				return (0);
49486a62bec0SDavid C Somayajulu 
49496a62bec0SDavid C Somayajulu                         if ( (temp & mask) != 0 ) {
49506a62bec0SDavid C Somayajulu                                 break;
49516a62bec0SDavid C Somayajulu                         }
49526a62bec0SDavid C Somayajulu                         wait_count++;
49536a62bec0SDavid C Somayajulu                 }
49546a62bec0SDavid C Somayajulu 
49556a62bec0SDavid C Somayajulu                 if (wait_count == poll) {
49566a62bec0SDavid C Somayajulu                         device_printf(ha->pci_dev,
49576a62bec0SDavid C Somayajulu 				"%s: Error in processing entry\n", __func__);
49586a62bec0SDavid C Somayajulu                         device_printf(ha->pci_dev,
49596a62bec0SDavid C Somayajulu 				"%s: wait_count <0x%x> poll <0x%x>\n",
49606a62bec0SDavid C Somayajulu 				__func__, wait_count, poll);
49616a62bec0SDavid C Somayajulu                         return 0;
49626a62bec0SDavid C Somayajulu                 }
49636a62bec0SDavid C Somayajulu 
49646a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &data, 1);
49656a62bec0SDavid C Somayajulu 		if (ret)
49666a62bec0SDavid C Somayajulu 			return (0);
49676a62bec0SDavid C Somayajulu 
49686a62bec0SDavid C Somayajulu                 *data_buff++ = select_value;
49696a62bec0SDavid C Somayajulu                 *data_buff++ = data;
49706a62bec0SDavid C Somayajulu                 select_value = select_value + select_value_stride;
49716a62bec0SDavid C Somayajulu         }
49726a62bec0SDavid C Somayajulu 
49736a62bec0SDavid C Somayajulu         /*
49746a62bec0SDavid C Somayajulu          * for testing purpose we return amount of data written
49756a62bec0SDavid C Somayajulu          */
49766a62bec0SDavid C Somayajulu         return (loop_cnt * (2 * sizeof(uint32_t)));
49776a62bec0SDavid C Somayajulu }
49786a62bec0SDavid C Somayajulu 
49796a62bec0SDavid C Somayajulu 
49806a62bec0SDavid C Somayajulu /*
49816a62bec0SDavid C Somayajulu  * Handling rd modify write poll entry.
49826a62bec0SDavid C Somayajulu  */
49836a62bec0SDavid C Somayajulu 
49846a62bec0SDavid C Somayajulu static uint32_t
49856a62bec0SDavid C Somayajulu ql_pollrd_modify_write(qla_host_t *ha,
49866a62bec0SDavid C Somayajulu 	ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
49876a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
49886a62bec0SDavid C Somayajulu {
49896a62bec0SDavid C Somayajulu 	int ret;
49906a62bec0SDavid C Somayajulu         uint32_t addr_1, addr_2, value_1, value_2, data;
49916a62bec0SDavid C Somayajulu         uint32_t poll, mask, data_size, modify_mask;
49926a62bec0SDavid C Somayajulu         uint32_t wait_count = 0;
49936a62bec0SDavid C Somayajulu 
49946a62bec0SDavid C Somayajulu         addr_1		= entry->addr_1;
49956a62bec0SDavid C Somayajulu         addr_2		= entry->addr_2;
49966a62bec0SDavid C Somayajulu         value_1		= entry->value_1;
49976a62bec0SDavid C Somayajulu         value_2		= entry->value_2;
49986a62bec0SDavid C Somayajulu 
49996a62bec0SDavid C Somayajulu         poll		= entry->poll;
50006a62bec0SDavid C Somayajulu         mask		= entry->mask;
50016a62bec0SDavid C Somayajulu         modify_mask	= entry->modify_mask;
50026a62bec0SDavid C Somayajulu         data_size	= entry->data_size;
50036a62bec0SDavid C Somayajulu 
50046a62bec0SDavid C Somayajulu 
50056a62bec0SDavid C Somayajulu 	ret = ql_rdwr_indreg32(ha, addr_1, &value_1, 0);
50066a62bec0SDavid C Somayajulu 	if (ret)
50076a62bec0SDavid C Somayajulu 		return (0);
50086a62bec0SDavid C Somayajulu 
50096a62bec0SDavid C Somayajulu         wait_count = 0;
50106a62bec0SDavid C Somayajulu         while (wait_count < poll) {
50116a62bec0SDavid C Somayajulu 
50126a62bec0SDavid C Somayajulu 		uint32_t temp;
50136a62bec0SDavid C Somayajulu 
50146a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
50156a62bec0SDavid C Somayajulu 		if (ret)
50166a62bec0SDavid C Somayajulu 			return (0);
50176a62bec0SDavid C Somayajulu 
50186a62bec0SDavid C Somayajulu                 if ( (temp & mask) != 0 ) {
50196a62bec0SDavid C Somayajulu                         break;
50206a62bec0SDavid C Somayajulu                 }
50216a62bec0SDavid C Somayajulu                 wait_count++;
50226a62bec0SDavid C Somayajulu         }
50236a62bec0SDavid C Somayajulu 
50246a62bec0SDavid C Somayajulu         if (wait_count == poll) {
50256a62bec0SDavid C Somayajulu                 device_printf(ha->pci_dev, "%s Error in processing entry\n",
50266a62bec0SDavid C Somayajulu 			__func__);
50276a62bec0SDavid C Somayajulu         } else {
50286a62bec0SDavid C Somayajulu 
50296a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_2, &data, 1);
50306a62bec0SDavid C Somayajulu 		if (ret)
50316a62bec0SDavid C Somayajulu 			return (0);
50326a62bec0SDavid C Somayajulu 
50336a62bec0SDavid C Somayajulu                 data = (data & modify_mask);
50346a62bec0SDavid C Somayajulu 
50356a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_2, &data, 0);
50366a62bec0SDavid C Somayajulu 		if (ret)
50376a62bec0SDavid C Somayajulu 			return (0);
50386a62bec0SDavid C Somayajulu 
50396a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_1, &value_2, 0);
50406a62bec0SDavid C Somayajulu 		if (ret)
50416a62bec0SDavid C Somayajulu 			return (0);
50426a62bec0SDavid C Somayajulu 
50436a62bec0SDavid C Somayajulu                 /* Poll again */
50446a62bec0SDavid C Somayajulu                 wait_count = 0;
50456a62bec0SDavid C Somayajulu                 while (wait_count < poll) {
50466a62bec0SDavid C Somayajulu 
50476a62bec0SDavid C Somayajulu                         uint32_t temp;
50486a62bec0SDavid C Somayajulu 
50496a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
50506a62bec0SDavid C Somayajulu 			if (ret)
50516a62bec0SDavid C Somayajulu 				return (0);
50526a62bec0SDavid C Somayajulu 
50536a62bec0SDavid C Somayajulu                         if ( (temp & mask) != 0 ) {
50546a62bec0SDavid C Somayajulu                                 break;
50556a62bec0SDavid C Somayajulu                         }
50566a62bec0SDavid C Somayajulu                         wait_count++;
50576a62bec0SDavid C Somayajulu                 }
50586a62bec0SDavid C Somayajulu                 *data_buff++ = addr_2;
50596a62bec0SDavid C Somayajulu                 *data_buff++ = data;
50606a62bec0SDavid C Somayajulu         }
50616a62bec0SDavid C Somayajulu 
50626a62bec0SDavid C Somayajulu         /*
50636a62bec0SDavid C Somayajulu          * for testing purpose we return amount of data written
50646a62bec0SDavid C Somayajulu          */
50656a62bec0SDavid C Somayajulu         return (2 * sizeof(uint32_t));
50666a62bec0SDavid C Somayajulu }
50676a62bec0SDavid C Somayajulu 
50686a62bec0SDavid C Somayajulu 
5069