xref: /freebsd/sys/dev/qlxgbe/ql_hw.c (revision 00caeec7)
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
1131f10a77bbSDavid C Somayajulu qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac)
1132f10a77bbSDavid C Somayajulu {
1133f10a77bbSDavid C Somayajulu 	q80_config_mac_addr_t		*cmac;
1134f10a77bbSDavid C Somayajulu 	q80_config_mac_addr_rsp_t	*cmac_rsp;
1135f10a77bbSDavid C Somayajulu 	uint32_t			err;
1136f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1137f10a77bbSDavid C Somayajulu 
1138f10a77bbSDavid C Somayajulu 	cmac = (q80_config_mac_addr_t *)ha->hw.mbox;
1139f10a77bbSDavid C Somayajulu 	bzero(cmac, (sizeof (q80_config_mac_addr_t)));
1140f10a77bbSDavid C Somayajulu 
1141f10a77bbSDavid C Somayajulu 	cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR;
1142f10a77bbSDavid C Somayajulu 	cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2;
1143f10a77bbSDavid C Somayajulu 	cmac->count_version |= Q8_MBX_CMD_VERSION;
1144f10a77bbSDavid C Somayajulu 
1145f10a77bbSDavid C Somayajulu 	if (add_mac)
1146f10a77bbSDavid C Somayajulu 		cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR;
1147f10a77bbSDavid C Somayajulu 	else
1148f10a77bbSDavid C Somayajulu 		cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR;
1149f10a77bbSDavid C Somayajulu 
1150f10a77bbSDavid C Somayajulu 	cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS;
1151f10a77bbSDavid C Somayajulu 
1152f10a77bbSDavid C Somayajulu 	cmac->nmac_entries = 1;
1153f10a77bbSDavid C Somayajulu 	cmac->cntxt_id = ha->hw.rcv_cntxt_id;
1154f10a77bbSDavid C Somayajulu 	bcopy(mac_addr, cmac->mac_addr[0].addr, 6);
1155f10a77bbSDavid C Somayajulu 
1156f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)cmac,
1157f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_mac_addr_t) >> 2),
1158f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) {
1159f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: %s failed0\n", __func__,
1160f10a77bbSDavid C Somayajulu 			(add_mac ? "Add" : "Del"));
1161f10a77bbSDavid C Somayajulu 		return (-1);
1162f10a77bbSDavid C Somayajulu 	}
1163f10a77bbSDavid C Somayajulu 	cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox;
1164f10a77bbSDavid C Somayajulu 
1165f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status);
1166f10a77bbSDavid C Somayajulu 
1167f10a77bbSDavid C Somayajulu 	if (err) {
1168f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: %s "
1169f10a77bbSDavid C Somayajulu 			"%02x:%02x:%02x:%02x:%02x:%02x failed1 [0x%08x]\n",
1170f10a77bbSDavid C Somayajulu 			__func__, (add_mac ? "Add" : "Del"),
1171f10a77bbSDavid C Somayajulu 			mac_addr[0], mac_addr[1], mac_addr[2],
1172f10a77bbSDavid C Somayajulu 			mac_addr[3], mac_addr[4], mac_addr[5], err);
1173f10a77bbSDavid C Somayajulu 		return (-1);
1174f10a77bbSDavid C Somayajulu 	}
1175f10a77bbSDavid C Somayajulu 
1176f10a77bbSDavid C Somayajulu 	return 0;
1177f10a77bbSDavid C Somayajulu }
1178f10a77bbSDavid C Somayajulu 
1179f10a77bbSDavid C Somayajulu 
1180f10a77bbSDavid C Somayajulu /*
1181f10a77bbSDavid C Somayajulu  * Name: qla_set_mac_rcv_mode
11826a62bec0SDavid C Somayajulu  * Function: Enable/Disable AllMulticast and Promiscous Modes.
1183f10a77bbSDavid C Somayajulu  */
1184f10a77bbSDavid C Somayajulu static int
1185f10a77bbSDavid C Somayajulu qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode)
1186f10a77bbSDavid C Somayajulu {
1187f10a77bbSDavid C Somayajulu 	q80_config_mac_rcv_mode_t	*rcv_mode;
1188f10a77bbSDavid C Somayajulu 	uint32_t			err;
1189f10a77bbSDavid C Somayajulu 	q80_config_mac_rcv_mode_rsp_t	*rcv_mode_rsp;
1190f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1191f10a77bbSDavid C Somayajulu 
1192f10a77bbSDavid C Somayajulu 	rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox;
1193f10a77bbSDavid C Somayajulu 	bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t)));
1194f10a77bbSDavid C Somayajulu 
1195f10a77bbSDavid C Somayajulu 	rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE;
1196f10a77bbSDavid C Somayajulu 	rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2;
1197f10a77bbSDavid C Somayajulu 	rcv_mode->count_version |= Q8_MBX_CMD_VERSION;
1198f10a77bbSDavid C Somayajulu 
1199f10a77bbSDavid C Somayajulu 	rcv_mode->mode = mode;
1200f10a77bbSDavid C Somayajulu 
1201f10a77bbSDavid C Somayajulu 	rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id;
1202f10a77bbSDavid C Somayajulu 
1203f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode,
1204f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_mac_rcv_mode_t) >> 2),
1205f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) {
1206f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1207f10a77bbSDavid C Somayajulu 		return (-1);
1208f10a77bbSDavid C Somayajulu 	}
1209f10a77bbSDavid C Somayajulu 	rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox;
1210f10a77bbSDavid C Somayajulu 
1211f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status);
1212f10a77bbSDavid C Somayajulu 
1213f10a77bbSDavid C Somayajulu 	if (err) {
1214f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1215f10a77bbSDavid C Somayajulu 		return (-1);
1216f10a77bbSDavid C Somayajulu 	}
1217f10a77bbSDavid C Somayajulu 
1218f10a77bbSDavid C Somayajulu 	return 0;
1219f10a77bbSDavid C Somayajulu }
1220f10a77bbSDavid C Somayajulu 
1221f10a77bbSDavid C Somayajulu int
1222f10a77bbSDavid C Somayajulu ql_set_promisc(qla_host_t *ha)
1223f10a77bbSDavid C Somayajulu {
1224f10a77bbSDavid C Somayajulu 	int ret;
1225f10a77bbSDavid C Somayajulu 
1226f10a77bbSDavid C Somayajulu 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1227f10a77bbSDavid C Somayajulu 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1228f10a77bbSDavid C Somayajulu 	return (ret);
1229f10a77bbSDavid C Somayajulu }
1230f10a77bbSDavid C Somayajulu 
123135291c22SDavid C Somayajulu void
123235291c22SDavid C Somayajulu qla_reset_promisc(qla_host_t *ha)
123335291c22SDavid C Somayajulu {
123435291c22SDavid C Somayajulu 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE;
123535291c22SDavid C Somayajulu 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
123635291c22SDavid C Somayajulu }
123735291c22SDavid C Somayajulu 
1238f10a77bbSDavid C Somayajulu int
1239f10a77bbSDavid C Somayajulu ql_set_allmulti(qla_host_t *ha)
1240f10a77bbSDavid C Somayajulu {
1241f10a77bbSDavid C Somayajulu 	int ret;
1242f10a77bbSDavid C Somayajulu 
1243f10a77bbSDavid C Somayajulu 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE;
1244f10a77bbSDavid C Somayajulu 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1245f10a77bbSDavid C Somayajulu 	return (ret);
1246f10a77bbSDavid C Somayajulu }
1247f10a77bbSDavid C Somayajulu 
124835291c22SDavid C Somayajulu void
124935291c22SDavid C Somayajulu qla_reset_allmulti(qla_host_t *ha)
125035291c22SDavid C Somayajulu {
125135291c22SDavid C Somayajulu 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE;
125235291c22SDavid C Somayajulu 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
125335291c22SDavid C Somayajulu }
1254f10a77bbSDavid C Somayajulu 
1255f10a77bbSDavid C Somayajulu /*
1256f10a77bbSDavid C Somayajulu  * Name: ql_set_max_mtu
1257f10a77bbSDavid C Somayajulu  * Function:
1258f10a77bbSDavid C Somayajulu  *	Sets the maximum transfer unit size for the specified rcv context.
1259f10a77bbSDavid C Somayajulu  */
1260f10a77bbSDavid C Somayajulu int
1261f10a77bbSDavid C Somayajulu ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id)
1262f10a77bbSDavid C Somayajulu {
1263f10a77bbSDavid C Somayajulu 	device_t		dev;
1264f10a77bbSDavid C Somayajulu 	q80_set_max_mtu_t	*max_mtu;
1265f10a77bbSDavid C Somayajulu 	q80_set_max_mtu_rsp_t	*max_mtu_rsp;
1266f10a77bbSDavid C Somayajulu 	uint32_t		err;
1267f10a77bbSDavid C Somayajulu 
1268f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1269f10a77bbSDavid C Somayajulu 
1270f10a77bbSDavid C Somayajulu 	max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox;
1271f10a77bbSDavid C Somayajulu 	bzero(max_mtu, (sizeof (q80_set_max_mtu_t)));
1272f10a77bbSDavid C Somayajulu 
1273f10a77bbSDavid C Somayajulu 	max_mtu->opcode = Q8_MBX_SET_MAX_MTU;
1274f10a77bbSDavid C Somayajulu 	max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2);
1275f10a77bbSDavid C Somayajulu 	max_mtu->count_version |= Q8_MBX_CMD_VERSION;
1276f10a77bbSDavid C Somayajulu 
1277f10a77bbSDavid C Somayajulu 	max_mtu->cntxt_id = cntxt_id;
1278f10a77bbSDavid C Somayajulu 	max_mtu->mtu = mtu;
1279f10a77bbSDavid C Somayajulu 
1280f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)max_mtu,
1281f10a77bbSDavid C Somayajulu 		(sizeof (q80_set_max_mtu_t) >> 2),
1282f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) {
1283f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1284f10a77bbSDavid C Somayajulu                 return -1;
1285f10a77bbSDavid C Somayajulu         }
1286f10a77bbSDavid C Somayajulu 
1287f10a77bbSDavid C Somayajulu 	max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox;
1288f10a77bbSDavid C Somayajulu 
1289f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status);
1290f10a77bbSDavid C Somayajulu 
1291f10a77bbSDavid C Somayajulu         if (err) {
1292f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1293f10a77bbSDavid C Somayajulu         }
1294f10a77bbSDavid C Somayajulu 
1295f10a77bbSDavid C Somayajulu 	return 0;
1296f10a77bbSDavid C Somayajulu }
1297f10a77bbSDavid C Somayajulu 
1298f10a77bbSDavid C Somayajulu static int
1299f10a77bbSDavid C Somayajulu qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id)
1300f10a77bbSDavid C Somayajulu {
1301f10a77bbSDavid C Somayajulu 	device_t		dev;
1302f10a77bbSDavid C Somayajulu 	q80_link_event_t	*lnk;
1303f10a77bbSDavid C Somayajulu 	q80_link_event_rsp_t	*lnk_rsp;
1304f10a77bbSDavid C Somayajulu 	uint32_t		err;
1305f10a77bbSDavid C Somayajulu 
1306f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1307f10a77bbSDavid C Somayajulu 
1308f10a77bbSDavid C Somayajulu 	lnk = (q80_link_event_t *)ha->hw.mbox;
1309f10a77bbSDavid C Somayajulu 	bzero(lnk, (sizeof (q80_link_event_t)));
1310f10a77bbSDavid C Somayajulu 
1311f10a77bbSDavid C Somayajulu 	lnk->opcode = Q8_MBX_LINK_EVENT_REQ;
1312f10a77bbSDavid C Somayajulu 	lnk->count_version = (sizeof (q80_link_event_t) >> 2);
1313f10a77bbSDavid C Somayajulu 	lnk->count_version |= Q8_MBX_CMD_VERSION;
1314f10a77bbSDavid C Somayajulu 
1315f10a77bbSDavid C Somayajulu 	lnk->cntxt_id = cntxt_id;
1316f10a77bbSDavid C Somayajulu 	lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC;
1317f10a77bbSDavid C Somayajulu 
1318f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2),
1319f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) {
1320f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1321f10a77bbSDavid C Somayajulu                 return -1;
1322f10a77bbSDavid C Somayajulu         }
1323f10a77bbSDavid C Somayajulu 
1324f10a77bbSDavid C Somayajulu 	lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox;
1325f10a77bbSDavid C Somayajulu 
1326f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status);
1327f10a77bbSDavid C Somayajulu 
1328f10a77bbSDavid C Somayajulu         if (err) {
1329f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1330f10a77bbSDavid C Somayajulu         }
1331f10a77bbSDavid C Somayajulu 
1332f10a77bbSDavid C Somayajulu 	return 0;
1333f10a77bbSDavid C Somayajulu }
1334f10a77bbSDavid C Somayajulu 
1335f10a77bbSDavid C Somayajulu static int
1336f10a77bbSDavid C Somayajulu qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id)
1337f10a77bbSDavid C Somayajulu {
1338f10a77bbSDavid C Somayajulu 	device_t		dev;
1339f10a77bbSDavid C Somayajulu 	q80_config_fw_lro_t	*fw_lro;
1340f10a77bbSDavid C Somayajulu 	q80_config_fw_lro_rsp_t	*fw_lro_rsp;
1341f10a77bbSDavid C Somayajulu 	uint32_t		err;
1342f10a77bbSDavid C Somayajulu 
1343f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1344f10a77bbSDavid C Somayajulu 
1345f10a77bbSDavid C Somayajulu 	fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox;
1346f10a77bbSDavid C Somayajulu 	bzero(fw_lro, sizeof(q80_config_fw_lro_t));
1347f10a77bbSDavid C Somayajulu 
1348f10a77bbSDavid C Somayajulu 	fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO;
1349f10a77bbSDavid C Somayajulu 	fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2);
1350f10a77bbSDavid C Somayajulu 	fw_lro->count_version |= Q8_MBX_CMD_VERSION;
1351f10a77bbSDavid C Somayajulu 
1352f10a77bbSDavid C Somayajulu 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK;
135335291c22SDavid C Somayajulu 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK;
1354f10a77bbSDavid C Somayajulu 
1355f10a77bbSDavid C Somayajulu 	fw_lro->cntxt_id = cntxt_id;
1356f10a77bbSDavid C Somayajulu 
1357f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)fw_lro,
1358f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_fw_lro_t) >> 2),
1359f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) {
1360f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
1361f10a77bbSDavid C Somayajulu 		return -1;
1362f10a77bbSDavid C Somayajulu 	}
1363f10a77bbSDavid C Somayajulu 
1364f10a77bbSDavid C Somayajulu 	fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox;
1365f10a77bbSDavid C Somayajulu 
1366f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status);
1367f10a77bbSDavid C Somayajulu 
1368f10a77bbSDavid C Somayajulu 	if (err) {
1369f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1370f10a77bbSDavid C Somayajulu 	}
1371f10a77bbSDavid C Somayajulu 
1372f10a77bbSDavid C Somayajulu 	return 0;
1373f10a77bbSDavid C Somayajulu }
1374f10a77bbSDavid C Somayajulu 
137500caeec7SDavid C Somayajulu static int
137600caeec7SDavid C Somayajulu qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode)
137700caeec7SDavid C Somayajulu {
137800caeec7SDavid C Somayajulu 	device_t                dev;
137900caeec7SDavid C Somayajulu 	q80_hw_config_t         *hw_config;
138000caeec7SDavid C Somayajulu 	q80_hw_config_rsp_t     *hw_config_rsp;
138100caeec7SDavid C Somayajulu 	uint32_t                err;
138200caeec7SDavid C Somayajulu 
138300caeec7SDavid C Somayajulu 	dev = ha->pci_dev;
138400caeec7SDavid C Somayajulu 
138500caeec7SDavid C Somayajulu 	hw_config = (q80_hw_config_t *)ha->hw.mbox;
138600caeec7SDavid C Somayajulu 	bzero(hw_config, sizeof (q80_hw_config_t));
138700caeec7SDavid C Somayajulu 
138800caeec7SDavid C Somayajulu 	hw_config->opcode = Q8_MBX_HW_CONFIG;
138900caeec7SDavid C Somayajulu 	hw_config->count_version = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE_COUNT;
139000caeec7SDavid C Somayajulu 	hw_config->count_version |= Q8_MBX_CMD_VERSION;
139100caeec7SDavid C Somayajulu 
139200caeec7SDavid C Somayajulu 	hw_config->cmd = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE;
139300caeec7SDavid C Somayajulu 
139400caeec7SDavid C Somayajulu 	hw_config->u.set_cam_search_mode.mode = search_mode;
139500caeec7SDavid C Somayajulu 
139600caeec7SDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
139700caeec7SDavid C Somayajulu 		(sizeof (q80_hw_config_t) >> 2),
139800caeec7SDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
139900caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
140000caeec7SDavid C Somayajulu 		return -1;
140100caeec7SDavid C Somayajulu 	}
140200caeec7SDavid C Somayajulu 	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
140300caeec7SDavid C Somayajulu 
140400caeec7SDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
140500caeec7SDavid C Somayajulu 
140600caeec7SDavid C Somayajulu 	if (err) {
140700caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
140800caeec7SDavid C Somayajulu 	}
140900caeec7SDavid C Somayajulu 
141000caeec7SDavid C Somayajulu 	return 0;
141100caeec7SDavid C Somayajulu }
141200caeec7SDavid C Somayajulu 
141300caeec7SDavid C Somayajulu static int
141400caeec7SDavid C Somayajulu qla_get_cam_search_mode(qla_host_t *ha)
141500caeec7SDavid C Somayajulu {
141600caeec7SDavid C Somayajulu 	device_t                dev;
141700caeec7SDavid C Somayajulu 	q80_hw_config_t         *hw_config;
141800caeec7SDavid C Somayajulu 	q80_hw_config_rsp_t     *hw_config_rsp;
141900caeec7SDavid C Somayajulu 	uint32_t                err;
142000caeec7SDavid C Somayajulu 
142100caeec7SDavid C Somayajulu 	dev = ha->pci_dev;
142200caeec7SDavid C Somayajulu 
142300caeec7SDavid C Somayajulu 	hw_config = (q80_hw_config_t *)ha->hw.mbox;
142400caeec7SDavid C Somayajulu 	bzero(hw_config, sizeof (q80_hw_config_t));
142500caeec7SDavid C Somayajulu 
142600caeec7SDavid C Somayajulu 	hw_config->opcode = Q8_MBX_HW_CONFIG;
142700caeec7SDavid C Somayajulu 	hw_config->count_version = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE_COUNT;
142800caeec7SDavid C Somayajulu 	hw_config->count_version |= Q8_MBX_CMD_VERSION;
142900caeec7SDavid C Somayajulu 
143000caeec7SDavid C Somayajulu 	hw_config->cmd = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE;
143100caeec7SDavid C Somayajulu 
143200caeec7SDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
143300caeec7SDavid C Somayajulu 		(sizeof (q80_hw_config_t) >> 2),
143400caeec7SDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
143500caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
143600caeec7SDavid C Somayajulu 		return -1;
143700caeec7SDavid C Somayajulu 	}
143800caeec7SDavid C Somayajulu 	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
143900caeec7SDavid C Somayajulu 
144000caeec7SDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
144100caeec7SDavid C Somayajulu 
144200caeec7SDavid C Somayajulu 	if (err) {
144300caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
144400caeec7SDavid C Somayajulu 	} else {
144500caeec7SDavid C Somayajulu 		device_printf(dev, "%s: cam search mode [0x%08x]\n", __func__,
144600caeec7SDavid C Somayajulu 			hw_config_rsp->u.get_cam_search_mode.mode);
144700caeec7SDavid C Somayajulu 	}
144800caeec7SDavid C Somayajulu 
144900caeec7SDavid C Somayajulu 	return 0;
145000caeec7SDavid C Somayajulu }
145100caeec7SDavid C Somayajulu 
145200caeec7SDavid C Somayajulu 
145300caeec7SDavid C Somayajulu 
1454f10a77bbSDavid C Somayajulu static void
145535291c22SDavid C Somayajulu qla_xmt_stats(qla_host_t *ha, q80_xmt_stats_t *xstat, int i)
1456f10a77bbSDavid C Somayajulu {
1457f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1458f10a77bbSDavid C Somayajulu 
145935291c22SDavid C Somayajulu 	if (i < ha->hw.num_tx_rings) {
146035291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: total_bytes\t\t%" PRIu64 "\n",
146135291c22SDavid C Somayajulu 			__func__, i, xstat->total_bytes);
146235291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: total_pkts\t\t%" PRIu64 "\n",
146335291c22SDavid C Somayajulu 			__func__, i, xstat->total_pkts);
146435291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: errors\t\t%" PRIu64 "\n",
146535291c22SDavid C Somayajulu 			__func__, i, xstat->errors);
146635291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: pkts_dropped\t%" PRIu64 "\n",
146735291c22SDavid C Somayajulu 			__func__, i, xstat->pkts_dropped);
146835291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: switch_pkts\t\t%" PRIu64 "\n",
146935291c22SDavid C Somayajulu 			__func__, i, xstat->switch_pkts);
147035291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: num_buffers\t\t%" PRIu64 "\n",
147135291c22SDavid C Somayajulu 			__func__, i, xstat->num_buffers);
147235291c22SDavid C Somayajulu 	} else {
147335291c22SDavid C Somayajulu 		device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n",
147435291c22SDavid C Somayajulu 			__func__, xstat->total_bytes);
147535291c22SDavid C Somayajulu 		device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n",
147635291c22SDavid C Somayajulu 			__func__, xstat->total_pkts);
147735291c22SDavid C Somayajulu 		device_printf(dev, "%s: errors\t\t\t%" PRIu64 "\n",
147835291c22SDavid C Somayajulu 			__func__, xstat->errors);
147935291c22SDavid C Somayajulu 		device_printf(dev, "%s: pkts_dropped\t\t\t%" PRIu64 "\n",
148035291c22SDavid C Somayajulu 			__func__, xstat->pkts_dropped);
148135291c22SDavid C Somayajulu 		device_printf(dev, "%s: switch_pkts\t\t\t%" PRIu64 "\n",
148235291c22SDavid C Somayajulu 			__func__, xstat->switch_pkts);
148335291c22SDavid C Somayajulu 		device_printf(dev, "%s: num_buffers\t\t\t%" PRIu64 "\n",
148435291c22SDavid C Somayajulu 			__func__, xstat->num_buffers);
148535291c22SDavid C Somayajulu 	}
1486f10a77bbSDavid C Somayajulu }
1487f10a77bbSDavid C Somayajulu 
1488f10a77bbSDavid C Somayajulu static void
1489f10a77bbSDavid C Somayajulu qla_rcv_stats(qla_host_t *ha, q80_rcv_stats_t *rstat)
1490f10a77bbSDavid C Somayajulu {
1491f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1492f10a77bbSDavid C Somayajulu 
1493f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n", __func__,
1494f10a77bbSDavid C Somayajulu 		rstat->total_bytes);
1495f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n", __func__,
1496f10a77bbSDavid C Somayajulu 		rstat->total_pkts);
1497f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_pkt_count\t\t%" PRIu64 "\n", __func__,
1498f10a77bbSDavid C Somayajulu 		rstat->lro_pkt_count);
149935291c22SDavid C Somayajulu 	device_printf(dev, "%s: sw_pkt_count\t\t\t%" PRIu64 "\n", __func__,
1500f10a77bbSDavid C Somayajulu 		rstat->sw_pkt_count);
1501f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: ip_chksum_err\t\t%" PRIu64 "\n", __func__,
1502f10a77bbSDavid C Somayajulu 		rstat->ip_chksum_err);
1503f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_wo_acntxts\t\t%" PRIu64 "\n", __func__,
1504f10a77bbSDavid C Somayajulu 		rstat->pkts_wo_acntxts);
1505f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_sds_card\t%" PRIu64 "\n",
1506f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_sds_card);
1507f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_sds_host\t%" PRIu64 "\n",
1508f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_sds_host);
1509f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: oversized_pkts\t\t%" PRIu64 "\n", __func__,
1510f10a77bbSDavid C Somayajulu 		rstat->oversized_pkts);
1511f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_rds\t\t%" PRIu64 "\n",
1512f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_rds);
1513f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: unxpctd_mcast_pkts\t\t%" PRIu64 "\n",
1514f10a77bbSDavid C Somayajulu 		__func__, rstat->unxpctd_mcast_pkts);
1515f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: re1_fbq_error\t\t%" PRIu64 "\n", __func__,
1516f10a77bbSDavid C Somayajulu 		rstat->re1_fbq_error);
1517f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: invalid_mac_addr\t\t%" PRIu64 "\n", __func__,
1518f10a77bbSDavid C Somayajulu 		rstat->invalid_mac_addr);
1519f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rds_prime_trys\t\t%" PRIu64 "\n", __func__,
1520f10a77bbSDavid C Somayajulu 		rstat->rds_prime_trys);
1521f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rds_prime_success\t\t%" PRIu64 "\n", __func__,
1522f10a77bbSDavid C Somayajulu 		rstat->rds_prime_success);
1523f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_added\t\t%" PRIu64 "\n", __func__,
1524f10a77bbSDavid C Somayajulu 		rstat->lro_flows_added);
1525f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_deleted\t\t%" PRIu64 "\n", __func__,
1526f10a77bbSDavid C Somayajulu 		rstat->lro_flows_deleted);
1527f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_active\t\t%" PRIu64 "\n", __func__,
1528f10a77bbSDavid C Somayajulu 		rstat->lro_flows_active);
1529f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_droped_unknown\t\t%" PRIu64 "\n",
1530f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_droped_unknown);
1531f10a77bbSDavid C Somayajulu }
1532f10a77bbSDavid C Somayajulu 
1533f10a77bbSDavid C Somayajulu static void
1534f10a77bbSDavid C Somayajulu qla_mac_stats(qla_host_t *ha, q80_mac_stats_t *mstat)
1535f10a77bbSDavid C Somayajulu {
1536f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1537f10a77bbSDavid C Somayajulu 
1538f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_frames\t\t\t%" PRIu64 "\n", __func__,
1539f10a77bbSDavid C Somayajulu 		mstat->xmt_frames);
1540f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_bytes\t\t\t%" PRIu64 "\n", __func__,
1541f10a77bbSDavid C Somayajulu 		mstat->xmt_bytes);
1542f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1543f10a77bbSDavid C Somayajulu 		mstat->xmt_mcast_pkts);
1544f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1545f10a77bbSDavid C Somayajulu 		mstat->xmt_bcast_pkts);
1546f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pause_frames\t\t%" PRIu64 "\n", __func__,
1547f10a77bbSDavid C Somayajulu 		mstat->xmt_pause_frames);
1548f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1549f10a77bbSDavid C Somayajulu 		mstat->xmt_cntrl_pkts);
1550f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1551f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_64bytes);
1552f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1553f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_127bytes);
1554f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1555f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_255bytes);
1556f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1557f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_511bytes);
155835291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_1023bytes\t\t%" PRIu64 "\n",
1559f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_1023bytes);
156035291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_1518bytes\t\t%" PRIu64 "\n",
1561f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_1518bytes);
156235291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_gt_1518bytes\t\t%" PRIu64 "\n",
1563f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_gt_1518bytes);
1564f10a77bbSDavid C Somayajulu 
1565f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_frames\t\t\t%" PRIu64 "\n", __func__,
1566f10a77bbSDavid C Somayajulu 		mstat->rcv_frames);
1567f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_bytes\t\t\t%" PRIu64 "\n", __func__,
1568f10a77bbSDavid C Somayajulu 		mstat->rcv_bytes);
1569f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1570f10a77bbSDavid C Somayajulu 		mstat->rcv_mcast_pkts);
1571f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1572f10a77bbSDavid C Somayajulu 		mstat->rcv_bcast_pkts);
1573f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pause_frames\t\t%" PRIu64 "\n", __func__,
1574f10a77bbSDavid C Somayajulu 		mstat->rcv_pause_frames);
1575f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1576f10a77bbSDavid C Somayajulu 		mstat->rcv_cntrl_pkts);
1577f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1578f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_64bytes);
1579f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1580f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_127bytes);
1581f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1582f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_255bytes);
1583f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1584f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_511bytes);
158535291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_1023bytes\t\t%" PRIu64 "\n",
1586f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_1023bytes);
158735291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_1518bytes\t\t%" PRIu64 "\n",
1588f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_1518bytes);
158935291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_gt_1518bytes\t\t%" PRIu64 "\n",
1590f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_gt_1518bytes);
1591f10a77bbSDavid C Somayajulu 
1592f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_error\t\t%" PRIu64 "\n", __func__,
1593f10a77bbSDavid C Somayajulu 		mstat->rcv_len_error);
1594f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_small\t\t%" PRIu64 "\n", __func__,
1595f10a77bbSDavid C Somayajulu 		mstat->rcv_len_small);
1596f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_large\t\t%" PRIu64 "\n", __func__,
1597f10a77bbSDavid C Somayajulu 		mstat->rcv_len_large);
1598f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_jabber\t\t\t%" PRIu64 "\n", __func__,
1599f10a77bbSDavid C Somayajulu 		mstat->rcv_jabber);
1600f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_dropped\t\t\t%" PRIu64 "\n", __func__,
1601f10a77bbSDavid C Somayajulu 		mstat->rcv_dropped);
1602f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: fcs_error\t\t\t%" PRIu64 "\n", __func__,
1603f10a77bbSDavid C Somayajulu 		mstat->fcs_error);
1604f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: align_error\t\t\t%" PRIu64 "\n", __func__,
1605f10a77bbSDavid C Somayajulu 		mstat->align_error);
1606f10a77bbSDavid C Somayajulu }
1607f10a77bbSDavid C Somayajulu 
1608f10a77bbSDavid C Somayajulu 
1609f10a77bbSDavid C Somayajulu static int
161035291c22SDavid C Somayajulu qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size)
1611f10a77bbSDavid C Somayajulu {
1612f10a77bbSDavid C Somayajulu 	device_t		dev;
1613f10a77bbSDavid C Somayajulu 	q80_get_stats_t		*stat;
1614f10a77bbSDavid C Somayajulu 	q80_get_stats_rsp_t	*stat_rsp;
1615f10a77bbSDavid C Somayajulu 	uint32_t		err;
1616f10a77bbSDavid C Somayajulu 
1617f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1618f10a77bbSDavid C Somayajulu 
1619f10a77bbSDavid C Somayajulu 	stat = (q80_get_stats_t *)ha->hw.mbox;
1620f10a77bbSDavid C Somayajulu 	bzero(stat, (sizeof (q80_get_stats_t)));
1621f10a77bbSDavid C Somayajulu 
1622f10a77bbSDavid C Somayajulu 	stat->opcode = Q8_MBX_GET_STATS;
1623f10a77bbSDavid C Somayajulu 	stat->count_version = 2;
1624f10a77bbSDavid C Somayajulu 	stat->count_version |= Q8_MBX_CMD_VERSION;
1625f10a77bbSDavid C Somayajulu 
1626f10a77bbSDavid C Somayajulu 	stat->cmd = cmd;
1627f10a77bbSDavid C Somayajulu 
1628f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)stat, 2,
162935291c22SDavid C Somayajulu                 ha->hw.mbox, (rsp_size >> 2), 0)) {
1630f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1631f10a77bbSDavid C Somayajulu                 return -1;
1632f10a77bbSDavid C Somayajulu         }
1633f10a77bbSDavid C Somayajulu 
1634f10a77bbSDavid C Somayajulu 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1635f10a77bbSDavid C Somayajulu 
1636f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status);
1637f10a77bbSDavid C Somayajulu 
1638f10a77bbSDavid C Somayajulu         if (err) {
1639f10a77bbSDavid C Somayajulu                 return -1;
1640f10a77bbSDavid C Somayajulu         }
1641f10a77bbSDavid C Somayajulu 
1642f10a77bbSDavid C Somayajulu 	return 0;
1643f10a77bbSDavid C Somayajulu }
1644f10a77bbSDavid C Somayajulu 
1645f10a77bbSDavid C Somayajulu void
1646f10a77bbSDavid C Somayajulu ql_get_stats(qla_host_t *ha)
1647f10a77bbSDavid C Somayajulu {
1648f10a77bbSDavid C Somayajulu 	q80_get_stats_rsp_t	*stat_rsp;
1649f10a77bbSDavid C Somayajulu 	q80_mac_stats_t		*mstat;
1650f10a77bbSDavid C Somayajulu 	q80_xmt_stats_t		*xstat;
1651f10a77bbSDavid C Somayajulu 	q80_rcv_stats_t		*rstat;
1652f10a77bbSDavid C Somayajulu 	uint32_t		cmd;
165335291c22SDavid C Somayajulu 	int			i;
1654f10a77bbSDavid C Somayajulu 
1655f10a77bbSDavid C Somayajulu 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1656f10a77bbSDavid C Somayajulu 	/*
1657f10a77bbSDavid C Somayajulu 	 * Get MAC Statistics
1658f10a77bbSDavid C Somayajulu 	 */
1659f10a77bbSDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_TYPE_MAC;
166035291c22SDavid C Somayajulu //	cmd |= Q8_GET_STATS_CMD_CLEAR;
1661f10a77bbSDavid C Somayajulu 
1662f10a77bbSDavid C Somayajulu 	cmd |= ((ha->pci_func & 0x1) << 16);
1663f10a77bbSDavid C Somayajulu 
166435291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
1665f10a77bbSDavid C Somayajulu 		mstat = (q80_mac_stats_t *)&stat_rsp->u.mac;
1666f10a77bbSDavid C Somayajulu 		qla_mac_stats(ha, mstat);
1667f10a77bbSDavid C Somayajulu 	} else {
1668f10a77bbSDavid C Somayajulu                 device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n",
1669f10a77bbSDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
1670f10a77bbSDavid C Somayajulu 	}
1671f10a77bbSDavid C Somayajulu 	/*
1672f10a77bbSDavid C Somayajulu 	 * Get RCV Statistics
1673f10a77bbSDavid C Somayajulu 	 */
1674f10a77bbSDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT;
167535291c22SDavid C Somayajulu //	cmd |= Q8_GET_STATS_CMD_CLEAR;
1676f10a77bbSDavid C Somayajulu 	cmd |= (ha->hw.rcv_cntxt_id << 16);
1677f10a77bbSDavid C Somayajulu 
167835291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
1679f10a77bbSDavid C Somayajulu 		rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv;
1680f10a77bbSDavid C Somayajulu 		qla_rcv_stats(ha, rstat);
1681f10a77bbSDavid C Somayajulu 	} else {
1682f10a77bbSDavid C Somayajulu                 device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n",
1683f10a77bbSDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
1684f10a77bbSDavid C Somayajulu 	}
1685f10a77bbSDavid C Somayajulu 	/*
1686f10a77bbSDavid C Somayajulu 	 * Get XMT Statistics
1687f10a77bbSDavid C Somayajulu 	 */
168835291c22SDavid C Somayajulu 	for (i = 0 ; i < ha->hw.num_tx_rings; i++) {
1689f10a77bbSDavid C Somayajulu 		cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT;
169035291c22SDavid C Somayajulu //		cmd |= Q8_GET_STATS_CMD_CLEAR;
169135291c22SDavid C Somayajulu 		cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16);
1692f10a77bbSDavid C Somayajulu 
169335291c22SDavid C Somayajulu 		if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t))
169435291c22SDavid C Somayajulu 			== 0) {
1695f10a77bbSDavid C Somayajulu 			xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt;
169635291c22SDavid C Somayajulu 			qla_xmt_stats(ha, xstat, i);
1697f10a77bbSDavid C Somayajulu 		} else {
1698f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n",
1699f10a77bbSDavid C Somayajulu 				__func__, ha->hw.mbox[0]);
1700f10a77bbSDavid C Somayajulu 		}
1701f10a77bbSDavid C Somayajulu 	}
170235291c22SDavid C Somayajulu 	return;
170335291c22SDavid C Somayajulu }
170435291c22SDavid C Somayajulu 
170535291c22SDavid C Somayajulu static void
170635291c22SDavid C Somayajulu qla_get_quick_stats(qla_host_t *ha)
170735291c22SDavid C Somayajulu {
170835291c22SDavid C Somayajulu 	q80_get_mac_rcv_xmt_stats_rsp_t *stat_rsp;
170935291c22SDavid C Somayajulu 	q80_mac_stats_t         *mstat;
171035291c22SDavid C Somayajulu 	q80_xmt_stats_t         *xstat;
171135291c22SDavid C Somayajulu 	q80_rcv_stats_t         *rstat;
171235291c22SDavid C Somayajulu 	uint32_t                cmd;
171335291c22SDavid C Somayajulu 
171435291c22SDavid C Somayajulu 	stat_rsp = (q80_get_mac_rcv_xmt_stats_rsp_t *)ha->hw.mbox;
171535291c22SDavid C Somayajulu 
171635291c22SDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_TYPE_ALL;
171735291c22SDavid C Somayajulu //      cmd |= Q8_GET_STATS_CMD_CLEAR;
171835291c22SDavid C Somayajulu 
171935291c22SDavid C Somayajulu //      cmd |= ((ha->pci_func & 0x3) << 16);
172035291c22SDavid C Somayajulu 	cmd |= (0xFFFF << 16);
172135291c22SDavid C Somayajulu 
172235291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd,
172335291c22SDavid C Somayajulu 			sizeof (q80_get_mac_rcv_xmt_stats_rsp_t)) == 0) {
172435291c22SDavid C Somayajulu 
172535291c22SDavid C Somayajulu 		mstat = (q80_mac_stats_t *)&stat_rsp->mac;
172635291c22SDavid C Somayajulu 		rstat = (q80_rcv_stats_t *)&stat_rsp->rcv;
172735291c22SDavid C Somayajulu 		xstat = (q80_xmt_stats_t *)&stat_rsp->xmt;
172835291c22SDavid C Somayajulu 		qla_mac_stats(ha, mstat);
172935291c22SDavid C Somayajulu 		qla_rcv_stats(ha, rstat);
173035291c22SDavid C Somayajulu 		qla_xmt_stats(ha, xstat, ha->hw.num_tx_rings);
173135291c22SDavid C Somayajulu 	} else {
173235291c22SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: failed [0x%08x]\n",
173335291c22SDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
173435291c22SDavid C Somayajulu 	}
173535291c22SDavid C Somayajulu 	return;
173635291c22SDavid C Somayajulu }
1737f10a77bbSDavid C Somayajulu 
1738f10a77bbSDavid C Somayajulu /*
1739f10a77bbSDavid C Somayajulu  * Name: qla_tx_tso
1740f10a77bbSDavid C Somayajulu  * Function: Checks if the packet to be transmitted is a candidate for
1741f10a77bbSDavid C Somayajulu  *	Large TCP Segment Offload. If yes, the appropriate fields in the Tx
1742f10a77bbSDavid C Somayajulu  *	Ring Structure are plugged in.
1743f10a77bbSDavid C Somayajulu  */
1744f10a77bbSDavid C Somayajulu static int
1745f10a77bbSDavid C Somayajulu qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
1746f10a77bbSDavid C Somayajulu {
1747f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1748f10a77bbSDavid C Somayajulu 	struct ip *ip = NULL;
1749f10a77bbSDavid C Somayajulu 	struct ip6_hdr *ip6 = NULL;
1750f10a77bbSDavid C Somayajulu 	struct tcphdr *th = NULL;
1751f10a77bbSDavid C Somayajulu 	uint32_t ehdrlen,  hdrlen, ip_hlen, tcp_hlen, tcp_opt_off;
1752f10a77bbSDavid C Somayajulu 	uint16_t etype, opcode, offload = 1;
1753f10a77bbSDavid C Somayajulu 	device_t dev;
1754f10a77bbSDavid C Somayajulu 
1755f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1756f10a77bbSDavid C Somayajulu 
1757f10a77bbSDavid C Somayajulu 
1758f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
1759f10a77bbSDavid C Somayajulu 
1760f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1761f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1762f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_proto);
1763f10a77bbSDavid C Somayajulu 	} else {
1764f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN;
1765f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_encap_proto);
1766f10a77bbSDavid C Somayajulu 	}
1767f10a77bbSDavid C Somayajulu 
1768f10a77bbSDavid C Somayajulu 	hdrlen = 0;
1769f10a77bbSDavid C Somayajulu 
1770f10a77bbSDavid C Somayajulu 	switch (etype) {
1771f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IP:
1772f10a77bbSDavid C Somayajulu 
1773f10a77bbSDavid C Somayajulu 			tcp_opt_off = ehdrlen + sizeof(struct ip) +
1774f10a77bbSDavid C Somayajulu 					sizeof(struct tcphdr);
1775f10a77bbSDavid C Somayajulu 
1776f10a77bbSDavid C Somayajulu 			if (mp->m_len < tcp_opt_off) {
1777f10a77bbSDavid C Somayajulu 				m_copydata(mp, 0, tcp_opt_off, hdr);
1778f10a77bbSDavid C Somayajulu 				ip = (struct ip *)(hdr + ehdrlen);
1779f10a77bbSDavid C Somayajulu 			} else {
1780f10a77bbSDavid C Somayajulu 				ip = (struct ip *)(mp->m_data + ehdrlen);
1781f10a77bbSDavid C Somayajulu 			}
1782f10a77bbSDavid C Somayajulu 
1783f10a77bbSDavid C Somayajulu 			ip_hlen = ip->ip_hl << 2;
1784f10a77bbSDavid C Somayajulu 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
1785f10a77bbSDavid C Somayajulu 
1786f10a77bbSDavid C Somayajulu 
1787f10a77bbSDavid C Somayajulu 			if ((ip->ip_p != IPPROTO_TCP) ||
1788f10a77bbSDavid C Somayajulu 				(ip_hlen != sizeof (struct ip))){
1789f10a77bbSDavid C Somayajulu 				/* IP Options are not supported */
1790f10a77bbSDavid C Somayajulu 
1791f10a77bbSDavid C Somayajulu 				offload = 0;
1792f10a77bbSDavid C Somayajulu 			} else
1793f10a77bbSDavid C Somayajulu 				th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
1794f10a77bbSDavid C Somayajulu 
1795f10a77bbSDavid C Somayajulu 		break;
1796f10a77bbSDavid C Somayajulu 
1797f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IPV6:
1798f10a77bbSDavid C Somayajulu 
1799f10a77bbSDavid C Somayajulu 			tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) +
1800f10a77bbSDavid C Somayajulu 					sizeof (struct tcphdr);
1801f10a77bbSDavid C Somayajulu 
1802f10a77bbSDavid C Somayajulu 			if (mp->m_len < tcp_opt_off) {
1803f10a77bbSDavid C Somayajulu 				m_copydata(mp, 0, tcp_opt_off, hdr);
1804f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)(hdr + ehdrlen);
1805f10a77bbSDavid C Somayajulu 			} else {
1806f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1807f10a77bbSDavid C Somayajulu 			}
1808f10a77bbSDavid C Somayajulu 
1809f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof(struct ip6_hdr);
1810f10a77bbSDavid C Somayajulu 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6;
1811f10a77bbSDavid C Somayajulu 
1812f10a77bbSDavid C Somayajulu 			if (ip6->ip6_nxt != IPPROTO_TCP) {
1813f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv6\n", __func__);
1814f10a77bbSDavid C Somayajulu 				offload = 0;
1815f10a77bbSDavid C Somayajulu 			} else
1816f10a77bbSDavid C Somayajulu 				th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
1817f10a77bbSDavid C Somayajulu 		break;
1818f10a77bbSDavid C Somayajulu 
1819f10a77bbSDavid C Somayajulu 		default:
1820f10a77bbSDavid C Somayajulu 			QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__));
1821f10a77bbSDavid C Somayajulu 			offload = 0;
1822f10a77bbSDavid C Somayajulu 		break;
1823f10a77bbSDavid C Somayajulu 	}
1824f10a77bbSDavid C Somayajulu 
1825f10a77bbSDavid C Somayajulu 	if (!offload)
1826f10a77bbSDavid C Somayajulu 		return (-1);
1827f10a77bbSDavid C Somayajulu 
1828f10a77bbSDavid C Somayajulu 	tcp_hlen = th->th_off << 2;
1829f10a77bbSDavid C Somayajulu 	hdrlen = ehdrlen + ip_hlen + tcp_hlen;
1830f10a77bbSDavid C Somayajulu 
1831f10a77bbSDavid C Somayajulu         if (mp->m_len < hdrlen) {
1832f10a77bbSDavid C Somayajulu                 if (mp->m_len < tcp_opt_off) {
1833f10a77bbSDavid C Somayajulu                         if (tcp_hlen > sizeof(struct tcphdr)) {
1834f10a77bbSDavid C Somayajulu                                 m_copydata(mp, tcp_opt_off,
1835f10a77bbSDavid C Somayajulu                                         (tcp_hlen - sizeof(struct tcphdr)),
1836f10a77bbSDavid C Somayajulu                                         &hdr[tcp_opt_off]);
1837f10a77bbSDavid C Somayajulu                         }
1838f10a77bbSDavid C Somayajulu                 } else {
1839f10a77bbSDavid C Somayajulu                         m_copydata(mp, 0, hdrlen, hdr);
1840f10a77bbSDavid C Somayajulu                 }
1841f10a77bbSDavid C Somayajulu         }
1842f10a77bbSDavid C Somayajulu 
1843f10a77bbSDavid C Somayajulu 	tx_cmd->mss = mp->m_pkthdr.tso_segsz;
1844f10a77bbSDavid C Somayajulu 
1845f10a77bbSDavid C Somayajulu 	tx_cmd->flags_opcode = opcode ;
1846f10a77bbSDavid C Somayajulu 	tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen;
1847f10a77bbSDavid C Somayajulu 	tx_cmd->total_hdr_len = hdrlen;
1848f10a77bbSDavid C Somayajulu 
1849f10a77bbSDavid C Somayajulu 	/* Check for Multicast least significant bit of MSB == 1 */
1850f10a77bbSDavid C Somayajulu 	if (eh->evl_dhost[0] & 0x01) {
1851f10a77bbSDavid C Somayajulu 		tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST;
1852f10a77bbSDavid C Somayajulu 	}
1853f10a77bbSDavid C Somayajulu 
1854f10a77bbSDavid C Somayajulu 	if (mp->m_len < hdrlen) {
1855f10a77bbSDavid C Somayajulu 		printf("%d\n", hdrlen);
1856f10a77bbSDavid C Somayajulu 		return (1);
1857f10a77bbSDavid C Somayajulu 	}
1858f10a77bbSDavid C Somayajulu 
1859f10a77bbSDavid C Somayajulu 	return (0);
1860f10a77bbSDavid C Somayajulu }
1861f10a77bbSDavid C Somayajulu 
1862f10a77bbSDavid C Somayajulu /*
1863f10a77bbSDavid C Somayajulu  * Name: qla_tx_chksum
1864f10a77bbSDavid C Somayajulu  * Function: Checks if the packet to be transmitted is a candidate for
1865f10a77bbSDavid C Somayajulu  *	TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx
1866f10a77bbSDavid C Somayajulu  *	Ring Structure are plugged in.
1867f10a77bbSDavid C Somayajulu  */
1868f10a77bbSDavid C Somayajulu static int
1869f10a77bbSDavid C Somayajulu qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code,
1870f10a77bbSDavid C Somayajulu 	uint32_t *tcp_hdr_off)
1871f10a77bbSDavid C Somayajulu {
1872f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1873f10a77bbSDavid C Somayajulu 	struct ip *ip;
1874f10a77bbSDavid C Somayajulu 	struct ip6_hdr *ip6;
1875f10a77bbSDavid C Somayajulu 	uint32_t ehdrlen, ip_hlen;
1876f10a77bbSDavid C Somayajulu 	uint16_t etype, opcode, offload = 1;
1877f10a77bbSDavid C Somayajulu 	device_t dev;
1878f10a77bbSDavid C Somayajulu 	uint8_t buf[sizeof(struct ip6_hdr)];
1879f10a77bbSDavid C Somayajulu 
1880f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1881f10a77bbSDavid C Somayajulu 
1882f10a77bbSDavid C Somayajulu 	*op_code = 0;
1883f10a77bbSDavid C Somayajulu 
1884f10a77bbSDavid C Somayajulu 	if ((mp->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) == 0)
1885f10a77bbSDavid C Somayajulu 		return (-1);
1886f10a77bbSDavid C Somayajulu 
1887f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
1888f10a77bbSDavid C Somayajulu 
1889f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1890f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1891f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_proto);
1892f10a77bbSDavid C Somayajulu 	} else {
1893f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN;
1894f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_encap_proto);
1895f10a77bbSDavid C Somayajulu 	}
1896f10a77bbSDavid C Somayajulu 
1897f10a77bbSDavid C Somayajulu 
1898f10a77bbSDavid C Somayajulu 	switch (etype) {
1899f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IP:
1900f10a77bbSDavid C Somayajulu 			ip = (struct ip *)(mp->m_data + ehdrlen);
1901f10a77bbSDavid C Somayajulu 
1902f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof (struct ip);
1903f10a77bbSDavid C Somayajulu 
1904f10a77bbSDavid C Somayajulu 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1905f10a77bbSDavid C Somayajulu 				m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
1906f10a77bbSDavid C Somayajulu 				ip = (struct ip *)buf;
1907f10a77bbSDavid C Somayajulu 			}
1908f10a77bbSDavid C Somayajulu 
1909f10a77bbSDavid C Somayajulu 			if (ip->ip_p == IPPROTO_TCP)
1910f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM;
1911f10a77bbSDavid C Somayajulu 			else if (ip->ip_p == IPPROTO_UDP)
1912f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM;
1913f10a77bbSDavid C Somayajulu 			else {
1914f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv4\n", __func__);
1915f10a77bbSDavid C Somayajulu 				offload = 0;
1916f10a77bbSDavid C Somayajulu 			}
1917f10a77bbSDavid C Somayajulu 		break;
1918f10a77bbSDavid C Somayajulu 
1919f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IPV6:
1920f10a77bbSDavid C Somayajulu 			ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1921f10a77bbSDavid C Somayajulu 
1922f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof(struct ip6_hdr);
1923f10a77bbSDavid C Somayajulu 
1924f10a77bbSDavid C Somayajulu 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1925f10a77bbSDavid C Somayajulu 				m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
1926f10a77bbSDavid C Somayajulu 					buf);
1927f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)buf;
1928f10a77bbSDavid C Somayajulu 			}
1929f10a77bbSDavid C Somayajulu 
1930f10a77bbSDavid C Somayajulu 			if (ip6->ip6_nxt == IPPROTO_TCP)
1931f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6;
1932f10a77bbSDavid C Somayajulu 			else if (ip6->ip6_nxt == IPPROTO_UDP)
1933f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6;
1934f10a77bbSDavid C Somayajulu 			else {
1935f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv6\n", __func__);
1936f10a77bbSDavid C Somayajulu 				offload = 0;
1937f10a77bbSDavid C Somayajulu 			}
1938f10a77bbSDavid C Somayajulu 		break;
1939f10a77bbSDavid C Somayajulu 
1940f10a77bbSDavid C Somayajulu 		default:
1941f10a77bbSDavid C Somayajulu 			offload = 0;
1942f10a77bbSDavid C Somayajulu 		break;
1943f10a77bbSDavid C Somayajulu 	}
1944f10a77bbSDavid C Somayajulu 	if (!offload)
1945f10a77bbSDavid C Somayajulu 		return (-1);
1946f10a77bbSDavid C Somayajulu 
1947f10a77bbSDavid C Somayajulu 	*op_code = opcode;
1948f10a77bbSDavid C Somayajulu 	*tcp_hdr_off = (ip_hlen + ehdrlen);
1949f10a77bbSDavid C Somayajulu 
1950f10a77bbSDavid C Somayajulu 	return (0);
1951f10a77bbSDavid C Somayajulu }
1952f10a77bbSDavid C Somayajulu 
1953f10a77bbSDavid C Somayajulu #define QLA_TX_MIN_FREE 2
1954f10a77bbSDavid C Somayajulu /*
1955f10a77bbSDavid C Somayajulu  * Name: ql_hw_send
1956f10a77bbSDavid C Somayajulu  * Function: Transmits a packet. It first checks if the packet is a
1957f10a77bbSDavid C Somayajulu  *	candidate for Large TCP Segment Offload and then for UDP/TCP checksum
1958f10a77bbSDavid C Somayajulu  *	offload. If either of these creteria are not met, it is transmitted
1959f10a77bbSDavid C Somayajulu  *	as a regular ethernet frame.
1960f10a77bbSDavid C Somayajulu  */
1961f10a77bbSDavid C Somayajulu int
1962f10a77bbSDavid C Somayajulu ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
196335291c22SDavid C Somayajulu 	uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu)
1964f10a77bbSDavid C Somayajulu {
1965f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1966f10a77bbSDavid C Somayajulu 	qla_hw_t *hw = &ha->hw;
1967f10a77bbSDavid C Somayajulu 	q80_tx_cmd_t *tx_cmd, tso_cmd;
1968f10a77bbSDavid C Somayajulu 	bus_dma_segment_t *c_seg;
1969f10a77bbSDavid C Somayajulu 	uint32_t num_tx_cmds, hdr_len = 0;
1970f10a77bbSDavid C Somayajulu 	uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next;
1971f10a77bbSDavid C Somayajulu 	device_t dev;
1972f10a77bbSDavid C Somayajulu 	int i, ret;
1973f10a77bbSDavid C Somayajulu 	uint8_t *src = NULL, *dst = NULL;
1974f10a77bbSDavid C Somayajulu 	uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
1975f10a77bbSDavid C Somayajulu 	uint32_t op_code = 0;
1976f10a77bbSDavid C Somayajulu 	uint32_t tcp_hdr_off = 0;
1977f10a77bbSDavid C Somayajulu 
1978f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1979f10a77bbSDavid C Somayajulu 
1980f10a77bbSDavid C Somayajulu 	/*
1981f10a77bbSDavid C Somayajulu 	 * Always make sure there is atleast one empty slot in the tx_ring
1982f10a77bbSDavid C Somayajulu 	 * tx_ring is considered full when there only one entry available
1983f10a77bbSDavid C Somayajulu 	 */
1984f10a77bbSDavid C Somayajulu         num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2;
1985f10a77bbSDavid C Somayajulu 
1986f10a77bbSDavid C Somayajulu 	total_length = mp->m_pkthdr.len;
1987f10a77bbSDavid C Somayajulu 	if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
1988f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
1989f10a77bbSDavid C Somayajulu 			__func__, total_length);
1990f10a77bbSDavid C Somayajulu 		return (-1);
1991f10a77bbSDavid C Somayajulu 	}
1992f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
1993f10a77bbSDavid C Somayajulu 
1994f10a77bbSDavid C Somayajulu 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
1995f10a77bbSDavid C Somayajulu 
1996f10a77bbSDavid C Somayajulu 		bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
1997f10a77bbSDavid C Somayajulu 
1998f10a77bbSDavid C Somayajulu 		src = frame_hdr;
1999f10a77bbSDavid C Somayajulu 		ret = qla_tx_tso(ha, mp, &tso_cmd, src);
2000f10a77bbSDavid C Somayajulu 
2001f10a77bbSDavid C Somayajulu 		if (!(ret & ~1)) {
2002f10a77bbSDavid C Somayajulu 			/* find the additional tx_cmd descriptors required */
2003f10a77bbSDavid C Somayajulu 
2004f10a77bbSDavid C Somayajulu 			if (mp->m_flags & M_VLANTAG)
2005f10a77bbSDavid C Somayajulu 				tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN;
2006f10a77bbSDavid C Somayajulu 
2007f10a77bbSDavid C Somayajulu 			hdr_len = tso_cmd.total_hdr_len;
2008f10a77bbSDavid C Somayajulu 
2009f10a77bbSDavid C Somayajulu 			bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2010f10a77bbSDavid C Somayajulu 			bytes = QL_MIN(bytes, hdr_len);
2011f10a77bbSDavid C Somayajulu 
2012f10a77bbSDavid C Somayajulu 			num_tx_cmds++;
2013f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2014f10a77bbSDavid C Somayajulu 
2015f10a77bbSDavid C Somayajulu 			while (hdr_len) {
2016f10a77bbSDavid C Somayajulu 				bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2017f10a77bbSDavid C Somayajulu 				hdr_len -= bytes;
2018f10a77bbSDavid C Somayajulu 				num_tx_cmds++;
2019f10a77bbSDavid C Somayajulu 			}
2020f10a77bbSDavid C Somayajulu 			hdr_len = tso_cmd.total_hdr_len;
2021f10a77bbSDavid C Somayajulu 
2022f10a77bbSDavid C Somayajulu 			if (ret == 0)
2023f10a77bbSDavid C Somayajulu 				src = (uint8_t *)eh;
2024f10a77bbSDavid C Somayajulu 		} else
2025f10a77bbSDavid C Somayajulu 			return (EINVAL);
2026f10a77bbSDavid C Somayajulu 	} else {
2027f10a77bbSDavid C Somayajulu 		(void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off);
2028f10a77bbSDavid C Somayajulu 	}
2029f10a77bbSDavid C Somayajulu 
203035291c22SDavid C Somayajulu 	if (iscsi_pdu)
203135291c22SDavid C Somayajulu 		ha->hw.iscsi_pkt_count++;
203235291c22SDavid C Somayajulu 
2033f10a77bbSDavid C Somayajulu 	if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
2034f10a77bbSDavid C Somayajulu 		qla_hw_tx_done_locked(ha, txr_idx);
2035f10a77bbSDavid C Somayajulu 		if (hw->tx_cntxt[txr_idx].txr_free <=
2036f10a77bbSDavid C Somayajulu 				(num_tx_cmds + QLA_TX_MIN_FREE)) {
2037f10a77bbSDavid C Somayajulu         		QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= "
2038f10a77bbSDavid C Somayajulu 				"(num_tx_cmds + QLA_TX_MIN_FREE))\n",
2039f10a77bbSDavid C Somayajulu 				__func__));
2040f10a77bbSDavid C Somayajulu 			return (-1);
2041f10a77bbSDavid C Somayajulu 		}
2042f10a77bbSDavid C Somayajulu 	}
2043f10a77bbSDavid C Somayajulu 
2044f10a77bbSDavid C Somayajulu 	tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx];
2045f10a77bbSDavid C Somayajulu 
2046f10a77bbSDavid C Somayajulu         if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) {
2047f10a77bbSDavid C Somayajulu 
2048f10a77bbSDavid C Somayajulu                 if (nsegs > ha->hw.max_tx_segs)
2049f10a77bbSDavid C Somayajulu                         ha->hw.max_tx_segs = nsegs;
2050f10a77bbSDavid C Somayajulu 
2051f10a77bbSDavid C Somayajulu                 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2052f10a77bbSDavid C Somayajulu 
2053f10a77bbSDavid C Somayajulu                 if (op_code) {
2054f10a77bbSDavid C Somayajulu                         tx_cmd->flags_opcode = op_code;
2055f10a77bbSDavid C Somayajulu                         tx_cmd->tcp_hdr_off = tcp_hdr_off;
2056f10a77bbSDavid C Somayajulu 
2057f10a77bbSDavid C Somayajulu                 } else {
2058f10a77bbSDavid C Somayajulu                         tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER;
2059f10a77bbSDavid C Somayajulu                 }
2060f10a77bbSDavid C Somayajulu 	} else {
2061f10a77bbSDavid C Somayajulu 		bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
2062f10a77bbSDavid C Somayajulu 		ha->tx_tso_frames++;
2063f10a77bbSDavid C Somayajulu 	}
2064f10a77bbSDavid C Somayajulu 
2065f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2066f10a77bbSDavid C Somayajulu         	tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
206735291c22SDavid C Somayajulu 
206835291c22SDavid C Somayajulu 		if (iscsi_pdu)
206935291c22SDavid C Somayajulu 			eh->evl_tag |= ha->hw.user_pri_iscsi << 13;
207035291c22SDavid C Somayajulu 
2071f10a77bbSDavid C Somayajulu 	} else if (mp->m_flags & M_VLANTAG) {
2072f10a77bbSDavid C Somayajulu 
2073f10a77bbSDavid C Somayajulu 		if (hdr_len) { /* TSO */
2074f10a77bbSDavid C Somayajulu 			tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED |
2075f10a77bbSDavid C Somayajulu 						Q8_TX_CMD_FLAGS_HW_VLAN_ID);
2076f10a77bbSDavid C Somayajulu 			tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN;
2077f10a77bbSDavid C Somayajulu 		} else
2078f10a77bbSDavid C Somayajulu 			tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID;
2079f10a77bbSDavid C Somayajulu 
2080f10a77bbSDavid C Somayajulu 		ha->hw_vlan_tx_frames++;
2081f10a77bbSDavid C Somayajulu 		tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag;
208235291c22SDavid C Somayajulu 
208335291c22SDavid C Somayajulu 		if (iscsi_pdu) {
208435291c22SDavid C Somayajulu 			tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13;
208535291c22SDavid C Somayajulu 			mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci;
208635291c22SDavid C Somayajulu 		}
2087f10a77bbSDavid C Somayajulu 	}
2088f10a77bbSDavid C Somayajulu 
2089f10a77bbSDavid C Somayajulu 
2090f10a77bbSDavid C Somayajulu         tx_cmd->n_bufs = (uint8_t)nsegs;
2091f10a77bbSDavid C Somayajulu         tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF);
2092f10a77bbSDavid C Somayajulu         tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8)));
2093f10a77bbSDavid C Somayajulu 	tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func);
2094f10a77bbSDavid C Somayajulu 
2095f10a77bbSDavid C Somayajulu 	c_seg = segs;
2096f10a77bbSDavid C Somayajulu 
2097f10a77bbSDavid C Somayajulu 	while (1) {
2098f10a77bbSDavid C Somayajulu 		for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) {
2099f10a77bbSDavid C Somayajulu 
2100f10a77bbSDavid C Somayajulu 			switch (i) {
2101f10a77bbSDavid C Somayajulu 			case 0:
2102f10a77bbSDavid C Somayajulu 				tx_cmd->buf1_addr = c_seg->ds_addr;
2103f10a77bbSDavid C Somayajulu 				tx_cmd->buf1_len = c_seg->ds_len;
2104f10a77bbSDavid C Somayajulu 				break;
2105f10a77bbSDavid C Somayajulu 
2106f10a77bbSDavid C Somayajulu 			case 1:
2107f10a77bbSDavid C Somayajulu 				tx_cmd->buf2_addr = c_seg->ds_addr;
2108f10a77bbSDavid C Somayajulu 				tx_cmd->buf2_len = c_seg->ds_len;
2109f10a77bbSDavid C Somayajulu 				break;
2110f10a77bbSDavid C Somayajulu 
2111f10a77bbSDavid C Somayajulu 			case 2:
2112f10a77bbSDavid C Somayajulu 				tx_cmd->buf3_addr = c_seg->ds_addr;
2113f10a77bbSDavid C Somayajulu 				tx_cmd->buf3_len = c_seg->ds_len;
2114f10a77bbSDavid C Somayajulu 				break;
2115f10a77bbSDavid C Somayajulu 
2116f10a77bbSDavid C Somayajulu 			case 3:
2117f10a77bbSDavid C Somayajulu 				tx_cmd->buf4_addr = c_seg->ds_addr;
2118f10a77bbSDavid C Somayajulu 				tx_cmd->buf4_len = c_seg->ds_len;
2119f10a77bbSDavid C Somayajulu 				break;
2120f10a77bbSDavid C Somayajulu 			}
2121f10a77bbSDavid C Somayajulu 
2122f10a77bbSDavid C Somayajulu 			c_seg++;
2123f10a77bbSDavid C Somayajulu 			nsegs--;
2124f10a77bbSDavid C Somayajulu 		}
2125f10a77bbSDavid C Somayajulu 
2126f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2127f10a77bbSDavid C Somayajulu 			(hw->tx_cntxt[txr_idx].txr_next + 1) &
2128f10a77bbSDavid C Somayajulu 				(NUM_TX_DESCRIPTORS - 1);
2129f10a77bbSDavid C Somayajulu 		tx_cmd_count++;
2130f10a77bbSDavid C Somayajulu 
2131f10a77bbSDavid C Somayajulu 		if (!nsegs)
2132f10a77bbSDavid C Somayajulu 			break;
2133f10a77bbSDavid C Somayajulu 
2134f10a77bbSDavid C Somayajulu 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2135f10a77bbSDavid C Somayajulu 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2136f10a77bbSDavid C Somayajulu 	}
2137f10a77bbSDavid C Somayajulu 
2138f10a77bbSDavid C Somayajulu 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2139f10a77bbSDavid C Somayajulu 
2140f10a77bbSDavid C Somayajulu 		/* TSO : Copy the header in the following tx cmd descriptors */
2141f10a77bbSDavid C Somayajulu 
2142f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next;
2143f10a77bbSDavid C Somayajulu 
2144f10a77bbSDavid C Somayajulu 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2145f10a77bbSDavid C Somayajulu 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2146f10a77bbSDavid C Somayajulu 
2147f10a77bbSDavid C Somayajulu 		bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2148f10a77bbSDavid C Somayajulu 		bytes = QL_MIN(bytes, hdr_len);
2149f10a77bbSDavid C Somayajulu 
2150f10a77bbSDavid C Somayajulu 		dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN;
2151f10a77bbSDavid C Somayajulu 
2152f10a77bbSDavid C Somayajulu 		if (mp->m_flags & M_VLANTAG) {
2153f10a77bbSDavid C Somayajulu 			/* first copy the src/dst MAC addresses */
2154f10a77bbSDavid C Somayajulu 			bcopy(src, dst, (ETHER_ADDR_LEN * 2));
2155f10a77bbSDavid C Somayajulu 			dst += (ETHER_ADDR_LEN * 2);
2156f10a77bbSDavid C Somayajulu 			src += (ETHER_ADDR_LEN * 2);
2157f10a77bbSDavid C Somayajulu 
2158f10a77bbSDavid C Somayajulu 			*((uint16_t *)dst) = htons(ETHERTYPE_VLAN);
2159f10a77bbSDavid C Somayajulu 			dst += 2;
2160f10a77bbSDavid C Somayajulu 			*((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag);
2161f10a77bbSDavid C Somayajulu 			dst += 2;
2162f10a77bbSDavid C Somayajulu 
2163f10a77bbSDavid C Somayajulu 			/* bytes left in src header */
2164f10a77bbSDavid C Somayajulu 			hdr_len -= ((ETHER_ADDR_LEN * 2) +
2165f10a77bbSDavid C Somayajulu 					ETHER_VLAN_ENCAP_LEN);
2166f10a77bbSDavid C Somayajulu 
2167f10a77bbSDavid C Somayajulu 			/* bytes left in TxCmd Entry */
2168f10a77bbSDavid C Somayajulu 			bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN);
2169f10a77bbSDavid C Somayajulu 
2170f10a77bbSDavid C Somayajulu 
2171f10a77bbSDavid C Somayajulu 			bcopy(src, dst, bytes);
2172f10a77bbSDavid C Somayajulu 			src += bytes;
2173f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2174f10a77bbSDavid C Somayajulu 		} else {
2175f10a77bbSDavid C Somayajulu 			bcopy(src, dst, bytes);
2176f10a77bbSDavid C Somayajulu 			src += bytes;
2177f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2178f10a77bbSDavid C Somayajulu 		}
2179f10a77bbSDavid C Somayajulu 
2180f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2181f10a77bbSDavid C Somayajulu 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2182f10a77bbSDavid C Somayajulu 					(NUM_TX_DESCRIPTORS - 1);
2183f10a77bbSDavid C Somayajulu 		tx_cmd_count++;
2184f10a77bbSDavid C Somayajulu 
2185f10a77bbSDavid C Somayajulu 		while (hdr_len) {
2186f10a77bbSDavid C Somayajulu 			tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2187f10a77bbSDavid C Somayajulu 			bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2188f10a77bbSDavid C Somayajulu 
2189f10a77bbSDavid C Somayajulu 			bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2190f10a77bbSDavid C Somayajulu 
2191f10a77bbSDavid C Somayajulu 			bcopy(src, tx_cmd, bytes);
2192f10a77bbSDavid C Somayajulu 			src += bytes;
2193f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2194f10a77bbSDavid C Somayajulu 
2195f10a77bbSDavid C Somayajulu 			txr_next = hw->tx_cntxt[txr_idx].txr_next =
2196f10a77bbSDavid C Somayajulu 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2197f10a77bbSDavid C Somayajulu 					(NUM_TX_DESCRIPTORS - 1);
2198f10a77bbSDavid C Somayajulu 			tx_cmd_count++;
2199f10a77bbSDavid C Somayajulu 		}
2200f10a77bbSDavid C Somayajulu 	}
2201f10a77bbSDavid C Somayajulu 
2202f10a77bbSDavid C Somayajulu 	hw->tx_cntxt[txr_idx].txr_free =
2203f10a77bbSDavid C Somayajulu 		hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count;
2204f10a77bbSDavid C Somayajulu 
2205f10a77bbSDavid C Somayajulu 	QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\
2206f10a77bbSDavid C Somayajulu 		txr_idx);
2207f10a77bbSDavid C Somayajulu        	QL_DPRINT8(ha, (dev, "%s: return\n", __func__));
2208f10a77bbSDavid C Somayajulu 
2209f10a77bbSDavid C Somayajulu 	return (0);
2210f10a77bbSDavid C Somayajulu }
2211f10a77bbSDavid C Somayajulu 
2212f10a77bbSDavid C Somayajulu 
221335291c22SDavid C Somayajulu 
221435291c22SDavid C Somayajulu #define Q8_CONFIG_IND_TBL_SIZE	32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */
2215f10a77bbSDavid C Somayajulu static int
2216f10a77bbSDavid C Somayajulu qla_config_rss_ind_table(qla_host_t *ha)
2217f10a77bbSDavid C Somayajulu {
2218f10a77bbSDavid C Somayajulu 	uint32_t i, count;
221935291c22SDavid C Somayajulu 	uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE];
2220f10a77bbSDavid C Somayajulu 
2221f10a77bbSDavid C Somayajulu 
222235291c22SDavid C Somayajulu 	for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) {
2223f10a77bbSDavid C Somayajulu 		rss_ind_tbl[i] = i % ha->hw.num_sds_rings;
2224f10a77bbSDavid C Somayajulu 	}
2225f10a77bbSDavid C Somayajulu 
222635291c22SDavid C Somayajulu 	for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ;
222735291c22SDavid C Somayajulu 		i = i + Q8_CONFIG_IND_TBL_SIZE) {
2228f10a77bbSDavid C Somayajulu 
222935291c22SDavid C Somayajulu 		if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) {
2230f10a77bbSDavid C Somayajulu 			count = Q8_RSS_IND_TBL_MAX_IDX - i + 1;
2231f10a77bbSDavid C Somayajulu 		} else {
223235291c22SDavid C Somayajulu 			count = Q8_CONFIG_IND_TBL_SIZE;
2233f10a77bbSDavid C Somayajulu 		}
2234f10a77bbSDavid C Somayajulu 
2235f10a77bbSDavid C Somayajulu 		if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id,
2236f10a77bbSDavid C Somayajulu 			rss_ind_tbl))
2237f10a77bbSDavid C Somayajulu 			return (-1);
2238f10a77bbSDavid C Somayajulu 	}
2239f10a77bbSDavid C Somayajulu 
2240f10a77bbSDavid C Somayajulu 	return (0);
2241f10a77bbSDavid C Somayajulu }
2242f10a77bbSDavid C Somayajulu 
2243f10a77bbSDavid C Somayajulu /*
2244f10a77bbSDavid C Somayajulu  * Name: ql_del_hw_if
2245f10a77bbSDavid C Somayajulu  * Function: Destroys the hardware specific entities corresponding to an
2246f10a77bbSDavid C Somayajulu  *	Ethernet Interface
2247f10a77bbSDavid C Somayajulu  */
2248f10a77bbSDavid C Somayajulu void
2249f10a77bbSDavid C Somayajulu ql_del_hw_if(qla_host_t *ha)
2250f10a77bbSDavid C Somayajulu {
225135291c22SDavid C Somayajulu 	uint32_t i;
225235291c22SDavid C Somayajulu 	uint32_t num_msix;
225335291c22SDavid C Somayajulu 
225435291c22SDavid C Somayajulu 	(void)qla_stop_nic_func(ha);
2255f10a77bbSDavid C Somayajulu 
2256f10a77bbSDavid C Somayajulu 	qla_del_rcv_cntxt(ha);
2257f10a77bbSDavid C Somayajulu 	qla_del_xmt_cntxt(ha);
2258f10a77bbSDavid C Somayajulu 
2259f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.init_intr_cnxt) {
226035291c22SDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; ) {
226135291c22SDavid C Somayajulu 
226235291c22SDavid C Somayajulu 			if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
226335291c22SDavid C Somayajulu 				num_msix = Q8_MAX_INTR_VECTORS;
226435291c22SDavid C Somayajulu 			else
226535291c22SDavid C Somayajulu 				num_msix = ha->hw.num_sds_rings - i;
226635291c22SDavid C Somayajulu 			qla_config_intr_cntxt(ha, i, num_msix, 0);
226735291c22SDavid C Somayajulu 
226835291c22SDavid C Somayajulu 			i += num_msix;
226935291c22SDavid C Somayajulu 		}
227035291c22SDavid C Somayajulu 
2271f10a77bbSDavid C Somayajulu 		ha->hw.flags.init_intr_cnxt = 0;
2272f10a77bbSDavid C Somayajulu 	}
227335291c22SDavid C Somayajulu 	return;
2274f10a77bbSDavid C Somayajulu }
2275f10a77bbSDavid C Somayajulu 
227635291c22SDavid C Somayajulu void
227735291c22SDavid C Somayajulu qla_confirm_9kb_enable(qla_host_t *ha)
227835291c22SDavid C Somayajulu {
227935291c22SDavid C Somayajulu 	uint32_t supports_9kb = 0;
228035291c22SDavid C Somayajulu 
228135291c22SDavid C Somayajulu 	ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX);
228235291c22SDavid C Somayajulu 
228335291c22SDavid C Somayajulu 	/* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */
228435291c22SDavid C Somayajulu 	WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2);
228535291c22SDavid C Somayajulu 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
228635291c22SDavid C Somayajulu 
228735291c22SDavid C Somayajulu 	qla_get_nic_partition(ha, &supports_9kb, NULL);
228835291c22SDavid C Somayajulu 
228935291c22SDavid C Somayajulu 	if (!supports_9kb)
229035291c22SDavid C Somayajulu 		ha->hw.enable_9kb = 0;
229135291c22SDavid C Somayajulu 
229235291c22SDavid C Somayajulu 	return;
229335291c22SDavid C Somayajulu }
229435291c22SDavid C Somayajulu 
229535291c22SDavid C Somayajulu 
2296f10a77bbSDavid C Somayajulu /*
2297f10a77bbSDavid C Somayajulu  * Name: ql_init_hw_if
2298f10a77bbSDavid C Somayajulu  * Function: Creates the hardware specific entities corresponding to an
2299f10a77bbSDavid C Somayajulu  *	Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
2300f10a77bbSDavid C Somayajulu  *	corresponding to the interface. Enables LRO if allowed.
2301f10a77bbSDavid C Somayajulu  */
2302f10a77bbSDavid C Somayajulu int
2303f10a77bbSDavid C Somayajulu ql_init_hw_if(qla_host_t *ha)
2304f10a77bbSDavid C Somayajulu {
2305f10a77bbSDavid C Somayajulu 	device_t	dev;
2306f10a77bbSDavid C Somayajulu 	uint32_t	i;
2307f10a77bbSDavid C Somayajulu 	uint8_t		bcast_mac[6];
2308f10a77bbSDavid C Somayajulu 	qla_rdesc_t	*rdesc;
230935291c22SDavid C Somayajulu 	uint32_t	num_msix;
2310f10a77bbSDavid C Somayajulu 
2311f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2312f10a77bbSDavid C Somayajulu 
2313f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; i++) {
2314f10a77bbSDavid C Somayajulu 		bzero(ha->hw.dma_buf.sds_ring[i].dma_b,
2315f10a77bbSDavid C Somayajulu 			ha->hw.dma_buf.sds_ring[i].size);
2316f10a77bbSDavid C Somayajulu 	}
2317f10a77bbSDavid C Somayajulu 
231835291c22SDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; ) {
2319f10a77bbSDavid C Somayajulu 
232035291c22SDavid C Somayajulu 		if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
232135291c22SDavid C Somayajulu 			num_msix = Q8_MAX_INTR_VECTORS;
232235291c22SDavid C Somayajulu 		else
232335291c22SDavid C Somayajulu 			num_msix = ha->hw.num_sds_rings - i;
2324f10a77bbSDavid C Somayajulu 
232535291c22SDavid C Somayajulu 		if (qla_config_intr_cntxt(ha, i, num_msix, 1)) {
232635291c22SDavid C Somayajulu 
232735291c22SDavid C Somayajulu 			if (i > 0) {
232835291c22SDavid C Somayajulu 
232935291c22SDavid C Somayajulu 				num_msix = i;
233035291c22SDavid C Somayajulu 
233135291c22SDavid C Somayajulu 				for (i = 0; i < num_msix; ) {
233235291c22SDavid C Somayajulu 					qla_config_intr_cntxt(ha, i,
233335291c22SDavid C Somayajulu 						Q8_MAX_INTR_VECTORS, 0);
233435291c22SDavid C Somayajulu 					i += Q8_MAX_INTR_VECTORS;
233535291c22SDavid C Somayajulu 				}
233635291c22SDavid C Somayajulu 			}
2337f10a77bbSDavid C Somayajulu 			return (-1);
233835291c22SDavid C Somayajulu 		}
233935291c22SDavid C Somayajulu 
234035291c22SDavid C Somayajulu 		i = i + num_msix;
234135291c22SDavid C Somayajulu 	}
234235291c22SDavid C Somayajulu 
234335291c22SDavid C Somayajulu         ha->hw.flags.init_intr_cnxt = 1;
2344f10a77bbSDavid C Somayajulu 
2345f10a77bbSDavid C Somayajulu 	/*
2346f10a77bbSDavid C Somayajulu 	 * Create Receive Context
2347f10a77bbSDavid C Somayajulu 	 */
2348f10a77bbSDavid C Somayajulu 	if (qla_init_rcv_cntxt(ha)) {
2349f10a77bbSDavid C Somayajulu 		return (-1);
2350f10a77bbSDavid C Somayajulu 	}
2351f10a77bbSDavid C Somayajulu 
2352f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_rds_rings; i++) {
2353f10a77bbSDavid C Somayajulu 		rdesc = &ha->hw.rds[i];
2354f10a77bbSDavid C Somayajulu 		rdesc->rx_next = NUM_RX_DESCRIPTORS - 2;
2355f10a77bbSDavid C Somayajulu 		rdesc->rx_in = 0;
2356f10a77bbSDavid C Somayajulu 		/* Update the RDS Producer Indices */
2357f10a77bbSDavid C Somayajulu 		QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\
2358f10a77bbSDavid C Somayajulu 			rdesc->rx_next);
2359f10a77bbSDavid C Somayajulu 	}
2360f10a77bbSDavid C Somayajulu 
2361f10a77bbSDavid C Somayajulu 
2362f10a77bbSDavid C Somayajulu 	/*
2363f10a77bbSDavid C Somayajulu 	 * Create Transmit Context
2364f10a77bbSDavid C Somayajulu 	 */
2365f10a77bbSDavid C Somayajulu 	if (qla_init_xmt_cntxt(ha)) {
2366f10a77bbSDavid C Somayajulu 		qla_del_rcv_cntxt(ha);
2367f10a77bbSDavid C Somayajulu 		return (-1);
2368f10a77bbSDavid C Somayajulu 	}
2369f10a77bbSDavid C Somayajulu 	ha->hw.max_tx_segs = 0;
2370f10a77bbSDavid C Somayajulu 
2371f10a77bbSDavid C Somayajulu 	if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1))
2372f10a77bbSDavid C Somayajulu 		return(-1);
2373f10a77bbSDavid C Somayajulu 
2374f10a77bbSDavid C Somayajulu 	ha->hw.flags.unicast_mac = 1;
2375f10a77bbSDavid C Somayajulu 
2376f10a77bbSDavid C Somayajulu 	bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2377f10a77bbSDavid C Somayajulu 	bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2378f10a77bbSDavid C Somayajulu 
2379f10a77bbSDavid C Somayajulu 	if (qla_config_mac_addr(ha, bcast_mac, 1))
2380f10a77bbSDavid C Somayajulu 		return (-1);
2381f10a77bbSDavid C Somayajulu 
2382f10a77bbSDavid C Somayajulu 	ha->hw.flags.bcast_mac = 1;
2383f10a77bbSDavid C Somayajulu 
2384f10a77bbSDavid C Somayajulu 	/*
2385f10a77bbSDavid C Somayajulu 	 * program any cached multicast addresses
2386f10a77bbSDavid C Somayajulu 	 */
2387f10a77bbSDavid C Somayajulu 	if (qla_hw_add_all_mcast(ha))
2388f10a77bbSDavid C Somayajulu 		return (-1);
2389f10a77bbSDavid C Somayajulu 
2390f10a77bbSDavid C Somayajulu 	if (qla_config_rss(ha, ha->hw.rcv_cntxt_id))
2391f10a77bbSDavid C Somayajulu 		return (-1);
2392f10a77bbSDavid C Somayajulu 
2393f10a77bbSDavid C Somayajulu 	if (qla_config_rss_ind_table(ha))
2394f10a77bbSDavid C Somayajulu 		return (-1);
2395f10a77bbSDavid C Somayajulu 
239635291c22SDavid C Somayajulu 	if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1))
2397f10a77bbSDavid C Somayajulu 		return (-1);
2398f10a77bbSDavid C Somayajulu 
2399f10a77bbSDavid C Somayajulu 	if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
2400f10a77bbSDavid C Somayajulu 		return (-1);
2401f10a77bbSDavid C Somayajulu 
2402f10a77bbSDavid C Somayajulu 	if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
2403f10a77bbSDavid C Somayajulu 		return (-1);
2404f10a77bbSDavid C Somayajulu 
240535291c22SDavid C Somayajulu         if (qla_init_nic_func(ha))
240635291c22SDavid C Somayajulu                 return (-1);
240735291c22SDavid C Somayajulu 
240835291c22SDavid C Somayajulu         if (qla_query_fw_dcbx_caps(ha))
240935291c22SDavid C Somayajulu                 return (-1);
241035291c22SDavid C Somayajulu 
2411f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; i++)
2412f10a77bbSDavid C Somayajulu 		QL_ENABLE_INTERRUPTS(ha, i);
2413f10a77bbSDavid C Somayajulu 
2414f10a77bbSDavid C Somayajulu 	return (0);
2415f10a77bbSDavid C Somayajulu }
2416f10a77bbSDavid C Somayajulu 
2417f10a77bbSDavid C Somayajulu static int
241835291c22SDavid C Somayajulu qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx)
2419f10a77bbSDavid C Somayajulu {
2420f10a77bbSDavid C Somayajulu         device_t                dev = ha->pci_dev;
2421f10a77bbSDavid C Somayajulu         q80_rq_map_sds_to_rds_t *map_rings;
242235291c22SDavid C Somayajulu 	q80_rsp_map_sds_to_rds_t *map_rings_rsp;
2423f10a77bbSDavid C Somayajulu         uint32_t                i, err;
2424f10a77bbSDavid C Somayajulu         qla_hw_t                *hw = &ha->hw;
2425f10a77bbSDavid C Somayajulu 
2426f10a77bbSDavid C Somayajulu         map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox;
2427f10a77bbSDavid C Somayajulu         bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t));
2428f10a77bbSDavid C Somayajulu 
2429f10a77bbSDavid C Somayajulu         map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS;
2430f10a77bbSDavid C Somayajulu         map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2);
2431f10a77bbSDavid C Somayajulu         map_rings->count_version |= Q8_MBX_CMD_VERSION;
2432f10a77bbSDavid C Somayajulu 
2433f10a77bbSDavid C Somayajulu         map_rings->cntxt_id = hw->rcv_cntxt_id;
243435291c22SDavid C Somayajulu         map_rings->num_rings = num_idx;
2435f10a77bbSDavid C Somayajulu 
243635291c22SDavid C Somayajulu 	for (i = 0; i < num_idx; i++) {
243735291c22SDavid C Somayajulu 		map_rings->sds_rds[i].sds_ring = i + start_idx;
243835291c22SDavid C Somayajulu 		map_rings->sds_rds[i].rds_ring = i + start_idx;
2439f10a77bbSDavid C Somayajulu 	}
2440f10a77bbSDavid C Somayajulu 
2441f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)map_rings,
2442f10a77bbSDavid C Somayajulu                 (sizeof (q80_rq_map_sds_to_rds_t) >> 2),
2443f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2444f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2445f10a77bbSDavid C Somayajulu                 return (-1);
2446f10a77bbSDavid C Somayajulu         }
2447f10a77bbSDavid C Somayajulu 
244835291c22SDavid C Somayajulu         map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox;
2449f10a77bbSDavid C Somayajulu 
2450f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status);
2451f10a77bbSDavid C Somayajulu 
2452f10a77bbSDavid C Somayajulu         if (err) {
2453f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2454f10a77bbSDavid C Somayajulu                 return (-1);
2455f10a77bbSDavid C Somayajulu         }
2456f10a77bbSDavid C Somayajulu 
2457f10a77bbSDavid C Somayajulu         return (0);
2458f10a77bbSDavid C Somayajulu }
2459f10a77bbSDavid C Somayajulu 
2460f10a77bbSDavid C Somayajulu /*
2461f10a77bbSDavid C Somayajulu  * Name: qla_init_rcv_cntxt
2462f10a77bbSDavid C Somayajulu  * Function: Creates the Receive Context.
2463f10a77bbSDavid C Somayajulu  */
2464f10a77bbSDavid C Somayajulu static int
2465f10a77bbSDavid C Somayajulu qla_init_rcv_cntxt(qla_host_t *ha)
2466f10a77bbSDavid C Somayajulu {
2467f10a77bbSDavid C Somayajulu 	q80_rq_rcv_cntxt_t	*rcntxt;
2468f10a77bbSDavid C Somayajulu 	q80_rsp_rcv_cntxt_t	*rcntxt_rsp;
2469f10a77bbSDavid C Somayajulu 	q80_stat_desc_t		*sdesc;
2470f10a77bbSDavid C Somayajulu 	int			i, j;
2471f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2472f10a77bbSDavid C Somayajulu 	device_t		dev;
2473f10a77bbSDavid C Somayajulu 	uint32_t		err;
2474f10a77bbSDavid C Somayajulu 	uint32_t		rcntxt_sds_rings;
2475f10a77bbSDavid C Somayajulu 	uint32_t		rcntxt_rds_rings;
247635291c22SDavid C Somayajulu 	uint32_t		max_idx;
2477f10a77bbSDavid C Somayajulu 
2478f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2479f10a77bbSDavid C Somayajulu 
2480f10a77bbSDavid C Somayajulu 	/*
2481f10a77bbSDavid C Somayajulu 	 * Create Receive Context
2482f10a77bbSDavid C Somayajulu 	 */
2483f10a77bbSDavid C Somayajulu 
2484f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
2485f10a77bbSDavid C Somayajulu 		sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0];
2486f10a77bbSDavid C Somayajulu 
2487f10a77bbSDavid C Somayajulu 		for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) {
2488f10a77bbSDavid C Somayajulu 			sdesc->data[0] = 1ULL;
2489f10a77bbSDavid C Somayajulu 			sdesc->data[1] = 1ULL;
2490f10a77bbSDavid C Somayajulu 		}
2491f10a77bbSDavid C Somayajulu 	}
2492f10a77bbSDavid C Somayajulu 
2493f10a77bbSDavid C Somayajulu 	rcntxt_sds_rings = hw->num_sds_rings;
2494f10a77bbSDavid C Somayajulu 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS)
2495f10a77bbSDavid C Somayajulu 		rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS;
2496f10a77bbSDavid C Somayajulu 
2497f10a77bbSDavid C Somayajulu 	rcntxt_rds_rings = hw->num_rds_rings;
2498f10a77bbSDavid C Somayajulu 
2499f10a77bbSDavid C Somayajulu 	if (hw->num_rds_rings > MAX_RDS_RING_SETS)
2500f10a77bbSDavid C Somayajulu 		rcntxt_rds_rings = MAX_RDS_RING_SETS;
2501f10a77bbSDavid C Somayajulu 
2502f10a77bbSDavid C Somayajulu 	rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox;
2503f10a77bbSDavid C Somayajulu 	bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t)));
2504f10a77bbSDavid C Somayajulu 
2505f10a77bbSDavid C Somayajulu 	rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT;
2506f10a77bbSDavid C Somayajulu 	rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2);
2507f10a77bbSDavid C Somayajulu 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2508f10a77bbSDavid C Somayajulu 
2509f10a77bbSDavid C Somayajulu 	rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW |
2510f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_LRO |
2511f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_HW_LRO |
2512f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_RSS |
2513f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_SGL_LRO;
2514f10a77bbSDavid C Somayajulu 
251535291c22SDavid C Somayajulu 	if (ha->hw.enable_9kb)
251635291c22SDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO;
251735291c22SDavid C Somayajulu 	else
251835291c22SDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO;
251935291c22SDavid C Somayajulu 
2520f10a77bbSDavid C Somayajulu 	if (ha->hw.num_rds_rings > 1) {
2521f10a77bbSDavid C Somayajulu 		rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5);
2522f10a77bbSDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS;
2523f10a77bbSDavid C Somayajulu 	} else
2524f10a77bbSDavid C Somayajulu 		rcntxt->nrds_sets_rings = 0x1 | (1 << 5);
2525f10a77bbSDavid C Somayajulu 
2526f10a77bbSDavid C Somayajulu 	rcntxt->nsds_rings = rcntxt_sds_rings;
2527f10a77bbSDavid C Somayajulu 
2528f10a77bbSDavid C Somayajulu 	rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE;
2529f10a77bbSDavid C Somayajulu 
2530f10a77bbSDavid C Somayajulu 	rcntxt->rcv_vpid = 0;
2531f10a77bbSDavid C Somayajulu 
2532f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2533f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].paddr =
2534f10a77bbSDavid C Somayajulu 			qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr);
2535f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].size =
2536f10a77bbSDavid C Somayajulu 			qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2537f10a77bbSDavid C Somayajulu 		if (ha->msix_count == 2) {
2538f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_id =
2539f10a77bbSDavid C Somayajulu 				qla_host_to_le16(hw->intr_id[0]);
2540f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_src_bit = qla_host_to_le16((i));
2541f10a77bbSDavid C Somayajulu 		} else {
2542f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_id =
2543f10a77bbSDavid C Somayajulu 				qla_host_to_le16(hw->intr_id[i]);
2544f10a77bbSDavid C Somayajulu 			rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0);
2545f10a77bbSDavid C Somayajulu 		}
2546f10a77bbSDavid C Somayajulu 	}
2547f10a77bbSDavid C Somayajulu 
2548f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2549f10a77bbSDavid C Somayajulu 		rcntxt->rds[i].paddr_std =
2550f10a77bbSDavid C Somayajulu 			qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr);
255135291c22SDavid C Somayajulu 
255235291c22SDavid C Somayajulu 		if (ha->hw.enable_9kb)
255335291c22SDavid C Somayajulu 			rcntxt->rds[i].std_bsize =
255435291c22SDavid C Somayajulu 				qla_host_to_le64(MJUM9BYTES);
255535291c22SDavid C Somayajulu 		else
2556f10a77bbSDavid C Somayajulu 			rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
255735291c22SDavid C Somayajulu 
2558f10a77bbSDavid C Somayajulu 		rcntxt->rds[i].std_nentries =
2559f10a77bbSDavid C Somayajulu 			qla_host_to_le32(NUM_RX_DESCRIPTORS);
2560f10a77bbSDavid C Somayajulu 	}
2561f10a77bbSDavid C Somayajulu 
2562f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2563f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_rcv_cntxt_t) >> 2),
2564f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) {
2565f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2566f10a77bbSDavid C Somayajulu                 return (-1);
2567f10a77bbSDavid C Somayajulu         }
2568f10a77bbSDavid C Somayajulu 
2569f10a77bbSDavid C Somayajulu         rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox;
2570f10a77bbSDavid C Somayajulu 
2571f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2572f10a77bbSDavid C Somayajulu 
2573f10a77bbSDavid C Somayajulu         if (err) {
2574f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2575f10a77bbSDavid C Somayajulu                 return (-1);
2576f10a77bbSDavid C Somayajulu         }
2577f10a77bbSDavid C Somayajulu 
2578f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2579f10a77bbSDavid C Somayajulu 		hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i];
2580f10a77bbSDavid C Somayajulu 	}
2581f10a77bbSDavid C Somayajulu 
2582f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2583f10a77bbSDavid C Somayajulu 		hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std;
2584f10a77bbSDavid C Somayajulu 	}
2585f10a77bbSDavid C Somayajulu 
2586f10a77bbSDavid C Somayajulu 	hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id;
2587f10a77bbSDavid C Somayajulu 
2588f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_rx_cnxt = 1;
2589f10a77bbSDavid C Somayajulu 
2590f10a77bbSDavid C Somayajulu 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) {
259135291c22SDavid C Somayajulu 
259235291c22SDavid C Somayajulu 		for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) {
259335291c22SDavid C Somayajulu 
259435291c22SDavid C Somayajulu 			if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings)
259535291c22SDavid C Somayajulu 				max_idx = MAX_RCNTXT_SDS_RINGS;
259635291c22SDavid C Somayajulu 			else
259735291c22SDavid C Somayajulu 				max_idx = hw->num_sds_rings - i;
259835291c22SDavid C Somayajulu 
259935291c22SDavid C Somayajulu 			err = qla_add_rcv_rings(ha, i, max_idx);
2600f10a77bbSDavid C Somayajulu 			if (err)
2601f10a77bbSDavid C Somayajulu 				return -1;
260235291c22SDavid C Somayajulu 
260335291c22SDavid C Somayajulu 			i += max_idx;
260435291c22SDavid C Somayajulu 		}
2605f10a77bbSDavid C Somayajulu 	}
2606f10a77bbSDavid C Somayajulu 
2607f10a77bbSDavid C Somayajulu 	if (hw->num_rds_rings > 1) {
260835291c22SDavid C Somayajulu 
260935291c22SDavid C Somayajulu 		for (i = 0; i < hw->num_rds_rings; ) {
261035291c22SDavid C Somayajulu 
261135291c22SDavid C Somayajulu 			if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings)
261235291c22SDavid C Somayajulu 				max_idx = MAX_SDS_TO_RDS_MAP;
261335291c22SDavid C Somayajulu 			else
261435291c22SDavid C Somayajulu 				max_idx = hw->num_rds_rings - i;
261535291c22SDavid C Somayajulu 
261635291c22SDavid C Somayajulu 			err = qla_map_sds_to_rds(ha, i, max_idx);
2617f10a77bbSDavid C Somayajulu 			if (err)
2618f10a77bbSDavid C Somayajulu 				return -1;
261935291c22SDavid C Somayajulu 
262035291c22SDavid C Somayajulu 			i += max_idx;
262135291c22SDavid C Somayajulu 		}
2622f10a77bbSDavid C Somayajulu 	}
2623f10a77bbSDavid C Somayajulu 
2624f10a77bbSDavid C Somayajulu 	return (0);
2625f10a77bbSDavid C Somayajulu }
2626f10a77bbSDavid C Somayajulu 
2627f10a77bbSDavid C Somayajulu static int
262835291c22SDavid C Somayajulu qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds)
2629f10a77bbSDavid C Somayajulu {
2630f10a77bbSDavid C Somayajulu 	device_t		dev = ha->pci_dev;
2631f10a77bbSDavid C Somayajulu 	q80_rq_add_rcv_rings_t	*add_rcv;
2632f10a77bbSDavid C Somayajulu 	q80_rsp_add_rcv_rings_t	*add_rcv_rsp;
2633f10a77bbSDavid C Somayajulu 	uint32_t		i,j, err;
2634f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2635f10a77bbSDavid C Somayajulu 
2636f10a77bbSDavid C Somayajulu 	add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox;
2637f10a77bbSDavid C Somayajulu 	bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t));
2638f10a77bbSDavid C Somayajulu 
2639f10a77bbSDavid C Somayajulu 	add_rcv->opcode = Q8_MBX_ADD_RX_RINGS;
2640f10a77bbSDavid C Somayajulu 	add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2);
2641f10a77bbSDavid C Somayajulu 	add_rcv->count_version |= Q8_MBX_CMD_VERSION;
2642f10a77bbSDavid C Somayajulu 
2643f10a77bbSDavid C Somayajulu 	add_rcv->nrds_sets_rings = nsds | (1 << 5);
2644f10a77bbSDavid C Somayajulu 	add_rcv->nsds_rings = nsds;
2645f10a77bbSDavid C Somayajulu 	add_rcv->cntxt_id = hw->rcv_cntxt_id;
2646f10a77bbSDavid C Somayajulu 
2647f10a77bbSDavid C Somayajulu         for (i = 0; i <  nsds; i++) {
2648f10a77bbSDavid C Somayajulu 
2649f10a77bbSDavid C Somayajulu 		j = i + sds_idx;
2650f10a77bbSDavid C Somayajulu 
2651f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].paddr =
2652f10a77bbSDavid C Somayajulu                         qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr);
2653f10a77bbSDavid C Somayajulu 
2654f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].size =
2655f10a77bbSDavid C Somayajulu                         qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2656f10a77bbSDavid C Somayajulu 
2657f10a77bbSDavid C Somayajulu                 if (ha->msix_count == 2) {
2658f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_id =
2659f10a77bbSDavid C Somayajulu                                 qla_host_to_le16(hw->intr_id[0]);
2660f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(j);
2661f10a77bbSDavid C Somayajulu                 } else {
2662f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_id =
2663f10a77bbSDavid C Somayajulu                                 qla_host_to_le16(hw->intr_id[j]);
2664f10a77bbSDavid C Somayajulu                         add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0);
2665f10a77bbSDavid C Somayajulu                 }
2666f10a77bbSDavid C Somayajulu 
2667f10a77bbSDavid C Somayajulu         }
266835291c22SDavid C Somayajulu         for (i = 0; (i <  nsds); i++) {
2669f10a77bbSDavid C Somayajulu                 j = i + sds_idx;
267035291c22SDavid C Somayajulu 
2671f10a77bbSDavid C Somayajulu                 add_rcv->rds[i].paddr_std =
2672f10a77bbSDavid C Somayajulu                         qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr);
267335291c22SDavid C Somayajulu 
267435291c22SDavid C Somayajulu 		if (ha->hw.enable_9kb)
267535291c22SDavid C Somayajulu 			add_rcv->rds[i].std_bsize =
267635291c22SDavid C Somayajulu 				qla_host_to_le64(MJUM9BYTES);
267735291c22SDavid C Somayajulu 		else
2678f10a77bbSDavid C Somayajulu                 	add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
267935291c22SDavid C Somayajulu 
2680f10a77bbSDavid C Somayajulu                 add_rcv->rds[i].std_nentries =
2681f10a77bbSDavid C Somayajulu                         qla_host_to_le32(NUM_RX_DESCRIPTORS);
2682f10a77bbSDavid C Somayajulu         }
2683f10a77bbSDavid C Somayajulu 
2684f10a77bbSDavid C Somayajulu 
2685f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)add_rcv,
2686f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_add_rcv_rings_t) >> 2),
2687f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2688f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2689f10a77bbSDavid C Somayajulu                 return (-1);
2690f10a77bbSDavid C Somayajulu         }
2691f10a77bbSDavid C Somayajulu 
2692f10a77bbSDavid C Somayajulu         add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
2693f10a77bbSDavid C Somayajulu 
2694f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status);
2695f10a77bbSDavid C Somayajulu 
2696f10a77bbSDavid C Somayajulu         if (err) {
2697f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2698f10a77bbSDavid C Somayajulu                 return (-1);
2699f10a77bbSDavid C Somayajulu         }
2700f10a77bbSDavid C Somayajulu 
270135291c22SDavid C Somayajulu 	for (i = 0; i < nsds; i++) {
270235291c22SDavid C Somayajulu 		hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i];
2703f10a77bbSDavid C Somayajulu 	}
270435291c22SDavid C Somayajulu 
270535291c22SDavid C Somayajulu 	for (i = 0; i < nsds; i++) {
270635291c22SDavid C Somayajulu 		hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std;
2707f10a77bbSDavid C Somayajulu 	}
270835291c22SDavid C Somayajulu 
2709f10a77bbSDavid C Somayajulu 	return (0);
2710f10a77bbSDavid C Somayajulu }
2711f10a77bbSDavid C Somayajulu 
2712f10a77bbSDavid C Somayajulu /*
2713f10a77bbSDavid C Somayajulu  * Name: qla_del_rcv_cntxt
2714f10a77bbSDavid C Somayajulu  * Function: Destroys the Receive Context.
2715f10a77bbSDavid C Somayajulu  */
2716f10a77bbSDavid C Somayajulu static void
2717f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(qla_host_t *ha)
2718f10a77bbSDavid C Somayajulu {
2719f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
2720f10a77bbSDavid C Somayajulu 	q80_rcv_cntxt_destroy_t		*rcntxt;
2721f10a77bbSDavid C Somayajulu 	q80_rcv_cntxt_destroy_rsp_t	*rcntxt_rsp;
2722f10a77bbSDavid C Somayajulu 	uint32_t			err;
2723f10a77bbSDavid C Somayajulu 	uint8_t				bcast_mac[6];
2724f10a77bbSDavid C Somayajulu 
2725f10a77bbSDavid C Somayajulu 	if (!ha->hw.flags.init_rx_cnxt)
2726f10a77bbSDavid C Somayajulu 		return;
2727f10a77bbSDavid C Somayajulu 
2728f10a77bbSDavid C Somayajulu 	if (qla_hw_del_all_mcast(ha))
2729f10a77bbSDavid C Somayajulu 		return;
2730f10a77bbSDavid C Somayajulu 
2731f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.bcast_mac) {
2732f10a77bbSDavid C Somayajulu 
2733f10a77bbSDavid C Somayajulu 		bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2734f10a77bbSDavid C Somayajulu 		bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2735f10a77bbSDavid C Somayajulu 
2736f10a77bbSDavid C Somayajulu 		if (qla_config_mac_addr(ha, bcast_mac, 0))
2737f10a77bbSDavid C Somayajulu 			return;
2738f10a77bbSDavid C Somayajulu 		ha->hw.flags.bcast_mac = 0;
2739f10a77bbSDavid C Somayajulu 
2740f10a77bbSDavid C Somayajulu 	}
2741f10a77bbSDavid C Somayajulu 
2742f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.unicast_mac) {
2743f10a77bbSDavid C Somayajulu 		if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0))
2744f10a77bbSDavid C Somayajulu 			return;
2745f10a77bbSDavid C Somayajulu 		ha->hw.flags.unicast_mac = 0;
2746f10a77bbSDavid C Somayajulu 	}
2747f10a77bbSDavid C Somayajulu 
2748f10a77bbSDavid C Somayajulu 	rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox;
2749f10a77bbSDavid C Somayajulu 	bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t)));
2750f10a77bbSDavid C Somayajulu 
2751f10a77bbSDavid C Somayajulu 	rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT;
2752f10a77bbSDavid C Somayajulu 	rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2);
2753f10a77bbSDavid C Somayajulu 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2754f10a77bbSDavid C Somayajulu 
2755f10a77bbSDavid C Somayajulu 	rcntxt->cntxt_id = ha->hw.rcv_cntxt_id;
2756f10a77bbSDavid C Somayajulu 
2757f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2758f10a77bbSDavid C Somayajulu 		(sizeof (q80_rcv_cntxt_destroy_t) >> 2),
2759f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) {
2760f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2761f10a77bbSDavid C Somayajulu                 return;
2762f10a77bbSDavid C Somayajulu         }
2763f10a77bbSDavid C Somayajulu         rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox;
2764f10a77bbSDavid C Somayajulu 
2765f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2766f10a77bbSDavid C Somayajulu 
2767f10a77bbSDavid C Somayajulu         if (err) {
2768f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2769f10a77bbSDavid C Somayajulu         }
2770f10a77bbSDavid C Somayajulu 
2771f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_rx_cnxt = 0;
2772f10a77bbSDavid C Somayajulu 	return;
2773f10a77bbSDavid C Somayajulu }
2774f10a77bbSDavid C Somayajulu 
2775f10a77bbSDavid C Somayajulu /*
2776f10a77bbSDavid C Somayajulu  * Name: qla_init_xmt_cntxt
2777f10a77bbSDavid C Somayajulu  * Function: Creates the Transmit Context.
2778f10a77bbSDavid C Somayajulu  */
2779f10a77bbSDavid C Somayajulu static int
2780f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2781f10a77bbSDavid C Somayajulu {
2782f10a77bbSDavid C Somayajulu 	device_t		dev;
2783f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2784f10a77bbSDavid C Somayajulu 	q80_rq_tx_cntxt_t	*tcntxt;
2785f10a77bbSDavid C Somayajulu 	q80_rsp_tx_cntxt_t	*tcntxt_rsp;
2786f10a77bbSDavid C Somayajulu 	uint32_t		err;
2787f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t       *hw_tx_cntxt;
2788f10a77bbSDavid C Somayajulu 
2789f10a77bbSDavid C Somayajulu 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
2790f10a77bbSDavid C Somayajulu 
2791f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2792f10a77bbSDavid C Somayajulu 
2793f10a77bbSDavid C Somayajulu 	/*
2794f10a77bbSDavid C Somayajulu 	 * Create Transmit Context
2795f10a77bbSDavid C Somayajulu 	 */
2796f10a77bbSDavid C Somayajulu 	tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox;
2797f10a77bbSDavid C Somayajulu 	bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t)));
2798f10a77bbSDavid C Somayajulu 
2799f10a77bbSDavid C Somayajulu 	tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT;
2800f10a77bbSDavid C Somayajulu 	tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2);
2801f10a77bbSDavid C Somayajulu 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2802f10a77bbSDavid C Somayajulu 
280335291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV
280435291c22SDavid C Somayajulu 
280535291c22SDavid C Somayajulu 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO |
280635291c22SDavid C Somayajulu 				Q8_TX_CNTXT_CAP0_TC;
280735291c22SDavid C Somayajulu 
280835291c22SDavid C Somayajulu 	if (txr_idx >= (ha->hw.num_tx_rings >> 1)) {
280935291c22SDavid C Somayajulu 		tcntxt->traffic_class = 1;
281035291c22SDavid C Somayajulu 	}
281135291c22SDavid C Somayajulu 
281235291c22SDavid C Somayajulu #else
281335291c22SDavid C Somayajulu 
2814f10a77bbSDavid C Somayajulu 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO;
2815f10a77bbSDavid C Somayajulu 
281635291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
281735291c22SDavid C Somayajulu 
2818f10a77bbSDavid C Somayajulu 	tcntxt->ntx_rings = 1;
2819f10a77bbSDavid C Somayajulu 
2820f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].paddr =
2821f10a77bbSDavid C Somayajulu 		qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr);
2822f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].tx_consumer =
2823f10a77bbSDavid C Somayajulu 		qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr);
2824f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS);
2825f10a77bbSDavid C Somayajulu 
2826f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[0]);
2827f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0);
2828f10a77bbSDavid C Somayajulu 
2829f10a77bbSDavid C Somayajulu 
2830f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS;
2831f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0;
2832f10a77bbSDavid C Somayajulu 
2833f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2834f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_tx_cntxt_t) >> 2),
2835f10a77bbSDavid C Somayajulu                 ha->hw.mbox,
2836f10a77bbSDavid C Somayajulu 		(sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) {
2837f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2838f10a77bbSDavid C Somayajulu                 return (-1);
2839f10a77bbSDavid C Somayajulu         }
2840f10a77bbSDavid C Somayajulu         tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox;
2841f10a77bbSDavid C Somayajulu 
2842f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2843f10a77bbSDavid C Somayajulu 
2844f10a77bbSDavid C Somayajulu         if (err) {
2845f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2846f10a77bbSDavid C Somayajulu 		return -1;
2847f10a77bbSDavid C Somayajulu         }
2848f10a77bbSDavid C Somayajulu 
2849f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index;
2850f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id;
2851f10a77bbSDavid C Somayajulu 
285235291c22SDavid C Somayajulu 	if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0))
285335291c22SDavid C Somayajulu 		return (-1);
285435291c22SDavid C Somayajulu 
2855f10a77bbSDavid C Somayajulu 	return (0);
2856f10a77bbSDavid C Somayajulu }
2857f10a77bbSDavid C Somayajulu 
2858f10a77bbSDavid C Somayajulu 
2859f10a77bbSDavid C Somayajulu /*
2860f10a77bbSDavid C Somayajulu  * Name: qla_del_xmt_cntxt
2861f10a77bbSDavid C Somayajulu  * Function: Destroys the Transmit Context.
2862f10a77bbSDavid C Somayajulu  */
2863f10a77bbSDavid C Somayajulu static int
2864f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2865f10a77bbSDavid C Somayajulu {
2866f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
2867f10a77bbSDavid C Somayajulu 	q80_tx_cntxt_destroy_t		*tcntxt;
2868f10a77bbSDavid C Somayajulu 	q80_tx_cntxt_destroy_rsp_t	*tcntxt_rsp;
2869f10a77bbSDavid C Somayajulu 	uint32_t			err;
2870f10a77bbSDavid C Somayajulu 
2871f10a77bbSDavid C Somayajulu 	tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox;
2872f10a77bbSDavid C Somayajulu 	bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t)));
2873f10a77bbSDavid C Somayajulu 
2874f10a77bbSDavid C Somayajulu 	tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT;
2875f10a77bbSDavid C Somayajulu 	tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2);
2876f10a77bbSDavid C Somayajulu 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2877f10a77bbSDavid C Somayajulu 
2878f10a77bbSDavid C Somayajulu 	tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id;
2879f10a77bbSDavid C Somayajulu 
2880f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2881f10a77bbSDavid C Somayajulu 		(sizeof (q80_tx_cntxt_destroy_t) >> 2),
2882f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) {
2883f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2884f10a77bbSDavid C Somayajulu                 return (-1);
2885f10a77bbSDavid C Somayajulu         }
2886f10a77bbSDavid C Somayajulu         tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox;
2887f10a77bbSDavid C Somayajulu 
2888f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2889f10a77bbSDavid C Somayajulu 
2890f10a77bbSDavid C Somayajulu         if (err) {
2891f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2892f10a77bbSDavid C Somayajulu 		return (-1);
2893f10a77bbSDavid C Somayajulu         }
2894f10a77bbSDavid C Somayajulu 
2895f10a77bbSDavid C Somayajulu 	return (0);
2896f10a77bbSDavid C Somayajulu }
2897f10a77bbSDavid C Somayajulu static void
2898f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt(qla_host_t *ha)
2899f10a77bbSDavid C Somayajulu {
2900f10a77bbSDavid C Somayajulu 	uint32_t i;
2901f10a77bbSDavid C Somayajulu 
2902f10a77bbSDavid C Somayajulu 	if (!ha->hw.flags.init_tx_cnxt)
2903f10a77bbSDavid C Somayajulu 		return;
2904f10a77bbSDavid C Somayajulu 
2905f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2906f10a77bbSDavid C Somayajulu 		if (qla_del_xmt_cntxt_i(ha, i))
2907f10a77bbSDavid C Somayajulu 			break;
2908f10a77bbSDavid C Somayajulu 	}
2909f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_tx_cnxt = 0;
2910f10a77bbSDavid C Somayajulu }
2911f10a77bbSDavid C Somayajulu 
2912f10a77bbSDavid C Somayajulu static int
2913f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt(qla_host_t *ha)
2914f10a77bbSDavid C Somayajulu {
2915f10a77bbSDavid C Somayajulu 	uint32_t i, j;
2916f10a77bbSDavid C Somayajulu 
2917f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
2918f10a77bbSDavid C Somayajulu 		if (qla_init_xmt_cntxt_i(ha, i) != 0) {
2919f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
2920f10a77bbSDavid C Somayajulu 				qla_del_xmt_cntxt_i(ha, j);
2921f10a77bbSDavid C Somayajulu 			return (-1);
2922f10a77bbSDavid C Somayajulu 		}
2923f10a77bbSDavid C Somayajulu 	}
2924f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_tx_cnxt = 1;
2925f10a77bbSDavid C Somayajulu 	return (0);
2926f10a77bbSDavid C Somayajulu }
2927f10a77bbSDavid C Somayajulu 
2928f10a77bbSDavid C Somayajulu static int
2929f10a77bbSDavid C Somayajulu qla_hw_add_all_mcast(qla_host_t *ha)
2930f10a77bbSDavid C Somayajulu {
2931f10a77bbSDavid C Somayajulu 	int i, nmcast;
2932f10a77bbSDavid C Somayajulu 
2933f10a77bbSDavid C Somayajulu 	nmcast = ha->hw.nmcast;
2934f10a77bbSDavid C Somayajulu 
2935f10a77bbSDavid C Somayajulu 	for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
2936f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] != 0) ||
2937f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] != 0) ||
2938f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] != 0) ||
2939f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] != 0) ||
2940f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] != 0) ||
2941f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] != 0)) {
2942f10a77bbSDavid C Somayajulu 
2943f10a77bbSDavid C Somayajulu 			if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 1)) {
2944f10a77bbSDavid C Somayajulu                 		device_printf(ha->pci_dev, "%s: failed\n",
2945f10a77bbSDavid C Somayajulu 					__func__);
2946f10a77bbSDavid C Somayajulu 				return (-1);
2947f10a77bbSDavid C Somayajulu 			}
2948f10a77bbSDavid C Somayajulu 
2949f10a77bbSDavid C Somayajulu 			nmcast--;
2950f10a77bbSDavid C Somayajulu 		}
2951f10a77bbSDavid C Somayajulu 	}
2952f10a77bbSDavid C Somayajulu 	return 0;
2953f10a77bbSDavid C Somayajulu }
2954f10a77bbSDavid C Somayajulu 
2955f10a77bbSDavid C Somayajulu static int
2956f10a77bbSDavid C Somayajulu qla_hw_del_all_mcast(qla_host_t *ha)
2957f10a77bbSDavid C Somayajulu {
2958f10a77bbSDavid C Somayajulu 	int i, nmcast;
2959f10a77bbSDavid C Somayajulu 
2960f10a77bbSDavid C Somayajulu 	nmcast = ha->hw.nmcast;
2961f10a77bbSDavid C Somayajulu 
2962f10a77bbSDavid C Somayajulu 	for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
2963f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] != 0) ||
2964f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] != 0) ||
2965f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] != 0) ||
2966f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] != 0) ||
2967f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] != 0) ||
2968f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] != 0)) {
2969f10a77bbSDavid C Somayajulu 
2970f10a77bbSDavid C Somayajulu 			if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 0))
2971f10a77bbSDavid C Somayajulu 				return (-1);
2972f10a77bbSDavid C Somayajulu 
2973f10a77bbSDavid C Somayajulu 			nmcast--;
2974f10a77bbSDavid C Somayajulu 		}
2975f10a77bbSDavid C Somayajulu 	}
2976f10a77bbSDavid C Somayajulu 	return 0;
2977f10a77bbSDavid C Somayajulu }
2978f10a77bbSDavid C Somayajulu 
2979f10a77bbSDavid C Somayajulu static int
2980f10a77bbSDavid C Somayajulu qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta)
2981f10a77bbSDavid C Somayajulu {
2982f10a77bbSDavid C Somayajulu 	int i;
2983f10a77bbSDavid C Somayajulu 
2984f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
2985f10a77bbSDavid C Somayajulu 
2986f10a77bbSDavid C Somayajulu 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0)
2987f10a77bbSDavid C Somayajulu 			return 0; /* its been already added */
2988f10a77bbSDavid C Somayajulu 	}
2989f10a77bbSDavid C Somayajulu 
2990f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
2991f10a77bbSDavid C Somayajulu 
2992f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] == 0) &&
2993f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] == 0) &&
2994f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] == 0) &&
2995f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] == 0) &&
2996f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] == 0) &&
2997f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] == 0)) {
2998f10a77bbSDavid C Somayajulu 
2999f10a77bbSDavid C Somayajulu 			if (qla_config_mac_addr(ha, mta, 1))
3000f10a77bbSDavid C Somayajulu 				return (-1);
3001f10a77bbSDavid C Somayajulu 
3002f10a77bbSDavid C Somayajulu 			bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN);
3003f10a77bbSDavid C Somayajulu 			ha->hw.nmcast++;
3004f10a77bbSDavid C Somayajulu 
3005f10a77bbSDavid C Somayajulu 			return 0;
3006f10a77bbSDavid C Somayajulu 		}
3007f10a77bbSDavid C Somayajulu 	}
3008f10a77bbSDavid C Somayajulu 	return 0;
3009f10a77bbSDavid C Somayajulu }
3010f10a77bbSDavid C Somayajulu 
3011f10a77bbSDavid C Somayajulu static int
3012f10a77bbSDavid C Somayajulu qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta)
3013f10a77bbSDavid C Somayajulu {
3014f10a77bbSDavid C Somayajulu 	int i;
3015f10a77bbSDavid C Somayajulu 
3016f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3017f10a77bbSDavid C Somayajulu 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) {
3018f10a77bbSDavid C Somayajulu 
3019f10a77bbSDavid C Somayajulu 			if (qla_config_mac_addr(ha, mta, 0))
3020f10a77bbSDavid C Somayajulu 				return (-1);
3021f10a77bbSDavid C Somayajulu 
3022f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[0] = 0;
3023f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[1] = 0;
3024f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[2] = 0;
3025f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[3] = 0;
3026f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[4] = 0;
3027f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[5] = 0;
3028f10a77bbSDavid C Somayajulu 
3029f10a77bbSDavid C Somayajulu 			ha->hw.nmcast--;
3030f10a77bbSDavid C Somayajulu 
3031f10a77bbSDavid C Somayajulu 			return 0;
3032f10a77bbSDavid C Somayajulu 		}
3033f10a77bbSDavid C Somayajulu 	}
3034f10a77bbSDavid C Somayajulu 	return 0;
3035f10a77bbSDavid C Somayajulu }
3036f10a77bbSDavid C Somayajulu 
3037f10a77bbSDavid C Somayajulu /*
3038f10a77bbSDavid C Somayajulu  * Name: ql_hw_set_multi
3039f10a77bbSDavid C Somayajulu  * Function: Sets the Multicast Addresses provided the host O.S into the
3040f10a77bbSDavid C Somayajulu  *	hardware (for the given interface)
3041f10a77bbSDavid C Somayajulu  */
3042f10a77bbSDavid C Somayajulu int
3043f10a77bbSDavid C Somayajulu ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast, uint32_t mcnt,
3044f10a77bbSDavid C Somayajulu 	uint32_t add_mac)
3045f10a77bbSDavid C Somayajulu {
3046f10a77bbSDavid C Somayajulu 	int i;
3047f10a77bbSDavid C Somayajulu 	uint8_t *mta = mcast;
3048f10a77bbSDavid C Somayajulu 	int ret = 0;
3049f10a77bbSDavid C Somayajulu 
3050f10a77bbSDavid C Somayajulu 	for (i = 0; i < mcnt; i++) {
3051f10a77bbSDavid C Somayajulu 		if (add_mac) {
3052f10a77bbSDavid C Somayajulu 			ret = qla_hw_add_mcast(ha, mta);
3053f10a77bbSDavid C Somayajulu 			if (ret)
3054f10a77bbSDavid C Somayajulu 				break;
3055f10a77bbSDavid C Somayajulu 		} else {
3056f10a77bbSDavid C Somayajulu 			ret = qla_hw_del_mcast(ha, mta);
3057f10a77bbSDavid C Somayajulu 			if (ret)
3058f10a77bbSDavid C Somayajulu 				break;
3059f10a77bbSDavid C Somayajulu 		}
3060f10a77bbSDavid C Somayajulu 
3061f10a77bbSDavid C Somayajulu 		mta += Q8_MAC_ADDR_LEN;
3062f10a77bbSDavid C Somayajulu 	}
3063f10a77bbSDavid C Somayajulu 	return (ret);
3064f10a77bbSDavid C Somayajulu }
3065f10a77bbSDavid C Somayajulu 
3066f10a77bbSDavid C Somayajulu /*
3067f10a77bbSDavid C Somayajulu  * Name: qla_hw_tx_done_locked
3068f10a77bbSDavid C Somayajulu  * Function: Handle Transmit Completions
3069f10a77bbSDavid C Somayajulu  */
3070f10a77bbSDavid C Somayajulu static void
3071f10a77bbSDavid C Somayajulu qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx)
3072f10a77bbSDavid C Somayajulu {
3073f10a77bbSDavid C Somayajulu 	qla_tx_buf_t *txb;
3074f10a77bbSDavid C Somayajulu         qla_hw_t *hw = &ha->hw;
3075f10a77bbSDavid C Somayajulu 	uint32_t comp_idx, comp_count = 0;
3076f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t *hw_tx_cntxt;
3077f10a77bbSDavid C Somayajulu 
3078f10a77bbSDavid C Somayajulu 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3079f10a77bbSDavid C Somayajulu 
3080f10a77bbSDavid C Somayajulu 	/* retrieve index of last entry in tx ring completed */
3081f10a77bbSDavid C Somayajulu 	comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons));
3082f10a77bbSDavid C Somayajulu 
3083f10a77bbSDavid C Somayajulu 	while (comp_idx != hw_tx_cntxt->txr_comp) {
3084f10a77bbSDavid C Somayajulu 
3085f10a77bbSDavid C Somayajulu 		txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp];
3086f10a77bbSDavid C Somayajulu 
3087f10a77bbSDavid C Somayajulu 		hw_tx_cntxt->txr_comp++;
3088f10a77bbSDavid C Somayajulu 		if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS)
3089f10a77bbSDavid C Somayajulu 			hw_tx_cntxt->txr_comp = 0;
3090f10a77bbSDavid C Somayajulu 
3091f10a77bbSDavid C Somayajulu 		comp_count++;
3092f10a77bbSDavid C Somayajulu 
3093f10a77bbSDavid C Somayajulu 		if (txb->m_head) {
3094c8dfaf38SGleb Smirnoff 			if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1);
3095f10a77bbSDavid C Somayajulu 
3096f10a77bbSDavid C Somayajulu 			bus_dmamap_sync(ha->tx_tag, txb->map,
3097f10a77bbSDavid C Somayajulu 				BUS_DMASYNC_POSTWRITE);
3098f10a77bbSDavid C Somayajulu 			bus_dmamap_unload(ha->tx_tag, txb->map);
3099f10a77bbSDavid C Somayajulu 			m_freem(txb->m_head);
3100f10a77bbSDavid C Somayajulu 
3101f10a77bbSDavid C Somayajulu 			txb->m_head = NULL;
3102f10a77bbSDavid C Somayajulu 		}
3103f10a77bbSDavid C Somayajulu 	}
3104f10a77bbSDavid C Somayajulu 
3105f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_free += comp_count;
3106f10a77bbSDavid C Somayajulu 	return;
3107f10a77bbSDavid C Somayajulu }
3108f10a77bbSDavid C Somayajulu 
3109f10a77bbSDavid C Somayajulu /*
3110f10a77bbSDavid C Somayajulu  * Name: ql_hw_tx_done
3111f10a77bbSDavid C Somayajulu  * Function: Handle Transmit Completions
3112f10a77bbSDavid C Somayajulu  */
3113f10a77bbSDavid C Somayajulu void
3114f10a77bbSDavid C Somayajulu ql_hw_tx_done(qla_host_t *ha)
3115f10a77bbSDavid C Somayajulu {
3116f10a77bbSDavid C Somayajulu 	int i;
3117f10a77bbSDavid C Somayajulu 	uint32_t flag = 0;
3118f10a77bbSDavid C Somayajulu 
3119f10a77bbSDavid C Somayajulu 	if (!mtx_trylock(&ha->tx_lock)) {
3120f10a77bbSDavid C Somayajulu        		QL_DPRINT8(ha, (ha->pci_dev,
3121f10a77bbSDavid C Somayajulu 			"%s: !mtx_trylock(&ha->tx_lock)\n", __func__));
3122f10a77bbSDavid C Somayajulu 		return;
3123f10a77bbSDavid C Somayajulu 	}
3124f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
3125f10a77bbSDavid C Somayajulu 		qla_hw_tx_done_locked(ha, i);
3126f10a77bbSDavid C Somayajulu 		if (ha->hw.tx_cntxt[i].txr_free <= (NUM_TX_DESCRIPTORS >> 1))
3127f10a77bbSDavid C Somayajulu 			flag = 1;
3128f10a77bbSDavid C Somayajulu 	}
3129f10a77bbSDavid C Somayajulu 
3130f10a77bbSDavid C Somayajulu 	if (!flag)
3131f10a77bbSDavid C Somayajulu 		ha->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
3132f10a77bbSDavid C Somayajulu 
3133f10a77bbSDavid C Somayajulu 	QLA_TX_UNLOCK(ha);
3134f10a77bbSDavid C Somayajulu 	return;
3135f10a77bbSDavid C Somayajulu }
3136f10a77bbSDavid C Somayajulu 
3137f10a77bbSDavid C Somayajulu void
3138f10a77bbSDavid C Somayajulu ql_update_link_state(qla_host_t *ha)
3139f10a77bbSDavid C Somayajulu {
3140f10a77bbSDavid C Somayajulu 	uint32_t link_state;
3141f10a77bbSDavid C Somayajulu 	uint32_t prev_link_state;
3142f10a77bbSDavid C Somayajulu 
3143f10a77bbSDavid C Somayajulu 	if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
3144f10a77bbSDavid C Somayajulu 		ha->hw.link_up = 0;
3145f10a77bbSDavid C Somayajulu 		return;
3146f10a77bbSDavid C Somayajulu 	}
3147f10a77bbSDavid C Somayajulu 	link_state = READ_REG32(ha, Q8_LINK_STATE);
3148f10a77bbSDavid C Somayajulu 
3149f10a77bbSDavid C Somayajulu 	prev_link_state =  ha->hw.link_up;
3150f10a77bbSDavid C Somayajulu 
3151f10a77bbSDavid C Somayajulu 	if (ha->pci_func == 0)
3152f10a77bbSDavid C Somayajulu 		ha->hw.link_up = (((link_state & 0xF) == 1)? 1 : 0);
3153f10a77bbSDavid C Somayajulu 	else
3154f10a77bbSDavid C Somayajulu 		ha->hw.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
3155f10a77bbSDavid C Somayajulu 
3156f10a77bbSDavid C Somayajulu 	if (prev_link_state !=  ha->hw.link_up) {
3157f10a77bbSDavid C Somayajulu 		if (ha->hw.link_up) {
3158f10a77bbSDavid C Somayajulu 			if_link_state_change(ha->ifp, LINK_STATE_UP);
3159f10a77bbSDavid C Somayajulu 		} else {
3160f10a77bbSDavid C Somayajulu 			if_link_state_change(ha->ifp, LINK_STATE_DOWN);
3161f10a77bbSDavid C Somayajulu 		}
3162f10a77bbSDavid C Somayajulu 	}
3163f10a77bbSDavid C Somayajulu 	return;
3164f10a77bbSDavid C Somayajulu }
3165f10a77bbSDavid C Somayajulu 
3166f10a77bbSDavid C Somayajulu void
3167f10a77bbSDavid C Somayajulu ql_hw_stop_rcv(qla_host_t *ha)
3168f10a77bbSDavid C Somayajulu {
3169f10a77bbSDavid C Somayajulu 	int i, done, count = 100;
3170f10a77bbSDavid C Somayajulu 
31716a62bec0SDavid C Somayajulu 	ha->flags.stop_rcv = 1;
31726a62bec0SDavid C Somayajulu 
317335291c22SDavid C Somayajulu 	while (count) {
3174f10a77bbSDavid C Somayajulu 		done = 1;
3175f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
3176f10a77bbSDavid C Somayajulu 			if (ha->hw.sds[i].rcv_active)
3177f10a77bbSDavid C Somayajulu 				done = 0;
3178f10a77bbSDavid C Somayajulu 		}
3179f10a77bbSDavid C Somayajulu 		if (done)
3180f10a77bbSDavid C Somayajulu 			break;
3181f10a77bbSDavid C Somayajulu 		else
3182f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 10);
318335291c22SDavid C Somayajulu 		count--;
3184f10a77bbSDavid C Somayajulu 	}
3185f10a77bbSDavid C Somayajulu 	if (!count)
3186f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Counter expired.\n", __func__);
3187f10a77bbSDavid C Somayajulu 
3188f10a77bbSDavid C Somayajulu 	return;
3189f10a77bbSDavid C Somayajulu }
3190f10a77bbSDavid C Somayajulu 
3191f10a77bbSDavid C Somayajulu int
3192f10a77bbSDavid C Somayajulu ql_hw_check_health(qla_host_t *ha)
3193f10a77bbSDavid C Somayajulu {
3194f10a77bbSDavid C Somayajulu 	uint32_t val;
3195f10a77bbSDavid C Somayajulu 
3196f10a77bbSDavid C Somayajulu 	ha->hw.health_count++;
3197f10a77bbSDavid C Somayajulu 
3198f10a77bbSDavid C Somayajulu 	if (ha->hw.health_count < 1000)
3199f10a77bbSDavid C Somayajulu 		return 0;
3200f10a77bbSDavid C Somayajulu 
3201f10a77bbSDavid C Somayajulu 	ha->hw.health_count = 0;
3202f10a77bbSDavid C Somayajulu 
3203f10a77bbSDavid C Somayajulu 	val = READ_REG32(ha, Q8_ASIC_TEMPERATURE);
3204f10a77bbSDavid C Somayajulu 
3205f10a77bbSDavid C Somayajulu 	if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) ||
3206f10a77bbSDavid C Somayajulu 		(QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) {
3207f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Temperature Alert [0x%08x]\n",
3208f10a77bbSDavid C Somayajulu 			__func__, val);
3209f10a77bbSDavid C Somayajulu 		return -1;
3210f10a77bbSDavid C Somayajulu 	}
3211f10a77bbSDavid C Somayajulu 
3212f10a77bbSDavid C Somayajulu 	val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
3213f10a77bbSDavid C Somayajulu 
3214f10a77bbSDavid C Somayajulu 	if ((val != ha->hw.hbeat_value) &&
3215467dcb5aSDavid C Somayajulu 		(!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) {
3216f10a77bbSDavid C Somayajulu 		ha->hw.hbeat_value = val;
3217f10a77bbSDavid C Somayajulu 		return 0;
3218f10a77bbSDavid C Somayajulu 	}
3219f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: Heartbeat Failue [0x%08x]\n",
3220f10a77bbSDavid C Somayajulu 		__func__, val);
3221f10a77bbSDavid C Somayajulu 
3222f10a77bbSDavid C Somayajulu 	return -1;
3223f10a77bbSDavid C Somayajulu }
3224f10a77bbSDavid C Somayajulu 
3225f10a77bbSDavid C Somayajulu static int
322635291c22SDavid C Somayajulu qla_init_nic_func(qla_host_t *ha)
322735291c22SDavid C Somayajulu {
322835291c22SDavid C Somayajulu         device_t                dev;
322935291c22SDavid C Somayajulu         q80_init_nic_func_t     *init_nic;
323035291c22SDavid C Somayajulu         q80_init_nic_func_rsp_t *init_nic_rsp;
323135291c22SDavid C Somayajulu         uint32_t                err;
323235291c22SDavid C Somayajulu 
323335291c22SDavid C Somayajulu         dev = ha->pci_dev;
323435291c22SDavid C Somayajulu 
323535291c22SDavid C Somayajulu         init_nic = (q80_init_nic_func_t *)ha->hw.mbox;
323635291c22SDavid C Somayajulu         bzero(init_nic, sizeof(q80_init_nic_func_t));
323735291c22SDavid C Somayajulu 
323835291c22SDavid C Somayajulu         init_nic->opcode = Q8_MBX_INIT_NIC_FUNC;
323935291c22SDavid C Somayajulu         init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2);
324035291c22SDavid C Somayajulu         init_nic->count_version |= Q8_MBX_CMD_VERSION;
324135291c22SDavid C Somayajulu 
324235291c22SDavid C Somayajulu         init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN;
324335291c22SDavid C Somayajulu         init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN;
324435291c22SDavid C Somayajulu         init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN;
324535291c22SDavid C Somayajulu 
324635291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t));
324735291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)init_nic,
324835291c22SDavid C Somayajulu                 (sizeof (q80_init_nic_func_t) >> 2),
324935291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) {
325035291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
325135291c22SDavid C Somayajulu                 return -1;
325235291c22SDavid C Somayajulu         }
325335291c22SDavid C Somayajulu 
325435291c22SDavid C Somayajulu         init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox;
325535291c22SDavid C Somayajulu // qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t));
325635291c22SDavid C Somayajulu 
325735291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status);
325835291c22SDavid C Somayajulu 
325935291c22SDavid C Somayajulu         if (err) {
326035291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
326135291c22SDavid C Somayajulu         }
326235291c22SDavid C Somayajulu 
326335291c22SDavid C Somayajulu         return 0;
326435291c22SDavid C Somayajulu }
326535291c22SDavid C Somayajulu 
326635291c22SDavid C Somayajulu static int
326735291c22SDavid C Somayajulu qla_stop_nic_func(qla_host_t *ha)
326835291c22SDavid C Somayajulu {
326935291c22SDavid C Somayajulu         device_t                dev;
327035291c22SDavid C Somayajulu         q80_stop_nic_func_t     *stop_nic;
327135291c22SDavid C Somayajulu         q80_stop_nic_func_rsp_t *stop_nic_rsp;
327235291c22SDavid C Somayajulu         uint32_t                err;
327335291c22SDavid C Somayajulu 
327435291c22SDavid C Somayajulu         dev = ha->pci_dev;
327535291c22SDavid C Somayajulu 
327635291c22SDavid C Somayajulu         stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox;
327735291c22SDavid C Somayajulu         bzero(stop_nic, sizeof(q80_stop_nic_func_t));
327835291c22SDavid C Somayajulu 
327935291c22SDavid C Somayajulu         stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC;
328035291c22SDavid C Somayajulu         stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2);
328135291c22SDavid C Somayajulu         stop_nic->count_version |= Q8_MBX_CMD_VERSION;
328235291c22SDavid C Somayajulu 
328335291c22SDavid C Somayajulu         stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN;
328435291c22SDavid C Somayajulu         stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN;
328535291c22SDavid C Somayajulu 
328635291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t));
328735291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)stop_nic,
328835291c22SDavid C Somayajulu                 (sizeof (q80_stop_nic_func_t) >> 2),
328935291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) {
329035291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
329135291c22SDavid C Somayajulu                 return -1;
329235291c22SDavid C Somayajulu         }
329335291c22SDavid C Somayajulu 
329435291c22SDavid C Somayajulu         stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox;
329535291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t));
329635291c22SDavid C Somayajulu 
329735291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status);
329835291c22SDavid C Somayajulu 
329935291c22SDavid C Somayajulu         if (err) {
330035291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
330135291c22SDavid C Somayajulu         }
330235291c22SDavid C Somayajulu 
330335291c22SDavid C Somayajulu         return 0;
330435291c22SDavid C Somayajulu }
330535291c22SDavid C Somayajulu 
330635291c22SDavid C Somayajulu static int
330735291c22SDavid C Somayajulu qla_query_fw_dcbx_caps(qla_host_t *ha)
330835291c22SDavid C Somayajulu {
330935291c22SDavid C Somayajulu         device_t                        dev;
331035291c22SDavid C Somayajulu         q80_query_fw_dcbx_caps_t        *fw_dcbx;
331135291c22SDavid C Somayajulu         q80_query_fw_dcbx_caps_rsp_t    *fw_dcbx_rsp;
331235291c22SDavid C Somayajulu         uint32_t                        err;
331335291c22SDavid C Somayajulu 
331435291c22SDavid C Somayajulu         dev = ha->pci_dev;
331535291c22SDavid C Somayajulu 
331635291c22SDavid C Somayajulu         fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox;
331735291c22SDavid C Somayajulu         bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t));
331835291c22SDavid C Somayajulu 
331935291c22SDavid C Somayajulu         fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS;
332035291c22SDavid C Somayajulu         fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2);
332135291c22SDavid C Somayajulu         fw_dcbx->count_version |= Q8_MBX_CMD_VERSION;
332235291c22SDavid C Somayajulu 
332335291c22SDavid C Somayajulu         ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t));
332435291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx,
332535291c22SDavid C Somayajulu                 (sizeof (q80_query_fw_dcbx_caps_t) >> 2),
332635291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) {
332735291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
332835291c22SDavid C Somayajulu                 return -1;
332935291c22SDavid C Somayajulu         }
333035291c22SDavid C Somayajulu 
333135291c22SDavid C Somayajulu         fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox;
333235291c22SDavid C Somayajulu         ql_dump_buf8(ha, __func__, fw_dcbx_rsp,
333335291c22SDavid C Somayajulu                 sizeof (q80_query_fw_dcbx_caps_rsp_t));
333435291c22SDavid C Somayajulu 
333535291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status);
333635291c22SDavid C Somayajulu 
333735291c22SDavid C Somayajulu         if (err) {
333835291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
333935291c22SDavid C Somayajulu         }
334035291c22SDavid C Somayajulu 
334135291c22SDavid C Somayajulu         return 0;
334235291c22SDavid C Somayajulu }
334335291c22SDavid C Somayajulu 
334435291c22SDavid C Somayajulu static int
334535291c22SDavid C Somayajulu qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2,
334635291c22SDavid C Somayajulu         uint32_t aen_mb3, uint32_t aen_mb4)
334735291c22SDavid C Somayajulu {
334835291c22SDavid C Somayajulu         device_t                dev;
334935291c22SDavid C Somayajulu         q80_idc_ack_t           *idc_ack;
335035291c22SDavid C Somayajulu         q80_idc_ack_rsp_t       *idc_ack_rsp;
335135291c22SDavid C Somayajulu         uint32_t                err;
335235291c22SDavid C Somayajulu         int                     count = 300;
335335291c22SDavid C Somayajulu 
335435291c22SDavid C Somayajulu         dev = ha->pci_dev;
335535291c22SDavid C Somayajulu 
335635291c22SDavid C Somayajulu         idc_ack = (q80_idc_ack_t *)ha->hw.mbox;
335735291c22SDavid C Somayajulu         bzero(idc_ack, sizeof(q80_idc_ack_t));
335835291c22SDavid C Somayajulu 
335935291c22SDavid C Somayajulu         idc_ack->opcode = Q8_MBX_IDC_ACK;
336035291c22SDavid C Somayajulu         idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2);
336135291c22SDavid C Somayajulu         idc_ack->count_version |= Q8_MBX_CMD_VERSION;
336235291c22SDavid C Somayajulu 
336335291c22SDavid C Somayajulu         idc_ack->aen_mb1 = aen_mb1;
336435291c22SDavid C Somayajulu         idc_ack->aen_mb2 = aen_mb2;
336535291c22SDavid C Somayajulu         idc_ack->aen_mb3 = aen_mb3;
336635291c22SDavid C Somayajulu         idc_ack->aen_mb4 = aen_mb4;
336735291c22SDavid C Somayajulu 
336835291c22SDavid C Somayajulu         ha->hw.imd_compl= 0;
336935291c22SDavid C Somayajulu 
337035291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)idc_ack,
337135291c22SDavid C Somayajulu                 (sizeof (q80_idc_ack_t) >> 2),
337235291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) {
337335291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
337435291c22SDavid C Somayajulu                 return -1;
337535291c22SDavid C Somayajulu         }
337635291c22SDavid C Somayajulu 
337735291c22SDavid C Somayajulu         idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox;
337835291c22SDavid C Somayajulu 
337935291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status);
338035291c22SDavid C Somayajulu 
338135291c22SDavid C Somayajulu         if (err) {
338235291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
338335291c22SDavid C Somayajulu                 return(-1);
338435291c22SDavid C Somayajulu         }
338535291c22SDavid C Somayajulu 
338635291c22SDavid C Somayajulu         while (count && !ha->hw.imd_compl) {
338735291c22SDavid C Somayajulu                 qla_mdelay(__func__, 100);
338835291c22SDavid C Somayajulu                 count--;
338935291c22SDavid C Somayajulu         }
339035291c22SDavid C Somayajulu 
339135291c22SDavid C Somayajulu         if (!count)
339235291c22SDavid C Somayajulu                 return -1;
339335291c22SDavid C Somayajulu         else
339435291c22SDavid C Somayajulu                 device_printf(dev, "%s: count %d\n", __func__, count);
339535291c22SDavid C Somayajulu 
339635291c22SDavid C Somayajulu         return (0);
339735291c22SDavid C Somayajulu }
339835291c22SDavid C Somayajulu 
339935291c22SDavid C Somayajulu static int
340035291c22SDavid C Somayajulu qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits)
340135291c22SDavid C Somayajulu {
340235291c22SDavid C Somayajulu         device_t                dev;
340335291c22SDavid C Somayajulu         q80_set_port_cfg_t      *pcfg;
340435291c22SDavid C Somayajulu         q80_set_port_cfg_rsp_t  *pfg_rsp;
340535291c22SDavid C Somayajulu         uint32_t                err;
340635291c22SDavid C Somayajulu         int                     count = 300;
340735291c22SDavid C Somayajulu 
340835291c22SDavid C Somayajulu         dev = ha->pci_dev;
340935291c22SDavid C Somayajulu 
341035291c22SDavid C Somayajulu         pcfg = (q80_set_port_cfg_t *)ha->hw.mbox;
341135291c22SDavid C Somayajulu         bzero(pcfg, sizeof(q80_set_port_cfg_t));
341235291c22SDavid C Somayajulu 
341335291c22SDavid C Somayajulu         pcfg->opcode = Q8_MBX_SET_PORT_CONFIG;
341435291c22SDavid C Somayajulu         pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2);
341535291c22SDavid C Somayajulu         pcfg->count_version |= Q8_MBX_CMD_VERSION;
341635291c22SDavid C Somayajulu 
341735291c22SDavid C Somayajulu         pcfg->cfg_bits = cfg_bits;
341835291c22SDavid C Somayajulu 
341935291c22SDavid C Somayajulu         device_printf(dev, "%s: cfg_bits"
342035291c22SDavid C Somayajulu                 " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
342135291c22SDavid C Somayajulu                 " [0x%x, 0x%x, 0x%x]\n", __func__,
342235291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
342335291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
342435291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0));
342535291c22SDavid C Somayajulu 
342635291c22SDavid C Somayajulu         ha->hw.imd_compl= 0;
342735291c22SDavid C Somayajulu 
342835291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
342935291c22SDavid C Somayajulu                 (sizeof (q80_set_port_cfg_t) >> 2),
343035291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) {
343135291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
343235291c22SDavid C Somayajulu                 return -1;
343335291c22SDavid C Somayajulu         }
343435291c22SDavid C Somayajulu 
343535291c22SDavid C Somayajulu         pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox;
343635291c22SDavid C Somayajulu 
343735291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status);
343835291c22SDavid C Somayajulu 
343935291c22SDavid C Somayajulu         if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) {
344035291c22SDavid C Somayajulu                 while (count && !ha->hw.imd_compl) {
344135291c22SDavid C Somayajulu                         qla_mdelay(__func__, 100);
344235291c22SDavid C Somayajulu                         count--;
344335291c22SDavid C Somayajulu                 }
344435291c22SDavid C Somayajulu                 if (count) {
344535291c22SDavid C Somayajulu                         device_printf(dev, "%s: count %d\n", __func__, count);
344635291c22SDavid C Somayajulu 
344735291c22SDavid C Somayajulu                         err = 0;
344835291c22SDavid C Somayajulu                 }
344935291c22SDavid C Somayajulu         }
345035291c22SDavid C Somayajulu 
345135291c22SDavid C Somayajulu         if (err) {
345235291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
345335291c22SDavid C Somayajulu                 return(-1);
345435291c22SDavid C Somayajulu         }
345535291c22SDavid C Somayajulu 
345635291c22SDavid C Somayajulu         return (0);
345735291c22SDavid C Somayajulu }
345835291c22SDavid C Somayajulu 
345935291c22SDavid C Somayajulu 
346035291c22SDavid C Somayajulu static int
3461f10a77bbSDavid C Somayajulu qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size)
3462f10a77bbSDavid C Somayajulu {
3463f10a77bbSDavid C Somayajulu 	uint32_t			err;
3464f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
3465f10a77bbSDavid C Somayajulu 	q80_config_md_templ_size_t	*md_size;
3466f10a77bbSDavid C Somayajulu 	q80_config_md_templ_size_rsp_t	*md_size_rsp;
3467f10a77bbSDavid C Somayajulu 
34686a62bec0SDavid C Somayajulu #ifndef QL_LDFLASH_FW
346935291c22SDavid C Somayajulu 
34706a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *hdr;
34716a62bec0SDavid C Somayajulu 
34726a62bec0SDavid C Somayajulu 	hdr = (ql_minidump_template_hdr_t *)ql83xx_minidump;
34736a62bec0SDavid C Somayajulu 	*size = hdr->size_of_template;
347435291c22SDavid C Somayajulu 	return (0);
347535291c22SDavid C Somayajulu 
347635291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
347735291c22SDavid C Somayajulu 
3478f10a77bbSDavid C Somayajulu 	md_size = (q80_config_md_templ_size_t *) ha->hw.mbox;
3479f10a77bbSDavid C Somayajulu 	bzero(md_size, sizeof(q80_config_md_templ_size_t));
3480f10a77bbSDavid C Somayajulu 
3481f10a77bbSDavid C Somayajulu 	md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE;
3482f10a77bbSDavid C Somayajulu 	md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2);
3483f10a77bbSDavid C Somayajulu 	md_size->count_version |= Q8_MBX_CMD_VERSION;
3484f10a77bbSDavid C Somayajulu 
3485f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *) md_size,
3486f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox,
3487f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) {
3488f10a77bbSDavid C Somayajulu 
3489f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
3490f10a77bbSDavid C Somayajulu 
3491f10a77bbSDavid C Somayajulu 		return (-1);
3492f10a77bbSDavid C Somayajulu 	}
3493f10a77bbSDavid C Somayajulu 
3494f10a77bbSDavid C Somayajulu 	md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox;
3495f10a77bbSDavid C Somayajulu 
3496f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status);
3497f10a77bbSDavid C Somayajulu 
3498f10a77bbSDavid C Somayajulu         if (err) {
3499f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3500f10a77bbSDavid C Somayajulu 		return(-1);
3501f10a77bbSDavid C Somayajulu         }
3502f10a77bbSDavid C Somayajulu 
3503f10a77bbSDavid C Somayajulu 	*size = md_size_rsp->templ_size;
3504f10a77bbSDavid C Somayajulu 
3505f10a77bbSDavid C Somayajulu 	return (0);
3506f10a77bbSDavid C Somayajulu }
3507f10a77bbSDavid C Somayajulu 
3508f10a77bbSDavid C Somayajulu static int
350935291c22SDavid C Somayajulu qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits)
351035291c22SDavid C Somayajulu {
351135291c22SDavid C Somayajulu         device_t                dev;
351235291c22SDavid C Somayajulu         q80_get_port_cfg_t      *pcfg;
351335291c22SDavid C Somayajulu         q80_get_port_cfg_rsp_t  *pcfg_rsp;
351435291c22SDavid C Somayajulu         uint32_t                err;
351535291c22SDavid C Somayajulu 
351635291c22SDavid C Somayajulu         dev = ha->pci_dev;
351735291c22SDavid C Somayajulu 
351835291c22SDavid C Somayajulu         pcfg = (q80_get_port_cfg_t *)ha->hw.mbox;
351935291c22SDavid C Somayajulu         bzero(pcfg, sizeof(q80_get_port_cfg_t));
352035291c22SDavid C Somayajulu 
352135291c22SDavid C Somayajulu         pcfg->opcode = Q8_MBX_GET_PORT_CONFIG;
352235291c22SDavid C Somayajulu         pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2);
352335291c22SDavid C Somayajulu         pcfg->count_version |= Q8_MBX_CMD_VERSION;
352435291c22SDavid C Somayajulu 
352535291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
352635291c22SDavid C Somayajulu                 (sizeof (q80_get_port_cfg_t) >> 2),
352735291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) {
352835291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
352935291c22SDavid C Somayajulu                 return -1;
353035291c22SDavid C Somayajulu         }
353135291c22SDavid C Somayajulu 
353235291c22SDavid C Somayajulu         pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox;
353335291c22SDavid C Somayajulu 
353435291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status);
353535291c22SDavid C Somayajulu 
353635291c22SDavid C Somayajulu         if (err) {
353735291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
353835291c22SDavid C Somayajulu                 return(-1);
353935291c22SDavid C Somayajulu         }
354035291c22SDavid C Somayajulu 
354135291c22SDavid C Somayajulu         device_printf(dev, "%s: [cfg_bits, port type]"
354235291c22SDavid C Somayajulu                 " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
354335291c22SDavid C Somayajulu                 " [0x%x, 0x%x, 0x%x]\n", __func__,
354435291c22SDavid C Somayajulu                 pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type,
354535291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
354635291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
354735291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)
354835291c22SDavid C Somayajulu                 );
354935291c22SDavid C Somayajulu 
355035291c22SDavid C Somayajulu         *cfg_bits = pcfg_rsp->cfg_bits;
355135291c22SDavid C Somayajulu 
355235291c22SDavid C Somayajulu         return (0);
355335291c22SDavid C Somayajulu }
355435291c22SDavid C Somayajulu 
355535291c22SDavid C Somayajulu int
355635291c22SDavid C Somayajulu qla_iscsi_pdu(qla_host_t *ha, struct mbuf *mp)
355735291c22SDavid C Somayajulu {
355835291c22SDavid C Somayajulu         struct ether_vlan_header        *eh;
355935291c22SDavid C Somayajulu         uint16_t                        etype;
356035291c22SDavid C Somayajulu         struct ip                       *ip = NULL;
356135291c22SDavid C Somayajulu         struct ip6_hdr                  *ip6 = NULL;
356235291c22SDavid C Somayajulu         struct tcphdr                   *th = NULL;
356335291c22SDavid C Somayajulu         uint32_t                        hdrlen;
356435291c22SDavid C Somayajulu         uint32_t                        offset;
356535291c22SDavid C Somayajulu         uint8_t                         buf[sizeof(struct ip6_hdr)];
356635291c22SDavid C Somayajulu 
356735291c22SDavid C Somayajulu         eh = mtod(mp, struct ether_vlan_header *);
356835291c22SDavid C Somayajulu 
356935291c22SDavid C Somayajulu         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
357035291c22SDavid C Somayajulu                 hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
357135291c22SDavid C Somayajulu                 etype = ntohs(eh->evl_proto);
357235291c22SDavid C Somayajulu         } else {
357335291c22SDavid C Somayajulu                 hdrlen = ETHER_HDR_LEN;
357435291c22SDavid C Somayajulu                 etype = ntohs(eh->evl_encap_proto);
357535291c22SDavid C Somayajulu         }
357635291c22SDavid C Somayajulu 
357735291c22SDavid C Somayajulu 	if (etype == ETHERTYPE_IP) {
357835291c22SDavid C Somayajulu 
357935291c22SDavid C Somayajulu 		offset = (hdrlen + sizeof (struct ip));
358035291c22SDavid C Somayajulu 
358135291c22SDavid C Somayajulu 		if (mp->m_len >= offset) {
358235291c22SDavid C Somayajulu                         ip = (struct ip *)(mp->m_data + hdrlen);
358335291c22SDavid C Somayajulu 		} else {
358435291c22SDavid C Somayajulu 			m_copydata(mp, hdrlen, sizeof (struct ip), buf);
358535291c22SDavid C Somayajulu                         ip = (struct ip *)buf;
358635291c22SDavid C Somayajulu 		}
358735291c22SDavid C Somayajulu 
358835291c22SDavid C Somayajulu                 if (ip->ip_p == IPPROTO_TCP) {
358935291c22SDavid C Somayajulu 
359035291c22SDavid C Somayajulu 			hdrlen += ip->ip_hl << 2;
359135291c22SDavid C Somayajulu 			offset = hdrlen + 4;
359235291c22SDavid C Somayajulu 
359335291c22SDavid C Somayajulu 			if (mp->m_len >= offset) {
35946a62bec0SDavid C Somayajulu 				th = (struct tcphdr *)(mp->m_data + hdrlen);;
359535291c22SDavid C Somayajulu 			} else {
359635291c22SDavid C Somayajulu                                 m_copydata(mp, hdrlen, 4, buf);
359735291c22SDavid C Somayajulu 				th = (struct tcphdr *)buf;
359835291c22SDavid C Somayajulu 			}
359935291c22SDavid C Somayajulu                 }
360035291c22SDavid C Somayajulu 
360135291c22SDavid C Somayajulu 	} else if (etype == ETHERTYPE_IPV6) {
360235291c22SDavid C Somayajulu 
360335291c22SDavid C Somayajulu 		offset = (hdrlen + sizeof (struct ip6_hdr));
360435291c22SDavid C Somayajulu 
360535291c22SDavid C Somayajulu 		if (mp->m_len >= offset) {
360635291c22SDavid C Somayajulu                         ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen);
360735291c22SDavid C Somayajulu 		} else {
360835291c22SDavid C Somayajulu                         m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf);
360935291c22SDavid C Somayajulu                         ip6 = (struct ip6_hdr *)buf;
361035291c22SDavid C Somayajulu 		}
361135291c22SDavid C Somayajulu 
361235291c22SDavid C Somayajulu                 if (ip6->ip6_nxt == IPPROTO_TCP) {
361335291c22SDavid C Somayajulu 
361435291c22SDavid C Somayajulu 			hdrlen += sizeof(struct ip6_hdr);
361535291c22SDavid C Somayajulu 			offset = hdrlen + 4;
361635291c22SDavid C Somayajulu 
361735291c22SDavid C Somayajulu 			if (mp->m_len >= offset) {
36186a62bec0SDavid C Somayajulu 				th = (struct tcphdr *)(mp->m_data + hdrlen);;
361935291c22SDavid C Somayajulu 			} else {
362035291c22SDavid C Somayajulu 				m_copydata(mp, hdrlen, 4, buf);
362135291c22SDavid C Somayajulu 				th = (struct tcphdr *)buf;
362235291c22SDavid C Somayajulu 			}
362335291c22SDavid C Somayajulu                 }
362435291c22SDavid C Somayajulu 	}
362535291c22SDavid C Somayajulu 
362635291c22SDavid C Somayajulu         if (th != NULL) {
362735291c22SDavid C Somayajulu                 if ((th->th_sport == htons(3260)) ||
362835291c22SDavid C Somayajulu                         (th->th_dport == htons(3260)))
362935291c22SDavid C Somayajulu                         return 0;
363035291c22SDavid C Somayajulu         }
363135291c22SDavid C Somayajulu         return (-1);
363235291c22SDavid C Somayajulu }
363335291c22SDavid C Somayajulu 
363435291c22SDavid C Somayajulu void
363535291c22SDavid C Somayajulu qla_hw_async_event(qla_host_t *ha)
363635291c22SDavid C Somayajulu {
363735291c22SDavid C Somayajulu         switch (ha->hw.aen_mb0) {
363835291c22SDavid C Somayajulu         case 0x8101:
363935291c22SDavid C Somayajulu                 (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2,
364035291c22SDavid C Somayajulu                         ha->hw.aen_mb3, ha->hw.aen_mb4);
364135291c22SDavid C Somayajulu 
364235291c22SDavid C Somayajulu                 break;
364335291c22SDavid C Somayajulu 
364435291c22SDavid C Somayajulu         default:
364535291c22SDavid C Somayajulu                 break;
364635291c22SDavid C Somayajulu         }
364735291c22SDavid C Somayajulu 
364835291c22SDavid C Somayajulu         return;
364935291c22SDavid C Somayajulu }
365035291c22SDavid C Somayajulu 
365135291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
365235291c22SDavid C Somayajulu static int
36536a62bec0SDavid C Somayajulu ql_get_minidump_template(qla_host_t *ha)
3654f10a77bbSDavid C Somayajulu {
3655f10a77bbSDavid C Somayajulu 	uint32_t			err;
3656f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
3657f10a77bbSDavid C Somayajulu 	q80_config_md_templ_cmd_t	*md_templ;
3658f10a77bbSDavid C Somayajulu 	q80_config_md_templ_cmd_rsp_t	*md_templ_rsp;
3659f10a77bbSDavid C Somayajulu 
3660f10a77bbSDavid C Somayajulu 	md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox;
3661f10a77bbSDavid C Somayajulu 	bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t)));
3662f10a77bbSDavid C Somayajulu 
3663f10a77bbSDavid C Somayajulu 	md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT;
3664f10a77bbSDavid C Somayajulu 	md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2);
3665f10a77bbSDavid C Somayajulu 	md_templ->count_version |= Q8_MBX_CMD_VERSION;
3666f10a77bbSDavid C Somayajulu 
3667f10a77bbSDavid C Somayajulu 	md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr;
3668f10a77bbSDavid C Somayajulu 	md_templ->buff_size = ha->hw.dma_buf.minidump.size;
3669f10a77bbSDavid C Somayajulu 
3670f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *) md_templ,
3671f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_cmd_t) >> 2),
3672f10a77bbSDavid C Somayajulu 		 ha->hw.mbox,
3673f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) {
3674f10a77bbSDavid C Somayajulu 
3675f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
3676f10a77bbSDavid C Somayajulu 
3677f10a77bbSDavid C Somayajulu 		return (-1);
3678f10a77bbSDavid C Somayajulu 	}
3679f10a77bbSDavid C Somayajulu 
3680f10a77bbSDavid C Somayajulu 	md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox;
3681f10a77bbSDavid C Somayajulu 
3682f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status);
3683f10a77bbSDavid C Somayajulu 
3684f10a77bbSDavid C Somayajulu 	if (err) {
3685f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3686f10a77bbSDavid C Somayajulu 		return (-1);
3687f10a77bbSDavid C Somayajulu 	}
3688f10a77bbSDavid C Somayajulu 
3689f10a77bbSDavid C Somayajulu 	return (0);
3690f10a77bbSDavid C Somayajulu 
3691f10a77bbSDavid C Somayajulu }
369235291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
3693f10a77bbSDavid C Somayajulu 
36946a62bec0SDavid C Somayajulu /*
36956a62bec0SDavid C Somayajulu  * Minidump related functionality
36966a62bec0SDavid C Somayajulu  */
36976a62bec0SDavid C Somayajulu 
36986a62bec0SDavid C Somayajulu static int ql_parse_template(qla_host_t *ha);
36996a62bec0SDavid C Somayajulu 
37006a62bec0SDavid C Somayajulu static uint32_t ql_rdcrb(qla_host_t *ha,
37016a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdcrb_t *crb_entry,
37026a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
37036a62bec0SDavid C Somayajulu 
37046a62bec0SDavid C Somayajulu static uint32_t ql_pollrd(qla_host_t *ha,
37056a62bec0SDavid C Somayajulu 			ql_minidump_entry_pollrd_t *entry,
37066a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
37076a62bec0SDavid C Somayajulu 
37086a62bec0SDavid C Somayajulu static uint32_t ql_pollrd_modify_write(qla_host_t *ha,
37096a62bec0SDavid C Somayajulu 			ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
37106a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
37116a62bec0SDavid C Somayajulu 
37126a62bec0SDavid C Somayajulu static uint32_t ql_L2Cache(qla_host_t *ha,
37136a62bec0SDavid C Somayajulu 			ql_minidump_entry_cache_t *cacheEntry,
37146a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
37156a62bec0SDavid C Somayajulu 
37166a62bec0SDavid C Somayajulu static uint32_t ql_L1Cache(qla_host_t *ha,
37176a62bec0SDavid C Somayajulu 			ql_minidump_entry_cache_t *cacheEntry,
37186a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
37196a62bec0SDavid C Somayajulu 
37206a62bec0SDavid C Somayajulu static uint32_t ql_rdocm(qla_host_t *ha,
37216a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdocm_t *ocmEntry,
37226a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
37236a62bec0SDavid C Somayajulu 
37246a62bec0SDavid C Somayajulu static uint32_t ql_rdmem(qla_host_t *ha,
37256a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdmem_t *mem_entry,
37266a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
37276a62bec0SDavid C Somayajulu 
37286a62bec0SDavid C Somayajulu static uint32_t ql_rdrom(qla_host_t *ha,
37296a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdrom_t *romEntry,
37306a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
37316a62bec0SDavid C Somayajulu 
37326a62bec0SDavid C Somayajulu static uint32_t ql_rdmux(qla_host_t *ha,
37336a62bec0SDavid C Somayajulu 			ql_minidump_entry_mux_t *muxEntry,
37346a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
37356a62bec0SDavid C Somayajulu 
37366a62bec0SDavid C Somayajulu static uint32_t ql_rdmux2(qla_host_t *ha,
37376a62bec0SDavid C Somayajulu 			ql_minidump_entry_mux2_t *muxEntry,
37386a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
37396a62bec0SDavid C Somayajulu 
37406a62bec0SDavid C Somayajulu static uint32_t ql_rdqueue(qla_host_t *ha,
37416a62bec0SDavid C Somayajulu 			ql_minidump_entry_queue_t *queueEntry,
37426a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
37436a62bec0SDavid C Somayajulu 
37446a62bec0SDavid C Somayajulu static uint32_t ql_cntrl(qla_host_t *ha,
37456a62bec0SDavid C Somayajulu 			ql_minidump_template_hdr_t *template_hdr,
37466a62bec0SDavid C Somayajulu 			ql_minidump_entry_cntrl_t *crbEntry);
37476a62bec0SDavid C Somayajulu 
37486a62bec0SDavid C Somayajulu 
37496a62bec0SDavid C Somayajulu static uint32_t
37506a62bec0SDavid C Somayajulu ql_minidump_size(qla_host_t *ha)
37516a62bec0SDavid C Somayajulu {
37526a62bec0SDavid C Somayajulu 	uint32_t i, k;
37536a62bec0SDavid C Somayajulu 	uint32_t size = 0;
37546a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *hdr;
37556a62bec0SDavid C Somayajulu 
37566a62bec0SDavid C Somayajulu 	hdr = (ql_minidump_template_hdr_t *)ha->hw.dma_buf.minidump.dma_b;
37576a62bec0SDavid C Somayajulu 
37586a62bec0SDavid C Somayajulu 	i = 0x2;
37596a62bec0SDavid C Somayajulu 
37606a62bec0SDavid C Somayajulu 	for (k = 1; k < QL_DBG_CAP_SIZE_ARRAY_LEN; k++) {
37616a62bec0SDavid C Somayajulu 		if (i & ha->hw.mdump_capture_mask)
37626a62bec0SDavid C Somayajulu 			size += hdr->capture_size_array[k];
37636a62bec0SDavid C Somayajulu 		i = i << 1;
37646a62bec0SDavid C Somayajulu 	}
37656a62bec0SDavid C Somayajulu 	return (size);
37666a62bec0SDavid C Somayajulu }
37676a62bec0SDavid C Somayajulu 
37686a62bec0SDavid C Somayajulu static void
37696a62bec0SDavid C Somayajulu ql_free_minidump_buffer(qla_host_t *ha)
37706a62bec0SDavid C Somayajulu {
37716a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_buffer != NULL) {
37726a62bec0SDavid C Somayajulu 		free(ha->hw.mdump_buffer, M_QLA83XXBUF);
37736a62bec0SDavid C Somayajulu 		ha->hw.mdump_buffer = NULL;
37746a62bec0SDavid C Somayajulu 		ha->hw.mdump_buffer_size = 0;
37756a62bec0SDavid C Somayajulu 	}
37766a62bec0SDavid C Somayajulu 	return;
37776a62bec0SDavid C Somayajulu }
37786a62bec0SDavid C Somayajulu 
3779f10a77bbSDavid C Somayajulu static int
37806a62bec0SDavid C Somayajulu ql_alloc_minidump_buffer(qla_host_t *ha)
37816a62bec0SDavid C Somayajulu {
37826a62bec0SDavid C Somayajulu 	ha->hw.mdump_buffer_size = ql_minidump_size(ha);
37836a62bec0SDavid C Somayajulu 
37846a62bec0SDavid C Somayajulu 	if (!ha->hw.mdump_buffer_size)
37856a62bec0SDavid C Somayajulu 		return (-1);
37866a62bec0SDavid C Somayajulu 
37876a62bec0SDavid C Somayajulu 	ha->hw.mdump_buffer = malloc(ha->hw.mdump_buffer_size, M_QLA83XXBUF,
37886a62bec0SDavid C Somayajulu 					M_NOWAIT);
37896a62bec0SDavid C Somayajulu 
37906a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_buffer == NULL)
37916a62bec0SDavid C Somayajulu 		return (-1);
37926a62bec0SDavid C Somayajulu 
37936a62bec0SDavid C Somayajulu 	return (0);
37946a62bec0SDavid C Somayajulu }
37956a62bec0SDavid C Somayajulu 
37966a62bec0SDavid C Somayajulu static void
37976a62bec0SDavid C Somayajulu ql_free_minidump_template_buffer(qla_host_t *ha)
37986a62bec0SDavid C Somayajulu {
37996a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_template != NULL) {
38006a62bec0SDavid C Somayajulu 		free(ha->hw.mdump_template, M_QLA83XXBUF);
38016a62bec0SDavid C Somayajulu 		ha->hw.mdump_template = NULL;
38026a62bec0SDavid C Somayajulu 		ha->hw.mdump_template_size = 0;
38036a62bec0SDavid C Somayajulu 	}
38046a62bec0SDavid C Somayajulu 	return;
38056a62bec0SDavid C Somayajulu }
38066a62bec0SDavid C Somayajulu 
38076a62bec0SDavid C Somayajulu static int
38086a62bec0SDavid C Somayajulu ql_alloc_minidump_template_buffer(qla_host_t *ha)
38096a62bec0SDavid C Somayajulu {
38106a62bec0SDavid C Somayajulu 	ha->hw.mdump_template_size = ha->hw.dma_buf.minidump.size;
38116a62bec0SDavid C Somayajulu 
38126a62bec0SDavid C Somayajulu 	ha->hw.mdump_template = malloc(ha->hw.mdump_template_size,
38136a62bec0SDavid C Somayajulu 					M_QLA83XXBUF, M_NOWAIT);
38146a62bec0SDavid C Somayajulu 
38156a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_template == NULL)
38166a62bec0SDavid C Somayajulu 		return (-1);
38176a62bec0SDavid C Somayajulu 
38186a62bec0SDavid C Somayajulu 	return (0);
38196a62bec0SDavid C Somayajulu }
38206a62bec0SDavid C Somayajulu 
38216a62bec0SDavid C Somayajulu static int
38226a62bec0SDavid C Somayajulu ql_alloc_minidump_buffers(qla_host_t *ha)
38236a62bec0SDavid C Somayajulu {
38246a62bec0SDavid C Somayajulu 	int ret;
38256a62bec0SDavid C Somayajulu 
38266a62bec0SDavid C Somayajulu 	ret = ql_alloc_minidump_template_buffer(ha);
38276a62bec0SDavid C Somayajulu 
38286a62bec0SDavid C Somayajulu 	if (ret)
38296a62bec0SDavid C Somayajulu 		return (ret);
38306a62bec0SDavid C Somayajulu 
38316a62bec0SDavid C Somayajulu 	ret = ql_alloc_minidump_buffer(ha);
38326a62bec0SDavid C Somayajulu 
38336a62bec0SDavid C Somayajulu 	if (ret)
38346a62bec0SDavid C Somayajulu 		ql_free_minidump_template_buffer(ha);
38356a62bec0SDavid C Somayajulu 
38366a62bec0SDavid C Somayajulu 	return (ret);
38376a62bec0SDavid C Somayajulu }
38386a62bec0SDavid C Somayajulu 
38396a62bec0SDavid C Somayajulu 
38406a62bec0SDavid C Somayajulu static uint32_t
38416a62bec0SDavid C Somayajulu ql_validate_minidump_checksum(qla_host_t *ha)
38426a62bec0SDavid C Somayajulu {
38436a62bec0SDavid C Somayajulu         uint64_t sum = 0;
38446a62bec0SDavid C Somayajulu 	int count;
38456a62bec0SDavid C Somayajulu 	uint32_t *template_buff;
38466a62bec0SDavid C Somayajulu 
38476a62bec0SDavid C Somayajulu 	count = ha->hw.dma_buf.minidump.size / sizeof (uint32_t);
38486a62bec0SDavid C Somayajulu 	template_buff = ha->hw.dma_buf.minidump.dma_b;
38496a62bec0SDavid C Somayajulu 
38506a62bec0SDavid C Somayajulu 	while (count-- > 0) {
38516a62bec0SDavid C Somayajulu 		sum += *template_buff++;
38526a62bec0SDavid C Somayajulu 	}
38536a62bec0SDavid C Somayajulu 
38546a62bec0SDavid C Somayajulu 	while (sum >> 32) {
38556a62bec0SDavid C Somayajulu 		sum = (sum & 0xFFFFFFFF) + (sum >> 32);
38566a62bec0SDavid C Somayajulu 	}
38576a62bec0SDavid C Somayajulu 
38586a62bec0SDavid C Somayajulu 	return (~sum);
38596a62bec0SDavid C Somayajulu }
38606a62bec0SDavid C Somayajulu 
38616a62bec0SDavid C Somayajulu int
38626a62bec0SDavid C Somayajulu ql_minidump_init(qla_host_t *ha)
3863f10a77bbSDavid C Somayajulu {
386435291c22SDavid C Somayajulu 	int		ret = 0;
3865f10a77bbSDavid C Somayajulu 	uint32_t	template_size = 0;
3866f10a77bbSDavid C Somayajulu 	device_t	dev = ha->pci_dev;
3867f10a77bbSDavid C Somayajulu 
3868f10a77bbSDavid C Somayajulu 	/*
3869f10a77bbSDavid C Somayajulu 	 * Get Minidump Template Size
3870f10a77bbSDavid C Somayajulu  	 */
3871f10a77bbSDavid C Somayajulu 	ret = qla_get_minidump_tmplt_size(ha, &template_size);
3872f10a77bbSDavid C Somayajulu 
3873f10a77bbSDavid C Somayajulu 	if (ret || (template_size == 0)) {
3874f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret,
3875f10a77bbSDavid C Somayajulu 			template_size);
3876f10a77bbSDavid C Somayajulu 		return (-1);
3877f10a77bbSDavid C Somayajulu 	}
3878f10a77bbSDavid C Somayajulu 
3879f10a77bbSDavid C Somayajulu 	/*
3880f10a77bbSDavid C Somayajulu 	 * Allocate Memory for Minidump Template
3881f10a77bbSDavid C Somayajulu 	 */
3882f10a77bbSDavid C Somayajulu 
3883f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.minidump.alignment = 8;
3884f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.minidump.size = template_size;
3885f10a77bbSDavid C Somayajulu 
388635291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
3887f10a77bbSDavid C Somayajulu 	if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) {
3888f10a77bbSDavid C Somayajulu 
3889f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: minidump dma alloc failed\n", __func__);
3890f10a77bbSDavid C Somayajulu 
3891f10a77bbSDavid C Somayajulu 		return (-1);
3892f10a77bbSDavid C Somayajulu 	}
3893f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.flags.minidump = 1;
3894f10a77bbSDavid C Somayajulu 
3895f10a77bbSDavid C Somayajulu 	/*
3896f10a77bbSDavid C Somayajulu 	 * Retrieve Minidump Template
3897f10a77bbSDavid C Somayajulu 	 */
38986a62bec0SDavid C Somayajulu 	ret = ql_get_minidump_template(ha);
389935291c22SDavid C Somayajulu #else
390035291c22SDavid C Somayajulu 	ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump;
39016a62bec0SDavid C Somayajulu 
390235291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
3903f10a77bbSDavid C Somayajulu 
39046a62bec0SDavid C Somayajulu 	if (ret == 0) {
39056a62bec0SDavid C Somayajulu 
39066a62bec0SDavid C Somayajulu 		ret = ql_validate_minidump_checksum(ha);
39076a62bec0SDavid C Somayajulu 
39086a62bec0SDavid C Somayajulu 		if (ret == 0) {
39096a62bec0SDavid C Somayajulu 
39106a62bec0SDavid C Somayajulu 			ret = ql_alloc_minidump_buffers(ha);
39116a62bec0SDavid C Somayajulu 
39126a62bec0SDavid C Somayajulu 			if (ret == 0)
3913f10a77bbSDavid C Somayajulu 		ha->hw.mdump_init = 1;
39146a62bec0SDavid C Somayajulu 			else
39156a62bec0SDavid C Somayajulu 				device_printf(dev,
39166a62bec0SDavid C Somayajulu 					"%s: ql_alloc_minidump_buffers"
39176a62bec0SDavid C Somayajulu 					" failed\n", __func__);
39186a62bec0SDavid C Somayajulu 		} else {
39196a62bec0SDavid C Somayajulu 			device_printf(dev, "%s: ql_validate_minidump_checksum"
39206a62bec0SDavid C Somayajulu 				" failed\n", __func__);
3921f10a77bbSDavid C Somayajulu 		}
39226a62bec0SDavid C Somayajulu 	} else {
39236a62bec0SDavid C Somayajulu 		device_printf(dev, "%s: ql_get_minidump_template failed\n",
39246a62bec0SDavid C Somayajulu 			 __func__);
39256a62bec0SDavid C Somayajulu 	}
39266a62bec0SDavid C Somayajulu 
39276a62bec0SDavid C Somayajulu 	if (ret)
39286a62bec0SDavid C Somayajulu 		ql_minidump_free(ha);
3929f10a77bbSDavid C Somayajulu 
3930f10a77bbSDavid C Somayajulu 	return (ret);
3931f10a77bbSDavid C Somayajulu }
3932f10a77bbSDavid C Somayajulu 
3933f10a77bbSDavid C Somayajulu static void
39346a62bec0SDavid C Somayajulu ql_minidump_free(qla_host_t *ha)
3935f10a77bbSDavid C Somayajulu {
3936f10a77bbSDavid C Somayajulu 	ha->hw.mdump_init = 0;
3937f10a77bbSDavid C Somayajulu 	if (ha->hw.dma_buf.flags.minidump) {
3938f10a77bbSDavid C Somayajulu 		ha->hw.dma_buf.flags.minidump = 0;
3939f10a77bbSDavid C Somayajulu 		ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump);
3940f10a77bbSDavid C Somayajulu 	}
39416a62bec0SDavid C Somayajulu 
39426a62bec0SDavid C Somayajulu 	ql_free_minidump_template_buffer(ha);
39436a62bec0SDavid C Somayajulu 	ql_free_minidump_buffer(ha);
39446a62bec0SDavid C Somayajulu 
3945f10a77bbSDavid C Somayajulu 	return;
3946f10a77bbSDavid C Somayajulu }
3947f10a77bbSDavid C Somayajulu 
3948f10a77bbSDavid C Somayajulu void
3949f10a77bbSDavid C Somayajulu ql_minidump(qla_host_t *ha)
3950f10a77bbSDavid C Somayajulu {
3951f10a77bbSDavid C Somayajulu 	if (!ha->hw.mdump_init)
3952f10a77bbSDavid C Somayajulu 		return;
3953f10a77bbSDavid C Somayajulu 
39546a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_done)
3955f10a77bbSDavid C Somayajulu 		return;
3956f10a77bbSDavid C Somayajulu 
3957f10a77bbSDavid C Somayajulu 		ha->hw.mdump_start_seq_index = ql_stop_sequence(ha);
3958f10a77bbSDavid C Somayajulu 
39596a62bec0SDavid C Somayajulu 	bzero(ha->hw.mdump_buffer, ha->hw.mdump_buffer_size);
39606a62bec0SDavid C Somayajulu 	bzero(ha->hw.mdump_template, ha->hw.mdump_template_size);
39616a62bec0SDavid C Somayajulu 
39626a62bec0SDavid C Somayajulu 	bcopy(ha->hw.dma_buf.minidump.dma_b, ha->hw.mdump_template,
39636a62bec0SDavid C Somayajulu 		ha->hw.mdump_template_size);
39646a62bec0SDavid C Somayajulu 
39656a62bec0SDavid C Somayajulu 	ql_parse_template(ha);
39666a62bec0SDavid C Somayajulu 
3967f10a77bbSDavid C Somayajulu 	ql_start_sequence(ha, ha->hw.mdump_start_seq_index);
3968f10a77bbSDavid C Somayajulu 
39696a62bec0SDavid C Somayajulu 	ha->hw.mdump_done = 1;
39706a62bec0SDavid C Somayajulu 
3971f10a77bbSDavid C Somayajulu 	return;
3972f10a77bbSDavid C Somayajulu }
39736a62bec0SDavid C Somayajulu 
39746a62bec0SDavid C Somayajulu 
39756a62bec0SDavid C Somayajulu /*
39766a62bec0SDavid C Somayajulu  * helper routines
39776a62bec0SDavid C Somayajulu  */
39786a62bec0SDavid C Somayajulu static void
39796a62bec0SDavid C Somayajulu ql_entry_err_chk(ql_minidump_entry_t *entry, uint32_t esize)
39806a62bec0SDavid C Somayajulu {
39816a62bec0SDavid C Somayajulu 	if (esize != entry->hdr.entry_capture_size) {
39826a62bec0SDavid C Somayajulu 		entry->hdr.entry_capture_size = esize;
39836a62bec0SDavid C Somayajulu 		entry->hdr.driver_flags |= QL_DBG_SIZE_ERR_FLAG;
39846a62bec0SDavid C Somayajulu 	}
39856a62bec0SDavid C Somayajulu 	return;
39866a62bec0SDavid C Somayajulu }
39876a62bec0SDavid C Somayajulu 
39886a62bec0SDavid C Somayajulu 
39896a62bec0SDavid C Somayajulu static int
39906a62bec0SDavid C Somayajulu ql_parse_template(qla_host_t *ha)
39916a62bec0SDavid C Somayajulu {
39926a62bec0SDavid C Somayajulu 	uint32_t num_of_entries, buff_level, e_cnt, esize;
39936a62bec0SDavid C Somayajulu 	uint32_t end_cnt, rv = 0;
39946a62bec0SDavid C Somayajulu 	char *dump_buff, *dbuff;
39956a62bec0SDavid C Somayajulu 	int sane_start = 0, sane_end = 0;
39966a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *template_hdr;
39976a62bec0SDavid C Somayajulu 	ql_minidump_entry_t *entry;
39986a62bec0SDavid C Somayajulu 	uint32_t capture_mask;
39996a62bec0SDavid C Somayajulu 	uint32_t dump_size;
40006a62bec0SDavid C Somayajulu 
40016a62bec0SDavid C Somayajulu 	/* Setup parameters */
40026a62bec0SDavid C Somayajulu 	template_hdr = (ql_minidump_template_hdr_t *)ha->hw.mdump_template;
40036a62bec0SDavid C Somayajulu 
40046a62bec0SDavid C Somayajulu 	if (template_hdr->entry_type == TLHDR)
40056a62bec0SDavid C Somayajulu 		sane_start = 1;
40066a62bec0SDavid C Somayajulu 
40076a62bec0SDavid C Somayajulu 	dump_buff = (char *) ha->hw.mdump_buffer;
40086a62bec0SDavid C Somayajulu 
40096a62bec0SDavid C Somayajulu 	num_of_entries = template_hdr->num_of_entries;
40106a62bec0SDavid C Somayajulu 
40116a62bec0SDavid C Somayajulu 	entry = (ql_minidump_entry_t *) ((char *)template_hdr
40126a62bec0SDavid C Somayajulu 			+ template_hdr->first_entry_offset );
40136a62bec0SDavid C Somayajulu 
40146a62bec0SDavid C Somayajulu 	template_hdr->saved_state_array[QL_OCM0_ADDR_INDX] =
40156a62bec0SDavid C Somayajulu 		template_hdr->ocm_window_array[ha->pci_func];
40166a62bec0SDavid C Somayajulu 	template_hdr->saved_state_array[QL_PCIE_FUNC_INDX] = ha->pci_func;
40176a62bec0SDavid C Somayajulu 
40186a62bec0SDavid C Somayajulu 	capture_mask = ha->hw.mdump_capture_mask;
40196a62bec0SDavid C Somayajulu 	dump_size = ha->hw.mdump_buffer_size;
40206a62bec0SDavid C Somayajulu 
40216a62bec0SDavid C Somayajulu 	template_hdr->driver_capture_mask = capture_mask;
40226a62bec0SDavid C Somayajulu 
40236a62bec0SDavid C Somayajulu 	QL_DPRINT80(ha, (ha->pci_dev,
40246a62bec0SDavid C Somayajulu 		"%s: sane_start = %d num_of_entries = %d "
40256a62bec0SDavid C Somayajulu 		"capture_mask = 0x%x dump_size = %d \n",
40266a62bec0SDavid C Somayajulu 		__func__, sane_start, num_of_entries, capture_mask, dump_size));
40276a62bec0SDavid C Somayajulu 
40286a62bec0SDavid C Somayajulu 	for (buff_level = 0, e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
40296a62bec0SDavid C Somayajulu 
40306a62bec0SDavid C Somayajulu 		/*
40316a62bec0SDavid C Somayajulu 		 * If the capture_mask of the entry does not match capture mask
40326a62bec0SDavid C Somayajulu 		 * skip the entry after marking the driver_flags indicator.
40336a62bec0SDavid C Somayajulu 		 */
40346a62bec0SDavid C Somayajulu 
40356a62bec0SDavid C Somayajulu 		if (!(entry->hdr.entry_capture_mask & capture_mask)) {
40366a62bec0SDavid C Somayajulu 
40376a62bec0SDavid C Somayajulu 			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
40386a62bec0SDavid C Somayajulu 			entry = (ql_minidump_entry_t *) ((char *) entry
40396a62bec0SDavid C Somayajulu 					+ entry->hdr.entry_size);
40406a62bec0SDavid C Somayajulu 			continue;
40416a62bec0SDavid C Somayajulu 		}
40426a62bec0SDavid C Somayajulu 
40436a62bec0SDavid C Somayajulu 		/*
40446a62bec0SDavid C Somayajulu 		 * This is ONLY needed in implementations where
40456a62bec0SDavid C Somayajulu 		 * the capture buffer allocated is too small to capture
40466a62bec0SDavid C Somayajulu 		 * all of the required entries for a given capture mask.
40476a62bec0SDavid C Somayajulu 		 * We need to empty the buffer contents to a file
40486a62bec0SDavid C Somayajulu 		 * if possible, before processing the next entry
40496a62bec0SDavid C Somayajulu 		 * If the buff_full_flag is set, no further capture will happen
40506a62bec0SDavid C Somayajulu 		 * and all remaining non-control entries will be skipped.
40516a62bec0SDavid C Somayajulu 		 */
40526a62bec0SDavid C Somayajulu 		if (entry->hdr.entry_capture_size != 0) {
40536a62bec0SDavid C Somayajulu 			if ((buff_level + entry->hdr.entry_capture_size) >
40546a62bec0SDavid C Somayajulu 				dump_size) {
40556a62bec0SDavid C Somayajulu 				/*  Try to recover by emptying buffer to file */
40566a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
40576a62bec0SDavid C Somayajulu 				entry = (ql_minidump_entry_t *) ((char *) entry
40586a62bec0SDavid C Somayajulu 						+ entry->hdr.entry_size);
40596a62bec0SDavid C Somayajulu 				continue;
40606a62bec0SDavid C Somayajulu 			}
40616a62bec0SDavid C Somayajulu 		}
40626a62bec0SDavid C Somayajulu 
40636a62bec0SDavid C Somayajulu 		/*
40646a62bec0SDavid C Somayajulu 		 * Decode the entry type and process it accordingly
40656a62bec0SDavid C Somayajulu 		 */
40666a62bec0SDavid C Somayajulu 
40676a62bec0SDavid C Somayajulu 		switch (entry->hdr.entry_type) {
40686a62bec0SDavid C Somayajulu 		case RDNOP:
40696a62bec0SDavid C Somayajulu 			break;
40706a62bec0SDavid C Somayajulu 
40716a62bec0SDavid C Somayajulu 		case RDEND:
40726a62bec0SDavid C Somayajulu 			if (sane_end == 0) {
40736a62bec0SDavid C Somayajulu 				end_cnt = e_cnt;
40746a62bec0SDavid C Somayajulu 			}
40756a62bec0SDavid C Somayajulu 			sane_end++;
40766a62bec0SDavid C Somayajulu 			break;
40776a62bec0SDavid C Somayajulu 
40786a62bec0SDavid C Somayajulu 		case RDCRB:
40796a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
40806a62bec0SDavid C Somayajulu 			esize = ql_rdcrb(ha, (void *)entry, (void *)dbuff);
40816a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
40826a62bec0SDavid C Somayajulu 			buff_level += esize;
40836a62bec0SDavid C Somayajulu 			break;
40846a62bec0SDavid C Somayajulu 
40856a62bec0SDavid C Somayajulu                 case POLLRD:
40866a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
40876a62bec0SDavid C Somayajulu                         esize = ql_pollrd(ha, (void *)entry, (void *)dbuff);
40886a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
40896a62bec0SDavid C Somayajulu                         buff_level += esize;
40906a62bec0SDavid C Somayajulu                         break;
40916a62bec0SDavid C Somayajulu 
40926a62bec0SDavid C Somayajulu                 case POLLRDMWR:
40936a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
40946a62bec0SDavid C Somayajulu                         esize = ql_pollrd_modify_write(ha, (void *)entry,
40956a62bec0SDavid C Somayajulu 					(void *)dbuff);
40966a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
40976a62bec0SDavid C Somayajulu                         buff_level += esize;
40986a62bec0SDavid C Somayajulu                         break;
40996a62bec0SDavid C Somayajulu 
41006a62bec0SDavid C Somayajulu 		case L2ITG:
41016a62bec0SDavid C Somayajulu 		case L2DTG:
41026a62bec0SDavid C Somayajulu 		case L2DAT:
41036a62bec0SDavid C Somayajulu 		case L2INS:
41046a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
41056a62bec0SDavid C Somayajulu 			esize = ql_L2Cache(ha, (void *)entry, (void *)dbuff);
41066a62bec0SDavid C Somayajulu 			if (esize == -1) {
41076a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
41086a62bec0SDavid C Somayajulu 			} else {
41096a62bec0SDavid C Somayajulu 				ql_entry_err_chk(entry, esize);
41106a62bec0SDavid C Somayajulu 				buff_level += esize;
41116a62bec0SDavid C Somayajulu 			}
41126a62bec0SDavid C Somayajulu 			break;
41136a62bec0SDavid C Somayajulu 
41146a62bec0SDavid C Somayajulu 		case L1DAT:
41156a62bec0SDavid C Somayajulu 		case L1INS:
41166a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
41176a62bec0SDavid C Somayajulu 			esize = ql_L1Cache(ha, (void *)entry, (void *)dbuff);
41186a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
41196a62bec0SDavid C Somayajulu 			buff_level += esize;
41206a62bec0SDavid C Somayajulu 			break;
41216a62bec0SDavid C Somayajulu 
41226a62bec0SDavid C Somayajulu 		case RDOCM:
41236a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
41246a62bec0SDavid C Somayajulu 			esize = ql_rdocm(ha, (void *)entry, (void *)dbuff);
41256a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
41266a62bec0SDavid C Somayajulu 			buff_level += esize;
41276a62bec0SDavid C Somayajulu 			break;
41286a62bec0SDavid C Somayajulu 
41296a62bec0SDavid C Somayajulu 		case RDMEM:
41306a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
41316a62bec0SDavid C Somayajulu 			esize = ql_rdmem(ha, (void *)entry, (void *)dbuff);
41326a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
41336a62bec0SDavid C Somayajulu 			buff_level += esize;
41346a62bec0SDavid C Somayajulu 			break;
41356a62bec0SDavid C Somayajulu 
41366a62bec0SDavid C Somayajulu 		case BOARD:
41376a62bec0SDavid C Somayajulu 		case RDROM:
41386a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
41396a62bec0SDavid C Somayajulu 			esize = ql_rdrom(ha, (void *)entry, (void *)dbuff);
41406a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
41416a62bec0SDavid C Somayajulu 			buff_level += esize;
41426a62bec0SDavid C Somayajulu 			break;
41436a62bec0SDavid C Somayajulu 
41446a62bec0SDavid C Somayajulu 		case RDMUX:
41456a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
41466a62bec0SDavid C Somayajulu 			esize = ql_rdmux(ha, (void *)entry, (void *)dbuff);
41476a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
41486a62bec0SDavid C Somayajulu 			buff_level += esize;
41496a62bec0SDavid C Somayajulu 			break;
41506a62bec0SDavid C Somayajulu 
41516a62bec0SDavid C Somayajulu                 case RDMUX2:
41526a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
41536a62bec0SDavid C Somayajulu                         esize = ql_rdmux2(ha, (void *)entry, (void *)dbuff);
41546a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
41556a62bec0SDavid C Somayajulu                         buff_level += esize;
41566a62bec0SDavid C Somayajulu                         break;
41576a62bec0SDavid C Somayajulu 
41586a62bec0SDavid C Somayajulu 		case QUEUE:
41596a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
41606a62bec0SDavid C Somayajulu 			esize = ql_rdqueue(ha, (void *)entry, (void *)dbuff);
41616a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
41626a62bec0SDavid C Somayajulu 			buff_level += esize;
41636a62bec0SDavid C Somayajulu 			break;
41646a62bec0SDavid C Somayajulu 
41656a62bec0SDavid C Somayajulu 		case CNTRL:
41666a62bec0SDavid C Somayajulu 			if ((rv = ql_cntrl(ha, template_hdr, (void *)entry))) {
41676a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
41686a62bec0SDavid C Somayajulu 			}
41696a62bec0SDavid C Somayajulu 			break;
41706a62bec0SDavid C Somayajulu 		default:
41716a62bec0SDavid C Somayajulu 			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
41726a62bec0SDavid C Somayajulu 			break;
41736a62bec0SDavid C Somayajulu 		}
41746a62bec0SDavid C Somayajulu 		/*  next entry in the template */
41756a62bec0SDavid C Somayajulu 		entry = (ql_minidump_entry_t *) ((char *) entry
41766a62bec0SDavid C Somayajulu 						+ entry->hdr.entry_size);
41776a62bec0SDavid C Somayajulu 	}
41786a62bec0SDavid C Somayajulu 
41796a62bec0SDavid C Somayajulu 	if (!sane_start || (sane_end > 1)) {
41806a62bec0SDavid C Somayajulu 		device_printf(ha->pci_dev,
41816a62bec0SDavid C Somayajulu 			"\n%s: Template configuration error. Check Template\n",
41826a62bec0SDavid C Somayajulu 			__func__);
41836a62bec0SDavid C Somayajulu 	}
41846a62bec0SDavid C Somayajulu 
41856a62bec0SDavid C Somayajulu 	QL_DPRINT80(ha, (ha->pci_dev, "%s: Minidump num of entries = %d\n",
41866a62bec0SDavid C Somayajulu 		__func__, template_hdr->num_of_entries));
41876a62bec0SDavid C Somayajulu 
41886a62bec0SDavid C Somayajulu 	return 0;
41896a62bec0SDavid C Somayajulu }
41906a62bec0SDavid C Somayajulu 
41916a62bec0SDavid C Somayajulu /*
41926a62bec0SDavid C Somayajulu  * Read CRB operation.
41936a62bec0SDavid C Somayajulu  */
41946a62bec0SDavid C Somayajulu static uint32_t
41956a62bec0SDavid C Somayajulu ql_rdcrb(qla_host_t *ha, ql_minidump_entry_rdcrb_t * crb_entry,
41966a62bec0SDavid C Somayajulu 	uint32_t * data_buff)
41976a62bec0SDavid C Somayajulu {
41986a62bec0SDavid C Somayajulu 	int loop_cnt;
41996a62bec0SDavid C Somayajulu 	int ret;
42006a62bec0SDavid C Somayajulu 	uint32_t op_count, addr, stride, value = 0;
42016a62bec0SDavid C Somayajulu 
42026a62bec0SDavid C Somayajulu 	addr = crb_entry->addr;
42036a62bec0SDavid C Somayajulu 	op_count = crb_entry->op_count;
42046a62bec0SDavid C Somayajulu 	stride = crb_entry->addr_stride;
42056a62bec0SDavid C Somayajulu 
42066a62bec0SDavid C Somayajulu 	for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
42076a62bec0SDavid C Somayajulu 
42086a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr, &value, 1);
42096a62bec0SDavid C Somayajulu 
42106a62bec0SDavid C Somayajulu 		if (ret)
42116a62bec0SDavid C Somayajulu 			return (0);
42126a62bec0SDavid C Somayajulu 
42136a62bec0SDavid C Somayajulu 		*data_buff++ = addr;
42146a62bec0SDavid C Somayajulu 		*data_buff++ = value;
42156a62bec0SDavid C Somayajulu 		addr = addr + stride;
42166a62bec0SDavid C Somayajulu 	}
42176a62bec0SDavid C Somayajulu 
42186a62bec0SDavid C Somayajulu 	/*
42196a62bec0SDavid C Somayajulu 	 * for testing purpose we return amount of data written
42206a62bec0SDavid C Somayajulu 	 */
42216a62bec0SDavid C Somayajulu 	return (op_count * (2 * sizeof(uint32_t)));
42226a62bec0SDavid C Somayajulu }
42236a62bec0SDavid C Somayajulu 
42246a62bec0SDavid C Somayajulu /*
42256a62bec0SDavid C Somayajulu  * Handle L2 Cache.
42266a62bec0SDavid C Somayajulu  */
42276a62bec0SDavid C Somayajulu 
42286a62bec0SDavid C Somayajulu static uint32_t
42296a62bec0SDavid C Somayajulu ql_L2Cache(qla_host_t *ha, ql_minidump_entry_cache_t *cacheEntry,
42306a62bec0SDavid C Somayajulu 	uint32_t * data_buff)
42316a62bec0SDavid C Somayajulu {
42326a62bec0SDavid C Somayajulu 	int i, k;
42336a62bec0SDavid C Somayajulu 	int loop_cnt;
42346a62bec0SDavid C Somayajulu 	int ret;
42356a62bec0SDavid C Somayajulu 
42366a62bec0SDavid C Somayajulu 	uint32_t read_value;
42376a62bec0SDavid C Somayajulu 	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr, cntl_value_w;
42386a62bec0SDavid C Somayajulu 	uint32_t tag_value, read_cnt;
42396a62bec0SDavid C Somayajulu 	volatile uint8_t cntl_value_r;
42406a62bec0SDavid C Somayajulu 	long timeout;
42416a62bec0SDavid C Somayajulu 	uint32_t data;
42426a62bec0SDavid C Somayajulu 
42436a62bec0SDavid C Somayajulu 	loop_cnt = cacheEntry->op_count;
42446a62bec0SDavid C Somayajulu 
42456a62bec0SDavid C Somayajulu 	read_addr = cacheEntry->read_addr;
42466a62bec0SDavid C Somayajulu 	cntrl_addr = cacheEntry->control_addr;
42476a62bec0SDavid C Somayajulu 	cntl_value_w = (uint32_t) cacheEntry->write_value;
42486a62bec0SDavid C Somayajulu 
42496a62bec0SDavid C Somayajulu 	tag_reg_addr = cacheEntry->tag_reg_addr;
42506a62bec0SDavid C Somayajulu 
42516a62bec0SDavid C Somayajulu 	tag_value = cacheEntry->init_tag_value;
42526a62bec0SDavid C Somayajulu 	read_cnt = cacheEntry->read_addr_cnt;
42536a62bec0SDavid C Somayajulu 
42546a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
42556a62bec0SDavid C Somayajulu 
42566a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
42576a62bec0SDavid C Somayajulu 		if (ret)
42586a62bec0SDavid C Somayajulu 			return (0);
42596a62bec0SDavid C Somayajulu 
42606a62bec0SDavid C Somayajulu 		if (cacheEntry->write_value != 0) {
42616a62bec0SDavid C Somayajulu 
42626a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, cntrl_addr,
42636a62bec0SDavid C Somayajulu 					&cntl_value_w, 0);
42646a62bec0SDavid C Somayajulu 			if (ret)
42656a62bec0SDavid C Somayajulu 				return (0);
42666a62bec0SDavid C Somayajulu 		}
42676a62bec0SDavid C Somayajulu 
42686a62bec0SDavid C Somayajulu 		if (cacheEntry->poll_mask != 0) {
42696a62bec0SDavid C Somayajulu 
42706a62bec0SDavid C Somayajulu 			timeout = cacheEntry->poll_wait;
42716a62bec0SDavid C Somayajulu 
42726a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, cntrl_addr, &data, 1);
42736a62bec0SDavid C Somayajulu 			if (ret)
42746a62bec0SDavid C Somayajulu 				return (0);
42756a62bec0SDavid C Somayajulu 
42766a62bec0SDavid C Somayajulu 			cntl_value_r = (uint8_t)data;
42776a62bec0SDavid C Somayajulu 
42786a62bec0SDavid C Somayajulu 			while ((cntl_value_r & cacheEntry->poll_mask) != 0) {
42796a62bec0SDavid C Somayajulu 
42806a62bec0SDavid C Somayajulu 				if (timeout) {
42816a62bec0SDavid C Somayajulu 					qla_mdelay(__func__, 1);
42826a62bec0SDavid C Somayajulu 					timeout--;
42836a62bec0SDavid C Somayajulu 				} else
42846a62bec0SDavid C Somayajulu 					break;
42856a62bec0SDavid C Somayajulu 
42866a62bec0SDavid C Somayajulu 				ret = ql_rdwr_indreg32(ha, cntrl_addr,
42876a62bec0SDavid C Somayajulu 						&data, 1);
42886a62bec0SDavid C Somayajulu 				if (ret)
42896a62bec0SDavid C Somayajulu 					return (0);
42906a62bec0SDavid C Somayajulu 
42916a62bec0SDavid C Somayajulu 				cntl_value_r = (uint8_t)data;
42926a62bec0SDavid C Somayajulu 			}
42936a62bec0SDavid C Somayajulu 			if (!timeout) {
42946a62bec0SDavid C Somayajulu 				/* Report timeout error.
42956a62bec0SDavid C Somayajulu 				 * core dump capture failed
42966a62bec0SDavid C Somayajulu 				 * Skip remaining entries.
42976a62bec0SDavid C Somayajulu 				 * Write buffer out to file
42986a62bec0SDavid C Somayajulu 				 * Use driver specific fields in template header
42996a62bec0SDavid C Somayajulu 				 * to report this error.
43006a62bec0SDavid C Somayajulu 				 */
43016a62bec0SDavid C Somayajulu 				return (-1);
43026a62bec0SDavid C Somayajulu 			}
43036a62bec0SDavid C Somayajulu 		}
43046a62bec0SDavid C Somayajulu 
43056a62bec0SDavid C Somayajulu 		addr = read_addr;
43066a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
43076a62bec0SDavid C Somayajulu 
43086a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
43096a62bec0SDavid C Somayajulu 			if (ret)
43106a62bec0SDavid C Somayajulu 				return (0);
43116a62bec0SDavid C Somayajulu 
43126a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
43136a62bec0SDavid C Somayajulu 			addr += cacheEntry->read_addr_stride;
43146a62bec0SDavid C Somayajulu 		}
43156a62bec0SDavid C Somayajulu 
43166a62bec0SDavid C Somayajulu 		tag_value += cacheEntry->tag_value_stride;
43176a62bec0SDavid C Somayajulu 	}
43186a62bec0SDavid C Somayajulu 
43196a62bec0SDavid C Somayajulu 	return (read_cnt * loop_cnt * sizeof(uint32_t));
43206a62bec0SDavid C Somayajulu }
43216a62bec0SDavid C Somayajulu 
43226a62bec0SDavid C Somayajulu /*
43236a62bec0SDavid C Somayajulu  * Handle L1 Cache.
43246a62bec0SDavid C Somayajulu  */
43256a62bec0SDavid C Somayajulu 
43266a62bec0SDavid C Somayajulu static uint32_t
43276a62bec0SDavid C Somayajulu ql_L1Cache(qla_host_t *ha,
43286a62bec0SDavid C Somayajulu 	ql_minidump_entry_cache_t *cacheEntry,
43296a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
43306a62bec0SDavid C Somayajulu {
43316a62bec0SDavid C Somayajulu 	int ret;
43326a62bec0SDavid C Somayajulu 	int i, k;
43336a62bec0SDavid C Somayajulu 	int loop_cnt;
43346a62bec0SDavid C Somayajulu 
43356a62bec0SDavid C Somayajulu 	uint32_t read_value;
43366a62bec0SDavid C Somayajulu 	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr;
43376a62bec0SDavid C Somayajulu 	uint32_t tag_value, read_cnt;
43386a62bec0SDavid C Somayajulu 	uint32_t cntl_value_w;
43396a62bec0SDavid C Somayajulu 
43406a62bec0SDavid C Somayajulu 	loop_cnt = cacheEntry->op_count;
43416a62bec0SDavid C Somayajulu 
43426a62bec0SDavid C Somayajulu 	read_addr = cacheEntry->read_addr;
43436a62bec0SDavid C Somayajulu 	cntrl_addr = cacheEntry->control_addr;
43446a62bec0SDavid C Somayajulu 	cntl_value_w = (uint32_t) cacheEntry->write_value;
43456a62bec0SDavid C Somayajulu 
43466a62bec0SDavid C Somayajulu 	tag_reg_addr = cacheEntry->tag_reg_addr;
43476a62bec0SDavid C Somayajulu 
43486a62bec0SDavid C Somayajulu 	tag_value = cacheEntry->init_tag_value;
43496a62bec0SDavid C Somayajulu 	read_cnt = cacheEntry->read_addr_cnt;
43506a62bec0SDavid C Somayajulu 
43516a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
43526a62bec0SDavid C Somayajulu 
43536a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
43546a62bec0SDavid C Somayajulu 		if (ret)
43556a62bec0SDavid C Somayajulu 			return (0);
43566a62bec0SDavid C Somayajulu 
43576a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, cntrl_addr, &cntl_value_w, 0);
43586a62bec0SDavid C Somayajulu 		if (ret)
43596a62bec0SDavid C Somayajulu 			return (0);
43606a62bec0SDavid C Somayajulu 
43616a62bec0SDavid C Somayajulu 		addr = read_addr;
43626a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
43636a62bec0SDavid C Somayajulu 
43646a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
43656a62bec0SDavid C Somayajulu 			if (ret)
43666a62bec0SDavid C Somayajulu 				return (0);
43676a62bec0SDavid C Somayajulu 
43686a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
43696a62bec0SDavid C Somayajulu 			addr += cacheEntry->read_addr_stride;
43706a62bec0SDavid C Somayajulu 		}
43716a62bec0SDavid C Somayajulu 
43726a62bec0SDavid C Somayajulu 		tag_value += cacheEntry->tag_value_stride;
43736a62bec0SDavid C Somayajulu 	}
43746a62bec0SDavid C Somayajulu 
43756a62bec0SDavid C Somayajulu 	return (read_cnt * loop_cnt * sizeof(uint32_t));
43766a62bec0SDavid C Somayajulu }
43776a62bec0SDavid C Somayajulu 
43786a62bec0SDavid C Somayajulu /*
43796a62bec0SDavid C Somayajulu  * Reading OCM memory
43806a62bec0SDavid C Somayajulu  */
43816a62bec0SDavid C Somayajulu 
43826a62bec0SDavid C Somayajulu static uint32_t
43836a62bec0SDavid C Somayajulu ql_rdocm(qla_host_t *ha,
43846a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdocm_t *ocmEntry,
43856a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
43866a62bec0SDavid C Somayajulu {
43876a62bec0SDavid C Somayajulu 	int i, loop_cnt;
43886a62bec0SDavid C Somayajulu 	volatile uint32_t addr;
43896a62bec0SDavid C Somayajulu 	volatile uint32_t value;
43906a62bec0SDavid C Somayajulu 
43916a62bec0SDavid C Somayajulu 	addr = ocmEntry->read_addr;
43926a62bec0SDavid C Somayajulu 	loop_cnt = ocmEntry->op_count;
43936a62bec0SDavid C Somayajulu 
43946a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
43956a62bec0SDavid C Somayajulu 		value = READ_REG32(ha, addr);
43966a62bec0SDavid C Somayajulu 		*data_buff++ = value;
43976a62bec0SDavid C Somayajulu 		addr += ocmEntry->read_addr_stride;
43986a62bec0SDavid C Somayajulu 	}
43996a62bec0SDavid C Somayajulu 	return (loop_cnt * sizeof(value));
44006a62bec0SDavid C Somayajulu }
44016a62bec0SDavid C Somayajulu 
44026a62bec0SDavid C Somayajulu /*
44036a62bec0SDavid C Somayajulu  * Read memory
44046a62bec0SDavid C Somayajulu  */
44056a62bec0SDavid C Somayajulu 
44066a62bec0SDavid C Somayajulu static uint32_t
44076a62bec0SDavid C Somayajulu ql_rdmem(qla_host_t *ha,
44086a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdmem_t *mem_entry,
44096a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
44106a62bec0SDavid C Somayajulu {
44116a62bec0SDavid C Somayajulu 	int ret;
44126a62bec0SDavid C Somayajulu         int i, loop_cnt;
44136a62bec0SDavid C Somayajulu         volatile uint32_t addr;
44146a62bec0SDavid C Somayajulu 	q80_offchip_mem_val_t val;
44156a62bec0SDavid C Somayajulu 
44166a62bec0SDavid C Somayajulu         addr = mem_entry->read_addr;
44176a62bec0SDavid C Somayajulu 
44186a62bec0SDavid C Somayajulu 	/* size in bytes / 16 */
44196a62bec0SDavid C Somayajulu         loop_cnt = mem_entry->read_data_size / (sizeof(uint32_t) * 4);
44206a62bec0SDavid C Somayajulu 
44216a62bec0SDavid C Somayajulu         for (i = 0; i < loop_cnt; i++) {
44226a62bec0SDavid C Somayajulu 
44236a62bec0SDavid C Somayajulu 		ret = ql_rdwr_offchip_mem(ha, (addr & 0x0ffffffff), &val, 1);
44246a62bec0SDavid C Somayajulu 		if (ret)
44256a62bec0SDavid C Somayajulu 			return (0);
44266a62bec0SDavid C Somayajulu 
44276a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_lo;
44286a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_hi;
44296a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_ulo;
44306a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_uhi;
44316a62bec0SDavid C Somayajulu 
44326a62bec0SDavid C Somayajulu                 addr += (sizeof(uint32_t) * 4);
44336a62bec0SDavid C Somayajulu         }
44346a62bec0SDavid C Somayajulu 
44356a62bec0SDavid C Somayajulu         return (loop_cnt * (sizeof(uint32_t) * 4));
44366a62bec0SDavid C Somayajulu }
44376a62bec0SDavid C Somayajulu 
44386a62bec0SDavid C Somayajulu /*
44396a62bec0SDavid C Somayajulu  * Read Rom
44406a62bec0SDavid C Somayajulu  */
44416a62bec0SDavid C Somayajulu 
44426a62bec0SDavid C Somayajulu static uint32_t
44436a62bec0SDavid C Somayajulu ql_rdrom(qla_host_t *ha,
44446a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdrom_t *romEntry,
44456a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
44466a62bec0SDavid C Somayajulu {
44476a62bec0SDavid C Somayajulu 	int ret;
44486a62bec0SDavid C Somayajulu 	int i, loop_cnt;
44496a62bec0SDavid C Somayajulu 	uint32_t addr;
44506a62bec0SDavid C Somayajulu 	uint32_t value;
44516a62bec0SDavid C Somayajulu 
44526a62bec0SDavid C Somayajulu 	addr = romEntry->read_addr;
44536a62bec0SDavid C Somayajulu 	loop_cnt = romEntry->read_data_size; /* This is size in bytes */
44546a62bec0SDavid C Somayajulu 	loop_cnt /= sizeof(value);
44556a62bec0SDavid C Somayajulu 
44566a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
44576a62bec0SDavid C Somayajulu 
44586a62bec0SDavid C Somayajulu 		ret = ql_rd_flash32(ha, addr, &value);
44596a62bec0SDavid C Somayajulu 		if (ret)
44606a62bec0SDavid C Somayajulu 			return (0);
44616a62bec0SDavid C Somayajulu 
44626a62bec0SDavid C Somayajulu 		*data_buff++ = value;
44636a62bec0SDavid C Somayajulu 		addr += sizeof(value);
44646a62bec0SDavid C Somayajulu 	}
44656a62bec0SDavid C Somayajulu 
44666a62bec0SDavid C Somayajulu 	return (loop_cnt * sizeof(value));
44676a62bec0SDavid C Somayajulu }
44686a62bec0SDavid C Somayajulu 
44696a62bec0SDavid C Somayajulu /*
44706a62bec0SDavid C Somayajulu  * Read MUX data
44716a62bec0SDavid C Somayajulu  */
44726a62bec0SDavid C Somayajulu 
44736a62bec0SDavid C Somayajulu static uint32_t
44746a62bec0SDavid C Somayajulu ql_rdmux(qla_host_t *ha,
44756a62bec0SDavid C Somayajulu 	ql_minidump_entry_mux_t *muxEntry,
44766a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
44776a62bec0SDavid C Somayajulu {
44786a62bec0SDavid C Somayajulu 	int ret;
44796a62bec0SDavid C Somayajulu 	int loop_cnt;
44806a62bec0SDavid C Somayajulu 	uint32_t read_value, sel_value;
44816a62bec0SDavid C Somayajulu 	uint32_t read_addr, select_addr;
44826a62bec0SDavid C Somayajulu 
44836a62bec0SDavid C Somayajulu 	select_addr = muxEntry->select_addr;
44846a62bec0SDavid C Somayajulu 	sel_value = muxEntry->select_value;
44856a62bec0SDavid C Somayajulu 	read_addr = muxEntry->read_addr;
44866a62bec0SDavid C Somayajulu 
44876a62bec0SDavid C Somayajulu 	for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
44886a62bec0SDavid C Somayajulu 
44896a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr, &sel_value, 0);
44906a62bec0SDavid C Somayajulu 		if (ret)
44916a62bec0SDavid C Somayajulu 			return (0);
44926a62bec0SDavid C Somayajulu 
44936a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
44946a62bec0SDavid C Somayajulu 		if (ret)
44956a62bec0SDavid C Somayajulu 			return (0);
44966a62bec0SDavid C Somayajulu 
44976a62bec0SDavid C Somayajulu 		*data_buff++ = sel_value;
44986a62bec0SDavid C Somayajulu 		*data_buff++ = read_value;
44996a62bec0SDavid C Somayajulu 
45006a62bec0SDavid C Somayajulu 		sel_value += muxEntry->select_value_stride;
45016a62bec0SDavid C Somayajulu 	}
45026a62bec0SDavid C Somayajulu 
45036a62bec0SDavid C Somayajulu 	return (loop_cnt * (2 * sizeof(uint32_t)));
45046a62bec0SDavid C Somayajulu }
45056a62bec0SDavid C Somayajulu 
45066a62bec0SDavid C Somayajulu static uint32_t
45076a62bec0SDavid C Somayajulu ql_rdmux2(qla_host_t *ha,
45086a62bec0SDavid C Somayajulu 	ql_minidump_entry_mux2_t *muxEntry,
45096a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
45106a62bec0SDavid C Somayajulu {
45116a62bec0SDavid C Somayajulu 	int ret;
45126a62bec0SDavid C Somayajulu         int loop_cnt;
45136a62bec0SDavid C Somayajulu 
45146a62bec0SDavid C Somayajulu         uint32_t select_addr_1, select_addr_2;
45156a62bec0SDavid C Somayajulu         uint32_t select_value_1, select_value_2;
45166a62bec0SDavid C Somayajulu         uint32_t select_value_count, select_value_mask;
45176a62bec0SDavid C Somayajulu         uint32_t read_addr, read_value;
45186a62bec0SDavid C Somayajulu 
45196a62bec0SDavid C Somayajulu         select_addr_1 = muxEntry->select_addr_1;
45206a62bec0SDavid C Somayajulu         select_addr_2 = muxEntry->select_addr_2;
45216a62bec0SDavid C Somayajulu         select_value_1 = muxEntry->select_value_1;
45226a62bec0SDavid C Somayajulu         select_value_2 = muxEntry->select_value_2;
45236a62bec0SDavid C Somayajulu         select_value_count = muxEntry->select_value_count;
45246a62bec0SDavid C Somayajulu         select_value_mask  = muxEntry->select_value_mask;
45256a62bec0SDavid C Somayajulu 
45266a62bec0SDavid C Somayajulu         read_addr = muxEntry->read_addr;
45276a62bec0SDavid C Somayajulu 
45286a62bec0SDavid C Somayajulu         for (loop_cnt = 0; loop_cnt < muxEntry->select_value_count;
45296a62bec0SDavid C Somayajulu 		loop_cnt++) {
45306a62bec0SDavid C Somayajulu 
45316a62bec0SDavid C Somayajulu                 uint32_t temp_sel_val;
45326a62bec0SDavid C Somayajulu 
45336a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_1, 0);
45346a62bec0SDavid C Somayajulu 		if (ret)
45356a62bec0SDavid C Somayajulu 			return (0);
45366a62bec0SDavid C Somayajulu 
45376a62bec0SDavid C Somayajulu                 temp_sel_val = select_value_1 & select_value_mask;
45386a62bec0SDavid C Somayajulu 
45396a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
45406a62bec0SDavid C Somayajulu 		if (ret)
45416a62bec0SDavid C Somayajulu 			return (0);
45426a62bec0SDavid C Somayajulu 
45436a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
45446a62bec0SDavid C Somayajulu 		if (ret)
45456a62bec0SDavid C Somayajulu 			return (0);
45466a62bec0SDavid C Somayajulu 
45476a62bec0SDavid C Somayajulu                 *data_buff++ = temp_sel_val;
45486a62bec0SDavid C Somayajulu                 *data_buff++ = read_value;
45496a62bec0SDavid C Somayajulu 
45506a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_2, 0);
45516a62bec0SDavid C Somayajulu 		if (ret)
45526a62bec0SDavid C Somayajulu 			return (0);
45536a62bec0SDavid C Somayajulu 
45546a62bec0SDavid C Somayajulu                 temp_sel_val = select_value_2 & select_value_mask;
45556a62bec0SDavid C Somayajulu 
45566a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
45576a62bec0SDavid C Somayajulu 		if (ret)
45586a62bec0SDavid C Somayajulu 			return (0);
45596a62bec0SDavid C Somayajulu 
45606a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
45616a62bec0SDavid C Somayajulu 		if (ret)
45626a62bec0SDavid C Somayajulu 			return (0);
45636a62bec0SDavid C Somayajulu 
45646a62bec0SDavid C Somayajulu                 *data_buff++ = temp_sel_val;
45656a62bec0SDavid C Somayajulu                 *data_buff++ = read_value;
45666a62bec0SDavid C Somayajulu 
45676a62bec0SDavid C Somayajulu                 select_value_1 += muxEntry->select_value_stride;
45686a62bec0SDavid C Somayajulu                 select_value_2 += muxEntry->select_value_stride;
45696a62bec0SDavid C Somayajulu         }
45706a62bec0SDavid C Somayajulu 
45716a62bec0SDavid C Somayajulu         return (loop_cnt * (4 * sizeof(uint32_t)));
45726a62bec0SDavid C Somayajulu }
45736a62bec0SDavid C Somayajulu 
45746a62bec0SDavid C Somayajulu /*
45756a62bec0SDavid C Somayajulu  * Handling Queue State Reads.
45766a62bec0SDavid C Somayajulu  */
45776a62bec0SDavid C Somayajulu 
45786a62bec0SDavid C Somayajulu static uint32_t
45796a62bec0SDavid C Somayajulu ql_rdqueue(qla_host_t *ha,
45806a62bec0SDavid C Somayajulu 	ql_minidump_entry_queue_t *queueEntry,
45816a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
45826a62bec0SDavid C Somayajulu {
45836a62bec0SDavid C Somayajulu 	int ret;
45846a62bec0SDavid C Somayajulu 	int loop_cnt, k;
45856a62bec0SDavid C Somayajulu 	uint32_t read_value;
45866a62bec0SDavid C Somayajulu 	uint32_t read_addr, read_stride, select_addr;
45876a62bec0SDavid C Somayajulu 	uint32_t queue_id, read_cnt;
45886a62bec0SDavid C Somayajulu 
45896a62bec0SDavid C Somayajulu 	read_cnt = queueEntry->read_addr_cnt;
45906a62bec0SDavid C Somayajulu 	read_stride = queueEntry->read_addr_stride;
45916a62bec0SDavid C Somayajulu 	select_addr = queueEntry->select_addr;
45926a62bec0SDavid C Somayajulu 
45936a62bec0SDavid C Somayajulu 	for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
45946a62bec0SDavid C Somayajulu 		loop_cnt++) {
45956a62bec0SDavid C Somayajulu 
45966a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr, &queue_id, 0);
45976a62bec0SDavid C Somayajulu 		if (ret)
45986a62bec0SDavid C Somayajulu 			return (0);
45996a62bec0SDavid C Somayajulu 
46006a62bec0SDavid C Somayajulu 		read_addr = queueEntry->read_addr;
46016a62bec0SDavid C Somayajulu 
46026a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
46036a62bec0SDavid C Somayajulu 
46046a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
46056a62bec0SDavid C Somayajulu 			if (ret)
46066a62bec0SDavid C Somayajulu 				return (0);
46076a62bec0SDavid C Somayajulu 
46086a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
46096a62bec0SDavid C Somayajulu 			read_addr += read_stride;
46106a62bec0SDavid C Somayajulu 		}
46116a62bec0SDavid C Somayajulu 
46126a62bec0SDavid C Somayajulu 		queue_id += queueEntry->queue_id_stride;
46136a62bec0SDavid C Somayajulu 	}
46146a62bec0SDavid C Somayajulu 
46156a62bec0SDavid C Somayajulu 	return (loop_cnt * (read_cnt * sizeof(uint32_t)));
46166a62bec0SDavid C Somayajulu }
46176a62bec0SDavid C Somayajulu 
46186a62bec0SDavid C Somayajulu /*
46196a62bec0SDavid C Somayajulu  * Handling control entries.
46206a62bec0SDavid C Somayajulu  */
46216a62bec0SDavid C Somayajulu 
46226a62bec0SDavid C Somayajulu static uint32_t
46236a62bec0SDavid C Somayajulu ql_cntrl(qla_host_t *ha,
46246a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *template_hdr,
46256a62bec0SDavid C Somayajulu 	ql_minidump_entry_cntrl_t *crbEntry)
46266a62bec0SDavid C Somayajulu {
46276a62bec0SDavid C Somayajulu 	int ret;
46286a62bec0SDavid C Somayajulu 	int count;
46296a62bec0SDavid C Somayajulu 	uint32_t opcode, read_value, addr, entry_addr;
46306a62bec0SDavid C Somayajulu 	long timeout;
46316a62bec0SDavid C Somayajulu 
46326a62bec0SDavid C Somayajulu 	entry_addr = crbEntry->addr;
46336a62bec0SDavid C Somayajulu 
46346a62bec0SDavid C Somayajulu 	for (count = 0; count < crbEntry->op_count; count++) {
46356a62bec0SDavid C Somayajulu 		opcode = crbEntry->opcode;
46366a62bec0SDavid C Somayajulu 
46376a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_WR) {
46386a62bec0SDavid C Somayajulu 
46396a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr,
46406a62bec0SDavid C Somayajulu 					&crbEntry->value_1, 0);
46416a62bec0SDavid C Somayajulu 			if (ret)
46426a62bec0SDavid C Somayajulu 				return (0);
46436a62bec0SDavid C Somayajulu 
46446a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_WR;
46456a62bec0SDavid C Somayajulu 		}
46466a62bec0SDavid C Somayajulu 
46476a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_RW) {
46486a62bec0SDavid C Somayajulu 
46496a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
46506a62bec0SDavid C Somayajulu 			if (ret)
46516a62bec0SDavid C Somayajulu 				return (0);
46526a62bec0SDavid C Somayajulu 
46536a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
46546a62bec0SDavid C Somayajulu 			if (ret)
46556a62bec0SDavid C Somayajulu 				return (0);
46566a62bec0SDavid C Somayajulu 
46576a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_RW;
46586a62bec0SDavid C Somayajulu 		}
46596a62bec0SDavid C Somayajulu 
46606a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_AND) {
46616a62bec0SDavid C Somayajulu 
46626a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
46636a62bec0SDavid C Somayajulu 			if (ret)
46646a62bec0SDavid C Somayajulu 				return (0);
46656a62bec0SDavid C Somayajulu 
46666a62bec0SDavid C Somayajulu 			read_value &= crbEntry->value_2;
46676a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_AND;
46686a62bec0SDavid C Somayajulu 
46696a62bec0SDavid C Somayajulu 			if (opcode & QL_DBG_OPCODE_OR) {
46706a62bec0SDavid C Somayajulu 				read_value |= crbEntry->value_3;
46716a62bec0SDavid C Somayajulu 				opcode &= ~QL_DBG_OPCODE_OR;
46726a62bec0SDavid C Somayajulu 			}
46736a62bec0SDavid C Somayajulu 
46746a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
46756a62bec0SDavid C Somayajulu 			if (ret)
46766a62bec0SDavid C Somayajulu 				return (0);
46776a62bec0SDavid C Somayajulu 		}
46786a62bec0SDavid C Somayajulu 
46796a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_OR) {
46806a62bec0SDavid C Somayajulu 
46816a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
46826a62bec0SDavid C Somayajulu 			if (ret)
46836a62bec0SDavid C Somayajulu 				return (0);
46846a62bec0SDavid C Somayajulu 
46856a62bec0SDavid C Somayajulu 			read_value |= crbEntry->value_3;
46866a62bec0SDavid C Somayajulu 
46876a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
46886a62bec0SDavid C Somayajulu 			if (ret)
46896a62bec0SDavid C Somayajulu 				return (0);
46906a62bec0SDavid C Somayajulu 
46916a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_OR;
46926a62bec0SDavid C Somayajulu 		}
46936a62bec0SDavid C Somayajulu 
46946a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_POLL) {
46956a62bec0SDavid C Somayajulu 
46966a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_POLL;
46976a62bec0SDavid C Somayajulu 			timeout = crbEntry->poll_timeout;
46986a62bec0SDavid C Somayajulu 			addr = entry_addr;
46996a62bec0SDavid C Somayajulu 
47006a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
47016a62bec0SDavid C Somayajulu 			if (ret)
47026a62bec0SDavid C Somayajulu 				return (0);
47036a62bec0SDavid C Somayajulu 
47046a62bec0SDavid C Somayajulu 			while ((read_value & crbEntry->value_2)
47056a62bec0SDavid C Somayajulu 				!= crbEntry->value_1) {
47066a62bec0SDavid C Somayajulu 
47076a62bec0SDavid C Somayajulu 				if (timeout) {
47086a62bec0SDavid C Somayajulu 					qla_mdelay(__func__, 1);
47096a62bec0SDavid C Somayajulu 					timeout--;
47106a62bec0SDavid C Somayajulu 				} else
47116a62bec0SDavid C Somayajulu 					break;
47126a62bec0SDavid C Somayajulu 
47136a62bec0SDavid C Somayajulu                 		ret = ql_rdwr_indreg32(ha, addr,
47146a62bec0SDavid C Somayajulu 						&read_value, 1);
47156a62bec0SDavid C Somayajulu 				if (ret)
47166a62bec0SDavid C Somayajulu 					return (0);
47176a62bec0SDavid C Somayajulu 			}
47186a62bec0SDavid C Somayajulu 
47196a62bec0SDavid C Somayajulu 			if (!timeout) {
47206a62bec0SDavid C Somayajulu 				/*
47216a62bec0SDavid C Somayajulu 				 * Report timeout error.
47226a62bec0SDavid C Somayajulu 				 * core dump capture failed
47236a62bec0SDavid C Somayajulu 				 * Skip remaining entries.
47246a62bec0SDavid C Somayajulu 				 * Write buffer out to file
47256a62bec0SDavid C Somayajulu 				 * Use driver specific fields in template header
47266a62bec0SDavid C Somayajulu 				 * to report this error.
47276a62bec0SDavid C Somayajulu 				 */
47286a62bec0SDavid C Somayajulu 				return (-1);
47296a62bec0SDavid C Somayajulu 			}
47306a62bec0SDavid C Somayajulu 		}
47316a62bec0SDavid C Somayajulu 
47326a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_RDSTATE) {
47336a62bec0SDavid C Somayajulu 			/*
47346a62bec0SDavid C Somayajulu 			 * decide which address to use.
47356a62bec0SDavid C Somayajulu 			 */
47366a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_a) {
47376a62bec0SDavid C Somayajulu 				addr = template_hdr->saved_state_array[
47386a62bec0SDavid C Somayajulu 						crbEntry-> state_index_a];
47396a62bec0SDavid C Somayajulu 			} else {
47406a62bec0SDavid C Somayajulu 				addr = entry_addr;
47416a62bec0SDavid C Somayajulu 			}
47426a62bec0SDavid C Somayajulu 
47436a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
47446a62bec0SDavid C Somayajulu 			if (ret)
47456a62bec0SDavid C Somayajulu 				return (0);
47466a62bec0SDavid C Somayajulu 
47476a62bec0SDavid C Somayajulu 			template_hdr->saved_state_array[crbEntry->state_index_v]
47486a62bec0SDavid C Somayajulu 					= read_value;
47496a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_RDSTATE;
47506a62bec0SDavid C Somayajulu 		}
47516a62bec0SDavid C Somayajulu 
47526a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_WRSTATE) {
47536a62bec0SDavid C Somayajulu 			/*
47546a62bec0SDavid C Somayajulu 			 * decide which value to use.
47556a62bec0SDavid C Somayajulu 			 */
47566a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_v) {
47576a62bec0SDavid C Somayajulu 				read_value = template_hdr->saved_state_array[
47586a62bec0SDavid C Somayajulu 						crbEntry->state_index_v];
47596a62bec0SDavid C Somayajulu 			} else {
47606a62bec0SDavid C Somayajulu 				read_value = crbEntry->value_1;
47616a62bec0SDavid C Somayajulu 			}
47626a62bec0SDavid C Somayajulu 			/*
47636a62bec0SDavid C Somayajulu 			 * decide which address to use.
47646a62bec0SDavid C Somayajulu 			 */
47656a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_a) {
47666a62bec0SDavid C Somayajulu 				addr = template_hdr->saved_state_array[
47676a62bec0SDavid C Somayajulu 						crbEntry-> state_index_a];
47686a62bec0SDavid C Somayajulu 			} else {
47696a62bec0SDavid C Somayajulu 				addr = entry_addr;
47706a62bec0SDavid C Somayajulu 			}
47716a62bec0SDavid C Somayajulu 
47726a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 0);
47736a62bec0SDavid C Somayajulu 			if (ret)
47746a62bec0SDavid C Somayajulu 				return (0);
47756a62bec0SDavid C Somayajulu 
47766a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_WRSTATE;
47776a62bec0SDavid C Somayajulu 		}
47786a62bec0SDavid C Somayajulu 
47796a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_MDSTATE) {
47806a62bec0SDavid C Somayajulu 			/*  Read value from saved state using index */
47816a62bec0SDavid C Somayajulu 			read_value = template_hdr->saved_state_array[
47826a62bec0SDavid C Somayajulu 						crbEntry->state_index_v];
47836a62bec0SDavid C Somayajulu 
47846a62bec0SDavid C Somayajulu 			read_value <<= crbEntry->shl; /*Shift left operation */
47856a62bec0SDavid C Somayajulu 			read_value >>= crbEntry->shr; /*Shift right operation */
47866a62bec0SDavid C Somayajulu 
47876a62bec0SDavid C Somayajulu 			if (crbEntry->value_2) {
47886a62bec0SDavid C Somayajulu 				/* check if AND mask is provided */
47896a62bec0SDavid C Somayajulu 				read_value &= crbEntry->value_2;
47906a62bec0SDavid C Somayajulu 			}
47916a62bec0SDavid C Somayajulu 
47926a62bec0SDavid C Somayajulu 			read_value |= crbEntry->value_3; /* OR operation */
47936a62bec0SDavid C Somayajulu 			read_value += crbEntry->value_1; /* increment op */
47946a62bec0SDavid C Somayajulu 
47956a62bec0SDavid C Somayajulu 			/* Write value back to state area. */
47966a62bec0SDavid C Somayajulu 
47976a62bec0SDavid C Somayajulu 			template_hdr->saved_state_array[crbEntry->state_index_v]
47986a62bec0SDavid C Somayajulu 					= read_value;
47996a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_MDSTATE;
48006a62bec0SDavid C Somayajulu 		}
48016a62bec0SDavid C Somayajulu 
48026a62bec0SDavid C Somayajulu 		entry_addr += crbEntry->addr_stride;
48036a62bec0SDavid C Somayajulu 	}
48046a62bec0SDavid C Somayajulu 
48056a62bec0SDavid C Somayajulu 	return (0);
48066a62bec0SDavid C Somayajulu }
48076a62bec0SDavid C Somayajulu 
48086a62bec0SDavid C Somayajulu /*
48096a62bec0SDavid C Somayajulu  * Handling rd poll entry.
48106a62bec0SDavid C Somayajulu  */
48116a62bec0SDavid C Somayajulu 
48126a62bec0SDavid C Somayajulu static uint32_t
48136a62bec0SDavid C Somayajulu ql_pollrd(qla_host_t *ha, ql_minidump_entry_pollrd_t *entry,
48146a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
48156a62bec0SDavid C Somayajulu {
48166a62bec0SDavid C Somayajulu         int ret;
48176a62bec0SDavid C Somayajulu         int loop_cnt;
48186a62bec0SDavid C Somayajulu         uint32_t op_count, select_addr, select_value_stride, select_value;
48196a62bec0SDavid C Somayajulu         uint32_t read_addr, poll, mask, data_size, data;
48206a62bec0SDavid C Somayajulu         uint32_t wait_count = 0;
48216a62bec0SDavid C Somayajulu 
48226a62bec0SDavid C Somayajulu         select_addr            = entry->select_addr;
48236a62bec0SDavid C Somayajulu         read_addr              = entry->read_addr;
48246a62bec0SDavid C Somayajulu         select_value           = entry->select_value;
48256a62bec0SDavid C Somayajulu         select_value_stride    = entry->select_value_stride;
48266a62bec0SDavid C Somayajulu         op_count               = entry->op_count;
48276a62bec0SDavid C Somayajulu         poll                   = entry->poll;
48286a62bec0SDavid C Somayajulu         mask                   = entry->mask;
48296a62bec0SDavid C Somayajulu         data_size              = entry->data_size;
48306a62bec0SDavid C Somayajulu 
48316a62bec0SDavid C Somayajulu         for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
48326a62bec0SDavid C Somayajulu 
48336a62bec0SDavid C Somayajulu                 ret = ql_rdwr_indreg32(ha, select_addr, &select_value, 0);
48346a62bec0SDavid C Somayajulu 		if (ret)
48356a62bec0SDavid C Somayajulu 			return (0);
48366a62bec0SDavid C Somayajulu 
48376a62bec0SDavid C Somayajulu                 wait_count = 0;
48386a62bec0SDavid C Somayajulu 
48396a62bec0SDavid C Somayajulu                 while (wait_count < poll) {
48406a62bec0SDavid C Somayajulu 
48416a62bec0SDavid C Somayajulu                         uint32_t temp;
48426a62bec0SDavid C Somayajulu 
48436a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, select_addr, &temp, 1);
48446a62bec0SDavid C Somayajulu 			if (ret)
48456a62bec0SDavid C Somayajulu 				return (0);
48466a62bec0SDavid C Somayajulu 
48476a62bec0SDavid C Somayajulu                         if ( (temp & mask) != 0 ) {
48486a62bec0SDavid C Somayajulu                                 break;
48496a62bec0SDavid C Somayajulu                         }
48506a62bec0SDavid C Somayajulu                         wait_count++;
48516a62bec0SDavid C Somayajulu                 }
48526a62bec0SDavid C Somayajulu 
48536a62bec0SDavid C Somayajulu                 if (wait_count == poll) {
48546a62bec0SDavid C Somayajulu                         device_printf(ha->pci_dev,
48556a62bec0SDavid C Somayajulu 				"%s: Error in processing entry\n", __func__);
48566a62bec0SDavid C Somayajulu                         device_printf(ha->pci_dev,
48576a62bec0SDavid C Somayajulu 				"%s: wait_count <0x%x> poll <0x%x>\n",
48586a62bec0SDavid C Somayajulu 				__func__, wait_count, poll);
48596a62bec0SDavid C Somayajulu                         return 0;
48606a62bec0SDavid C Somayajulu                 }
48616a62bec0SDavid C Somayajulu 
48626a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &data, 1);
48636a62bec0SDavid C Somayajulu 		if (ret)
48646a62bec0SDavid C Somayajulu 			return (0);
48656a62bec0SDavid C Somayajulu 
48666a62bec0SDavid C Somayajulu                 *data_buff++ = select_value;
48676a62bec0SDavid C Somayajulu                 *data_buff++ = data;
48686a62bec0SDavid C Somayajulu                 select_value = select_value + select_value_stride;
48696a62bec0SDavid C Somayajulu         }
48706a62bec0SDavid C Somayajulu 
48716a62bec0SDavid C Somayajulu         /*
48726a62bec0SDavid C Somayajulu          * for testing purpose we return amount of data written
48736a62bec0SDavid C Somayajulu          */
48746a62bec0SDavid C Somayajulu         return (loop_cnt * (2 * sizeof(uint32_t)));
48756a62bec0SDavid C Somayajulu }
48766a62bec0SDavid C Somayajulu 
48776a62bec0SDavid C Somayajulu 
48786a62bec0SDavid C Somayajulu /*
48796a62bec0SDavid C Somayajulu  * Handling rd modify write poll entry.
48806a62bec0SDavid C Somayajulu  */
48816a62bec0SDavid C Somayajulu 
48826a62bec0SDavid C Somayajulu static uint32_t
48836a62bec0SDavid C Somayajulu ql_pollrd_modify_write(qla_host_t *ha,
48846a62bec0SDavid C Somayajulu 	ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
48856a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
48866a62bec0SDavid C Somayajulu {
48876a62bec0SDavid C Somayajulu 	int ret;
48886a62bec0SDavid C Somayajulu         uint32_t addr_1, addr_2, value_1, value_2, data;
48896a62bec0SDavid C Somayajulu         uint32_t poll, mask, data_size, modify_mask;
48906a62bec0SDavid C Somayajulu         uint32_t wait_count = 0;
48916a62bec0SDavid C Somayajulu 
48926a62bec0SDavid C Somayajulu         addr_1		= entry->addr_1;
48936a62bec0SDavid C Somayajulu         addr_2		= entry->addr_2;
48946a62bec0SDavid C Somayajulu         value_1		= entry->value_1;
48956a62bec0SDavid C Somayajulu         value_2		= entry->value_2;
48966a62bec0SDavid C Somayajulu 
48976a62bec0SDavid C Somayajulu         poll		= entry->poll;
48986a62bec0SDavid C Somayajulu         mask		= entry->mask;
48996a62bec0SDavid C Somayajulu         modify_mask	= entry->modify_mask;
49006a62bec0SDavid C Somayajulu         data_size	= entry->data_size;
49016a62bec0SDavid C Somayajulu 
49026a62bec0SDavid C Somayajulu 
49036a62bec0SDavid C Somayajulu 	ret = ql_rdwr_indreg32(ha, addr_1, &value_1, 0);
49046a62bec0SDavid C Somayajulu 	if (ret)
49056a62bec0SDavid C Somayajulu 		return (0);
49066a62bec0SDavid C Somayajulu 
49076a62bec0SDavid C Somayajulu         wait_count = 0;
49086a62bec0SDavid C Somayajulu         while (wait_count < poll) {
49096a62bec0SDavid C Somayajulu 
49106a62bec0SDavid C Somayajulu 		uint32_t temp;
49116a62bec0SDavid C Somayajulu 
49126a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
49136a62bec0SDavid C Somayajulu 		if (ret)
49146a62bec0SDavid C Somayajulu 			return (0);
49156a62bec0SDavid C Somayajulu 
49166a62bec0SDavid C Somayajulu                 if ( (temp & mask) != 0 ) {
49176a62bec0SDavid C Somayajulu                         break;
49186a62bec0SDavid C Somayajulu                 }
49196a62bec0SDavid C Somayajulu                 wait_count++;
49206a62bec0SDavid C Somayajulu         }
49216a62bec0SDavid C Somayajulu 
49226a62bec0SDavid C Somayajulu         if (wait_count == poll) {
49236a62bec0SDavid C Somayajulu                 device_printf(ha->pci_dev, "%s Error in processing entry\n",
49246a62bec0SDavid C Somayajulu 			__func__);
49256a62bec0SDavid C Somayajulu         } else {
49266a62bec0SDavid C Somayajulu 
49276a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_2, &data, 1);
49286a62bec0SDavid C Somayajulu 		if (ret)
49296a62bec0SDavid C Somayajulu 			return (0);
49306a62bec0SDavid C Somayajulu 
49316a62bec0SDavid C Somayajulu                 data = (data & modify_mask);
49326a62bec0SDavid C Somayajulu 
49336a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_2, &data, 0);
49346a62bec0SDavid C Somayajulu 		if (ret)
49356a62bec0SDavid C Somayajulu 			return (0);
49366a62bec0SDavid C Somayajulu 
49376a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_1, &value_2, 0);
49386a62bec0SDavid C Somayajulu 		if (ret)
49396a62bec0SDavid C Somayajulu 			return (0);
49406a62bec0SDavid C Somayajulu 
49416a62bec0SDavid C Somayajulu                 /* Poll again */
49426a62bec0SDavid C Somayajulu                 wait_count = 0;
49436a62bec0SDavid C Somayajulu                 while (wait_count < poll) {
49446a62bec0SDavid C Somayajulu 
49456a62bec0SDavid C Somayajulu                         uint32_t temp;
49466a62bec0SDavid C Somayajulu 
49476a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
49486a62bec0SDavid C Somayajulu 			if (ret)
49496a62bec0SDavid C Somayajulu 				return (0);
49506a62bec0SDavid C Somayajulu 
49516a62bec0SDavid C Somayajulu                         if ( (temp & mask) != 0 ) {
49526a62bec0SDavid C Somayajulu                                 break;
49536a62bec0SDavid C Somayajulu                         }
49546a62bec0SDavid C Somayajulu                         wait_count++;
49556a62bec0SDavid C Somayajulu                 }
49566a62bec0SDavid C Somayajulu                 *data_buff++ = addr_2;
49576a62bec0SDavid C Somayajulu                 *data_buff++ = data;
49586a62bec0SDavid C Somayajulu         }
49596a62bec0SDavid C Somayajulu 
49606a62bec0SDavid C Somayajulu         /*
49616a62bec0SDavid C Somayajulu          * for testing purpose we return amount of data written
49626a62bec0SDavid C Somayajulu          */
49636a62bec0SDavid C Somayajulu         return (2 * sizeof(uint32_t));
49646a62bec0SDavid C Somayajulu }
49656a62bec0SDavid C Somayajulu 
49666a62bec0SDavid C Somayajulu 
4967