xref: /freebsd/sys/dev/qlxgbe/ql_hw.c (revision b5c2be72)
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 int qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
55f10a77bbSDavid C Somayajulu 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause);
5635291c22SDavid C Somayajulu static int qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx,
5735291c22SDavid C Somayajulu 	uint32_t num_intrs, uint32_t create);
58f10a77bbSDavid C Somayajulu static int qla_config_rss(qla_host_t *ha, uint16_t cntxt_id);
59f10a77bbSDavid C Somayajulu static int qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id,
6035291c22SDavid C Somayajulu 	int tenable, int rcv);
61f10a77bbSDavid C Somayajulu static int qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode);
62f10a77bbSDavid C Somayajulu static int qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id);
63f10a77bbSDavid C Somayajulu 
64f10a77bbSDavid C Somayajulu static int qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd,
65f10a77bbSDavid C Somayajulu 		uint8_t *hdr);
66f10a77bbSDavid C Somayajulu static int qla_hw_add_all_mcast(qla_host_t *ha);
67f10a77bbSDavid C Somayajulu static int qla_hw_del_all_mcast(qla_host_t *ha);
6835291c22SDavid C Somayajulu static int qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds);
6935291c22SDavid C Somayajulu 
7035291c22SDavid C Somayajulu static int qla_init_nic_func(qla_host_t *ha);
7135291c22SDavid C Somayajulu static int qla_stop_nic_func(qla_host_t *ha);
7235291c22SDavid C Somayajulu static int qla_query_fw_dcbx_caps(qla_host_t *ha);
7335291c22SDavid C Somayajulu static int qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits);
7435291c22SDavid C Somayajulu static int qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits);
7535291c22SDavid C Somayajulu static void qla_get_quick_stats(qla_host_t *ha);
7600caeec7SDavid C Somayajulu static int qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode);
7700caeec7SDavid C Somayajulu static int qla_get_cam_search_mode(qla_host_t *ha);
78f10a77bbSDavid C Somayajulu 
796a62bec0SDavid C Somayajulu static void ql_minidump_free(qla_host_t *ha);
80f10a77bbSDavid C Somayajulu 
81f10a77bbSDavid C Somayajulu 
82f10a77bbSDavid C Somayajulu static int
83f10a77bbSDavid C Somayajulu qla_sysctl_get_drvr_stats(SYSCTL_HANDLER_ARGS)
84f10a77bbSDavid C Somayajulu {
85f10a77bbSDavid C Somayajulu         int err = 0, ret;
86f10a77bbSDavid C Somayajulu         qla_host_t *ha;
87f10a77bbSDavid C Somayajulu 	uint32_t i;
88f10a77bbSDavid C Somayajulu 
89f10a77bbSDavid C Somayajulu         err = sysctl_handle_int(oidp, &ret, 0, req);
90f10a77bbSDavid C Somayajulu 
91f10a77bbSDavid C Somayajulu         if (err || !req->newptr)
92f10a77bbSDavid C Somayajulu                 return (err);
93f10a77bbSDavid C Somayajulu 
94f10a77bbSDavid C Somayajulu         if (ret == 1) {
95f10a77bbSDavid C Somayajulu 
96f10a77bbSDavid C Somayajulu                 ha = (qla_host_t *)arg1;
97f10a77bbSDavid C Somayajulu 
9800caeec7SDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
9900caeec7SDavid C Somayajulu 
100f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
101f10a77bbSDavid C Somayajulu 				"%s: sds_ring[%d] = %p\n", __func__,i,
102f10a77bbSDavid C Somayajulu 				(void *)ha->hw.sds[i].intr_count);
103f10a77bbSDavid C Somayajulu 
10400caeec7SDavid C Somayajulu 			device_printf(ha->pci_dev,
10500caeec7SDavid C Somayajulu 				"%s: sds_ring[%d].spurious_intr_count = %p\n",
10600caeec7SDavid C Somayajulu 				__func__,
10700caeec7SDavid C Somayajulu 				i, (void *)ha->hw.sds[i].spurious_intr_count);
10800caeec7SDavid C Somayajulu 
10900caeec7SDavid C Somayajulu 			device_printf(ha->pci_dev,
11000caeec7SDavid C Somayajulu 				"%s: sds_ring[%d].rx_free = %d\n", __func__,i,
11100caeec7SDavid C Somayajulu 				ha->hw.sds[i].rx_free);
11200caeec7SDavid C Somayajulu 		}
11300caeec7SDavid C Somayajulu 
114f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_tx_rings; i++)
115f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
116f10a77bbSDavid C Somayajulu 				"%s: tx[%d] = %p\n", __func__,i,
117f10a77bbSDavid C Somayajulu 				(void *)ha->tx_ring[i].count);
118f10a77bbSDavid C Somayajulu 
119f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_rds_rings; i++)
120f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
121f10a77bbSDavid C Somayajulu 				"%s: rds_ring[%d] = %p\n", __func__,i,
122f10a77bbSDavid C Somayajulu 				(void *)ha->hw.rds[i].count);
123f10a77bbSDavid C Somayajulu 
124f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: lro_pkt_count = %p\n", __func__,
125f10a77bbSDavid C Somayajulu 			(void *)ha->lro_pkt_count);
126f10a77bbSDavid C Somayajulu 
127f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: lro_bytes = %p\n", __func__,
128f10a77bbSDavid C Somayajulu 			(void *)ha->lro_bytes);
12935291c22SDavid C Somayajulu 
13035291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV
13135291c22SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: iscsi_pkts = %p\n", __func__,
13235291c22SDavid C Somayajulu 			(void *)ha->hw.iscsi_pkt_count);
13335291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
13435291c22SDavid C Somayajulu 
13535291c22SDavid C Somayajulu 	}
13635291c22SDavid C Somayajulu 	return (err);
13735291c22SDavid C Somayajulu }
13835291c22SDavid C Somayajulu 
13935291c22SDavid C Somayajulu static int
14035291c22SDavid C Somayajulu qla_sysctl_get_quick_stats(SYSCTL_HANDLER_ARGS)
14135291c22SDavid C Somayajulu {
14235291c22SDavid C Somayajulu 	int err, ret = 0;
14335291c22SDavid C Somayajulu 	qla_host_t *ha;
14435291c22SDavid C Somayajulu 
14535291c22SDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
14635291c22SDavid C Somayajulu 
14735291c22SDavid C Somayajulu 	if (err || !req->newptr)
14835291c22SDavid C Somayajulu 		return (err);
14935291c22SDavid C Somayajulu 
15035291c22SDavid C Somayajulu 	if (ret == 1) {
15135291c22SDavid C Somayajulu 		ha = (qla_host_t *)arg1;
15235291c22SDavid C Somayajulu 		qla_get_quick_stats(ha);
153f10a77bbSDavid C Somayajulu 	}
154f10a77bbSDavid C Somayajulu 	return (err);
155f10a77bbSDavid C Somayajulu }
156f10a77bbSDavid C Somayajulu 
157f10a77bbSDavid C Somayajulu #ifdef QL_DBG
158f10a77bbSDavid C Somayajulu 
159f10a77bbSDavid C Somayajulu static void
160f10a77bbSDavid C Somayajulu qla_stop_pegs(qla_host_t *ha)
161f10a77bbSDavid C Somayajulu {
162f10a77bbSDavid C Somayajulu         uint32_t val = 1;
163f10a77bbSDavid C Somayajulu 
164f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0);
165f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0);
166f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0);
167f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0);
168f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0);
169f10a77bbSDavid C Somayajulu         device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__);
170f10a77bbSDavid C Somayajulu }
171f10a77bbSDavid C Somayajulu 
172f10a77bbSDavid C Somayajulu static int
173f10a77bbSDavid C Somayajulu qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)
174f10a77bbSDavid C Somayajulu {
175f10a77bbSDavid C Somayajulu 	int err, ret = 0;
176f10a77bbSDavid C Somayajulu 	qla_host_t *ha;
177f10a77bbSDavid C Somayajulu 
178f10a77bbSDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
179f10a77bbSDavid C Somayajulu 
180f10a77bbSDavid C Somayajulu 
181f10a77bbSDavid C Somayajulu 	if (err || !req->newptr)
182f10a77bbSDavid C Somayajulu 		return (err);
183f10a77bbSDavid C Somayajulu 
184f10a77bbSDavid C Somayajulu 	if (ret == 1) {
185f10a77bbSDavid C Somayajulu 		ha = (qla_host_t *)arg1;
1869a5f7854SDavid C Somayajulu 		QLA_LOCK(ha);
187f10a77bbSDavid C Somayajulu 		qla_stop_pegs(ha);
1889a5f7854SDavid C Somayajulu 		QLA_UNLOCK(ha);
189f10a77bbSDavid C Somayajulu 	}
190f10a77bbSDavid C Somayajulu 
191f10a77bbSDavid C Somayajulu 	return err;
192f10a77bbSDavid C Somayajulu }
193f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */
194f10a77bbSDavid C Somayajulu 
19535291c22SDavid C Somayajulu static int
19635291c22SDavid C Somayajulu qla_validate_set_port_cfg_bit(uint32_t bits)
19735291c22SDavid C Somayajulu {
19835291c22SDavid C Somayajulu         if ((bits & 0xF) > 1)
19935291c22SDavid C Somayajulu                 return (-1);
20035291c22SDavid C Somayajulu 
20135291c22SDavid C Somayajulu         if (((bits >> 4) & 0xF) > 2)
20235291c22SDavid C Somayajulu                 return (-1);
20335291c22SDavid C Somayajulu 
20435291c22SDavid C Somayajulu         if (((bits >> 8) & 0xF) > 2)
20535291c22SDavid C Somayajulu                 return (-1);
20635291c22SDavid C Somayajulu 
20735291c22SDavid C Somayajulu         return (0);
20835291c22SDavid C Somayajulu }
20935291c22SDavid C Somayajulu 
21035291c22SDavid C Somayajulu static int
21135291c22SDavid C Somayajulu qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS)
21235291c22SDavid C Somayajulu {
21335291c22SDavid C Somayajulu         int err, ret = 0;
21435291c22SDavid C Somayajulu         qla_host_t *ha;
21535291c22SDavid C Somayajulu         uint32_t cfg_bits;
21635291c22SDavid C Somayajulu 
21735291c22SDavid C Somayajulu         err = sysctl_handle_int(oidp, &ret, 0, req);
21835291c22SDavid C Somayajulu 
21935291c22SDavid C Somayajulu         if (err || !req->newptr)
22035291c22SDavid C Somayajulu                 return (err);
22135291c22SDavid C Somayajulu 
22235291c22SDavid C Somayajulu         if ((qla_validate_set_port_cfg_bit((uint32_t)ret) == 0)) {
22335291c22SDavid C Somayajulu 
22435291c22SDavid C Somayajulu                 ha = (qla_host_t *)arg1;
22535291c22SDavid C Somayajulu 
22635291c22SDavid C Somayajulu                 err = qla_get_port_config(ha, &cfg_bits);
22735291c22SDavid C Somayajulu 
22835291c22SDavid C Somayajulu                 if (err)
22935291c22SDavid C Somayajulu                         goto qla_sysctl_set_port_cfg_exit;
23035291c22SDavid C Somayajulu 
23135291c22SDavid C Somayajulu                 if (ret & 0x1) {
23235291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_DCBX_ENABLE;
23335291c22SDavid C Somayajulu                 } else {
23435291c22SDavid C Somayajulu                         cfg_bits &= ~Q8_PORT_CFG_BITS_DCBX_ENABLE;
23535291c22SDavid C Somayajulu                 }
23635291c22SDavid C Somayajulu 
23735291c22SDavid C Somayajulu                 ret = ret >> 4;
23835291c22SDavid C Somayajulu                 cfg_bits &= ~Q8_PORT_CFG_BITS_PAUSE_CFG_MASK;
23935291c22SDavid C Somayajulu 
24035291c22SDavid C Somayajulu                 if ((ret & 0xF) == 0) {
24135291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_DISABLED;
24235291c22SDavid C Somayajulu                 } else if ((ret & 0xF) == 1){
24335291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_STD;
24435291c22SDavid C Somayajulu                 } else {
24535291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_PPM;
24635291c22SDavid C Somayajulu                 }
24735291c22SDavid C Somayajulu 
24835291c22SDavid C Somayajulu                 ret = ret >> 4;
24935291c22SDavid C Somayajulu                 cfg_bits &= ~Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK;
25035291c22SDavid C Somayajulu 
25135291c22SDavid C Somayajulu                 if (ret == 0) {
25235291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT_RCV;
25335291c22SDavid C Somayajulu                 } else if (ret == 1){
25435291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT;
25535291c22SDavid C Somayajulu                 } else {
25635291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_RCV;
25735291c22SDavid C Somayajulu                 }
25835291c22SDavid C Somayajulu 
25935291c22SDavid C Somayajulu                 err = qla_set_port_config(ha, cfg_bits);
26035291c22SDavid C Somayajulu         } else {
26135291c22SDavid C Somayajulu                 ha = (qla_host_t *)arg1;
26235291c22SDavid C Somayajulu 
26335291c22SDavid C Somayajulu                 err = qla_get_port_config(ha, &cfg_bits);
26435291c22SDavid C Somayajulu         }
26535291c22SDavid C Somayajulu 
26635291c22SDavid C Somayajulu qla_sysctl_set_port_cfg_exit:
26735291c22SDavid C Somayajulu         return err;
26835291c22SDavid C Somayajulu }
26935291c22SDavid C Somayajulu 
27000caeec7SDavid C Somayajulu static int
27100caeec7SDavid C Somayajulu qla_sysctl_set_cam_search_mode(SYSCTL_HANDLER_ARGS)
27200caeec7SDavid C Somayajulu {
27300caeec7SDavid C Somayajulu 	int err, ret = 0;
27400caeec7SDavid C Somayajulu 	qla_host_t *ha;
27500caeec7SDavid C Somayajulu 
27600caeec7SDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
27700caeec7SDavid C Somayajulu 
27800caeec7SDavid C Somayajulu 	if (err || !req->newptr)
27900caeec7SDavid C Somayajulu 		return (err);
28000caeec7SDavid C Somayajulu 
28100caeec7SDavid C Somayajulu 	ha = (qla_host_t *)arg1;
28200caeec7SDavid C Somayajulu 
28300caeec7SDavid C Somayajulu 	if ((ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_INTERNAL) ||
28400caeec7SDavid C Somayajulu 		(ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_AUTO)) {
28500caeec7SDavid C Somayajulu 		err = qla_set_cam_search_mode(ha, (uint32_t)ret);
28600caeec7SDavid C Somayajulu 	} else {
28700caeec7SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: ret = %d\n", __func__, ret);
28800caeec7SDavid C Somayajulu 	}
28900caeec7SDavid C Somayajulu 
29000caeec7SDavid C Somayajulu 	return (err);
29100caeec7SDavid C Somayajulu }
29200caeec7SDavid C Somayajulu 
29300caeec7SDavid C Somayajulu static int
29400caeec7SDavid C Somayajulu qla_sysctl_get_cam_search_mode(SYSCTL_HANDLER_ARGS)
29500caeec7SDavid C Somayajulu {
29600caeec7SDavid C Somayajulu 	int err, ret = 0;
29700caeec7SDavid C Somayajulu 	qla_host_t *ha;
29800caeec7SDavid C Somayajulu 
29900caeec7SDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
30000caeec7SDavid C Somayajulu 
30100caeec7SDavid C Somayajulu 	if (err || !req->newptr)
30200caeec7SDavid C Somayajulu 		return (err);
30300caeec7SDavid C Somayajulu 
30400caeec7SDavid C Somayajulu 	ha = (qla_host_t *)arg1;
30500caeec7SDavid C Somayajulu 	err = qla_get_cam_search_mode(ha);
30600caeec7SDavid C Somayajulu 
30700caeec7SDavid C Somayajulu 	return (err);
30800caeec7SDavid C Somayajulu }
30900caeec7SDavid C Somayajulu 
31000caeec7SDavid C Somayajulu 
311f10a77bbSDavid C Somayajulu /*
312f10a77bbSDavid C Somayajulu  * Name: ql_hw_add_sysctls
313f10a77bbSDavid C Somayajulu  * Function: Add P3Plus specific sysctls
314f10a77bbSDavid C Somayajulu  */
315f10a77bbSDavid C Somayajulu void
316f10a77bbSDavid C Somayajulu ql_hw_add_sysctls(qla_host_t *ha)
317f10a77bbSDavid C Somayajulu {
318f10a77bbSDavid C Somayajulu         device_t	dev;
319f10a77bbSDavid C Somayajulu 
320f10a77bbSDavid C Somayajulu         dev = ha->pci_dev;
321f10a77bbSDavid C Somayajulu 
322f10a77bbSDavid C Somayajulu 	ha->hw.num_sds_rings = MAX_SDS_RINGS;
323f10a77bbSDavid C Somayajulu 	ha->hw.num_rds_rings = MAX_RDS_RINGS;
324f10a77bbSDavid C Somayajulu 	ha->hw.num_tx_rings = NUM_TX_RINGS;
325f10a77bbSDavid C Somayajulu 
326f10a77bbSDavid C Somayajulu 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
327f10a77bbSDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
328f10a77bbSDavid C Somayajulu 		OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings,
329f10a77bbSDavid C Somayajulu 		ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings");
330f10a77bbSDavid C Somayajulu 
331f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
332f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
333f10a77bbSDavid C Somayajulu                 OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings,
334f10a77bbSDavid C Somayajulu 		ha->hw.num_sds_rings, "Number of Status Descriptor Rings");
335f10a77bbSDavid C Somayajulu 
336f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
337f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
338f10a77bbSDavid C Somayajulu                 OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings,
339f10a77bbSDavid C Somayajulu 		ha->hw.num_tx_rings, "Number of Transmit Rings");
340f10a77bbSDavid C Somayajulu 
341f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
342f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
343f10a77bbSDavid C Somayajulu                 OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx,
344f10a77bbSDavid C Somayajulu 		ha->txr_idx, "Tx Ring Used");
345f10a77bbSDavid C Somayajulu 
346f10a77bbSDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
347f10a77bbSDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
348f10a77bbSDavid C Somayajulu 		OID_AUTO, "drvr_stats", CTLTYPE_INT | CTLFLAG_RW,
349f10a77bbSDavid C Somayajulu 		(void *)ha, 0,
350f10a77bbSDavid C Somayajulu 		qla_sysctl_get_drvr_stats, "I", "Driver Maintained Statistics");
351f10a77bbSDavid C Somayajulu 
35235291c22SDavid C Somayajulu         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
35335291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
35435291c22SDavid C Somayajulu                 OID_AUTO, "quick_stats", CTLTYPE_INT | CTLFLAG_RW,
35535291c22SDavid C Somayajulu                 (void *)ha, 0,
35635291c22SDavid C Somayajulu                 qla_sysctl_get_quick_stats, "I", "Quick Statistics");
35735291c22SDavid C Somayajulu 
358f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
359f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
360f10a77bbSDavid C Somayajulu                 OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs,
361f10a77bbSDavid C Somayajulu 		ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt");
362f10a77bbSDavid C Somayajulu 
363f10a77bbSDavid C Somayajulu 	ha->hw.sds_cidx_thres = 32;
364f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
365f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
366f10a77bbSDavid C Somayajulu                 OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres,
367f10a77bbSDavid C Somayajulu 		ha->hw.sds_cidx_thres,
368f10a77bbSDavid C Somayajulu 		"Number of SDS entries to process before updating"
369f10a77bbSDavid C Somayajulu 		" SDS Ring Consumer Index");
370f10a77bbSDavid C Somayajulu 
371f10a77bbSDavid C Somayajulu 	ha->hw.rds_pidx_thres = 32;
372f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
373f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
374f10a77bbSDavid C Somayajulu                 OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres,
375f10a77bbSDavid C Somayajulu 		ha->hw.rds_pidx_thres,
376f10a77bbSDavid C Somayajulu 		"Number of Rcv Rings Entries to post before updating"
377f10a77bbSDavid C Somayajulu 		" RDS Ring Producer Index");
378f10a77bbSDavid C Somayajulu 
37935291c22SDavid C Somayajulu         ha->hw.rcv_intr_coalesce = (3 << 16) | 256;
380c12c5bfbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
381c12c5bfbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
38235291c22SDavid C Somayajulu                 OID_AUTO, "rcv_intr_coalesce", CTLFLAG_RW,
38335291c22SDavid C Somayajulu                 &ha->hw.rcv_intr_coalesce,
38435291c22SDavid C Somayajulu                 ha->hw.rcv_intr_coalesce,
38535291c22SDavid C Somayajulu                 "Rcv Intr Coalescing Parameters\n"
38635291c22SDavid C Somayajulu                 "\tbits 15:0 max packets\n"
38735291c22SDavid C Somayajulu                 "\tbits 31:16 max micro-seconds to wait\n"
38835291c22SDavid C Somayajulu                 "\tplease run\n"
38935291c22SDavid C Somayajulu                 "\tifconfig <if> down && ifconfig <if> up\n"
39035291c22SDavid C Somayajulu                 "\tto take effect \n");
39135291c22SDavid C Somayajulu 
39235291c22SDavid C Somayajulu         ha->hw.xmt_intr_coalesce = (64 << 16) | 64;
39335291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
39435291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
39535291c22SDavid C Somayajulu                 OID_AUTO, "xmt_intr_coalesce", CTLFLAG_RW,
39635291c22SDavid C Somayajulu                 &ha->hw.xmt_intr_coalesce,
39735291c22SDavid C Somayajulu                 ha->hw.xmt_intr_coalesce,
39835291c22SDavid C Somayajulu                 "Xmt Intr Coalescing Parameters\n"
39935291c22SDavid C Somayajulu                 "\tbits 15:0 max packets\n"
40035291c22SDavid C Somayajulu                 "\tbits 31:16 max micro-seconds to wait\n"
40135291c22SDavid C Somayajulu                 "\tplease run\n"
40235291c22SDavid C Somayajulu                 "\tifconfig <if> down && ifconfig <if> up\n"
40335291c22SDavid C Somayajulu                 "\tto take effect \n");
40435291c22SDavid C Somayajulu 
40535291c22SDavid C Somayajulu         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
40635291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
40735291c22SDavid C Somayajulu                 OID_AUTO, "port_cfg", CTLTYPE_INT | CTLFLAG_RW,
40835291c22SDavid C Somayajulu                 (void *)ha, 0,
40935291c22SDavid C Somayajulu                 qla_sysctl_port_cfg, "I",
41035291c22SDavid C Somayajulu                         "Set Port Configuration if values below "
41135291c22SDavid C Somayajulu                         "otherwise Get Port Configuration\n"
41235291c22SDavid C Somayajulu                         "\tBits 0-3 ; 1 = DCBX Enable; 0 = DCBX Disable\n"
41335291c22SDavid C Somayajulu                         "\tBits 4-7 : 0 = no pause; 1 = std ; 2 = ppm \n"
41435291c22SDavid C Somayajulu                         "\tBits 8-11: std pause cfg; 0 = xmt and rcv;"
41535291c22SDavid C Somayajulu                         " 1 = xmt only; 2 = rcv only;\n"
41635291c22SDavid C Somayajulu                 );
41735291c22SDavid C Somayajulu 
41800caeec7SDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
41900caeec7SDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
42000caeec7SDavid C Somayajulu 		OID_AUTO, "set_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW,
42100caeec7SDavid C Somayajulu 		(void *)ha, 0,
42200caeec7SDavid C Somayajulu 		qla_sysctl_set_cam_search_mode, "I",
42300caeec7SDavid C Somayajulu 			"Set CAM Search Mode"
42400caeec7SDavid C Somayajulu 			"\t 1 = search mode internal\n"
42500caeec7SDavid C Somayajulu 			"\t 2 = search mode auto\n");
42600caeec7SDavid C Somayajulu 
42700caeec7SDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
42800caeec7SDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
42900caeec7SDavid C Somayajulu 		OID_AUTO, "get_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW,
43000caeec7SDavid C Somayajulu 		(void *)ha, 0,
43100caeec7SDavid C Somayajulu 		qla_sysctl_get_cam_search_mode, "I",
43200caeec7SDavid C Somayajulu 			"Get CAM Search Mode"
43300caeec7SDavid C Somayajulu 			"\t 1 = search mode internal\n"
43400caeec7SDavid C Somayajulu 			"\t 2 = search mode auto\n");
43500caeec7SDavid C Somayajulu 
43635291c22SDavid C Somayajulu         ha->hw.enable_9kb = 1;
43735291c22SDavid C Somayajulu 
43835291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
43935291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
44035291c22SDavid C Somayajulu                 OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb,
44135291c22SDavid C Somayajulu                 ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000");
442c12c5bfbSDavid C Somayajulu 
443a7c62c11SDavid C Somayajulu         ha->hw.enable_hw_lro = 1;
444a7c62c11SDavid C Somayajulu 
445a7c62c11SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
446a7c62c11SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
447a7c62c11SDavid C Somayajulu                 OID_AUTO, "enable_hw_lro", CTLFLAG_RW, &ha->hw.enable_hw_lro,
448a7c62c11SDavid C Somayajulu                 ha->hw.enable_hw_lro, "Enable Hardware LRO; Default is true \n"
449a7c62c11SDavid C Somayajulu 		"\t 1 : Hardware LRO if LRO is enabled\n"
450a7c62c11SDavid C Somayajulu 		"\t 0 : Software LRO if LRO is enabled\n"
451a7c62c11SDavid C Somayajulu 		"\t Any change requires ifconfig down/up to take effect\n"
452a7c62c11SDavid C Somayajulu 		"\t Note that LRO may be turned off/on via ifconfig\n");
453a7c62c11SDavid C Somayajulu 
454f10a77bbSDavid C Somayajulu 	ha->hw.mdump_active = 0;
455f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
456f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
457f10a77bbSDavid C Somayajulu                 OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active,
458f10a77bbSDavid C Somayajulu 		ha->hw.mdump_active,
4596a62bec0SDavid C Somayajulu 		"Minidump retrieval is Active");
460f10a77bbSDavid C Somayajulu 
4616a62bec0SDavid C Somayajulu 	ha->hw.mdump_done = 0;
462f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
463f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
4646a62bec0SDavid C Somayajulu                 OID_AUTO, "mdump_done", CTLFLAG_RW,
4656a62bec0SDavid C Somayajulu 		&ha->hw.mdump_done, ha->hw.mdump_done,
4666a62bec0SDavid C Somayajulu 		"Minidump has been done and available for retrieval");
4676a62bec0SDavid C Somayajulu 
4686a62bec0SDavid C Somayajulu 	ha->hw.mdump_capture_mask = 0xF;
4696a62bec0SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
4706a62bec0SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
4716a62bec0SDavid C Somayajulu                 OID_AUTO, "minidump_capture_mask", CTLFLAG_RW,
4726a62bec0SDavid C Somayajulu 		&ha->hw.mdump_capture_mask, ha->hw.mdump_capture_mask,
4736a62bec0SDavid C Somayajulu 		"Minidump capture mask");
474f10a77bbSDavid C Somayajulu #ifdef QL_DBG
475f10a77bbSDavid C Somayajulu 
476467dcb5aSDavid C Somayajulu 	ha->err_inject = 0;
477f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
478f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
479f10a77bbSDavid C Somayajulu                 OID_AUTO, "err_inject",
480f10a77bbSDavid C Somayajulu                 CTLFLAG_RW, &ha->err_inject, ha->err_inject,
481f10a77bbSDavid C Somayajulu                 "Error to be injected\n"
482f10a77bbSDavid C Somayajulu                 "\t\t\t 0: No Errors\n"
483f10a77bbSDavid C Somayajulu                 "\t\t\t 1: rcv: rxb struct invalid\n"
484f10a77bbSDavid C Somayajulu                 "\t\t\t 2: rcv: mp == NULL\n"
485f10a77bbSDavid C Somayajulu                 "\t\t\t 3: lro: rxb struct invalid\n"
486f10a77bbSDavid C Somayajulu                 "\t\t\t 4: lro: mp == NULL\n"
487f10a77bbSDavid C Somayajulu                 "\t\t\t 5: rcv: num handles invalid\n"
488f10a77bbSDavid C Somayajulu                 "\t\t\t 6: reg: indirect reg rd_wr failure\n"
489f10a77bbSDavid C Somayajulu                 "\t\t\t 7: ocm: offchip memory rd_wr failure\n"
490f10a77bbSDavid C Somayajulu                 "\t\t\t 8: mbx: mailbox command failure\n"
491f10a77bbSDavid C Somayajulu                 "\t\t\t 9: heartbeat failure\n"
49200caeec7SDavid C Somayajulu                 "\t\t\t A: temperature failure\n"
49300caeec7SDavid C Somayajulu 		"\t\t\t 11: m_getcl or m_getjcl failure\n" );
494f10a77bbSDavid C Somayajulu 
495f10a77bbSDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
496f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
497f10a77bbSDavid C Somayajulu                 OID_AUTO, "peg_stop", CTLTYPE_INT | CTLFLAG_RW,
498f10a77bbSDavid C Somayajulu                 (void *)ha, 0,
499f10a77bbSDavid C Somayajulu                 qla_sysctl_stop_pegs, "I", "Peg Stop");
500f10a77bbSDavid C Somayajulu 
501f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */
502f10a77bbSDavid C Somayajulu 
50335291c22SDavid C Somayajulu         ha->hw.user_pri_nic = 0;
50435291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
50535291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
50635291c22SDavid C Somayajulu                 OID_AUTO, "user_pri_nic", CTLFLAG_RW, &ha->hw.user_pri_nic,
50735291c22SDavid C Somayajulu                 ha->hw.user_pri_nic,
50835291c22SDavid C Somayajulu                 "VLAN Tag User Priority for Normal Ethernet Packets");
50935291c22SDavid C Somayajulu 
51035291c22SDavid C Somayajulu         ha->hw.user_pri_iscsi = 4;
51135291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
51235291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
51335291c22SDavid C Somayajulu                 OID_AUTO, "user_pri_iscsi", CTLFLAG_RW, &ha->hw.user_pri_iscsi,
51435291c22SDavid C Somayajulu                 ha->hw.user_pri_iscsi,
51535291c22SDavid C Somayajulu                 "VLAN Tag User Priority for iSCSI Packets");
51635291c22SDavid C Somayajulu 
517f10a77bbSDavid C Somayajulu }
518f10a77bbSDavid C Somayajulu 
519f10a77bbSDavid C Somayajulu void
520f10a77bbSDavid C Somayajulu ql_hw_link_status(qla_host_t *ha)
521f10a77bbSDavid C Somayajulu {
522f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui);
523f10a77bbSDavid C Somayajulu 
524f10a77bbSDavid C Somayajulu 	if (ha->hw.link_up) {
525f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link Up\n");
526f10a77bbSDavid C Somayajulu 	} else {
527f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link Down\n");
528f10a77bbSDavid C Somayajulu 	}
529f10a77bbSDavid C Somayajulu 
530f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.fduplex) {
531f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Full Duplex\n");
532f10a77bbSDavid C Somayajulu 	} else {
533f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Half Duplex\n");
534f10a77bbSDavid C Somayajulu 	}
535f10a77bbSDavid C Somayajulu 
536f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.autoneg) {
537f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Auto Negotiation Enabled\n");
538f10a77bbSDavid C Somayajulu 	} else {
539f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Auto Negotiation Disabled\n");
540f10a77bbSDavid C Somayajulu 	}
541f10a77bbSDavid C Somayajulu 
542f10a77bbSDavid C Somayajulu 	switch (ha->hw.link_speed) {
543f10a77bbSDavid C Somayajulu 	case 0x710:
544f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 10Gps\n");
545f10a77bbSDavid C Somayajulu 		break;
546f10a77bbSDavid C Somayajulu 
547f10a77bbSDavid C Somayajulu 	case 0x3E8:
548f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 1Gps\n");
549f10a77bbSDavid C Somayajulu 		break;
550f10a77bbSDavid C Somayajulu 
551f10a77bbSDavid C Somayajulu 	case 0x64:
552f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n");
553f10a77bbSDavid C Somayajulu 		break;
554f10a77bbSDavid C Somayajulu 
555f10a77bbSDavid C Somayajulu 	default:
556f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t Unknown\n");
557f10a77bbSDavid C Somayajulu 		break;
558f10a77bbSDavid C Somayajulu 	}
559f10a77bbSDavid C Somayajulu 
560f10a77bbSDavid C Somayajulu 	switch (ha->hw.module_type) {
561f10a77bbSDavid C Somayajulu 
562f10a77bbSDavid C Somayajulu 	case 0x01:
563f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n");
564f10a77bbSDavid C Somayajulu 		break;
565f10a77bbSDavid C Somayajulu 
566f10a77bbSDavid C Somayajulu 	case 0x02:
567f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-LR\n");
568f10a77bbSDavid C Somayajulu 		break;
569f10a77bbSDavid C Somayajulu 
570f10a77bbSDavid C Somayajulu 	case 0x03:
571f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-SR\n");
572f10a77bbSDavid C Somayajulu 		break;
573f10a77bbSDavid C Somayajulu 
574f10a77bbSDavid C Somayajulu 	case 0x04:
575f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
576f10a77bbSDavid C Somayajulu 			"Module Type 10GE Passive Copper(Compliant)[%d m]\n",
577f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
578f10a77bbSDavid C Somayajulu 		break;
579f10a77bbSDavid C Somayajulu 
580f10a77bbSDavid C Somayajulu 	case 0x05:
581f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GE Active"
582f10a77bbSDavid C Somayajulu 			" Limiting Copper(Compliant)[%d m]\n",
583f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
584f10a77bbSDavid C Somayajulu 		break;
585f10a77bbSDavid C Somayajulu 
586f10a77bbSDavid C Somayajulu 	case 0x06:
587f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
588f10a77bbSDavid C Somayajulu 			"Module Type 10GE Passive Copper"
589f10a77bbSDavid C Somayajulu 			" (Legacy, Best Effort)[%d m]\n",
590f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
591f10a77bbSDavid C Somayajulu 		break;
592f10a77bbSDavid C Somayajulu 
593f10a77bbSDavid C Somayajulu 	case 0x07:
594f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-SX\n");
595f10a77bbSDavid C Somayajulu 		break;
596f10a77bbSDavid C Somayajulu 
597f10a77bbSDavid C Somayajulu 	case 0x08:
598f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-LX\n");
599f10a77bbSDavid C Somayajulu 		break;
600f10a77bbSDavid C Somayajulu 
601f10a77bbSDavid C Somayajulu 	case 0x09:
602f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-CX\n");
603f10a77bbSDavid C Somayajulu 		break;
604f10a77bbSDavid C Somayajulu 
605f10a77bbSDavid C Somayajulu 	case 0x0A:
606f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-T\n");
607f10a77bbSDavid C Somayajulu 		break;
608f10a77bbSDavid C Somayajulu 
609f10a77bbSDavid C Somayajulu 	case 0x0B:
610f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1GE Passive Copper"
611f10a77bbSDavid C Somayajulu 			"(Legacy, Best Effort)\n");
612f10a77bbSDavid C Somayajulu 		break;
613f10a77bbSDavid C Somayajulu 
614f10a77bbSDavid C Somayajulu 	default:
615f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n",
616f10a77bbSDavid C Somayajulu 			ha->hw.module_type);
617f10a77bbSDavid C Somayajulu 		break;
618f10a77bbSDavid C Somayajulu 	}
619f10a77bbSDavid C Somayajulu 
620f10a77bbSDavid C Somayajulu 	if (ha->hw.link_faults == 1)
621f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "SFP Power Fault\n");
622f10a77bbSDavid C Somayajulu }
623f10a77bbSDavid C Somayajulu 
624f10a77bbSDavid C Somayajulu /*
625f10a77bbSDavid C Somayajulu  * Name: ql_free_dma
626f10a77bbSDavid C Somayajulu  * Function: Frees the DMA'able memory allocated in ql_alloc_dma()
627f10a77bbSDavid C Somayajulu  */
628f10a77bbSDavid C Somayajulu void
629f10a77bbSDavid C Somayajulu ql_free_dma(qla_host_t *ha)
630f10a77bbSDavid C Somayajulu {
631f10a77bbSDavid C Somayajulu 	uint32_t i;
632f10a77bbSDavid C Somayajulu 
633f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.sds_ring) {
634f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
635f10a77bbSDavid C Somayajulu 			ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]);
636f10a77bbSDavid C Somayajulu 		}
637f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.sds_ring = 0;
638f10a77bbSDavid C Somayajulu 	}
639f10a77bbSDavid C Somayajulu 
640f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.rds_ring) {
641f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_rds_rings; i++) {
642f10a77bbSDavid C Somayajulu 			ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]);
643f10a77bbSDavid C Somayajulu 		}
644f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.rds_ring = 0;
645f10a77bbSDavid C Somayajulu 	}
646f10a77bbSDavid C Somayajulu 
647f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.tx_ring) {
648f10a77bbSDavid C Somayajulu 		ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring);
649f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.tx_ring = 0;
650f10a77bbSDavid C Somayajulu 	}
6516a62bec0SDavid C Somayajulu 	ql_minidump_free(ha);
652f10a77bbSDavid C Somayajulu }
653f10a77bbSDavid C Somayajulu 
654f10a77bbSDavid C Somayajulu /*
655f10a77bbSDavid C Somayajulu  * Name: ql_alloc_dma
656f10a77bbSDavid C Somayajulu  * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts.
657f10a77bbSDavid C Somayajulu  */
658f10a77bbSDavid C Somayajulu int
659f10a77bbSDavid C Somayajulu ql_alloc_dma(qla_host_t *ha)
660f10a77bbSDavid C Somayajulu {
661f10a77bbSDavid C Somayajulu         device_t                dev;
662f10a77bbSDavid C Somayajulu 	uint32_t		i, j, size, tx_ring_size;
663f10a77bbSDavid C Somayajulu 	qla_hw_t		*hw;
664f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t	*tx_cntxt;
665f10a77bbSDavid C Somayajulu 	uint8_t			*vaddr;
666f10a77bbSDavid C Somayajulu 	bus_addr_t		paddr;
667f10a77bbSDavid C Somayajulu 
668f10a77bbSDavid C Somayajulu         dev = ha->pci_dev;
669f10a77bbSDavid C Somayajulu 
670f10a77bbSDavid C Somayajulu         QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
671f10a77bbSDavid C Somayajulu 
672f10a77bbSDavid C Somayajulu 	hw = &ha->hw;
673f10a77bbSDavid C Somayajulu 	/*
674f10a77bbSDavid C Somayajulu 	 * Allocate Transmit Ring
675f10a77bbSDavid C Somayajulu 	 */
676f10a77bbSDavid C Somayajulu 	tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS);
677f10a77bbSDavid C Somayajulu 	size = (tx_ring_size * ha->hw.num_tx_rings);
678f10a77bbSDavid C Somayajulu 
679f10a77bbSDavid C Somayajulu 	hw->dma_buf.tx_ring.alignment = 8;
680f10a77bbSDavid C Somayajulu 	hw->dma_buf.tx_ring.size = size + PAGE_SIZE;
681f10a77bbSDavid C Somayajulu 
682f10a77bbSDavid C Somayajulu         if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) {
683f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: tx ring alloc failed\n", __func__);
684f10a77bbSDavid C Somayajulu                 goto ql_alloc_dma_exit;
685f10a77bbSDavid C Somayajulu         }
686f10a77bbSDavid C Somayajulu 
687f10a77bbSDavid C Somayajulu 	vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b;
688f10a77bbSDavid C Somayajulu 	paddr = hw->dma_buf.tx_ring.dma_addr;
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_ring_base = (q80_tx_cmd_t *)vaddr;
694f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_ring_paddr = paddr;
695f10a77bbSDavid C Somayajulu 
696f10a77bbSDavid C Somayajulu 		vaddr += tx_ring_size;
697f10a77bbSDavid C Somayajulu 		paddr += tx_ring_size;
698f10a77bbSDavid C Somayajulu 	}
699f10a77bbSDavid C Somayajulu 
700f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
701f10a77bbSDavid C Somayajulu 		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
702f10a77bbSDavid C Somayajulu 
703f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_cons = (uint32_t *)vaddr;
704f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_cons_paddr = paddr;
705f10a77bbSDavid C Somayajulu 
706f10a77bbSDavid C Somayajulu 		vaddr += sizeof (uint32_t);
707f10a77bbSDavid C Somayajulu 		paddr += sizeof (uint32_t);
708f10a77bbSDavid C Somayajulu 	}
709f10a77bbSDavid C Somayajulu 
710f10a77bbSDavid C Somayajulu         ha->hw.dma_buf.flags.tx_ring = 1;
711f10a77bbSDavid C Somayajulu 
712f10a77bbSDavid C Somayajulu 	QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n",
713f10a77bbSDavid C Somayajulu 		__func__, (void *)(hw->dma_buf.tx_ring.dma_addr),
714f10a77bbSDavid C Somayajulu 		hw->dma_buf.tx_ring.dma_b));
715f10a77bbSDavid C Somayajulu 	/*
716f10a77bbSDavid C Somayajulu 	 * Allocate Receive Descriptor Rings
717f10a77bbSDavid C Somayajulu 	 */
718f10a77bbSDavid C Somayajulu 
719f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_rds_rings; i++) {
720f10a77bbSDavid C Somayajulu 
721f10a77bbSDavid C Somayajulu 		hw->dma_buf.rds_ring[i].alignment = 8;
722f10a77bbSDavid C Somayajulu 		hw->dma_buf.rds_ring[i].size =
723f10a77bbSDavid C Somayajulu 			(sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS;
724f10a77bbSDavid C Somayajulu 
725f10a77bbSDavid C Somayajulu 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) {
726f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: rds ring[%d] alloc failed\n",
727f10a77bbSDavid C Somayajulu 				__func__, i);
728f10a77bbSDavid C Somayajulu 
729f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
730f10a77bbSDavid C Somayajulu 				ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]);
731f10a77bbSDavid C Somayajulu 
732f10a77bbSDavid C Somayajulu 			goto ql_alloc_dma_exit;
733f10a77bbSDavid C Somayajulu 		}
734f10a77bbSDavid C Somayajulu 		QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n",
735f10a77bbSDavid C Somayajulu 			__func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr),
736f10a77bbSDavid C Somayajulu 			hw->dma_buf.rds_ring[i].dma_b));
737f10a77bbSDavid C Somayajulu 	}
738f10a77bbSDavid C Somayajulu 
739f10a77bbSDavid C Somayajulu 	hw->dma_buf.flags.rds_ring = 1;
740f10a77bbSDavid C Somayajulu 
741f10a77bbSDavid C Somayajulu 	/*
742f10a77bbSDavid C Somayajulu 	 * Allocate Status Descriptor Rings
743f10a77bbSDavid C Somayajulu 	 */
744f10a77bbSDavid C Somayajulu 
745f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
746f10a77bbSDavid C Somayajulu 		hw->dma_buf.sds_ring[i].alignment = 8;
747f10a77bbSDavid C Somayajulu 		hw->dma_buf.sds_ring[i].size =
748f10a77bbSDavid C Somayajulu 			(sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS;
749f10a77bbSDavid C Somayajulu 
750f10a77bbSDavid C Somayajulu 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) {
751f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: sds ring alloc failed\n",
752f10a77bbSDavid C Somayajulu 				__func__);
753f10a77bbSDavid C Somayajulu 
754f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
755f10a77bbSDavid C Somayajulu 				ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]);
756f10a77bbSDavid C Somayajulu 
757f10a77bbSDavid C Somayajulu 			goto ql_alloc_dma_exit;
758f10a77bbSDavid C Somayajulu 		}
759f10a77bbSDavid C Somayajulu 		QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n",
760f10a77bbSDavid C Somayajulu 			__func__, i,
761f10a77bbSDavid C Somayajulu 			(void *)(hw->dma_buf.sds_ring[i].dma_addr),
762f10a77bbSDavid C Somayajulu 			hw->dma_buf.sds_ring[i].dma_b));
763f10a77bbSDavid C Somayajulu 	}
764f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
765f10a77bbSDavid C Somayajulu 		hw->sds[i].sds_ring_base =
766f10a77bbSDavid C Somayajulu 			(q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b;
767f10a77bbSDavid C Somayajulu 	}
768f10a77bbSDavid C Somayajulu 
769f10a77bbSDavid C Somayajulu 	hw->dma_buf.flags.sds_ring = 1;
770f10a77bbSDavid C Somayajulu 
771f10a77bbSDavid C Somayajulu 	return 0;
772f10a77bbSDavid C Somayajulu 
773f10a77bbSDavid C Somayajulu ql_alloc_dma_exit:
774f10a77bbSDavid C Somayajulu 	ql_free_dma(ha);
775f10a77bbSDavid C Somayajulu 	return -1;
776f10a77bbSDavid C Somayajulu }
777f10a77bbSDavid C Somayajulu 
778f10a77bbSDavid C Somayajulu #define Q8_MBX_MSEC_DELAY	5000
779f10a77bbSDavid C Somayajulu 
780f10a77bbSDavid C Somayajulu static int
781f10a77bbSDavid C Somayajulu qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
782f10a77bbSDavid C Somayajulu 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause)
783f10a77bbSDavid C Somayajulu {
784f10a77bbSDavid C Somayajulu 	uint32_t i;
785f10a77bbSDavid C Somayajulu 	uint32_t data;
786f10a77bbSDavid C Somayajulu 	int ret = 0;
787f10a77bbSDavid C Somayajulu 
788f10a77bbSDavid C Somayajulu 	if (QL_ERR_INJECT(ha, INJCT_MBX_CMD_FAILURE)) {
789f10a77bbSDavid C Somayajulu 		ret = -3;
790f10a77bbSDavid C Somayajulu 		ha->qla_initiate_recovery = 1;
791f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
792f10a77bbSDavid C Somayajulu 	}
793f10a77bbSDavid C Somayajulu 
794f10a77bbSDavid C Somayajulu 	if (no_pause)
795f10a77bbSDavid C Somayajulu 		i = 1000;
796f10a77bbSDavid C Somayajulu 	else
797f10a77bbSDavid C Somayajulu 		i = Q8_MBX_MSEC_DELAY;
798f10a77bbSDavid C Somayajulu 
799f10a77bbSDavid C Somayajulu 	while (i) {
800f10a77bbSDavid C Somayajulu 		data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL);
801f10a77bbSDavid C Somayajulu 		if (data == 0)
802f10a77bbSDavid C Somayajulu 			break;
803f10a77bbSDavid C Somayajulu 		if (no_pause) {
804f10a77bbSDavid C Somayajulu 			DELAY(1000);
805f10a77bbSDavid C Somayajulu 		} else {
806f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
807f10a77bbSDavid C Somayajulu 		}
808f10a77bbSDavid C Somayajulu 		i--;
809f10a77bbSDavid C Somayajulu 	}
810f10a77bbSDavid C Somayajulu 
811f10a77bbSDavid C Somayajulu 	if (i == 0) {
812f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n",
813f10a77bbSDavid C Somayajulu 			__func__, data);
814f10a77bbSDavid C Somayajulu 		ret = -1;
815f10a77bbSDavid C Somayajulu 		ha->qla_initiate_recovery = 1;
816f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
817f10a77bbSDavid C Somayajulu 	}
818f10a77bbSDavid C Somayajulu 
819f10a77bbSDavid C Somayajulu 	for (i = 0; i < n_hmbox; i++) {
820f10a77bbSDavid C Somayajulu 		WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox);
821f10a77bbSDavid C Somayajulu 		h_mbox++;
822f10a77bbSDavid C Somayajulu 	}
823f10a77bbSDavid C Somayajulu 
824f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1);
825f10a77bbSDavid C Somayajulu 
826f10a77bbSDavid C Somayajulu 
827f10a77bbSDavid C Somayajulu 	i = Q8_MBX_MSEC_DELAY;
828f10a77bbSDavid C Somayajulu 	while (i) {
829f10a77bbSDavid C Somayajulu 		data = READ_REG32(ha, Q8_FW_MBOX_CNTRL);
830f10a77bbSDavid C Somayajulu 
831f10a77bbSDavid C Somayajulu 		if ((data & 0x3) == 1) {
832f10a77bbSDavid C Somayajulu 			data = READ_REG32(ha, Q8_FW_MBOX0);
833f10a77bbSDavid C Somayajulu 			if ((data & 0xF000) != 0x8000)
834f10a77bbSDavid C Somayajulu 				break;
835f10a77bbSDavid C Somayajulu 		}
836f10a77bbSDavid C Somayajulu 		if (no_pause) {
837f10a77bbSDavid C Somayajulu 			DELAY(1000);
838f10a77bbSDavid C Somayajulu 		} else {
839f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
840f10a77bbSDavid C Somayajulu 		}
841f10a77bbSDavid C Somayajulu 		i--;
842f10a77bbSDavid C Somayajulu 	}
843f10a77bbSDavid C Somayajulu 	if (i == 0) {
844f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n",
845f10a77bbSDavid C Somayajulu 			__func__, data);
846f10a77bbSDavid C Somayajulu 		ret = -2;
847f10a77bbSDavid C Somayajulu 		ha->qla_initiate_recovery = 1;
848f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
849f10a77bbSDavid C Somayajulu 	}
850f10a77bbSDavid C Somayajulu 
851f10a77bbSDavid C Somayajulu 	for (i = 0; i < n_fwmbox; i++) {
852f10a77bbSDavid C Somayajulu 		*fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2)));
853f10a77bbSDavid C Somayajulu 	}
854f10a77bbSDavid C Somayajulu 
855f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0);
856f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
857f10a77bbSDavid C Somayajulu 
858f10a77bbSDavid C Somayajulu exit_qla_mbx_cmd:
859f10a77bbSDavid C Somayajulu 	return (ret);
860f10a77bbSDavid C Somayajulu }
861f10a77bbSDavid C Somayajulu 
86235291c22SDavid C Somayajulu int
86335291c22SDavid C Somayajulu qla_get_nic_partition(qla_host_t *ha, uint32_t *supports_9kb,
86435291c22SDavid C Somayajulu 	uint32_t *num_rcvq)
865f10a77bbSDavid C Somayajulu {
866f10a77bbSDavid C Somayajulu 	uint32_t *mbox, err;
867f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
868f10a77bbSDavid C Somayajulu 
869f10a77bbSDavid C Somayajulu 	bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX));
870f10a77bbSDavid C Somayajulu 
871f10a77bbSDavid C Somayajulu 	mbox = ha->hw.mbox;
872f10a77bbSDavid C Somayajulu 
873f10a77bbSDavid C Somayajulu 	mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29);
874f10a77bbSDavid C Somayajulu 
875f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) {
876f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
877f10a77bbSDavid C Somayajulu 		return (-1);
878f10a77bbSDavid C Somayajulu 	}
879f10a77bbSDavid C Somayajulu 	err = mbox[0] >> 25;
880f10a77bbSDavid C Somayajulu 
88135291c22SDavid C Somayajulu 	if (supports_9kb != NULL) {
88235291c22SDavid C Somayajulu 		if (mbox[16] & 0x80) /* bit 7 of mbox 16 */
88335291c22SDavid C Somayajulu 			*supports_9kb = 1;
88435291c22SDavid C Somayajulu 		else
88535291c22SDavid C Somayajulu 			*supports_9kb = 0;
88635291c22SDavid C Somayajulu 	}
88735291c22SDavid C Somayajulu 
88835291c22SDavid C Somayajulu 	if (num_rcvq != NULL)
88935291c22SDavid C Somayajulu 		*num_rcvq =  ((mbox[6] >> 16) & 0xFFFF);
89035291c22SDavid C Somayajulu 
891f10a77bbSDavid C Somayajulu 	if ((err != 1) && (err != 0)) {
892f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
893f10a77bbSDavid C Somayajulu 		return (-1);
894f10a77bbSDavid C Somayajulu 	}
895f10a77bbSDavid C Somayajulu 	return 0;
896f10a77bbSDavid C Somayajulu }
897f10a77bbSDavid C Somayajulu 
898f10a77bbSDavid C Somayajulu static int
89935291c22SDavid C Somayajulu qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, uint32_t num_intrs,
90035291c22SDavid C Somayajulu 	uint32_t create)
901f10a77bbSDavid C Somayajulu {
902f10a77bbSDavid C Somayajulu 	uint32_t i, err;
903f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
904f10a77bbSDavid C Somayajulu 	q80_config_intr_t *c_intr;
905f10a77bbSDavid C Somayajulu 	q80_config_intr_rsp_t *c_intr_rsp;
906f10a77bbSDavid C Somayajulu 
907f10a77bbSDavid C Somayajulu 	c_intr = (q80_config_intr_t *)ha->hw.mbox;
908f10a77bbSDavid C Somayajulu 	bzero(c_intr, (sizeof (q80_config_intr_t)));
909f10a77bbSDavid C Somayajulu 
910f10a77bbSDavid C Somayajulu 	c_intr->opcode = Q8_MBX_CONFIG_INTR;
911f10a77bbSDavid C Somayajulu 
912f10a77bbSDavid C Somayajulu 	c_intr->count_version = (sizeof (q80_config_intr_t) >> 2);
913f10a77bbSDavid C Somayajulu 	c_intr->count_version |= Q8_MBX_CMD_VERSION;
914f10a77bbSDavid C Somayajulu 
915f10a77bbSDavid C Somayajulu 	c_intr->nentries = num_intrs;
916f10a77bbSDavid C Somayajulu 
917f10a77bbSDavid C Somayajulu 	for (i = 0; i < num_intrs; i++) {
918f10a77bbSDavid C Somayajulu 		if (create) {
919f10a77bbSDavid C Somayajulu 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE;
92035291c22SDavid C Somayajulu 			c_intr->intr[i].msix_index = start_idx + 1 + i;
921f10a77bbSDavid C Somayajulu 		} else {
922f10a77bbSDavid C Somayajulu 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE;
92335291c22SDavid C Somayajulu 			c_intr->intr[i].msix_index =
92435291c22SDavid C Somayajulu 				ha->hw.intr_id[(start_idx + i)];
925f10a77bbSDavid C Somayajulu 		}
926f10a77bbSDavid C Somayajulu 
927f10a77bbSDavid C Somayajulu 		c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X;
928f10a77bbSDavid C Somayajulu 	}
929f10a77bbSDavid C Somayajulu 
930f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_intr,
931f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_intr_t) >> 2),
932f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) {
933f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
934f10a77bbSDavid C Somayajulu 		return (-1);
935f10a77bbSDavid C Somayajulu 	}
936f10a77bbSDavid C Somayajulu 
937f10a77bbSDavid C Somayajulu 	c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox;
938f10a77bbSDavid C Somayajulu 
939f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status);
940f10a77bbSDavid C Somayajulu 
941f10a77bbSDavid C Somayajulu 	if (err) {
942f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x, %d]\n", __func__, err,
943f10a77bbSDavid C Somayajulu 			c_intr_rsp->nentries);
944f10a77bbSDavid C Somayajulu 
945f10a77bbSDavid C Somayajulu 		for (i = 0; i < c_intr_rsp->nentries; i++) {
946f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n",
947f10a77bbSDavid C Somayajulu 				__func__, i,
948f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].status,
949f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].intr_id,
950f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].intr_src);
951f10a77bbSDavid C Somayajulu 		}
952f10a77bbSDavid C Somayajulu 
953f10a77bbSDavid C Somayajulu 		return (-1);
954f10a77bbSDavid C Somayajulu 	}
955f10a77bbSDavid C Somayajulu 
956f10a77bbSDavid C Somayajulu 	for (i = 0; ((i < num_intrs) && create); i++) {
957f10a77bbSDavid C Somayajulu 		if (!c_intr_rsp->intr[i].status) {
95835291c22SDavid C Somayajulu 			ha->hw.intr_id[(start_idx + i)] =
95935291c22SDavid C Somayajulu 				c_intr_rsp->intr[i].intr_id;
96035291c22SDavid C Somayajulu 			ha->hw.intr_src[(start_idx + i)] =
96135291c22SDavid C Somayajulu 				c_intr_rsp->intr[i].intr_src;
962f10a77bbSDavid C Somayajulu 		}
963f10a77bbSDavid C Somayajulu 	}
964f10a77bbSDavid C Somayajulu 
965f10a77bbSDavid C Somayajulu 	return (0);
966f10a77bbSDavid C Somayajulu }
967f10a77bbSDavid C Somayajulu 
968f10a77bbSDavid C Somayajulu /*
969f10a77bbSDavid C Somayajulu  * Name: qla_config_rss
970f10a77bbSDavid C Somayajulu  * Function: Configure RSS for the context/interface.
971f10a77bbSDavid C Somayajulu  */
972f10a77bbSDavid C Somayajulu static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL,
973f10a77bbSDavid C Somayajulu 			0x8030f20c77cb2da3ULL,
974f10a77bbSDavid C Somayajulu 			0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
975f10a77bbSDavid C Somayajulu 			0x255b0ec26d5a56daULL };
976f10a77bbSDavid C Somayajulu 
977f10a77bbSDavid C Somayajulu static int
978f10a77bbSDavid C Somayajulu qla_config_rss(qla_host_t *ha, uint16_t cntxt_id)
979f10a77bbSDavid C Somayajulu {
980f10a77bbSDavid C Somayajulu 	q80_config_rss_t	*c_rss;
981f10a77bbSDavid C Somayajulu 	q80_config_rss_rsp_t	*c_rss_rsp;
982f10a77bbSDavid C Somayajulu 	uint32_t		err, i;
983f10a77bbSDavid C Somayajulu 	device_t		dev = ha->pci_dev;
984f10a77bbSDavid C Somayajulu 
985f10a77bbSDavid C Somayajulu 	c_rss = (q80_config_rss_t *)ha->hw.mbox;
986f10a77bbSDavid C Somayajulu 	bzero(c_rss, (sizeof (q80_config_rss_t)));
987f10a77bbSDavid C Somayajulu 
988f10a77bbSDavid C Somayajulu 	c_rss->opcode = Q8_MBX_CONFIG_RSS;
989f10a77bbSDavid C Somayajulu 
990f10a77bbSDavid C Somayajulu 	c_rss->count_version = (sizeof (q80_config_rss_t) >> 2);
991f10a77bbSDavid C Somayajulu 	c_rss->count_version |= Q8_MBX_CMD_VERSION;
992f10a77bbSDavid C Somayajulu 
993f10a77bbSDavid C Somayajulu 	c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP |
994f10a77bbSDavid C Somayajulu 				Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP);
99535291c22SDavid C Somayajulu 	//c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP |
99635291c22SDavid C Somayajulu 	//			Q8_MBX_RSS_HASH_TYPE_IPV6_TCP);
997f10a77bbSDavid C Somayajulu 
998f10a77bbSDavid C Somayajulu 	c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS;
999f10a77bbSDavid C Somayajulu 	c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE;
1000f10a77bbSDavid C Somayajulu 
1001f10a77bbSDavid C Somayajulu 	c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK;
1002f10a77bbSDavid C Somayajulu 
1003f10a77bbSDavid C Somayajulu 	c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID;
1004f10a77bbSDavid C Somayajulu 	c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS;
1005f10a77bbSDavid C Somayajulu 
1006f10a77bbSDavid C Somayajulu 	c_rss->cntxt_id = cntxt_id;
1007f10a77bbSDavid C Somayajulu 
1008f10a77bbSDavid C Somayajulu 	for (i = 0; i < 5; i++) {
1009f10a77bbSDavid C Somayajulu 		c_rss->rss_key[i] = rss_key[i];
1010f10a77bbSDavid C Somayajulu 	}
1011f10a77bbSDavid C Somayajulu 
1012f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss,
1013f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_rss_t) >> 2),
1014f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) {
1015f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1016f10a77bbSDavid C Somayajulu 		return (-1);
1017f10a77bbSDavid C Somayajulu 	}
1018f10a77bbSDavid C Somayajulu 	c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox;
1019f10a77bbSDavid C Somayajulu 
1020f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status);
1021f10a77bbSDavid C Somayajulu 
1022f10a77bbSDavid C Somayajulu 	if (err) {
1023f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1024f10a77bbSDavid C Somayajulu 		return (-1);
1025f10a77bbSDavid C Somayajulu 	}
1026f10a77bbSDavid C Somayajulu 	return 0;
1027f10a77bbSDavid C Somayajulu }
1028f10a77bbSDavid C Somayajulu 
1029f10a77bbSDavid C Somayajulu static int
1030f10a77bbSDavid C Somayajulu qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count,
1031f10a77bbSDavid C Somayajulu         uint16_t cntxt_id, uint8_t *ind_table)
1032f10a77bbSDavid C Somayajulu {
1033f10a77bbSDavid C Somayajulu         q80_config_rss_ind_table_t      *c_rss_ind;
1034f10a77bbSDavid C Somayajulu         q80_config_rss_ind_table_rsp_t  *c_rss_ind_rsp;
1035f10a77bbSDavid C Somayajulu         uint32_t                        err;
1036f10a77bbSDavid C Somayajulu         device_t                        dev = ha->pci_dev;
1037f10a77bbSDavid C Somayajulu 
1038f10a77bbSDavid C Somayajulu 	if ((count > Q8_RSS_IND_TBL_SIZE) ||
1039f10a77bbSDavid C Somayajulu 		((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) {
1040f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: illegal count [%d, %d]\n", __func__,
1041f10a77bbSDavid C Somayajulu 			start_idx, count);
1042f10a77bbSDavid C Somayajulu 		return (-1);
1043f10a77bbSDavid C Somayajulu 	}
1044f10a77bbSDavid C Somayajulu 
1045f10a77bbSDavid C Somayajulu         c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox;
1046f10a77bbSDavid C Somayajulu         bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t));
1047f10a77bbSDavid C Somayajulu 
1048f10a77bbSDavid C Somayajulu         c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE;
1049f10a77bbSDavid C Somayajulu         c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2);
1050f10a77bbSDavid C Somayajulu         c_rss_ind->count_version |= Q8_MBX_CMD_VERSION;
1051f10a77bbSDavid C Somayajulu 
1052f10a77bbSDavid C Somayajulu 	c_rss_ind->start_idx = start_idx;
1053f10a77bbSDavid C Somayajulu 	c_rss_ind->end_idx = start_idx + count - 1;
1054f10a77bbSDavid C Somayajulu 	c_rss_ind->cntxt_id = cntxt_id;
1055f10a77bbSDavid C Somayajulu 	bcopy(ind_table, c_rss_ind->ind_table, count);
1056f10a77bbSDavid C Somayajulu 
1057f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind,
1058f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox,
1059f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) {
1060f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1061f10a77bbSDavid C Somayajulu 		return (-1);
1062f10a77bbSDavid C Somayajulu 	}
1063f10a77bbSDavid C Somayajulu 
1064f10a77bbSDavid C Somayajulu 	c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox;
1065f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status);
1066f10a77bbSDavid C Somayajulu 
1067f10a77bbSDavid C Somayajulu 	if (err) {
1068f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1069f10a77bbSDavid C Somayajulu 		return (-1);
1070f10a77bbSDavid C Somayajulu 	}
1071f10a77bbSDavid C Somayajulu 	return 0;
1072f10a77bbSDavid C Somayajulu }
1073f10a77bbSDavid C Somayajulu 
1074f10a77bbSDavid C Somayajulu /*
1075f10a77bbSDavid C Somayajulu  * Name: qla_config_intr_coalesce
1076f10a77bbSDavid C Somayajulu  * Function: Configure Interrupt Coalescing.
1077f10a77bbSDavid C Somayajulu  */
1078f10a77bbSDavid C Somayajulu static int
107935291c22SDavid C Somayajulu qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable,
108035291c22SDavid C Somayajulu 	int rcv)
1081f10a77bbSDavid C Somayajulu {
1082f10a77bbSDavid C Somayajulu 	q80_config_intr_coalesc_t	*intrc;
1083f10a77bbSDavid C Somayajulu 	q80_config_intr_coalesc_rsp_t	*intrc_rsp;
1084f10a77bbSDavid C Somayajulu 	uint32_t			err, i;
1085f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1086f10a77bbSDavid C Somayajulu 
1087f10a77bbSDavid C Somayajulu 	intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox;
1088f10a77bbSDavid C Somayajulu 	bzero(intrc, (sizeof (q80_config_intr_coalesc_t)));
1089f10a77bbSDavid C Somayajulu 
1090f10a77bbSDavid C Somayajulu 	intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE;
1091f10a77bbSDavid C Somayajulu 	intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2);
1092f10a77bbSDavid C Somayajulu 	intrc->count_version |= Q8_MBX_CMD_VERSION;
1093f10a77bbSDavid C Somayajulu 
109435291c22SDavid C Somayajulu 	if (rcv) {
1095f10a77bbSDavid C Somayajulu 		intrc->flags = Q8_MBX_INTRC_FLAGS_RCV;
109635291c22SDavid C Somayajulu 		intrc->max_pkts = ha->hw.rcv_intr_coalesce & 0xFFFF;
109735291c22SDavid C Somayajulu 		intrc->max_mswait = (ha->hw.rcv_intr_coalesce >> 16) & 0xFFFF;
109835291c22SDavid C Somayajulu 	} else {
109935291c22SDavid C Somayajulu 		intrc->flags = Q8_MBX_INTRC_FLAGS_XMT;
110035291c22SDavid C Somayajulu 		intrc->max_pkts = ha->hw.xmt_intr_coalesce & 0xFFFF;
110135291c22SDavid C Somayajulu 		intrc->max_mswait = (ha->hw.xmt_intr_coalesce >> 16) & 0xFFFF;
110235291c22SDavid C Somayajulu 	}
1103f10a77bbSDavid C Somayajulu 
110435291c22SDavid C Somayajulu 	intrc->cntxt_id = cntxt_id;
1105f10a77bbSDavid C Somayajulu 
1106f10a77bbSDavid C Somayajulu 	if (tenable) {
1107f10a77bbSDavid C Somayajulu 		intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC;
1108f10a77bbSDavid C Somayajulu 		intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC;
1109f10a77bbSDavid C Somayajulu 
1110f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
1111f10a77bbSDavid C Somayajulu 			intrc->sds_ring_mask |= (1 << i);
1112f10a77bbSDavid C Somayajulu 		}
1113f10a77bbSDavid C Somayajulu 		intrc->ms_timeout = 1000;
1114f10a77bbSDavid C Somayajulu 	}
1115f10a77bbSDavid C Somayajulu 
1116f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)intrc,
1117f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_intr_coalesc_t) >> 2),
1118f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) {
1119f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1120f10a77bbSDavid C Somayajulu 		return (-1);
1121f10a77bbSDavid C Somayajulu 	}
1122f10a77bbSDavid C Somayajulu 	intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox;
1123f10a77bbSDavid C Somayajulu 
1124f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status);
1125f10a77bbSDavid C Somayajulu 
1126f10a77bbSDavid C Somayajulu 	if (err) {
1127f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1128f10a77bbSDavid C Somayajulu 		return (-1);
1129f10a77bbSDavid C Somayajulu 	}
1130f10a77bbSDavid C Somayajulu 
1131f10a77bbSDavid C Somayajulu 	return 0;
1132f10a77bbSDavid C Somayajulu }
1133f10a77bbSDavid C Somayajulu 
1134f10a77bbSDavid C Somayajulu 
1135f10a77bbSDavid C Somayajulu /*
1136f10a77bbSDavid C Somayajulu  * Name: qla_config_mac_addr
1137f10a77bbSDavid C Somayajulu  * Function: binds a MAC address to the context/interface.
1138f10a77bbSDavid C Somayajulu  *	Can be unicast, multicast or broadcast.
1139f10a77bbSDavid C Somayajulu  */
1140f10a77bbSDavid C Somayajulu static int
1141da834d52SDavid C Somayajulu qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac,
1142da834d52SDavid C Somayajulu 	uint32_t num_mac)
1143f10a77bbSDavid C Somayajulu {
1144f10a77bbSDavid C Somayajulu 	q80_config_mac_addr_t		*cmac;
1145f10a77bbSDavid C Somayajulu 	q80_config_mac_addr_rsp_t	*cmac_rsp;
1146f10a77bbSDavid C Somayajulu 	uint32_t			err;
1147f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1148da834d52SDavid C Somayajulu 	int				i;
1149da834d52SDavid C Somayajulu 	uint8_t				*mac_cpy = mac_addr;
1150da834d52SDavid C Somayajulu 
1151da834d52SDavid C Somayajulu 	if (num_mac > Q8_MAX_MAC_ADDRS) {
1152da834d52SDavid C Somayajulu 		device_printf(dev, "%s: %s num_mac [0x%x] > Q8_MAX_MAC_ADDRS\n",
1153da834d52SDavid C Somayajulu 			__func__, (add_mac ? "Add" : "Del"), num_mac);
1154da834d52SDavid C Somayajulu 		return (-1);
1155da834d52SDavid C Somayajulu 	}
1156f10a77bbSDavid C Somayajulu 
1157f10a77bbSDavid C Somayajulu 	cmac = (q80_config_mac_addr_t *)ha->hw.mbox;
1158f10a77bbSDavid C Somayajulu 	bzero(cmac, (sizeof (q80_config_mac_addr_t)));
1159f10a77bbSDavid C Somayajulu 
1160f10a77bbSDavid C Somayajulu 	cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR;
1161f10a77bbSDavid C Somayajulu 	cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2;
1162f10a77bbSDavid C Somayajulu 	cmac->count_version |= Q8_MBX_CMD_VERSION;
1163f10a77bbSDavid C Somayajulu 
1164f10a77bbSDavid C Somayajulu 	if (add_mac)
1165f10a77bbSDavid C Somayajulu 		cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR;
1166f10a77bbSDavid C Somayajulu 	else
1167f10a77bbSDavid C Somayajulu 		cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR;
1168f10a77bbSDavid C Somayajulu 
1169f10a77bbSDavid C Somayajulu 	cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS;
1170f10a77bbSDavid C Somayajulu 
1171da834d52SDavid C Somayajulu 	cmac->nmac_entries = num_mac;
1172f10a77bbSDavid C Somayajulu 	cmac->cntxt_id = ha->hw.rcv_cntxt_id;
1173da834d52SDavid C Somayajulu 
1174da834d52SDavid C Somayajulu 	for (i = 0; i < num_mac; i++) {
1175da834d52SDavid C Somayajulu 		bcopy(mac_addr, cmac->mac_addr[i].addr, Q8_ETHER_ADDR_LEN);
1176da834d52SDavid C Somayajulu 		mac_addr = mac_addr + ETHER_ADDR_LEN;
1177da834d52SDavid C Somayajulu 	}
1178f10a77bbSDavid C Somayajulu 
1179f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)cmac,
1180f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_mac_addr_t) >> 2),
1181f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) {
1182f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: %s failed0\n", __func__,
1183f10a77bbSDavid C Somayajulu 			(add_mac ? "Add" : "Del"));
1184f10a77bbSDavid C Somayajulu 		return (-1);
1185f10a77bbSDavid C Somayajulu 	}
1186f10a77bbSDavid C Somayajulu 	cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox;
1187f10a77bbSDavid C Somayajulu 
1188f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status);
1189f10a77bbSDavid C Somayajulu 
1190f10a77bbSDavid C Somayajulu 	if (err) {
1191da834d52SDavid C Somayajulu 		device_printf(dev, "%s: %s failed1 [0x%08x]\n", __func__,
1192da834d52SDavid C Somayajulu 			(add_mac ? "Add" : "Del"), err);
1193da834d52SDavid C Somayajulu 		for (i = 0; i < num_mac; i++) {
1194da834d52SDavid C Somayajulu 			device_printf(dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
1195da834d52SDavid C Somayajulu 				__func__, mac_cpy[0], mac_cpy[1], mac_cpy[2],
1196da834d52SDavid C Somayajulu 				mac_cpy[3], mac_cpy[4], mac_cpy[5]);
1197da834d52SDavid C Somayajulu 			mac_cpy += ETHER_ADDR_LEN;
1198da834d52SDavid C Somayajulu 		}
1199f10a77bbSDavid C Somayajulu 		return (-1);
1200f10a77bbSDavid C Somayajulu 	}
1201f10a77bbSDavid C Somayajulu 
1202f10a77bbSDavid C Somayajulu 	return 0;
1203f10a77bbSDavid C Somayajulu }
1204f10a77bbSDavid C Somayajulu 
1205f10a77bbSDavid C Somayajulu 
1206f10a77bbSDavid C Somayajulu /*
1207f10a77bbSDavid C Somayajulu  * Name: qla_set_mac_rcv_mode
12086a62bec0SDavid C Somayajulu  * Function: Enable/Disable AllMulticast and Promiscous Modes.
1209f10a77bbSDavid C Somayajulu  */
1210f10a77bbSDavid C Somayajulu static int
1211f10a77bbSDavid C Somayajulu qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode)
1212f10a77bbSDavid C Somayajulu {
1213f10a77bbSDavid C Somayajulu 	q80_config_mac_rcv_mode_t	*rcv_mode;
1214f10a77bbSDavid C Somayajulu 	uint32_t			err;
1215f10a77bbSDavid C Somayajulu 	q80_config_mac_rcv_mode_rsp_t	*rcv_mode_rsp;
1216f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1217f10a77bbSDavid C Somayajulu 
1218f10a77bbSDavid C Somayajulu 	rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox;
1219f10a77bbSDavid C Somayajulu 	bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t)));
1220f10a77bbSDavid C Somayajulu 
1221f10a77bbSDavid C Somayajulu 	rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE;
1222f10a77bbSDavid C Somayajulu 	rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2;
1223f10a77bbSDavid C Somayajulu 	rcv_mode->count_version |= Q8_MBX_CMD_VERSION;
1224f10a77bbSDavid C Somayajulu 
1225f10a77bbSDavid C Somayajulu 	rcv_mode->mode = mode;
1226f10a77bbSDavid C Somayajulu 
1227f10a77bbSDavid C Somayajulu 	rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id;
1228f10a77bbSDavid C Somayajulu 
1229f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode,
1230f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_mac_rcv_mode_t) >> 2),
1231f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) {
1232f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1233f10a77bbSDavid C Somayajulu 		return (-1);
1234f10a77bbSDavid C Somayajulu 	}
1235f10a77bbSDavid C Somayajulu 	rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox;
1236f10a77bbSDavid C Somayajulu 
1237f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status);
1238f10a77bbSDavid C Somayajulu 
1239f10a77bbSDavid C Somayajulu 	if (err) {
1240f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1241f10a77bbSDavid C Somayajulu 		return (-1);
1242f10a77bbSDavid C Somayajulu 	}
1243f10a77bbSDavid C Somayajulu 
1244f10a77bbSDavid C Somayajulu 	return 0;
1245f10a77bbSDavid C Somayajulu }
1246f10a77bbSDavid C Somayajulu 
1247f10a77bbSDavid C Somayajulu int
1248f10a77bbSDavid C Somayajulu ql_set_promisc(qla_host_t *ha)
1249f10a77bbSDavid C Somayajulu {
1250f10a77bbSDavid C Somayajulu 	int ret;
1251f10a77bbSDavid C Somayajulu 
1252f10a77bbSDavid C Somayajulu 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1253f10a77bbSDavid C Somayajulu 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1254f10a77bbSDavid C Somayajulu 	return (ret);
1255f10a77bbSDavid C Somayajulu }
1256f10a77bbSDavid C Somayajulu 
125735291c22SDavid C Somayajulu void
125835291c22SDavid C Somayajulu qla_reset_promisc(qla_host_t *ha)
125935291c22SDavid C Somayajulu {
126035291c22SDavid C Somayajulu 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE;
126135291c22SDavid C Somayajulu 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
126235291c22SDavid C Somayajulu }
126335291c22SDavid C Somayajulu 
1264f10a77bbSDavid C Somayajulu int
1265f10a77bbSDavid C Somayajulu ql_set_allmulti(qla_host_t *ha)
1266f10a77bbSDavid C Somayajulu {
1267f10a77bbSDavid C Somayajulu 	int ret;
1268f10a77bbSDavid C Somayajulu 
1269f10a77bbSDavid C Somayajulu 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE;
1270f10a77bbSDavid C Somayajulu 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1271f10a77bbSDavid C Somayajulu 	return (ret);
1272f10a77bbSDavid C Somayajulu }
1273f10a77bbSDavid C Somayajulu 
127435291c22SDavid C Somayajulu void
127535291c22SDavid C Somayajulu qla_reset_allmulti(qla_host_t *ha)
127635291c22SDavid C Somayajulu {
127735291c22SDavid C Somayajulu 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE;
127835291c22SDavid C Somayajulu 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
127935291c22SDavid C Somayajulu }
1280f10a77bbSDavid C Somayajulu 
1281f10a77bbSDavid C Somayajulu /*
1282f10a77bbSDavid C Somayajulu  * Name: ql_set_max_mtu
1283f10a77bbSDavid C Somayajulu  * Function:
1284f10a77bbSDavid C Somayajulu  *	Sets the maximum transfer unit size for the specified rcv context.
1285f10a77bbSDavid C Somayajulu  */
1286f10a77bbSDavid C Somayajulu int
1287f10a77bbSDavid C Somayajulu ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id)
1288f10a77bbSDavid C Somayajulu {
1289f10a77bbSDavid C Somayajulu 	device_t		dev;
1290f10a77bbSDavid C Somayajulu 	q80_set_max_mtu_t	*max_mtu;
1291f10a77bbSDavid C Somayajulu 	q80_set_max_mtu_rsp_t	*max_mtu_rsp;
1292f10a77bbSDavid C Somayajulu 	uint32_t		err;
1293f10a77bbSDavid C Somayajulu 
1294f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1295f10a77bbSDavid C Somayajulu 
1296f10a77bbSDavid C Somayajulu 	max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox;
1297f10a77bbSDavid C Somayajulu 	bzero(max_mtu, (sizeof (q80_set_max_mtu_t)));
1298f10a77bbSDavid C Somayajulu 
1299f10a77bbSDavid C Somayajulu 	max_mtu->opcode = Q8_MBX_SET_MAX_MTU;
1300f10a77bbSDavid C Somayajulu 	max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2);
1301f10a77bbSDavid C Somayajulu 	max_mtu->count_version |= Q8_MBX_CMD_VERSION;
1302f10a77bbSDavid C Somayajulu 
1303f10a77bbSDavid C Somayajulu 	max_mtu->cntxt_id = cntxt_id;
1304f10a77bbSDavid C Somayajulu 	max_mtu->mtu = mtu;
1305f10a77bbSDavid C Somayajulu 
1306f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)max_mtu,
1307f10a77bbSDavid C Somayajulu 		(sizeof (q80_set_max_mtu_t) >> 2),
1308f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) {
1309f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1310f10a77bbSDavid C Somayajulu                 return -1;
1311f10a77bbSDavid C Somayajulu         }
1312f10a77bbSDavid C Somayajulu 
1313f10a77bbSDavid C Somayajulu 	max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox;
1314f10a77bbSDavid C Somayajulu 
1315f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status);
1316f10a77bbSDavid C Somayajulu 
1317f10a77bbSDavid C Somayajulu         if (err) {
1318f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1319f10a77bbSDavid C Somayajulu         }
1320f10a77bbSDavid C Somayajulu 
1321f10a77bbSDavid C Somayajulu 	return 0;
1322f10a77bbSDavid C Somayajulu }
1323f10a77bbSDavid C Somayajulu 
1324f10a77bbSDavid C Somayajulu static int
1325f10a77bbSDavid C Somayajulu qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id)
1326f10a77bbSDavid C Somayajulu {
1327f10a77bbSDavid C Somayajulu 	device_t		dev;
1328f10a77bbSDavid C Somayajulu 	q80_link_event_t	*lnk;
1329f10a77bbSDavid C Somayajulu 	q80_link_event_rsp_t	*lnk_rsp;
1330f10a77bbSDavid C Somayajulu 	uint32_t		err;
1331f10a77bbSDavid C Somayajulu 
1332f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1333f10a77bbSDavid C Somayajulu 
1334f10a77bbSDavid C Somayajulu 	lnk = (q80_link_event_t *)ha->hw.mbox;
1335f10a77bbSDavid C Somayajulu 	bzero(lnk, (sizeof (q80_link_event_t)));
1336f10a77bbSDavid C Somayajulu 
1337f10a77bbSDavid C Somayajulu 	lnk->opcode = Q8_MBX_LINK_EVENT_REQ;
1338f10a77bbSDavid C Somayajulu 	lnk->count_version = (sizeof (q80_link_event_t) >> 2);
1339f10a77bbSDavid C Somayajulu 	lnk->count_version |= Q8_MBX_CMD_VERSION;
1340f10a77bbSDavid C Somayajulu 
1341f10a77bbSDavid C Somayajulu 	lnk->cntxt_id = cntxt_id;
1342f10a77bbSDavid C Somayajulu 	lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC;
1343f10a77bbSDavid C Somayajulu 
1344f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2),
1345f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) {
1346f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1347f10a77bbSDavid C Somayajulu                 return -1;
1348f10a77bbSDavid C Somayajulu         }
1349f10a77bbSDavid C Somayajulu 
1350f10a77bbSDavid C Somayajulu 	lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox;
1351f10a77bbSDavid C Somayajulu 
1352f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status);
1353f10a77bbSDavid C Somayajulu 
1354f10a77bbSDavid C Somayajulu         if (err) {
1355f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1356f10a77bbSDavid C Somayajulu         }
1357f10a77bbSDavid C Somayajulu 
1358f10a77bbSDavid C Somayajulu 	return 0;
1359f10a77bbSDavid C Somayajulu }
1360f10a77bbSDavid C Somayajulu 
1361f10a77bbSDavid C Somayajulu static int
1362f10a77bbSDavid C Somayajulu qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id)
1363f10a77bbSDavid C Somayajulu {
1364f10a77bbSDavid C Somayajulu 	device_t		dev;
1365f10a77bbSDavid C Somayajulu 	q80_config_fw_lro_t	*fw_lro;
1366f10a77bbSDavid C Somayajulu 	q80_config_fw_lro_rsp_t	*fw_lro_rsp;
1367f10a77bbSDavid C Somayajulu 	uint32_t		err;
1368f10a77bbSDavid C Somayajulu 
1369f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1370f10a77bbSDavid C Somayajulu 
1371f10a77bbSDavid C Somayajulu 	fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox;
1372f10a77bbSDavid C Somayajulu 	bzero(fw_lro, sizeof(q80_config_fw_lro_t));
1373f10a77bbSDavid C Somayajulu 
1374f10a77bbSDavid C Somayajulu 	fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO;
1375f10a77bbSDavid C Somayajulu 	fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2);
1376f10a77bbSDavid C Somayajulu 	fw_lro->count_version |= Q8_MBX_CMD_VERSION;
1377f10a77bbSDavid C Somayajulu 
1378f10a77bbSDavid C Somayajulu 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK;
137935291c22SDavid C Somayajulu 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK;
1380f10a77bbSDavid C Somayajulu 
1381f10a77bbSDavid C Somayajulu 	fw_lro->cntxt_id = cntxt_id;
1382f10a77bbSDavid C Somayajulu 
1383f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)fw_lro,
1384f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_fw_lro_t) >> 2),
1385f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) {
1386f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
1387f10a77bbSDavid C Somayajulu 		return -1;
1388f10a77bbSDavid C Somayajulu 	}
1389f10a77bbSDavid C Somayajulu 
1390f10a77bbSDavid C Somayajulu 	fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox;
1391f10a77bbSDavid C Somayajulu 
1392f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status);
1393f10a77bbSDavid C Somayajulu 
1394f10a77bbSDavid C Somayajulu 	if (err) {
1395f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1396f10a77bbSDavid C Somayajulu 	}
1397f10a77bbSDavid C Somayajulu 
1398f10a77bbSDavid C Somayajulu 	return 0;
1399f10a77bbSDavid C Somayajulu }
1400f10a77bbSDavid C Somayajulu 
140100caeec7SDavid C Somayajulu static int
140200caeec7SDavid C Somayajulu qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode)
140300caeec7SDavid C Somayajulu {
140400caeec7SDavid C Somayajulu 	device_t                dev;
140500caeec7SDavid C Somayajulu 	q80_hw_config_t         *hw_config;
140600caeec7SDavid C Somayajulu 	q80_hw_config_rsp_t     *hw_config_rsp;
140700caeec7SDavid C Somayajulu 	uint32_t                err;
140800caeec7SDavid C Somayajulu 
140900caeec7SDavid C Somayajulu 	dev = ha->pci_dev;
141000caeec7SDavid C Somayajulu 
141100caeec7SDavid C Somayajulu 	hw_config = (q80_hw_config_t *)ha->hw.mbox;
141200caeec7SDavid C Somayajulu 	bzero(hw_config, sizeof (q80_hw_config_t));
141300caeec7SDavid C Somayajulu 
141400caeec7SDavid C Somayajulu 	hw_config->opcode = Q8_MBX_HW_CONFIG;
141500caeec7SDavid C Somayajulu 	hw_config->count_version = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE_COUNT;
141600caeec7SDavid C Somayajulu 	hw_config->count_version |= Q8_MBX_CMD_VERSION;
141700caeec7SDavid C Somayajulu 
141800caeec7SDavid C Somayajulu 	hw_config->cmd = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE;
141900caeec7SDavid C Somayajulu 
142000caeec7SDavid C Somayajulu 	hw_config->u.set_cam_search_mode.mode = search_mode;
142100caeec7SDavid C Somayajulu 
142200caeec7SDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
142300caeec7SDavid C Somayajulu 		(sizeof (q80_hw_config_t) >> 2),
142400caeec7SDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
142500caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
142600caeec7SDavid C Somayajulu 		return -1;
142700caeec7SDavid C Somayajulu 	}
142800caeec7SDavid C Somayajulu 	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
142900caeec7SDavid C Somayajulu 
143000caeec7SDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
143100caeec7SDavid C Somayajulu 
143200caeec7SDavid C Somayajulu 	if (err) {
143300caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
143400caeec7SDavid C Somayajulu 	}
143500caeec7SDavid C Somayajulu 
143600caeec7SDavid C Somayajulu 	return 0;
143700caeec7SDavid C Somayajulu }
143800caeec7SDavid C Somayajulu 
143900caeec7SDavid C Somayajulu static int
144000caeec7SDavid C Somayajulu qla_get_cam_search_mode(qla_host_t *ha)
144100caeec7SDavid C Somayajulu {
144200caeec7SDavid C Somayajulu 	device_t                dev;
144300caeec7SDavid C Somayajulu 	q80_hw_config_t         *hw_config;
144400caeec7SDavid C Somayajulu 	q80_hw_config_rsp_t     *hw_config_rsp;
144500caeec7SDavid C Somayajulu 	uint32_t                err;
144600caeec7SDavid C Somayajulu 
144700caeec7SDavid C Somayajulu 	dev = ha->pci_dev;
144800caeec7SDavid C Somayajulu 
144900caeec7SDavid C Somayajulu 	hw_config = (q80_hw_config_t *)ha->hw.mbox;
145000caeec7SDavid C Somayajulu 	bzero(hw_config, sizeof (q80_hw_config_t));
145100caeec7SDavid C Somayajulu 
145200caeec7SDavid C Somayajulu 	hw_config->opcode = Q8_MBX_HW_CONFIG;
145300caeec7SDavid C Somayajulu 	hw_config->count_version = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE_COUNT;
145400caeec7SDavid C Somayajulu 	hw_config->count_version |= Q8_MBX_CMD_VERSION;
145500caeec7SDavid C Somayajulu 
145600caeec7SDavid C Somayajulu 	hw_config->cmd = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE;
145700caeec7SDavid C Somayajulu 
145800caeec7SDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
145900caeec7SDavid C Somayajulu 		(sizeof (q80_hw_config_t) >> 2),
146000caeec7SDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
146100caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
146200caeec7SDavid C Somayajulu 		return -1;
146300caeec7SDavid C Somayajulu 	}
146400caeec7SDavid C Somayajulu 	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
146500caeec7SDavid C Somayajulu 
146600caeec7SDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
146700caeec7SDavid C Somayajulu 
146800caeec7SDavid C Somayajulu 	if (err) {
146900caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
147000caeec7SDavid C Somayajulu 	} else {
147100caeec7SDavid C Somayajulu 		device_printf(dev, "%s: cam search mode [0x%08x]\n", __func__,
147200caeec7SDavid C Somayajulu 			hw_config_rsp->u.get_cam_search_mode.mode);
147300caeec7SDavid C Somayajulu 	}
147400caeec7SDavid C Somayajulu 
147500caeec7SDavid C Somayajulu 	return 0;
147600caeec7SDavid C Somayajulu }
147700caeec7SDavid C Somayajulu 
147800caeec7SDavid C Somayajulu 
147900caeec7SDavid C Somayajulu 
1480f10a77bbSDavid C Somayajulu static void
148135291c22SDavid C Somayajulu qla_xmt_stats(qla_host_t *ha, q80_xmt_stats_t *xstat, int i)
1482f10a77bbSDavid C Somayajulu {
1483f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1484f10a77bbSDavid C Somayajulu 
148535291c22SDavid C Somayajulu 	if (i < ha->hw.num_tx_rings) {
148635291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: total_bytes\t\t%" PRIu64 "\n",
148735291c22SDavid C Somayajulu 			__func__, i, xstat->total_bytes);
148835291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: total_pkts\t\t%" PRIu64 "\n",
148935291c22SDavid C Somayajulu 			__func__, i, xstat->total_pkts);
149035291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: errors\t\t%" PRIu64 "\n",
149135291c22SDavid C Somayajulu 			__func__, i, xstat->errors);
149235291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: pkts_dropped\t%" PRIu64 "\n",
149335291c22SDavid C Somayajulu 			__func__, i, xstat->pkts_dropped);
149435291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: switch_pkts\t\t%" PRIu64 "\n",
149535291c22SDavid C Somayajulu 			__func__, i, xstat->switch_pkts);
149635291c22SDavid C Somayajulu 		device_printf(dev, "%s[%d]: num_buffers\t\t%" PRIu64 "\n",
149735291c22SDavid C Somayajulu 			__func__, i, xstat->num_buffers);
149835291c22SDavid C Somayajulu 	} else {
149935291c22SDavid C Somayajulu 		device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n",
150035291c22SDavid C Somayajulu 			__func__, xstat->total_bytes);
150135291c22SDavid C Somayajulu 		device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n",
150235291c22SDavid C Somayajulu 			__func__, xstat->total_pkts);
150335291c22SDavid C Somayajulu 		device_printf(dev, "%s: errors\t\t\t%" PRIu64 "\n",
150435291c22SDavid C Somayajulu 			__func__, xstat->errors);
150535291c22SDavid C Somayajulu 		device_printf(dev, "%s: pkts_dropped\t\t\t%" PRIu64 "\n",
150635291c22SDavid C Somayajulu 			__func__, xstat->pkts_dropped);
150735291c22SDavid C Somayajulu 		device_printf(dev, "%s: switch_pkts\t\t\t%" PRIu64 "\n",
150835291c22SDavid C Somayajulu 			__func__, xstat->switch_pkts);
150935291c22SDavid C Somayajulu 		device_printf(dev, "%s: num_buffers\t\t\t%" PRIu64 "\n",
151035291c22SDavid C Somayajulu 			__func__, xstat->num_buffers);
151135291c22SDavid C Somayajulu 	}
1512f10a77bbSDavid C Somayajulu }
1513f10a77bbSDavid C Somayajulu 
1514f10a77bbSDavid C Somayajulu static void
1515f10a77bbSDavid C Somayajulu qla_rcv_stats(qla_host_t *ha, q80_rcv_stats_t *rstat)
1516f10a77bbSDavid C Somayajulu {
1517f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1518f10a77bbSDavid C Somayajulu 
1519f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n", __func__,
1520f10a77bbSDavid C Somayajulu 		rstat->total_bytes);
1521f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n", __func__,
1522f10a77bbSDavid C Somayajulu 		rstat->total_pkts);
1523f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_pkt_count\t\t%" PRIu64 "\n", __func__,
1524f10a77bbSDavid C Somayajulu 		rstat->lro_pkt_count);
152535291c22SDavid C Somayajulu 	device_printf(dev, "%s: sw_pkt_count\t\t\t%" PRIu64 "\n", __func__,
1526f10a77bbSDavid C Somayajulu 		rstat->sw_pkt_count);
1527f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: ip_chksum_err\t\t%" PRIu64 "\n", __func__,
1528f10a77bbSDavid C Somayajulu 		rstat->ip_chksum_err);
1529f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_wo_acntxts\t\t%" PRIu64 "\n", __func__,
1530f10a77bbSDavid C Somayajulu 		rstat->pkts_wo_acntxts);
1531f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_sds_card\t%" PRIu64 "\n",
1532f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_sds_card);
1533f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_sds_host\t%" PRIu64 "\n",
1534f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_sds_host);
1535f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: oversized_pkts\t\t%" PRIu64 "\n", __func__,
1536f10a77bbSDavid C Somayajulu 		rstat->oversized_pkts);
1537f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_dropped_no_rds\t\t%" PRIu64 "\n",
1538f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_dropped_no_rds);
1539f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: unxpctd_mcast_pkts\t\t%" PRIu64 "\n",
1540f10a77bbSDavid C Somayajulu 		__func__, rstat->unxpctd_mcast_pkts);
1541f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: re1_fbq_error\t\t%" PRIu64 "\n", __func__,
1542f10a77bbSDavid C Somayajulu 		rstat->re1_fbq_error);
1543f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: invalid_mac_addr\t\t%" PRIu64 "\n", __func__,
1544f10a77bbSDavid C Somayajulu 		rstat->invalid_mac_addr);
1545f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rds_prime_trys\t\t%" PRIu64 "\n", __func__,
1546f10a77bbSDavid C Somayajulu 		rstat->rds_prime_trys);
1547f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rds_prime_success\t\t%" PRIu64 "\n", __func__,
1548f10a77bbSDavid C Somayajulu 		rstat->rds_prime_success);
1549f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_added\t\t%" PRIu64 "\n", __func__,
1550f10a77bbSDavid C Somayajulu 		rstat->lro_flows_added);
1551f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_deleted\t\t%" PRIu64 "\n", __func__,
1552f10a77bbSDavid C Somayajulu 		rstat->lro_flows_deleted);
1553f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: lro_flows_active\t\t%" PRIu64 "\n", __func__,
1554f10a77bbSDavid C Somayajulu 		rstat->lro_flows_active);
1555f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: pkts_droped_unknown\t\t%" PRIu64 "\n",
1556f10a77bbSDavid C Somayajulu 		__func__, rstat->pkts_droped_unknown);
1557d2b62c58SDavid C Somayajulu 	device_printf(dev, "%s: pkts_cnt_oversized\t\t%" PRIu64 "\n",
1558d2b62c58SDavid C Somayajulu 		__func__, rstat->pkts_cnt_oversized);
1559f10a77bbSDavid C Somayajulu }
1560f10a77bbSDavid C Somayajulu 
1561f10a77bbSDavid C Somayajulu static void
1562f10a77bbSDavid C Somayajulu qla_mac_stats(qla_host_t *ha, q80_mac_stats_t *mstat)
1563f10a77bbSDavid C Somayajulu {
1564f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1565f10a77bbSDavid C Somayajulu 
1566f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_frames\t\t\t%" PRIu64 "\n", __func__,
1567f10a77bbSDavid C Somayajulu 		mstat->xmt_frames);
1568f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_bytes\t\t\t%" PRIu64 "\n", __func__,
1569f10a77bbSDavid C Somayajulu 		mstat->xmt_bytes);
1570f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1571f10a77bbSDavid C Somayajulu 		mstat->xmt_mcast_pkts);
1572f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1573f10a77bbSDavid C Somayajulu 		mstat->xmt_bcast_pkts);
1574f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pause_frames\t\t%" PRIu64 "\n", __func__,
1575f10a77bbSDavid C Somayajulu 		mstat->xmt_pause_frames);
1576f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1577f10a77bbSDavid C Somayajulu 		mstat->xmt_cntrl_pkts);
1578f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1579f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_64bytes);
1580f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1581f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_127bytes);
1582f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1583f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_255bytes);
1584f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1585f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_511bytes);
158635291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_1023bytes\t\t%" PRIu64 "\n",
1587f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_1023bytes);
158835291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_lt_1518bytes\t\t%" PRIu64 "\n",
1589f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_lt_1518bytes);
159035291c22SDavid C Somayajulu 	device_printf(dev, "%s: xmt_pkt_gt_1518bytes\t\t%" PRIu64 "\n",
1591f10a77bbSDavid C Somayajulu 		__func__, mstat->xmt_pkt_gt_1518bytes);
1592f10a77bbSDavid C Somayajulu 
1593f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_frames\t\t\t%" PRIu64 "\n", __func__,
1594f10a77bbSDavid C Somayajulu 		mstat->rcv_frames);
1595f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_bytes\t\t\t%" PRIu64 "\n", __func__,
1596f10a77bbSDavid C Somayajulu 		mstat->rcv_bytes);
1597f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_mcast_pkts\t\t%" PRIu64 "\n", __func__,
1598f10a77bbSDavid C Somayajulu 		mstat->rcv_mcast_pkts);
1599f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_bcast_pkts\t\t%" PRIu64 "\n", __func__,
1600f10a77bbSDavid C Somayajulu 		mstat->rcv_bcast_pkts);
1601f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pause_frames\t\t%" PRIu64 "\n", __func__,
1602f10a77bbSDavid C Somayajulu 		mstat->rcv_pause_frames);
1603f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_cntrl_pkts\t\t%" PRIu64 "\n", __func__,
1604f10a77bbSDavid C Somayajulu 		mstat->rcv_cntrl_pkts);
1605f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_64bytes\t\t%" PRIu64 "\n",
1606f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_64bytes);
1607f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_127bytes\t\t%" PRIu64 "\n",
1608f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_127bytes);
1609f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_255bytes\t\t%" PRIu64 "\n",
1610f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_255bytes);
1611f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_511bytes\t\t%" PRIu64 "\n",
1612f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_511bytes);
161335291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_1023bytes\t\t%" PRIu64 "\n",
1614f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_1023bytes);
161535291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_lt_1518bytes\t\t%" PRIu64 "\n",
1616f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_lt_1518bytes);
161735291c22SDavid C Somayajulu 	device_printf(dev, "%s: rcv_pkt_gt_1518bytes\t\t%" PRIu64 "\n",
1618f10a77bbSDavid C Somayajulu 		__func__, mstat->rcv_pkt_gt_1518bytes);
1619f10a77bbSDavid C Somayajulu 
1620f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_error\t\t%" PRIu64 "\n", __func__,
1621f10a77bbSDavid C Somayajulu 		mstat->rcv_len_error);
1622f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_small\t\t%" PRIu64 "\n", __func__,
1623f10a77bbSDavid C Somayajulu 		mstat->rcv_len_small);
1624f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_len_large\t\t%" PRIu64 "\n", __func__,
1625f10a77bbSDavid C Somayajulu 		mstat->rcv_len_large);
1626f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_jabber\t\t\t%" PRIu64 "\n", __func__,
1627f10a77bbSDavid C Somayajulu 		mstat->rcv_jabber);
1628f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: rcv_dropped\t\t\t%" PRIu64 "\n", __func__,
1629f10a77bbSDavid C Somayajulu 		mstat->rcv_dropped);
1630f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: fcs_error\t\t\t%" PRIu64 "\n", __func__,
1631f10a77bbSDavid C Somayajulu 		mstat->fcs_error);
1632f10a77bbSDavid C Somayajulu 	device_printf(dev, "%s: align_error\t\t\t%" PRIu64 "\n", __func__,
1633f10a77bbSDavid C Somayajulu 		mstat->align_error);
1634f10a77bbSDavid C Somayajulu }
1635f10a77bbSDavid C Somayajulu 
1636f10a77bbSDavid C Somayajulu 
1637f10a77bbSDavid C Somayajulu static int
163835291c22SDavid C Somayajulu qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size)
1639f10a77bbSDavid C Somayajulu {
1640f10a77bbSDavid C Somayajulu 	device_t		dev;
1641f10a77bbSDavid C Somayajulu 	q80_get_stats_t		*stat;
1642f10a77bbSDavid C Somayajulu 	q80_get_stats_rsp_t	*stat_rsp;
1643f10a77bbSDavid C Somayajulu 	uint32_t		err;
1644f10a77bbSDavid C Somayajulu 
1645f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1646f10a77bbSDavid C Somayajulu 
1647f10a77bbSDavid C Somayajulu 	stat = (q80_get_stats_t *)ha->hw.mbox;
1648f10a77bbSDavid C Somayajulu 	bzero(stat, (sizeof (q80_get_stats_t)));
1649f10a77bbSDavid C Somayajulu 
1650f10a77bbSDavid C Somayajulu 	stat->opcode = Q8_MBX_GET_STATS;
1651f10a77bbSDavid C Somayajulu 	stat->count_version = 2;
1652f10a77bbSDavid C Somayajulu 	stat->count_version |= Q8_MBX_CMD_VERSION;
1653f10a77bbSDavid C Somayajulu 
1654f10a77bbSDavid C Somayajulu 	stat->cmd = cmd;
1655f10a77bbSDavid C Somayajulu 
1656f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)stat, 2,
165735291c22SDavid C Somayajulu                 ha->hw.mbox, (rsp_size >> 2), 0)) {
1658f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1659f10a77bbSDavid C Somayajulu                 return -1;
1660f10a77bbSDavid C Somayajulu         }
1661f10a77bbSDavid C Somayajulu 
1662f10a77bbSDavid C Somayajulu 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1663f10a77bbSDavid C Somayajulu 
1664f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status);
1665f10a77bbSDavid C Somayajulu 
1666f10a77bbSDavid C Somayajulu         if (err) {
1667f10a77bbSDavid C Somayajulu                 return -1;
1668f10a77bbSDavid C Somayajulu         }
1669f10a77bbSDavid C Somayajulu 
1670f10a77bbSDavid C Somayajulu 	return 0;
1671f10a77bbSDavid C Somayajulu }
1672f10a77bbSDavid C Somayajulu 
1673f10a77bbSDavid C Somayajulu void
1674f10a77bbSDavid C Somayajulu ql_get_stats(qla_host_t *ha)
1675f10a77bbSDavid C Somayajulu {
1676f10a77bbSDavid C Somayajulu 	q80_get_stats_rsp_t	*stat_rsp;
1677f10a77bbSDavid C Somayajulu 	q80_mac_stats_t		*mstat;
1678f10a77bbSDavid C Somayajulu 	q80_xmt_stats_t		*xstat;
1679f10a77bbSDavid C Somayajulu 	q80_rcv_stats_t		*rstat;
1680f10a77bbSDavid C Somayajulu 	uint32_t		cmd;
168135291c22SDavid C Somayajulu 	int			i;
1682f10a77bbSDavid C Somayajulu 
1683f10a77bbSDavid C Somayajulu 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
1684f10a77bbSDavid C Somayajulu 	/*
1685f10a77bbSDavid C Somayajulu 	 * Get MAC Statistics
1686f10a77bbSDavid C Somayajulu 	 */
1687f10a77bbSDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_TYPE_MAC;
168835291c22SDavid C Somayajulu //	cmd |= Q8_GET_STATS_CMD_CLEAR;
1689f10a77bbSDavid C Somayajulu 
1690f10a77bbSDavid C Somayajulu 	cmd |= ((ha->pci_func & 0x1) << 16);
1691f10a77bbSDavid C Somayajulu 
169235291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
1693f10a77bbSDavid C Somayajulu 		mstat = (q80_mac_stats_t *)&stat_rsp->u.mac;
1694f10a77bbSDavid C Somayajulu 		qla_mac_stats(ha, mstat);
1695f10a77bbSDavid C Somayajulu 	} else {
1696f10a77bbSDavid C Somayajulu                 device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n",
1697f10a77bbSDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
1698f10a77bbSDavid C Somayajulu 	}
1699f10a77bbSDavid C Somayajulu 	/*
1700f10a77bbSDavid C Somayajulu 	 * Get RCV Statistics
1701f10a77bbSDavid C Somayajulu 	 */
1702f10a77bbSDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT;
170335291c22SDavid C Somayajulu //	cmd |= Q8_GET_STATS_CMD_CLEAR;
1704f10a77bbSDavid C Somayajulu 	cmd |= (ha->hw.rcv_cntxt_id << 16);
1705f10a77bbSDavid C Somayajulu 
170635291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
1707f10a77bbSDavid C Somayajulu 		rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv;
1708f10a77bbSDavid C Somayajulu 		qla_rcv_stats(ha, rstat);
1709f10a77bbSDavid C Somayajulu 	} else {
1710f10a77bbSDavid C Somayajulu                 device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n",
1711f10a77bbSDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
1712f10a77bbSDavid C Somayajulu 	}
1713f10a77bbSDavid C Somayajulu 	/*
1714f10a77bbSDavid C Somayajulu 	 * Get XMT Statistics
1715f10a77bbSDavid C Somayajulu 	 */
171635291c22SDavid C Somayajulu 	for (i = 0 ; i < ha->hw.num_tx_rings; i++) {
1717f10a77bbSDavid C Somayajulu 		cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT;
171835291c22SDavid C Somayajulu //		cmd |= Q8_GET_STATS_CMD_CLEAR;
171935291c22SDavid C Somayajulu 		cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16);
1720f10a77bbSDavid C Somayajulu 
172135291c22SDavid C Somayajulu 		if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t))
172235291c22SDavid C Somayajulu 			== 0) {
1723f10a77bbSDavid C Somayajulu 			xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt;
172435291c22SDavid C Somayajulu 			qla_xmt_stats(ha, xstat, i);
1725f10a77bbSDavid C Somayajulu 		} else {
1726f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n",
1727f10a77bbSDavid C Somayajulu 				__func__, ha->hw.mbox[0]);
1728f10a77bbSDavid C Somayajulu 		}
1729f10a77bbSDavid C Somayajulu 	}
173035291c22SDavid C Somayajulu 	return;
173135291c22SDavid C Somayajulu }
173235291c22SDavid C Somayajulu 
173335291c22SDavid C Somayajulu static void
173435291c22SDavid C Somayajulu qla_get_quick_stats(qla_host_t *ha)
173535291c22SDavid C Somayajulu {
173635291c22SDavid C Somayajulu 	q80_get_mac_rcv_xmt_stats_rsp_t *stat_rsp;
173735291c22SDavid C Somayajulu 	q80_mac_stats_t         *mstat;
173835291c22SDavid C Somayajulu 	q80_xmt_stats_t         *xstat;
173935291c22SDavid C Somayajulu 	q80_rcv_stats_t         *rstat;
174035291c22SDavid C Somayajulu 	uint32_t                cmd;
174135291c22SDavid C Somayajulu 
174235291c22SDavid C Somayajulu 	stat_rsp = (q80_get_mac_rcv_xmt_stats_rsp_t *)ha->hw.mbox;
174335291c22SDavid C Somayajulu 
174435291c22SDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_TYPE_ALL;
174535291c22SDavid C Somayajulu //      cmd |= Q8_GET_STATS_CMD_CLEAR;
174635291c22SDavid C Somayajulu 
174735291c22SDavid C Somayajulu //      cmd |= ((ha->pci_func & 0x3) << 16);
174835291c22SDavid C Somayajulu 	cmd |= (0xFFFF << 16);
174935291c22SDavid C Somayajulu 
175035291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd,
175135291c22SDavid C Somayajulu 			sizeof (q80_get_mac_rcv_xmt_stats_rsp_t)) == 0) {
175235291c22SDavid C Somayajulu 
175335291c22SDavid C Somayajulu 		mstat = (q80_mac_stats_t *)&stat_rsp->mac;
175435291c22SDavid C Somayajulu 		rstat = (q80_rcv_stats_t *)&stat_rsp->rcv;
175535291c22SDavid C Somayajulu 		xstat = (q80_xmt_stats_t *)&stat_rsp->xmt;
175635291c22SDavid C Somayajulu 		qla_mac_stats(ha, mstat);
175735291c22SDavid C Somayajulu 		qla_rcv_stats(ha, rstat);
175835291c22SDavid C Somayajulu 		qla_xmt_stats(ha, xstat, ha->hw.num_tx_rings);
175935291c22SDavid C Somayajulu 	} else {
176035291c22SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: failed [0x%08x]\n",
176135291c22SDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
176235291c22SDavid C Somayajulu 	}
176335291c22SDavid C Somayajulu 	return;
176435291c22SDavid C Somayajulu }
1765f10a77bbSDavid C Somayajulu 
1766f10a77bbSDavid C Somayajulu /*
1767f10a77bbSDavid C Somayajulu  * Name: qla_tx_tso
1768f10a77bbSDavid C Somayajulu  * Function: Checks if the packet to be transmitted is a candidate for
1769f10a77bbSDavid C Somayajulu  *	Large TCP Segment Offload. If yes, the appropriate fields in the Tx
1770f10a77bbSDavid C Somayajulu  *	Ring Structure are plugged in.
1771f10a77bbSDavid C Somayajulu  */
1772f10a77bbSDavid C Somayajulu static int
1773f10a77bbSDavid C Somayajulu qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
1774f10a77bbSDavid C Somayajulu {
1775f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1776f10a77bbSDavid C Somayajulu 	struct ip *ip = NULL;
1777f10a77bbSDavid C Somayajulu 	struct ip6_hdr *ip6 = NULL;
1778f10a77bbSDavid C Somayajulu 	struct tcphdr *th = NULL;
1779f10a77bbSDavid C Somayajulu 	uint32_t ehdrlen,  hdrlen, ip_hlen, tcp_hlen, tcp_opt_off;
1780f10a77bbSDavid C Somayajulu 	uint16_t etype, opcode, offload = 1;
1781f10a77bbSDavid C Somayajulu 	device_t dev;
1782f10a77bbSDavid C Somayajulu 
1783f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1784f10a77bbSDavid C Somayajulu 
1785f10a77bbSDavid C Somayajulu 
1786f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
1787f10a77bbSDavid C Somayajulu 
1788f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1789f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1790f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_proto);
1791f10a77bbSDavid C Somayajulu 	} else {
1792f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN;
1793f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_encap_proto);
1794f10a77bbSDavid C Somayajulu 	}
1795f10a77bbSDavid C Somayajulu 
1796f10a77bbSDavid C Somayajulu 	hdrlen = 0;
1797f10a77bbSDavid C Somayajulu 
1798f10a77bbSDavid C Somayajulu 	switch (etype) {
1799f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IP:
1800f10a77bbSDavid C Somayajulu 
1801f10a77bbSDavid C Somayajulu 			tcp_opt_off = ehdrlen + sizeof(struct ip) +
1802f10a77bbSDavid C Somayajulu 					sizeof(struct tcphdr);
1803f10a77bbSDavid C Somayajulu 
1804f10a77bbSDavid C Somayajulu 			if (mp->m_len < tcp_opt_off) {
1805f10a77bbSDavid C Somayajulu 				m_copydata(mp, 0, tcp_opt_off, hdr);
1806f10a77bbSDavid C Somayajulu 				ip = (struct ip *)(hdr + ehdrlen);
1807f10a77bbSDavid C Somayajulu 			} else {
1808f10a77bbSDavid C Somayajulu 				ip = (struct ip *)(mp->m_data + ehdrlen);
1809f10a77bbSDavid C Somayajulu 			}
1810f10a77bbSDavid C Somayajulu 
1811f10a77bbSDavid C Somayajulu 			ip_hlen = ip->ip_hl << 2;
1812f10a77bbSDavid C Somayajulu 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
1813f10a77bbSDavid C Somayajulu 
1814f10a77bbSDavid C Somayajulu 
1815f10a77bbSDavid C Somayajulu 			if ((ip->ip_p != IPPROTO_TCP) ||
1816f10a77bbSDavid C Somayajulu 				(ip_hlen != sizeof (struct ip))){
1817f10a77bbSDavid C Somayajulu 				/* IP Options are not supported */
1818f10a77bbSDavid C Somayajulu 
1819f10a77bbSDavid C Somayajulu 				offload = 0;
1820f10a77bbSDavid C Somayajulu 			} else
1821f10a77bbSDavid C Somayajulu 				th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
1822f10a77bbSDavid C Somayajulu 
1823f10a77bbSDavid C Somayajulu 		break;
1824f10a77bbSDavid C Somayajulu 
1825f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IPV6:
1826f10a77bbSDavid C Somayajulu 
1827f10a77bbSDavid C Somayajulu 			tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) +
1828f10a77bbSDavid C Somayajulu 					sizeof (struct tcphdr);
1829f10a77bbSDavid C Somayajulu 
1830f10a77bbSDavid C Somayajulu 			if (mp->m_len < tcp_opt_off) {
1831f10a77bbSDavid C Somayajulu 				m_copydata(mp, 0, tcp_opt_off, hdr);
1832f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)(hdr + ehdrlen);
1833f10a77bbSDavid C Somayajulu 			} else {
1834f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1835f10a77bbSDavid C Somayajulu 			}
1836f10a77bbSDavid C Somayajulu 
1837f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof(struct ip6_hdr);
1838f10a77bbSDavid C Somayajulu 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6;
1839f10a77bbSDavid C Somayajulu 
1840f10a77bbSDavid C Somayajulu 			if (ip6->ip6_nxt != IPPROTO_TCP) {
1841f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv6\n", __func__);
1842f10a77bbSDavid C Somayajulu 				offload = 0;
1843f10a77bbSDavid C Somayajulu 			} else
1844f10a77bbSDavid C Somayajulu 				th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
1845f10a77bbSDavid C Somayajulu 		break;
1846f10a77bbSDavid C Somayajulu 
1847f10a77bbSDavid C Somayajulu 		default:
1848f10a77bbSDavid C Somayajulu 			QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__));
1849f10a77bbSDavid C Somayajulu 			offload = 0;
1850f10a77bbSDavid C Somayajulu 		break;
1851f10a77bbSDavid C Somayajulu 	}
1852f10a77bbSDavid C Somayajulu 
1853f10a77bbSDavid C Somayajulu 	if (!offload)
1854f10a77bbSDavid C Somayajulu 		return (-1);
1855f10a77bbSDavid C Somayajulu 
1856f10a77bbSDavid C Somayajulu 	tcp_hlen = th->th_off << 2;
1857f10a77bbSDavid C Somayajulu 	hdrlen = ehdrlen + ip_hlen + tcp_hlen;
1858f10a77bbSDavid C Somayajulu 
1859f10a77bbSDavid C Somayajulu         if (mp->m_len < hdrlen) {
1860f10a77bbSDavid C Somayajulu                 if (mp->m_len < tcp_opt_off) {
1861f10a77bbSDavid C Somayajulu                         if (tcp_hlen > sizeof(struct tcphdr)) {
1862f10a77bbSDavid C Somayajulu                                 m_copydata(mp, tcp_opt_off,
1863f10a77bbSDavid C Somayajulu                                         (tcp_hlen - sizeof(struct tcphdr)),
1864f10a77bbSDavid C Somayajulu                                         &hdr[tcp_opt_off]);
1865f10a77bbSDavid C Somayajulu                         }
1866f10a77bbSDavid C Somayajulu                 } else {
1867f10a77bbSDavid C Somayajulu                         m_copydata(mp, 0, hdrlen, hdr);
1868f10a77bbSDavid C Somayajulu                 }
1869f10a77bbSDavid C Somayajulu         }
1870f10a77bbSDavid C Somayajulu 
1871f10a77bbSDavid C Somayajulu 	tx_cmd->mss = mp->m_pkthdr.tso_segsz;
1872f10a77bbSDavid C Somayajulu 
1873f10a77bbSDavid C Somayajulu 	tx_cmd->flags_opcode = opcode ;
1874f10a77bbSDavid C Somayajulu 	tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen;
1875f10a77bbSDavid C Somayajulu 	tx_cmd->total_hdr_len = hdrlen;
1876f10a77bbSDavid C Somayajulu 
1877f10a77bbSDavid C Somayajulu 	/* Check for Multicast least significant bit of MSB == 1 */
1878f10a77bbSDavid C Somayajulu 	if (eh->evl_dhost[0] & 0x01) {
1879f10a77bbSDavid C Somayajulu 		tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST;
1880f10a77bbSDavid C Somayajulu 	}
1881f10a77bbSDavid C Somayajulu 
1882f10a77bbSDavid C Somayajulu 	if (mp->m_len < hdrlen) {
1883f10a77bbSDavid C Somayajulu 		printf("%d\n", hdrlen);
1884f10a77bbSDavid C Somayajulu 		return (1);
1885f10a77bbSDavid C Somayajulu 	}
1886f10a77bbSDavid C Somayajulu 
1887f10a77bbSDavid C Somayajulu 	return (0);
1888f10a77bbSDavid C Somayajulu }
1889f10a77bbSDavid C Somayajulu 
1890f10a77bbSDavid C Somayajulu /*
1891f10a77bbSDavid C Somayajulu  * Name: qla_tx_chksum
1892f10a77bbSDavid C Somayajulu  * Function: Checks if the packet to be transmitted is a candidate for
1893f10a77bbSDavid C Somayajulu  *	TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx
1894f10a77bbSDavid C Somayajulu  *	Ring Structure are plugged in.
1895f10a77bbSDavid C Somayajulu  */
1896f10a77bbSDavid C Somayajulu static int
1897f10a77bbSDavid C Somayajulu qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code,
1898f10a77bbSDavid C Somayajulu 	uint32_t *tcp_hdr_off)
1899f10a77bbSDavid C Somayajulu {
1900f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1901f10a77bbSDavid C Somayajulu 	struct ip *ip;
1902f10a77bbSDavid C Somayajulu 	struct ip6_hdr *ip6;
1903f10a77bbSDavid C Somayajulu 	uint32_t ehdrlen, ip_hlen;
1904f10a77bbSDavid C Somayajulu 	uint16_t etype, opcode, offload = 1;
1905f10a77bbSDavid C Somayajulu 	device_t dev;
1906f10a77bbSDavid C Somayajulu 	uint8_t buf[sizeof(struct ip6_hdr)];
1907f10a77bbSDavid C Somayajulu 
1908f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1909f10a77bbSDavid C Somayajulu 
1910f10a77bbSDavid C Somayajulu 	*op_code = 0;
1911f10a77bbSDavid C Somayajulu 
1912f10a77bbSDavid C Somayajulu 	if ((mp->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) == 0)
1913f10a77bbSDavid C Somayajulu 		return (-1);
1914f10a77bbSDavid C Somayajulu 
1915f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
1916f10a77bbSDavid C Somayajulu 
1917f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1918f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1919f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_proto);
1920f10a77bbSDavid C Somayajulu 	} else {
1921f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN;
1922f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_encap_proto);
1923f10a77bbSDavid C Somayajulu 	}
1924f10a77bbSDavid C Somayajulu 
1925f10a77bbSDavid C Somayajulu 
1926f10a77bbSDavid C Somayajulu 	switch (etype) {
1927f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IP:
1928f10a77bbSDavid C Somayajulu 			ip = (struct ip *)(mp->m_data + ehdrlen);
1929f10a77bbSDavid C Somayajulu 
1930f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof (struct ip);
1931f10a77bbSDavid C Somayajulu 
1932f10a77bbSDavid C Somayajulu 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1933f10a77bbSDavid C Somayajulu 				m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
1934f10a77bbSDavid C Somayajulu 				ip = (struct ip *)buf;
1935f10a77bbSDavid C Somayajulu 			}
1936f10a77bbSDavid C Somayajulu 
1937f10a77bbSDavid C Somayajulu 			if (ip->ip_p == IPPROTO_TCP)
1938f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM;
1939f10a77bbSDavid C Somayajulu 			else if (ip->ip_p == IPPROTO_UDP)
1940f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM;
1941f10a77bbSDavid C Somayajulu 			else {
1942f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv4\n", __func__);
1943f10a77bbSDavid C Somayajulu 				offload = 0;
1944f10a77bbSDavid C Somayajulu 			}
1945f10a77bbSDavid C Somayajulu 		break;
1946f10a77bbSDavid C Somayajulu 
1947f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IPV6:
1948f10a77bbSDavid C Somayajulu 			ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
1949f10a77bbSDavid C Somayajulu 
1950f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof(struct ip6_hdr);
1951f10a77bbSDavid C Somayajulu 
1952f10a77bbSDavid C Somayajulu 			if (mp->m_len < (ehdrlen + ip_hlen)) {
1953f10a77bbSDavid C Somayajulu 				m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
1954f10a77bbSDavid C Somayajulu 					buf);
1955f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)buf;
1956f10a77bbSDavid C Somayajulu 			}
1957f10a77bbSDavid C Somayajulu 
1958f10a77bbSDavid C Somayajulu 			if (ip6->ip6_nxt == IPPROTO_TCP)
1959f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6;
1960f10a77bbSDavid C Somayajulu 			else if (ip6->ip6_nxt == IPPROTO_UDP)
1961f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6;
1962f10a77bbSDavid C Somayajulu 			else {
1963f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv6\n", __func__);
1964f10a77bbSDavid C Somayajulu 				offload = 0;
1965f10a77bbSDavid C Somayajulu 			}
1966f10a77bbSDavid C Somayajulu 		break;
1967f10a77bbSDavid C Somayajulu 
1968f10a77bbSDavid C Somayajulu 		default:
1969f10a77bbSDavid C Somayajulu 			offload = 0;
1970f10a77bbSDavid C Somayajulu 		break;
1971f10a77bbSDavid C Somayajulu 	}
1972f10a77bbSDavid C Somayajulu 	if (!offload)
1973f10a77bbSDavid C Somayajulu 		return (-1);
1974f10a77bbSDavid C Somayajulu 
1975f10a77bbSDavid C Somayajulu 	*op_code = opcode;
1976f10a77bbSDavid C Somayajulu 	*tcp_hdr_off = (ip_hlen + ehdrlen);
1977f10a77bbSDavid C Somayajulu 
1978f10a77bbSDavid C Somayajulu 	return (0);
1979f10a77bbSDavid C Somayajulu }
1980f10a77bbSDavid C Somayajulu 
1981f10a77bbSDavid C Somayajulu #define QLA_TX_MIN_FREE 2
1982f10a77bbSDavid C Somayajulu /*
1983f10a77bbSDavid C Somayajulu  * Name: ql_hw_send
1984f10a77bbSDavid C Somayajulu  * Function: Transmits a packet. It first checks if the packet is a
1985f10a77bbSDavid C Somayajulu  *	candidate for Large TCP Segment Offload and then for UDP/TCP checksum
1986f10a77bbSDavid C Somayajulu  *	offload. If either of these creteria are not met, it is transmitted
1987f10a77bbSDavid C Somayajulu  *	as a regular ethernet frame.
1988f10a77bbSDavid C Somayajulu  */
1989f10a77bbSDavid C Somayajulu int
1990f10a77bbSDavid C Somayajulu ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
199135291c22SDavid C Somayajulu 	uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu)
1992f10a77bbSDavid C Somayajulu {
1993f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
1994f10a77bbSDavid C Somayajulu 	qla_hw_t *hw = &ha->hw;
1995f10a77bbSDavid C Somayajulu 	q80_tx_cmd_t *tx_cmd, tso_cmd;
1996f10a77bbSDavid C Somayajulu 	bus_dma_segment_t *c_seg;
1997f10a77bbSDavid C Somayajulu 	uint32_t num_tx_cmds, hdr_len = 0;
1998f10a77bbSDavid C Somayajulu 	uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next;
1999f10a77bbSDavid C Somayajulu 	device_t dev;
2000f10a77bbSDavid C Somayajulu 	int i, ret;
2001f10a77bbSDavid C Somayajulu 	uint8_t *src = NULL, *dst = NULL;
2002f10a77bbSDavid C Somayajulu 	uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
2003f10a77bbSDavid C Somayajulu 	uint32_t op_code = 0;
2004f10a77bbSDavid C Somayajulu 	uint32_t tcp_hdr_off = 0;
2005f10a77bbSDavid C Somayajulu 
2006f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2007f10a77bbSDavid C Somayajulu 
2008f10a77bbSDavid C Somayajulu 	/*
2009f10a77bbSDavid C Somayajulu 	 * Always make sure there is atleast one empty slot in the tx_ring
2010f10a77bbSDavid C Somayajulu 	 * tx_ring is considered full when there only one entry available
2011f10a77bbSDavid C Somayajulu 	 */
2012f10a77bbSDavid C Somayajulu         num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2;
2013f10a77bbSDavid C Somayajulu 
2014f10a77bbSDavid C Somayajulu 	total_length = mp->m_pkthdr.len;
2015f10a77bbSDavid C Somayajulu 	if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
2016f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
2017f10a77bbSDavid C Somayajulu 			__func__, total_length);
2018f10a77bbSDavid C Somayajulu 		return (-1);
2019f10a77bbSDavid C Somayajulu 	}
2020f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
2021f10a77bbSDavid C Somayajulu 
2022f10a77bbSDavid C Somayajulu 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2023f10a77bbSDavid C Somayajulu 
2024f10a77bbSDavid C Somayajulu 		bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
2025f10a77bbSDavid C Somayajulu 
2026f10a77bbSDavid C Somayajulu 		src = frame_hdr;
2027f10a77bbSDavid C Somayajulu 		ret = qla_tx_tso(ha, mp, &tso_cmd, src);
2028f10a77bbSDavid C Somayajulu 
2029f10a77bbSDavid C Somayajulu 		if (!(ret & ~1)) {
2030f10a77bbSDavid C Somayajulu 			/* find the additional tx_cmd descriptors required */
2031f10a77bbSDavid C Somayajulu 
2032f10a77bbSDavid C Somayajulu 			if (mp->m_flags & M_VLANTAG)
2033f10a77bbSDavid C Somayajulu 				tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN;
2034f10a77bbSDavid C Somayajulu 
2035f10a77bbSDavid C Somayajulu 			hdr_len = tso_cmd.total_hdr_len;
2036f10a77bbSDavid C Somayajulu 
2037f10a77bbSDavid C Somayajulu 			bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2038f10a77bbSDavid C Somayajulu 			bytes = QL_MIN(bytes, hdr_len);
2039f10a77bbSDavid C Somayajulu 
2040f10a77bbSDavid C Somayajulu 			num_tx_cmds++;
2041f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2042f10a77bbSDavid C Somayajulu 
2043f10a77bbSDavid C Somayajulu 			while (hdr_len) {
2044f10a77bbSDavid C Somayajulu 				bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2045f10a77bbSDavid C Somayajulu 				hdr_len -= bytes;
2046f10a77bbSDavid C Somayajulu 				num_tx_cmds++;
2047f10a77bbSDavid C Somayajulu 			}
2048f10a77bbSDavid C Somayajulu 			hdr_len = tso_cmd.total_hdr_len;
2049f10a77bbSDavid C Somayajulu 
2050f10a77bbSDavid C Somayajulu 			if (ret == 0)
2051f10a77bbSDavid C Somayajulu 				src = (uint8_t *)eh;
2052f10a77bbSDavid C Somayajulu 		} else
2053f10a77bbSDavid C Somayajulu 			return (EINVAL);
2054f10a77bbSDavid C Somayajulu 	} else {
2055f10a77bbSDavid C Somayajulu 		(void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off);
2056f10a77bbSDavid C Somayajulu 	}
2057f10a77bbSDavid C Somayajulu 
205835291c22SDavid C Somayajulu 	if (iscsi_pdu)
205935291c22SDavid C Somayajulu 		ha->hw.iscsi_pkt_count++;
206035291c22SDavid C Somayajulu 
2061f10a77bbSDavid C Somayajulu 	if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
2062b89f2279SDavid C Somayajulu 		ql_hw_tx_done_locked(ha, txr_idx);
2063f10a77bbSDavid C Somayajulu 		if (hw->tx_cntxt[txr_idx].txr_free <=
2064f10a77bbSDavid C Somayajulu 				(num_tx_cmds + QLA_TX_MIN_FREE)) {
2065f10a77bbSDavid C Somayajulu         		QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= "
2066f10a77bbSDavid C Somayajulu 				"(num_tx_cmds + QLA_TX_MIN_FREE))\n",
2067f10a77bbSDavid C Somayajulu 				__func__));
2068f10a77bbSDavid C Somayajulu 			return (-1);
2069f10a77bbSDavid C Somayajulu 		}
2070f10a77bbSDavid C Somayajulu 	}
2071f10a77bbSDavid C Somayajulu 
2072f10a77bbSDavid C Somayajulu 	tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx];
2073f10a77bbSDavid C Somayajulu 
2074f10a77bbSDavid C Somayajulu         if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) {
2075f10a77bbSDavid C Somayajulu 
2076f10a77bbSDavid C Somayajulu                 if (nsegs > ha->hw.max_tx_segs)
2077f10a77bbSDavid C Somayajulu                         ha->hw.max_tx_segs = nsegs;
2078f10a77bbSDavid C Somayajulu 
2079f10a77bbSDavid C Somayajulu                 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2080f10a77bbSDavid C Somayajulu 
2081f10a77bbSDavid C Somayajulu                 if (op_code) {
2082f10a77bbSDavid C Somayajulu                         tx_cmd->flags_opcode = op_code;
2083f10a77bbSDavid C Somayajulu                         tx_cmd->tcp_hdr_off = tcp_hdr_off;
2084f10a77bbSDavid C Somayajulu 
2085f10a77bbSDavid C Somayajulu                 } else {
2086f10a77bbSDavid C Somayajulu                         tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER;
2087f10a77bbSDavid C Somayajulu                 }
2088f10a77bbSDavid C Somayajulu 	} else {
2089f10a77bbSDavid C Somayajulu 		bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
2090f10a77bbSDavid C Somayajulu 		ha->tx_tso_frames++;
2091f10a77bbSDavid C Somayajulu 	}
2092f10a77bbSDavid C Somayajulu 
2093f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2094f10a77bbSDavid C Somayajulu         	tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
209535291c22SDavid C Somayajulu 
209635291c22SDavid C Somayajulu 		if (iscsi_pdu)
209735291c22SDavid C Somayajulu 			eh->evl_tag |= ha->hw.user_pri_iscsi << 13;
209835291c22SDavid C Somayajulu 
2099f10a77bbSDavid C Somayajulu 	} else if (mp->m_flags & M_VLANTAG) {
2100f10a77bbSDavid C Somayajulu 
2101f10a77bbSDavid C Somayajulu 		if (hdr_len) { /* TSO */
2102f10a77bbSDavid C Somayajulu 			tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED |
2103f10a77bbSDavid C Somayajulu 						Q8_TX_CMD_FLAGS_HW_VLAN_ID);
2104f10a77bbSDavid C Somayajulu 			tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN;
2105f10a77bbSDavid C Somayajulu 		} else
2106f10a77bbSDavid C Somayajulu 			tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID;
2107f10a77bbSDavid C Somayajulu 
2108f10a77bbSDavid C Somayajulu 		ha->hw_vlan_tx_frames++;
2109f10a77bbSDavid C Somayajulu 		tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag;
211035291c22SDavid C Somayajulu 
211135291c22SDavid C Somayajulu 		if (iscsi_pdu) {
211235291c22SDavid C Somayajulu 			tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13;
211335291c22SDavid C Somayajulu 			mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci;
211435291c22SDavid C Somayajulu 		}
2115f10a77bbSDavid C Somayajulu 	}
2116f10a77bbSDavid C Somayajulu 
2117f10a77bbSDavid C Somayajulu 
2118f10a77bbSDavid C Somayajulu         tx_cmd->n_bufs = (uint8_t)nsegs;
2119f10a77bbSDavid C Somayajulu         tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF);
2120f10a77bbSDavid C Somayajulu         tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8)));
2121f10a77bbSDavid C Somayajulu 	tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func);
2122f10a77bbSDavid C Somayajulu 
2123f10a77bbSDavid C Somayajulu 	c_seg = segs;
2124f10a77bbSDavid C Somayajulu 
2125f10a77bbSDavid C Somayajulu 	while (1) {
2126f10a77bbSDavid C Somayajulu 		for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) {
2127f10a77bbSDavid C Somayajulu 
2128f10a77bbSDavid C Somayajulu 			switch (i) {
2129f10a77bbSDavid C Somayajulu 			case 0:
2130f10a77bbSDavid C Somayajulu 				tx_cmd->buf1_addr = c_seg->ds_addr;
2131f10a77bbSDavid C Somayajulu 				tx_cmd->buf1_len = c_seg->ds_len;
2132f10a77bbSDavid C Somayajulu 				break;
2133f10a77bbSDavid C Somayajulu 
2134f10a77bbSDavid C Somayajulu 			case 1:
2135f10a77bbSDavid C Somayajulu 				tx_cmd->buf2_addr = c_seg->ds_addr;
2136f10a77bbSDavid C Somayajulu 				tx_cmd->buf2_len = c_seg->ds_len;
2137f10a77bbSDavid C Somayajulu 				break;
2138f10a77bbSDavid C Somayajulu 
2139f10a77bbSDavid C Somayajulu 			case 2:
2140f10a77bbSDavid C Somayajulu 				tx_cmd->buf3_addr = c_seg->ds_addr;
2141f10a77bbSDavid C Somayajulu 				tx_cmd->buf3_len = c_seg->ds_len;
2142f10a77bbSDavid C Somayajulu 				break;
2143f10a77bbSDavid C Somayajulu 
2144f10a77bbSDavid C Somayajulu 			case 3:
2145f10a77bbSDavid C Somayajulu 				tx_cmd->buf4_addr = c_seg->ds_addr;
2146f10a77bbSDavid C Somayajulu 				tx_cmd->buf4_len = c_seg->ds_len;
2147f10a77bbSDavid C Somayajulu 				break;
2148f10a77bbSDavid C Somayajulu 			}
2149f10a77bbSDavid C Somayajulu 
2150f10a77bbSDavid C Somayajulu 			c_seg++;
2151f10a77bbSDavid C Somayajulu 			nsegs--;
2152f10a77bbSDavid C Somayajulu 		}
2153f10a77bbSDavid C Somayajulu 
2154f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2155f10a77bbSDavid C Somayajulu 			(hw->tx_cntxt[txr_idx].txr_next + 1) &
2156f10a77bbSDavid C Somayajulu 				(NUM_TX_DESCRIPTORS - 1);
2157f10a77bbSDavid C Somayajulu 		tx_cmd_count++;
2158f10a77bbSDavid C Somayajulu 
2159f10a77bbSDavid C Somayajulu 		if (!nsegs)
2160f10a77bbSDavid C Somayajulu 			break;
2161f10a77bbSDavid C Somayajulu 
2162f10a77bbSDavid C Somayajulu 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2163f10a77bbSDavid C Somayajulu 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2164f10a77bbSDavid C Somayajulu 	}
2165f10a77bbSDavid C Somayajulu 
2166f10a77bbSDavid C Somayajulu 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2167f10a77bbSDavid C Somayajulu 
2168f10a77bbSDavid C Somayajulu 		/* TSO : Copy the header in the following tx cmd descriptors */
2169f10a77bbSDavid C Somayajulu 
2170f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next;
2171f10a77bbSDavid C Somayajulu 
2172f10a77bbSDavid C Somayajulu 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2173f10a77bbSDavid C Somayajulu 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2174f10a77bbSDavid C Somayajulu 
2175f10a77bbSDavid C Somayajulu 		bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2176f10a77bbSDavid C Somayajulu 		bytes = QL_MIN(bytes, hdr_len);
2177f10a77bbSDavid C Somayajulu 
2178f10a77bbSDavid C Somayajulu 		dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN;
2179f10a77bbSDavid C Somayajulu 
2180f10a77bbSDavid C Somayajulu 		if (mp->m_flags & M_VLANTAG) {
2181f10a77bbSDavid C Somayajulu 			/* first copy the src/dst MAC addresses */
2182f10a77bbSDavid C Somayajulu 			bcopy(src, dst, (ETHER_ADDR_LEN * 2));
2183f10a77bbSDavid C Somayajulu 			dst += (ETHER_ADDR_LEN * 2);
2184f10a77bbSDavid C Somayajulu 			src += (ETHER_ADDR_LEN * 2);
2185f10a77bbSDavid C Somayajulu 
2186f10a77bbSDavid C Somayajulu 			*((uint16_t *)dst) = htons(ETHERTYPE_VLAN);
2187f10a77bbSDavid C Somayajulu 			dst += 2;
2188f10a77bbSDavid C Somayajulu 			*((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag);
2189f10a77bbSDavid C Somayajulu 			dst += 2;
2190f10a77bbSDavid C Somayajulu 
2191f10a77bbSDavid C Somayajulu 			/* bytes left in src header */
2192f10a77bbSDavid C Somayajulu 			hdr_len -= ((ETHER_ADDR_LEN * 2) +
2193f10a77bbSDavid C Somayajulu 					ETHER_VLAN_ENCAP_LEN);
2194f10a77bbSDavid C Somayajulu 
2195f10a77bbSDavid C Somayajulu 			/* bytes left in TxCmd Entry */
2196f10a77bbSDavid C Somayajulu 			bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN);
2197f10a77bbSDavid C Somayajulu 
2198f10a77bbSDavid C Somayajulu 
2199f10a77bbSDavid C Somayajulu 			bcopy(src, dst, bytes);
2200f10a77bbSDavid C Somayajulu 			src += bytes;
2201f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2202f10a77bbSDavid C Somayajulu 		} else {
2203f10a77bbSDavid C Somayajulu 			bcopy(src, dst, bytes);
2204f10a77bbSDavid C Somayajulu 			src += bytes;
2205f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2206f10a77bbSDavid C Somayajulu 		}
2207f10a77bbSDavid C Somayajulu 
2208f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2209f10a77bbSDavid C Somayajulu 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2210f10a77bbSDavid C Somayajulu 					(NUM_TX_DESCRIPTORS - 1);
2211f10a77bbSDavid C Somayajulu 		tx_cmd_count++;
2212f10a77bbSDavid C Somayajulu 
2213f10a77bbSDavid C Somayajulu 		while (hdr_len) {
2214f10a77bbSDavid C Somayajulu 			tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2215f10a77bbSDavid C Somayajulu 			bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2216f10a77bbSDavid C Somayajulu 
2217f10a77bbSDavid C Somayajulu 			bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2218f10a77bbSDavid C Somayajulu 
2219f10a77bbSDavid C Somayajulu 			bcopy(src, tx_cmd, bytes);
2220f10a77bbSDavid C Somayajulu 			src += bytes;
2221f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2222f10a77bbSDavid C Somayajulu 
2223f10a77bbSDavid C Somayajulu 			txr_next = hw->tx_cntxt[txr_idx].txr_next =
2224f10a77bbSDavid C Somayajulu 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2225f10a77bbSDavid C Somayajulu 					(NUM_TX_DESCRIPTORS - 1);
2226f10a77bbSDavid C Somayajulu 			tx_cmd_count++;
2227f10a77bbSDavid C Somayajulu 		}
2228f10a77bbSDavid C Somayajulu 	}
2229f10a77bbSDavid C Somayajulu 
2230f10a77bbSDavid C Somayajulu 	hw->tx_cntxt[txr_idx].txr_free =
2231f10a77bbSDavid C Somayajulu 		hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count;
2232f10a77bbSDavid C Somayajulu 
2233f10a77bbSDavid C Somayajulu 	QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\
2234f10a77bbSDavid C Somayajulu 		txr_idx);
2235f10a77bbSDavid C Somayajulu        	QL_DPRINT8(ha, (dev, "%s: return\n", __func__));
2236f10a77bbSDavid C Somayajulu 
2237f10a77bbSDavid C Somayajulu 	return (0);
2238f10a77bbSDavid C Somayajulu }
2239f10a77bbSDavid C Somayajulu 
2240f10a77bbSDavid C Somayajulu 
224135291c22SDavid C Somayajulu 
224235291c22SDavid C Somayajulu #define Q8_CONFIG_IND_TBL_SIZE	32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */
2243f10a77bbSDavid C Somayajulu static int
2244f10a77bbSDavid C Somayajulu qla_config_rss_ind_table(qla_host_t *ha)
2245f10a77bbSDavid C Somayajulu {
2246f10a77bbSDavid C Somayajulu 	uint32_t i, count;
224735291c22SDavid C Somayajulu 	uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE];
2248f10a77bbSDavid C Somayajulu 
2249f10a77bbSDavid C Somayajulu 
225035291c22SDavid C Somayajulu 	for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) {
2251f10a77bbSDavid C Somayajulu 		rss_ind_tbl[i] = i % ha->hw.num_sds_rings;
2252f10a77bbSDavid C Somayajulu 	}
2253f10a77bbSDavid C Somayajulu 
225435291c22SDavid C Somayajulu 	for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ;
225535291c22SDavid C Somayajulu 		i = i + Q8_CONFIG_IND_TBL_SIZE) {
2256f10a77bbSDavid C Somayajulu 
225735291c22SDavid C Somayajulu 		if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) {
2258f10a77bbSDavid C Somayajulu 			count = Q8_RSS_IND_TBL_MAX_IDX - i + 1;
2259f10a77bbSDavid C Somayajulu 		} else {
226035291c22SDavid C Somayajulu 			count = Q8_CONFIG_IND_TBL_SIZE;
2261f10a77bbSDavid C Somayajulu 		}
2262f10a77bbSDavid C Somayajulu 
2263f10a77bbSDavid C Somayajulu 		if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id,
2264f10a77bbSDavid C Somayajulu 			rss_ind_tbl))
2265f10a77bbSDavid C Somayajulu 			return (-1);
2266f10a77bbSDavid C Somayajulu 	}
2267f10a77bbSDavid C Somayajulu 
2268f10a77bbSDavid C Somayajulu 	return (0);
2269f10a77bbSDavid C Somayajulu }
2270f10a77bbSDavid C Somayajulu 
2271a7c62c11SDavid C Somayajulu static int
2272a7c62c11SDavid C Somayajulu qla_config_soft_lro(qla_host_t *ha)
2273a7c62c11SDavid C Somayajulu {
2274a7c62c11SDavid C Somayajulu         int i;
2275a7c62c11SDavid C Somayajulu         qla_hw_t *hw = &ha->hw;
2276a7c62c11SDavid C Somayajulu         struct lro_ctrl *lro;
2277a7c62c11SDavid C Somayajulu 
2278a7c62c11SDavid C Somayajulu         for (i = 0; i < hw->num_sds_rings; i++) {
2279a7c62c11SDavid C Somayajulu                 lro = &hw->sds[i].lro;
2280a7c62c11SDavid C Somayajulu 
2281a7c62c11SDavid C Somayajulu 		bzero(lro, sizeof(struct lro_ctrl));
2282a7c62c11SDavid C Somayajulu 
2283a7c62c11SDavid C Somayajulu #if (__FreeBSD_version >= 1100101)
2284a7c62c11SDavid C Somayajulu                 if (tcp_lro_init_args(lro, ha->ifp, 0, NUM_RX_DESCRIPTORS)) {
2285a7c62c11SDavid C Somayajulu                         device_printf(ha->pci_dev,
2286a7c62c11SDavid C Somayajulu 				"%s: tcp_lro_init_args [%d] failed\n",
2287a7c62c11SDavid C Somayajulu                                 __func__, i);
2288a7c62c11SDavid C Somayajulu                         return (-1);
2289a7c62c11SDavid C Somayajulu                 }
2290a7c62c11SDavid C Somayajulu #else
2291a7c62c11SDavid C Somayajulu                 if (tcp_lro_init(lro)) {
2292a7c62c11SDavid C Somayajulu                         device_printf(ha->pci_dev,
2293a7c62c11SDavid C Somayajulu 				"%s: tcp_lro_init [%d] failed\n",
2294a7c62c11SDavid C Somayajulu                                 __func__, i);
2295a7c62c11SDavid C Somayajulu                         return (-1);
2296a7c62c11SDavid C Somayajulu                 }
2297a7c62c11SDavid C Somayajulu #endif /* #if (__FreeBSD_version >= 1100101) */
2298a7c62c11SDavid C Somayajulu 
2299a7c62c11SDavid C Somayajulu                 lro->ifp = ha->ifp;
2300a7c62c11SDavid C Somayajulu         }
2301a7c62c11SDavid C Somayajulu 
2302a7c62c11SDavid C Somayajulu         QL_DPRINT2(ha, (ha->pci_dev, "%s: LRO initialized\n", __func__));
2303a7c62c11SDavid C Somayajulu         return (0);
2304a7c62c11SDavid C Somayajulu }
2305a7c62c11SDavid C Somayajulu 
2306a7c62c11SDavid C Somayajulu static void
2307a7c62c11SDavid C Somayajulu qla_drain_soft_lro(qla_host_t *ha)
2308a7c62c11SDavid C Somayajulu {
2309a7c62c11SDavid C Somayajulu         int i;
2310a7c62c11SDavid C Somayajulu         qla_hw_t *hw = &ha->hw;
2311a7c62c11SDavid C Somayajulu         struct lro_ctrl *lro;
2312a7c62c11SDavid C Somayajulu 
2313a7c62c11SDavid C Somayajulu        	for (i = 0; i < hw->num_sds_rings; i++) {
2314a7c62c11SDavid C Somayajulu                	lro = &hw->sds[i].lro;
2315a7c62c11SDavid C Somayajulu 
2316a7c62c11SDavid C Somayajulu #if (__FreeBSD_version >= 1100101)
2317a7c62c11SDavid C Somayajulu 		tcp_lro_flush_all(lro);
2318a7c62c11SDavid C Somayajulu #else
2319a7c62c11SDavid C Somayajulu                 struct lro_entry *queued;
2320a7c62c11SDavid C Somayajulu 
2321a7c62c11SDavid C Somayajulu 		while ((!SLIST_EMPTY(&lro->lro_active))) {
2322a7c62c11SDavid C Somayajulu 			queued = SLIST_FIRST(&lro->lro_active);
2323a7c62c11SDavid C Somayajulu 			SLIST_REMOVE_HEAD(&lro->lro_active, next);
2324a7c62c11SDavid C Somayajulu 			tcp_lro_flush(lro, queued);
2325a7c62c11SDavid C Somayajulu 		}
2326a7c62c11SDavid C Somayajulu #endif /* #if (__FreeBSD_version >= 1100101) */
2327a7c62c11SDavid C Somayajulu 	}
2328a7c62c11SDavid C Somayajulu 
2329a7c62c11SDavid C Somayajulu 	return;
2330a7c62c11SDavid C Somayajulu }
2331a7c62c11SDavid C Somayajulu 
2332a7c62c11SDavid C Somayajulu static void
2333a7c62c11SDavid C Somayajulu qla_free_soft_lro(qla_host_t *ha)
2334a7c62c11SDavid C Somayajulu {
2335a7c62c11SDavid C Somayajulu         int i;
2336a7c62c11SDavid C Somayajulu         qla_hw_t *hw = &ha->hw;
2337a7c62c11SDavid C Somayajulu         struct lro_ctrl *lro;
2338a7c62c11SDavid C Somayajulu 
2339a7c62c11SDavid C Somayajulu         for (i = 0; i < hw->num_sds_rings; i++) {
2340a7c62c11SDavid C Somayajulu                	lro = &hw->sds[i].lro;
2341a7c62c11SDavid C Somayajulu 		tcp_lro_free(lro);
2342a7c62c11SDavid C Somayajulu 	}
2343a7c62c11SDavid C Somayajulu 
2344a7c62c11SDavid C Somayajulu 	return;
2345a7c62c11SDavid C Somayajulu }
2346a7c62c11SDavid C Somayajulu 
2347a7c62c11SDavid C Somayajulu 
2348f10a77bbSDavid C Somayajulu /*
2349f10a77bbSDavid C Somayajulu  * Name: ql_del_hw_if
2350f10a77bbSDavid C Somayajulu  * Function: Destroys the hardware specific entities corresponding to an
2351f10a77bbSDavid C Somayajulu  *	Ethernet Interface
2352f10a77bbSDavid C Somayajulu  */
2353f10a77bbSDavid C Somayajulu void
2354f10a77bbSDavid C Somayajulu ql_del_hw_if(qla_host_t *ha)
2355f10a77bbSDavid C Somayajulu {
235635291c22SDavid C Somayajulu 	uint32_t i;
235735291c22SDavid C Somayajulu 	uint32_t num_msix;
235835291c22SDavid C Somayajulu 
235935291c22SDavid C Somayajulu 	(void)qla_stop_nic_func(ha);
2360f10a77bbSDavid C Somayajulu 
2361f10a77bbSDavid C Somayajulu 	qla_del_rcv_cntxt(ha);
2362da834d52SDavid C Somayajulu 
2363f10a77bbSDavid C Somayajulu 	qla_del_xmt_cntxt(ha);
2364f10a77bbSDavid C Somayajulu 
2365f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.init_intr_cnxt) {
236635291c22SDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; ) {
236735291c22SDavid C Somayajulu 
236835291c22SDavid C Somayajulu 			if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
236935291c22SDavid C Somayajulu 				num_msix = Q8_MAX_INTR_VECTORS;
237035291c22SDavid C Somayajulu 			else
237135291c22SDavid C Somayajulu 				num_msix = ha->hw.num_sds_rings - i;
237235291c22SDavid C Somayajulu 			qla_config_intr_cntxt(ha, i, num_msix, 0);
237335291c22SDavid C Somayajulu 
237435291c22SDavid C Somayajulu 			i += num_msix;
237535291c22SDavid C Somayajulu 		}
237635291c22SDavid C Somayajulu 
2377f10a77bbSDavid C Somayajulu 		ha->hw.flags.init_intr_cnxt = 0;
2378f10a77bbSDavid C Somayajulu 	}
2379da834d52SDavid C Somayajulu 
2380a7c62c11SDavid C Somayajulu 	if (ha->hw.enable_soft_lro) {
2381a7c62c11SDavid C Somayajulu 		qla_drain_soft_lro(ha);
2382a7c62c11SDavid C Somayajulu 		qla_free_soft_lro(ha);
2383a7c62c11SDavid C Somayajulu 	}
2384a7c62c11SDavid C Somayajulu 
238535291c22SDavid C Somayajulu 	return;
2386f10a77bbSDavid C Somayajulu }
2387f10a77bbSDavid C Somayajulu 
238835291c22SDavid C Somayajulu void
238935291c22SDavid C Somayajulu qla_confirm_9kb_enable(qla_host_t *ha)
239035291c22SDavid C Somayajulu {
239135291c22SDavid C Somayajulu 	uint32_t supports_9kb = 0;
239235291c22SDavid C Somayajulu 
239335291c22SDavid C Somayajulu 	ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX);
239435291c22SDavid C Somayajulu 
239535291c22SDavid C Somayajulu 	/* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */
239635291c22SDavid C Somayajulu 	WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2);
239735291c22SDavid C Somayajulu 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
239835291c22SDavid C Somayajulu 
239935291c22SDavid C Somayajulu 	qla_get_nic_partition(ha, &supports_9kb, NULL);
240035291c22SDavid C Somayajulu 
240135291c22SDavid C Somayajulu 	if (!supports_9kb)
240235291c22SDavid C Somayajulu 		ha->hw.enable_9kb = 0;
240335291c22SDavid C Somayajulu 
240435291c22SDavid C Somayajulu 	return;
240535291c22SDavid C Somayajulu }
240635291c22SDavid C Somayajulu 
2407f10a77bbSDavid C Somayajulu /*
2408f10a77bbSDavid C Somayajulu  * Name: ql_init_hw_if
2409f10a77bbSDavid C Somayajulu  * Function: Creates the hardware specific entities corresponding to an
2410f10a77bbSDavid C Somayajulu  *	Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
2411f10a77bbSDavid C Somayajulu  *	corresponding to the interface. Enables LRO if allowed.
2412f10a77bbSDavid C Somayajulu  */
2413f10a77bbSDavid C Somayajulu int
2414f10a77bbSDavid C Somayajulu ql_init_hw_if(qla_host_t *ha)
2415f10a77bbSDavid C Somayajulu {
2416f10a77bbSDavid C Somayajulu 	device_t	dev;
2417f10a77bbSDavid C Somayajulu 	uint32_t	i;
2418f10a77bbSDavid C Somayajulu 	uint8_t		bcast_mac[6];
2419f10a77bbSDavid C Somayajulu 	qla_rdesc_t	*rdesc;
242035291c22SDavid C Somayajulu 	uint32_t	num_msix;
2421f10a77bbSDavid C Somayajulu 
2422f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2423f10a77bbSDavid C Somayajulu 
2424f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; i++) {
2425f10a77bbSDavid C Somayajulu 		bzero(ha->hw.dma_buf.sds_ring[i].dma_b,
2426f10a77bbSDavid C Somayajulu 			ha->hw.dma_buf.sds_ring[i].size);
2427f10a77bbSDavid C Somayajulu 	}
2428f10a77bbSDavid C Somayajulu 
242935291c22SDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; ) {
2430f10a77bbSDavid C Somayajulu 
243135291c22SDavid C Somayajulu 		if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
243235291c22SDavid C Somayajulu 			num_msix = Q8_MAX_INTR_VECTORS;
243335291c22SDavid C Somayajulu 		else
243435291c22SDavid C Somayajulu 			num_msix = ha->hw.num_sds_rings - i;
2435f10a77bbSDavid C Somayajulu 
243635291c22SDavid C Somayajulu 		if (qla_config_intr_cntxt(ha, i, num_msix, 1)) {
243735291c22SDavid C Somayajulu 
243835291c22SDavid C Somayajulu 			if (i > 0) {
243935291c22SDavid C Somayajulu 
244035291c22SDavid C Somayajulu 				num_msix = i;
244135291c22SDavid C Somayajulu 
244235291c22SDavid C Somayajulu 				for (i = 0; i < num_msix; ) {
244335291c22SDavid C Somayajulu 					qla_config_intr_cntxt(ha, i,
244435291c22SDavid C Somayajulu 						Q8_MAX_INTR_VECTORS, 0);
244535291c22SDavid C Somayajulu 					i += Q8_MAX_INTR_VECTORS;
244635291c22SDavid C Somayajulu 				}
244735291c22SDavid C Somayajulu 			}
2448f10a77bbSDavid C Somayajulu 			return (-1);
244935291c22SDavid C Somayajulu 		}
245035291c22SDavid C Somayajulu 
245135291c22SDavid C Somayajulu 		i = i + num_msix;
245235291c22SDavid C Somayajulu 	}
245335291c22SDavid C Somayajulu 
245435291c22SDavid C Somayajulu         ha->hw.flags.init_intr_cnxt = 1;
2455f10a77bbSDavid C Somayajulu 
2456f10a77bbSDavid C Somayajulu 	/*
2457f10a77bbSDavid C Somayajulu 	 * Create Receive Context
2458f10a77bbSDavid C Somayajulu 	 */
2459f10a77bbSDavid C Somayajulu 	if (qla_init_rcv_cntxt(ha)) {
2460f10a77bbSDavid C Somayajulu 		return (-1);
2461f10a77bbSDavid C Somayajulu 	}
2462f10a77bbSDavid C Somayajulu 
2463f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_rds_rings; i++) {
2464f10a77bbSDavid C Somayajulu 		rdesc = &ha->hw.rds[i];
2465f10a77bbSDavid C Somayajulu 		rdesc->rx_next = NUM_RX_DESCRIPTORS - 2;
2466f10a77bbSDavid C Somayajulu 		rdesc->rx_in = 0;
2467f10a77bbSDavid C Somayajulu 		/* Update the RDS Producer Indices */
2468f10a77bbSDavid C Somayajulu 		QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\
2469f10a77bbSDavid C Somayajulu 			rdesc->rx_next);
2470f10a77bbSDavid C Somayajulu 	}
2471f10a77bbSDavid C Somayajulu 
2472f10a77bbSDavid C Somayajulu 
2473f10a77bbSDavid C Somayajulu 	/*
2474f10a77bbSDavid C Somayajulu 	 * Create Transmit Context
2475f10a77bbSDavid C Somayajulu 	 */
2476f10a77bbSDavid C Somayajulu 	if (qla_init_xmt_cntxt(ha)) {
2477f10a77bbSDavid C Somayajulu 		qla_del_rcv_cntxt(ha);
2478f10a77bbSDavid C Somayajulu 		return (-1);
2479f10a77bbSDavid C Somayajulu 	}
2480f10a77bbSDavid C Somayajulu 	ha->hw.max_tx_segs = 0;
2481f10a77bbSDavid C Somayajulu 
2482da834d52SDavid C Somayajulu 	if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1, 1))
2483f10a77bbSDavid C Somayajulu 		return(-1);
2484f10a77bbSDavid C Somayajulu 
2485f10a77bbSDavid C Somayajulu 	ha->hw.flags.unicast_mac = 1;
2486f10a77bbSDavid C Somayajulu 
2487f10a77bbSDavid C Somayajulu 	bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2488f10a77bbSDavid C Somayajulu 	bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2489f10a77bbSDavid C Somayajulu 
2490da834d52SDavid C Somayajulu 	if (qla_config_mac_addr(ha, bcast_mac, 1, 1))
2491f10a77bbSDavid C Somayajulu 		return (-1);
2492f10a77bbSDavid C Somayajulu 
2493f10a77bbSDavid C Somayajulu 	ha->hw.flags.bcast_mac = 1;
2494f10a77bbSDavid C Somayajulu 
2495f10a77bbSDavid C Somayajulu 	/*
2496f10a77bbSDavid C Somayajulu 	 * program any cached multicast addresses
2497f10a77bbSDavid C Somayajulu 	 */
2498f10a77bbSDavid C Somayajulu 	if (qla_hw_add_all_mcast(ha))
2499f10a77bbSDavid C Somayajulu 		return (-1);
2500f10a77bbSDavid C Somayajulu 
2501b5c2be72SDavid C Somayajulu 	if (ql_set_max_mtu(ha, ha->max_frame_size, ha->hw.rcv_cntxt_id))
2502b5c2be72SDavid C Somayajulu 		return (-1);
2503b5c2be72SDavid C Somayajulu 
2504f10a77bbSDavid C Somayajulu 	if (qla_config_rss(ha, ha->hw.rcv_cntxt_id))
2505f10a77bbSDavid C Somayajulu 		return (-1);
2506f10a77bbSDavid C Somayajulu 
2507f10a77bbSDavid C Somayajulu 	if (qla_config_rss_ind_table(ha))
2508f10a77bbSDavid C Somayajulu 		return (-1);
2509f10a77bbSDavid C Somayajulu 
251035291c22SDavid C Somayajulu 	if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1))
2511f10a77bbSDavid C Somayajulu 		return (-1);
2512f10a77bbSDavid C Somayajulu 
2513f10a77bbSDavid C Somayajulu 	if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
2514f10a77bbSDavid C Somayajulu 		return (-1);
2515f10a77bbSDavid C Somayajulu 
2516a7c62c11SDavid C Somayajulu 	if (ha->ifp->if_capenable & IFCAP_LRO) {
2517a7c62c11SDavid C Somayajulu 		if (ha->hw.enable_hw_lro) {
2518a7c62c11SDavid C Somayajulu 			ha->hw.enable_soft_lro = 0;
2519a7c62c11SDavid C Somayajulu 
2520f10a77bbSDavid C Somayajulu 			if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
2521f10a77bbSDavid C Somayajulu 				return (-1);
2522a7c62c11SDavid C Somayajulu 		} else {
2523a7c62c11SDavid C Somayajulu 			ha->hw.enable_soft_lro = 1;
2524a7c62c11SDavid C Somayajulu 
2525a7c62c11SDavid C Somayajulu 			if (qla_config_soft_lro(ha))
2526a7c62c11SDavid C Somayajulu 				return (-1);
2527a7c62c11SDavid C Somayajulu 		}
2528a7c62c11SDavid C Somayajulu 	}
2529f10a77bbSDavid C Somayajulu 
253035291c22SDavid C Somayajulu         if (qla_init_nic_func(ha))
253135291c22SDavid C Somayajulu                 return (-1);
253235291c22SDavid C Somayajulu 
253335291c22SDavid C Somayajulu         if (qla_query_fw_dcbx_caps(ha))
253435291c22SDavid C Somayajulu                 return (-1);
253535291c22SDavid C Somayajulu 
2536f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; i++)
2537f10a77bbSDavid C Somayajulu 		QL_ENABLE_INTERRUPTS(ha, i);
2538f10a77bbSDavid C Somayajulu 
2539f10a77bbSDavid C Somayajulu 	return (0);
2540f10a77bbSDavid C Somayajulu }
2541f10a77bbSDavid C Somayajulu 
2542f10a77bbSDavid C Somayajulu static int
254335291c22SDavid C Somayajulu qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx)
2544f10a77bbSDavid C Somayajulu {
2545f10a77bbSDavid C Somayajulu         device_t                dev = ha->pci_dev;
2546f10a77bbSDavid C Somayajulu         q80_rq_map_sds_to_rds_t *map_rings;
254735291c22SDavid C Somayajulu 	q80_rsp_map_sds_to_rds_t *map_rings_rsp;
2548f10a77bbSDavid C Somayajulu         uint32_t                i, err;
2549f10a77bbSDavid C Somayajulu         qla_hw_t                *hw = &ha->hw;
2550f10a77bbSDavid C Somayajulu 
2551f10a77bbSDavid C Somayajulu         map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox;
2552f10a77bbSDavid C Somayajulu         bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t));
2553f10a77bbSDavid C Somayajulu 
2554f10a77bbSDavid C Somayajulu         map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS;
2555f10a77bbSDavid C Somayajulu         map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2);
2556f10a77bbSDavid C Somayajulu         map_rings->count_version |= Q8_MBX_CMD_VERSION;
2557f10a77bbSDavid C Somayajulu 
2558f10a77bbSDavid C Somayajulu         map_rings->cntxt_id = hw->rcv_cntxt_id;
255935291c22SDavid C Somayajulu         map_rings->num_rings = num_idx;
2560f10a77bbSDavid C Somayajulu 
256135291c22SDavid C Somayajulu 	for (i = 0; i < num_idx; i++) {
256235291c22SDavid C Somayajulu 		map_rings->sds_rds[i].sds_ring = i + start_idx;
256335291c22SDavid C Somayajulu 		map_rings->sds_rds[i].rds_ring = i + start_idx;
2564f10a77bbSDavid C Somayajulu 	}
2565f10a77bbSDavid C Somayajulu 
2566f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)map_rings,
2567f10a77bbSDavid C Somayajulu                 (sizeof (q80_rq_map_sds_to_rds_t) >> 2),
2568f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2569f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2570f10a77bbSDavid C Somayajulu                 return (-1);
2571f10a77bbSDavid C Somayajulu         }
2572f10a77bbSDavid C Somayajulu 
257335291c22SDavid C Somayajulu         map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox;
2574f10a77bbSDavid C Somayajulu 
2575f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status);
2576f10a77bbSDavid C Somayajulu 
2577f10a77bbSDavid C Somayajulu         if (err) {
2578f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2579f10a77bbSDavid C Somayajulu                 return (-1);
2580f10a77bbSDavid C Somayajulu         }
2581f10a77bbSDavid C Somayajulu 
2582f10a77bbSDavid C Somayajulu         return (0);
2583f10a77bbSDavid C Somayajulu }
2584f10a77bbSDavid C Somayajulu 
2585f10a77bbSDavid C Somayajulu /*
2586f10a77bbSDavid C Somayajulu  * Name: qla_init_rcv_cntxt
2587f10a77bbSDavid C Somayajulu  * Function: Creates the Receive Context.
2588f10a77bbSDavid C Somayajulu  */
2589f10a77bbSDavid C Somayajulu static int
2590f10a77bbSDavid C Somayajulu qla_init_rcv_cntxt(qla_host_t *ha)
2591f10a77bbSDavid C Somayajulu {
2592f10a77bbSDavid C Somayajulu 	q80_rq_rcv_cntxt_t	*rcntxt;
2593f10a77bbSDavid C Somayajulu 	q80_rsp_rcv_cntxt_t	*rcntxt_rsp;
2594f10a77bbSDavid C Somayajulu 	q80_stat_desc_t		*sdesc;
2595f10a77bbSDavid C Somayajulu 	int			i, j;
2596f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2597f10a77bbSDavid C Somayajulu 	device_t		dev;
2598f10a77bbSDavid C Somayajulu 	uint32_t		err;
2599f10a77bbSDavid C Somayajulu 	uint32_t		rcntxt_sds_rings;
2600f10a77bbSDavid C Somayajulu 	uint32_t		rcntxt_rds_rings;
260135291c22SDavid C Somayajulu 	uint32_t		max_idx;
2602f10a77bbSDavid C Somayajulu 
2603f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2604f10a77bbSDavid C Somayajulu 
2605f10a77bbSDavid C Somayajulu 	/*
2606f10a77bbSDavid C Somayajulu 	 * Create Receive Context
2607f10a77bbSDavid C Somayajulu 	 */
2608f10a77bbSDavid C Somayajulu 
2609f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
2610f10a77bbSDavid C Somayajulu 		sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0];
2611f10a77bbSDavid C Somayajulu 
2612f10a77bbSDavid C Somayajulu 		for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) {
2613f10a77bbSDavid C Somayajulu 			sdesc->data[0] = 1ULL;
2614f10a77bbSDavid C Somayajulu 			sdesc->data[1] = 1ULL;
2615f10a77bbSDavid C Somayajulu 		}
2616f10a77bbSDavid C Somayajulu 	}
2617f10a77bbSDavid C Somayajulu 
2618f10a77bbSDavid C Somayajulu 	rcntxt_sds_rings = hw->num_sds_rings;
2619f10a77bbSDavid C Somayajulu 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS)
2620f10a77bbSDavid C Somayajulu 		rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS;
2621f10a77bbSDavid C Somayajulu 
2622f10a77bbSDavid C Somayajulu 	rcntxt_rds_rings = hw->num_rds_rings;
2623f10a77bbSDavid C Somayajulu 
2624f10a77bbSDavid C Somayajulu 	if (hw->num_rds_rings > MAX_RDS_RING_SETS)
2625f10a77bbSDavid C Somayajulu 		rcntxt_rds_rings = MAX_RDS_RING_SETS;
2626f10a77bbSDavid C Somayajulu 
2627f10a77bbSDavid C Somayajulu 	rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox;
2628f10a77bbSDavid C Somayajulu 	bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t)));
2629f10a77bbSDavid C Somayajulu 
2630f10a77bbSDavid C Somayajulu 	rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT;
2631f10a77bbSDavid C Somayajulu 	rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2);
2632f10a77bbSDavid C Somayajulu 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2633f10a77bbSDavid C Somayajulu 
2634f10a77bbSDavid C Somayajulu 	rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW |
2635f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_LRO |
2636f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_HW_LRO |
2637f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_RSS |
2638f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_SGL_LRO;
2639f10a77bbSDavid C Somayajulu 
264035291c22SDavid C Somayajulu 	if (ha->hw.enable_9kb)
264135291c22SDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO;
264235291c22SDavid C Somayajulu 	else
264335291c22SDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO;
264435291c22SDavid C Somayajulu 
2645f10a77bbSDavid C Somayajulu 	if (ha->hw.num_rds_rings > 1) {
2646f10a77bbSDavid C Somayajulu 		rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5);
2647f10a77bbSDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS;
2648f10a77bbSDavid C Somayajulu 	} else
2649f10a77bbSDavid C Somayajulu 		rcntxt->nrds_sets_rings = 0x1 | (1 << 5);
2650f10a77bbSDavid C Somayajulu 
2651f10a77bbSDavid C Somayajulu 	rcntxt->nsds_rings = rcntxt_sds_rings;
2652f10a77bbSDavid C Somayajulu 
2653f10a77bbSDavid C Somayajulu 	rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE;
2654f10a77bbSDavid C Somayajulu 
2655f10a77bbSDavid C Somayajulu 	rcntxt->rcv_vpid = 0;
2656f10a77bbSDavid C Somayajulu 
2657f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2658f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].paddr =
2659f10a77bbSDavid C Somayajulu 			qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr);
2660f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].size =
2661f10a77bbSDavid C Somayajulu 			qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2662b89f2279SDavid C Somayajulu 		rcntxt->sds[i].intr_id = qla_host_to_le16(hw->intr_id[i]);
2663f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0);
2664f10a77bbSDavid C Somayajulu 	}
2665f10a77bbSDavid C Somayajulu 
2666f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2667f10a77bbSDavid C Somayajulu 		rcntxt->rds[i].paddr_std =
2668f10a77bbSDavid C Somayajulu 			qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr);
266935291c22SDavid C Somayajulu 
267035291c22SDavid C Somayajulu 		if (ha->hw.enable_9kb)
267135291c22SDavid C Somayajulu 			rcntxt->rds[i].std_bsize =
267235291c22SDavid C Somayajulu 				qla_host_to_le64(MJUM9BYTES);
267335291c22SDavid C Somayajulu 		else
2674f10a77bbSDavid C Somayajulu 			rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
267535291c22SDavid C Somayajulu 
2676f10a77bbSDavid C Somayajulu 		rcntxt->rds[i].std_nentries =
2677f10a77bbSDavid C Somayajulu 			qla_host_to_le32(NUM_RX_DESCRIPTORS);
2678f10a77bbSDavid C Somayajulu 	}
2679f10a77bbSDavid C Somayajulu 
2680f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2681f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_rcv_cntxt_t) >> 2),
2682f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) {
2683f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2684f10a77bbSDavid C Somayajulu                 return (-1);
2685f10a77bbSDavid C Somayajulu         }
2686f10a77bbSDavid C Somayajulu 
2687f10a77bbSDavid C Somayajulu         rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox;
2688f10a77bbSDavid C Somayajulu 
2689f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2690f10a77bbSDavid C Somayajulu 
2691f10a77bbSDavid C Somayajulu         if (err) {
2692f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2693f10a77bbSDavid C Somayajulu                 return (-1);
2694f10a77bbSDavid C Somayajulu         }
2695f10a77bbSDavid C Somayajulu 
2696f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_sds_rings; i++) {
2697f10a77bbSDavid C Somayajulu 		hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i];
2698f10a77bbSDavid C Somayajulu 	}
2699f10a77bbSDavid C Somayajulu 
2700f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_rds_rings; i++) {
2701f10a77bbSDavid C Somayajulu 		hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std;
2702f10a77bbSDavid C Somayajulu 	}
2703f10a77bbSDavid C Somayajulu 
2704f10a77bbSDavid C Somayajulu 	hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id;
2705f10a77bbSDavid C Somayajulu 
2706f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_rx_cnxt = 1;
2707f10a77bbSDavid C Somayajulu 
2708f10a77bbSDavid C Somayajulu 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) {
270935291c22SDavid C Somayajulu 
271035291c22SDavid C Somayajulu 		for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) {
271135291c22SDavid C Somayajulu 
271235291c22SDavid C Somayajulu 			if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings)
271335291c22SDavid C Somayajulu 				max_idx = MAX_RCNTXT_SDS_RINGS;
271435291c22SDavid C Somayajulu 			else
271535291c22SDavid C Somayajulu 				max_idx = hw->num_sds_rings - i;
271635291c22SDavid C Somayajulu 
271735291c22SDavid C Somayajulu 			err = qla_add_rcv_rings(ha, i, max_idx);
2718f10a77bbSDavid C Somayajulu 			if (err)
2719f10a77bbSDavid C Somayajulu 				return -1;
272035291c22SDavid C Somayajulu 
272135291c22SDavid C Somayajulu 			i += max_idx;
272235291c22SDavid C Somayajulu 		}
2723f10a77bbSDavid C Somayajulu 	}
2724f10a77bbSDavid C Somayajulu 
2725f10a77bbSDavid C Somayajulu 	if (hw->num_rds_rings > 1) {
272635291c22SDavid C Somayajulu 
272735291c22SDavid C Somayajulu 		for (i = 0; i < hw->num_rds_rings; ) {
272835291c22SDavid C Somayajulu 
272935291c22SDavid C Somayajulu 			if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings)
273035291c22SDavid C Somayajulu 				max_idx = MAX_SDS_TO_RDS_MAP;
273135291c22SDavid C Somayajulu 			else
273235291c22SDavid C Somayajulu 				max_idx = hw->num_rds_rings - i;
273335291c22SDavid C Somayajulu 
273435291c22SDavid C Somayajulu 			err = qla_map_sds_to_rds(ha, i, max_idx);
2735f10a77bbSDavid C Somayajulu 			if (err)
2736f10a77bbSDavid C Somayajulu 				return -1;
273735291c22SDavid C Somayajulu 
273835291c22SDavid C Somayajulu 			i += max_idx;
273935291c22SDavid C Somayajulu 		}
2740f10a77bbSDavid C Somayajulu 	}
2741f10a77bbSDavid C Somayajulu 
2742f10a77bbSDavid C Somayajulu 	return (0);
2743f10a77bbSDavid C Somayajulu }
2744f10a77bbSDavid C Somayajulu 
2745f10a77bbSDavid C Somayajulu static int
274635291c22SDavid C Somayajulu qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds)
2747f10a77bbSDavid C Somayajulu {
2748f10a77bbSDavid C Somayajulu 	device_t		dev = ha->pci_dev;
2749f10a77bbSDavid C Somayajulu 	q80_rq_add_rcv_rings_t	*add_rcv;
2750f10a77bbSDavid C Somayajulu 	q80_rsp_add_rcv_rings_t	*add_rcv_rsp;
2751f10a77bbSDavid C Somayajulu 	uint32_t		i,j, err;
2752f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2753f10a77bbSDavid C Somayajulu 
2754f10a77bbSDavid C Somayajulu 	add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox;
2755f10a77bbSDavid C Somayajulu 	bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t));
2756f10a77bbSDavid C Somayajulu 
2757f10a77bbSDavid C Somayajulu 	add_rcv->opcode = Q8_MBX_ADD_RX_RINGS;
2758f10a77bbSDavid C Somayajulu 	add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2);
2759f10a77bbSDavid C Somayajulu 	add_rcv->count_version |= Q8_MBX_CMD_VERSION;
2760f10a77bbSDavid C Somayajulu 
2761f10a77bbSDavid C Somayajulu 	add_rcv->nrds_sets_rings = nsds | (1 << 5);
2762f10a77bbSDavid C Somayajulu 	add_rcv->nsds_rings = nsds;
2763f10a77bbSDavid C Somayajulu 	add_rcv->cntxt_id = hw->rcv_cntxt_id;
2764f10a77bbSDavid C Somayajulu 
2765f10a77bbSDavid C Somayajulu         for (i = 0; i <  nsds; i++) {
2766f10a77bbSDavid C Somayajulu 
2767f10a77bbSDavid C Somayajulu 		j = i + sds_idx;
2768f10a77bbSDavid C Somayajulu 
2769f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].paddr =
2770f10a77bbSDavid C Somayajulu                         qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr);
2771f10a77bbSDavid C Somayajulu 
2772f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].size =
2773f10a77bbSDavid C Somayajulu                         qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
2774f10a77bbSDavid C Somayajulu 
2775b89f2279SDavid C Somayajulu                 add_rcv->sds[i].intr_id = qla_host_to_le16(hw->intr_id[j]);
2776f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0);
2777f10a77bbSDavid C Somayajulu 
2778f10a77bbSDavid C Somayajulu         }
2779b89f2279SDavid C Somayajulu 
278035291c22SDavid C Somayajulu         for (i = 0; (i <  nsds); i++) {
2781f10a77bbSDavid C Somayajulu                 j = i + sds_idx;
278235291c22SDavid C Somayajulu 
2783f10a77bbSDavid C Somayajulu                 add_rcv->rds[i].paddr_std =
2784f10a77bbSDavid C Somayajulu                         qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr);
278535291c22SDavid C Somayajulu 
278635291c22SDavid C Somayajulu 		if (ha->hw.enable_9kb)
278735291c22SDavid C Somayajulu 			add_rcv->rds[i].std_bsize =
278835291c22SDavid C Somayajulu 				qla_host_to_le64(MJUM9BYTES);
278935291c22SDavid C Somayajulu 		else
2790f10a77bbSDavid C Somayajulu                 	add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
279135291c22SDavid C Somayajulu 
2792f10a77bbSDavid C Somayajulu                 add_rcv->rds[i].std_nentries =
2793f10a77bbSDavid C Somayajulu                         qla_host_to_le32(NUM_RX_DESCRIPTORS);
2794f10a77bbSDavid C Somayajulu         }
2795f10a77bbSDavid C Somayajulu 
2796f10a77bbSDavid C Somayajulu 
2797f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)add_rcv,
2798f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_add_rcv_rings_t) >> 2),
2799f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
2800f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2801f10a77bbSDavid C Somayajulu                 return (-1);
2802f10a77bbSDavid C Somayajulu         }
2803f10a77bbSDavid C Somayajulu 
2804f10a77bbSDavid C Somayajulu         add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
2805f10a77bbSDavid C Somayajulu 
2806f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status);
2807f10a77bbSDavid C Somayajulu 
2808f10a77bbSDavid C Somayajulu         if (err) {
2809f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2810f10a77bbSDavid C Somayajulu                 return (-1);
2811f10a77bbSDavid C Somayajulu         }
2812f10a77bbSDavid C Somayajulu 
281335291c22SDavid C Somayajulu 	for (i = 0; i < nsds; i++) {
281435291c22SDavid C Somayajulu 		hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i];
2815f10a77bbSDavid C Somayajulu 	}
281635291c22SDavid C Somayajulu 
281735291c22SDavid C Somayajulu 	for (i = 0; i < nsds; i++) {
281835291c22SDavid C Somayajulu 		hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std;
2819f10a77bbSDavid C Somayajulu 	}
282035291c22SDavid C Somayajulu 
2821f10a77bbSDavid C Somayajulu 	return (0);
2822f10a77bbSDavid C Somayajulu }
2823f10a77bbSDavid C Somayajulu 
2824f10a77bbSDavid C Somayajulu /*
2825f10a77bbSDavid C Somayajulu  * Name: qla_del_rcv_cntxt
2826f10a77bbSDavid C Somayajulu  * Function: Destroys the Receive Context.
2827f10a77bbSDavid C Somayajulu  */
2828f10a77bbSDavid C Somayajulu static void
2829f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(qla_host_t *ha)
2830f10a77bbSDavid C Somayajulu {
2831f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
2832f10a77bbSDavid C Somayajulu 	q80_rcv_cntxt_destroy_t		*rcntxt;
2833f10a77bbSDavid C Somayajulu 	q80_rcv_cntxt_destroy_rsp_t	*rcntxt_rsp;
2834f10a77bbSDavid C Somayajulu 	uint32_t			err;
2835f10a77bbSDavid C Somayajulu 	uint8_t				bcast_mac[6];
2836f10a77bbSDavid C Somayajulu 
2837f10a77bbSDavid C Somayajulu 	if (!ha->hw.flags.init_rx_cnxt)
2838f10a77bbSDavid C Somayajulu 		return;
2839f10a77bbSDavid C Somayajulu 
2840f10a77bbSDavid C Somayajulu 	if (qla_hw_del_all_mcast(ha))
2841f10a77bbSDavid C Somayajulu 		return;
2842f10a77bbSDavid C Somayajulu 
2843f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.bcast_mac) {
2844f10a77bbSDavid C Somayajulu 
2845f10a77bbSDavid C Somayajulu 		bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2846f10a77bbSDavid C Somayajulu 		bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2847f10a77bbSDavid C Somayajulu 
2848da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, bcast_mac, 0, 1))
2849f10a77bbSDavid C Somayajulu 			return;
2850f10a77bbSDavid C Somayajulu 		ha->hw.flags.bcast_mac = 0;
2851f10a77bbSDavid C Somayajulu 
2852f10a77bbSDavid C Somayajulu 	}
2853f10a77bbSDavid C Somayajulu 
2854f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.unicast_mac) {
2855da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0, 1))
2856f10a77bbSDavid C Somayajulu 			return;
2857f10a77bbSDavid C Somayajulu 		ha->hw.flags.unicast_mac = 0;
2858f10a77bbSDavid C Somayajulu 	}
2859f10a77bbSDavid C Somayajulu 
2860f10a77bbSDavid C Somayajulu 	rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox;
2861f10a77bbSDavid C Somayajulu 	bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t)));
2862f10a77bbSDavid C Somayajulu 
2863f10a77bbSDavid C Somayajulu 	rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT;
2864f10a77bbSDavid C Somayajulu 	rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2);
2865f10a77bbSDavid C Somayajulu 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
2866f10a77bbSDavid C Somayajulu 
2867f10a77bbSDavid C Somayajulu 	rcntxt->cntxt_id = ha->hw.rcv_cntxt_id;
2868f10a77bbSDavid C Somayajulu 
2869f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
2870f10a77bbSDavid C Somayajulu 		(sizeof (q80_rcv_cntxt_destroy_t) >> 2),
2871f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) {
2872f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2873f10a77bbSDavid C Somayajulu                 return;
2874f10a77bbSDavid C Somayajulu         }
2875f10a77bbSDavid C Somayajulu         rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox;
2876f10a77bbSDavid C Somayajulu 
2877f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
2878f10a77bbSDavid C Somayajulu 
2879f10a77bbSDavid C Somayajulu         if (err) {
2880f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2881f10a77bbSDavid C Somayajulu         }
2882f10a77bbSDavid C Somayajulu 
2883f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_rx_cnxt = 0;
2884f10a77bbSDavid C Somayajulu 	return;
2885f10a77bbSDavid C Somayajulu }
2886f10a77bbSDavid C Somayajulu 
2887f10a77bbSDavid C Somayajulu /*
2888f10a77bbSDavid C Somayajulu  * Name: qla_init_xmt_cntxt
2889f10a77bbSDavid C Somayajulu  * Function: Creates the Transmit Context.
2890f10a77bbSDavid C Somayajulu  */
2891f10a77bbSDavid C Somayajulu static int
2892f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2893f10a77bbSDavid C Somayajulu {
2894f10a77bbSDavid C Somayajulu 	device_t		dev;
2895f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
2896f10a77bbSDavid C Somayajulu 	q80_rq_tx_cntxt_t	*tcntxt;
2897f10a77bbSDavid C Somayajulu 	q80_rsp_tx_cntxt_t	*tcntxt_rsp;
2898f10a77bbSDavid C Somayajulu 	uint32_t		err;
2899f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t       *hw_tx_cntxt;
2900b89f2279SDavid C Somayajulu 	uint32_t		intr_idx;
2901f10a77bbSDavid C Somayajulu 
2902f10a77bbSDavid C Somayajulu 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
2903f10a77bbSDavid C Somayajulu 
2904f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2905f10a77bbSDavid C Somayajulu 
2906f10a77bbSDavid C Somayajulu 	/*
2907f10a77bbSDavid C Somayajulu 	 * Create Transmit Context
2908f10a77bbSDavid C Somayajulu 	 */
2909f10a77bbSDavid C Somayajulu 	tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox;
2910f10a77bbSDavid C Somayajulu 	bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t)));
2911f10a77bbSDavid C Somayajulu 
2912f10a77bbSDavid C Somayajulu 	tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT;
2913f10a77bbSDavid C Somayajulu 	tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2);
2914f10a77bbSDavid C Somayajulu 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2915f10a77bbSDavid C Somayajulu 
2916b89f2279SDavid C Somayajulu 	intr_idx = txr_idx;
2917b89f2279SDavid C Somayajulu 
291835291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV
291935291c22SDavid C Somayajulu 
292035291c22SDavid C Somayajulu 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO |
292135291c22SDavid C Somayajulu 				Q8_TX_CNTXT_CAP0_TC;
292235291c22SDavid C Somayajulu 
292335291c22SDavid C Somayajulu 	if (txr_idx >= (ha->hw.num_tx_rings >> 1)) {
292435291c22SDavid C Somayajulu 		tcntxt->traffic_class = 1;
292535291c22SDavid C Somayajulu 	}
292635291c22SDavid C Somayajulu 
2927b89f2279SDavid C Somayajulu 	intr_idx = txr_idx % (ha->hw.num_tx_rings >> 1);
292835291c22SDavid C Somayajulu 
2929b89f2279SDavid C Somayajulu #else
2930f10a77bbSDavid C Somayajulu 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO;
2931f10a77bbSDavid C Somayajulu 
293235291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
293335291c22SDavid C Somayajulu 
2934f10a77bbSDavid C Somayajulu 	tcntxt->ntx_rings = 1;
2935f10a77bbSDavid C Somayajulu 
2936f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].paddr =
2937f10a77bbSDavid C Somayajulu 		qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr);
2938f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].tx_consumer =
2939f10a77bbSDavid C Somayajulu 		qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr);
2940f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS);
2941f10a77bbSDavid C Somayajulu 
2942b89f2279SDavid C Somayajulu 	tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[intr_idx]);
2943f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0);
2944f10a77bbSDavid C Somayajulu 
2945f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS;
2946f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0;
2947f10a77bbSDavid C Somayajulu 
2948f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2949f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_tx_cntxt_t) >> 2),
2950f10a77bbSDavid C Somayajulu                 ha->hw.mbox,
2951f10a77bbSDavid C Somayajulu 		(sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) {
2952f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2953f10a77bbSDavid C Somayajulu                 return (-1);
2954f10a77bbSDavid C Somayajulu         }
2955f10a77bbSDavid C Somayajulu         tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox;
2956f10a77bbSDavid C Somayajulu 
2957f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
2958f10a77bbSDavid C Somayajulu 
2959f10a77bbSDavid C Somayajulu         if (err) {
2960f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
2961f10a77bbSDavid C Somayajulu 		return -1;
2962f10a77bbSDavid C Somayajulu         }
2963f10a77bbSDavid C Somayajulu 
2964f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index;
2965f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id;
2966f10a77bbSDavid C Somayajulu 
296735291c22SDavid C Somayajulu 	if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0))
296835291c22SDavid C Somayajulu 		return (-1);
296935291c22SDavid C Somayajulu 
2970f10a77bbSDavid C Somayajulu 	return (0);
2971f10a77bbSDavid C Somayajulu }
2972f10a77bbSDavid C Somayajulu 
2973f10a77bbSDavid C Somayajulu 
2974f10a77bbSDavid C Somayajulu /*
2975f10a77bbSDavid C Somayajulu  * Name: qla_del_xmt_cntxt
2976f10a77bbSDavid C Somayajulu  * Function: Destroys the Transmit Context.
2977f10a77bbSDavid C Somayajulu  */
2978f10a77bbSDavid C Somayajulu static int
2979f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
2980f10a77bbSDavid C Somayajulu {
2981f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
2982f10a77bbSDavid C Somayajulu 	q80_tx_cntxt_destroy_t		*tcntxt;
2983f10a77bbSDavid C Somayajulu 	q80_tx_cntxt_destroy_rsp_t	*tcntxt_rsp;
2984f10a77bbSDavid C Somayajulu 	uint32_t			err;
2985f10a77bbSDavid C Somayajulu 
2986f10a77bbSDavid C Somayajulu 	tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox;
2987f10a77bbSDavid C Somayajulu 	bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t)));
2988f10a77bbSDavid C Somayajulu 
2989f10a77bbSDavid C Somayajulu 	tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT;
2990f10a77bbSDavid C Somayajulu 	tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2);
2991f10a77bbSDavid C Somayajulu 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
2992f10a77bbSDavid C Somayajulu 
2993f10a77bbSDavid C Somayajulu 	tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id;
2994f10a77bbSDavid C Somayajulu 
2995f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
2996f10a77bbSDavid C Somayajulu 		(sizeof (q80_tx_cntxt_destroy_t) >> 2),
2997f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) {
2998f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
2999f10a77bbSDavid C Somayajulu                 return (-1);
3000f10a77bbSDavid C Somayajulu         }
3001f10a77bbSDavid C Somayajulu         tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox;
3002f10a77bbSDavid C Somayajulu 
3003f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
3004f10a77bbSDavid C Somayajulu 
3005f10a77bbSDavid C Somayajulu         if (err) {
3006f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3007f10a77bbSDavid C Somayajulu 		return (-1);
3008f10a77bbSDavid C Somayajulu         }
3009f10a77bbSDavid C Somayajulu 
3010f10a77bbSDavid C Somayajulu 	return (0);
3011f10a77bbSDavid C Somayajulu }
3012f10a77bbSDavid C Somayajulu static void
3013f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt(qla_host_t *ha)
3014f10a77bbSDavid C Somayajulu {
3015f10a77bbSDavid C Somayajulu 	uint32_t i;
3016f10a77bbSDavid C Somayajulu 
3017f10a77bbSDavid C Somayajulu 	if (!ha->hw.flags.init_tx_cnxt)
3018f10a77bbSDavid C Somayajulu 		return;
3019f10a77bbSDavid C Somayajulu 
3020f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
3021f10a77bbSDavid C Somayajulu 		if (qla_del_xmt_cntxt_i(ha, i))
3022f10a77bbSDavid C Somayajulu 			break;
3023f10a77bbSDavid C Somayajulu 	}
3024f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_tx_cnxt = 0;
3025f10a77bbSDavid C Somayajulu }
3026f10a77bbSDavid C Somayajulu 
3027f10a77bbSDavid C Somayajulu static int
3028f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt(qla_host_t *ha)
3029f10a77bbSDavid C Somayajulu {
3030f10a77bbSDavid C Somayajulu 	uint32_t i, j;
3031f10a77bbSDavid C Somayajulu 
3032f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
3033f10a77bbSDavid C Somayajulu 		if (qla_init_xmt_cntxt_i(ha, i) != 0) {
3034f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
3035f10a77bbSDavid C Somayajulu 				qla_del_xmt_cntxt_i(ha, j);
3036f10a77bbSDavid C Somayajulu 			return (-1);
3037f10a77bbSDavid C Somayajulu 		}
3038f10a77bbSDavid C Somayajulu 	}
3039f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_tx_cnxt = 1;
3040f10a77bbSDavid C Somayajulu 	return (0);
3041f10a77bbSDavid C Somayajulu }
3042f10a77bbSDavid C Somayajulu 
3043f10a77bbSDavid C Somayajulu static int
3044da834d52SDavid C Somayajulu qla_hw_all_mcast(qla_host_t *ha, uint32_t add_mcast)
3045f10a77bbSDavid C Somayajulu {
3046f10a77bbSDavid C Somayajulu 	int i, nmcast;
3047da834d52SDavid C Somayajulu 	uint32_t count = 0;
3048da834d52SDavid C Somayajulu 	uint8_t *mcast;
3049f10a77bbSDavid C Somayajulu 
3050f10a77bbSDavid C Somayajulu 	nmcast = ha->hw.nmcast;
3051f10a77bbSDavid C Somayajulu 
3052da834d52SDavid C Somayajulu 	QL_DPRINT2(ha, (ha->pci_dev,
3053da834d52SDavid C Somayajulu 		"%s:[0x%x] enter nmcast = %d \n", __func__, add_mcast, nmcast));
3054da834d52SDavid C Somayajulu 
3055da834d52SDavid C Somayajulu 	mcast = ha->hw.mac_addr_arr;
3056da834d52SDavid C Somayajulu 	memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3057da834d52SDavid C Somayajulu 
3058f10a77bbSDavid C Somayajulu 	for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
3059f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] != 0) ||
3060f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] != 0) ||
3061f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] != 0) ||
3062f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] != 0) ||
3063f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] != 0) ||
3064f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] != 0)) {
3065f10a77bbSDavid C Somayajulu 
3066da834d52SDavid C Somayajulu 			bcopy(ha->hw.mcast[i].addr, mcast, ETHER_ADDR_LEN);
3067da834d52SDavid C Somayajulu 			mcast = mcast + ETHER_ADDR_LEN;
3068da834d52SDavid C Somayajulu 			count++;
3069da834d52SDavid C Somayajulu 
3070da834d52SDavid C Somayajulu 			if (count == Q8_MAX_MAC_ADDRS) {
3071da834d52SDavid C Somayajulu 				if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3072da834d52SDavid C Somayajulu 					add_mcast, count)) {
3073da834d52SDavid C Somayajulu                 			device_printf(ha->pci_dev,
3074da834d52SDavid C Somayajulu 						"%s: failed\n", __func__);
3075f10a77bbSDavid C Somayajulu 					return (-1);
3076f10a77bbSDavid C Somayajulu 				}
3077f10a77bbSDavid C Somayajulu 
3078da834d52SDavid C Somayajulu 				count = 0;
3079da834d52SDavid C Somayajulu 				mcast = ha->hw.mac_addr_arr;
3080da834d52SDavid C Somayajulu 				memset(mcast, 0,
3081da834d52SDavid C Somayajulu 					(Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3082da834d52SDavid C Somayajulu 			}
3083da834d52SDavid C Somayajulu 
3084f10a77bbSDavid C Somayajulu 			nmcast--;
3085f10a77bbSDavid C Somayajulu 		}
3086f10a77bbSDavid C Somayajulu 	}
3087da834d52SDavid C Somayajulu 
3088da834d52SDavid C Somayajulu 	if (count) {
3089da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mcast,
3090da834d52SDavid C Somayajulu 			count)) {
3091da834d52SDavid C Somayajulu                 	device_printf(ha->pci_dev, "%s: failed\n", __func__);
3092da834d52SDavid C Somayajulu 			return (-1);
3093da834d52SDavid C Somayajulu 		}
3094da834d52SDavid C Somayajulu 	}
3095da834d52SDavid C Somayajulu 	QL_DPRINT2(ha, (ha->pci_dev,
3096da834d52SDavid C Somayajulu 		"%s:[0x%x] exit nmcast = %d \n", __func__, add_mcast, nmcast));
3097da834d52SDavid C Somayajulu 
3098f10a77bbSDavid C Somayajulu 	return 0;
3099f10a77bbSDavid C Somayajulu }
3100f10a77bbSDavid C Somayajulu 
3101f10a77bbSDavid C Somayajulu static int
3102da834d52SDavid C Somayajulu qla_hw_add_all_mcast(qla_host_t *ha)
3103da834d52SDavid C Somayajulu {
3104da834d52SDavid C Somayajulu 	int ret;
3105da834d52SDavid C Somayajulu 
3106da834d52SDavid C Somayajulu 	ret = qla_hw_all_mcast(ha, 1);
3107da834d52SDavid C Somayajulu 
3108da834d52SDavid C Somayajulu 	return (ret);
3109da834d52SDavid C Somayajulu }
3110da834d52SDavid C Somayajulu 
3111da834d52SDavid C Somayajulu static int
3112f10a77bbSDavid C Somayajulu qla_hw_del_all_mcast(qla_host_t *ha)
3113f10a77bbSDavid C Somayajulu {
3114da834d52SDavid C Somayajulu 	int ret;
3115f10a77bbSDavid C Somayajulu 
3116da834d52SDavid C Somayajulu 	ret = qla_hw_all_mcast(ha, 0);
3117f10a77bbSDavid C Somayajulu 
3118da834d52SDavid C Somayajulu 	bzero(ha->hw.mcast, (sizeof (qla_mcast_t) * Q8_MAX_NUM_MULTICAST_ADDRS));
3119da834d52SDavid C Somayajulu 	ha->hw.nmcast = 0;
3120f10a77bbSDavid C Somayajulu 
3121da834d52SDavid C Somayajulu 	return (ret);
3122f10a77bbSDavid C Somayajulu }
3123f10a77bbSDavid C Somayajulu 
3124f10a77bbSDavid C Somayajulu static int
3125da834d52SDavid C Somayajulu qla_hw_mac_addr_present(qla_host_t *ha, uint8_t *mta)
3126f10a77bbSDavid C Somayajulu {
3127f10a77bbSDavid C Somayajulu 	int i;
3128f10a77bbSDavid C Somayajulu 
3129f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3130f10a77bbSDavid C Somayajulu 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0)
3131da834d52SDavid C Somayajulu 			return (0); /* its been already added */
3132f10a77bbSDavid C Somayajulu 	}
3133da834d52SDavid C Somayajulu 	return (-1);
3134da834d52SDavid C Somayajulu }
3135da834d52SDavid C Somayajulu 
3136da834d52SDavid C Somayajulu static int
3137da834d52SDavid C Somayajulu qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3138da834d52SDavid C Somayajulu {
3139da834d52SDavid C Somayajulu 	int i;
3140f10a77bbSDavid C Somayajulu 
3141f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3142f10a77bbSDavid C Somayajulu 
3143f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] == 0) &&
3144f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] == 0) &&
3145f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] == 0) &&
3146f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] == 0) &&
3147f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] == 0) &&
3148f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] == 0)) {
3149f10a77bbSDavid C Somayajulu 
3150f10a77bbSDavid C Somayajulu 			bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN);
3151f10a77bbSDavid C Somayajulu 			ha->hw.nmcast++;
3152f10a77bbSDavid C Somayajulu 
3153da834d52SDavid C Somayajulu 			mta = mta + ETHER_ADDR_LEN;
3154da834d52SDavid C Somayajulu 			nmcast--;
3155da834d52SDavid C Somayajulu 
3156da834d52SDavid C Somayajulu 			if (nmcast == 0)
3157da834d52SDavid C Somayajulu 				break;
3158f10a77bbSDavid C Somayajulu 		}
3159da834d52SDavid C Somayajulu 
3160f10a77bbSDavid C Somayajulu 	}
3161f10a77bbSDavid C Somayajulu 	return 0;
3162f10a77bbSDavid C Somayajulu }
3163f10a77bbSDavid C Somayajulu 
3164f10a77bbSDavid C Somayajulu static int
3165da834d52SDavid C Somayajulu qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3166f10a77bbSDavid C Somayajulu {
3167f10a77bbSDavid C Somayajulu 	int i;
3168f10a77bbSDavid C Somayajulu 
3169f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3170f10a77bbSDavid C Somayajulu 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) {
3171f10a77bbSDavid C Somayajulu 
3172f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[0] = 0;
3173f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[1] = 0;
3174f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[2] = 0;
3175f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[3] = 0;
3176f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[4] = 0;
3177f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[5] = 0;
3178f10a77bbSDavid C Somayajulu 
3179f10a77bbSDavid C Somayajulu 			ha->hw.nmcast--;
3180f10a77bbSDavid C Somayajulu 
3181da834d52SDavid C Somayajulu 			mta = mta + ETHER_ADDR_LEN;
3182da834d52SDavid C Somayajulu 			nmcast--;
3183da834d52SDavid C Somayajulu 
3184da834d52SDavid C Somayajulu 			if (nmcast == 0)
3185da834d52SDavid C Somayajulu 				break;
3186f10a77bbSDavid C Somayajulu 		}
3187f10a77bbSDavid C Somayajulu 	}
3188f10a77bbSDavid C Somayajulu 	return 0;
3189f10a77bbSDavid C Somayajulu }
3190f10a77bbSDavid C Somayajulu 
3191f10a77bbSDavid C Somayajulu /*
3192f10a77bbSDavid C Somayajulu  * Name: ql_hw_set_multi
3193da834d52SDavid C Somayajulu  * Function: Sets the Multicast Addresses provided by the host O.S into the
3194f10a77bbSDavid C Somayajulu  *	hardware (for the given interface)
3195f10a77bbSDavid C Somayajulu  */
3196f10a77bbSDavid C Somayajulu int
3197da834d52SDavid C Somayajulu ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast_addr, uint32_t mcnt,
3198f10a77bbSDavid C Somayajulu 	uint32_t add_mac)
3199f10a77bbSDavid C Somayajulu {
3200da834d52SDavid C Somayajulu 	uint8_t *mta = mcast_addr;
3201f10a77bbSDavid C Somayajulu 	int i;
3202f10a77bbSDavid C Somayajulu 	int ret = 0;
3203da834d52SDavid C Somayajulu 	uint32_t count = 0;
3204da834d52SDavid C Somayajulu 	uint8_t *mcast;
3205da834d52SDavid C Somayajulu 
3206da834d52SDavid C Somayajulu 	mcast = ha->hw.mac_addr_arr;
3207da834d52SDavid C Somayajulu 	memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3208f10a77bbSDavid C Somayajulu 
3209f10a77bbSDavid C Somayajulu 	for (i = 0; i < mcnt; i++) {
3210da834d52SDavid C Somayajulu 		if (mta[0] || mta[1] || mta[2] || mta[3] || mta[4] || mta[5]) {
3211f10a77bbSDavid C Somayajulu 			if (add_mac) {
3212da834d52SDavid C Somayajulu 				if (qla_hw_mac_addr_present(ha, mta) != 0) {
3213da834d52SDavid C Somayajulu 					bcopy(mta, mcast, ETHER_ADDR_LEN);
3214da834d52SDavid C Somayajulu 					mcast = mcast + ETHER_ADDR_LEN;
3215da834d52SDavid C Somayajulu 					count++;
3216da834d52SDavid C Somayajulu 				}
3217f10a77bbSDavid C Somayajulu 			} else {
3218da834d52SDavid C Somayajulu 				if (qla_hw_mac_addr_present(ha, mta) == 0) {
3219da834d52SDavid C Somayajulu 					bcopy(mta, mcast, ETHER_ADDR_LEN);
3220da834d52SDavid C Somayajulu 					mcast = mcast + ETHER_ADDR_LEN;
3221da834d52SDavid C Somayajulu 					count++;
3222da834d52SDavid C Somayajulu 				}
3223da834d52SDavid C Somayajulu 			}
3224da834d52SDavid C Somayajulu 		}
3225da834d52SDavid C Somayajulu 		if (count == Q8_MAX_MAC_ADDRS) {
3226da834d52SDavid C Somayajulu 			if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3227da834d52SDavid C Somayajulu 				add_mac, count)) {
3228da834d52SDavid C Somayajulu                 		device_printf(ha->pci_dev, "%s: failed\n",
3229da834d52SDavid C Somayajulu 					__func__);
3230da834d52SDavid C Somayajulu 				return (-1);
3231da834d52SDavid C Somayajulu 			}
3232da834d52SDavid C Somayajulu 
3233da834d52SDavid C Somayajulu 			if (add_mac) {
3234da834d52SDavid C Somayajulu 				qla_hw_add_mcast(ha, ha->hw.mac_addr_arr,
3235da834d52SDavid C Somayajulu 					count);
3236da834d52SDavid C Somayajulu 			} else {
3237da834d52SDavid C Somayajulu 				qla_hw_del_mcast(ha, ha->hw.mac_addr_arr,
3238da834d52SDavid C Somayajulu 					count);
3239da834d52SDavid C Somayajulu 			}
3240da834d52SDavid C Somayajulu 
3241da834d52SDavid C Somayajulu 			count = 0;
3242da834d52SDavid C Somayajulu 			mcast = ha->hw.mac_addr_arr;
3243da834d52SDavid C Somayajulu 			memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3244f10a77bbSDavid C Somayajulu 		}
3245f10a77bbSDavid C Somayajulu 
3246f10a77bbSDavid C Somayajulu 		mta += Q8_MAC_ADDR_LEN;
3247f10a77bbSDavid C Somayajulu 	}
3248da834d52SDavid C Somayajulu 
3249da834d52SDavid C Somayajulu 	if (count) {
3250da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mac,
3251da834d52SDavid C Somayajulu 			count)) {
3252da834d52SDavid C Somayajulu                 	device_printf(ha->pci_dev, "%s: failed\n", __func__);
3253da834d52SDavid C Somayajulu 			return (-1);
3254da834d52SDavid C Somayajulu 		}
3255da834d52SDavid C Somayajulu 		if (add_mac) {
3256da834d52SDavid C Somayajulu 			qla_hw_add_mcast(ha, ha->hw.mac_addr_arr, count);
3257da834d52SDavid C Somayajulu 		} else {
3258da834d52SDavid C Somayajulu 			qla_hw_del_mcast(ha, ha->hw.mac_addr_arr, count);
3259da834d52SDavid C Somayajulu 		}
3260da834d52SDavid C Somayajulu 	}
3261da834d52SDavid C Somayajulu 
3262f10a77bbSDavid C Somayajulu 	return (ret);
3263f10a77bbSDavid C Somayajulu }
3264f10a77bbSDavid C Somayajulu 
3265f10a77bbSDavid C Somayajulu /*
3266b89f2279SDavid C Somayajulu  * Name: ql_hw_tx_done_locked
3267f10a77bbSDavid C Somayajulu  * Function: Handle Transmit Completions
3268f10a77bbSDavid C Somayajulu  */
3269b89f2279SDavid C Somayajulu void
3270b89f2279SDavid C Somayajulu ql_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx)
3271f10a77bbSDavid C Somayajulu {
3272f10a77bbSDavid C Somayajulu 	qla_tx_buf_t *txb;
3273f10a77bbSDavid C Somayajulu         qla_hw_t *hw = &ha->hw;
3274f10a77bbSDavid C Somayajulu 	uint32_t comp_idx, comp_count = 0;
3275f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t *hw_tx_cntxt;
3276f10a77bbSDavid C Somayajulu 
3277f10a77bbSDavid C Somayajulu 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3278f10a77bbSDavid C Somayajulu 
3279f10a77bbSDavid C Somayajulu 	/* retrieve index of last entry in tx ring completed */
3280f10a77bbSDavid C Somayajulu 	comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons));
3281f10a77bbSDavid C Somayajulu 
3282f10a77bbSDavid C Somayajulu 	while (comp_idx != hw_tx_cntxt->txr_comp) {
3283f10a77bbSDavid C Somayajulu 
3284f10a77bbSDavid C Somayajulu 		txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp];
3285f10a77bbSDavid C Somayajulu 
3286f10a77bbSDavid C Somayajulu 		hw_tx_cntxt->txr_comp++;
3287f10a77bbSDavid C Somayajulu 		if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS)
3288f10a77bbSDavid C Somayajulu 			hw_tx_cntxt->txr_comp = 0;
3289f10a77bbSDavid C Somayajulu 
3290f10a77bbSDavid C Somayajulu 		comp_count++;
3291f10a77bbSDavid C Somayajulu 
3292f10a77bbSDavid C Somayajulu 		if (txb->m_head) {
3293c8dfaf38SGleb Smirnoff 			if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1);
3294f10a77bbSDavid C Somayajulu 
3295f10a77bbSDavid C Somayajulu 			bus_dmamap_sync(ha->tx_tag, txb->map,
3296f10a77bbSDavid C Somayajulu 				BUS_DMASYNC_POSTWRITE);
3297f10a77bbSDavid C Somayajulu 			bus_dmamap_unload(ha->tx_tag, txb->map);
3298f10a77bbSDavid C Somayajulu 			m_freem(txb->m_head);
3299f10a77bbSDavid C Somayajulu 
3300f10a77bbSDavid C Somayajulu 			txb->m_head = NULL;
3301f10a77bbSDavid C Somayajulu 		}
3302f10a77bbSDavid C Somayajulu 	}
3303f10a77bbSDavid C Somayajulu 
3304f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_free += comp_count;
3305f10a77bbSDavid C Somayajulu 	return;
3306f10a77bbSDavid C Somayajulu }
3307f10a77bbSDavid C Somayajulu 
3308f10a77bbSDavid C Somayajulu void
3309f10a77bbSDavid C Somayajulu ql_update_link_state(qla_host_t *ha)
3310f10a77bbSDavid C Somayajulu {
3311f10a77bbSDavid C Somayajulu 	uint32_t link_state;
3312f10a77bbSDavid C Somayajulu 	uint32_t prev_link_state;
3313f10a77bbSDavid C Somayajulu 
3314f10a77bbSDavid C Somayajulu 	if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
3315f10a77bbSDavid C Somayajulu 		ha->hw.link_up = 0;
3316f10a77bbSDavid C Somayajulu 		return;
3317f10a77bbSDavid C Somayajulu 	}
3318f10a77bbSDavid C Somayajulu 	link_state = READ_REG32(ha, Q8_LINK_STATE);
3319f10a77bbSDavid C Somayajulu 
3320f10a77bbSDavid C Somayajulu 	prev_link_state =  ha->hw.link_up;
3321f10a77bbSDavid C Somayajulu 
3322f10a77bbSDavid C Somayajulu 	if (ha->pci_func == 0)
3323f10a77bbSDavid C Somayajulu 		ha->hw.link_up = (((link_state & 0xF) == 1)? 1 : 0);
3324f10a77bbSDavid C Somayajulu 	else
3325f10a77bbSDavid C Somayajulu 		ha->hw.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
3326f10a77bbSDavid C Somayajulu 
3327f10a77bbSDavid C Somayajulu 	if (prev_link_state !=  ha->hw.link_up) {
3328f10a77bbSDavid C Somayajulu 		if (ha->hw.link_up) {
3329f10a77bbSDavid C Somayajulu 			if_link_state_change(ha->ifp, LINK_STATE_UP);
3330f10a77bbSDavid C Somayajulu 		} else {
3331f10a77bbSDavid C Somayajulu 			if_link_state_change(ha->ifp, LINK_STATE_DOWN);
3332f10a77bbSDavid C Somayajulu 		}
3333f10a77bbSDavid C Somayajulu 	}
3334f10a77bbSDavid C Somayajulu 	return;
3335f10a77bbSDavid C Somayajulu }
3336f10a77bbSDavid C Somayajulu 
3337f10a77bbSDavid C Somayajulu void
3338f10a77bbSDavid C Somayajulu ql_hw_stop_rcv(qla_host_t *ha)
3339f10a77bbSDavid C Somayajulu {
3340f10a77bbSDavid C Somayajulu 	int i, done, count = 100;
3341f10a77bbSDavid C Somayajulu 
33426a62bec0SDavid C Somayajulu 	ha->flags.stop_rcv = 1;
33436a62bec0SDavid C Somayajulu 
334435291c22SDavid C Somayajulu 	while (count) {
3345f10a77bbSDavid C Somayajulu 		done = 1;
3346f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
3347f10a77bbSDavid C Somayajulu 			if (ha->hw.sds[i].rcv_active)
3348f10a77bbSDavid C Somayajulu 				done = 0;
3349f10a77bbSDavid C Somayajulu 		}
3350f10a77bbSDavid C Somayajulu 		if (done)
3351f10a77bbSDavid C Somayajulu 			break;
3352f10a77bbSDavid C Somayajulu 		else
3353f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 10);
335435291c22SDavid C Somayajulu 		count--;
3355f10a77bbSDavid C Somayajulu 	}
3356f10a77bbSDavid C Somayajulu 	if (!count)
3357f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Counter expired.\n", __func__);
3358f10a77bbSDavid C Somayajulu 
3359f10a77bbSDavid C Somayajulu 	return;
3360f10a77bbSDavid C Somayajulu }
3361f10a77bbSDavid C Somayajulu 
3362f10a77bbSDavid C Somayajulu int
3363f10a77bbSDavid C Somayajulu ql_hw_check_health(qla_host_t *ha)
3364f10a77bbSDavid C Somayajulu {
3365f10a77bbSDavid C Somayajulu 	uint32_t val;
3366f10a77bbSDavid C Somayajulu 
3367f10a77bbSDavid C Somayajulu 	ha->hw.health_count++;
3368f10a77bbSDavid C Somayajulu 
3369f10a77bbSDavid C Somayajulu 	if (ha->hw.health_count < 1000)
3370f10a77bbSDavid C Somayajulu 		return 0;
3371f10a77bbSDavid C Somayajulu 
3372f10a77bbSDavid C Somayajulu 	ha->hw.health_count = 0;
3373f10a77bbSDavid C Somayajulu 
3374f10a77bbSDavid C Somayajulu 	val = READ_REG32(ha, Q8_ASIC_TEMPERATURE);
3375f10a77bbSDavid C Somayajulu 
3376f10a77bbSDavid C Somayajulu 	if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) ||
3377f10a77bbSDavid C Somayajulu 		(QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) {
3378f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Temperature Alert [0x%08x]\n",
3379f10a77bbSDavid C Somayajulu 			__func__, val);
3380f10a77bbSDavid C Somayajulu 		return -1;
3381f10a77bbSDavid C Somayajulu 	}
3382f10a77bbSDavid C Somayajulu 
3383f10a77bbSDavid C Somayajulu 	val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
3384f10a77bbSDavid C Somayajulu 
3385f10a77bbSDavid C Somayajulu 	if ((val != ha->hw.hbeat_value) &&
3386467dcb5aSDavid C Somayajulu 		(!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) {
3387f10a77bbSDavid C Somayajulu 		ha->hw.hbeat_value = val;
3388f10a77bbSDavid C Somayajulu 		return 0;
3389f10a77bbSDavid C Somayajulu 	}
3390f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: Heartbeat Failue [0x%08x]\n",
3391f10a77bbSDavid C Somayajulu 		__func__, val);
3392f10a77bbSDavid C Somayajulu 
3393f10a77bbSDavid C Somayajulu 	return -1;
3394f10a77bbSDavid C Somayajulu }
3395f10a77bbSDavid C Somayajulu 
3396f10a77bbSDavid C Somayajulu static int
339735291c22SDavid C Somayajulu qla_init_nic_func(qla_host_t *ha)
339835291c22SDavid C Somayajulu {
339935291c22SDavid C Somayajulu         device_t                dev;
340035291c22SDavid C Somayajulu         q80_init_nic_func_t     *init_nic;
340135291c22SDavid C Somayajulu         q80_init_nic_func_rsp_t *init_nic_rsp;
340235291c22SDavid C Somayajulu         uint32_t                err;
340335291c22SDavid C Somayajulu 
340435291c22SDavid C Somayajulu         dev = ha->pci_dev;
340535291c22SDavid C Somayajulu 
340635291c22SDavid C Somayajulu         init_nic = (q80_init_nic_func_t *)ha->hw.mbox;
340735291c22SDavid C Somayajulu         bzero(init_nic, sizeof(q80_init_nic_func_t));
340835291c22SDavid C Somayajulu 
340935291c22SDavid C Somayajulu         init_nic->opcode = Q8_MBX_INIT_NIC_FUNC;
341035291c22SDavid C Somayajulu         init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2);
341135291c22SDavid C Somayajulu         init_nic->count_version |= Q8_MBX_CMD_VERSION;
341235291c22SDavid C Somayajulu 
341335291c22SDavid C Somayajulu         init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN;
341435291c22SDavid C Somayajulu         init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN;
341535291c22SDavid C Somayajulu         init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN;
341635291c22SDavid C Somayajulu 
341735291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t));
341835291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)init_nic,
341935291c22SDavid C Somayajulu                 (sizeof (q80_init_nic_func_t) >> 2),
342035291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) {
342135291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
342235291c22SDavid C Somayajulu                 return -1;
342335291c22SDavid C Somayajulu         }
342435291c22SDavid C Somayajulu 
342535291c22SDavid C Somayajulu         init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox;
342635291c22SDavid C Somayajulu // qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t));
342735291c22SDavid C Somayajulu 
342835291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status);
342935291c22SDavid C Somayajulu 
343035291c22SDavid C Somayajulu         if (err) {
343135291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
343235291c22SDavid C Somayajulu         }
343335291c22SDavid C Somayajulu 
343435291c22SDavid C Somayajulu         return 0;
343535291c22SDavid C Somayajulu }
343635291c22SDavid C Somayajulu 
343735291c22SDavid C Somayajulu static int
343835291c22SDavid C Somayajulu qla_stop_nic_func(qla_host_t *ha)
343935291c22SDavid C Somayajulu {
344035291c22SDavid C Somayajulu         device_t                dev;
344135291c22SDavid C Somayajulu         q80_stop_nic_func_t     *stop_nic;
344235291c22SDavid C Somayajulu         q80_stop_nic_func_rsp_t *stop_nic_rsp;
344335291c22SDavid C Somayajulu         uint32_t                err;
344435291c22SDavid C Somayajulu 
344535291c22SDavid C Somayajulu         dev = ha->pci_dev;
344635291c22SDavid C Somayajulu 
344735291c22SDavid C Somayajulu         stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox;
344835291c22SDavid C Somayajulu         bzero(stop_nic, sizeof(q80_stop_nic_func_t));
344935291c22SDavid C Somayajulu 
345035291c22SDavid C Somayajulu         stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC;
345135291c22SDavid C Somayajulu         stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2);
345235291c22SDavid C Somayajulu         stop_nic->count_version |= Q8_MBX_CMD_VERSION;
345335291c22SDavid C Somayajulu 
345435291c22SDavid C Somayajulu         stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN;
345535291c22SDavid C Somayajulu         stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN;
345635291c22SDavid C Somayajulu 
345735291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t));
345835291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)stop_nic,
345935291c22SDavid C Somayajulu                 (sizeof (q80_stop_nic_func_t) >> 2),
346035291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) {
346135291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
346235291c22SDavid C Somayajulu                 return -1;
346335291c22SDavid C Somayajulu         }
346435291c22SDavid C Somayajulu 
346535291c22SDavid C Somayajulu         stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox;
346635291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t));
346735291c22SDavid C Somayajulu 
346835291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status);
346935291c22SDavid C Somayajulu 
347035291c22SDavid C Somayajulu         if (err) {
347135291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
347235291c22SDavid C Somayajulu         }
347335291c22SDavid C Somayajulu 
347435291c22SDavid C Somayajulu         return 0;
347535291c22SDavid C Somayajulu }
347635291c22SDavid C Somayajulu 
347735291c22SDavid C Somayajulu static int
347835291c22SDavid C Somayajulu qla_query_fw_dcbx_caps(qla_host_t *ha)
347935291c22SDavid C Somayajulu {
348035291c22SDavid C Somayajulu         device_t                        dev;
348135291c22SDavid C Somayajulu         q80_query_fw_dcbx_caps_t        *fw_dcbx;
348235291c22SDavid C Somayajulu         q80_query_fw_dcbx_caps_rsp_t    *fw_dcbx_rsp;
348335291c22SDavid C Somayajulu         uint32_t                        err;
348435291c22SDavid C Somayajulu 
348535291c22SDavid C Somayajulu         dev = ha->pci_dev;
348635291c22SDavid C Somayajulu 
348735291c22SDavid C Somayajulu         fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox;
348835291c22SDavid C Somayajulu         bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t));
348935291c22SDavid C Somayajulu 
349035291c22SDavid C Somayajulu         fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS;
349135291c22SDavid C Somayajulu         fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2);
349235291c22SDavid C Somayajulu         fw_dcbx->count_version |= Q8_MBX_CMD_VERSION;
349335291c22SDavid C Somayajulu 
349435291c22SDavid C Somayajulu         ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t));
349535291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx,
349635291c22SDavid C Somayajulu                 (sizeof (q80_query_fw_dcbx_caps_t) >> 2),
349735291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) {
349835291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
349935291c22SDavid C Somayajulu                 return -1;
350035291c22SDavid C Somayajulu         }
350135291c22SDavid C Somayajulu 
350235291c22SDavid C Somayajulu         fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox;
350335291c22SDavid C Somayajulu         ql_dump_buf8(ha, __func__, fw_dcbx_rsp,
350435291c22SDavid C Somayajulu                 sizeof (q80_query_fw_dcbx_caps_rsp_t));
350535291c22SDavid C Somayajulu 
350635291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status);
350735291c22SDavid C Somayajulu 
350835291c22SDavid C Somayajulu         if (err) {
350935291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
351035291c22SDavid C Somayajulu         }
351135291c22SDavid C Somayajulu 
351235291c22SDavid C Somayajulu         return 0;
351335291c22SDavid C Somayajulu }
351435291c22SDavid C Somayajulu 
351535291c22SDavid C Somayajulu static int
351635291c22SDavid C Somayajulu qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2,
351735291c22SDavid C Somayajulu         uint32_t aen_mb3, uint32_t aen_mb4)
351835291c22SDavid C Somayajulu {
351935291c22SDavid C Somayajulu         device_t                dev;
352035291c22SDavid C Somayajulu         q80_idc_ack_t           *idc_ack;
352135291c22SDavid C Somayajulu         q80_idc_ack_rsp_t       *idc_ack_rsp;
352235291c22SDavid C Somayajulu         uint32_t                err;
352335291c22SDavid C Somayajulu         int                     count = 300;
352435291c22SDavid C Somayajulu 
352535291c22SDavid C Somayajulu         dev = ha->pci_dev;
352635291c22SDavid C Somayajulu 
352735291c22SDavid C Somayajulu         idc_ack = (q80_idc_ack_t *)ha->hw.mbox;
352835291c22SDavid C Somayajulu         bzero(idc_ack, sizeof(q80_idc_ack_t));
352935291c22SDavid C Somayajulu 
353035291c22SDavid C Somayajulu         idc_ack->opcode = Q8_MBX_IDC_ACK;
353135291c22SDavid C Somayajulu         idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2);
353235291c22SDavid C Somayajulu         idc_ack->count_version |= Q8_MBX_CMD_VERSION;
353335291c22SDavid C Somayajulu 
353435291c22SDavid C Somayajulu         idc_ack->aen_mb1 = aen_mb1;
353535291c22SDavid C Somayajulu         idc_ack->aen_mb2 = aen_mb2;
353635291c22SDavid C Somayajulu         idc_ack->aen_mb3 = aen_mb3;
353735291c22SDavid C Somayajulu         idc_ack->aen_mb4 = aen_mb4;
353835291c22SDavid C Somayajulu 
353935291c22SDavid C Somayajulu         ha->hw.imd_compl= 0;
354035291c22SDavid C Somayajulu 
354135291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)idc_ack,
354235291c22SDavid C Somayajulu                 (sizeof (q80_idc_ack_t) >> 2),
354335291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) {
354435291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
354535291c22SDavid C Somayajulu                 return -1;
354635291c22SDavid C Somayajulu         }
354735291c22SDavid C Somayajulu 
354835291c22SDavid C Somayajulu         idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox;
354935291c22SDavid C Somayajulu 
355035291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status);
355135291c22SDavid C Somayajulu 
355235291c22SDavid C Somayajulu         if (err) {
355335291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
355435291c22SDavid C Somayajulu                 return(-1);
355535291c22SDavid C Somayajulu         }
355635291c22SDavid C Somayajulu 
355735291c22SDavid C Somayajulu         while (count && !ha->hw.imd_compl) {
355835291c22SDavid C Somayajulu                 qla_mdelay(__func__, 100);
355935291c22SDavid C Somayajulu                 count--;
356035291c22SDavid C Somayajulu         }
356135291c22SDavid C Somayajulu 
356235291c22SDavid C Somayajulu         if (!count)
356335291c22SDavid C Somayajulu                 return -1;
356435291c22SDavid C Somayajulu         else
356535291c22SDavid C Somayajulu                 device_printf(dev, "%s: count %d\n", __func__, count);
356635291c22SDavid C Somayajulu 
356735291c22SDavid C Somayajulu         return (0);
356835291c22SDavid C Somayajulu }
356935291c22SDavid C Somayajulu 
357035291c22SDavid C Somayajulu static int
357135291c22SDavid C Somayajulu qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits)
357235291c22SDavid C Somayajulu {
357335291c22SDavid C Somayajulu         device_t                dev;
357435291c22SDavid C Somayajulu         q80_set_port_cfg_t      *pcfg;
357535291c22SDavid C Somayajulu         q80_set_port_cfg_rsp_t  *pfg_rsp;
357635291c22SDavid C Somayajulu         uint32_t                err;
357735291c22SDavid C Somayajulu         int                     count = 300;
357835291c22SDavid C Somayajulu 
357935291c22SDavid C Somayajulu         dev = ha->pci_dev;
358035291c22SDavid C Somayajulu 
358135291c22SDavid C Somayajulu         pcfg = (q80_set_port_cfg_t *)ha->hw.mbox;
358235291c22SDavid C Somayajulu         bzero(pcfg, sizeof(q80_set_port_cfg_t));
358335291c22SDavid C Somayajulu 
358435291c22SDavid C Somayajulu         pcfg->opcode = Q8_MBX_SET_PORT_CONFIG;
358535291c22SDavid C Somayajulu         pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2);
358635291c22SDavid C Somayajulu         pcfg->count_version |= Q8_MBX_CMD_VERSION;
358735291c22SDavid C Somayajulu 
358835291c22SDavid C Somayajulu         pcfg->cfg_bits = cfg_bits;
358935291c22SDavid C Somayajulu 
359035291c22SDavid C Somayajulu         device_printf(dev, "%s: cfg_bits"
359135291c22SDavid C Somayajulu                 " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
359235291c22SDavid C Somayajulu                 " [0x%x, 0x%x, 0x%x]\n", __func__,
359335291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
359435291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
359535291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0));
359635291c22SDavid C Somayajulu 
359735291c22SDavid C Somayajulu         ha->hw.imd_compl= 0;
359835291c22SDavid C Somayajulu 
359935291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
360035291c22SDavid C Somayajulu                 (sizeof (q80_set_port_cfg_t) >> 2),
360135291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) {
360235291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
360335291c22SDavid C Somayajulu                 return -1;
360435291c22SDavid C Somayajulu         }
360535291c22SDavid C Somayajulu 
360635291c22SDavid C Somayajulu         pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox;
360735291c22SDavid C Somayajulu 
360835291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status);
360935291c22SDavid C Somayajulu 
361035291c22SDavid C Somayajulu         if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) {
361135291c22SDavid C Somayajulu                 while (count && !ha->hw.imd_compl) {
361235291c22SDavid C Somayajulu                         qla_mdelay(__func__, 100);
361335291c22SDavid C Somayajulu                         count--;
361435291c22SDavid C Somayajulu                 }
361535291c22SDavid C Somayajulu                 if (count) {
361635291c22SDavid C Somayajulu                         device_printf(dev, "%s: count %d\n", __func__, count);
361735291c22SDavid C Somayajulu 
361835291c22SDavid C Somayajulu                         err = 0;
361935291c22SDavid C Somayajulu                 }
362035291c22SDavid C Somayajulu         }
362135291c22SDavid C Somayajulu 
362235291c22SDavid C Somayajulu         if (err) {
362335291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
362435291c22SDavid C Somayajulu                 return(-1);
362535291c22SDavid C Somayajulu         }
362635291c22SDavid C Somayajulu 
362735291c22SDavid C Somayajulu         return (0);
362835291c22SDavid C Somayajulu }
362935291c22SDavid C Somayajulu 
363035291c22SDavid C Somayajulu 
363135291c22SDavid C Somayajulu static int
3632f10a77bbSDavid C Somayajulu qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size)
3633f10a77bbSDavid C Somayajulu {
3634f10a77bbSDavid C Somayajulu 	uint32_t			err;
3635f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
3636f10a77bbSDavid C Somayajulu 	q80_config_md_templ_size_t	*md_size;
3637f10a77bbSDavid C Somayajulu 	q80_config_md_templ_size_rsp_t	*md_size_rsp;
3638f10a77bbSDavid C Somayajulu 
36396a62bec0SDavid C Somayajulu #ifndef QL_LDFLASH_FW
364035291c22SDavid C Somayajulu 
36416a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *hdr;
36426a62bec0SDavid C Somayajulu 
36436a62bec0SDavid C Somayajulu 	hdr = (ql_minidump_template_hdr_t *)ql83xx_minidump;
36446a62bec0SDavid C Somayajulu 	*size = hdr->size_of_template;
364535291c22SDavid C Somayajulu 	return (0);
364635291c22SDavid C Somayajulu 
364735291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
364835291c22SDavid C Somayajulu 
3649f10a77bbSDavid C Somayajulu 	md_size = (q80_config_md_templ_size_t *) ha->hw.mbox;
3650f10a77bbSDavid C Somayajulu 	bzero(md_size, sizeof(q80_config_md_templ_size_t));
3651f10a77bbSDavid C Somayajulu 
3652f10a77bbSDavid C Somayajulu 	md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE;
3653f10a77bbSDavid C Somayajulu 	md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2);
3654f10a77bbSDavid C Somayajulu 	md_size->count_version |= Q8_MBX_CMD_VERSION;
3655f10a77bbSDavid C Somayajulu 
3656f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *) md_size,
3657f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox,
3658f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) {
3659f10a77bbSDavid C Somayajulu 
3660f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
3661f10a77bbSDavid C Somayajulu 
3662f10a77bbSDavid C Somayajulu 		return (-1);
3663f10a77bbSDavid C Somayajulu 	}
3664f10a77bbSDavid C Somayajulu 
3665f10a77bbSDavid C Somayajulu 	md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox;
3666f10a77bbSDavid C Somayajulu 
3667f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status);
3668f10a77bbSDavid C Somayajulu 
3669f10a77bbSDavid C Somayajulu         if (err) {
3670f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3671f10a77bbSDavid C Somayajulu 		return(-1);
3672f10a77bbSDavid C Somayajulu         }
3673f10a77bbSDavid C Somayajulu 
3674f10a77bbSDavid C Somayajulu 	*size = md_size_rsp->templ_size;
3675f10a77bbSDavid C Somayajulu 
3676f10a77bbSDavid C Somayajulu 	return (0);
3677f10a77bbSDavid C Somayajulu }
3678f10a77bbSDavid C Somayajulu 
3679f10a77bbSDavid C Somayajulu static int
368035291c22SDavid C Somayajulu qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits)
368135291c22SDavid C Somayajulu {
368235291c22SDavid C Somayajulu         device_t                dev;
368335291c22SDavid C Somayajulu         q80_get_port_cfg_t      *pcfg;
368435291c22SDavid C Somayajulu         q80_get_port_cfg_rsp_t  *pcfg_rsp;
368535291c22SDavid C Somayajulu         uint32_t                err;
368635291c22SDavid C Somayajulu 
368735291c22SDavid C Somayajulu         dev = ha->pci_dev;
368835291c22SDavid C Somayajulu 
368935291c22SDavid C Somayajulu         pcfg = (q80_get_port_cfg_t *)ha->hw.mbox;
369035291c22SDavid C Somayajulu         bzero(pcfg, sizeof(q80_get_port_cfg_t));
369135291c22SDavid C Somayajulu 
369235291c22SDavid C Somayajulu         pcfg->opcode = Q8_MBX_GET_PORT_CONFIG;
369335291c22SDavid C Somayajulu         pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2);
369435291c22SDavid C Somayajulu         pcfg->count_version |= Q8_MBX_CMD_VERSION;
369535291c22SDavid C Somayajulu 
369635291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
369735291c22SDavid C Somayajulu                 (sizeof (q80_get_port_cfg_t) >> 2),
369835291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) {
369935291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
370035291c22SDavid C Somayajulu                 return -1;
370135291c22SDavid C Somayajulu         }
370235291c22SDavid C Somayajulu 
370335291c22SDavid C Somayajulu         pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox;
370435291c22SDavid C Somayajulu 
370535291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status);
370635291c22SDavid C Somayajulu 
370735291c22SDavid C Somayajulu         if (err) {
370835291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
370935291c22SDavid C Somayajulu                 return(-1);
371035291c22SDavid C Somayajulu         }
371135291c22SDavid C Somayajulu 
371235291c22SDavid C Somayajulu         device_printf(dev, "%s: [cfg_bits, port type]"
371335291c22SDavid C Somayajulu                 " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
371435291c22SDavid C Somayajulu                 " [0x%x, 0x%x, 0x%x]\n", __func__,
371535291c22SDavid C Somayajulu                 pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type,
371635291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
371735291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
371835291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)
371935291c22SDavid C Somayajulu                 );
372035291c22SDavid C Somayajulu 
372135291c22SDavid C Somayajulu         *cfg_bits = pcfg_rsp->cfg_bits;
372235291c22SDavid C Somayajulu 
372335291c22SDavid C Somayajulu         return (0);
372435291c22SDavid C Somayajulu }
372535291c22SDavid C Somayajulu 
372635291c22SDavid C Somayajulu int
3727b89f2279SDavid C Somayajulu ql_iscsi_pdu(qla_host_t *ha, struct mbuf *mp)
372835291c22SDavid C Somayajulu {
372935291c22SDavid C Somayajulu         struct ether_vlan_header        *eh;
373035291c22SDavid C Somayajulu         uint16_t                        etype;
373135291c22SDavid C Somayajulu         struct ip                       *ip = NULL;
373235291c22SDavid C Somayajulu         struct ip6_hdr                  *ip6 = NULL;
373335291c22SDavid C Somayajulu         struct tcphdr                   *th = NULL;
373435291c22SDavid C Somayajulu         uint32_t                        hdrlen;
373535291c22SDavid C Somayajulu         uint32_t                        offset;
373635291c22SDavid C Somayajulu         uint8_t                         buf[sizeof(struct ip6_hdr)];
373735291c22SDavid C Somayajulu 
373835291c22SDavid C Somayajulu         eh = mtod(mp, struct ether_vlan_header *);
373935291c22SDavid C Somayajulu 
374035291c22SDavid C Somayajulu         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
374135291c22SDavid C Somayajulu                 hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
374235291c22SDavid C Somayajulu                 etype = ntohs(eh->evl_proto);
374335291c22SDavid C Somayajulu         } else {
374435291c22SDavid C Somayajulu                 hdrlen = ETHER_HDR_LEN;
374535291c22SDavid C Somayajulu                 etype = ntohs(eh->evl_encap_proto);
374635291c22SDavid C Somayajulu         }
374735291c22SDavid C Somayajulu 
374835291c22SDavid C Somayajulu 	if (etype == ETHERTYPE_IP) {
374935291c22SDavid C Somayajulu 
375035291c22SDavid C Somayajulu 		offset = (hdrlen + sizeof (struct ip));
375135291c22SDavid C Somayajulu 
375235291c22SDavid C Somayajulu 		if (mp->m_len >= offset) {
375335291c22SDavid C Somayajulu                         ip = (struct ip *)(mp->m_data + hdrlen);
375435291c22SDavid C Somayajulu 		} else {
375535291c22SDavid C Somayajulu 			m_copydata(mp, hdrlen, sizeof (struct ip), buf);
375635291c22SDavid C Somayajulu                         ip = (struct ip *)buf;
375735291c22SDavid C Somayajulu 		}
375835291c22SDavid C Somayajulu 
375935291c22SDavid C Somayajulu                 if (ip->ip_p == IPPROTO_TCP) {
376035291c22SDavid C Somayajulu 
376135291c22SDavid C Somayajulu 			hdrlen += ip->ip_hl << 2;
376235291c22SDavid C Somayajulu 			offset = hdrlen + 4;
376335291c22SDavid C Somayajulu 
376435291c22SDavid C Somayajulu 			if (mp->m_len >= offset) {
37656a62bec0SDavid C Somayajulu 				th = (struct tcphdr *)(mp->m_data + hdrlen);;
376635291c22SDavid C Somayajulu 			} else {
376735291c22SDavid C Somayajulu                                 m_copydata(mp, hdrlen, 4, buf);
376835291c22SDavid C Somayajulu 				th = (struct tcphdr *)buf;
376935291c22SDavid C Somayajulu 			}
377035291c22SDavid C Somayajulu                 }
377135291c22SDavid C Somayajulu 
377235291c22SDavid C Somayajulu 	} else if (etype == ETHERTYPE_IPV6) {
377335291c22SDavid C Somayajulu 
377435291c22SDavid C Somayajulu 		offset = (hdrlen + sizeof (struct ip6_hdr));
377535291c22SDavid C Somayajulu 
377635291c22SDavid C Somayajulu 		if (mp->m_len >= offset) {
377735291c22SDavid C Somayajulu                         ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen);
377835291c22SDavid C Somayajulu 		} else {
377935291c22SDavid C Somayajulu                         m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf);
378035291c22SDavid C Somayajulu                         ip6 = (struct ip6_hdr *)buf;
378135291c22SDavid C Somayajulu 		}
378235291c22SDavid C Somayajulu 
378335291c22SDavid C Somayajulu                 if (ip6->ip6_nxt == IPPROTO_TCP) {
378435291c22SDavid C Somayajulu 
378535291c22SDavid C Somayajulu 			hdrlen += sizeof(struct ip6_hdr);
378635291c22SDavid C Somayajulu 			offset = hdrlen + 4;
378735291c22SDavid C Somayajulu 
378835291c22SDavid C Somayajulu 			if (mp->m_len >= offset) {
37896a62bec0SDavid C Somayajulu 				th = (struct tcphdr *)(mp->m_data + hdrlen);;
379035291c22SDavid C Somayajulu 			} else {
379135291c22SDavid C Somayajulu 				m_copydata(mp, hdrlen, 4, buf);
379235291c22SDavid C Somayajulu 				th = (struct tcphdr *)buf;
379335291c22SDavid C Somayajulu 			}
379435291c22SDavid C Somayajulu                 }
379535291c22SDavid C Somayajulu 	}
379635291c22SDavid C Somayajulu 
379735291c22SDavid C Somayajulu         if (th != NULL) {
379835291c22SDavid C Somayajulu                 if ((th->th_sport == htons(3260)) ||
379935291c22SDavid C Somayajulu                         (th->th_dport == htons(3260)))
380035291c22SDavid C Somayajulu                         return 0;
380135291c22SDavid C Somayajulu         }
380235291c22SDavid C Somayajulu         return (-1);
380335291c22SDavid C Somayajulu }
380435291c22SDavid C Somayajulu 
380535291c22SDavid C Somayajulu void
380635291c22SDavid C Somayajulu qla_hw_async_event(qla_host_t *ha)
380735291c22SDavid C Somayajulu {
380835291c22SDavid C Somayajulu         switch (ha->hw.aen_mb0) {
380935291c22SDavid C Somayajulu         case 0x8101:
381035291c22SDavid C Somayajulu                 (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2,
381135291c22SDavid C Somayajulu                         ha->hw.aen_mb3, ha->hw.aen_mb4);
381235291c22SDavid C Somayajulu 
381335291c22SDavid C Somayajulu                 break;
381435291c22SDavid C Somayajulu 
381535291c22SDavid C Somayajulu         default:
381635291c22SDavid C Somayajulu                 break;
381735291c22SDavid C Somayajulu         }
381835291c22SDavid C Somayajulu 
381935291c22SDavid C Somayajulu         return;
382035291c22SDavid C Somayajulu }
382135291c22SDavid C Somayajulu 
382235291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
382335291c22SDavid C Somayajulu static int
38246a62bec0SDavid C Somayajulu ql_get_minidump_template(qla_host_t *ha)
3825f10a77bbSDavid C Somayajulu {
3826f10a77bbSDavid C Somayajulu 	uint32_t			err;
3827f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
3828f10a77bbSDavid C Somayajulu 	q80_config_md_templ_cmd_t	*md_templ;
3829f10a77bbSDavid C Somayajulu 	q80_config_md_templ_cmd_rsp_t	*md_templ_rsp;
3830f10a77bbSDavid C Somayajulu 
3831f10a77bbSDavid C Somayajulu 	md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox;
3832f10a77bbSDavid C Somayajulu 	bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t)));
3833f10a77bbSDavid C Somayajulu 
3834f10a77bbSDavid C Somayajulu 	md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT;
3835f10a77bbSDavid C Somayajulu 	md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2);
3836f10a77bbSDavid C Somayajulu 	md_templ->count_version |= Q8_MBX_CMD_VERSION;
3837f10a77bbSDavid C Somayajulu 
3838f10a77bbSDavid C Somayajulu 	md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr;
3839f10a77bbSDavid C Somayajulu 	md_templ->buff_size = ha->hw.dma_buf.minidump.size;
3840f10a77bbSDavid C Somayajulu 
3841f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *) md_templ,
3842f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_cmd_t) >> 2),
3843f10a77bbSDavid C Somayajulu 		 ha->hw.mbox,
3844f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) {
3845f10a77bbSDavid C Somayajulu 
3846f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
3847f10a77bbSDavid C Somayajulu 
3848f10a77bbSDavid C Somayajulu 		return (-1);
3849f10a77bbSDavid C Somayajulu 	}
3850f10a77bbSDavid C Somayajulu 
3851f10a77bbSDavid C Somayajulu 	md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox;
3852f10a77bbSDavid C Somayajulu 
3853f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status);
3854f10a77bbSDavid C Somayajulu 
3855f10a77bbSDavid C Somayajulu 	if (err) {
3856f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3857f10a77bbSDavid C Somayajulu 		return (-1);
3858f10a77bbSDavid C Somayajulu 	}
3859f10a77bbSDavid C Somayajulu 
3860f10a77bbSDavid C Somayajulu 	return (0);
3861f10a77bbSDavid C Somayajulu 
3862f10a77bbSDavid C Somayajulu }
386335291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
3864f10a77bbSDavid C Somayajulu 
38656a62bec0SDavid C Somayajulu /*
38666a62bec0SDavid C Somayajulu  * Minidump related functionality
38676a62bec0SDavid C Somayajulu  */
38686a62bec0SDavid C Somayajulu 
38696a62bec0SDavid C Somayajulu static int ql_parse_template(qla_host_t *ha);
38706a62bec0SDavid C Somayajulu 
38716a62bec0SDavid C Somayajulu static uint32_t ql_rdcrb(qla_host_t *ha,
38726a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdcrb_t *crb_entry,
38736a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
38746a62bec0SDavid C Somayajulu 
38756a62bec0SDavid C Somayajulu static uint32_t ql_pollrd(qla_host_t *ha,
38766a62bec0SDavid C Somayajulu 			ql_minidump_entry_pollrd_t *entry,
38776a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
38786a62bec0SDavid C Somayajulu 
38796a62bec0SDavid C Somayajulu static uint32_t ql_pollrd_modify_write(qla_host_t *ha,
38806a62bec0SDavid C Somayajulu 			ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
38816a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38826a62bec0SDavid C Somayajulu 
38836a62bec0SDavid C Somayajulu static uint32_t ql_L2Cache(qla_host_t *ha,
38846a62bec0SDavid C Somayajulu 			ql_minidump_entry_cache_t *cacheEntry,
38856a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
38866a62bec0SDavid C Somayajulu 
38876a62bec0SDavid C Somayajulu static uint32_t ql_L1Cache(qla_host_t *ha,
38886a62bec0SDavid C Somayajulu 			ql_minidump_entry_cache_t *cacheEntry,
38896a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38906a62bec0SDavid C Somayajulu 
38916a62bec0SDavid C Somayajulu static uint32_t ql_rdocm(qla_host_t *ha,
38926a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdocm_t *ocmEntry,
38936a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38946a62bec0SDavid C Somayajulu 
38956a62bec0SDavid C Somayajulu static uint32_t ql_rdmem(qla_host_t *ha,
38966a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdmem_t *mem_entry,
38976a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
38986a62bec0SDavid C Somayajulu 
38996a62bec0SDavid C Somayajulu static uint32_t ql_rdrom(qla_host_t *ha,
39006a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdrom_t *romEntry,
39016a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
39026a62bec0SDavid C Somayajulu 
39036a62bec0SDavid C Somayajulu static uint32_t ql_rdmux(qla_host_t *ha,
39046a62bec0SDavid C Somayajulu 			ql_minidump_entry_mux_t *muxEntry,
39056a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
39066a62bec0SDavid C Somayajulu 
39076a62bec0SDavid C Somayajulu static uint32_t ql_rdmux2(qla_host_t *ha,
39086a62bec0SDavid C Somayajulu 			ql_minidump_entry_mux2_t *muxEntry,
39096a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
39106a62bec0SDavid C Somayajulu 
39116a62bec0SDavid C Somayajulu static uint32_t ql_rdqueue(qla_host_t *ha,
39126a62bec0SDavid C Somayajulu 			ql_minidump_entry_queue_t *queueEntry,
39136a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
39146a62bec0SDavid C Somayajulu 
39156a62bec0SDavid C Somayajulu static uint32_t ql_cntrl(qla_host_t *ha,
39166a62bec0SDavid C Somayajulu 			ql_minidump_template_hdr_t *template_hdr,
39176a62bec0SDavid C Somayajulu 			ql_minidump_entry_cntrl_t *crbEntry);
39186a62bec0SDavid C Somayajulu 
39196a62bec0SDavid C Somayajulu 
39206a62bec0SDavid C Somayajulu static uint32_t
39216a62bec0SDavid C Somayajulu ql_minidump_size(qla_host_t *ha)
39226a62bec0SDavid C Somayajulu {
39236a62bec0SDavid C Somayajulu 	uint32_t i, k;
39246a62bec0SDavid C Somayajulu 	uint32_t size = 0;
39256a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *hdr;
39266a62bec0SDavid C Somayajulu 
39276a62bec0SDavid C Somayajulu 	hdr = (ql_minidump_template_hdr_t *)ha->hw.dma_buf.minidump.dma_b;
39286a62bec0SDavid C Somayajulu 
39296a62bec0SDavid C Somayajulu 	i = 0x2;
39306a62bec0SDavid C Somayajulu 
39316a62bec0SDavid C Somayajulu 	for (k = 1; k < QL_DBG_CAP_SIZE_ARRAY_LEN; k++) {
39326a62bec0SDavid C Somayajulu 		if (i & ha->hw.mdump_capture_mask)
39336a62bec0SDavid C Somayajulu 			size += hdr->capture_size_array[k];
39346a62bec0SDavid C Somayajulu 		i = i << 1;
39356a62bec0SDavid C Somayajulu 	}
39366a62bec0SDavid C Somayajulu 	return (size);
39376a62bec0SDavid C Somayajulu }
39386a62bec0SDavid C Somayajulu 
39396a62bec0SDavid C Somayajulu static void
39406a62bec0SDavid C Somayajulu ql_free_minidump_buffer(qla_host_t *ha)
39416a62bec0SDavid C Somayajulu {
39426a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_buffer != NULL) {
39436a62bec0SDavid C Somayajulu 		free(ha->hw.mdump_buffer, M_QLA83XXBUF);
39446a62bec0SDavid C Somayajulu 		ha->hw.mdump_buffer = NULL;
39456a62bec0SDavid C Somayajulu 		ha->hw.mdump_buffer_size = 0;
39466a62bec0SDavid C Somayajulu 	}
39476a62bec0SDavid C Somayajulu 	return;
39486a62bec0SDavid C Somayajulu }
39496a62bec0SDavid C Somayajulu 
3950f10a77bbSDavid C Somayajulu static int
39516a62bec0SDavid C Somayajulu ql_alloc_minidump_buffer(qla_host_t *ha)
39526a62bec0SDavid C Somayajulu {
39536a62bec0SDavid C Somayajulu 	ha->hw.mdump_buffer_size = ql_minidump_size(ha);
39546a62bec0SDavid C Somayajulu 
39556a62bec0SDavid C Somayajulu 	if (!ha->hw.mdump_buffer_size)
39566a62bec0SDavid C Somayajulu 		return (-1);
39576a62bec0SDavid C Somayajulu 
39586a62bec0SDavid C Somayajulu 	ha->hw.mdump_buffer = malloc(ha->hw.mdump_buffer_size, M_QLA83XXBUF,
39596a62bec0SDavid C Somayajulu 					M_NOWAIT);
39606a62bec0SDavid C Somayajulu 
39616a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_buffer == NULL)
39626a62bec0SDavid C Somayajulu 		return (-1);
39636a62bec0SDavid C Somayajulu 
39646a62bec0SDavid C Somayajulu 	return (0);
39656a62bec0SDavid C Somayajulu }
39666a62bec0SDavid C Somayajulu 
39676a62bec0SDavid C Somayajulu static void
39686a62bec0SDavid C Somayajulu ql_free_minidump_template_buffer(qla_host_t *ha)
39696a62bec0SDavid C Somayajulu {
39706a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_template != NULL) {
39716a62bec0SDavid C Somayajulu 		free(ha->hw.mdump_template, M_QLA83XXBUF);
39726a62bec0SDavid C Somayajulu 		ha->hw.mdump_template = NULL;
39736a62bec0SDavid C Somayajulu 		ha->hw.mdump_template_size = 0;
39746a62bec0SDavid C Somayajulu 	}
39756a62bec0SDavid C Somayajulu 	return;
39766a62bec0SDavid C Somayajulu }
39776a62bec0SDavid C Somayajulu 
39786a62bec0SDavid C Somayajulu static int
39796a62bec0SDavid C Somayajulu ql_alloc_minidump_template_buffer(qla_host_t *ha)
39806a62bec0SDavid C Somayajulu {
39816a62bec0SDavid C Somayajulu 	ha->hw.mdump_template_size = ha->hw.dma_buf.minidump.size;
39826a62bec0SDavid C Somayajulu 
39836a62bec0SDavid C Somayajulu 	ha->hw.mdump_template = malloc(ha->hw.mdump_template_size,
39846a62bec0SDavid C Somayajulu 					M_QLA83XXBUF, M_NOWAIT);
39856a62bec0SDavid C Somayajulu 
39866a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_template == NULL)
39876a62bec0SDavid C Somayajulu 		return (-1);
39886a62bec0SDavid C Somayajulu 
39896a62bec0SDavid C Somayajulu 	return (0);
39906a62bec0SDavid C Somayajulu }
39916a62bec0SDavid C Somayajulu 
39926a62bec0SDavid C Somayajulu static int
39936a62bec0SDavid C Somayajulu ql_alloc_minidump_buffers(qla_host_t *ha)
39946a62bec0SDavid C Somayajulu {
39956a62bec0SDavid C Somayajulu 	int ret;
39966a62bec0SDavid C Somayajulu 
39976a62bec0SDavid C Somayajulu 	ret = ql_alloc_minidump_template_buffer(ha);
39986a62bec0SDavid C Somayajulu 
39996a62bec0SDavid C Somayajulu 	if (ret)
40006a62bec0SDavid C Somayajulu 		return (ret);
40016a62bec0SDavid C Somayajulu 
40026a62bec0SDavid C Somayajulu 	ret = ql_alloc_minidump_buffer(ha);
40036a62bec0SDavid C Somayajulu 
40046a62bec0SDavid C Somayajulu 	if (ret)
40056a62bec0SDavid C Somayajulu 		ql_free_minidump_template_buffer(ha);
40066a62bec0SDavid C Somayajulu 
40076a62bec0SDavid C Somayajulu 	return (ret);
40086a62bec0SDavid C Somayajulu }
40096a62bec0SDavid C Somayajulu 
40106a62bec0SDavid C Somayajulu 
40116a62bec0SDavid C Somayajulu static uint32_t
40126a62bec0SDavid C Somayajulu ql_validate_minidump_checksum(qla_host_t *ha)
40136a62bec0SDavid C Somayajulu {
40146a62bec0SDavid C Somayajulu         uint64_t sum = 0;
40156a62bec0SDavid C Somayajulu 	int count;
40166a62bec0SDavid C Somayajulu 	uint32_t *template_buff;
40176a62bec0SDavid C Somayajulu 
40186a62bec0SDavid C Somayajulu 	count = ha->hw.dma_buf.minidump.size / sizeof (uint32_t);
40196a62bec0SDavid C Somayajulu 	template_buff = ha->hw.dma_buf.minidump.dma_b;
40206a62bec0SDavid C Somayajulu 
40216a62bec0SDavid C Somayajulu 	while (count-- > 0) {
40226a62bec0SDavid C Somayajulu 		sum += *template_buff++;
40236a62bec0SDavid C Somayajulu 	}
40246a62bec0SDavid C Somayajulu 
40256a62bec0SDavid C Somayajulu 	while (sum >> 32) {
40266a62bec0SDavid C Somayajulu 		sum = (sum & 0xFFFFFFFF) + (sum >> 32);
40276a62bec0SDavid C Somayajulu 	}
40286a62bec0SDavid C Somayajulu 
40296a62bec0SDavid C Somayajulu 	return (~sum);
40306a62bec0SDavid C Somayajulu }
40316a62bec0SDavid C Somayajulu 
40326a62bec0SDavid C Somayajulu int
40336a62bec0SDavid C Somayajulu ql_minidump_init(qla_host_t *ha)
4034f10a77bbSDavid C Somayajulu {
403535291c22SDavid C Somayajulu 	int		ret = 0;
4036f10a77bbSDavid C Somayajulu 	uint32_t	template_size = 0;
4037f10a77bbSDavid C Somayajulu 	device_t	dev = ha->pci_dev;
4038f10a77bbSDavid C Somayajulu 
4039f10a77bbSDavid C Somayajulu 	/*
4040f10a77bbSDavid C Somayajulu 	 * Get Minidump Template Size
4041f10a77bbSDavid C Somayajulu  	 */
4042f10a77bbSDavid C Somayajulu 	ret = qla_get_minidump_tmplt_size(ha, &template_size);
4043f10a77bbSDavid C Somayajulu 
4044f10a77bbSDavid C Somayajulu 	if (ret || (template_size == 0)) {
4045f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret,
4046f10a77bbSDavid C Somayajulu 			template_size);
4047f10a77bbSDavid C Somayajulu 		return (-1);
4048f10a77bbSDavid C Somayajulu 	}
4049f10a77bbSDavid C Somayajulu 
4050f10a77bbSDavid C Somayajulu 	/*
4051f10a77bbSDavid C Somayajulu 	 * Allocate Memory for Minidump Template
4052f10a77bbSDavid C Somayajulu 	 */
4053f10a77bbSDavid C Somayajulu 
4054f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.minidump.alignment = 8;
4055f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.minidump.size = template_size;
4056f10a77bbSDavid C Somayajulu 
405735291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
4058f10a77bbSDavid C Somayajulu 	if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) {
4059f10a77bbSDavid C Somayajulu 
4060f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: minidump dma alloc failed\n", __func__);
4061f10a77bbSDavid C Somayajulu 
4062f10a77bbSDavid C Somayajulu 		return (-1);
4063f10a77bbSDavid C Somayajulu 	}
4064f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.flags.minidump = 1;
4065f10a77bbSDavid C Somayajulu 
4066f10a77bbSDavid C Somayajulu 	/*
4067f10a77bbSDavid C Somayajulu 	 * Retrieve Minidump Template
4068f10a77bbSDavid C Somayajulu 	 */
40696a62bec0SDavid C Somayajulu 	ret = ql_get_minidump_template(ha);
407035291c22SDavid C Somayajulu #else
407135291c22SDavid C Somayajulu 	ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump;
40726a62bec0SDavid C Somayajulu 
407335291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
4074f10a77bbSDavid C Somayajulu 
40756a62bec0SDavid C Somayajulu 	if (ret == 0) {
40766a62bec0SDavid C Somayajulu 
40776a62bec0SDavid C Somayajulu 		ret = ql_validate_minidump_checksum(ha);
40786a62bec0SDavid C Somayajulu 
40796a62bec0SDavid C Somayajulu 		if (ret == 0) {
40806a62bec0SDavid C Somayajulu 
40816a62bec0SDavid C Somayajulu 			ret = ql_alloc_minidump_buffers(ha);
40826a62bec0SDavid C Somayajulu 
40836a62bec0SDavid C Somayajulu 			if (ret == 0)
4084f10a77bbSDavid C Somayajulu 		ha->hw.mdump_init = 1;
40856a62bec0SDavid C Somayajulu 			else
40866a62bec0SDavid C Somayajulu 				device_printf(dev,
40876a62bec0SDavid C Somayajulu 					"%s: ql_alloc_minidump_buffers"
40886a62bec0SDavid C Somayajulu 					" failed\n", __func__);
40896a62bec0SDavid C Somayajulu 		} else {
40906a62bec0SDavid C Somayajulu 			device_printf(dev, "%s: ql_validate_minidump_checksum"
40916a62bec0SDavid C Somayajulu 				" failed\n", __func__);
4092f10a77bbSDavid C Somayajulu 		}
40936a62bec0SDavid C Somayajulu 	} else {
40946a62bec0SDavid C Somayajulu 		device_printf(dev, "%s: ql_get_minidump_template failed\n",
40956a62bec0SDavid C Somayajulu 			 __func__);
40966a62bec0SDavid C Somayajulu 	}
40976a62bec0SDavid C Somayajulu 
40986a62bec0SDavid C Somayajulu 	if (ret)
40996a62bec0SDavid C Somayajulu 		ql_minidump_free(ha);
4100f10a77bbSDavid C Somayajulu 
4101f10a77bbSDavid C Somayajulu 	return (ret);
4102f10a77bbSDavid C Somayajulu }
4103f10a77bbSDavid C Somayajulu 
4104f10a77bbSDavid C Somayajulu static void
41056a62bec0SDavid C Somayajulu ql_minidump_free(qla_host_t *ha)
4106f10a77bbSDavid C Somayajulu {
4107f10a77bbSDavid C Somayajulu 	ha->hw.mdump_init = 0;
4108f10a77bbSDavid C Somayajulu 	if (ha->hw.dma_buf.flags.minidump) {
4109f10a77bbSDavid C Somayajulu 		ha->hw.dma_buf.flags.minidump = 0;
4110f10a77bbSDavid C Somayajulu 		ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump);
4111f10a77bbSDavid C Somayajulu 	}
41126a62bec0SDavid C Somayajulu 
41136a62bec0SDavid C Somayajulu 	ql_free_minidump_template_buffer(ha);
41146a62bec0SDavid C Somayajulu 	ql_free_minidump_buffer(ha);
41156a62bec0SDavid C Somayajulu 
4116f10a77bbSDavid C Somayajulu 	return;
4117f10a77bbSDavid C Somayajulu }
4118f10a77bbSDavid C Somayajulu 
4119f10a77bbSDavid C Somayajulu void
4120f10a77bbSDavid C Somayajulu ql_minidump(qla_host_t *ha)
4121f10a77bbSDavid C Somayajulu {
4122f10a77bbSDavid C Somayajulu 	if (!ha->hw.mdump_init)
4123f10a77bbSDavid C Somayajulu 		return;
4124f10a77bbSDavid C Somayajulu 
41256a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_done)
4126f10a77bbSDavid C Somayajulu 		return;
4127f10a77bbSDavid C Somayajulu 
4128f10a77bbSDavid C Somayajulu 		ha->hw.mdump_start_seq_index = ql_stop_sequence(ha);
4129f10a77bbSDavid C Somayajulu 
41306a62bec0SDavid C Somayajulu 	bzero(ha->hw.mdump_buffer, ha->hw.mdump_buffer_size);
41316a62bec0SDavid C Somayajulu 	bzero(ha->hw.mdump_template, ha->hw.mdump_template_size);
41326a62bec0SDavid C Somayajulu 
41336a62bec0SDavid C Somayajulu 	bcopy(ha->hw.dma_buf.minidump.dma_b, ha->hw.mdump_template,
41346a62bec0SDavid C Somayajulu 		ha->hw.mdump_template_size);
41356a62bec0SDavid C Somayajulu 
41366a62bec0SDavid C Somayajulu 	ql_parse_template(ha);
41376a62bec0SDavid C Somayajulu 
4138f10a77bbSDavid C Somayajulu 	ql_start_sequence(ha, ha->hw.mdump_start_seq_index);
4139f10a77bbSDavid C Somayajulu 
41406a62bec0SDavid C Somayajulu 	ha->hw.mdump_done = 1;
41416a62bec0SDavid C Somayajulu 
4142f10a77bbSDavid C Somayajulu 	return;
4143f10a77bbSDavid C Somayajulu }
41446a62bec0SDavid C Somayajulu 
41456a62bec0SDavid C Somayajulu 
41466a62bec0SDavid C Somayajulu /*
41476a62bec0SDavid C Somayajulu  * helper routines
41486a62bec0SDavid C Somayajulu  */
41496a62bec0SDavid C Somayajulu static void
41506a62bec0SDavid C Somayajulu ql_entry_err_chk(ql_minidump_entry_t *entry, uint32_t esize)
41516a62bec0SDavid C Somayajulu {
41526a62bec0SDavid C Somayajulu 	if (esize != entry->hdr.entry_capture_size) {
41536a62bec0SDavid C Somayajulu 		entry->hdr.entry_capture_size = esize;
41546a62bec0SDavid C Somayajulu 		entry->hdr.driver_flags |= QL_DBG_SIZE_ERR_FLAG;
41556a62bec0SDavid C Somayajulu 	}
41566a62bec0SDavid C Somayajulu 	return;
41576a62bec0SDavid C Somayajulu }
41586a62bec0SDavid C Somayajulu 
41596a62bec0SDavid C Somayajulu 
41606a62bec0SDavid C Somayajulu static int
41616a62bec0SDavid C Somayajulu ql_parse_template(qla_host_t *ha)
41626a62bec0SDavid C Somayajulu {
41636a62bec0SDavid C Somayajulu 	uint32_t num_of_entries, buff_level, e_cnt, esize;
41646a62bec0SDavid C Somayajulu 	uint32_t end_cnt, rv = 0;
41656a62bec0SDavid C Somayajulu 	char *dump_buff, *dbuff;
41666a62bec0SDavid C Somayajulu 	int sane_start = 0, sane_end = 0;
41676a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *template_hdr;
41686a62bec0SDavid C Somayajulu 	ql_minidump_entry_t *entry;
41696a62bec0SDavid C Somayajulu 	uint32_t capture_mask;
41706a62bec0SDavid C Somayajulu 	uint32_t dump_size;
41716a62bec0SDavid C Somayajulu 
41726a62bec0SDavid C Somayajulu 	/* Setup parameters */
41736a62bec0SDavid C Somayajulu 	template_hdr = (ql_minidump_template_hdr_t *)ha->hw.mdump_template;
41746a62bec0SDavid C Somayajulu 
41756a62bec0SDavid C Somayajulu 	if (template_hdr->entry_type == TLHDR)
41766a62bec0SDavid C Somayajulu 		sane_start = 1;
41776a62bec0SDavid C Somayajulu 
41786a62bec0SDavid C Somayajulu 	dump_buff = (char *) ha->hw.mdump_buffer;
41796a62bec0SDavid C Somayajulu 
41806a62bec0SDavid C Somayajulu 	num_of_entries = template_hdr->num_of_entries;
41816a62bec0SDavid C Somayajulu 
41826a62bec0SDavid C Somayajulu 	entry = (ql_minidump_entry_t *) ((char *)template_hdr
41836a62bec0SDavid C Somayajulu 			+ template_hdr->first_entry_offset );
41846a62bec0SDavid C Somayajulu 
41856a62bec0SDavid C Somayajulu 	template_hdr->saved_state_array[QL_OCM0_ADDR_INDX] =
41866a62bec0SDavid C Somayajulu 		template_hdr->ocm_window_array[ha->pci_func];
41876a62bec0SDavid C Somayajulu 	template_hdr->saved_state_array[QL_PCIE_FUNC_INDX] = ha->pci_func;
41886a62bec0SDavid C Somayajulu 
41896a62bec0SDavid C Somayajulu 	capture_mask = ha->hw.mdump_capture_mask;
41906a62bec0SDavid C Somayajulu 	dump_size = ha->hw.mdump_buffer_size;
41916a62bec0SDavid C Somayajulu 
41926a62bec0SDavid C Somayajulu 	template_hdr->driver_capture_mask = capture_mask;
41936a62bec0SDavid C Somayajulu 
41946a62bec0SDavid C Somayajulu 	QL_DPRINT80(ha, (ha->pci_dev,
41956a62bec0SDavid C Somayajulu 		"%s: sane_start = %d num_of_entries = %d "
41966a62bec0SDavid C Somayajulu 		"capture_mask = 0x%x dump_size = %d \n",
41976a62bec0SDavid C Somayajulu 		__func__, sane_start, num_of_entries, capture_mask, dump_size));
41986a62bec0SDavid C Somayajulu 
41996a62bec0SDavid C Somayajulu 	for (buff_level = 0, e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
42006a62bec0SDavid C Somayajulu 
42016a62bec0SDavid C Somayajulu 		/*
42026a62bec0SDavid C Somayajulu 		 * If the capture_mask of the entry does not match capture mask
42036a62bec0SDavid C Somayajulu 		 * skip the entry after marking the driver_flags indicator.
42046a62bec0SDavid C Somayajulu 		 */
42056a62bec0SDavid C Somayajulu 
42066a62bec0SDavid C Somayajulu 		if (!(entry->hdr.entry_capture_mask & capture_mask)) {
42076a62bec0SDavid C Somayajulu 
42086a62bec0SDavid C Somayajulu 			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
42096a62bec0SDavid C Somayajulu 			entry = (ql_minidump_entry_t *) ((char *) entry
42106a62bec0SDavid C Somayajulu 					+ entry->hdr.entry_size);
42116a62bec0SDavid C Somayajulu 			continue;
42126a62bec0SDavid C Somayajulu 		}
42136a62bec0SDavid C Somayajulu 
42146a62bec0SDavid C Somayajulu 		/*
42156a62bec0SDavid C Somayajulu 		 * This is ONLY needed in implementations where
42166a62bec0SDavid C Somayajulu 		 * the capture buffer allocated is too small to capture
42176a62bec0SDavid C Somayajulu 		 * all of the required entries for a given capture mask.
42186a62bec0SDavid C Somayajulu 		 * We need to empty the buffer contents to a file
42196a62bec0SDavid C Somayajulu 		 * if possible, before processing the next entry
42206a62bec0SDavid C Somayajulu 		 * If the buff_full_flag is set, no further capture will happen
42216a62bec0SDavid C Somayajulu 		 * and all remaining non-control entries will be skipped.
42226a62bec0SDavid C Somayajulu 		 */
42236a62bec0SDavid C Somayajulu 		if (entry->hdr.entry_capture_size != 0) {
42246a62bec0SDavid C Somayajulu 			if ((buff_level + entry->hdr.entry_capture_size) >
42256a62bec0SDavid C Somayajulu 				dump_size) {
42266a62bec0SDavid C Somayajulu 				/*  Try to recover by emptying buffer to file */
42276a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
42286a62bec0SDavid C Somayajulu 				entry = (ql_minidump_entry_t *) ((char *) entry
42296a62bec0SDavid C Somayajulu 						+ entry->hdr.entry_size);
42306a62bec0SDavid C Somayajulu 				continue;
42316a62bec0SDavid C Somayajulu 			}
42326a62bec0SDavid C Somayajulu 		}
42336a62bec0SDavid C Somayajulu 
42346a62bec0SDavid C Somayajulu 		/*
42356a62bec0SDavid C Somayajulu 		 * Decode the entry type and process it accordingly
42366a62bec0SDavid C Somayajulu 		 */
42376a62bec0SDavid C Somayajulu 
42386a62bec0SDavid C Somayajulu 		switch (entry->hdr.entry_type) {
42396a62bec0SDavid C Somayajulu 		case RDNOP:
42406a62bec0SDavid C Somayajulu 			break;
42416a62bec0SDavid C Somayajulu 
42426a62bec0SDavid C Somayajulu 		case RDEND:
42436a62bec0SDavid C Somayajulu 			if (sane_end == 0) {
42446a62bec0SDavid C Somayajulu 				end_cnt = e_cnt;
42456a62bec0SDavid C Somayajulu 			}
42466a62bec0SDavid C Somayajulu 			sane_end++;
42476a62bec0SDavid C Somayajulu 			break;
42486a62bec0SDavid C Somayajulu 
42496a62bec0SDavid C Somayajulu 		case RDCRB:
42506a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
42516a62bec0SDavid C Somayajulu 			esize = ql_rdcrb(ha, (void *)entry, (void *)dbuff);
42526a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
42536a62bec0SDavid C Somayajulu 			buff_level += esize;
42546a62bec0SDavid C Somayajulu 			break;
42556a62bec0SDavid C Somayajulu 
42566a62bec0SDavid C Somayajulu                 case POLLRD:
42576a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
42586a62bec0SDavid C Somayajulu                         esize = ql_pollrd(ha, (void *)entry, (void *)dbuff);
42596a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
42606a62bec0SDavid C Somayajulu                         buff_level += esize;
42616a62bec0SDavid C Somayajulu                         break;
42626a62bec0SDavid C Somayajulu 
42636a62bec0SDavid C Somayajulu                 case POLLRDMWR:
42646a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
42656a62bec0SDavid C Somayajulu                         esize = ql_pollrd_modify_write(ha, (void *)entry,
42666a62bec0SDavid C Somayajulu 					(void *)dbuff);
42676a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
42686a62bec0SDavid C Somayajulu                         buff_level += esize;
42696a62bec0SDavid C Somayajulu                         break;
42706a62bec0SDavid C Somayajulu 
42716a62bec0SDavid C Somayajulu 		case L2ITG:
42726a62bec0SDavid C Somayajulu 		case L2DTG:
42736a62bec0SDavid C Somayajulu 		case L2DAT:
42746a62bec0SDavid C Somayajulu 		case L2INS:
42756a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
42766a62bec0SDavid C Somayajulu 			esize = ql_L2Cache(ha, (void *)entry, (void *)dbuff);
42776a62bec0SDavid C Somayajulu 			if (esize == -1) {
42786a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
42796a62bec0SDavid C Somayajulu 			} else {
42806a62bec0SDavid C Somayajulu 				ql_entry_err_chk(entry, esize);
42816a62bec0SDavid C Somayajulu 				buff_level += esize;
42826a62bec0SDavid C Somayajulu 			}
42836a62bec0SDavid C Somayajulu 			break;
42846a62bec0SDavid C Somayajulu 
42856a62bec0SDavid C Somayajulu 		case L1DAT:
42866a62bec0SDavid C Somayajulu 		case L1INS:
42876a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
42886a62bec0SDavid C Somayajulu 			esize = ql_L1Cache(ha, (void *)entry, (void *)dbuff);
42896a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
42906a62bec0SDavid C Somayajulu 			buff_level += esize;
42916a62bec0SDavid C Somayajulu 			break;
42926a62bec0SDavid C Somayajulu 
42936a62bec0SDavid C Somayajulu 		case RDOCM:
42946a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
42956a62bec0SDavid C Somayajulu 			esize = ql_rdocm(ha, (void *)entry, (void *)dbuff);
42966a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
42976a62bec0SDavid C Somayajulu 			buff_level += esize;
42986a62bec0SDavid C Somayajulu 			break;
42996a62bec0SDavid C Somayajulu 
43006a62bec0SDavid C Somayajulu 		case RDMEM:
43016a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
43026a62bec0SDavid C Somayajulu 			esize = ql_rdmem(ha, (void *)entry, (void *)dbuff);
43036a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
43046a62bec0SDavid C Somayajulu 			buff_level += esize;
43056a62bec0SDavid C Somayajulu 			break;
43066a62bec0SDavid C Somayajulu 
43076a62bec0SDavid C Somayajulu 		case BOARD:
43086a62bec0SDavid C Somayajulu 		case RDROM:
43096a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
43106a62bec0SDavid C Somayajulu 			esize = ql_rdrom(ha, (void *)entry, (void *)dbuff);
43116a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
43126a62bec0SDavid C Somayajulu 			buff_level += esize;
43136a62bec0SDavid C Somayajulu 			break;
43146a62bec0SDavid C Somayajulu 
43156a62bec0SDavid C Somayajulu 		case RDMUX:
43166a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
43176a62bec0SDavid C Somayajulu 			esize = ql_rdmux(ha, (void *)entry, (void *)dbuff);
43186a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
43196a62bec0SDavid C Somayajulu 			buff_level += esize;
43206a62bec0SDavid C Somayajulu 			break;
43216a62bec0SDavid C Somayajulu 
43226a62bec0SDavid C Somayajulu                 case RDMUX2:
43236a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
43246a62bec0SDavid C Somayajulu                         esize = ql_rdmux2(ha, (void *)entry, (void *)dbuff);
43256a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
43266a62bec0SDavid C Somayajulu                         buff_level += esize;
43276a62bec0SDavid C Somayajulu                         break;
43286a62bec0SDavid C Somayajulu 
43296a62bec0SDavid C Somayajulu 		case QUEUE:
43306a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
43316a62bec0SDavid C Somayajulu 			esize = ql_rdqueue(ha, (void *)entry, (void *)dbuff);
43326a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
43336a62bec0SDavid C Somayajulu 			buff_level += esize;
43346a62bec0SDavid C Somayajulu 			break;
43356a62bec0SDavid C Somayajulu 
43366a62bec0SDavid C Somayajulu 		case CNTRL:
43376a62bec0SDavid C Somayajulu 			if ((rv = ql_cntrl(ha, template_hdr, (void *)entry))) {
43386a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
43396a62bec0SDavid C Somayajulu 			}
43406a62bec0SDavid C Somayajulu 			break;
43416a62bec0SDavid C Somayajulu 		default:
43426a62bec0SDavid C Somayajulu 			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
43436a62bec0SDavid C Somayajulu 			break;
43446a62bec0SDavid C Somayajulu 		}
43456a62bec0SDavid C Somayajulu 		/*  next entry in the template */
43466a62bec0SDavid C Somayajulu 		entry = (ql_minidump_entry_t *) ((char *) entry
43476a62bec0SDavid C Somayajulu 						+ entry->hdr.entry_size);
43486a62bec0SDavid C Somayajulu 	}
43496a62bec0SDavid C Somayajulu 
43506a62bec0SDavid C Somayajulu 	if (!sane_start || (sane_end > 1)) {
43516a62bec0SDavid C Somayajulu 		device_printf(ha->pci_dev,
43526a62bec0SDavid C Somayajulu 			"\n%s: Template configuration error. Check Template\n",
43536a62bec0SDavid C Somayajulu 			__func__);
43546a62bec0SDavid C Somayajulu 	}
43556a62bec0SDavid C Somayajulu 
43566a62bec0SDavid C Somayajulu 	QL_DPRINT80(ha, (ha->pci_dev, "%s: Minidump num of entries = %d\n",
43576a62bec0SDavid C Somayajulu 		__func__, template_hdr->num_of_entries));
43586a62bec0SDavid C Somayajulu 
43596a62bec0SDavid C Somayajulu 	return 0;
43606a62bec0SDavid C Somayajulu }
43616a62bec0SDavid C Somayajulu 
43626a62bec0SDavid C Somayajulu /*
43636a62bec0SDavid C Somayajulu  * Read CRB operation.
43646a62bec0SDavid C Somayajulu  */
43656a62bec0SDavid C Somayajulu static uint32_t
43666a62bec0SDavid C Somayajulu ql_rdcrb(qla_host_t *ha, ql_minidump_entry_rdcrb_t * crb_entry,
43676a62bec0SDavid C Somayajulu 	uint32_t * data_buff)
43686a62bec0SDavid C Somayajulu {
43696a62bec0SDavid C Somayajulu 	int loop_cnt;
43706a62bec0SDavid C Somayajulu 	int ret;
43716a62bec0SDavid C Somayajulu 	uint32_t op_count, addr, stride, value = 0;
43726a62bec0SDavid C Somayajulu 
43736a62bec0SDavid C Somayajulu 	addr = crb_entry->addr;
43746a62bec0SDavid C Somayajulu 	op_count = crb_entry->op_count;
43756a62bec0SDavid C Somayajulu 	stride = crb_entry->addr_stride;
43766a62bec0SDavid C Somayajulu 
43776a62bec0SDavid C Somayajulu 	for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
43786a62bec0SDavid C Somayajulu 
43796a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr, &value, 1);
43806a62bec0SDavid C Somayajulu 
43816a62bec0SDavid C Somayajulu 		if (ret)
43826a62bec0SDavid C Somayajulu 			return (0);
43836a62bec0SDavid C Somayajulu 
43846a62bec0SDavid C Somayajulu 		*data_buff++ = addr;
43856a62bec0SDavid C Somayajulu 		*data_buff++ = value;
43866a62bec0SDavid C Somayajulu 		addr = addr + stride;
43876a62bec0SDavid C Somayajulu 	}
43886a62bec0SDavid C Somayajulu 
43896a62bec0SDavid C Somayajulu 	/*
43906a62bec0SDavid C Somayajulu 	 * for testing purpose we return amount of data written
43916a62bec0SDavid C Somayajulu 	 */
43926a62bec0SDavid C Somayajulu 	return (op_count * (2 * sizeof(uint32_t)));
43936a62bec0SDavid C Somayajulu }
43946a62bec0SDavid C Somayajulu 
43956a62bec0SDavid C Somayajulu /*
43966a62bec0SDavid C Somayajulu  * Handle L2 Cache.
43976a62bec0SDavid C Somayajulu  */
43986a62bec0SDavid C Somayajulu 
43996a62bec0SDavid C Somayajulu static uint32_t
44006a62bec0SDavid C Somayajulu ql_L2Cache(qla_host_t *ha, ql_minidump_entry_cache_t *cacheEntry,
44016a62bec0SDavid C Somayajulu 	uint32_t * data_buff)
44026a62bec0SDavid C Somayajulu {
44036a62bec0SDavid C Somayajulu 	int i, k;
44046a62bec0SDavid C Somayajulu 	int loop_cnt;
44056a62bec0SDavid C Somayajulu 	int ret;
44066a62bec0SDavid C Somayajulu 
44076a62bec0SDavid C Somayajulu 	uint32_t read_value;
44086a62bec0SDavid C Somayajulu 	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr, cntl_value_w;
44096a62bec0SDavid C Somayajulu 	uint32_t tag_value, read_cnt;
44106a62bec0SDavid C Somayajulu 	volatile uint8_t cntl_value_r;
44116a62bec0SDavid C Somayajulu 	long timeout;
44126a62bec0SDavid C Somayajulu 	uint32_t data;
44136a62bec0SDavid C Somayajulu 
44146a62bec0SDavid C Somayajulu 	loop_cnt = cacheEntry->op_count;
44156a62bec0SDavid C Somayajulu 
44166a62bec0SDavid C Somayajulu 	read_addr = cacheEntry->read_addr;
44176a62bec0SDavid C Somayajulu 	cntrl_addr = cacheEntry->control_addr;
44186a62bec0SDavid C Somayajulu 	cntl_value_w = (uint32_t) cacheEntry->write_value;
44196a62bec0SDavid C Somayajulu 
44206a62bec0SDavid C Somayajulu 	tag_reg_addr = cacheEntry->tag_reg_addr;
44216a62bec0SDavid C Somayajulu 
44226a62bec0SDavid C Somayajulu 	tag_value = cacheEntry->init_tag_value;
44236a62bec0SDavid C Somayajulu 	read_cnt = cacheEntry->read_addr_cnt;
44246a62bec0SDavid C Somayajulu 
44256a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
44266a62bec0SDavid C Somayajulu 
44276a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
44286a62bec0SDavid C Somayajulu 		if (ret)
44296a62bec0SDavid C Somayajulu 			return (0);
44306a62bec0SDavid C Somayajulu 
44316a62bec0SDavid C Somayajulu 		if (cacheEntry->write_value != 0) {
44326a62bec0SDavid C Somayajulu 
44336a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, cntrl_addr,
44346a62bec0SDavid C Somayajulu 					&cntl_value_w, 0);
44356a62bec0SDavid C Somayajulu 			if (ret)
44366a62bec0SDavid C Somayajulu 				return (0);
44376a62bec0SDavid C Somayajulu 		}
44386a62bec0SDavid C Somayajulu 
44396a62bec0SDavid C Somayajulu 		if (cacheEntry->poll_mask != 0) {
44406a62bec0SDavid C Somayajulu 
44416a62bec0SDavid C Somayajulu 			timeout = cacheEntry->poll_wait;
44426a62bec0SDavid C Somayajulu 
44436a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, cntrl_addr, &data, 1);
44446a62bec0SDavid C Somayajulu 			if (ret)
44456a62bec0SDavid C Somayajulu 				return (0);
44466a62bec0SDavid C Somayajulu 
44476a62bec0SDavid C Somayajulu 			cntl_value_r = (uint8_t)data;
44486a62bec0SDavid C Somayajulu 
44496a62bec0SDavid C Somayajulu 			while ((cntl_value_r & cacheEntry->poll_mask) != 0) {
44506a62bec0SDavid C Somayajulu 
44516a62bec0SDavid C Somayajulu 				if (timeout) {
44526a62bec0SDavid C Somayajulu 					qla_mdelay(__func__, 1);
44536a62bec0SDavid C Somayajulu 					timeout--;
44546a62bec0SDavid C Somayajulu 				} else
44556a62bec0SDavid C Somayajulu 					break;
44566a62bec0SDavid C Somayajulu 
44576a62bec0SDavid C Somayajulu 				ret = ql_rdwr_indreg32(ha, cntrl_addr,
44586a62bec0SDavid C Somayajulu 						&data, 1);
44596a62bec0SDavid C Somayajulu 				if (ret)
44606a62bec0SDavid C Somayajulu 					return (0);
44616a62bec0SDavid C Somayajulu 
44626a62bec0SDavid C Somayajulu 				cntl_value_r = (uint8_t)data;
44636a62bec0SDavid C Somayajulu 			}
44646a62bec0SDavid C Somayajulu 			if (!timeout) {
44656a62bec0SDavid C Somayajulu 				/* Report timeout error.
44666a62bec0SDavid C Somayajulu 				 * core dump capture failed
44676a62bec0SDavid C Somayajulu 				 * Skip remaining entries.
44686a62bec0SDavid C Somayajulu 				 * Write buffer out to file
44696a62bec0SDavid C Somayajulu 				 * Use driver specific fields in template header
44706a62bec0SDavid C Somayajulu 				 * to report this error.
44716a62bec0SDavid C Somayajulu 				 */
44726a62bec0SDavid C Somayajulu 				return (-1);
44736a62bec0SDavid C Somayajulu 			}
44746a62bec0SDavid C Somayajulu 		}
44756a62bec0SDavid C Somayajulu 
44766a62bec0SDavid C Somayajulu 		addr = read_addr;
44776a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
44786a62bec0SDavid C Somayajulu 
44796a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
44806a62bec0SDavid C Somayajulu 			if (ret)
44816a62bec0SDavid C Somayajulu 				return (0);
44826a62bec0SDavid C Somayajulu 
44836a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
44846a62bec0SDavid C Somayajulu 			addr += cacheEntry->read_addr_stride;
44856a62bec0SDavid C Somayajulu 		}
44866a62bec0SDavid C Somayajulu 
44876a62bec0SDavid C Somayajulu 		tag_value += cacheEntry->tag_value_stride;
44886a62bec0SDavid C Somayajulu 	}
44896a62bec0SDavid C Somayajulu 
44906a62bec0SDavid C Somayajulu 	return (read_cnt * loop_cnt * sizeof(uint32_t));
44916a62bec0SDavid C Somayajulu }
44926a62bec0SDavid C Somayajulu 
44936a62bec0SDavid C Somayajulu /*
44946a62bec0SDavid C Somayajulu  * Handle L1 Cache.
44956a62bec0SDavid C Somayajulu  */
44966a62bec0SDavid C Somayajulu 
44976a62bec0SDavid C Somayajulu static uint32_t
44986a62bec0SDavid C Somayajulu ql_L1Cache(qla_host_t *ha,
44996a62bec0SDavid C Somayajulu 	ql_minidump_entry_cache_t *cacheEntry,
45006a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
45016a62bec0SDavid C Somayajulu {
45026a62bec0SDavid C Somayajulu 	int ret;
45036a62bec0SDavid C Somayajulu 	int i, k;
45046a62bec0SDavid C Somayajulu 	int loop_cnt;
45056a62bec0SDavid C Somayajulu 
45066a62bec0SDavid C Somayajulu 	uint32_t read_value;
45076a62bec0SDavid C Somayajulu 	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr;
45086a62bec0SDavid C Somayajulu 	uint32_t tag_value, read_cnt;
45096a62bec0SDavid C Somayajulu 	uint32_t cntl_value_w;
45106a62bec0SDavid C Somayajulu 
45116a62bec0SDavid C Somayajulu 	loop_cnt = cacheEntry->op_count;
45126a62bec0SDavid C Somayajulu 
45136a62bec0SDavid C Somayajulu 	read_addr = cacheEntry->read_addr;
45146a62bec0SDavid C Somayajulu 	cntrl_addr = cacheEntry->control_addr;
45156a62bec0SDavid C Somayajulu 	cntl_value_w = (uint32_t) cacheEntry->write_value;
45166a62bec0SDavid C Somayajulu 
45176a62bec0SDavid C Somayajulu 	tag_reg_addr = cacheEntry->tag_reg_addr;
45186a62bec0SDavid C Somayajulu 
45196a62bec0SDavid C Somayajulu 	tag_value = cacheEntry->init_tag_value;
45206a62bec0SDavid C Somayajulu 	read_cnt = cacheEntry->read_addr_cnt;
45216a62bec0SDavid C Somayajulu 
45226a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
45236a62bec0SDavid C Somayajulu 
45246a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
45256a62bec0SDavid C Somayajulu 		if (ret)
45266a62bec0SDavid C Somayajulu 			return (0);
45276a62bec0SDavid C Somayajulu 
45286a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, cntrl_addr, &cntl_value_w, 0);
45296a62bec0SDavid C Somayajulu 		if (ret)
45306a62bec0SDavid C Somayajulu 			return (0);
45316a62bec0SDavid C Somayajulu 
45326a62bec0SDavid C Somayajulu 		addr = read_addr;
45336a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
45346a62bec0SDavid C Somayajulu 
45356a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
45366a62bec0SDavid C Somayajulu 			if (ret)
45376a62bec0SDavid C Somayajulu 				return (0);
45386a62bec0SDavid C Somayajulu 
45396a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
45406a62bec0SDavid C Somayajulu 			addr += cacheEntry->read_addr_stride;
45416a62bec0SDavid C Somayajulu 		}
45426a62bec0SDavid C Somayajulu 
45436a62bec0SDavid C Somayajulu 		tag_value += cacheEntry->tag_value_stride;
45446a62bec0SDavid C Somayajulu 	}
45456a62bec0SDavid C Somayajulu 
45466a62bec0SDavid C Somayajulu 	return (read_cnt * loop_cnt * sizeof(uint32_t));
45476a62bec0SDavid C Somayajulu }
45486a62bec0SDavid C Somayajulu 
45496a62bec0SDavid C Somayajulu /*
45506a62bec0SDavid C Somayajulu  * Reading OCM memory
45516a62bec0SDavid C Somayajulu  */
45526a62bec0SDavid C Somayajulu 
45536a62bec0SDavid C Somayajulu static uint32_t
45546a62bec0SDavid C Somayajulu ql_rdocm(qla_host_t *ha,
45556a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdocm_t *ocmEntry,
45566a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
45576a62bec0SDavid C Somayajulu {
45586a62bec0SDavid C Somayajulu 	int i, loop_cnt;
45596a62bec0SDavid C Somayajulu 	volatile uint32_t addr;
45606a62bec0SDavid C Somayajulu 	volatile uint32_t value;
45616a62bec0SDavid C Somayajulu 
45626a62bec0SDavid C Somayajulu 	addr = ocmEntry->read_addr;
45636a62bec0SDavid C Somayajulu 	loop_cnt = ocmEntry->op_count;
45646a62bec0SDavid C Somayajulu 
45656a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
45666a62bec0SDavid C Somayajulu 		value = READ_REG32(ha, addr);
45676a62bec0SDavid C Somayajulu 		*data_buff++ = value;
45686a62bec0SDavid C Somayajulu 		addr += ocmEntry->read_addr_stride;
45696a62bec0SDavid C Somayajulu 	}
45706a62bec0SDavid C Somayajulu 	return (loop_cnt * sizeof(value));
45716a62bec0SDavid C Somayajulu }
45726a62bec0SDavid C Somayajulu 
45736a62bec0SDavid C Somayajulu /*
45746a62bec0SDavid C Somayajulu  * Read memory
45756a62bec0SDavid C Somayajulu  */
45766a62bec0SDavid C Somayajulu 
45776a62bec0SDavid C Somayajulu static uint32_t
45786a62bec0SDavid C Somayajulu ql_rdmem(qla_host_t *ha,
45796a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdmem_t *mem_entry,
45806a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
45816a62bec0SDavid C Somayajulu {
45826a62bec0SDavid C Somayajulu 	int ret;
45836a62bec0SDavid C Somayajulu         int i, loop_cnt;
45846a62bec0SDavid C Somayajulu         volatile uint32_t addr;
45856a62bec0SDavid C Somayajulu 	q80_offchip_mem_val_t val;
45866a62bec0SDavid C Somayajulu 
45876a62bec0SDavid C Somayajulu         addr = mem_entry->read_addr;
45886a62bec0SDavid C Somayajulu 
45896a62bec0SDavid C Somayajulu 	/* size in bytes / 16 */
45906a62bec0SDavid C Somayajulu         loop_cnt = mem_entry->read_data_size / (sizeof(uint32_t) * 4);
45916a62bec0SDavid C Somayajulu 
45926a62bec0SDavid C Somayajulu         for (i = 0; i < loop_cnt; i++) {
45936a62bec0SDavid C Somayajulu 
45946a62bec0SDavid C Somayajulu 		ret = ql_rdwr_offchip_mem(ha, (addr & 0x0ffffffff), &val, 1);
45956a62bec0SDavid C Somayajulu 		if (ret)
45966a62bec0SDavid C Somayajulu 			return (0);
45976a62bec0SDavid C Somayajulu 
45986a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_lo;
45996a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_hi;
46006a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_ulo;
46016a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_uhi;
46026a62bec0SDavid C Somayajulu 
46036a62bec0SDavid C Somayajulu                 addr += (sizeof(uint32_t) * 4);
46046a62bec0SDavid C Somayajulu         }
46056a62bec0SDavid C Somayajulu 
46066a62bec0SDavid C Somayajulu         return (loop_cnt * (sizeof(uint32_t) * 4));
46076a62bec0SDavid C Somayajulu }
46086a62bec0SDavid C Somayajulu 
46096a62bec0SDavid C Somayajulu /*
46106a62bec0SDavid C Somayajulu  * Read Rom
46116a62bec0SDavid C Somayajulu  */
46126a62bec0SDavid C Somayajulu 
46136a62bec0SDavid C Somayajulu static uint32_t
46146a62bec0SDavid C Somayajulu ql_rdrom(qla_host_t *ha,
46156a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdrom_t *romEntry,
46166a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
46176a62bec0SDavid C Somayajulu {
46186a62bec0SDavid C Somayajulu 	int ret;
46196a62bec0SDavid C Somayajulu 	int i, loop_cnt;
46206a62bec0SDavid C Somayajulu 	uint32_t addr;
46216a62bec0SDavid C Somayajulu 	uint32_t value;
46226a62bec0SDavid C Somayajulu 
46236a62bec0SDavid C Somayajulu 	addr = romEntry->read_addr;
46246a62bec0SDavid C Somayajulu 	loop_cnt = romEntry->read_data_size; /* This is size in bytes */
46256a62bec0SDavid C Somayajulu 	loop_cnt /= sizeof(value);
46266a62bec0SDavid C Somayajulu 
46276a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
46286a62bec0SDavid C Somayajulu 
46296a62bec0SDavid C Somayajulu 		ret = ql_rd_flash32(ha, addr, &value);
46306a62bec0SDavid C Somayajulu 		if (ret)
46316a62bec0SDavid C Somayajulu 			return (0);
46326a62bec0SDavid C Somayajulu 
46336a62bec0SDavid C Somayajulu 		*data_buff++ = value;
46346a62bec0SDavid C Somayajulu 		addr += sizeof(value);
46356a62bec0SDavid C Somayajulu 	}
46366a62bec0SDavid C Somayajulu 
46376a62bec0SDavid C Somayajulu 	return (loop_cnt * sizeof(value));
46386a62bec0SDavid C Somayajulu }
46396a62bec0SDavid C Somayajulu 
46406a62bec0SDavid C Somayajulu /*
46416a62bec0SDavid C Somayajulu  * Read MUX data
46426a62bec0SDavid C Somayajulu  */
46436a62bec0SDavid C Somayajulu 
46446a62bec0SDavid C Somayajulu static uint32_t
46456a62bec0SDavid C Somayajulu ql_rdmux(qla_host_t *ha,
46466a62bec0SDavid C Somayajulu 	ql_minidump_entry_mux_t *muxEntry,
46476a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
46486a62bec0SDavid C Somayajulu {
46496a62bec0SDavid C Somayajulu 	int ret;
46506a62bec0SDavid C Somayajulu 	int loop_cnt;
46516a62bec0SDavid C Somayajulu 	uint32_t read_value, sel_value;
46526a62bec0SDavid C Somayajulu 	uint32_t read_addr, select_addr;
46536a62bec0SDavid C Somayajulu 
46546a62bec0SDavid C Somayajulu 	select_addr = muxEntry->select_addr;
46556a62bec0SDavid C Somayajulu 	sel_value = muxEntry->select_value;
46566a62bec0SDavid C Somayajulu 	read_addr = muxEntry->read_addr;
46576a62bec0SDavid C Somayajulu 
46586a62bec0SDavid C Somayajulu 	for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
46596a62bec0SDavid C Somayajulu 
46606a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr, &sel_value, 0);
46616a62bec0SDavid C Somayajulu 		if (ret)
46626a62bec0SDavid C Somayajulu 			return (0);
46636a62bec0SDavid C Somayajulu 
46646a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
46656a62bec0SDavid C Somayajulu 		if (ret)
46666a62bec0SDavid C Somayajulu 			return (0);
46676a62bec0SDavid C Somayajulu 
46686a62bec0SDavid C Somayajulu 		*data_buff++ = sel_value;
46696a62bec0SDavid C Somayajulu 		*data_buff++ = read_value;
46706a62bec0SDavid C Somayajulu 
46716a62bec0SDavid C Somayajulu 		sel_value += muxEntry->select_value_stride;
46726a62bec0SDavid C Somayajulu 	}
46736a62bec0SDavid C Somayajulu 
46746a62bec0SDavid C Somayajulu 	return (loop_cnt * (2 * sizeof(uint32_t)));
46756a62bec0SDavid C Somayajulu }
46766a62bec0SDavid C Somayajulu 
46776a62bec0SDavid C Somayajulu static uint32_t
46786a62bec0SDavid C Somayajulu ql_rdmux2(qla_host_t *ha,
46796a62bec0SDavid C Somayajulu 	ql_minidump_entry_mux2_t *muxEntry,
46806a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
46816a62bec0SDavid C Somayajulu {
46826a62bec0SDavid C Somayajulu 	int ret;
46836a62bec0SDavid C Somayajulu         int loop_cnt;
46846a62bec0SDavid C Somayajulu 
46856a62bec0SDavid C Somayajulu         uint32_t select_addr_1, select_addr_2;
46866a62bec0SDavid C Somayajulu         uint32_t select_value_1, select_value_2;
46876a62bec0SDavid C Somayajulu         uint32_t select_value_count, select_value_mask;
46886a62bec0SDavid C Somayajulu         uint32_t read_addr, read_value;
46896a62bec0SDavid C Somayajulu 
46906a62bec0SDavid C Somayajulu         select_addr_1 = muxEntry->select_addr_1;
46916a62bec0SDavid C Somayajulu         select_addr_2 = muxEntry->select_addr_2;
46926a62bec0SDavid C Somayajulu         select_value_1 = muxEntry->select_value_1;
46936a62bec0SDavid C Somayajulu         select_value_2 = muxEntry->select_value_2;
46946a62bec0SDavid C Somayajulu         select_value_count = muxEntry->select_value_count;
46956a62bec0SDavid C Somayajulu         select_value_mask  = muxEntry->select_value_mask;
46966a62bec0SDavid C Somayajulu 
46976a62bec0SDavid C Somayajulu         read_addr = muxEntry->read_addr;
46986a62bec0SDavid C Somayajulu 
46996a62bec0SDavid C Somayajulu         for (loop_cnt = 0; loop_cnt < muxEntry->select_value_count;
47006a62bec0SDavid C Somayajulu 		loop_cnt++) {
47016a62bec0SDavid C Somayajulu 
47026a62bec0SDavid C Somayajulu                 uint32_t temp_sel_val;
47036a62bec0SDavid C Somayajulu 
47046a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_1, 0);
47056a62bec0SDavid C Somayajulu 		if (ret)
47066a62bec0SDavid C Somayajulu 			return (0);
47076a62bec0SDavid C Somayajulu 
47086a62bec0SDavid C Somayajulu                 temp_sel_val = select_value_1 & select_value_mask;
47096a62bec0SDavid C Somayajulu 
47106a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
47116a62bec0SDavid C Somayajulu 		if (ret)
47126a62bec0SDavid C Somayajulu 			return (0);
47136a62bec0SDavid C Somayajulu 
47146a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
47156a62bec0SDavid C Somayajulu 		if (ret)
47166a62bec0SDavid C Somayajulu 			return (0);
47176a62bec0SDavid C Somayajulu 
47186a62bec0SDavid C Somayajulu                 *data_buff++ = temp_sel_val;
47196a62bec0SDavid C Somayajulu                 *data_buff++ = read_value;
47206a62bec0SDavid C Somayajulu 
47216a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_2, 0);
47226a62bec0SDavid C Somayajulu 		if (ret)
47236a62bec0SDavid C Somayajulu 			return (0);
47246a62bec0SDavid C Somayajulu 
47256a62bec0SDavid C Somayajulu                 temp_sel_val = select_value_2 & select_value_mask;
47266a62bec0SDavid C Somayajulu 
47276a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
47286a62bec0SDavid C Somayajulu 		if (ret)
47296a62bec0SDavid C Somayajulu 			return (0);
47306a62bec0SDavid C Somayajulu 
47316a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
47326a62bec0SDavid C Somayajulu 		if (ret)
47336a62bec0SDavid C Somayajulu 			return (0);
47346a62bec0SDavid C Somayajulu 
47356a62bec0SDavid C Somayajulu                 *data_buff++ = temp_sel_val;
47366a62bec0SDavid C Somayajulu                 *data_buff++ = read_value;
47376a62bec0SDavid C Somayajulu 
47386a62bec0SDavid C Somayajulu                 select_value_1 += muxEntry->select_value_stride;
47396a62bec0SDavid C Somayajulu                 select_value_2 += muxEntry->select_value_stride;
47406a62bec0SDavid C Somayajulu         }
47416a62bec0SDavid C Somayajulu 
47426a62bec0SDavid C Somayajulu         return (loop_cnt * (4 * sizeof(uint32_t)));
47436a62bec0SDavid C Somayajulu }
47446a62bec0SDavid C Somayajulu 
47456a62bec0SDavid C Somayajulu /*
47466a62bec0SDavid C Somayajulu  * Handling Queue State Reads.
47476a62bec0SDavid C Somayajulu  */
47486a62bec0SDavid C Somayajulu 
47496a62bec0SDavid C Somayajulu static uint32_t
47506a62bec0SDavid C Somayajulu ql_rdqueue(qla_host_t *ha,
47516a62bec0SDavid C Somayajulu 	ql_minidump_entry_queue_t *queueEntry,
47526a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
47536a62bec0SDavid C Somayajulu {
47546a62bec0SDavid C Somayajulu 	int ret;
47556a62bec0SDavid C Somayajulu 	int loop_cnt, k;
47566a62bec0SDavid C Somayajulu 	uint32_t read_value;
47576a62bec0SDavid C Somayajulu 	uint32_t read_addr, read_stride, select_addr;
47586a62bec0SDavid C Somayajulu 	uint32_t queue_id, read_cnt;
47596a62bec0SDavid C Somayajulu 
47606a62bec0SDavid C Somayajulu 	read_cnt = queueEntry->read_addr_cnt;
47616a62bec0SDavid C Somayajulu 	read_stride = queueEntry->read_addr_stride;
47626a62bec0SDavid C Somayajulu 	select_addr = queueEntry->select_addr;
47636a62bec0SDavid C Somayajulu 
47646a62bec0SDavid C Somayajulu 	for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
47656a62bec0SDavid C Somayajulu 		loop_cnt++) {
47666a62bec0SDavid C Somayajulu 
47676a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr, &queue_id, 0);
47686a62bec0SDavid C Somayajulu 		if (ret)
47696a62bec0SDavid C Somayajulu 			return (0);
47706a62bec0SDavid C Somayajulu 
47716a62bec0SDavid C Somayajulu 		read_addr = queueEntry->read_addr;
47726a62bec0SDavid C Somayajulu 
47736a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
47746a62bec0SDavid C Somayajulu 
47756a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
47766a62bec0SDavid C Somayajulu 			if (ret)
47776a62bec0SDavid C Somayajulu 				return (0);
47786a62bec0SDavid C Somayajulu 
47796a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
47806a62bec0SDavid C Somayajulu 			read_addr += read_stride;
47816a62bec0SDavid C Somayajulu 		}
47826a62bec0SDavid C Somayajulu 
47836a62bec0SDavid C Somayajulu 		queue_id += queueEntry->queue_id_stride;
47846a62bec0SDavid C Somayajulu 	}
47856a62bec0SDavid C Somayajulu 
47866a62bec0SDavid C Somayajulu 	return (loop_cnt * (read_cnt * sizeof(uint32_t)));
47876a62bec0SDavid C Somayajulu }
47886a62bec0SDavid C Somayajulu 
47896a62bec0SDavid C Somayajulu /*
47906a62bec0SDavid C Somayajulu  * Handling control entries.
47916a62bec0SDavid C Somayajulu  */
47926a62bec0SDavid C Somayajulu 
47936a62bec0SDavid C Somayajulu static uint32_t
47946a62bec0SDavid C Somayajulu ql_cntrl(qla_host_t *ha,
47956a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *template_hdr,
47966a62bec0SDavid C Somayajulu 	ql_minidump_entry_cntrl_t *crbEntry)
47976a62bec0SDavid C Somayajulu {
47986a62bec0SDavid C Somayajulu 	int ret;
47996a62bec0SDavid C Somayajulu 	int count;
48006a62bec0SDavid C Somayajulu 	uint32_t opcode, read_value, addr, entry_addr;
48016a62bec0SDavid C Somayajulu 	long timeout;
48026a62bec0SDavid C Somayajulu 
48036a62bec0SDavid C Somayajulu 	entry_addr = crbEntry->addr;
48046a62bec0SDavid C Somayajulu 
48056a62bec0SDavid C Somayajulu 	for (count = 0; count < crbEntry->op_count; count++) {
48066a62bec0SDavid C Somayajulu 		opcode = crbEntry->opcode;
48076a62bec0SDavid C Somayajulu 
48086a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_WR) {
48096a62bec0SDavid C Somayajulu 
48106a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr,
48116a62bec0SDavid C Somayajulu 					&crbEntry->value_1, 0);
48126a62bec0SDavid C Somayajulu 			if (ret)
48136a62bec0SDavid C Somayajulu 				return (0);
48146a62bec0SDavid C Somayajulu 
48156a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_WR;
48166a62bec0SDavid C Somayajulu 		}
48176a62bec0SDavid C Somayajulu 
48186a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_RW) {
48196a62bec0SDavid C Somayajulu 
48206a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
48216a62bec0SDavid C Somayajulu 			if (ret)
48226a62bec0SDavid C Somayajulu 				return (0);
48236a62bec0SDavid C Somayajulu 
48246a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
48256a62bec0SDavid C Somayajulu 			if (ret)
48266a62bec0SDavid C Somayajulu 				return (0);
48276a62bec0SDavid C Somayajulu 
48286a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_RW;
48296a62bec0SDavid C Somayajulu 		}
48306a62bec0SDavid C Somayajulu 
48316a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_AND) {
48326a62bec0SDavid C Somayajulu 
48336a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
48346a62bec0SDavid C Somayajulu 			if (ret)
48356a62bec0SDavid C Somayajulu 				return (0);
48366a62bec0SDavid C Somayajulu 
48376a62bec0SDavid C Somayajulu 			read_value &= crbEntry->value_2;
48386a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_AND;
48396a62bec0SDavid C Somayajulu 
48406a62bec0SDavid C Somayajulu 			if (opcode & QL_DBG_OPCODE_OR) {
48416a62bec0SDavid C Somayajulu 				read_value |= crbEntry->value_3;
48426a62bec0SDavid C Somayajulu 				opcode &= ~QL_DBG_OPCODE_OR;
48436a62bec0SDavid C Somayajulu 			}
48446a62bec0SDavid C Somayajulu 
48456a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
48466a62bec0SDavid C Somayajulu 			if (ret)
48476a62bec0SDavid C Somayajulu 				return (0);
48486a62bec0SDavid C Somayajulu 		}
48496a62bec0SDavid C Somayajulu 
48506a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_OR) {
48516a62bec0SDavid C Somayajulu 
48526a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
48536a62bec0SDavid C Somayajulu 			if (ret)
48546a62bec0SDavid C Somayajulu 				return (0);
48556a62bec0SDavid C Somayajulu 
48566a62bec0SDavid C Somayajulu 			read_value |= crbEntry->value_3;
48576a62bec0SDavid C Somayajulu 
48586a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
48596a62bec0SDavid C Somayajulu 			if (ret)
48606a62bec0SDavid C Somayajulu 				return (0);
48616a62bec0SDavid C Somayajulu 
48626a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_OR;
48636a62bec0SDavid C Somayajulu 		}
48646a62bec0SDavid C Somayajulu 
48656a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_POLL) {
48666a62bec0SDavid C Somayajulu 
48676a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_POLL;
48686a62bec0SDavid C Somayajulu 			timeout = crbEntry->poll_timeout;
48696a62bec0SDavid C Somayajulu 			addr = entry_addr;
48706a62bec0SDavid C Somayajulu 
48716a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
48726a62bec0SDavid C Somayajulu 			if (ret)
48736a62bec0SDavid C Somayajulu 				return (0);
48746a62bec0SDavid C Somayajulu 
48756a62bec0SDavid C Somayajulu 			while ((read_value & crbEntry->value_2)
48766a62bec0SDavid C Somayajulu 				!= crbEntry->value_1) {
48776a62bec0SDavid C Somayajulu 
48786a62bec0SDavid C Somayajulu 				if (timeout) {
48796a62bec0SDavid C Somayajulu 					qla_mdelay(__func__, 1);
48806a62bec0SDavid C Somayajulu 					timeout--;
48816a62bec0SDavid C Somayajulu 				} else
48826a62bec0SDavid C Somayajulu 					break;
48836a62bec0SDavid C Somayajulu 
48846a62bec0SDavid C Somayajulu                 		ret = ql_rdwr_indreg32(ha, addr,
48856a62bec0SDavid C Somayajulu 						&read_value, 1);
48866a62bec0SDavid C Somayajulu 				if (ret)
48876a62bec0SDavid C Somayajulu 					return (0);
48886a62bec0SDavid C Somayajulu 			}
48896a62bec0SDavid C Somayajulu 
48906a62bec0SDavid C Somayajulu 			if (!timeout) {
48916a62bec0SDavid C Somayajulu 				/*
48926a62bec0SDavid C Somayajulu 				 * Report timeout error.
48936a62bec0SDavid C Somayajulu 				 * core dump capture failed
48946a62bec0SDavid C Somayajulu 				 * Skip remaining entries.
48956a62bec0SDavid C Somayajulu 				 * Write buffer out to file
48966a62bec0SDavid C Somayajulu 				 * Use driver specific fields in template header
48976a62bec0SDavid C Somayajulu 				 * to report this error.
48986a62bec0SDavid C Somayajulu 				 */
48996a62bec0SDavid C Somayajulu 				return (-1);
49006a62bec0SDavid C Somayajulu 			}
49016a62bec0SDavid C Somayajulu 		}
49026a62bec0SDavid C Somayajulu 
49036a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_RDSTATE) {
49046a62bec0SDavid C Somayajulu 			/*
49056a62bec0SDavid C Somayajulu 			 * decide which address to use.
49066a62bec0SDavid C Somayajulu 			 */
49076a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_a) {
49086a62bec0SDavid C Somayajulu 				addr = template_hdr->saved_state_array[
49096a62bec0SDavid C Somayajulu 						crbEntry-> state_index_a];
49106a62bec0SDavid C Somayajulu 			} else {
49116a62bec0SDavid C Somayajulu 				addr = entry_addr;
49126a62bec0SDavid C Somayajulu 			}
49136a62bec0SDavid C Somayajulu 
49146a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
49156a62bec0SDavid C Somayajulu 			if (ret)
49166a62bec0SDavid C Somayajulu 				return (0);
49176a62bec0SDavid C Somayajulu 
49186a62bec0SDavid C Somayajulu 			template_hdr->saved_state_array[crbEntry->state_index_v]
49196a62bec0SDavid C Somayajulu 					= read_value;
49206a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_RDSTATE;
49216a62bec0SDavid C Somayajulu 		}
49226a62bec0SDavid C Somayajulu 
49236a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_WRSTATE) {
49246a62bec0SDavid C Somayajulu 			/*
49256a62bec0SDavid C Somayajulu 			 * decide which value to use.
49266a62bec0SDavid C Somayajulu 			 */
49276a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_v) {
49286a62bec0SDavid C Somayajulu 				read_value = template_hdr->saved_state_array[
49296a62bec0SDavid C Somayajulu 						crbEntry->state_index_v];
49306a62bec0SDavid C Somayajulu 			} else {
49316a62bec0SDavid C Somayajulu 				read_value = crbEntry->value_1;
49326a62bec0SDavid C Somayajulu 			}
49336a62bec0SDavid C Somayajulu 			/*
49346a62bec0SDavid C Somayajulu 			 * decide which address to use.
49356a62bec0SDavid C Somayajulu 			 */
49366a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_a) {
49376a62bec0SDavid C Somayajulu 				addr = template_hdr->saved_state_array[
49386a62bec0SDavid C Somayajulu 						crbEntry-> state_index_a];
49396a62bec0SDavid C Somayajulu 			} else {
49406a62bec0SDavid C Somayajulu 				addr = entry_addr;
49416a62bec0SDavid C Somayajulu 			}
49426a62bec0SDavid C Somayajulu 
49436a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 0);
49446a62bec0SDavid C Somayajulu 			if (ret)
49456a62bec0SDavid C Somayajulu 				return (0);
49466a62bec0SDavid C Somayajulu 
49476a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_WRSTATE;
49486a62bec0SDavid C Somayajulu 		}
49496a62bec0SDavid C Somayajulu 
49506a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_MDSTATE) {
49516a62bec0SDavid C Somayajulu 			/*  Read value from saved state using index */
49526a62bec0SDavid C Somayajulu 			read_value = template_hdr->saved_state_array[
49536a62bec0SDavid C Somayajulu 						crbEntry->state_index_v];
49546a62bec0SDavid C Somayajulu 
49556a62bec0SDavid C Somayajulu 			read_value <<= crbEntry->shl; /*Shift left operation */
49566a62bec0SDavid C Somayajulu 			read_value >>= crbEntry->shr; /*Shift right operation */
49576a62bec0SDavid C Somayajulu 
49586a62bec0SDavid C Somayajulu 			if (crbEntry->value_2) {
49596a62bec0SDavid C Somayajulu 				/* check if AND mask is provided */
49606a62bec0SDavid C Somayajulu 				read_value &= crbEntry->value_2;
49616a62bec0SDavid C Somayajulu 			}
49626a62bec0SDavid C Somayajulu 
49636a62bec0SDavid C Somayajulu 			read_value |= crbEntry->value_3; /* OR operation */
49646a62bec0SDavid C Somayajulu 			read_value += crbEntry->value_1; /* increment op */
49656a62bec0SDavid C Somayajulu 
49666a62bec0SDavid C Somayajulu 			/* Write value back to state area. */
49676a62bec0SDavid C Somayajulu 
49686a62bec0SDavid C Somayajulu 			template_hdr->saved_state_array[crbEntry->state_index_v]
49696a62bec0SDavid C Somayajulu 					= read_value;
49706a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_MDSTATE;
49716a62bec0SDavid C Somayajulu 		}
49726a62bec0SDavid C Somayajulu 
49736a62bec0SDavid C Somayajulu 		entry_addr += crbEntry->addr_stride;
49746a62bec0SDavid C Somayajulu 	}
49756a62bec0SDavid C Somayajulu 
49766a62bec0SDavid C Somayajulu 	return (0);
49776a62bec0SDavid C Somayajulu }
49786a62bec0SDavid C Somayajulu 
49796a62bec0SDavid C Somayajulu /*
49806a62bec0SDavid C Somayajulu  * Handling rd poll entry.
49816a62bec0SDavid C Somayajulu  */
49826a62bec0SDavid C Somayajulu 
49836a62bec0SDavid C Somayajulu static uint32_t
49846a62bec0SDavid C Somayajulu ql_pollrd(qla_host_t *ha, ql_minidump_entry_pollrd_t *entry,
49856a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
49866a62bec0SDavid C Somayajulu {
49876a62bec0SDavid C Somayajulu         int ret;
49886a62bec0SDavid C Somayajulu         int loop_cnt;
49896a62bec0SDavid C Somayajulu         uint32_t op_count, select_addr, select_value_stride, select_value;
49906a62bec0SDavid C Somayajulu         uint32_t read_addr, poll, mask, data_size, data;
49916a62bec0SDavid C Somayajulu         uint32_t wait_count = 0;
49926a62bec0SDavid C Somayajulu 
49936a62bec0SDavid C Somayajulu         select_addr            = entry->select_addr;
49946a62bec0SDavid C Somayajulu         read_addr              = entry->read_addr;
49956a62bec0SDavid C Somayajulu         select_value           = entry->select_value;
49966a62bec0SDavid C Somayajulu         select_value_stride    = entry->select_value_stride;
49976a62bec0SDavid C Somayajulu         op_count               = entry->op_count;
49986a62bec0SDavid C Somayajulu         poll                   = entry->poll;
49996a62bec0SDavid C Somayajulu         mask                   = entry->mask;
50006a62bec0SDavid C Somayajulu         data_size              = entry->data_size;
50016a62bec0SDavid C Somayajulu 
50026a62bec0SDavid C Somayajulu         for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
50036a62bec0SDavid C Somayajulu 
50046a62bec0SDavid C Somayajulu                 ret = ql_rdwr_indreg32(ha, select_addr, &select_value, 0);
50056a62bec0SDavid C Somayajulu 		if (ret)
50066a62bec0SDavid C Somayajulu 			return (0);
50076a62bec0SDavid C Somayajulu 
50086a62bec0SDavid C Somayajulu                 wait_count = 0;
50096a62bec0SDavid C Somayajulu 
50106a62bec0SDavid C Somayajulu                 while (wait_count < poll) {
50116a62bec0SDavid C Somayajulu 
50126a62bec0SDavid C Somayajulu                         uint32_t temp;
50136a62bec0SDavid C Somayajulu 
50146a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, select_addr, &temp, 1);
50156a62bec0SDavid C Somayajulu 			if (ret)
50166a62bec0SDavid C Somayajulu 				return (0);
50176a62bec0SDavid C Somayajulu 
50186a62bec0SDavid C Somayajulu                         if ( (temp & mask) != 0 ) {
50196a62bec0SDavid C Somayajulu                                 break;
50206a62bec0SDavid C Somayajulu                         }
50216a62bec0SDavid C Somayajulu                         wait_count++;
50226a62bec0SDavid C Somayajulu                 }
50236a62bec0SDavid C Somayajulu 
50246a62bec0SDavid C Somayajulu                 if (wait_count == poll) {
50256a62bec0SDavid C Somayajulu                         device_printf(ha->pci_dev,
50266a62bec0SDavid C Somayajulu 				"%s: Error in processing entry\n", __func__);
50276a62bec0SDavid C Somayajulu                         device_printf(ha->pci_dev,
50286a62bec0SDavid C Somayajulu 				"%s: wait_count <0x%x> poll <0x%x>\n",
50296a62bec0SDavid C Somayajulu 				__func__, wait_count, poll);
50306a62bec0SDavid C Somayajulu                         return 0;
50316a62bec0SDavid C Somayajulu                 }
50326a62bec0SDavid C Somayajulu 
50336a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &data, 1);
50346a62bec0SDavid C Somayajulu 		if (ret)
50356a62bec0SDavid C Somayajulu 			return (0);
50366a62bec0SDavid C Somayajulu 
50376a62bec0SDavid C Somayajulu                 *data_buff++ = select_value;
50386a62bec0SDavid C Somayajulu                 *data_buff++ = data;
50396a62bec0SDavid C Somayajulu                 select_value = select_value + select_value_stride;
50406a62bec0SDavid C Somayajulu         }
50416a62bec0SDavid C Somayajulu 
50426a62bec0SDavid C Somayajulu         /*
50436a62bec0SDavid C Somayajulu          * for testing purpose we return amount of data written
50446a62bec0SDavid C Somayajulu          */
50456a62bec0SDavid C Somayajulu         return (loop_cnt * (2 * sizeof(uint32_t)));
50466a62bec0SDavid C Somayajulu }
50476a62bec0SDavid C Somayajulu 
50486a62bec0SDavid C Somayajulu 
50496a62bec0SDavid C Somayajulu /*
50506a62bec0SDavid C Somayajulu  * Handling rd modify write poll entry.
50516a62bec0SDavid C Somayajulu  */
50526a62bec0SDavid C Somayajulu 
50536a62bec0SDavid C Somayajulu static uint32_t
50546a62bec0SDavid C Somayajulu ql_pollrd_modify_write(qla_host_t *ha,
50556a62bec0SDavid C Somayajulu 	ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
50566a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
50576a62bec0SDavid C Somayajulu {
50586a62bec0SDavid C Somayajulu 	int ret;
50596a62bec0SDavid C Somayajulu         uint32_t addr_1, addr_2, value_1, value_2, data;
50606a62bec0SDavid C Somayajulu         uint32_t poll, mask, data_size, modify_mask;
50616a62bec0SDavid C Somayajulu         uint32_t wait_count = 0;
50626a62bec0SDavid C Somayajulu 
50636a62bec0SDavid C Somayajulu         addr_1		= entry->addr_1;
50646a62bec0SDavid C Somayajulu         addr_2		= entry->addr_2;
50656a62bec0SDavid C Somayajulu         value_1		= entry->value_1;
50666a62bec0SDavid C Somayajulu         value_2		= entry->value_2;
50676a62bec0SDavid C Somayajulu 
50686a62bec0SDavid C Somayajulu         poll		= entry->poll;
50696a62bec0SDavid C Somayajulu         mask		= entry->mask;
50706a62bec0SDavid C Somayajulu         modify_mask	= entry->modify_mask;
50716a62bec0SDavid C Somayajulu         data_size	= entry->data_size;
50726a62bec0SDavid C Somayajulu 
50736a62bec0SDavid C Somayajulu 
50746a62bec0SDavid C Somayajulu 	ret = ql_rdwr_indreg32(ha, addr_1, &value_1, 0);
50756a62bec0SDavid C Somayajulu 	if (ret)
50766a62bec0SDavid C Somayajulu 		return (0);
50776a62bec0SDavid C Somayajulu 
50786a62bec0SDavid C Somayajulu         wait_count = 0;
50796a62bec0SDavid C Somayajulu         while (wait_count < poll) {
50806a62bec0SDavid C Somayajulu 
50816a62bec0SDavid C Somayajulu 		uint32_t temp;
50826a62bec0SDavid C Somayajulu 
50836a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
50846a62bec0SDavid C Somayajulu 		if (ret)
50856a62bec0SDavid C Somayajulu 			return (0);
50866a62bec0SDavid C Somayajulu 
50876a62bec0SDavid C Somayajulu                 if ( (temp & mask) != 0 ) {
50886a62bec0SDavid C Somayajulu                         break;
50896a62bec0SDavid C Somayajulu                 }
50906a62bec0SDavid C Somayajulu                 wait_count++;
50916a62bec0SDavid C Somayajulu         }
50926a62bec0SDavid C Somayajulu 
50936a62bec0SDavid C Somayajulu         if (wait_count == poll) {
50946a62bec0SDavid C Somayajulu                 device_printf(ha->pci_dev, "%s Error in processing entry\n",
50956a62bec0SDavid C Somayajulu 			__func__);
50966a62bec0SDavid C Somayajulu         } else {
50976a62bec0SDavid C Somayajulu 
50986a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_2, &data, 1);
50996a62bec0SDavid C Somayajulu 		if (ret)
51006a62bec0SDavid C Somayajulu 			return (0);
51016a62bec0SDavid C Somayajulu 
51026a62bec0SDavid C Somayajulu                 data = (data & modify_mask);
51036a62bec0SDavid C Somayajulu 
51046a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_2, &data, 0);
51056a62bec0SDavid C Somayajulu 		if (ret)
51066a62bec0SDavid C Somayajulu 			return (0);
51076a62bec0SDavid C Somayajulu 
51086a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_1, &value_2, 0);
51096a62bec0SDavid C Somayajulu 		if (ret)
51106a62bec0SDavid C Somayajulu 			return (0);
51116a62bec0SDavid C Somayajulu 
51126a62bec0SDavid C Somayajulu                 /* Poll again */
51136a62bec0SDavid C Somayajulu                 wait_count = 0;
51146a62bec0SDavid C Somayajulu                 while (wait_count < poll) {
51156a62bec0SDavid C Somayajulu 
51166a62bec0SDavid C Somayajulu                         uint32_t temp;
51176a62bec0SDavid C Somayajulu 
51186a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
51196a62bec0SDavid C Somayajulu 			if (ret)
51206a62bec0SDavid C Somayajulu 				return (0);
51216a62bec0SDavid C Somayajulu 
51226a62bec0SDavid C Somayajulu                         if ( (temp & mask) != 0 ) {
51236a62bec0SDavid C Somayajulu                                 break;
51246a62bec0SDavid C Somayajulu                         }
51256a62bec0SDavid C Somayajulu                         wait_count++;
51266a62bec0SDavid C Somayajulu                 }
51276a62bec0SDavid C Somayajulu                 *data_buff++ = addr_2;
51286a62bec0SDavid C Somayajulu                 *data_buff++ = data;
51296a62bec0SDavid C Somayajulu         }
51306a62bec0SDavid C Somayajulu 
51316a62bec0SDavid C Somayajulu         /*
51326a62bec0SDavid C Somayajulu          * for testing purpose we return amount of data written
51336a62bec0SDavid C Somayajulu          */
51346a62bec0SDavid C Somayajulu         return (2 * sizeof(uint32_t));
51356a62bec0SDavid C Somayajulu }
51366a62bec0SDavid C Somayajulu 
51376a62bec0SDavid C Somayajulu 
5138