xref: /freebsd/sys/dev/qlxgbe/ql_hw.c (revision 971e53c9)
1718cf2ccSPedro F. Giffuni /*-
2718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3718cf2ccSPedro F. Giffuni  *
435291c22SDavid C Somayajulu  * Copyright (c) 2013-2016 Qlogic Corporation
5f10a77bbSDavid C Somayajulu  * All rights reserved.
6f10a77bbSDavid C Somayajulu  *
7f10a77bbSDavid C Somayajulu  *  Redistribution and use in source and binary forms, with or without
8f10a77bbSDavid C Somayajulu  *  modification, are permitted provided that the following conditions
9f10a77bbSDavid C Somayajulu  *  are met:
10f10a77bbSDavid C Somayajulu  *
11f10a77bbSDavid C Somayajulu  *  1. Redistributions of source code must retain the above copyright
12f10a77bbSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer.
13f10a77bbSDavid C Somayajulu  *  2. Redistributions in binary form must reproduce the above copyright
14f10a77bbSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer in the
15f10a77bbSDavid C Somayajulu  *     documentation and/or other materials provided with the distribution.
16f10a77bbSDavid C Somayajulu  *
17f10a77bbSDavid C Somayajulu  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18f10a77bbSDavid C Somayajulu  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19f10a77bbSDavid C Somayajulu  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20f10a77bbSDavid C Somayajulu  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21f10a77bbSDavid C Somayajulu  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22f10a77bbSDavid C Somayajulu  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23f10a77bbSDavid C Somayajulu  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24f10a77bbSDavid C Somayajulu  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25f10a77bbSDavid C Somayajulu  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26f10a77bbSDavid C Somayajulu  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27f10a77bbSDavid C Somayajulu  *  POSSIBILITY OF SUCH DAMAGE.
28f10a77bbSDavid C Somayajulu  */
29f10a77bbSDavid C Somayajulu 
30f10a77bbSDavid C Somayajulu /*
31f10a77bbSDavid C Somayajulu  * File: ql_hw.c
32f10a77bbSDavid C Somayajulu  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
33453130d9SPedro F. Giffuni  * Content: Contains Hardware dependent functions
34f10a77bbSDavid C Somayajulu  */
35f10a77bbSDavid C Somayajulu 
36f10a77bbSDavid C Somayajulu #include <sys/cdefs.h>
37f10a77bbSDavid C Somayajulu __FBSDID("$FreeBSD$");
38f10a77bbSDavid C Somayajulu 
39f10a77bbSDavid C Somayajulu #include "ql_os.h"
40f10a77bbSDavid C Somayajulu #include "ql_hw.h"
41f10a77bbSDavid C Somayajulu #include "ql_def.h"
42f10a77bbSDavid C Somayajulu #include "ql_inline.h"
43f10a77bbSDavid C Somayajulu #include "ql_ver.h"
44f10a77bbSDavid C Somayajulu #include "ql_glbl.h"
45f10a77bbSDavid C Somayajulu #include "ql_dbg.h"
466a62bec0SDavid C Somayajulu #include "ql_minidump.h"
47f10a77bbSDavid C Somayajulu 
48f10a77bbSDavid C Somayajulu /*
49f10a77bbSDavid C Somayajulu  * Static Functions
50f10a77bbSDavid C Somayajulu  */
51f10a77bbSDavid C Somayajulu 
52f10a77bbSDavid C Somayajulu static void qla_del_rcv_cntxt(qla_host_t *ha);
53f10a77bbSDavid C Somayajulu static int qla_init_rcv_cntxt(qla_host_t *ha);
54b65c0c07SDavid C Somayajulu static int qla_del_xmt_cntxt(qla_host_t *ha);
55f10a77bbSDavid C Somayajulu static int qla_init_xmt_cntxt(qla_host_t *ha);
56f10a77bbSDavid C Somayajulu static int qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
57f10a77bbSDavid C Somayajulu 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause);
5835291c22SDavid C Somayajulu static int qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx,
5935291c22SDavid C Somayajulu 	uint32_t num_intrs, uint32_t create);
60f10a77bbSDavid C Somayajulu static int qla_config_rss(qla_host_t *ha, uint16_t cntxt_id);
61f10a77bbSDavid C Somayajulu static int qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id,
6235291c22SDavid C Somayajulu 	int tenable, int rcv);
63f10a77bbSDavid C Somayajulu static int qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode);
64f10a77bbSDavid C Somayajulu static int qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id);
65f10a77bbSDavid C Somayajulu 
66f10a77bbSDavid C Somayajulu static int qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd,
67f10a77bbSDavid C Somayajulu 		uint8_t *hdr);
68f10a77bbSDavid C Somayajulu static int qla_hw_add_all_mcast(qla_host_t *ha);
6935291c22SDavid C Somayajulu static int qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds);
7035291c22SDavid C Somayajulu 
7135291c22SDavid C Somayajulu static int qla_init_nic_func(qla_host_t *ha);
7235291c22SDavid C Somayajulu static int qla_stop_nic_func(qla_host_t *ha);
7335291c22SDavid C Somayajulu static int qla_query_fw_dcbx_caps(qla_host_t *ha);
7435291c22SDavid C Somayajulu static int qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits);
7535291c22SDavid C Somayajulu static int qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits);
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 #ifdef QL_DBG
82f10a77bbSDavid C Somayajulu 
83f10a77bbSDavid C Somayajulu static void
84f10a77bbSDavid C Somayajulu qla_stop_pegs(qla_host_t *ha)
85f10a77bbSDavid C Somayajulu {
86f10a77bbSDavid C Somayajulu         uint32_t val = 1;
87f10a77bbSDavid C Somayajulu 
88f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0);
89f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0);
90f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0);
91f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0);
92f10a77bbSDavid C Somayajulu         ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0);
93f10a77bbSDavid C Somayajulu         device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__);
94f10a77bbSDavid C Somayajulu }
95f10a77bbSDavid C Somayajulu 
96f10a77bbSDavid C Somayajulu static int
97f10a77bbSDavid C Somayajulu qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)
98f10a77bbSDavid C Somayajulu {
99f10a77bbSDavid C Somayajulu 	int err, ret = 0;
100f10a77bbSDavid C Somayajulu 	qla_host_t *ha;
101f10a77bbSDavid C Somayajulu 
102f10a77bbSDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
103f10a77bbSDavid C Somayajulu 
104f10a77bbSDavid C Somayajulu 
105f10a77bbSDavid C Somayajulu 	if (err || !req->newptr)
106f10a77bbSDavid C Somayajulu 		return (err);
107f10a77bbSDavid C Somayajulu 
108f10a77bbSDavid C Somayajulu 	if (ret == 1) {
109f10a77bbSDavid C Somayajulu 		ha = (qla_host_t *)arg1;
1107fb51846SDavid C Somayajulu 		if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
111f10a77bbSDavid C Somayajulu 			qla_stop_pegs(ha);
1127fb51846SDavid C Somayajulu 			QLA_UNLOCK(ha, __func__);
1137fb51846SDavid C Somayajulu 		}
114f10a77bbSDavid C Somayajulu 	}
115f10a77bbSDavid C Somayajulu 
116f10a77bbSDavid C Somayajulu 	return err;
117f10a77bbSDavid C Somayajulu }
118f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */
119f10a77bbSDavid C Somayajulu 
12035291c22SDavid C Somayajulu static int
12135291c22SDavid C Somayajulu qla_validate_set_port_cfg_bit(uint32_t bits)
12235291c22SDavid C Somayajulu {
12335291c22SDavid C Somayajulu         if ((bits & 0xF) > 1)
12435291c22SDavid C Somayajulu                 return (-1);
12535291c22SDavid C Somayajulu 
12635291c22SDavid C Somayajulu         if (((bits >> 4) & 0xF) > 2)
12735291c22SDavid C Somayajulu                 return (-1);
12835291c22SDavid C Somayajulu 
12935291c22SDavid C Somayajulu         if (((bits >> 8) & 0xF) > 2)
13035291c22SDavid C Somayajulu                 return (-1);
13135291c22SDavid C Somayajulu 
13235291c22SDavid C Somayajulu         return (0);
13335291c22SDavid C Somayajulu }
13435291c22SDavid C Somayajulu 
13535291c22SDavid C Somayajulu static int
13635291c22SDavid C Somayajulu qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS)
13735291c22SDavid C Somayajulu {
13835291c22SDavid C Somayajulu         int err, ret = 0;
13935291c22SDavid C Somayajulu         qla_host_t *ha;
14035291c22SDavid C Somayajulu         uint32_t cfg_bits;
14135291c22SDavid C Somayajulu 
14235291c22SDavid C Somayajulu         err = sysctl_handle_int(oidp, &ret, 0, req);
14335291c22SDavid C Somayajulu 
14435291c22SDavid C Somayajulu         if (err || !req->newptr)
14535291c22SDavid C Somayajulu                 return (err);
14635291c22SDavid C Somayajulu 
14735291c22SDavid C Somayajulu 	ha = (qla_host_t *)arg1;
14835291c22SDavid C Somayajulu 
1497fb51846SDavid C Somayajulu         if ((qla_validate_set_port_cfg_bit((uint32_t)ret) == 0)) {
1507fb51846SDavid C Somayajulu 
15135291c22SDavid C Somayajulu                 err = qla_get_port_config(ha, &cfg_bits);
15235291c22SDavid C Somayajulu 
15335291c22SDavid C Somayajulu                 if (err)
15435291c22SDavid C Somayajulu                         goto qla_sysctl_set_port_cfg_exit;
15535291c22SDavid C Somayajulu 
15635291c22SDavid C Somayajulu                 if (ret & 0x1) {
15735291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_DCBX_ENABLE;
15835291c22SDavid C Somayajulu                 } else {
15935291c22SDavid C Somayajulu                         cfg_bits &= ~Q8_PORT_CFG_BITS_DCBX_ENABLE;
16035291c22SDavid C Somayajulu                 }
16135291c22SDavid C Somayajulu 
16235291c22SDavid C Somayajulu                 ret = ret >> 4;
16335291c22SDavid C Somayajulu                 cfg_bits &= ~Q8_PORT_CFG_BITS_PAUSE_CFG_MASK;
16435291c22SDavid C Somayajulu 
16535291c22SDavid C Somayajulu                 if ((ret & 0xF) == 0) {
16635291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_DISABLED;
16735291c22SDavid C Somayajulu                 } else if ((ret & 0xF) == 1){
16835291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_STD;
16935291c22SDavid C Somayajulu                 } else {
17035291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_PPM;
17135291c22SDavid C Somayajulu                 }
17235291c22SDavid C Somayajulu 
17335291c22SDavid C Somayajulu                 ret = ret >> 4;
17435291c22SDavid C Somayajulu                 cfg_bits &= ~Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK;
17535291c22SDavid C Somayajulu 
17635291c22SDavid C Somayajulu                 if (ret == 0) {
17735291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT_RCV;
17835291c22SDavid C Somayajulu                 } else if (ret == 1){
17935291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT;
18035291c22SDavid C Somayajulu                 } else {
18135291c22SDavid C Somayajulu                         cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_RCV;
18235291c22SDavid C Somayajulu                 }
18335291c22SDavid C Somayajulu 
1847fb51846SDavid C Somayajulu 		if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
18535291c22SDavid C Somayajulu                 	err = qla_set_port_config(ha, cfg_bits);
1867fb51846SDavid C Somayajulu 			QLA_UNLOCK(ha, __func__);
18735291c22SDavid C Somayajulu 		} else {
1887fb51846SDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: failed\n", __func__);
1897fb51846SDavid C Somayajulu 		}
1907fb51846SDavid C Somayajulu         } else {
1917fb51846SDavid C Somayajulu 		if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
19235291c22SDavid C Somayajulu                 	err = qla_get_port_config(ha, &cfg_bits);
1937fb51846SDavid C Somayajulu 			QLA_UNLOCK(ha, __func__);
1947fb51846SDavid C Somayajulu 		} else {
1957fb51846SDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: failed\n", __func__);
1967fb51846SDavid C Somayajulu 		}
19735291c22SDavid C Somayajulu         }
19835291c22SDavid C Somayajulu 
19935291c22SDavid C Somayajulu qla_sysctl_set_port_cfg_exit:
20035291c22SDavid C Somayajulu         return err;
20135291c22SDavid C Somayajulu }
20235291c22SDavid C Somayajulu 
20300caeec7SDavid C Somayajulu static int
20400caeec7SDavid C Somayajulu qla_sysctl_set_cam_search_mode(SYSCTL_HANDLER_ARGS)
20500caeec7SDavid C Somayajulu {
20600caeec7SDavid C Somayajulu 	int err, ret = 0;
20700caeec7SDavid C Somayajulu 	qla_host_t *ha;
20800caeec7SDavid C Somayajulu 
20900caeec7SDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
21000caeec7SDavid C Somayajulu 
21100caeec7SDavid C Somayajulu 	if (err || !req->newptr)
21200caeec7SDavid C Somayajulu 		return (err);
21300caeec7SDavid C Somayajulu 
21400caeec7SDavid C Somayajulu 	ha = (qla_host_t *)arg1;
21500caeec7SDavid C Somayajulu 
21600caeec7SDavid C Somayajulu 	if ((ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_INTERNAL) ||
21700caeec7SDavid C Somayajulu 		(ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_AUTO)) {
2187fb51846SDavid C Somayajulu 
2197fb51846SDavid C Somayajulu 		if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
22000caeec7SDavid C Somayajulu 			err = qla_set_cam_search_mode(ha, (uint32_t)ret);
2217fb51846SDavid C Somayajulu 			QLA_UNLOCK(ha, __func__);
2227fb51846SDavid C Somayajulu 		} else {
2237fb51846SDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: failed\n", __func__);
2247fb51846SDavid C Somayajulu 		}
2257fb51846SDavid C Somayajulu 
22600caeec7SDavid C Somayajulu 	} else {
22700caeec7SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: ret = %d\n", __func__, ret);
22800caeec7SDavid C Somayajulu 	}
22900caeec7SDavid C Somayajulu 
23000caeec7SDavid C Somayajulu 	return (err);
23100caeec7SDavid C Somayajulu }
23200caeec7SDavid C Somayajulu 
23300caeec7SDavid C Somayajulu static int
23400caeec7SDavid C Somayajulu qla_sysctl_get_cam_search_mode(SYSCTL_HANDLER_ARGS)
23500caeec7SDavid C Somayajulu {
23600caeec7SDavid C Somayajulu 	int err, ret = 0;
23700caeec7SDavid C Somayajulu 	qla_host_t *ha;
23800caeec7SDavid C Somayajulu 
23900caeec7SDavid C Somayajulu 	err = sysctl_handle_int(oidp, &ret, 0, req);
24000caeec7SDavid C Somayajulu 
24100caeec7SDavid C Somayajulu 	if (err || !req->newptr)
24200caeec7SDavid C Somayajulu 		return (err);
24300caeec7SDavid C Somayajulu 
24400caeec7SDavid C Somayajulu 	ha = (qla_host_t *)arg1;
2457fb51846SDavid C Somayajulu 	if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
24600caeec7SDavid C Somayajulu 		err = qla_get_cam_search_mode(ha);
2477fb51846SDavid C Somayajulu 		QLA_UNLOCK(ha, __func__);
2487fb51846SDavid C Somayajulu 	} else {
2497fb51846SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: failed\n", __func__);
2507fb51846SDavid C Somayajulu 	}
25100caeec7SDavid C Somayajulu 
25200caeec7SDavid C Somayajulu 	return (err);
25300caeec7SDavid C Somayajulu }
25400caeec7SDavid C Somayajulu 
2557fb51846SDavid C Somayajulu static void
2567fb51846SDavid C Somayajulu qlnx_add_hw_mac_stats_sysctls(qla_host_t *ha)
2577fb51846SDavid C Somayajulu {
2587fb51846SDavid C Somayajulu         struct sysctl_ctx_list  *ctx;
2597fb51846SDavid C Somayajulu         struct sysctl_oid_list  *children;
2607fb51846SDavid C Somayajulu         struct sysctl_oid       *ctx_oid;
2617fb51846SDavid C Somayajulu 
2627fb51846SDavid C Somayajulu         ctx = device_get_sysctl_ctx(ha->pci_dev);
2637fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
2647fb51846SDavid C Somayajulu 
2657fb51846SDavid C Somayajulu         ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_mac",
2667fb51846SDavid C Somayajulu                         CTLFLAG_RD, NULL, "stats_hw_mac");
2677fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(ctx_oid);
2687fb51846SDavid C Somayajulu 
2697fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
2707fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_frames",
2717fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_frames,
2727fb51846SDavid C Somayajulu                 "xmt_frames");
2737fb51846SDavid C Somayajulu 
2747fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
2757fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_bytes",
2767fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_bytes,
2777fb51846SDavid C Somayajulu                 "xmt_frames");
2787fb51846SDavid C Somayajulu 
2797fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
2807fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_mcast_pkts",
2817fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_mcast_pkts,
2827fb51846SDavid C Somayajulu                 "xmt_mcast_pkts");
2837fb51846SDavid C Somayajulu 
2847fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
2857fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_bcast_pkts",
2867fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_bcast_pkts,
2877fb51846SDavid C Somayajulu                 "xmt_bcast_pkts");
2887fb51846SDavid C Somayajulu 
2897fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
2907fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_pause_frames",
2917fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_pause_frames,
2927fb51846SDavid C Somayajulu                 "xmt_pause_frames");
2937fb51846SDavid C Somayajulu 
2947fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
2957fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_cntrl_pkts",
2967fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_cntrl_pkts,
2977fb51846SDavid C Somayajulu                 "xmt_cntrl_pkts");
2987fb51846SDavid C Somayajulu 
2997fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3007fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_pkt_lt_64bytes",
3017fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_64bytes,
3027fb51846SDavid C Somayajulu                 "xmt_pkt_lt_64bytes");
3037fb51846SDavid C Somayajulu 
3047fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3057fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_pkt_lt_127bytes",
3067fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_127bytes,
3077fb51846SDavid C Somayajulu                 "xmt_pkt_lt_127bytes");
3087fb51846SDavid C Somayajulu 
3097fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3107fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_pkt_lt_255bytes",
3117fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_255bytes,
3127fb51846SDavid C Somayajulu                 "xmt_pkt_lt_255bytes");
3137fb51846SDavid C Somayajulu 
3147fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3157fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_pkt_lt_511bytes",
3167fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_511bytes,
3177fb51846SDavid C Somayajulu                 "xmt_pkt_lt_511bytes");
3187fb51846SDavid C Somayajulu 
3197fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3207fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_pkt_lt_1023bytes",
3217fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_1023bytes,
3227fb51846SDavid C Somayajulu                 "xmt_pkt_lt_1023bytes");
3237fb51846SDavid C Somayajulu 
3247fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3257fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_pkt_lt_1518bytes",
3267fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_1518bytes,
3277fb51846SDavid C Somayajulu                 "xmt_pkt_lt_1518bytes");
3287fb51846SDavid C Somayajulu 
3297fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3307fb51846SDavid C Somayajulu                 OID_AUTO, "xmt_pkt_gt_1518bytes",
3317fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.xmt_pkt_gt_1518bytes,
3327fb51846SDavid C Somayajulu                 "xmt_pkt_gt_1518bytes");
3337fb51846SDavid C Somayajulu 
3347fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3357fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_frames",
3367fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_frames,
3377fb51846SDavid C Somayajulu                 "rcv_frames");
3387fb51846SDavid C Somayajulu 
3397fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3407fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_bytes",
3417fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_bytes,
3427fb51846SDavid C Somayajulu                 "rcv_bytes");
3437fb51846SDavid C Somayajulu 
3447fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3457fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_mcast_pkts",
3467fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_mcast_pkts,
3477fb51846SDavid C Somayajulu                 "rcv_mcast_pkts");
3487fb51846SDavid C Somayajulu 
3497fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3507fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_bcast_pkts",
3517fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_bcast_pkts,
3527fb51846SDavid C Somayajulu                 "rcv_bcast_pkts");
3537fb51846SDavid C Somayajulu 
3547fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3557fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_pause_frames",
3567fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_pause_frames,
3577fb51846SDavid C Somayajulu                 "rcv_pause_frames");
3587fb51846SDavid C Somayajulu 
3597fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3607fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_cntrl_pkts",
3617fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_cntrl_pkts,
3627fb51846SDavid C Somayajulu                 "rcv_cntrl_pkts");
3637fb51846SDavid C Somayajulu 
3647fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3657fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_pkt_lt_64bytes",
3667fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_64bytes,
3677fb51846SDavid C Somayajulu                 "rcv_pkt_lt_64bytes");
3687fb51846SDavid C Somayajulu 
3697fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3707fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_pkt_lt_127bytes",
3717fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_127bytes,
3727fb51846SDavid C Somayajulu                 "rcv_pkt_lt_127bytes");
3737fb51846SDavid C Somayajulu 
3747fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3757fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_pkt_lt_255bytes",
3767fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_255bytes,
3777fb51846SDavid C Somayajulu                 "rcv_pkt_lt_255bytes");
3787fb51846SDavid C Somayajulu 
3797fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3807fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_pkt_lt_511bytes",
3817fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_511bytes,
3827fb51846SDavid C Somayajulu                 "rcv_pkt_lt_511bytes");
3837fb51846SDavid C Somayajulu 
3847fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3857fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_pkt_lt_1023bytes",
3867fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_1023bytes,
3877fb51846SDavid C Somayajulu                 "rcv_pkt_lt_1023bytes");
3887fb51846SDavid C Somayajulu 
3897fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3907fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_pkt_lt_1518bytes",
3917fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_1518bytes,
3927fb51846SDavid C Somayajulu                 "rcv_pkt_lt_1518bytes");
3937fb51846SDavid C Somayajulu 
3947fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
3957fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_pkt_gt_1518bytes",
3967fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_pkt_gt_1518bytes,
3977fb51846SDavid C Somayajulu                 "rcv_pkt_gt_1518bytes");
3987fb51846SDavid C Somayajulu 
3997fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4007fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_len_error",
4017fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_len_error,
4027fb51846SDavid C Somayajulu                 "rcv_len_error");
4037fb51846SDavid C Somayajulu 
4047fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4057fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_len_small",
4067fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_len_small,
4077fb51846SDavid C Somayajulu                 "rcv_len_small");
4087fb51846SDavid C Somayajulu 
4097fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4107fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_len_large",
4117fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_len_large,
4127fb51846SDavid C Somayajulu                 "rcv_len_large");
4137fb51846SDavid C Somayajulu 
4147fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4157fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_jabber",
4167fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_jabber,
4177fb51846SDavid C Somayajulu                 "rcv_jabber");
4187fb51846SDavid C Somayajulu 
4197fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4207fb51846SDavid C Somayajulu                 OID_AUTO, "rcv_dropped",
4217fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.rcv_dropped,
4227fb51846SDavid C Somayajulu                 "rcv_dropped");
4237fb51846SDavid C Somayajulu 
4247fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4257fb51846SDavid C Somayajulu                 OID_AUTO, "fcs_error",
4267fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.fcs_error,
4277fb51846SDavid C Somayajulu                 "fcs_error");
4287fb51846SDavid C Somayajulu 
4297fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4307fb51846SDavid C Somayajulu                 OID_AUTO, "align_error",
4317fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.align_error,
4327fb51846SDavid C Somayajulu                 "align_error");
4337fb51846SDavid C Somayajulu 
4347fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4357fb51846SDavid C Somayajulu                 OID_AUTO, "eswitched_frames",
4367fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.eswitched_frames,
4377fb51846SDavid C Somayajulu                 "eswitched_frames");
4387fb51846SDavid C Somayajulu 
4397fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4407fb51846SDavid C Somayajulu                 OID_AUTO, "eswitched_bytes",
4417fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.eswitched_bytes,
4427fb51846SDavid C Somayajulu                 "eswitched_bytes");
4437fb51846SDavid C Somayajulu 
4447fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4457fb51846SDavid C Somayajulu                 OID_AUTO, "eswitched_mcast_frames",
4467fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.eswitched_mcast_frames,
4477fb51846SDavid C Somayajulu                 "eswitched_mcast_frames");
4487fb51846SDavid C Somayajulu 
4497fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4507fb51846SDavid C Somayajulu                 OID_AUTO, "eswitched_bcast_frames",
4517fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.eswitched_bcast_frames,
4527fb51846SDavid C Somayajulu                 "eswitched_bcast_frames");
4537fb51846SDavid C Somayajulu 
4547fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4557fb51846SDavid C Somayajulu                 OID_AUTO, "eswitched_ucast_frames",
4567fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.eswitched_ucast_frames,
4577fb51846SDavid C Somayajulu                 "eswitched_ucast_frames");
4587fb51846SDavid C Somayajulu 
4597fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4607fb51846SDavid C Somayajulu                 OID_AUTO, "eswitched_err_free_frames",
4617fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.eswitched_err_free_frames,
4627fb51846SDavid C Somayajulu                 "eswitched_err_free_frames");
4637fb51846SDavid C Somayajulu 
4647fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4657fb51846SDavid C Somayajulu                 OID_AUTO, "eswitched_err_free_bytes",
4667fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.mac.eswitched_err_free_bytes,
4677fb51846SDavid C Somayajulu                 "eswitched_err_free_bytes");
4687fb51846SDavid C Somayajulu 
4697fb51846SDavid C Somayajulu 	return;
4707fb51846SDavid C Somayajulu }
4717fb51846SDavid C Somayajulu 
4727fb51846SDavid C Somayajulu static void
4737fb51846SDavid C Somayajulu qlnx_add_hw_rcv_stats_sysctls(qla_host_t *ha)
4747fb51846SDavid C Somayajulu {
4757fb51846SDavid C Somayajulu         struct sysctl_ctx_list  *ctx;
4767fb51846SDavid C Somayajulu         struct sysctl_oid_list  *children;
4777fb51846SDavid C Somayajulu         struct sysctl_oid       *ctx_oid;
4787fb51846SDavid C Somayajulu 
4797fb51846SDavid C Somayajulu         ctx = device_get_sysctl_ctx(ha->pci_dev);
4807fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
4817fb51846SDavid C Somayajulu 
4827fb51846SDavid C Somayajulu         ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_rcv",
4837fb51846SDavid C Somayajulu                         CTLFLAG_RD, NULL, "stats_hw_rcv");
4847fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(ctx_oid);
4857fb51846SDavid C Somayajulu 
4867fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4877fb51846SDavid C Somayajulu                 OID_AUTO, "total_bytes",
4887fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.total_bytes,
4897fb51846SDavid C Somayajulu                 "total_bytes");
4907fb51846SDavid C Somayajulu 
4917fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4927fb51846SDavid C Somayajulu                 OID_AUTO, "total_pkts",
4937fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.total_pkts,
4947fb51846SDavid C Somayajulu                 "total_pkts");
4957fb51846SDavid C Somayajulu 
4967fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
4977fb51846SDavid C Somayajulu                 OID_AUTO, "lro_pkt_count",
4987fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.lro_pkt_count,
4997fb51846SDavid C Somayajulu                 "lro_pkt_count");
5007fb51846SDavid C Somayajulu 
5017fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5027fb51846SDavid C Somayajulu                 OID_AUTO, "sw_pkt_count",
5037fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.sw_pkt_count,
5047fb51846SDavid C Somayajulu                 "sw_pkt_count");
5057fb51846SDavid C Somayajulu 
5067fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5077fb51846SDavid C Somayajulu                 OID_AUTO, "ip_chksum_err",
5087fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.ip_chksum_err,
5097fb51846SDavid C Somayajulu                 "ip_chksum_err");
5107fb51846SDavid C Somayajulu 
5117fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5127fb51846SDavid C Somayajulu                 OID_AUTO, "pkts_wo_acntxts",
5137fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.pkts_wo_acntxts,
5147fb51846SDavid C Somayajulu                 "pkts_wo_acntxts");
5157fb51846SDavid C Somayajulu 
5167fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5177fb51846SDavid C Somayajulu                 OID_AUTO, "pkts_dropped_no_sds_card",
5187fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_sds_card,
5197fb51846SDavid C Somayajulu                 "pkts_dropped_no_sds_card");
5207fb51846SDavid C Somayajulu 
5217fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5227fb51846SDavid C Somayajulu                 OID_AUTO, "pkts_dropped_no_sds_host",
5237fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_sds_host,
5247fb51846SDavid C Somayajulu                 "pkts_dropped_no_sds_host");
5257fb51846SDavid C Somayajulu 
5267fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5277fb51846SDavid C Somayajulu                 OID_AUTO, "oversized_pkts",
5287fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.oversized_pkts,
5297fb51846SDavid C Somayajulu                 "oversized_pkts");
5307fb51846SDavid C Somayajulu 
5317fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5327fb51846SDavid C Somayajulu                 OID_AUTO, "pkts_dropped_no_rds",
5337fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_rds,
5347fb51846SDavid C Somayajulu                 "pkts_dropped_no_rds");
5357fb51846SDavid C Somayajulu 
5367fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5377fb51846SDavid C Somayajulu                 OID_AUTO, "unxpctd_mcast_pkts",
5387fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.unxpctd_mcast_pkts,
5397fb51846SDavid C Somayajulu                 "unxpctd_mcast_pkts");
5407fb51846SDavid C Somayajulu 
5417fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5427fb51846SDavid C Somayajulu                 OID_AUTO, "re1_fbq_error",
5437fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.re1_fbq_error,
5447fb51846SDavid C Somayajulu                 "re1_fbq_error");
5457fb51846SDavid C Somayajulu 
5467fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5477fb51846SDavid C Somayajulu                 OID_AUTO, "invalid_mac_addr",
5487fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.invalid_mac_addr,
5497fb51846SDavid C Somayajulu                 "invalid_mac_addr");
5507fb51846SDavid C Somayajulu 
5517fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5527fb51846SDavid C Somayajulu                 OID_AUTO, "rds_prime_trys",
5537fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.rds_prime_trys,
5547fb51846SDavid C Somayajulu                 "rds_prime_trys");
5557fb51846SDavid C Somayajulu 
5567fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5577fb51846SDavid C Somayajulu                 OID_AUTO, "rds_prime_success",
5587fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.rds_prime_success,
5597fb51846SDavid C Somayajulu                 "rds_prime_success");
5607fb51846SDavid C Somayajulu 
5617fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5627fb51846SDavid C Somayajulu                 OID_AUTO, "lro_flows_added",
5637fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.lro_flows_added,
5647fb51846SDavid C Somayajulu                 "lro_flows_added");
5657fb51846SDavid C Somayajulu 
5667fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5677fb51846SDavid C Somayajulu                 OID_AUTO, "lro_flows_deleted",
5687fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.lro_flows_deleted,
5697fb51846SDavid C Somayajulu                 "lro_flows_deleted");
5707fb51846SDavid C Somayajulu 
5717fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5727fb51846SDavid C Somayajulu                 OID_AUTO, "lro_flows_active",
5737fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.lro_flows_active,
5747fb51846SDavid C Somayajulu                 "lro_flows_active");
5757fb51846SDavid C Somayajulu 
5767fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5777fb51846SDavid C Somayajulu                 OID_AUTO, "pkts_droped_unknown",
5787fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.pkts_droped_unknown,
5797fb51846SDavid C Somayajulu                 "pkts_droped_unknown");
5807fb51846SDavid C Somayajulu 
5817fb51846SDavid C Somayajulu         SYSCTL_ADD_QUAD(ctx, children,
5827fb51846SDavid C Somayajulu                 OID_AUTO, "pkts_cnt_oversized",
5837fb51846SDavid C Somayajulu                 CTLFLAG_RD, &ha->hw.rcv.pkts_cnt_oversized,
5847fb51846SDavid C Somayajulu                 "pkts_cnt_oversized");
5857fb51846SDavid C Somayajulu 
5867fb51846SDavid C Somayajulu 	return;
5877fb51846SDavid C Somayajulu }
5887fb51846SDavid C Somayajulu 
5897fb51846SDavid C Somayajulu static void
5907fb51846SDavid C Somayajulu qlnx_add_hw_xmt_stats_sysctls(qla_host_t *ha)
5917fb51846SDavid C Somayajulu {
5927fb51846SDavid C Somayajulu         struct sysctl_ctx_list  *ctx;
5937fb51846SDavid C Somayajulu         struct sysctl_oid_list  *children;
5947fb51846SDavid C Somayajulu         struct sysctl_oid_list  *node_children;
5957fb51846SDavid C Somayajulu         struct sysctl_oid       *ctx_oid;
5967fb51846SDavid C Somayajulu         int                     i;
5977fb51846SDavid C Somayajulu         uint8_t                 name_str[16];
5987fb51846SDavid C Somayajulu 
5997fb51846SDavid C Somayajulu         ctx = device_get_sysctl_ctx(ha->pci_dev);
6007fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
6017fb51846SDavid C Somayajulu 
6027fb51846SDavid C Somayajulu         ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_xmt",
6037fb51846SDavid C Somayajulu                         CTLFLAG_RD, NULL, "stats_hw_xmt");
6047fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(ctx_oid);
6057fb51846SDavid C Somayajulu 
6067fb51846SDavid C Somayajulu         for (i = 0; i < ha->hw.num_tx_rings; i++) {
6077fb51846SDavid C Somayajulu 
6087fb51846SDavid C Somayajulu                 bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
6097fb51846SDavid C Somayajulu                 snprintf(name_str, sizeof(name_str), "%d", i);
6107fb51846SDavid C Somayajulu 
6117fb51846SDavid C Somayajulu                 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
6127fb51846SDavid C Somayajulu                         CTLFLAG_RD, NULL, name_str);
6137fb51846SDavid C Somayajulu                 node_children = SYSCTL_CHILDREN(ctx_oid);
6147fb51846SDavid C Somayajulu 
6157fb51846SDavid C Somayajulu                 /* Tx Related */
6167fb51846SDavid C Somayajulu 
6177fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
6187fb51846SDavid C Somayajulu 			OID_AUTO, "total_bytes",
6197fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->hw.xmt[i].total_bytes,
6207fb51846SDavid C Somayajulu                         "total_bytes");
6217fb51846SDavid C Somayajulu 
6227fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
6237fb51846SDavid C Somayajulu 			OID_AUTO, "total_pkts",
6247fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->hw.xmt[i].total_pkts,
6257fb51846SDavid C Somayajulu                         "total_pkts");
6267fb51846SDavid C Somayajulu 
6277fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
6287fb51846SDavid C Somayajulu 			OID_AUTO, "errors",
6297fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->hw.xmt[i].errors,
6307fb51846SDavid C Somayajulu                         "errors");
6317fb51846SDavid C Somayajulu 
6327fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
6337fb51846SDavid C Somayajulu 			OID_AUTO, "pkts_dropped",
6347fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->hw.xmt[i].pkts_dropped,
6357fb51846SDavid C Somayajulu                         "pkts_dropped");
6367fb51846SDavid C Somayajulu 
6377fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
6387fb51846SDavid C Somayajulu 			OID_AUTO, "switch_pkts",
6397fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->hw.xmt[i].switch_pkts,
6407fb51846SDavid C Somayajulu                         "switch_pkts");
6417fb51846SDavid C Somayajulu 
6427fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
6437fb51846SDavid C Somayajulu 			OID_AUTO, "num_buffers",
6447fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->hw.xmt[i].num_buffers,
6457fb51846SDavid C Somayajulu                         "num_buffers");
6467fb51846SDavid C Somayajulu 	}
6477fb51846SDavid C Somayajulu 
6487fb51846SDavid C Somayajulu 	return;
6497fb51846SDavid C Somayajulu }
6507fb51846SDavid C Somayajulu 
6517fb51846SDavid C Somayajulu static void
652b65c0c07SDavid C Somayajulu qlnx_add_hw_mbx_cmpl_stats_sysctls(qla_host_t *ha)
653b65c0c07SDavid C Somayajulu {
654b65c0c07SDavid C Somayajulu         struct sysctl_ctx_list  *ctx;
655b65c0c07SDavid C Somayajulu         struct sysctl_oid_list  *node_children;
656b65c0c07SDavid C Somayajulu 
657b65c0c07SDavid C Somayajulu         ctx = device_get_sysctl_ctx(ha->pci_dev);
658b65c0c07SDavid C Somayajulu         node_children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
659b65c0c07SDavid C Somayajulu 
660b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
661b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_lt_200ms",
662b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[0],
663b65c0c07SDavid C Somayajulu 		"mbx_completion_time_lt_200ms");
664b65c0c07SDavid C Somayajulu 
665b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
666b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_200ms_400ms",
667b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[1],
668b65c0c07SDavid C Somayajulu 		"mbx_completion_time_200ms_400ms");
669b65c0c07SDavid C Somayajulu 
670b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
671b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_400ms_600ms",
672b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[2],
673b65c0c07SDavid C Somayajulu 		"mbx_completion_time_400ms_600ms");
674b65c0c07SDavid C Somayajulu 
675b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
676b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_600ms_800ms",
677b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[3],
678b65c0c07SDavid C Somayajulu 		"mbx_completion_time_600ms_800ms");
679b65c0c07SDavid C Somayajulu 
680b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
681b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_800ms_1000ms",
682b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[4],
683b65c0c07SDavid C Somayajulu 		"mbx_completion_time_800ms_1000ms");
684b65c0c07SDavid C Somayajulu 
685b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
686b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_1000ms_1200ms",
687b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[5],
688b65c0c07SDavid C Somayajulu 		"mbx_completion_time_1000ms_1200ms");
689b65c0c07SDavid C Somayajulu 
690b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
691b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_1200ms_1400ms",
692b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[6],
693b65c0c07SDavid C Somayajulu 		"mbx_completion_time_1200ms_1400ms");
694b65c0c07SDavid C Somayajulu 
695b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
696b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_1400ms_1600ms",
697b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[7],
698b65c0c07SDavid C Somayajulu 		"mbx_completion_time_1400ms_1600ms");
699b65c0c07SDavid C Somayajulu 
700b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
701b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_1600ms_1800ms",
702b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[8],
703b65c0c07SDavid C Somayajulu 		"mbx_completion_time_1600ms_1800ms");
704b65c0c07SDavid C Somayajulu 
705b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
706b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_1800ms_2000ms",
707b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[9],
708b65c0c07SDavid C Somayajulu 		"mbx_completion_time_1800ms_2000ms");
709b65c0c07SDavid C Somayajulu 
710b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
711b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_2000ms_2200ms",
712b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[10],
713b65c0c07SDavid C Somayajulu 		"mbx_completion_time_2000ms_2200ms");
714b65c0c07SDavid C Somayajulu 
715b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
716b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_2200ms_2400ms",
717b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[11],
718b65c0c07SDavid C Somayajulu 		"mbx_completion_time_2200ms_2400ms");
719b65c0c07SDavid C Somayajulu 
720b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
721b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_2400ms_2600ms",
722b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[12],
723b65c0c07SDavid C Somayajulu 		"mbx_completion_time_2400ms_2600ms");
724b65c0c07SDavid C Somayajulu 
725b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
726b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_2600ms_2800ms",
727b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[13],
728b65c0c07SDavid C Somayajulu 		"mbx_completion_time_2600ms_2800ms");
729b65c0c07SDavid C Somayajulu 
730b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
731b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_2800ms_3000ms",
732b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[14],
733b65c0c07SDavid C Somayajulu 		"mbx_completion_time_2800ms_3000ms");
734b65c0c07SDavid C Somayajulu 
735b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
736b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_3000ms_4000ms",
737b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[15],
738b65c0c07SDavid C Somayajulu 		"mbx_completion_time_3000ms_4000ms");
739b65c0c07SDavid C Somayajulu 
740b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
741b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_time_4000ms_5000ms",
742b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[16],
743b65c0c07SDavid C Somayajulu 		"mbx_completion_time_4000ms_5000ms");
744b65c0c07SDavid C Somayajulu 
745b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
746b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_host_mbx_cntrl_timeout",
747b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[17],
748b65c0c07SDavid C Somayajulu 		"mbx_completion_host_mbx_cntrl_timeout");
749b65c0c07SDavid C Somayajulu 
750b65c0c07SDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, node_children,
751b65c0c07SDavid C Somayajulu 		OID_AUTO, "mbx_completion_fw_mbx_cntrl_timeout",
752b65c0c07SDavid C Somayajulu 		CTLFLAG_RD, &ha->hw.mbx_comp_msecs[18],
753b65c0c07SDavid C Somayajulu 		"mbx_completion_fw_mbx_cntrl_timeout");
754b65c0c07SDavid C Somayajulu 	return;
755b65c0c07SDavid C Somayajulu }
756b65c0c07SDavid C Somayajulu 
757b65c0c07SDavid C Somayajulu static void
7587fb51846SDavid C Somayajulu qlnx_add_hw_stats_sysctls(qla_host_t *ha)
7597fb51846SDavid C Somayajulu {
7607fb51846SDavid C Somayajulu 	qlnx_add_hw_mac_stats_sysctls(ha);
7617fb51846SDavid C Somayajulu 	qlnx_add_hw_rcv_stats_sysctls(ha);
7627fb51846SDavid C Somayajulu 	qlnx_add_hw_xmt_stats_sysctls(ha);
763b65c0c07SDavid C Somayajulu 	qlnx_add_hw_mbx_cmpl_stats_sysctls(ha);
7647fb51846SDavid C Somayajulu 
7657fb51846SDavid C Somayajulu 	return;
7667fb51846SDavid C Somayajulu }
7677fb51846SDavid C Somayajulu 
7687fb51846SDavid C Somayajulu static void
7697fb51846SDavid C Somayajulu qlnx_add_drvr_sds_stats(qla_host_t *ha)
7707fb51846SDavid C Somayajulu {
7717fb51846SDavid C Somayajulu         struct sysctl_ctx_list  *ctx;
7727fb51846SDavid C Somayajulu         struct sysctl_oid_list  *children;
7737fb51846SDavid C Somayajulu         struct sysctl_oid_list  *node_children;
7747fb51846SDavid C Somayajulu         struct sysctl_oid       *ctx_oid;
7757fb51846SDavid C Somayajulu         int                     i;
7767fb51846SDavid C Somayajulu         uint8_t                 name_str[16];
7777fb51846SDavid C Somayajulu 
7787fb51846SDavid C Somayajulu         ctx = device_get_sysctl_ctx(ha->pci_dev);
7797fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
7807fb51846SDavid C Somayajulu 
7817fb51846SDavid C Somayajulu         ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_sds",
7827fb51846SDavid C Somayajulu                         CTLFLAG_RD, NULL, "stats_drvr_sds");
7837fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(ctx_oid);
7847fb51846SDavid C Somayajulu 
7857fb51846SDavid C Somayajulu         for (i = 0; i < ha->hw.num_sds_rings; i++) {
7867fb51846SDavid C Somayajulu 
7877fb51846SDavid C Somayajulu                 bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
7887fb51846SDavid C Somayajulu                 snprintf(name_str, sizeof(name_str), "%d", i);
7897fb51846SDavid C Somayajulu 
7907fb51846SDavid C Somayajulu                 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
7917fb51846SDavid C Somayajulu                         CTLFLAG_RD, NULL, name_str);
7927fb51846SDavid C Somayajulu                 node_children = SYSCTL_CHILDREN(ctx_oid);
7937fb51846SDavid C Somayajulu 
7947fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
7957fb51846SDavid C Somayajulu 			OID_AUTO, "intr_count",
7967fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->hw.sds[i].intr_count,
7977fb51846SDavid C Somayajulu                         "intr_count");
7987fb51846SDavid C Somayajulu 
7997fb51846SDavid C Somayajulu                 SYSCTL_ADD_UINT(ctx, node_children,
8007fb51846SDavid C Somayajulu 			OID_AUTO, "rx_free",
8017fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->hw.sds[i].rx_free,
8027fb51846SDavid C Somayajulu 			ha->hw.sds[i].rx_free, "rx_free");
8037fb51846SDavid C Somayajulu 	}
8047fb51846SDavid C Somayajulu 
8057fb51846SDavid C Somayajulu 	return;
8067fb51846SDavid C Somayajulu }
8077fb51846SDavid C Somayajulu static void
8087fb51846SDavid C Somayajulu qlnx_add_drvr_rds_stats(qla_host_t *ha)
8097fb51846SDavid C Somayajulu {
8107fb51846SDavid C Somayajulu         struct sysctl_ctx_list  *ctx;
8117fb51846SDavid C Somayajulu         struct sysctl_oid_list  *children;
8127fb51846SDavid C Somayajulu         struct sysctl_oid_list  *node_children;
8137fb51846SDavid C Somayajulu         struct sysctl_oid       *ctx_oid;
8147fb51846SDavid C Somayajulu         int                     i;
8157fb51846SDavid C Somayajulu         uint8_t                 name_str[16];
8167fb51846SDavid C Somayajulu 
8177fb51846SDavid C Somayajulu         ctx = device_get_sysctl_ctx(ha->pci_dev);
8187fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
8197fb51846SDavid C Somayajulu 
8207fb51846SDavid C Somayajulu         ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_rds",
8217fb51846SDavid C Somayajulu                         CTLFLAG_RD, NULL, "stats_drvr_rds");
8227fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(ctx_oid);
8237fb51846SDavid C Somayajulu 
8247fb51846SDavid C Somayajulu         for (i = 0; i < ha->hw.num_rds_rings; i++) {
8257fb51846SDavid C Somayajulu 
8267fb51846SDavid C Somayajulu                 bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
8277fb51846SDavid C Somayajulu                 snprintf(name_str, sizeof(name_str), "%d", i);
8287fb51846SDavid C Somayajulu 
8297fb51846SDavid C Somayajulu                 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
8307fb51846SDavid C Somayajulu                         CTLFLAG_RD, NULL, name_str);
8317fb51846SDavid C Somayajulu                 node_children = SYSCTL_CHILDREN(ctx_oid);
8327fb51846SDavid C Somayajulu 
8337fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
8347fb51846SDavid C Somayajulu 			OID_AUTO, "count",
8357fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->hw.rds[i].count,
8367fb51846SDavid C Somayajulu                         "count");
8377fb51846SDavid C Somayajulu 
8387fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
8397fb51846SDavid C Somayajulu 			OID_AUTO, "lro_pkt_count",
8407fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->hw.rds[i].lro_pkt_count,
8417fb51846SDavid C Somayajulu                         "lro_pkt_count");
8427fb51846SDavid C Somayajulu 
8437fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
8447fb51846SDavid C Somayajulu 			OID_AUTO, "lro_bytes",
8457fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->hw.rds[i].lro_bytes,
8467fb51846SDavid C Somayajulu                         "lro_bytes");
8477fb51846SDavid C Somayajulu 	}
8487fb51846SDavid C Somayajulu 
8497fb51846SDavid C Somayajulu 	return;
8507fb51846SDavid C Somayajulu }
8517fb51846SDavid C Somayajulu 
8527fb51846SDavid C Somayajulu static void
8537fb51846SDavid C Somayajulu qlnx_add_drvr_tx_stats(qla_host_t *ha)
8547fb51846SDavid C Somayajulu {
8557fb51846SDavid C Somayajulu         struct sysctl_ctx_list  *ctx;
8567fb51846SDavid C Somayajulu         struct sysctl_oid_list  *children;
8577fb51846SDavid C Somayajulu         struct sysctl_oid_list  *node_children;
8587fb51846SDavid C Somayajulu         struct sysctl_oid       *ctx_oid;
8597fb51846SDavid C Somayajulu         int                     i;
8607fb51846SDavid C Somayajulu         uint8_t                 name_str[16];
8617fb51846SDavid C Somayajulu 
8627fb51846SDavid C Somayajulu         ctx = device_get_sysctl_ctx(ha->pci_dev);
8637fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
8647fb51846SDavid C Somayajulu 
8657fb51846SDavid C Somayajulu         ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_xmt",
8667fb51846SDavid C Somayajulu                         CTLFLAG_RD, NULL, "stats_drvr_xmt");
8677fb51846SDavid C Somayajulu         children = SYSCTL_CHILDREN(ctx_oid);
8687fb51846SDavid C Somayajulu 
8697fb51846SDavid C Somayajulu         for (i = 0; i < ha->hw.num_tx_rings; i++) {
8707fb51846SDavid C Somayajulu 
8717fb51846SDavid C Somayajulu                 bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
8727fb51846SDavid C Somayajulu                 snprintf(name_str, sizeof(name_str), "%d", i);
8737fb51846SDavid C Somayajulu 
8747fb51846SDavid C Somayajulu                 ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
8757fb51846SDavid C Somayajulu                         CTLFLAG_RD, NULL, name_str);
8767fb51846SDavid C Somayajulu                 node_children = SYSCTL_CHILDREN(ctx_oid);
8777fb51846SDavid C Somayajulu 
8787fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
8797fb51846SDavid C Somayajulu 			OID_AUTO, "count",
8807fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->tx_ring[i].count,
8817fb51846SDavid C Somayajulu                         "count");
8827fb51846SDavid C Somayajulu 
8837fb51846SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV
8847fb51846SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
8857fb51846SDavid C Somayajulu 			OID_AUTO, "iscsi_pkt_count",
8867fb51846SDavid C Somayajulu                         CTLFLAG_RD, &ha->tx_ring[i].iscsi_pkt_count,
8877fb51846SDavid C Somayajulu                         "iscsi_pkt_count");
8887fb51846SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
8897fb51846SDavid C Somayajulu 	}
8907fb51846SDavid C Somayajulu 
8917fb51846SDavid C Somayajulu 	return;
8927fb51846SDavid C Somayajulu }
8937fb51846SDavid C Somayajulu 
8947fb51846SDavid C Somayajulu static void
8957fb51846SDavid C Somayajulu qlnx_add_drvr_stats_sysctls(qla_host_t *ha)
8967fb51846SDavid C Somayajulu {
8977fb51846SDavid C Somayajulu 	qlnx_add_drvr_sds_stats(ha);
8987fb51846SDavid C Somayajulu 	qlnx_add_drvr_rds_stats(ha);
8997fb51846SDavid C Somayajulu 	qlnx_add_drvr_tx_stats(ha);
9007fb51846SDavid C Somayajulu 	return;
9017fb51846SDavid C Somayajulu }
90200caeec7SDavid C Somayajulu 
903f10a77bbSDavid C Somayajulu /*
904f10a77bbSDavid C Somayajulu  * Name: ql_hw_add_sysctls
905f10a77bbSDavid C Somayajulu  * Function: Add P3Plus specific sysctls
906f10a77bbSDavid C Somayajulu  */
907f10a77bbSDavid C Somayajulu void
908f10a77bbSDavid C Somayajulu ql_hw_add_sysctls(qla_host_t *ha)
909f10a77bbSDavid C Somayajulu {
910f10a77bbSDavid C Somayajulu         device_t	dev;
911f10a77bbSDavid C Somayajulu 
912f10a77bbSDavid C Somayajulu         dev = ha->pci_dev;
913f10a77bbSDavid C Somayajulu 
914f10a77bbSDavid C Somayajulu 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
915f10a77bbSDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
916f10a77bbSDavid C Somayajulu 		OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings,
917f10a77bbSDavid C Somayajulu 		ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings");
918f10a77bbSDavid C Somayajulu 
919f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
920f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
921f10a77bbSDavid C Somayajulu                 OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings,
922f10a77bbSDavid C Somayajulu 		ha->hw.num_sds_rings, "Number of Status Descriptor Rings");
923f10a77bbSDavid C Somayajulu 
924f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
925f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
926f10a77bbSDavid C Somayajulu                 OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings,
927f10a77bbSDavid C Somayajulu 		ha->hw.num_tx_rings, "Number of Transmit Rings");
928f10a77bbSDavid C Somayajulu 
929f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
930f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
931f10a77bbSDavid C Somayajulu                 OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx,
932f10a77bbSDavid C Somayajulu 		ha->txr_idx, "Tx Ring Used");
933f10a77bbSDavid C Somayajulu 
934f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
935f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
936f10a77bbSDavid C Somayajulu                 OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs,
937f10a77bbSDavid C Somayajulu 		ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt");
938f10a77bbSDavid C Somayajulu 
939f10a77bbSDavid C Somayajulu 	ha->hw.sds_cidx_thres = 32;
940f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
941f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
942f10a77bbSDavid C Somayajulu                 OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres,
943f10a77bbSDavid C Somayajulu 		ha->hw.sds_cidx_thres,
944f10a77bbSDavid C Somayajulu 		"Number of SDS entries to process before updating"
945f10a77bbSDavid C Somayajulu 		" SDS Ring Consumer Index");
946f10a77bbSDavid C Somayajulu 
947f10a77bbSDavid C Somayajulu 	ha->hw.rds_pidx_thres = 32;
948f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
949f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
950f10a77bbSDavid C Somayajulu                 OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres,
951f10a77bbSDavid C Somayajulu 		ha->hw.rds_pidx_thres,
952f10a77bbSDavid C Somayajulu 		"Number of Rcv Rings Entries to post before updating"
953f10a77bbSDavid C Somayajulu 		" RDS Ring Producer Index");
954f10a77bbSDavid C Somayajulu 
95535291c22SDavid C Somayajulu         ha->hw.rcv_intr_coalesce = (3 << 16) | 256;
956c12c5bfbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
957c12c5bfbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
95835291c22SDavid C Somayajulu                 OID_AUTO, "rcv_intr_coalesce", CTLFLAG_RW,
95935291c22SDavid C Somayajulu                 &ha->hw.rcv_intr_coalesce,
96035291c22SDavid C Somayajulu                 ha->hw.rcv_intr_coalesce,
96135291c22SDavid C Somayajulu                 "Rcv Intr Coalescing Parameters\n"
96235291c22SDavid C Somayajulu                 "\tbits 15:0 max packets\n"
96335291c22SDavid C Somayajulu                 "\tbits 31:16 max micro-seconds to wait\n"
96435291c22SDavid C Somayajulu                 "\tplease run\n"
96535291c22SDavid C Somayajulu                 "\tifconfig <if> down && ifconfig <if> up\n"
96635291c22SDavid C Somayajulu                 "\tto take effect \n");
96735291c22SDavid C Somayajulu 
96835291c22SDavid C Somayajulu         ha->hw.xmt_intr_coalesce = (64 << 16) | 64;
96935291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
97035291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
97135291c22SDavid C Somayajulu                 OID_AUTO, "xmt_intr_coalesce", CTLFLAG_RW,
97235291c22SDavid C Somayajulu                 &ha->hw.xmt_intr_coalesce,
97335291c22SDavid C Somayajulu                 ha->hw.xmt_intr_coalesce,
97435291c22SDavid C Somayajulu                 "Xmt Intr Coalescing Parameters\n"
97535291c22SDavid C Somayajulu                 "\tbits 15:0 max packets\n"
97635291c22SDavid C Somayajulu                 "\tbits 31:16 max micro-seconds to wait\n"
97735291c22SDavid C Somayajulu                 "\tplease run\n"
97835291c22SDavid C Somayajulu                 "\tifconfig <if> down && ifconfig <if> up\n"
97935291c22SDavid C Somayajulu                 "\tto take effect \n");
98035291c22SDavid C Somayajulu 
98135291c22SDavid C Somayajulu         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
98235291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
98335291c22SDavid C Somayajulu                 OID_AUTO, "port_cfg", CTLTYPE_INT | CTLFLAG_RW,
98435291c22SDavid C Somayajulu                 (void *)ha, 0,
98535291c22SDavid C Somayajulu                 qla_sysctl_port_cfg, "I",
98635291c22SDavid C Somayajulu                         "Set Port Configuration if values below "
98735291c22SDavid C Somayajulu                         "otherwise Get Port Configuration\n"
98835291c22SDavid C Somayajulu                         "\tBits 0-3 ; 1 = DCBX Enable; 0 = DCBX Disable\n"
98935291c22SDavid C Somayajulu                         "\tBits 4-7 : 0 = no pause; 1 = std ; 2 = ppm \n"
99035291c22SDavid C Somayajulu                         "\tBits 8-11: std pause cfg; 0 = xmt and rcv;"
99135291c22SDavid C Somayajulu                         " 1 = xmt only; 2 = rcv only;\n"
99235291c22SDavid C Somayajulu                 );
99335291c22SDavid C Somayajulu 
99400caeec7SDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
99500caeec7SDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
99600caeec7SDavid C Somayajulu 		OID_AUTO, "set_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW,
99700caeec7SDavid C Somayajulu 		(void *)ha, 0,
99800caeec7SDavid C Somayajulu 		qla_sysctl_set_cam_search_mode, "I",
99900caeec7SDavid C Somayajulu 			"Set CAM Search Mode"
100000caeec7SDavid C Somayajulu 			"\t 1 = search mode internal\n"
100100caeec7SDavid C Somayajulu 			"\t 2 = search mode auto\n");
100200caeec7SDavid C Somayajulu 
100300caeec7SDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
100400caeec7SDavid C Somayajulu 		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
100500caeec7SDavid C Somayajulu 		OID_AUTO, "get_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW,
100600caeec7SDavid C Somayajulu 		(void *)ha, 0,
100700caeec7SDavid C Somayajulu 		qla_sysctl_get_cam_search_mode, "I",
100800caeec7SDavid C Somayajulu 			"Get CAM Search Mode"
100900caeec7SDavid C Somayajulu 			"\t 1 = search mode internal\n"
101000caeec7SDavid C Somayajulu 			"\t 2 = search mode auto\n");
101100caeec7SDavid C Somayajulu 
101235291c22SDavid C Somayajulu         ha->hw.enable_9kb = 1;
101335291c22SDavid C Somayajulu 
101435291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
101535291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
101635291c22SDavid C Somayajulu                 OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb,
101735291c22SDavid C Somayajulu                 ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000");
1018c12c5bfbSDavid C Somayajulu 
1019a7c62c11SDavid C Somayajulu         ha->hw.enable_hw_lro = 1;
1020a7c62c11SDavid C Somayajulu 
1021a7c62c11SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1022a7c62c11SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1023a7c62c11SDavid C Somayajulu                 OID_AUTO, "enable_hw_lro", CTLFLAG_RW, &ha->hw.enable_hw_lro,
1024a7c62c11SDavid C Somayajulu                 ha->hw.enable_hw_lro, "Enable Hardware LRO; Default is true \n"
1025a7c62c11SDavid C Somayajulu 		"\t 1 : Hardware LRO if LRO is enabled\n"
1026a7c62c11SDavid C Somayajulu 		"\t 0 : Software LRO if LRO is enabled\n"
1027a7c62c11SDavid C Somayajulu 		"\t Any change requires ifconfig down/up to take effect\n"
1028a7c62c11SDavid C Somayajulu 		"\t Note that LRO may be turned off/on via ifconfig\n");
1029a7c62c11SDavid C Somayajulu 
1030b65c0c07SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1031b65c0c07SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1032b65c0c07SDavid C Somayajulu                 OID_AUTO, "sp_log_index", CTLFLAG_RW, &ha->hw.sp_log_index,
1033b65c0c07SDavid C Somayajulu                 ha->hw.sp_log_index, "sp_log_index");
1034b65c0c07SDavid C Somayajulu 
1035b65c0c07SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1036b65c0c07SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1037b65c0c07SDavid C Somayajulu                 OID_AUTO, "sp_log_stop", CTLFLAG_RW, &ha->hw.sp_log_stop,
1038b65c0c07SDavid C Somayajulu                 ha->hw.sp_log_stop, "sp_log_stop");
1039b65c0c07SDavid C Somayajulu 
1040b65c0c07SDavid C Somayajulu         ha->hw.sp_log_stop_events = 0;
1041b65c0c07SDavid C Somayajulu 
1042b65c0c07SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1043b65c0c07SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1044b65c0c07SDavid C Somayajulu                 OID_AUTO, "sp_log_stop_events", CTLFLAG_RW,
1045b65c0c07SDavid C Somayajulu 		&ha->hw.sp_log_stop_events,
1046b65c0c07SDavid C Somayajulu                 ha->hw.sp_log_stop_events, "Slow path event log is stopped"
1047b65c0c07SDavid C Somayajulu 		" when OR of the following events occur \n"
1048b65c0c07SDavid C Somayajulu 		"\t 0x01 : Heart beat Failure\n"
1049b65c0c07SDavid C Somayajulu 		"\t 0x02 : Temperature Failure\n"
1050b65c0c07SDavid C Somayajulu 		"\t 0x04 : HW Initialization Failure\n"
1051b65c0c07SDavid C Somayajulu 		"\t 0x08 : Interface Initialization Failure\n"
1052b65c0c07SDavid C Somayajulu 		"\t 0x10 : Error Recovery Failure\n");
1053b65c0c07SDavid C Somayajulu 
1054f10a77bbSDavid C Somayajulu 	ha->hw.mdump_active = 0;
1055f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1056f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1057f10a77bbSDavid C Somayajulu                 OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active,
1058f10a77bbSDavid C Somayajulu 		ha->hw.mdump_active,
10596a62bec0SDavid C Somayajulu 		"Minidump retrieval is Active");
1060f10a77bbSDavid C Somayajulu 
10616a62bec0SDavid C Somayajulu 	ha->hw.mdump_done = 0;
1062f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1063f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
10646a62bec0SDavid C Somayajulu                 OID_AUTO, "mdump_done", CTLFLAG_RW,
10656a62bec0SDavid C Somayajulu 		&ha->hw.mdump_done, ha->hw.mdump_done,
10666a62bec0SDavid C Somayajulu 		"Minidump has been done and available for retrieval");
10676a62bec0SDavid C Somayajulu 
10686a62bec0SDavid C Somayajulu 	ha->hw.mdump_capture_mask = 0xF;
10696a62bec0SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
10706a62bec0SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
10716a62bec0SDavid C Somayajulu                 OID_AUTO, "minidump_capture_mask", CTLFLAG_RW,
10726a62bec0SDavid C Somayajulu 		&ha->hw.mdump_capture_mask, ha->hw.mdump_capture_mask,
10736a62bec0SDavid C Somayajulu 		"Minidump capture mask");
1074f10a77bbSDavid C Somayajulu #ifdef QL_DBG
1075f10a77bbSDavid C Somayajulu 
1076467dcb5aSDavid C Somayajulu 	ha->err_inject = 0;
1077f10a77bbSDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1078f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1079f10a77bbSDavid C Somayajulu                 OID_AUTO, "err_inject",
1080f10a77bbSDavid C Somayajulu                 CTLFLAG_RW, &ha->err_inject, ha->err_inject,
1081f10a77bbSDavid C Somayajulu                 "Error to be injected\n"
1082f10a77bbSDavid C Somayajulu                 "\t\t\t 0: No Errors\n"
1083f10a77bbSDavid C Somayajulu                 "\t\t\t 1: rcv: rxb struct invalid\n"
1084f10a77bbSDavid C Somayajulu                 "\t\t\t 2: rcv: mp == NULL\n"
1085f10a77bbSDavid C Somayajulu                 "\t\t\t 3: lro: rxb struct invalid\n"
1086f10a77bbSDavid C Somayajulu                 "\t\t\t 4: lro: mp == NULL\n"
1087f10a77bbSDavid C Somayajulu                 "\t\t\t 5: rcv: num handles invalid\n"
1088f10a77bbSDavid C Somayajulu                 "\t\t\t 6: reg: indirect reg rd_wr failure\n"
1089f10a77bbSDavid C Somayajulu                 "\t\t\t 7: ocm: offchip memory rd_wr failure\n"
1090f10a77bbSDavid C Somayajulu                 "\t\t\t 8: mbx: mailbox command failure\n"
1091f10a77bbSDavid C Somayajulu                 "\t\t\t 9: heartbeat failure\n"
109200caeec7SDavid C Somayajulu                 "\t\t\t A: temperature failure\n"
1093971e53c9SDavid C Somayajulu 		"\t\t\t 11: m_getcl or m_getjcl failure\n"
1094971e53c9SDavid C Somayajulu 		"\t\t\t 13: Invalid Descriptor Count in SGL Receive\n"
1095971e53c9SDavid C Somayajulu 		"\t\t\t 14: Invalid Descriptor Count in LRO Receive\n"
1096971e53c9SDavid C Somayajulu 		"\t\t\t 15: peer port error recovery failure\n"
1097971e53c9SDavid C Somayajulu 		"\t\t\t 16: tx_buf[next_prod_index].mbuf != NULL\n" );
1098f10a77bbSDavid C Somayajulu 
1099f10a77bbSDavid C Somayajulu 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1100f10a77bbSDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1101f10a77bbSDavid C Somayajulu                 OID_AUTO, "peg_stop", CTLTYPE_INT | CTLFLAG_RW,
1102f10a77bbSDavid C Somayajulu                 (void *)ha, 0,
1103f10a77bbSDavid C Somayajulu                 qla_sysctl_stop_pegs, "I", "Peg Stop");
1104f10a77bbSDavid C Somayajulu 
1105f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */
1106f10a77bbSDavid C Somayajulu 
110735291c22SDavid C Somayajulu         ha->hw.user_pri_nic = 0;
110835291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
110935291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
111035291c22SDavid C Somayajulu                 OID_AUTO, "user_pri_nic", CTLFLAG_RW, &ha->hw.user_pri_nic,
111135291c22SDavid C Somayajulu                 ha->hw.user_pri_nic,
111235291c22SDavid C Somayajulu                 "VLAN Tag User Priority for Normal Ethernet Packets");
111335291c22SDavid C Somayajulu 
111435291c22SDavid C Somayajulu         ha->hw.user_pri_iscsi = 4;
111535291c22SDavid C Somayajulu         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
111635291c22SDavid C Somayajulu                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
111735291c22SDavid C Somayajulu                 OID_AUTO, "user_pri_iscsi", CTLFLAG_RW, &ha->hw.user_pri_iscsi,
111835291c22SDavid C Somayajulu                 ha->hw.user_pri_iscsi,
111935291c22SDavid C Somayajulu                 "VLAN Tag User Priority for iSCSI Packets");
112035291c22SDavid C Somayajulu 
11217fb51846SDavid C Somayajulu 	qlnx_add_hw_stats_sysctls(ha);
11227fb51846SDavid C Somayajulu 	qlnx_add_drvr_stats_sysctls(ha);
11237fb51846SDavid C Somayajulu 
11247fb51846SDavid C Somayajulu 	return;
1125f10a77bbSDavid C Somayajulu }
1126f10a77bbSDavid C Somayajulu 
1127f10a77bbSDavid C Somayajulu void
1128f10a77bbSDavid C Somayajulu ql_hw_link_status(qla_host_t *ha)
1129f10a77bbSDavid C Somayajulu {
1130f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui);
1131f10a77bbSDavid C Somayajulu 
1132f10a77bbSDavid C Somayajulu 	if (ha->hw.link_up) {
1133f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link Up\n");
1134f10a77bbSDavid C Somayajulu 	} else {
1135f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link Down\n");
1136f10a77bbSDavid C Somayajulu 	}
1137f10a77bbSDavid C Somayajulu 
1138b65c0c07SDavid C Somayajulu 	if (ha->hw.fduplex) {
1139f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Full Duplex\n");
1140f10a77bbSDavid C Somayajulu 	} else {
1141f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Half Duplex\n");
1142f10a77bbSDavid C Somayajulu 	}
1143f10a77bbSDavid C Somayajulu 
1144b65c0c07SDavid C Somayajulu 	if (ha->hw.autoneg) {
1145f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Auto Negotiation Enabled\n");
1146f10a77bbSDavid C Somayajulu 	} else {
1147f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Auto Negotiation Disabled\n");
1148f10a77bbSDavid C Somayajulu 	}
1149f10a77bbSDavid C Somayajulu 
1150f10a77bbSDavid C Somayajulu 	switch (ha->hw.link_speed) {
1151f10a77bbSDavid C Somayajulu 	case 0x710:
1152f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 10Gps\n");
1153f10a77bbSDavid C Somayajulu 		break;
1154f10a77bbSDavid C Somayajulu 
1155f10a77bbSDavid C Somayajulu 	case 0x3E8:
1156f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 1Gps\n");
1157f10a77bbSDavid C Somayajulu 		break;
1158f10a77bbSDavid C Somayajulu 
1159f10a77bbSDavid C Somayajulu 	case 0x64:
1160f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n");
1161f10a77bbSDavid C Somayajulu 		break;
1162f10a77bbSDavid C Somayajulu 
1163f10a77bbSDavid C Somayajulu 	default:
1164f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "link speed\t\t Unknown\n");
1165f10a77bbSDavid C Somayajulu 		break;
1166f10a77bbSDavid C Somayajulu 	}
1167f10a77bbSDavid C Somayajulu 
1168f10a77bbSDavid C Somayajulu 	switch (ha->hw.module_type) {
1169f10a77bbSDavid C Somayajulu 
1170f10a77bbSDavid C Somayajulu 	case 0x01:
1171f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n");
1172f10a77bbSDavid C Somayajulu 		break;
1173f10a77bbSDavid C Somayajulu 
1174f10a77bbSDavid C Somayajulu 	case 0x02:
1175f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-LR\n");
1176f10a77bbSDavid C Somayajulu 		break;
1177f10a77bbSDavid C Somayajulu 
1178f10a77bbSDavid C Somayajulu 	case 0x03:
1179f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GBase-SR\n");
1180f10a77bbSDavid C Somayajulu 		break;
1181f10a77bbSDavid C Somayajulu 
1182f10a77bbSDavid C Somayajulu 	case 0x04:
1183f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
1184f10a77bbSDavid C Somayajulu 			"Module Type 10GE Passive Copper(Compliant)[%d m]\n",
1185f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
1186f10a77bbSDavid C Somayajulu 		break;
1187f10a77bbSDavid C Somayajulu 
1188f10a77bbSDavid C Somayajulu 	case 0x05:
1189f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 10GE Active"
1190f10a77bbSDavid C Somayajulu 			" Limiting Copper(Compliant)[%d m]\n",
1191f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
1192f10a77bbSDavid C Somayajulu 		break;
1193f10a77bbSDavid C Somayajulu 
1194f10a77bbSDavid C Somayajulu 	case 0x06:
1195f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
1196f10a77bbSDavid C Somayajulu 			"Module Type 10GE Passive Copper"
1197f10a77bbSDavid C Somayajulu 			" (Legacy, Best Effort)[%d m]\n",
1198f10a77bbSDavid C Somayajulu 			ha->hw.cable_length);
1199f10a77bbSDavid C Somayajulu 		break;
1200f10a77bbSDavid C Somayajulu 
1201f10a77bbSDavid C Somayajulu 	case 0x07:
1202f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-SX\n");
1203f10a77bbSDavid C Somayajulu 		break;
1204f10a77bbSDavid C Somayajulu 
1205f10a77bbSDavid C Somayajulu 	case 0x08:
1206f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-LX\n");
1207f10a77bbSDavid C Somayajulu 		break;
1208f10a77bbSDavid C Somayajulu 
1209f10a77bbSDavid C Somayajulu 	case 0x09:
1210f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-CX\n");
1211f10a77bbSDavid C Somayajulu 		break;
1212f10a77bbSDavid C Somayajulu 
1213f10a77bbSDavid C Somayajulu 	case 0x0A:
1214f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1000Base-T\n");
1215f10a77bbSDavid C Somayajulu 		break;
1216f10a77bbSDavid C Somayajulu 
1217f10a77bbSDavid C Somayajulu 	case 0x0B:
1218f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Module Type 1GE Passive Copper"
1219f10a77bbSDavid C Somayajulu 			"(Legacy, Best Effort)\n");
1220f10a77bbSDavid C Somayajulu 		break;
1221f10a77bbSDavid C Somayajulu 
1222f10a77bbSDavid C Somayajulu 	default:
1223f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n",
1224f10a77bbSDavid C Somayajulu 			ha->hw.module_type);
1225f10a77bbSDavid C Somayajulu 		break;
1226f10a77bbSDavid C Somayajulu 	}
1227f10a77bbSDavid C Somayajulu 
1228f10a77bbSDavid C Somayajulu 	if (ha->hw.link_faults == 1)
1229f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "SFP Power Fault\n");
1230f10a77bbSDavid C Somayajulu }
1231f10a77bbSDavid C Somayajulu 
1232f10a77bbSDavid C Somayajulu /*
1233f10a77bbSDavid C Somayajulu  * Name: ql_free_dma
1234f10a77bbSDavid C Somayajulu  * Function: Frees the DMA'able memory allocated in ql_alloc_dma()
1235f10a77bbSDavid C Somayajulu  */
1236f10a77bbSDavid C Somayajulu void
1237f10a77bbSDavid C Somayajulu ql_free_dma(qla_host_t *ha)
1238f10a77bbSDavid C Somayajulu {
1239f10a77bbSDavid C Somayajulu 	uint32_t i;
1240f10a77bbSDavid C Somayajulu 
1241f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.sds_ring) {
1242f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
1243f10a77bbSDavid C Somayajulu 			ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]);
1244f10a77bbSDavid C Somayajulu 		}
1245f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.sds_ring = 0;
1246f10a77bbSDavid C Somayajulu 	}
1247f10a77bbSDavid C Somayajulu 
1248f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.rds_ring) {
1249f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_rds_rings; i++) {
1250f10a77bbSDavid C Somayajulu 			ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]);
1251f10a77bbSDavid C Somayajulu 		}
1252f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.rds_ring = 0;
1253f10a77bbSDavid C Somayajulu 	}
1254f10a77bbSDavid C Somayajulu 
1255f10a77bbSDavid C Somayajulu         if (ha->hw.dma_buf.flags.tx_ring) {
1256f10a77bbSDavid C Somayajulu 		ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring);
1257f10a77bbSDavid C Somayajulu         	ha->hw.dma_buf.flags.tx_ring = 0;
1258f10a77bbSDavid C Somayajulu 	}
12596a62bec0SDavid C Somayajulu 	ql_minidump_free(ha);
1260f10a77bbSDavid C Somayajulu }
1261f10a77bbSDavid C Somayajulu 
1262f10a77bbSDavid C Somayajulu /*
1263f10a77bbSDavid C Somayajulu  * Name: ql_alloc_dma
1264f10a77bbSDavid C Somayajulu  * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts.
1265f10a77bbSDavid C Somayajulu  */
1266f10a77bbSDavid C Somayajulu int
1267f10a77bbSDavid C Somayajulu ql_alloc_dma(qla_host_t *ha)
1268f10a77bbSDavid C Somayajulu {
1269f10a77bbSDavid C Somayajulu         device_t                dev;
1270f10a77bbSDavid C Somayajulu 	uint32_t		i, j, size, tx_ring_size;
1271f10a77bbSDavid C Somayajulu 	qla_hw_t		*hw;
1272f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t	*tx_cntxt;
1273f10a77bbSDavid C Somayajulu 	uint8_t			*vaddr;
1274f10a77bbSDavid C Somayajulu 	bus_addr_t		paddr;
1275f10a77bbSDavid C Somayajulu 
1276f10a77bbSDavid C Somayajulu         dev = ha->pci_dev;
1277f10a77bbSDavid C Somayajulu 
1278f10a77bbSDavid C Somayajulu         QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
1279f10a77bbSDavid C Somayajulu 
1280f10a77bbSDavid C Somayajulu 	hw = &ha->hw;
1281f10a77bbSDavid C Somayajulu 	/*
1282f10a77bbSDavid C Somayajulu 	 * Allocate Transmit Ring
1283f10a77bbSDavid C Somayajulu 	 */
1284f10a77bbSDavid C Somayajulu 	tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS);
1285f10a77bbSDavid C Somayajulu 	size = (tx_ring_size * ha->hw.num_tx_rings);
1286f10a77bbSDavid C Somayajulu 
1287f10a77bbSDavid C Somayajulu 	hw->dma_buf.tx_ring.alignment = 8;
1288f10a77bbSDavid C Somayajulu 	hw->dma_buf.tx_ring.size = size + PAGE_SIZE;
1289f10a77bbSDavid C Somayajulu 
1290f10a77bbSDavid C Somayajulu         if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) {
1291f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: tx ring alloc failed\n", __func__);
1292f10a77bbSDavid C Somayajulu                 goto ql_alloc_dma_exit;
1293f10a77bbSDavid C Somayajulu         }
1294f10a77bbSDavid C Somayajulu 
1295f10a77bbSDavid C Somayajulu 	vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b;
1296f10a77bbSDavid C Somayajulu 	paddr = hw->dma_buf.tx_ring.dma_addr;
1297f10a77bbSDavid C Somayajulu 
1298f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
1299f10a77bbSDavid C Somayajulu 		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
1300f10a77bbSDavid C Somayajulu 
1301f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr;
1302f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_ring_paddr = paddr;
1303f10a77bbSDavid C Somayajulu 
1304f10a77bbSDavid C Somayajulu 		vaddr += tx_ring_size;
1305f10a77bbSDavid C Somayajulu 		paddr += tx_ring_size;
1306f10a77bbSDavid C Somayajulu 	}
1307f10a77bbSDavid C Somayajulu 
1308f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
1309f10a77bbSDavid C Somayajulu 		tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
1310f10a77bbSDavid C Somayajulu 
1311f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_cons = (uint32_t *)vaddr;
1312f10a77bbSDavid C Somayajulu 		tx_cntxt->tx_cons_paddr = paddr;
1313f10a77bbSDavid C Somayajulu 
1314f10a77bbSDavid C Somayajulu 		vaddr += sizeof (uint32_t);
1315f10a77bbSDavid C Somayajulu 		paddr += sizeof (uint32_t);
1316f10a77bbSDavid C Somayajulu 	}
1317f10a77bbSDavid C Somayajulu 
1318f10a77bbSDavid C Somayajulu         ha->hw.dma_buf.flags.tx_ring = 1;
1319f10a77bbSDavid C Somayajulu 
1320f10a77bbSDavid C Somayajulu 	QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n",
1321f10a77bbSDavid C Somayajulu 		__func__, (void *)(hw->dma_buf.tx_ring.dma_addr),
1322f10a77bbSDavid C Somayajulu 		hw->dma_buf.tx_ring.dma_b));
1323f10a77bbSDavid C Somayajulu 	/*
1324f10a77bbSDavid C Somayajulu 	 * Allocate Receive Descriptor Rings
1325f10a77bbSDavid C Somayajulu 	 */
1326f10a77bbSDavid C Somayajulu 
1327f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_rds_rings; i++) {
1328f10a77bbSDavid C Somayajulu 
1329f10a77bbSDavid C Somayajulu 		hw->dma_buf.rds_ring[i].alignment = 8;
1330f10a77bbSDavid C Somayajulu 		hw->dma_buf.rds_ring[i].size =
1331f10a77bbSDavid C Somayajulu 			(sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS;
1332f10a77bbSDavid C Somayajulu 
1333f10a77bbSDavid C Somayajulu 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) {
1334f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: rds ring[%d] alloc failed\n",
1335f10a77bbSDavid C Somayajulu 				__func__, i);
1336f10a77bbSDavid C Somayajulu 
1337f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
1338f10a77bbSDavid C Somayajulu 				ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]);
1339f10a77bbSDavid C Somayajulu 
1340f10a77bbSDavid C Somayajulu 			goto ql_alloc_dma_exit;
1341f10a77bbSDavid C Somayajulu 		}
1342f10a77bbSDavid C Somayajulu 		QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n",
1343f10a77bbSDavid C Somayajulu 			__func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr),
1344f10a77bbSDavid C Somayajulu 			hw->dma_buf.rds_ring[i].dma_b));
1345f10a77bbSDavid C Somayajulu 	}
1346f10a77bbSDavid C Somayajulu 
1347f10a77bbSDavid C Somayajulu 	hw->dma_buf.flags.rds_ring = 1;
1348f10a77bbSDavid C Somayajulu 
1349f10a77bbSDavid C Somayajulu 	/*
1350f10a77bbSDavid C Somayajulu 	 * Allocate Status Descriptor Rings
1351f10a77bbSDavid C Somayajulu 	 */
1352f10a77bbSDavid C Somayajulu 
1353f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
1354f10a77bbSDavid C Somayajulu 		hw->dma_buf.sds_ring[i].alignment = 8;
1355f10a77bbSDavid C Somayajulu 		hw->dma_buf.sds_ring[i].size =
1356f10a77bbSDavid C Somayajulu 			(sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS;
1357f10a77bbSDavid C Somayajulu 
1358f10a77bbSDavid C Somayajulu 		if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) {
1359f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: sds ring alloc failed\n",
1360f10a77bbSDavid C Somayajulu 				__func__);
1361f10a77bbSDavid C Somayajulu 
1362f10a77bbSDavid C Somayajulu 			for (j = 0; j < i; j++)
1363f10a77bbSDavid C Somayajulu 				ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]);
1364f10a77bbSDavid C Somayajulu 
1365f10a77bbSDavid C Somayajulu 			goto ql_alloc_dma_exit;
1366f10a77bbSDavid C Somayajulu 		}
1367f10a77bbSDavid C Somayajulu 		QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n",
1368f10a77bbSDavid C Somayajulu 			__func__, i,
1369f10a77bbSDavid C Somayajulu 			(void *)(hw->dma_buf.sds_ring[i].dma_addr),
1370f10a77bbSDavid C Somayajulu 			hw->dma_buf.sds_ring[i].dma_b));
1371f10a77bbSDavid C Somayajulu 	}
1372f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
1373f10a77bbSDavid C Somayajulu 		hw->sds[i].sds_ring_base =
1374f10a77bbSDavid C Somayajulu 			(q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b;
1375f10a77bbSDavid C Somayajulu 	}
1376f10a77bbSDavid C Somayajulu 
1377f10a77bbSDavid C Somayajulu 	hw->dma_buf.flags.sds_ring = 1;
1378f10a77bbSDavid C Somayajulu 
1379f10a77bbSDavid C Somayajulu 	return 0;
1380f10a77bbSDavid C Somayajulu 
1381f10a77bbSDavid C Somayajulu ql_alloc_dma_exit:
1382f10a77bbSDavid C Somayajulu 	ql_free_dma(ha);
1383f10a77bbSDavid C Somayajulu 	return -1;
1384f10a77bbSDavid C Somayajulu }
1385f10a77bbSDavid C Somayajulu 
1386f10a77bbSDavid C Somayajulu #define Q8_MBX_MSEC_DELAY	5000
1387f10a77bbSDavid C Somayajulu 
1388f10a77bbSDavid C Somayajulu static int
1389f10a77bbSDavid C Somayajulu qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
1390f10a77bbSDavid C Somayajulu 	uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause)
1391f10a77bbSDavid C Somayajulu {
1392f10a77bbSDavid C Somayajulu 	uint32_t i;
1393f10a77bbSDavid C Somayajulu 	uint32_t data;
1394f10a77bbSDavid C Somayajulu 	int ret = 0;
1395b65c0c07SDavid C Somayajulu 	uint64_t start_usecs;
1396b65c0c07SDavid C Somayajulu 	uint64_t end_usecs;
1397b65c0c07SDavid C Somayajulu 	uint64_t msecs_200;
1398f10a77bbSDavid C Somayajulu 
1399b65c0c07SDavid C Somayajulu 	ql_sp_log(ha, 0, 5, no_pause, h_mbox[0], h_mbox[1], h_mbox[2], h_mbox[3]);
1400b65c0c07SDavid C Somayajulu 
1401b65c0c07SDavid C Somayajulu 	if (ha->offline || ha->qla_initiate_recovery) {
1402b65c0c07SDavid C Somayajulu 		ql_sp_log(ha, 1, 2, ha->offline, ha->qla_initiate_recovery, 0, 0, 0);
1403f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
1404f10a77bbSDavid C Somayajulu 	}
1405f10a77bbSDavid C Somayajulu 
1406b65c0c07SDavid C Somayajulu 	if (((ha->err_inject & 0xFFFF) == INJCT_MBX_CMD_FAILURE) &&
1407b65c0c07SDavid C Somayajulu 		(((ha->err_inject & ~0xFFFF) == ((h_mbox[0] & 0xFFFF) << 16))||
1408b65c0c07SDavid C Somayajulu 		!(ha->err_inject & ~0xFFFF))) {
1409b65c0c07SDavid C Somayajulu 		ret = -3;
1410b65c0c07SDavid C Somayajulu 		QL_INITIATE_RECOVERY(ha);
1411b65c0c07SDavid C Somayajulu 		goto exit_qla_mbx_cmd;
1412b65c0c07SDavid C Somayajulu 	}
1413b65c0c07SDavid C Somayajulu 
1414b65c0c07SDavid C Somayajulu 	start_usecs = qla_get_usec_timestamp();
1415b65c0c07SDavid C Somayajulu 
1416f10a77bbSDavid C Somayajulu 	if (no_pause)
1417f10a77bbSDavid C Somayajulu 		i = 1000;
1418f10a77bbSDavid C Somayajulu 	else
1419f10a77bbSDavid C Somayajulu 		i = Q8_MBX_MSEC_DELAY;
1420f10a77bbSDavid C Somayajulu 
1421f10a77bbSDavid C Somayajulu 	while (i) {
1422b65c0c07SDavid C Somayajulu 
1423b65c0c07SDavid C Somayajulu 		if (ha->qla_initiate_recovery) {
1424b65c0c07SDavid C Somayajulu 			ql_sp_log(ha, 2, 1, ha->qla_initiate_recovery, 0, 0, 0, 0);
1425b65c0c07SDavid C Somayajulu 			return (-1);
1426b65c0c07SDavid C Somayajulu 		}
1427b65c0c07SDavid C Somayajulu 
1428f10a77bbSDavid C Somayajulu 		data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL);
1429f10a77bbSDavid C Somayajulu 		if (data == 0)
1430f10a77bbSDavid C Somayajulu 			break;
1431f10a77bbSDavid C Somayajulu 		if (no_pause) {
1432f10a77bbSDavid C Somayajulu 			DELAY(1000);
1433f10a77bbSDavid C Somayajulu 		} else {
1434f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
1435f10a77bbSDavid C Somayajulu 		}
1436f10a77bbSDavid C Somayajulu 		i--;
1437f10a77bbSDavid C Somayajulu 	}
1438f10a77bbSDavid C Somayajulu 
1439f10a77bbSDavid C Somayajulu 	if (i == 0) {
1440f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n",
1441f10a77bbSDavid C Somayajulu 			__func__, data);
1442b65c0c07SDavid C Somayajulu 		ql_sp_log(ha, 3, 1, data, 0, 0, 0, 0);
1443f10a77bbSDavid C Somayajulu 		ret = -1;
1444b65c0c07SDavid C Somayajulu 		ha->hw.mbx_comp_msecs[(Q8_MBX_COMP_MSECS - 2)]++;
1445b65c0c07SDavid C Somayajulu 		QL_INITIATE_RECOVERY(ha);
1446f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
1447f10a77bbSDavid C Somayajulu 	}
1448f10a77bbSDavid C Somayajulu 
1449f10a77bbSDavid C Somayajulu 	for (i = 0; i < n_hmbox; i++) {
1450f10a77bbSDavid C Somayajulu 		WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox);
1451f10a77bbSDavid C Somayajulu 		h_mbox++;
1452f10a77bbSDavid C Somayajulu 	}
1453f10a77bbSDavid C Somayajulu 
1454f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1);
1455f10a77bbSDavid C Somayajulu 
1456f10a77bbSDavid C Somayajulu 
1457f10a77bbSDavid C Somayajulu 	i = Q8_MBX_MSEC_DELAY;
1458f10a77bbSDavid C Somayajulu 	while (i) {
1459b65c0c07SDavid C Somayajulu 
1460b65c0c07SDavid C Somayajulu 		if (ha->qla_initiate_recovery) {
1461b65c0c07SDavid C Somayajulu 			ql_sp_log(ha, 4, 1, ha->qla_initiate_recovery, 0, 0, 0, 0);
1462b65c0c07SDavid C Somayajulu 			return (-1);
1463b65c0c07SDavid C Somayajulu 		}
1464b65c0c07SDavid C Somayajulu 
1465f10a77bbSDavid C Somayajulu 		data = READ_REG32(ha, Q8_FW_MBOX_CNTRL);
1466f10a77bbSDavid C Somayajulu 
1467f10a77bbSDavid C Somayajulu 		if ((data & 0x3) == 1) {
1468f10a77bbSDavid C Somayajulu 			data = READ_REG32(ha, Q8_FW_MBOX0);
1469f10a77bbSDavid C Somayajulu 			if ((data & 0xF000) != 0x8000)
1470f10a77bbSDavid C Somayajulu 				break;
1471f10a77bbSDavid C Somayajulu 		}
1472f10a77bbSDavid C Somayajulu 		if (no_pause) {
1473f10a77bbSDavid C Somayajulu 			DELAY(1000);
1474f10a77bbSDavid C Somayajulu 		} else {
1475f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
1476f10a77bbSDavid C Somayajulu 		}
1477f10a77bbSDavid C Somayajulu 		i--;
1478f10a77bbSDavid C Somayajulu 	}
1479f10a77bbSDavid C Somayajulu 	if (i == 0) {
1480f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n",
1481f10a77bbSDavid C Somayajulu 			__func__, data);
1482b65c0c07SDavid C Somayajulu 		ql_sp_log(ha, 5, 1, data, 0, 0, 0, 0);
1483f10a77bbSDavid C Somayajulu 		ret = -2;
1484b65c0c07SDavid C Somayajulu 		ha->hw.mbx_comp_msecs[(Q8_MBX_COMP_MSECS - 1)]++;
1485b65c0c07SDavid C Somayajulu 		QL_INITIATE_RECOVERY(ha);
1486f10a77bbSDavid C Somayajulu 		goto exit_qla_mbx_cmd;
1487f10a77bbSDavid C Somayajulu 	}
1488f10a77bbSDavid C Somayajulu 
1489f10a77bbSDavid C Somayajulu 	for (i = 0; i < n_fwmbox; i++) {
1490b65c0c07SDavid C Somayajulu 
1491b65c0c07SDavid C Somayajulu 		if (ha->qla_initiate_recovery) {
1492b65c0c07SDavid C Somayajulu 			ql_sp_log(ha, 6, 1, ha->qla_initiate_recovery, 0, 0, 0, 0);
1493b65c0c07SDavid C Somayajulu 			return (-1);
1494b65c0c07SDavid C Somayajulu 		}
1495b65c0c07SDavid C Somayajulu 
1496f10a77bbSDavid C Somayajulu 		*fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2)));
1497f10a77bbSDavid C Somayajulu 	}
1498f10a77bbSDavid C Somayajulu 
1499f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0);
1500f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
1501f10a77bbSDavid C Somayajulu 
1502b65c0c07SDavid C Somayajulu 	end_usecs = qla_get_usec_timestamp();
1503b65c0c07SDavid C Somayajulu 
1504b65c0c07SDavid C Somayajulu 	if (end_usecs > start_usecs) {
1505b65c0c07SDavid C Somayajulu 		msecs_200 = (end_usecs - start_usecs)/(1000 * 200);
1506b65c0c07SDavid C Somayajulu 
1507b65c0c07SDavid C Somayajulu 		if (msecs_200 < 15)
1508b65c0c07SDavid C Somayajulu 			ha->hw.mbx_comp_msecs[msecs_200]++;
1509b65c0c07SDavid C Somayajulu 		else if (msecs_200 < 20)
1510b65c0c07SDavid C Somayajulu 			ha->hw.mbx_comp_msecs[15]++;
1511b65c0c07SDavid C Somayajulu 		else {
1512b65c0c07SDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: [%ld, %ld] %ld\n", __func__,
1513b65c0c07SDavid C Somayajulu 				start_usecs, end_usecs, msecs_200);
1514b65c0c07SDavid C Somayajulu 			ha->hw.mbx_comp_msecs[16]++;
1515b65c0c07SDavid C Somayajulu 		}
1516b65c0c07SDavid C Somayajulu 	}
1517b65c0c07SDavid C Somayajulu 	ql_sp_log(ha, 7, 5, fw_mbox[0], fw_mbox[1], fw_mbox[2], fw_mbox[3], fw_mbox[4]);
1518b65c0c07SDavid C Somayajulu 
1519b65c0c07SDavid C Somayajulu 
1520f10a77bbSDavid C Somayajulu exit_qla_mbx_cmd:
1521f10a77bbSDavid C Somayajulu 	return (ret);
1522f10a77bbSDavid C Somayajulu }
1523f10a77bbSDavid C Somayajulu 
152435291c22SDavid C Somayajulu int
152535291c22SDavid C Somayajulu qla_get_nic_partition(qla_host_t *ha, uint32_t *supports_9kb,
152635291c22SDavid C Somayajulu 	uint32_t *num_rcvq)
1527f10a77bbSDavid C Somayajulu {
1528f10a77bbSDavid C Somayajulu 	uint32_t *mbox, err;
1529f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1530f10a77bbSDavid C Somayajulu 
1531f10a77bbSDavid C Somayajulu 	bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX));
1532f10a77bbSDavid C Somayajulu 
1533f10a77bbSDavid C Somayajulu 	mbox = ha->hw.mbox;
1534f10a77bbSDavid C Somayajulu 
1535f10a77bbSDavid C Somayajulu 	mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29);
1536f10a77bbSDavid C Somayajulu 
1537f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) {
1538f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1539f10a77bbSDavid C Somayajulu 		return (-1);
1540f10a77bbSDavid C Somayajulu 	}
1541f10a77bbSDavid C Somayajulu 	err = mbox[0] >> 25;
1542f10a77bbSDavid C Somayajulu 
154335291c22SDavid C Somayajulu 	if (supports_9kb != NULL) {
154435291c22SDavid C Somayajulu 		if (mbox[16] & 0x80) /* bit 7 of mbox 16 */
154535291c22SDavid C Somayajulu 			*supports_9kb = 1;
154635291c22SDavid C Somayajulu 		else
154735291c22SDavid C Somayajulu 			*supports_9kb = 0;
154835291c22SDavid C Somayajulu 	}
154935291c22SDavid C Somayajulu 
155035291c22SDavid C Somayajulu 	if (num_rcvq != NULL)
155135291c22SDavid C Somayajulu 		*num_rcvq =  ((mbox[6] >> 16) & 0xFFFF);
155235291c22SDavid C Somayajulu 
1553f10a77bbSDavid C Somayajulu 	if ((err != 1) && (err != 0)) {
1554f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1555f10a77bbSDavid C Somayajulu 		return (-1);
1556f10a77bbSDavid C Somayajulu 	}
1557f10a77bbSDavid C Somayajulu 	return 0;
1558f10a77bbSDavid C Somayajulu }
1559f10a77bbSDavid C Somayajulu 
1560f10a77bbSDavid C Somayajulu static int
156135291c22SDavid C Somayajulu qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, uint32_t num_intrs,
156235291c22SDavid C Somayajulu 	uint32_t create)
1563f10a77bbSDavid C Somayajulu {
1564f10a77bbSDavid C Somayajulu 	uint32_t i, err;
1565f10a77bbSDavid C Somayajulu 	device_t dev = ha->pci_dev;
1566f10a77bbSDavid C Somayajulu 	q80_config_intr_t *c_intr;
1567f10a77bbSDavid C Somayajulu 	q80_config_intr_rsp_t *c_intr_rsp;
1568f10a77bbSDavid C Somayajulu 
1569f10a77bbSDavid C Somayajulu 	c_intr = (q80_config_intr_t *)ha->hw.mbox;
1570f10a77bbSDavid C Somayajulu 	bzero(c_intr, (sizeof (q80_config_intr_t)));
1571f10a77bbSDavid C Somayajulu 
1572f10a77bbSDavid C Somayajulu 	c_intr->opcode = Q8_MBX_CONFIG_INTR;
1573f10a77bbSDavid C Somayajulu 
1574f10a77bbSDavid C Somayajulu 	c_intr->count_version = (sizeof (q80_config_intr_t) >> 2);
1575f10a77bbSDavid C Somayajulu 	c_intr->count_version |= Q8_MBX_CMD_VERSION;
1576f10a77bbSDavid C Somayajulu 
1577f10a77bbSDavid C Somayajulu 	c_intr->nentries = num_intrs;
1578f10a77bbSDavid C Somayajulu 
1579f10a77bbSDavid C Somayajulu 	for (i = 0; i < num_intrs; i++) {
1580f10a77bbSDavid C Somayajulu 		if (create) {
1581f10a77bbSDavid C Somayajulu 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE;
158235291c22SDavid C Somayajulu 			c_intr->intr[i].msix_index = start_idx + 1 + i;
1583f10a77bbSDavid C Somayajulu 		} else {
1584f10a77bbSDavid C Somayajulu 			c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE;
158535291c22SDavid C Somayajulu 			c_intr->intr[i].msix_index =
158635291c22SDavid C Somayajulu 				ha->hw.intr_id[(start_idx + i)];
1587f10a77bbSDavid C Somayajulu 		}
1588f10a77bbSDavid C Somayajulu 
1589f10a77bbSDavid C Somayajulu 		c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X;
1590f10a77bbSDavid C Somayajulu 	}
1591f10a77bbSDavid C Somayajulu 
1592f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_intr,
1593f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_intr_t) >> 2),
1594f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) {
1595b65c0c07SDavid C Somayajulu 		device_printf(dev, "%s: %s failed0\n", __func__,
1596b65c0c07SDavid C Somayajulu 			(create ? "create" : "delete"));
1597f10a77bbSDavid C Somayajulu 		return (-1);
1598f10a77bbSDavid C Somayajulu 	}
1599f10a77bbSDavid C Somayajulu 
1600f10a77bbSDavid C Somayajulu 	c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox;
1601f10a77bbSDavid C Somayajulu 
1602f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status);
1603f10a77bbSDavid C Somayajulu 
1604f10a77bbSDavid C Somayajulu 	if (err) {
1605b65c0c07SDavid C Somayajulu 		device_printf(dev, "%s: %s failed1 [0x%08x, %d]\n", __func__,
1606b65c0c07SDavid C Somayajulu 			(create ? "create" : "delete"), err, c_intr_rsp->nentries);
1607f10a77bbSDavid C Somayajulu 
1608f10a77bbSDavid C Somayajulu 		for (i = 0; i < c_intr_rsp->nentries; i++) {
1609f10a77bbSDavid C Somayajulu 			device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n",
1610f10a77bbSDavid C Somayajulu 				__func__, i,
1611f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].status,
1612f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].intr_id,
1613f10a77bbSDavid C Somayajulu 				c_intr_rsp->intr[i].intr_src);
1614f10a77bbSDavid C Somayajulu 		}
1615f10a77bbSDavid C Somayajulu 
1616f10a77bbSDavid C Somayajulu 		return (-1);
1617f10a77bbSDavid C Somayajulu 	}
1618f10a77bbSDavid C Somayajulu 
1619f10a77bbSDavid C Somayajulu 	for (i = 0; ((i < num_intrs) && create); i++) {
1620f10a77bbSDavid C Somayajulu 		if (!c_intr_rsp->intr[i].status) {
162135291c22SDavid C Somayajulu 			ha->hw.intr_id[(start_idx + i)] =
162235291c22SDavid C Somayajulu 				c_intr_rsp->intr[i].intr_id;
162335291c22SDavid C Somayajulu 			ha->hw.intr_src[(start_idx + i)] =
162435291c22SDavid C Somayajulu 				c_intr_rsp->intr[i].intr_src;
1625f10a77bbSDavid C Somayajulu 		}
1626f10a77bbSDavid C Somayajulu 	}
1627f10a77bbSDavid C Somayajulu 
1628f10a77bbSDavid C Somayajulu 	return (0);
1629f10a77bbSDavid C Somayajulu }
1630f10a77bbSDavid C Somayajulu 
1631f10a77bbSDavid C Somayajulu /*
1632f10a77bbSDavid C Somayajulu  * Name: qla_config_rss
1633f10a77bbSDavid C Somayajulu  * Function: Configure RSS for the context/interface.
1634f10a77bbSDavid C Somayajulu  */
1635f10a77bbSDavid C Somayajulu static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL,
1636f10a77bbSDavid C Somayajulu 			0x8030f20c77cb2da3ULL,
1637f10a77bbSDavid C Somayajulu 			0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
1638f10a77bbSDavid C Somayajulu 			0x255b0ec26d5a56daULL };
1639f10a77bbSDavid C Somayajulu 
1640f10a77bbSDavid C Somayajulu static int
1641f10a77bbSDavid C Somayajulu qla_config_rss(qla_host_t *ha, uint16_t cntxt_id)
1642f10a77bbSDavid C Somayajulu {
1643f10a77bbSDavid C Somayajulu 	q80_config_rss_t	*c_rss;
1644f10a77bbSDavid C Somayajulu 	q80_config_rss_rsp_t	*c_rss_rsp;
1645f10a77bbSDavid C Somayajulu 	uint32_t		err, i;
1646f10a77bbSDavid C Somayajulu 	device_t		dev = ha->pci_dev;
1647f10a77bbSDavid C Somayajulu 
1648f10a77bbSDavid C Somayajulu 	c_rss = (q80_config_rss_t *)ha->hw.mbox;
1649f10a77bbSDavid C Somayajulu 	bzero(c_rss, (sizeof (q80_config_rss_t)));
1650f10a77bbSDavid C Somayajulu 
1651f10a77bbSDavid C Somayajulu 	c_rss->opcode = Q8_MBX_CONFIG_RSS;
1652f10a77bbSDavid C Somayajulu 
1653f10a77bbSDavid C Somayajulu 	c_rss->count_version = (sizeof (q80_config_rss_t) >> 2);
1654f10a77bbSDavid C Somayajulu 	c_rss->count_version |= Q8_MBX_CMD_VERSION;
1655f10a77bbSDavid C Somayajulu 
1656f10a77bbSDavid C Somayajulu 	c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP |
1657f10a77bbSDavid C Somayajulu 				Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP);
165835291c22SDavid C Somayajulu 	//c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP |
165935291c22SDavid C Somayajulu 	//			Q8_MBX_RSS_HASH_TYPE_IPV6_TCP);
1660f10a77bbSDavid C Somayajulu 
1661f10a77bbSDavid C Somayajulu 	c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS;
1662f10a77bbSDavid C Somayajulu 	c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE;
1663f10a77bbSDavid C Somayajulu 
1664f10a77bbSDavid C Somayajulu 	c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK;
1665f10a77bbSDavid C Somayajulu 
1666f10a77bbSDavid C Somayajulu 	c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID;
1667f10a77bbSDavid C Somayajulu 	c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS;
1668f10a77bbSDavid C Somayajulu 
1669f10a77bbSDavid C Somayajulu 	c_rss->cntxt_id = cntxt_id;
1670f10a77bbSDavid C Somayajulu 
1671f10a77bbSDavid C Somayajulu 	for (i = 0; i < 5; i++) {
1672f10a77bbSDavid C Somayajulu 		c_rss->rss_key[i] = rss_key[i];
1673f10a77bbSDavid C Somayajulu 	}
1674f10a77bbSDavid C Somayajulu 
1675f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss,
1676f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_rss_t) >> 2),
1677f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) {
1678f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1679f10a77bbSDavid C Somayajulu 		return (-1);
1680f10a77bbSDavid C Somayajulu 	}
1681f10a77bbSDavid C Somayajulu 	c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox;
1682f10a77bbSDavid C Somayajulu 
1683f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status);
1684f10a77bbSDavid C Somayajulu 
1685f10a77bbSDavid C Somayajulu 	if (err) {
1686f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1687f10a77bbSDavid C Somayajulu 		return (-1);
1688f10a77bbSDavid C Somayajulu 	}
1689f10a77bbSDavid C Somayajulu 	return 0;
1690f10a77bbSDavid C Somayajulu }
1691f10a77bbSDavid C Somayajulu 
1692f10a77bbSDavid C Somayajulu static int
1693f10a77bbSDavid C Somayajulu qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count,
1694f10a77bbSDavid C Somayajulu         uint16_t cntxt_id, uint8_t *ind_table)
1695f10a77bbSDavid C Somayajulu {
1696f10a77bbSDavid C Somayajulu         q80_config_rss_ind_table_t      *c_rss_ind;
1697f10a77bbSDavid C Somayajulu         q80_config_rss_ind_table_rsp_t  *c_rss_ind_rsp;
1698f10a77bbSDavid C Somayajulu         uint32_t                        err;
1699f10a77bbSDavid C Somayajulu         device_t                        dev = ha->pci_dev;
1700f10a77bbSDavid C Somayajulu 
1701f10a77bbSDavid C Somayajulu 	if ((count > Q8_RSS_IND_TBL_SIZE) ||
1702f10a77bbSDavid C Somayajulu 		((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) {
1703f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: illegal count [%d, %d]\n", __func__,
1704f10a77bbSDavid C Somayajulu 			start_idx, count);
1705f10a77bbSDavid C Somayajulu 		return (-1);
1706f10a77bbSDavid C Somayajulu 	}
1707f10a77bbSDavid C Somayajulu 
1708f10a77bbSDavid C Somayajulu         c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox;
1709f10a77bbSDavid C Somayajulu         bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t));
1710f10a77bbSDavid C Somayajulu 
1711f10a77bbSDavid C Somayajulu         c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE;
1712f10a77bbSDavid C Somayajulu         c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2);
1713f10a77bbSDavid C Somayajulu         c_rss_ind->count_version |= Q8_MBX_CMD_VERSION;
1714f10a77bbSDavid C Somayajulu 
1715f10a77bbSDavid C Somayajulu 	c_rss_ind->start_idx = start_idx;
1716f10a77bbSDavid C Somayajulu 	c_rss_ind->end_idx = start_idx + count - 1;
1717f10a77bbSDavid C Somayajulu 	c_rss_ind->cntxt_id = cntxt_id;
1718f10a77bbSDavid C Somayajulu 	bcopy(ind_table, c_rss_ind->ind_table, count);
1719f10a77bbSDavid C Somayajulu 
1720f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind,
1721f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox,
1722f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) {
1723f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1724f10a77bbSDavid C Somayajulu 		return (-1);
1725f10a77bbSDavid C Somayajulu 	}
1726f10a77bbSDavid C Somayajulu 
1727f10a77bbSDavid C Somayajulu 	c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox;
1728f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status);
1729f10a77bbSDavid C Somayajulu 
1730f10a77bbSDavid C Somayajulu 	if (err) {
1731f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1732f10a77bbSDavid C Somayajulu 		return (-1);
1733f10a77bbSDavid C Somayajulu 	}
1734f10a77bbSDavid C Somayajulu 	return 0;
1735f10a77bbSDavid C Somayajulu }
1736f10a77bbSDavid C Somayajulu 
1737f10a77bbSDavid C Somayajulu /*
1738f10a77bbSDavid C Somayajulu  * Name: qla_config_intr_coalesce
1739f10a77bbSDavid C Somayajulu  * Function: Configure Interrupt Coalescing.
1740f10a77bbSDavid C Somayajulu  */
1741f10a77bbSDavid C Somayajulu static int
174235291c22SDavid C Somayajulu qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable,
174335291c22SDavid C Somayajulu 	int rcv)
1744f10a77bbSDavid C Somayajulu {
1745f10a77bbSDavid C Somayajulu 	q80_config_intr_coalesc_t	*intrc;
1746f10a77bbSDavid C Somayajulu 	q80_config_intr_coalesc_rsp_t	*intrc_rsp;
1747f10a77bbSDavid C Somayajulu 	uint32_t			err, i;
1748f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1749f10a77bbSDavid C Somayajulu 
1750f10a77bbSDavid C Somayajulu 	intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox;
1751f10a77bbSDavid C Somayajulu 	bzero(intrc, (sizeof (q80_config_intr_coalesc_t)));
1752f10a77bbSDavid C Somayajulu 
1753f10a77bbSDavid C Somayajulu 	intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE;
1754f10a77bbSDavid C Somayajulu 	intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2);
1755f10a77bbSDavid C Somayajulu 	intrc->count_version |= Q8_MBX_CMD_VERSION;
1756f10a77bbSDavid C Somayajulu 
175735291c22SDavid C Somayajulu 	if (rcv) {
1758f10a77bbSDavid C Somayajulu 		intrc->flags = Q8_MBX_INTRC_FLAGS_RCV;
175935291c22SDavid C Somayajulu 		intrc->max_pkts = ha->hw.rcv_intr_coalesce & 0xFFFF;
176035291c22SDavid C Somayajulu 		intrc->max_mswait = (ha->hw.rcv_intr_coalesce >> 16) & 0xFFFF;
176135291c22SDavid C Somayajulu 	} else {
176235291c22SDavid C Somayajulu 		intrc->flags = Q8_MBX_INTRC_FLAGS_XMT;
176335291c22SDavid C Somayajulu 		intrc->max_pkts = ha->hw.xmt_intr_coalesce & 0xFFFF;
176435291c22SDavid C Somayajulu 		intrc->max_mswait = (ha->hw.xmt_intr_coalesce >> 16) & 0xFFFF;
176535291c22SDavid C Somayajulu 	}
1766f10a77bbSDavid C Somayajulu 
176735291c22SDavid C Somayajulu 	intrc->cntxt_id = cntxt_id;
1768f10a77bbSDavid C Somayajulu 
1769f10a77bbSDavid C Somayajulu 	if (tenable) {
1770f10a77bbSDavid C Somayajulu 		intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC;
1771f10a77bbSDavid C Somayajulu 		intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC;
1772f10a77bbSDavid C Somayajulu 
1773f10a77bbSDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; i++) {
1774f10a77bbSDavid C Somayajulu 			intrc->sds_ring_mask |= (1 << i);
1775f10a77bbSDavid C Somayajulu 		}
1776f10a77bbSDavid C Somayajulu 		intrc->ms_timeout = 1000;
1777f10a77bbSDavid C Somayajulu 	}
1778f10a77bbSDavid C Somayajulu 
1779f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)intrc,
1780f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_intr_coalesc_t) >> 2),
1781f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) {
1782f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1783f10a77bbSDavid C Somayajulu 		return (-1);
1784f10a77bbSDavid C Somayajulu 	}
1785f10a77bbSDavid C Somayajulu 	intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox;
1786f10a77bbSDavid C Somayajulu 
1787f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status);
1788f10a77bbSDavid C Somayajulu 
1789f10a77bbSDavid C Somayajulu 	if (err) {
1790f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1791f10a77bbSDavid C Somayajulu 		return (-1);
1792f10a77bbSDavid C Somayajulu 	}
1793f10a77bbSDavid C Somayajulu 
1794f10a77bbSDavid C Somayajulu 	return 0;
1795f10a77bbSDavid C Somayajulu }
1796f10a77bbSDavid C Somayajulu 
1797f10a77bbSDavid C Somayajulu 
1798f10a77bbSDavid C Somayajulu /*
1799f10a77bbSDavid C Somayajulu  * Name: qla_config_mac_addr
1800f10a77bbSDavid C Somayajulu  * Function: binds a MAC address to the context/interface.
1801f10a77bbSDavid C Somayajulu  *	Can be unicast, multicast or broadcast.
1802f10a77bbSDavid C Somayajulu  */
1803f10a77bbSDavid C Somayajulu static int
1804da834d52SDavid C Somayajulu qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac,
1805da834d52SDavid C Somayajulu 	uint32_t num_mac)
1806f10a77bbSDavid C Somayajulu {
1807f10a77bbSDavid C Somayajulu 	q80_config_mac_addr_t		*cmac;
1808f10a77bbSDavid C Somayajulu 	q80_config_mac_addr_rsp_t	*cmac_rsp;
1809f10a77bbSDavid C Somayajulu 	uint32_t			err;
1810f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1811da834d52SDavid C Somayajulu 	int				i;
1812da834d52SDavid C Somayajulu 	uint8_t				*mac_cpy = mac_addr;
1813da834d52SDavid C Somayajulu 
1814da834d52SDavid C Somayajulu 	if (num_mac > Q8_MAX_MAC_ADDRS) {
1815da834d52SDavid C Somayajulu 		device_printf(dev, "%s: %s num_mac [0x%x] > Q8_MAX_MAC_ADDRS\n",
1816da834d52SDavid C Somayajulu 			__func__, (add_mac ? "Add" : "Del"), num_mac);
1817da834d52SDavid C Somayajulu 		return (-1);
1818da834d52SDavid C Somayajulu 	}
1819f10a77bbSDavid C Somayajulu 
1820f10a77bbSDavid C Somayajulu 	cmac = (q80_config_mac_addr_t *)ha->hw.mbox;
1821f10a77bbSDavid C Somayajulu 	bzero(cmac, (sizeof (q80_config_mac_addr_t)));
1822f10a77bbSDavid C Somayajulu 
1823f10a77bbSDavid C Somayajulu 	cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR;
1824f10a77bbSDavid C Somayajulu 	cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2;
1825f10a77bbSDavid C Somayajulu 	cmac->count_version |= Q8_MBX_CMD_VERSION;
1826f10a77bbSDavid C Somayajulu 
1827f10a77bbSDavid C Somayajulu 	if (add_mac)
1828f10a77bbSDavid C Somayajulu 		cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR;
1829f10a77bbSDavid C Somayajulu 	else
1830f10a77bbSDavid C Somayajulu 		cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR;
1831f10a77bbSDavid C Somayajulu 
1832f10a77bbSDavid C Somayajulu 	cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS;
1833f10a77bbSDavid C Somayajulu 
1834da834d52SDavid C Somayajulu 	cmac->nmac_entries = num_mac;
1835f10a77bbSDavid C Somayajulu 	cmac->cntxt_id = ha->hw.rcv_cntxt_id;
1836da834d52SDavid C Somayajulu 
1837da834d52SDavid C Somayajulu 	for (i = 0; i < num_mac; i++) {
1838da834d52SDavid C Somayajulu 		bcopy(mac_addr, cmac->mac_addr[i].addr, Q8_ETHER_ADDR_LEN);
1839da834d52SDavid C Somayajulu 		mac_addr = mac_addr + ETHER_ADDR_LEN;
1840da834d52SDavid C Somayajulu 	}
1841f10a77bbSDavid C Somayajulu 
1842f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)cmac,
1843f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_mac_addr_t) >> 2),
1844f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) {
1845f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: %s failed0\n", __func__,
1846f10a77bbSDavid C Somayajulu 			(add_mac ? "Add" : "Del"));
1847f10a77bbSDavid C Somayajulu 		return (-1);
1848f10a77bbSDavid C Somayajulu 	}
1849f10a77bbSDavid C Somayajulu 	cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox;
1850f10a77bbSDavid C Somayajulu 
1851f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status);
1852f10a77bbSDavid C Somayajulu 
1853f10a77bbSDavid C Somayajulu 	if (err) {
1854da834d52SDavid C Somayajulu 		device_printf(dev, "%s: %s failed1 [0x%08x]\n", __func__,
1855da834d52SDavid C Somayajulu 			(add_mac ? "Add" : "Del"), err);
1856da834d52SDavid C Somayajulu 		for (i = 0; i < num_mac; i++) {
1857da834d52SDavid C Somayajulu 			device_printf(dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
1858da834d52SDavid C Somayajulu 				__func__, mac_cpy[0], mac_cpy[1], mac_cpy[2],
1859da834d52SDavid C Somayajulu 				mac_cpy[3], mac_cpy[4], mac_cpy[5]);
1860da834d52SDavid C Somayajulu 			mac_cpy += ETHER_ADDR_LEN;
1861da834d52SDavid C Somayajulu 		}
1862f10a77bbSDavid C Somayajulu 		return (-1);
1863f10a77bbSDavid C Somayajulu 	}
1864f10a77bbSDavid C Somayajulu 
1865f10a77bbSDavid C Somayajulu 	return 0;
1866f10a77bbSDavid C Somayajulu }
1867f10a77bbSDavid C Somayajulu 
1868f10a77bbSDavid C Somayajulu 
1869f10a77bbSDavid C Somayajulu /*
1870f10a77bbSDavid C Somayajulu  * Name: qla_set_mac_rcv_mode
18716a62bec0SDavid C Somayajulu  * Function: Enable/Disable AllMulticast and Promiscous Modes.
1872f10a77bbSDavid C Somayajulu  */
1873f10a77bbSDavid C Somayajulu static int
1874f10a77bbSDavid C Somayajulu qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode)
1875f10a77bbSDavid C Somayajulu {
1876f10a77bbSDavid C Somayajulu 	q80_config_mac_rcv_mode_t	*rcv_mode;
1877f10a77bbSDavid C Somayajulu 	uint32_t			err;
1878f10a77bbSDavid C Somayajulu 	q80_config_mac_rcv_mode_rsp_t	*rcv_mode_rsp;
1879f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
1880f10a77bbSDavid C Somayajulu 
1881f10a77bbSDavid C Somayajulu 	rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox;
1882f10a77bbSDavid C Somayajulu 	bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t)));
1883f10a77bbSDavid C Somayajulu 
1884f10a77bbSDavid C Somayajulu 	rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE;
1885f10a77bbSDavid C Somayajulu 	rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2;
1886f10a77bbSDavid C Somayajulu 	rcv_mode->count_version |= Q8_MBX_CMD_VERSION;
1887f10a77bbSDavid C Somayajulu 
1888f10a77bbSDavid C Somayajulu 	rcv_mode->mode = mode;
1889f10a77bbSDavid C Somayajulu 
1890f10a77bbSDavid C Somayajulu 	rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id;
1891f10a77bbSDavid C Somayajulu 
1892f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode,
1893f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_mac_rcv_mode_t) >> 2),
1894f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) {
1895f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed0\n", __func__);
1896f10a77bbSDavid C Somayajulu 		return (-1);
1897f10a77bbSDavid C Somayajulu 	}
1898f10a77bbSDavid C Somayajulu 	rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox;
1899f10a77bbSDavid C Somayajulu 
1900f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status);
1901f10a77bbSDavid C Somayajulu 
1902f10a77bbSDavid C Somayajulu 	if (err) {
1903f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1904f10a77bbSDavid C Somayajulu 		return (-1);
1905f10a77bbSDavid C Somayajulu 	}
1906f10a77bbSDavid C Somayajulu 
1907f10a77bbSDavid C Somayajulu 	return 0;
1908f10a77bbSDavid C Somayajulu }
1909f10a77bbSDavid C Somayajulu 
1910f10a77bbSDavid C Somayajulu int
1911f10a77bbSDavid C Somayajulu ql_set_promisc(qla_host_t *ha)
1912f10a77bbSDavid C Somayajulu {
1913f10a77bbSDavid C Somayajulu 	int ret;
1914f10a77bbSDavid C Somayajulu 
1915f10a77bbSDavid C Somayajulu 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1916f10a77bbSDavid C Somayajulu 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1917f10a77bbSDavid C Somayajulu 	return (ret);
1918f10a77bbSDavid C Somayajulu }
1919f10a77bbSDavid C Somayajulu 
192035291c22SDavid C Somayajulu void
192135291c22SDavid C Somayajulu qla_reset_promisc(qla_host_t *ha)
192235291c22SDavid C Somayajulu {
192335291c22SDavid C Somayajulu 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE;
192435291c22SDavid C Somayajulu 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
192535291c22SDavid C Somayajulu }
192635291c22SDavid C Somayajulu 
1927f10a77bbSDavid C Somayajulu int
1928f10a77bbSDavid C Somayajulu ql_set_allmulti(qla_host_t *ha)
1929f10a77bbSDavid C Somayajulu {
1930f10a77bbSDavid C Somayajulu 	int ret;
1931f10a77bbSDavid C Somayajulu 
1932f10a77bbSDavid C Somayajulu 	ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE;
1933f10a77bbSDavid C Somayajulu 	ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1934f10a77bbSDavid C Somayajulu 	return (ret);
1935f10a77bbSDavid C Somayajulu }
1936f10a77bbSDavid C Somayajulu 
193735291c22SDavid C Somayajulu void
193835291c22SDavid C Somayajulu qla_reset_allmulti(qla_host_t *ha)
193935291c22SDavid C Somayajulu {
194035291c22SDavid C Somayajulu 	ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE;
194135291c22SDavid C Somayajulu 	(void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
194235291c22SDavid C Somayajulu }
1943f10a77bbSDavid C Somayajulu 
1944f10a77bbSDavid C Somayajulu /*
1945f10a77bbSDavid C Somayajulu  * Name: ql_set_max_mtu
1946f10a77bbSDavid C Somayajulu  * Function:
1947f10a77bbSDavid C Somayajulu  *	Sets the maximum transfer unit size for the specified rcv context.
1948f10a77bbSDavid C Somayajulu  */
1949f10a77bbSDavid C Somayajulu int
1950f10a77bbSDavid C Somayajulu ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id)
1951f10a77bbSDavid C Somayajulu {
1952f10a77bbSDavid C Somayajulu 	device_t		dev;
1953f10a77bbSDavid C Somayajulu 	q80_set_max_mtu_t	*max_mtu;
1954f10a77bbSDavid C Somayajulu 	q80_set_max_mtu_rsp_t	*max_mtu_rsp;
1955f10a77bbSDavid C Somayajulu 	uint32_t		err;
1956f10a77bbSDavid C Somayajulu 
1957f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1958f10a77bbSDavid C Somayajulu 
1959f10a77bbSDavid C Somayajulu 	max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox;
1960f10a77bbSDavid C Somayajulu 	bzero(max_mtu, (sizeof (q80_set_max_mtu_t)));
1961f10a77bbSDavid C Somayajulu 
1962f10a77bbSDavid C Somayajulu 	max_mtu->opcode = Q8_MBX_SET_MAX_MTU;
1963f10a77bbSDavid C Somayajulu 	max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2);
1964f10a77bbSDavid C Somayajulu 	max_mtu->count_version |= Q8_MBX_CMD_VERSION;
1965f10a77bbSDavid C Somayajulu 
1966f10a77bbSDavid C Somayajulu 	max_mtu->cntxt_id = cntxt_id;
1967f10a77bbSDavid C Somayajulu 	max_mtu->mtu = mtu;
1968f10a77bbSDavid C Somayajulu 
1969f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)max_mtu,
1970f10a77bbSDavid C Somayajulu 		(sizeof (q80_set_max_mtu_t) >> 2),
1971f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) {
1972f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
1973f10a77bbSDavid C Somayajulu                 return -1;
1974f10a77bbSDavid C Somayajulu         }
1975f10a77bbSDavid C Somayajulu 
1976f10a77bbSDavid C Somayajulu 	max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox;
1977f10a77bbSDavid C Somayajulu 
1978f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status);
1979f10a77bbSDavid C Somayajulu 
1980f10a77bbSDavid C Somayajulu         if (err) {
1981f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1982f10a77bbSDavid C Somayajulu         }
1983f10a77bbSDavid C Somayajulu 
1984f10a77bbSDavid C Somayajulu 	return 0;
1985f10a77bbSDavid C Somayajulu }
1986f10a77bbSDavid C Somayajulu 
1987f10a77bbSDavid C Somayajulu static int
1988f10a77bbSDavid C Somayajulu qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id)
1989f10a77bbSDavid C Somayajulu {
1990f10a77bbSDavid C Somayajulu 	device_t		dev;
1991f10a77bbSDavid C Somayajulu 	q80_link_event_t	*lnk;
1992f10a77bbSDavid C Somayajulu 	q80_link_event_rsp_t	*lnk_rsp;
1993f10a77bbSDavid C Somayajulu 	uint32_t		err;
1994f10a77bbSDavid C Somayajulu 
1995f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
1996f10a77bbSDavid C Somayajulu 
1997f10a77bbSDavid C Somayajulu 	lnk = (q80_link_event_t *)ha->hw.mbox;
1998f10a77bbSDavid C Somayajulu 	bzero(lnk, (sizeof (q80_link_event_t)));
1999f10a77bbSDavid C Somayajulu 
2000f10a77bbSDavid C Somayajulu 	lnk->opcode = Q8_MBX_LINK_EVENT_REQ;
2001f10a77bbSDavid C Somayajulu 	lnk->count_version = (sizeof (q80_link_event_t) >> 2);
2002f10a77bbSDavid C Somayajulu 	lnk->count_version |= Q8_MBX_CMD_VERSION;
2003f10a77bbSDavid C Somayajulu 
2004f10a77bbSDavid C Somayajulu 	lnk->cntxt_id = cntxt_id;
2005f10a77bbSDavid C Somayajulu 	lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC;
2006f10a77bbSDavid C Somayajulu 
2007f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2),
2008f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) {
2009f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
2010f10a77bbSDavid C Somayajulu                 return -1;
2011f10a77bbSDavid C Somayajulu         }
2012f10a77bbSDavid C Somayajulu 
2013f10a77bbSDavid C Somayajulu 	lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox;
2014f10a77bbSDavid C Somayajulu 
2015f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status);
2016f10a77bbSDavid C Somayajulu 
2017f10a77bbSDavid C Somayajulu         if (err) {
2018f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
2019f10a77bbSDavid C Somayajulu         }
2020f10a77bbSDavid C Somayajulu 
2021f10a77bbSDavid C Somayajulu 	return 0;
2022f10a77bbSDavid C Somayajulu }
2023f10a77bbSDavid C Somayajulu 
2024f10a77bbSDavid C Somayajulu static int
2025f10a77bbSDavid C Somayajulu qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id)
2026f10a77bbSDavid C Somayajulu {
2027f10a77bbSDavid C Somayajulu 	device_t		dev;
2028f10a77bbSDavid C Somayajulu 	q80_config_fw_lro_t	*fw_lro;
2029f10a77bbSDavid C Somayajulu 	q80_config_fw_lro_rsp_t	*fw_lro_rsp;
2030f10a77bbSDavid C Somayajulu 	uint32_t		err;
2031f10a77bbSDavid C Somayajulu 
2032f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2033f10a77bbSDavid C Somayajulu 
2034f10a77bbSDavid C Somayajulu 	fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox;
2035f10a77bbSDavid C Somayajulu 	bzero(fw_lro, sizeof(q80_config_fw_lro_t));
2036f10a77bbSDavid C Somayajulu 
2037f10a77bbSDavid C Somayajulu 	fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO;
2038f10a77bbSDavid C Somayajulu 	fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2);
2039f10a77bbSDavid C Somayajulu 	fw_lro->count_version |= Q8_MBX_CMD_VERSION;
2040f10a77bbSDavid C Somayajulu 
2041f10a77bbSDavid C Somayajulu 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK;
204235291c22SDavid C Somayajulu 	fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK;
2043f10a77bbSDavid C Somayajulu 
2044f10a77bbSDavid C Somayajulu 	fw_lro->cntxt_id = cntxt_id;
2045f10a77bbSDavid C Somayajulu 
2046f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)fw_lro,
2047f10a77bbSDavid C Somayajulu 		(sizeof (q80_config_fw_lro_t) >> 2),
2048f10a77bbSDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) {
2049f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
2050f10a77bbSDavid C Somayajulu 		return -1;
2051f10a77bbSDavid C Somayajulu 	}
2052f10a77bbSDavid C Somayajulu 
2053f10a77bbSDavid C Somayajulu 	fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox;
2054f10a77bbSDavid C Somayajulu 
2055f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status);
2056f10a77bbSDavid C Somayajulu 
2057f10a77bbSDavid C Somayajulu 	if (err) {
2058f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
2059f10a77bbSDavid C Somayajulu 	}
2060f10a77bbSDavid C Somayajulu 
2061f10a77bbSDavid C Somayajulu 	return 0;
2062f10a77bbSDavid C Somayajulu }
2063f10a77bbSDavid C Somayajulu 
206400caeec7SDavid C Somayajulu static int
206500caeec7SDavid C Somayajulu qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode)
206600caeec7SDavid C Somayajulu {
206700caeec7SDavid C Somayajulu 	device_t                dev;
206800caeec7SDavid C Somayajulu 	q80_hw_config_t         *hw_config;
206900caeec7SDavid C Somayajulu 	q80_hw_config_rsp_t     *hw_config_rsp;
207000caeec7SDavid C Somayajulu 	uint32_t                err;
207100caeec7SDavid C Somayajulu 
207200caeec7SDavid C Somayajulu 	dev = ha->pci_dev;
207300caeec7SDavid C Somayajulu 
207400caeec7SDavid C Somayajulu 	hw_config = (q80_hw_config_t *)ha->hw.mbox;
207500caeec7SDavid C Somayajulu 	bzero(hw_config, sizeof (q80_hw_config_t));
207600caeec7SDavid C Somayajulu 
207700caeec7SDavid C Somayajulu 	hw_config->opcode = Q8_MBX_HW_CONFIG;
207800caeec7SDavid C Somayajulu 	hw_config->count_version = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE_COUNT;
207900caeec7SDavid C Somayajulu 	hw_config->count_version |= Q8_MBX_CMD_VERSION;
208000caeec7SDavid C Somayajulu 
208100caeec7SDavid C Somayajulu 	hw_config->cmd = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE;
208200caeec7SDavid C Somayajulu 
208300caeec7SDavid C Somayajulu 	hw_config->u.set_cam_search_mode.mode = search_mode;
208400caeec7SDavid C Somayajulu 
208500caeec7SDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
208600caeec7SDavid C Somayajulu 		(sizeof (q80_hw_config_t) >> 2),
208700caeec7SDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
208800caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
208900caeec7SDavid C Somayajulu 		return -1;
209000caeec7SDavid C Somayajulu 	}
209100caeec7SDavid C Somayajulu 	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
209200caeec7SDavid C Somayajulu 
209300caeec7SDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
209400caeec7SDavid C Somayajulu 
209500caeec7SDavid C Somayajulu 	if (err) {
209600caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
209700caeec7SDavid C Somayajulu 	}
209800caeec7SDavid C Somayajulu 
209900caeec7SDavid C Somayajulu 	return 0;
210000caeec7SDavid C Somayajulu }
210100caeec7SDavid C Somayajulu 
210200caeec7SDavid C Somayajulu static int
210300caeec7SDavid C Somayajulu qla_get_cam_search_mode(qla_host_t *ha)
210400caeec7SDavid C Somayajulu {
210500caeec7SDavid C Somayajulu 	device_t                dev;
210600caeec7SDavid C Somayajulu 	q80_hw_config_t         *hw_config;
210700caeec7SDavid C Somayajulu 	q80_hw_config_rsp_t     *hw_config_rsp;
210800caeec7SDavid C Somayajulu 	uint32_t                err;
210900caeec7SDavid C Somayajulu 
211000caeec7SDavid C Somayajulu 	dev = ha->pci_dev;
211100caeec7SDavid C Somayajulu 
211200caeec7SDavid C Somayajulu 	hw_config = (q80_hw_config_t *)ha->hw.mbox;
211300caeec7SDavid C Somayajulu 	bzero(hw_config, sizeof (q80_hw_config_t));
211400caeec7SDavid C Somayajulu 
211500caeec7SDavid C Somayajulu 	hw_config->opcode = Q8_MBX_HW_CONFIG;
211600caeec7SDavid C Somayajulu 	hw_config->count_version = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE_COUNT;
211700caeec7SDavid C Somayajulu 	hw_config->count_version |= Q8_MBX_CMD_VERSION;
211800caeec7SDavid C Somayajulu 
211900caeec7SDavid C Somayajulu 	hw_config->cmd = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE;
212000caeec7SDavid C Somayajulu 
212100caeec7SDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
212200caeec7SDavid C Somayajulu 		(sizeof (q80_hw_config_t) >> 2),
212300caeec7SDavid C Somayajulu 		ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
212400caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
212500caeec7SDavid C Somayajulu 		return -1;
212600caeec7SDavid C Somayajulu 	}
212700caeec7SDavid C Somayajulu 	hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
212800caeec7SDavid C Somayajulu 
212900caeec7SDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
213000caeec7SDavid C Somayajulu 
213100caeec7SDavid C Somayajulu 	if (err) {
213200caeec7SDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
213300caeec7SDavid C Somayajulu 	} else {
213400caeec7SDavid C Somayajulu 		device_printf(dev, "%s: cam search mode [0x%08x]\n", __func__,
213500caeec7SDavid C Somayajulu 			hw_config_rsp->u.get_cam_search_mode.mode);
213600caeec7SDavid C Somayajulu 	}
213700caeec7SDavid C Somayajulu 
213800caeec7SDavid C Somayajulu 	return 0;
213900caeec7SDavid C Somayajulu }
214000caeec7SDavid C Somayajulu 
2141f10a77bbSDavid C Somayajulu static int
214235291c22SDavid C Somayajulu qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size)
2143f10a77bbSDavid C Somayajulu {
2144f10a77bbSDavid C Somayajulu 	device_t		dev;
2145f10a77bbSDavid C Somayajulu 	q80_get_stats_t		*stat;
2146f10a77bbSDavid C Somayajulu 	q80_get_stats_rsp_t	*stat_rsp;
2147f10a77bbSDavid C Somayajulu 	uint32_t		err;
2148f10a77bbSDavid C Somayajulu 
2149f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2150f10a77bbSDavid C Somayajulu 
2151f10a77bbSDavid C Somayajulu 	stat = (q80_get_stats_t *)ha->hw.mbox;
2152f10a77bbSDavid C Somayajulu 	bzero(stat, (sizeof (q80_get_stats_t)));
2153f10a77bbSDavid C Somayajulu 
2154f10a77bbSDavid C Somayajulu 	stat->opcode = Q8_MBX_GET_STATS;
2155f10a77bbSDavid C Somayajulu 	stat->count_version = 2;
2156f10a77bbSDavid C Somayajulu 	stat->count_version |= Q8_MBX_CMD_VERSION;
2157f10a77bbSDavid C Somayajulu 
2158f10a77bbSDavid C Somayajulu 	stat->cmd = cmd;
2159f10a77bbSDavid C Somayajulu 
2160f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)stat, 2,
216135291c22SDavid C Somayajulu                 ha->hw.mbox, (rsp_size >> 2), 0)) {
2162f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
2163f10a77bbSDavid C Somayajulu                 return -1;
2164f10a77bbSDavid C Somayajulu         }
2165f10a77bbSDavid C Somayajulu 
2166f10a77bbSDavid C Somayajulu 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
2167f10a77bbSDavid C Somayajulu 
2168f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status);
2169f10a77bbSDavid C Somayajulu 
2170f10a77bbSDavid C Somayajulu         if (err) {
2171f10a77bbSDavid C Somayajulu                 return -1;
2172f10a77bbSDavid C Somayajulu         }
2173f10a77bbSDavid C Somayajulu 
2174f10a77bbSDavid C Somayajulu 	return 0;
2175f10a77bbSDavid C Somayajulu }
2176f10a77bbSDavid C Somayajulu 
2177f10a77bbSDavid C Somayajulu void
2178f10a77bbSDavid C Somayajulu ql_get_stats(qla_host_t *ha)
2179f10a77bbSDavid C Somayajulu {
2180f10a77bbSDavid C Somayajulu 	q80_get_stats_rsp_t	*stat_rsp;
2181f10a77bbSDavid C Somayajulu 	q80_mac_stats_t		*mstat;
2182f10a77bbSDavid C Somayajulu 	q80_xmt_stats_t		*xstat;
2183f10a77bbSDavid C Somayajulu 	q80_rcv_stats_t		*rstat;
2184f10a77bbSDavid C Somayajulu 	uint32_t		cmd;
218535291c22SDavid C Somayajulu 	int			i;
21867fb51846SDavid C Somayajulu 	struct ifnet *ifp = ha->ifp;
21877fb51846SDavid C Somayajulu 
21887fb51846SDavid C Somayajulu 	if (ifp == NULL)
21897fb51846SDavid C Somayajulu 		return;
21907fb51846SDavid C Somayajulu 
21917fb51846SDavid C Somayajulu 	if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) != 0) {
21927fb51846SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: failed\n", __func__);
21937fb51846SDavid C Somayajulu 		return;
21947fb51846SDavid C Somayajulu 	}
21957fb51846SDavid C Somayajulu 
21967fb51846SDavid C Somayajulu 	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
21977fb51846SDavid C Somayajulu 		QLA_UNLOCK(ha, __func__);
21987fb51846SDavid C Somayajulu 		return;
21997fb51846SDavid C Somayajulu 	}
2200f10a77bbSDavid C Somayajulu 
2201f10a77bbSDavid C Somayajulu 	stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
2202f10a77bbSDavid C Somayajulu 	/*
2203f10a77bbSDavid C Somayajulu 	 * Get MAC Statistics
2204f10a77bbSDavid C Somayajulu 	 */
2205f10a77bbSDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_TYPE_MAC;
220635291c22SDavid C Somayajulu //	cmd |= Q8_GET_STATS_CMD_CLEAR;
2207f10a77bbSDavid C Somayajulu 
2208f10a77bbSDavid C Somayajulu 	cmd |= ((ha->pci_func & 0x1) << 16);
2209f10a77bbSDavid C Somayajulu 
2210b65c0c07SDavid C Somayajulu 	if (ha->qla_watchdog_pause || (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
2211b65c0c07SDavid C Somayajulu 		ha->offline)
22127fb51846SDavid C Somayajulu 		goto ql_get_stats_exit;
22137fb51846SDavid C Somayajulu 
221435291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
2215f10a77bbSDavid C Somayajulu 		mstat = (q80_mac_stats_t *)&stat_rsp->u.mac;
22167fb51846SDavid C Somayajulu 		bcopy(mstat, &ha->hw.mac, sizeof(q80_mac_stats_t));
2217f10a77bbSDavid C Somayajulu 	} else {
2218f10a77bbSDavid C Somayajulu                 device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n",
2219f10a77bbSDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
2220f10a77bbSDavid C Somayajulu 	}
2221f10a77bbSDavid C Somayajulu 	/*
2222f10a77bbSDavid C Somayajulu 	 * Get RCV Statistics
2223f10a77bbSDavid C Somayajulu 	 */
2224f10a77bbSDavid C Somayajulu 	cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT;
222535291c22SDavid C Somayajulu //	cmd |= Q8_GET_STATS_CMD_CLEAR;
2226f10a77bbSDavid C Somayajulu 	cmd |= (ha->hw.rcv_cntxt_id << 16);
2227f10a77bbSDavid C Somayajulu 
2228b65c0c07SDavid C Somayajulu 	if (ha->qla_watchdog_pause || (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
2229b65c0c07SDavid C Somayajulu 		ha->offline)
22307fb51846SDavid C Somayajulu 		goto ql_get_stats_exit;
22317fb51846SDavid C Somayajulu 
223235291c22SDavid C Somayajulu 	if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
2233f10a77bbSDavid C Somayajulu 		rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv;
22347fb51846SDavid C Somayajulu 		bcopy(rstat, &ha->hw.rcv, sizeof(q80_rcv_stats_t));
2235f10a77bbSDavid C Somayajulu 	} else {
2236f10a77bbSDavid C Somayajulu                 device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n",
2237f10a77bbSDavid C Somayajulu 			__func__, ha->hw.mbox[0]);
2238f10a77bbSDavid C Somayajulu 	}
22397fb51846SDavid C Somayajulu 
2240b65c0c07SDavid C Somayajulu 	if (ha->qla_watchdog_pause || (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
2241b65c0c07SDavid C Somayajulu 		ha->offline)
22427fb51846SDavid C Somayajulu 		goto ql_get_stats_exit;
2243f10a77bbSDavid C Somayajulu 	/*
2244f10a77bbSDavid C Somayajulu 	 * Get XMT Statistics
2245f10a77bbSDavid C Somayajulu 	 */
2246b65c0c07SDavid C Somayajulu 	for (i = 0 ; (i < ha->hw.num_tx_rings); i++) {
2247b65c0c07SDavid C Somayajulu 		if (ha->qla_watchdog_pause ||
2248b65c0c07SDavid C Somayajulu 			(!(ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
2249b65c0c07SDavid C Somayajulu 			ha->offline)
2250b65c0c07SDavid C Somayajulu 			goto ql_get_stats_exit;
2251b65c0c07SDavid C Somayajulu 
2252f10a77bbSDavid C Somayajulu 		cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT;
225335291c22SDavid C Somayajulu //		cmd |= Q8_GET_STATS_CMD_CLEAR;
225435291c22SDavid C Somayajulu 		cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16);
2255f10a77bbSDavid C Somayajulu 
225635291c22SDavid C Somayajulu 		if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t))
225735291c22SDavid C Somayajulu 			== 0) {
2258f10a77bbSDavid C Somayajulu 			xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt;
22597fb51846SDavid C Somayajulu 			bcopy(xstat, &ha->hw.xmt[i], sizeof(q80_xmt_stats_t));
2260f10a77bbSDavid C Somayajulu 		} else {
2261f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n",
2262f10a77bbSDavid C Somayajulu 				__func__, ha->hw.mbox[0]);
2263f10a77bbSDavid C Somayajulu 		}
2264f10a77bbSDavid C Somayajulu 	}
226535291c22SDavid C Somayajulu 
22667fb51846SDavid C Somayajulu ql_get_stats_exit:
22677fb51846SDavid C Somayajulu 	QLA_UNLOCK(ha, __func__);
226835291c22SDavid C Somayajulu 
226935291c22SDavid C Somayajulu 	return;
227035291c22SDavid C Somayajulu }
2271f10a77bbSDavid C Somayajulu 
2272f10a77bbSDavid C Somayajulu /*
2273f10a77bbSDavid C Somayajulu  * Name: qla_tx_tso
2274f10a77bbSDavid C Somayajulu  * Function: Checks if the packet to be transmitted is a candidate for
2275f10a77bbSDavid C Somayajulu  *	Large TCP Segment Offload. If yes, the appropriate fields in the Tx
2276f10a77bbSDavid C Somayajulu  *	Ring Structure are plugged in.
2277f10a77bbSDavid C Somayajulu  */
2278f10a77bbSDavid C Somayajulu static int
2279f10a77bbSDavid C Somayajulu qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
2280f10a77bbSDavid C Somayajulu {
2281f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
2282f10a77bbSDavid C Somayajulu 	struct ip *ip = NULL;
2283f10a77bbSDavid C Somayajulu 	struct ip6_hdr *ip6 = NULL;
2284f10a77bbSDavid C Somayajulu 	struct tcphdr *th = NULL;
2285f10a77bbSDavid C Somayajulu 	uint32_t ehdrlen,  hdrlen, ip_hlen, tcp_hlen, tcp_opt_off;
2286f10a77bbSDavid C Somayajulu 	uint16_t etype, opcode, offload = 1;
2287f10a77bbSDavid C Somayajulu 	device_t dev;
2288f10a77bbSDavid C Somayajulu 
2289f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2290f10a77bbSDavid C Somayajulu 
2291f10a77bbSDavid C Somayajulu 
2292f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
2293f10a77bbSDavid C Somayajulu 
2294f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2295f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
2296f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_proto);
2297f10a77bbSDavid C Somayajulu 	} else {
2298f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN;
2299f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_encap_proto);
2300f10a77bbSDavid C Somayajulu 	}
2301f10a77bbSDavid C Somayajulu 
2302f10a77bbSDavid C Somayajulu 	hdrlen = 0;
2303f10a77bbSDavid C Somayajulu 
2304f10a77bbSDavid C Somayajulu 	switch (etype) {
2305f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IP:
2306f10a77bbSDavid C Somayajulu 
2307f10a77bbSDavid C Somayajulu 			tcp_opt_off = ehdrlen + sizeof(struct ip) +
2308f10a77bbSDavid C Somayajulu 					sizeof(struct tcphdr);
2309f10a77bbSDavid C Somayajulu 
2310f10a77bbSDavid C Somayajulu 			if (mp->m_len < tcp_opt_off) {
2311f10a77bbSDavid C Somayajulu 				m_copydata(mp, 0, tcp_opt_off, hdr);
2312f10a77bbSDavid C Somayajulu 				ip = (struct ip *)(hdr + ehdrlen);
2313f10a77bbSDavid C Somayajulu 			} else {
2314f10a77bbSDavid C Somayajulu 				ip = (struct ip *)(mp->m_data + ehdrlen);
2315f10a77bbSDavid C Somayajulu 			}
2316f10a77bbSDavid C Somayajulu 
2317f10a77bbSDavid C Somayajulu 			ip_hlen = ip->ip_hl << 2;
2318f10a77bbSDavid C Somayajulu 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
2319f10a77bbSDavid C Somayajulu 
2320f10a77bbSDavid C Somayajulu 
2321f10a77bbSDavid C Somayajulu 			if ((ip->ip_p != IPPROTO_TCP) ||
2322f10a77bbSDavid C Somayajulu 				(ip_hlen != sizeof (struct ip))){
2323f10a77bbSDavid C Somayajulu 				/* IP Options are not supported */
2324f10a77bbSDavid C Somayajulu 
2325f10a77bbSDavid C Somayajulu 				offload = 0;
2326f10a77bbSDavid C Somayajulu 			} else
2327f10a77bbSDavid C Somayajulu 				th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
2328f10a77bbSDavid C Somayajulu 
2329f10a77bbSDavid C Somayajulu 		break;
2330f10a77bbSDavid C Somayajulu 
2331f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IPV6:
2332f10a77bbSDavid C Somayajulu 
2333f10a77bbSDavid C Somayajulu 			tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) +
2334f10a77bbSDavid C Somayajulu 					sizeof (struct tcphdr);
2335f10a77bbSDavid C Somayajulu 
2336f10a77bbSDavid C Somayajulu 			if (mp->m_len < tcp_opt_off) {
2337f10a77bbSDavid C Somayajulu 				m_copydata(mp, 0, tcp_opt_off, hdr);
2338f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)(hdr + ehdrlen);
2339f10a77bbSDavid C Somayajulu 			} else {
2340f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
2341f10a77bbSDavid C Somayajulu 			}
2342f10a77bbSDavid C Somayajulu 
2343f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof(struct ip6_hdr);
2344f10a77bbSDavid C Somayajulu 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6;
2345f10a77bbSDavid C Somayajulu 
2346f10a77bbSDavid C Somayajulu 			if (ip6->ip6_nxt != IPPROTO_TCP) {
2347f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv6\n", __func__);
2348f10a77bbSDavid C Somayajulu 				offload = 0;
2349f10a77bbSDavid C Somayajulu 			} else
2350f10a77bbSDavid C Somayajulu 				th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
2351f10a77bbSDavid C Somayajulu 		break;
2352f10a77bbSDavid C Somayajulu 
2353f10a77bbSDavid C Somayajulu 		default:
2354f10a77bbSDavid C Somayajulu 			QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__));
2355f10a77bbSDavid C Somayajulu 			offload = 0;
2356f10a77bbSDavid C Somayajulu 		break;
2357f10a77bbSDavid C Somayajulu 	}
2358f10a77bbSDavid C Somayajulu 
2359f10a77bbSDavid C Somayajulu 	if (!offload)
2360f10a77bbSDavid C Somayajulu 		return (-1);
2361f10a77bbSDavid C Somayajulu 
2362f10a77bbSDavid C Somayajulu 	tcp_hlen = th->th_off << 2;
2363f10a77bbSDavid C Somayajulu 	hdrlen = ehdrlen + ip_hlen + tcp_hlen;
2364f10a77bbSDavid C Somayajulu 
2365f10a77bbSDavid C Somayajulu         if (mp->m_len < hdrlen) {
2366f10a77bbSDavid C Somayajulu                 if (mp->m_len < tcp_opt_off) {
2367f10a77bbSDavid C Somayajulu                         if (tcp_hlen > sizeof(struct tcphdr)) {
2368f10a77bbSDavid C Somayajulu                                 m_copydata(mp, tcp_opt_off,
2369f10a77bbSDavid C Somayajulu                                         (tcp_hlen - sizeof(struct tcphdr)),
2370f10a77bbSDavid C Somayajulu                                         &hdr[tcp_opt_off]);
2371f10a77bbSDavid C Somayajulu                         }
2372f10a77bbSDavid C Somayajulu                 } else {
2373f10a77bbSDavid C Somayajulu                         m_copydata(mp, 0, hdrlen, hdr);
2374f10a77bbSDavid C Somayajulu                 }
2375f10a77bbSDavid C Somayajulu         }
2376f10a77bbSDavid C Somayajulu 
2377f10a77bbSDavid C Somayajulu 	tx_cmd->mss = mp->m_pkthdr.tso_segsz;
2378f10a77bbSDavid C Somayajulu 
2379f10a77bbSDavid C Somayajulu 	tx_cmd->flags_opcode = opcode ;
2380f10a77bbSDavid C Somayajulu 	tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen;
2381f10a77bbSDavid C Somayajulu 	tx_cmd->total_hdr_len = hdrlen;
2382f10a77bbSDavid C Somayajulu 
2383f10a77bbSDavid C Somayajulu 	/* Check for Multicast least significant bit of MSB == 1 */
2384f10a77bbSDavid C Somayajulu 	if (eh->evl_dhost[0] & 0x01) {
2385f10a77bbSDavid C Somayajulu 		tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST;
2386f10a77bbSDavid C Somayajulu 	}
2387f10a77bbSDavid C Somayajulu 
2388f10a77bbSDavid C Somayajulu 	if (mp->m_len < hdrlen) {
2389f10a77bbSDavid C Somayajulu 		printf("%d\n", hdrlen);
2390f10a77bbSDavid C Somayajulu 		return (1);
2391f10a77bbSDavid C Somayajulu 	}
2392f10a77bbSDavid C Somayajulu 
2393f10a77bbSDavid C Somayajulu 	return (0);
2394f10a77bbSDavid C Somayajulu }
2395f10a77bbSDavid C Somayajulu 
2396f10a77bbSDavid C Somayajulu /*
2397f10a77bbSDavid C Somayajulu  * Name: qla_tx_chksum
2398f10a77bbSDavid C Somayajulu  * Function: Checks if the packet to be transmitted is a candidate for
2399f10a77bbSDavid C Somayajulu  *	TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx
2400f10a77bbSDavid C Somayajulu  *	Ring Structure are plugged in.
2401f10a77bbSDavid C Somayajulu  */
2402f10a77bbSDavid C Somayajulu static int
2403f10a77bbSDavid C Somayajulu qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code,
2404f10a77bbSDavid C Somayajulu 	uint32_t *tcp_hdr_off)
2405f10a77bbSDavid C Somayajulu {
2406f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
2407f10a77bbSDavid C Somayajulu 	struct ip *ip;
2408f10a77bbSDavid C Somayajulu 	struct ip6_hdr *ip6;
2409f10a77bbSDavid C Somayajulu 	uint32_t ehdrlen, ip_hlen;
2410f10a77bbSDavid C Somayajulu 	uint16_t etype, opcode, offload = 1;
2411f10a77bbSDavid C Somayajulu 	device_t dev;
2412f10a77bbSDavid C Somayajulu 	uint8_t buf[sizeof(struct ip6_hdr)];
2413f10a77bbSDavid C Somayajulu 
2414f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2415f10a77bbSDavid C Somayajulu 
2416f10a77bbSDavid C Somayajulu 	*op_code = 0;
2417f10a77bbSDavid C Somayajulu 
24187fb51846SDavid C Somayajulu 	if ((mp->m_pkthdr.csum_flags &
24197fb51846SDavid C Somayajulu 		(CSUM_TCP|CSUM_UDP|CSUM_TCP_IPV6 | CSUM_UDP_IPV6)) == 0)
2420f10a77bbSDavid C Somayajulu 		return (-1);
2421f10a77bbSDavid C Somayajulu 
2422f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
2423f10a77bbSDavid C Somayajulu 
2424f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2425f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
2426f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_proto);
2427f10a77bbSDavid C Somayajulu 	} else {
2428f10a77bbSDavid C Somayajulu 		ehdrlen = ETHER_HDR_LEN;
2429f10a77bbSDavid C Somayajulu 		etype = ntohs(eh->evl_encap_proto);
2430f10a77bbSDavid C Somayajulu 	}
2431f10a77bbSDavid C Somayajulu 
2432f10a77bbSDavid C Somayajulu 
2433f10a77bbSDavid C Somayajulu 	switch (etype) {
2434f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IP:
2435f10a77bbSDavid C Somayajulu 			ip = (struct ip *)(mp->m_data + ehdrlen);
2436f10a77bbSDavid C Somayajulu 
2437f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof (struct ip);
2438f10a77bbSDavid C Somayajulu 
2439f10a77bbSDavid C Somayajulu 			if (mp->m_len < (ehdrlen + ip_hlen)) {
2440f10a77bbSDavid C Somayajulu 				m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
2441f10a77bbSDavid C Somayajulu 				ip = (struct ip *)buf;
2442f10a77bbSDavid C Somayajulu 			}
2443f10a77bbSDavid C Somayajulu 
2444f10a77bbSDavid C Somayajulu 			if (ip->ip_p == IPPROTO_TCP)
2445f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM;
2446f10a77bbSDavid C Somayajulu 			else if (ip->ip_p == IPPROTO_UDP)
2447f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM;
2448f10a77bbSDavid C Somayajulu 			else {
2449f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv4\n", __func__);
2450f10a77bbSDavid C Somayajulu 				offload = 0;
2451f10a77bbSDavid C Somayajulu 			}
2452f10a77bbSDavid C Somayajulu 		break;
2453f10a77bbSDavid C Somayajulu 
2454f10a77bbSDavid C Somayajulu 		case ETHERTYPE_IPV6:
2455f10a77bbSDavid C Somayajulu 			ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
2456f10a77bbSDavid C Somayajulu 
2457f10a77bbSDavid C Somayajulu 			ip_hlen = sizeof(struct ip6_hdr);
2458f10a77bbSDavid C Somayajulu 
2459f10a77bbSDavid C Somayajulu 			if (mp->m_len < (ehdrlen + ip_hlen)) {
2460f10a77bbSDavid C Somayajulu 				m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
2461f10a77bbSDavid C Somayajulu 					buf);
2462f10a77bbSDavid C Somayajulu 				ip6 = (struct ip6_hdr *)buf;
2463f10a77bbSDavid C Somayajulu 			}
2464f10a77bbSDavid C Somayajulu 
2465f10a77bbSDavid C Somayajulu 			if (ip6->ip6_nxt == IPPROTO_TCP)
2466f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6;
2467f10a77bbSDavid C Somayajulu 			else if (ip6->ip6_nxt == IPPROTO_UDP)
2468f10a77bbSDavid C Somayajulu 				opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6;
2469f10a77bbSDavid C Somayajulu 			else {
2470f10a77bbSDavid C Somayajulu 				//device_printf(dev, "%s: ipv6\n", __func__);
2471f10a77bbSDavid C Somayajulu 				offload = 0;
2472f10a77bbSDavid C Somayajulu 			}
2473f10a77bbSDavid C Somayajulu 		break;
2474f10a77bbSDavid C Somayajulu 
2475f10a77bbSDavid C Somayajulu 		default:
2476f10a77bbSDavid C Somayajulu 			offload = 0;
2477f10a77bbSDavid C Somayajulu 		break;
2478f10a77bbSDavid C Somayajulu 	}
2479f10a77bbSDavid C Somayajulu 	if (!offload)
2480f10a77bbSDavid C Somayajulu 		return (-1);
2481f10a77bbSDavid C Somayajulu 
2482f10a77bbSDavid C Somayajulu 	*op_code = opcode;
2483f10a77bbSDavid C Somayajulu 	*tcp_hdr_off = (ip_hlen + ehdrlen);
2484f10a77bbSDavid C Somayajulu 
2485f10a77bbSDavid C Somayajulu 	return (0);
2486f10a77bbSDavid C Somayajulu }
2487f10a77bbSDavid C Somayajulu 
2488f10a77bbSDavid C Somayajulu #define QLA_TX_MIN_FREE 2
2489f10a77bbSDavid C Somayajulu /*
2490f10a77bbSDavid C Somayajulu  * Name: ql_hw_send
2491f10a77bbSDavid C Somayajulu  * Function: Transmits a packet. It first checks if the packet is a
2492f10a77bbSDavid C Somayajulu  *	candidate for Large TCP Segment Offload and then for UDP/TCP checksum
2493f10a77bbSDavid C Somayajulu  *	offload. If either of these creteria are not met, it is transmitted
2494f10a77bbSDavid C Somayajulu  *	as a regular ethernet frame.
2495f10a77bbSDavid C Somayajulu  */
2496f10a77bbSDavid C Somayajulu int
2497f10a77bbSDavid C Somayajulu ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
249835291c22SDavid C Somayajulu 	uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu)
2499f10a77bbSDavid C Somayajulu {
2500f10a77bbSDavid C Somayajulu 	struct ether_vlan_header *eh;
2501f10a77bbSDavid C Somayajulu 	qla_hw_t *hw = &ha->hw;
2502f10a77bbSDavid C Somayajulu 	q80_tx_cmd_t *tx_cmd, tso_cmd;
2503f10a77bbSDavid C Somayajulu 	bus_dma_segment_t *c_seg;
2504f10a77bbSDavid C Somayajulu 	uint32_t num_tx_cmds, hdr_len = 0;
2505f10a77bbSDavid C Somayajulu 	uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next;
2506f10a77bbSDavid C Somayajulu 	device_t dev;
2507f10a77bbSDavid C Somayajulu 	int i, ret;
2508f10a77bbSDavid C Somayajulu 	uint8_t *src = NULL, *dst = NULL;
2509f10a77bbSDavid C Somayajulu 	uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
2510f10a77bbSDavid C Somayajulu 	uint32_t op_code = 0;
2511f10a77bbSDavid C Somayajulu 	uint32_t tcp_hdr_off = 0;
2512f10a77bbSDavid C Somayajulu 
2513f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2514f10a77bbSDavid C Somayajulu 
2515f10a77bbSDavid C Somayajulu 	/*
2516f10a77bbSDavid C Somayajulu 	 * Always make sure there is atleast one empty slot in the tx_ring
2517f10a77bbSDavid C Somayajulu 	 * tx_ring is considered full when there only one entry available
2518f10a77bbSDavid C Somayajulu 	 */
2519f10a77bbSDavid C Somayajulu         num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2;
2520f10a77bbSDavid C Somayajulu 
2521f10a77bbSDavid C Somayajulu 	total_length = mp->m_pkthdr.len;
2522f10a77bbSDavid C Somayajulu 	if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
2523f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
2524f10a77bbSDavid C Somayajulu 			__func__, total_length);
2525203f9d18SDavid C Somayajulu 		return (EINVAL);
2526f10a77bbSDavid C Somayajulu 	}
2527f10a77bbSDavid C Somayajulu 	eh = mtod(mp, struct ether_vlan_header *);
2528f10a77bbSDavid C Somayajulu 
2529f10a77bbSDavid C Somayajulu 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2530f10a77bbSDavid C Somayajulu 
2531f10a77bbSDavid C Somayajulu 		bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
2532f10a77bbSDavid C Somayajulu 
2533f10a77bbSDavid C Somayajulu 		src = frame_hdr;
2534f10a77bbSDavid C Somayajulu 		ret = qla_tx_tso(ha, mp, &tso_cmd, src);
2535f10a77bbSDavid C Somayajulu 
2536f10a77bbSDavid C Somayajulu 		if (!(ret & ~1)) {
2537f10a77bbSDavid C Somayajulu 			/* find the additional tx_cmd descriptors required */
2538f10a77bbSDavid C Somayajulu 
2539f10a77bbSDavid C Somayajulu 			if (mp->m_flags & M_VLANTAG)
2540f10a77bbSDavid C Somayajulu 				tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN;
2541f10a77bbSDavid C Somayajulu 
2542f10a77bbSDavid C Somayajulu 			hdr_len = tso_cmd.total_hdr_len;
2543f10a77bbSDavid C Somayajulu 
2544f10a77bbSDavid C Somayajulu 			bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2545f10a77bbSDavid C Somayajulu 			bytes = QL_MIN(bytes, hdr_len);
2546f10a77bbSDavid C Somayajulu 
2547f10a77bbSDavid C Somayajulu 			num_tx_cmds++;
2548f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2549f10a77bbSDavid C Somayajulu 
2550f10a77bbSDavid C Somayajulu 			while (hdr_len) {
2551f10a77bbSDavid C Somayajulu 				bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2552f10a77bbSDavid C Somayajulu 				hdr_len -= bytes;
2553f10a77bbSDavid C Somayajulu 				num_tx_cmds++;
2554f10a77bbSDavid C Somayajulu 			}
2555f10a77bbSDavid C Somayajulu 			hdr_len = tso_cmd.total_hdr_len;
2556f10a77bbSDavid C Somayajulu 
2557f10a77bbSDavid C Somayajulu 			if (ret == 0)
2558f10a77bbSDavid C Somayajulu 				src = (uint8_t *)eh;
2559f10a77bbSDavid C Somayajulu 		} else
2560f10a77bbSDavid C Somayajulu 			return (EINVAL);
2561f10a77bbSDavid C Somayajulu 	} else {
2562f10a77bbSDavid C Somayajulu 		(void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off);
2563f10a77bbSDavid C Somayajulu 	}
2564f10a77bbSDavid C Somayajulu 
2565f10a77bbSDavid C Somayajulu 	if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
2566b89f2279SDavid C Somayajulu 		ql_hw_tx_done_locked(ha, txr_idx);
2567f10a77bbSDavid C Somayajulu 		if (hw->tx_cntxt[txr_idx].txr_free <=
2568f10a77bbSDavid C Somayajulu 				(num_tx_cmds + QLA_TX_MIN_FREE)) {
2569f10a77bbSDavid C Somayajulu         		QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= "
2570f10a77bbSDavid C Somayajulu 				"(num_tx_cmds + QLA_TX_MIN_FREE))\n",
2571f10a77bbSDavid C Somayajulu 				__func__));
2572f10a77bbSDavid C Somayajulu 			return (-1);
2573f10a77bbSDavid C Somayajulu 		}
2574f10a77bbSDavid C Somayajulu 	}
2575f10a77bbSDavid C Somayajulu 
2576c6acf96aSDavid C Somayajulu 	for (i = 0; i < num_tx_cmds; i++) {
2577c6acf96aSDavid C Somayajulu 		int j;
2578c6acf96aSDavid C Somayajulu 
2579c6acf96aSDavid C Somayajulu 		j = (tx_idx+i) & (NUM_TX_DESCRIPTORS - 1);
2580c6acf96aSDavid C Somayajulu 
2581c6acf96aSDavid C Somayajulu 		if (NULL != ha->tx_ring[txr_idx].tx_buf[j].m_head) {
2582c6acf96aSDavid C Somayajulu 			QL_ASSERT(ha, 0, \
2583c6acf96aSDavid C Somayajulu 				("%s [%d]: txr_idx = %d tx_idx = %d mbuf = %p\n",\
2584c6acf96aSDavid C Somayajulu 				__func__, __LINE__, txr_idx, j,\
2585c6acf96aSDavid C Somayajulu 				ha->tx_ring[txr_idx].tx_buf[j].m_head));
2586c6acf96aSDavid C Somayajulu 			return (EINVAL);
2587c6acf96aSDavid C Somayajulu 		}
2588c6acf96aSDavid C Somayajulu 	}
2589c6acf96aSDavid C Somayajulu 
2590f10a77bbSDavid C Somayajulu 	tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx];
2591f10a77bbSDavid C Somayajulu 
2592f10a77bbSDavid C Somayajulu         if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) {
2593f10a77bbSDavid C Somayajulu 
2594f10a77bbSDavid C Somayajulu                 if (nsegs > ha->hw.max_tx_segs)
2595f10a77bbSDavid C Somayajulu                         ha->hw.max_tx_segs = nsegs;
2596f10a77bbSDavid C Somayajulu 
2597f10a77bbSDavid C Somayajulu                 bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2598f10a77bbSDavid C Somayajulu 
2599f10a77bbSDavid C Somayajulu                 if (op_code) {
2600f10a77bbSDavid C Somayajulu                         tx_cmd->flags_opcode = op_code;
2601f10a77bbSDavid C Somayajulu                         tx_cmd->tcp_hdr_off = tcp_hdr_off;
2602f10a77bbSDavid C Somayajulu 
2603f10a77bbSDavid C Somayajulu                 } else {
2604f10a77bbSDavid C Somayajulu                         tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER;
2605f10a77bbSDavid C Somayajulu                 }
2606f10a77bbSDavid C Somayajulu 	} else {
2607f10a77bbSDavid C Somayajulu 		bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
2608f10a77bbSDavid C Somayajulu 		ha->tx_tso_frames++;
2609f10a77bbSDavid C Somayajulu 	}
2610f10a77bbSDavid C Somayajulu 
2611f10a77bbSDavid C Somayajulu 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2612f10a77bbSDavid C Somayajulu         	tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
261335291c22SDavid C Somayajulu 
261435291c22SDavid C Somayajulu 		if (iscsi_pdu)
261535291c22SDavid C Somayajulu 			eh->evl_tag |= ha->hw.user_pri_iscsi << 13;
261635291c22SDavid C Somayajulu 
2617f10a77bbSDavid C Somayajulu 	} else if (mp->m_flags & M_VLANTAG) {
2618f10a77bbSDavid C Somayajulu 
2619f10a77bbSDavid C Somayajulu 		if (hdr_len) { /* TSO */
2620f10a77bbSDavid C Somayajulu 			tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED |
2621f10a77bbSDavid C Somayajulu 						Q8_TX_CMD_FLAGS_HW_VLAN_ID);
2622f10a77bbSDavid C Somayajulu 			tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN;
2623f10a77bbSDavid C Somayajulu 		} else
2624f10a77bbSDavid C Somayajulu 			tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID;
2625f10a77bbSDavid C Somayajulu 
2626f10a77bbSDavid C Somayajulu 		ha->hw_vlan_tx_frames++;
2627f10a77bbSDavid C Somayajulu 		tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag;
262835291c22SDavid C Somayajulu 
262935291c22SDavid C Somayajulu 		if (iscsi_pdu) {
263035291c22SDavid C Somayajulu 			tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13;
263135291c22SDavid C Somayajulu 			mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci;
263235291c22SDavid C Somayajulu 		}
2633f10a77bbSDavid C Somayajulu 	}
2634f10a77bbSDavid C Somayajulu 
2635f10a77bbSDavid C Somayajulu 
2636f10a77bbSDavid C Somayajulu         tx_cmd->n_bufs = (uint8_t)nsegs;
2637f10a77bbSDavid C Somayajulu         tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF);
2638f10a77bbSDavid C Somayajulu         tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8)));
2639f10a77bbSDavid C Somayajulu 	tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func);
2640f10a77bbSDavid C Somayajulu 
2641f10a77bbSDavid C Somayajulu 	c_seg = segs;
2642f10a77bbSDavid C Somayajulu 
2643f10a77bbSDavid C Somayajulu 	while (1) {
2644f10a77bbSDavid C Somayajulu 		for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) {
2645f10a77bbSDavid C Somayajulu 
2646f10a77bbSDavid C Somayajulu 			switch (i) {
2647f10a77bbSDavid C Somayajulu 			case 0:
2648f10a77bbSDavid C Somayajulu 				tx_cmd->buf1_addr = c_seg->ds_addr;
2649f10a77bbSDavid C Somayajulu 				tx_cmd->buf1_len = c_seg->ds_len;
2650f10a77bbSDavid C Somayajulu 				break;
2651f10a77bbSDavid C Somayajulu 
2652f10a77bbSDavid C Somayajulu 			case 1:
2653f10a77bbSDavid C Somayajulu 				tx_cmd->buf2_addr = c_seg->ds_addr;
2654f10a77bbSDavid C Somayajulu 				tx_cmd->buf2_len = c_seg->ds_len;
2655f10a77bbSDavid C Somayajulu 				break;
2656f10a77bbSDavid C Somayajulu 
2657f10a77bbSDavid C Somayajulu 			case 2:
2658f10a77bbSDavid C Somayajulu 				tx_cmd->buf3_addr = c_seg->ds_addr;
2659f10a77bbSDavid C Somayajulu 				tx_cmd->buf3_len = c_seg->ds_len;
2660f10a77bbSDavid C Somayajulu 				break;
2661f10a77bbSDavid C Somayajulu 
2662f10a77bbSDavid C Somayajulu 			case 3:
2663f10a77bbSDavid C Somayajulu 				tx_cmd->buf4_addr = c_seg->ds_addr;
2664f10a77bbSDavid C Somayajulu 				tx_cmd->buf4_len = c_seg->ds_len;
2665f10a77bbSDavid C Somayajulu 				break;
2666f10a77bbSDavid C Somayajulu 			}
2667f10a77bbSDavid C Somayajulu 
2668f10a77bbSDavid C Somayajulu 			c_seg++;
2669f10a77bbSDavid C Somayajulu 			nsegs--;
2670f10a77bbSDavid C Somayajulu 		}
2671f10a77bbSDavid C Somayajulu 
2672f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2673f10a77bbSDavid C Somayajulu 			(hw->tx_cntxt[txr_idx].txr_next + 1) &
2674f10a77bbSDavid C Somayajulu 				(NUM_TX_DESCRIPTORS - 1);
2675f10a77bbSDavid C Somayajulu 		tx_cmd_count++;
2676f10a77bbSDavid C Somayajulu 
2677f10a77bbSDavid C Somayajulu 		if (!nsegs)
2678f10a77bbSDavid C Somayajulu 			break;
2679f10a77bbSDavid C Somayajulu 
2680f10a77bbSDavid C Somayajulu 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2681f10a77bbSDavid C Somayajulu 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2682f10a77bbSDavid C Somayajulu 	}
2683f10a77bbSDavid C Somayajulu 
2684f10a77bbSDavid C Somayajulu 	if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2685f10a77bbSDavid C Somayajulu 
2686f10a77bbSDavid C Somayajulu 		/* TSO : Copy the header in the following tx cmd descriptors */
2687f10a77bbSDavid C Somayajulu 
2688f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next;
2689f10a77bbSDavid C Somayajulu 
2690f10a77bbSDavid C Somayajulu 		tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2691f10a77bbSDavid C Somayajulu 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2692f10a77bbSDavid C Somayajulu 
2693f10a77bbSDavid C Somayajulu 		bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2694f10a77bbSDavid C Somayajulu 		bytes = QL_MIN(bytes, hdr_len);
2695f10a77bbSDavid C Somayajulu 
2696f10a77bbSDavid C Somayajulu 		dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN;
2697f10a77bbSDavid C Somayajulu 
2698f10a77bbSDavid C Somayajulu 		if (mp->m_flags & M_VLANTAG) {
2699f10a77bbSDavid C Somayajulu 			/* first copy the src/dst MAC addresses */
2700f10a77bbSDavid C Somayajulu 			bcopy(src, dst, (ETHER_ADDR_LEN * 2));
2701f10a77bbSDavid C Somayajulu 			dst += (ETHER_ADDR_LEN * 2);
2702f10a77bbSDavid C Somayajulu 			src += (ETHER_ADDR_LEN * 2);
2703f10a77bbSDavid C Somayajulu 
2704f10a77bbSDavid C Somayajulu 			*((uint16_t *)dst) = htons(ETHERTYPE_VLAN);
2705f10a77bbSDavid C Somayajulu 			dst += 2;
2706f10a77bbSDavid C Somayajulu 			*((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag);
2707f10a77bbSDavid C Somayajulu 			dst += 2;
2708f10a77bbSDavid C Somayajulu 
2709f10a77bbSDavid C Somayajulu 			/* bytes left in src header */
2710f10a77bbSDavid C Somayajulu 			hdr_len -= ((ETHER_ADDR_LEN * 2) +
2711f10a77bbSDavid C Somayajulu 					ETHER_VLAN_ENCAP_LEN);
2712f10a77bbSDavid C Somayajulu 
2713f10a77bbSDavid C Somayajulu 			/* bytes left in TxCmd Entry */
2714f10a77bbSDavid C Somayajulu 			bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN);
2715f10a77bbSDavid C Somayajulu 
2716f10a77bbSDavid C Somayajulu 
2717f10a77bbSDavid C Somayajulu 			bcopy(src, dst, bytes);
2718f10a77bbSDavid C Somayajulu 			src += bytes;
2719f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2720f10a77bbSDavid C Somayajulu 		} else {
2721f10a77bbSDavid C Somayajulu 			bcopy(src, dst, bytes);
2722f10a77bbSDavid C Somayajulu 			src += bytes;
2723f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2724f10a77bbSDavid C Somayajulu 		}
2725f10a77bbSDavid C Somayajulu 
2726f10a77bbSDavid C Somayajulu 		txr_next = hw->tx_cntxt[txr_idx].txr_next =
2727f10a77bbSDavid C Somayajulu 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2728f10a77bbSDavid C Somayajulu 					(NUM_TX_DESCRIPTORS - 1);
2729f10a77bbSDavid C Somayajulu 		tx_cmd_count++;
2730f10a77bbSDavid C Somayajulu 
2731f10a77bbSDavid C Somayajulu 		while (hdr_len) {
2732f10a77bbSDavid C Somayajulu 			tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2733f10a77bbSDavid C Somayajulu 			bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2734f10a77bbSDavid C Somayajulu 
2735f10a77bbSDavid C Somayajulu 			bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2736f10a77bbSDavid C Somayajulu 
2737f10a77bbSDavid C Somayajulu 			bcopy(src, tx_cmd, bytes);
2738f10a77bbSDavid C Somayajulu 			src += bytes;
2739f10a77bbSDavid C Somayajulu 			hdr_len -= bytes;
2740f10a77bbSDavid C Somayajulu 
2741f10a77bbSDavid C Somayajulu 			txr_next = hw->tx_cntxt[txr_idx].txr_next =
2742f10a77bbSDavid C Somayajulu 				(hw->tx_cntxt[txr_idx].txr_next + 1) &
2743f10a77bbSDavid C Somayajulu 					(NUM_TX_DESCRIPTORS - 1);
2744f10a77bbSDavid C Somayajulu 			tx_cmd_count++;
2745f10a77bbSDavid C Somayajulu 		}
2746f10a77bbSDavid C Somayajulu 	}
2747f10a77bbSDavid C Somayajulu 
2748f10a77bbSDavid C Somayajulu 	hw->tx_cntxt[txr_idx].txr_free =
2749f10a77bbSDavid C Somayajulu 		hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count;
2750f10a77bbSDavid C Somayajulu 
2751f10a77bbSDavid C Somayajulu 	QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\
2752f10a77bbSDavid C Somayajulu 		txr_idx);
2753f10a77bbSDavid C Somayajulu        	QL_DPRINT8(ha, (dev, "%s: return\n", __func__));
2754f10a77bbSDavid C Somayajulu 
2755f10a77bbSDavid C Somayajulu 	return (0);
2756f10a77bbSDavid C Somayajulu }
2757f10a77bbSDavid C Somayajulu 
2758f10a77bbSDavid C Somayajulu 
275935291c22SDavid C Somayajulu 
276035291c22SDavid C Somayajulu #define Q8_CONFIG_IND_TBL_SIZE	32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */
2761f10a77bbSDavid C Somayajulu static int
2762f10a77bbSDavid C Somayajulu qla_config_rss_ind_table(qla_host_t *ha)
2763f10a77bbSDavid C Somayajulu {
2764f10a77bbSDavid C Somayajulu 	uint32_t i, count;
276535291c22SDavid C Somayajulu 	uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE];
2766f10a77bbSDavid C Somayajulu 
2767f10a77bbSDavid C Somayajulu 
276835291c22SDavid C Somayajulu 	for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) {
2769f10a77bbSDavid C Somayajulu 		rss_ind_tbl[i] = i % ha->hw.num_sds_rings;
2770f10a77bbSDavid C Somayajulu 	}
2771f10a77bbSDavid C Somayajulu 
277235291c22SDavid C Somayajulu 	for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ;
277335291c22SDavid C Somayajulu 		i = i + Q8_CONFIG_IND_TBL_SIZE) {
2774f10a77bbSDavid C Somayajulu 
277535291c22SDavid C Somayajulu 		if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) {
2776f10a77bbSDavid C Somayajulu 			count = Q8_RSS_IND_TBL_MAX_IDX - i + 1;
2777f10a77bbSDavid C Somayajulu 		} else {
277835291c22SDavid C Somayajulu 			count = Q8_CONFIG_IND_TBL_SIZE;
2779f10a77bbSDavid C Somayajulu 		}
2780f10a77bbSDavid C Somayajulu 
2781f10a77bbSDavid C Somayajulu 		if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id,
2782f10a77bbSDavid C Somayajulu 			rss_ind_tbl))
2783f10a77bbSDavid C Somayajulu 			return (-1);
2784f10a77bbSDavid C Somayajulu 	}
2785f10a77bbSDavid C Somayajulu 
2786f10a77bbSDavid C Somayajulu 	return (0);
2787f10a77bbSDavid C Somayajulu }
2788f10a77bbSDavid C Somayajulu 
2789a7c62c11SDavid C Somayajulu static int
2790a7c62c11SDavid C Somayajulu qla_config_soft_lro(qla_host_t *ha)
2791a7c62c11SDavid C Somayajulu {
2792a7c62c11SDavid C Somayajulu         int i;
2793a7c62c11SDavid C Somayajulu         qla_hw_t *hw = &ha->hw;
2794a7c62c11SDavid C Somayajulu         struct lro_ctrl *lro;
2795a7c62c11SDavid C Somayajulu 
2796a7c62c11SDavid C Somayajulu         for (i = 0; i < hw->num_sds_rings; i++) {
2797a7c62c11SDavid C Somayajulu                 lro = &hw->sds[i].lro;
2798a7c62c11SDavid C Somayajulu 
2799a7c62c11SDavid C Somayajulu 		bzero(lro, sizeof(struct lro_ctrl));
2800a7c62c11SDavid C Somayajulu 
2801a7c62c11SDavid C Somayajulu #if (__FreeBSD_version >= 1100101)
2802a7c62c11SDavid C Somayajulu                 if (tcp_lro_init_args(lro, ha->ifp, 0, NUM_RX_DESCRIPTORS)) {
2803a7c62c11SDavid C Somayajulu                         device_printf(ha->pci_dev,
2804a7c62c11SDavid C Somayajulu 				"%s: tcp_lro_init_args [%d] failed\n",
2805a7c62c11SDavid C Somayajulu                                 __func__, i);
2806a7c62c11SDavid C Somayajulu                         return (-1);
2807a7c62c11SDavid C Somayajulu                 }
2808a7c62c11SDavid C Somayajulu #else
2809a7c62c11SDavid C Somayajulu                 if (tcp_lro_init(lro)) {
2810a7c62c11SDavid C Somayajulu                         device_printf(ha->pci_dev,
2811a7c62c11SDavid C Somayajulu 				"%s: tcp_lro_init [%d] failed\n",
2812a7c62c11SDavid C Somayajulu                                 __func__, i);
2813a7c62c11SDavid C Somayajulu                         return (-1);
2814a7c62c11SDavid C Somayajulu                 }
2815a7c62c11SDavid C Somayajulu #endif /* #if (__FreeBSD_version >= 1100101) */
2816a7c62c11SDavid C Somayajulu 
2817a7c62c11SDavid C Somayajulu                 lro->ifp = ha->ifp;
2818a7c62c11SDavid C Somayajulu         }
2819a7c62c11SDavid C Somayajulu 
2820a7c62c11SDavid C Somayajulu         QL_DPRINT2(ha, (ha->pci_dev, "%s: LRO initialized\n", __func__));
2821a7c62c11SDavid C Somayajulu         return (0);
2822a7c62c11SDavid C Somayajulu }
2823a7c62c11SDavid C Somayajulu 
2824a7c62c11SDavid C Somayajulu static void
2825a7c62c11SDavid C Somayajulu qla_drain_soft_lro(qla_host_t *ha)
2826a7c62c11SDavid C Somayajulu {
2827a7c62c11SDavid C Somayajulu         int i;
2828a7c62c11SDavid C Somayajulu         qla_hw_t *hw = &ha->hw;
2829a7c62c11SDavid C Somayajulu         struct lro_ctrl *lro;
2830a7c62c11SDavid C Somayajulu 
2831a7c62c11SDavid C Somayajulu        	for (i = 0; i < hw->num_sds_rings; i++) {
2832a7c62c11SDavid C Somayajulu                	lro = &hw->sds[i].lro;
2833a7c62c11SDavid C Somayajulu 
2834a7c62c11SDavid C Somayajulu #if (__FreeBSD_version >= 1100101)
2835a7c62c11SDavid C Somayajulu 		tcp_lro_flush_all(lro);
2836a7c62c11SDavid C Somayajulu #else
2837a7c62c11SDavid C Somayajulu                 struct lro_entry *queued;
2838a7c62c11SDavid C Somayajulu 
2839a7c62c11SDavid C Somayajulu 		while ((!SLIST_EMPTY(&lro->lro_active))) {
2840a7c62c11SDavid C Somayajulu 			queued = SLIST_FIRST(&lro->lro_active);
2841a7c62c11SDavid C Somayajulu 			SLIST_REMOVE_HEAD(&lro->lro_active, next);
2842a7c62c11SDavid C Somayajulu 			tcp_lro_flush(lro, queued);
2843a7c62c11SDavid C Somayajulu 		}
2844a7c62c11SDavid C Somayajulu #endif /* #if (__FreeBSD_version >= 1100101) */
2845a7c62c11SDavid C Somayajulu 	}
2846a7c62c11SDavid C Somayajulu 
2847a7c62c11SDavid C Somayajulu 	return;
2848a7c62c11SDavid C Somayajulu }
2849a7c62c11SDavid C Somayajulu 
2850a7c62c11SDavid C Somayajulu static void
2851a7c62c11SDavid C Somayajulu qla_free_soft_lro(qla_host_t *ha)
2852a7c62c11SDavid C Somayajulu {
2853a7c62c11SDavid C Somayajulu         int i;
2854a7c62c11SDavid C Somayajulu         qla_hw_t *hw = &ha->hw;
2855a7c62c11SDavid C Somayajulu         struct lro_ctrl *lro;
2856a7c62c11SDavid C Somayajulu 
2857a7c62c11SDavid C Somayajulu         for (i = 0; i < hw->num_sds_rings; i++) {
2858a7c62c11SDavid C Somayajulu                	lro = &hw->sds[i].lro;
2859a7c62c11SDavid C Somayajulu 		tcp_lro_free(lro);
2860a7c62c11SDavid C Somayajulu 	}
2861a7c62c11SDavid C Somayajulu 
2862a7c62c11SDavid C Somayajulu 	return;
2863a7c62c11SDavid C Somayajulu }
2864a7c62c11SDavid C Somayajulu 
2865a7c62c11SDavid C Somayajulu 
2866f10a77bbSDavid C Somayajulu /*
2867f10a77bbSDavid C Somayajulu  * Name: ql_del_hw_if
2868f10a77bbSDavid C Somayajulu  * Function: Destroys the hardware specific entities corresponding to an
2869f10a77bbSDavid C Somayajulu  *	Ethernet Interface
2870f10a77bbSDavid C Somayajulu  */
2871f10a77bbSDavid C Somayajulu void
2872f10a77bbSDavid C Somayajulu ql_del_hw_if(qla_host_t *ha)
2873f10a77bbSDavid C Somayajulu {
287435291c22SDavid C Somayajulu 	uint32_t i;
287535291c22SDavid C Somayajulu 	uint32_t num_msix;
287635291c22SDavid C Somayajulu 
287735291c22SDavid C Somayajulu 	(void)qla_stop_nic_func(ha);
2878f10a77bbSDavid C Somayajulu 
2879f10a77bbSDavid C Somayajulu 	qla_del_rcv_cntxt(ha);
2880da834d52SDavid C Somayajulu 
2881b65c0c07SDavid C Somayajulu 	if(qla_del_xmt_cntxt(ha))
2882b65c0c07SDavid C Somayajulu 		goto ql_del_hw_if_exit;
2883f10a77bbSDavid C Somayajulu 
2884f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.init_intr_cnxt) {
288535291c22SDavid C Somayajulu 		for (i = 0; i < ha->hw.num_sds_rings; ) {
288635291c22SDavid C Somayajulu 
288735291c22SDavid C Somayajulu 			if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
288835291c22SDavid C Somayajulu 				num_msix = Q8_MAX_INTR_VECTORS;
288935291c22SDavid C Somayajulu 			else
289035291c22SDavid C Somayajulu 				num_msix = ha->hw.num_sds_rings - i;
2891b65c0c07SDavid C Somayajulu 
2892b65c0c07SDavid C Somayajulu 			if (qla_config_intr_cntxt(ha, i, num_msix, 0))
2893b65c0c07SDavid C Somayajulu 				break;
289435291c22SDavid C Somayajulu 
289535291c22SDavid C Somayajulu 			i += num_msix;
289635291c22SDavid C Somayajulu 		}
289735291c22SDavid C Somayajulu 
2898f10a77bbSDavid C Somayajulu 		ha->hw.flags.init_intr_cnxt = 0;
2899f10a77bbSDavid C Somayajulu 	}
2900da834d52SDavid C Somayajulu 
2901b65c0c07SDavid C Somayajulu ql_del_hw_if_exit:
2902a7c62c11SDavid C Somayajulu 	if (ha->hw.enable_soft_lro) {
2903a7c62c11SDavid C Somayajulu 		qla_drain_soft_lro(ha);
2904a7c62c11SDavid C Somayajulu 		qla_free_soft_lro(ha);
2905a7c62c11SDavid C Somayajulu 	}
2906a7c62c11SDavid C Somayajulu 
290735291c22SDavid C Somayajulu 	return;
2908f10a77bbSDavid C Somayajulu }
2909f10a77bbSDavid C Somayajulu 
291035291c22SDavid C Somayajulu void
291135291c22SDavid C Somayajulu qla_confirm_9kb_enable(qla_host_t *ha)
291235291c22SDavid C Somayajulu {
2913971e53c9SDavid C Somayajulu //	uint32_t supports_9kb = 0;
291435291c22SDavid C Somayajulu 
291535291c22SDavid C Somayajulu 	ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX);
291635291c22SDavid C Somayajulu 
291735291c22SDavid C Somayajulu 	/* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */
291835291c22SDavid C Somayajulu 	WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2);
291935291c22SDavid C Somayajulu 	WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
292035291c22SDavid C Somayajulu 
2921971e53c9SDavid C Somayajulu #if 0
292235291c22SDavid C Somayajulu 	qla_get_nic_partition(ha, &supports_9kb, NULL);
292335291c22SDavid C Somayajulu 
292435291c22SDavid C Somayajulu 	if (!supports_9kb)
2925971e53c9SDavid C Somayajulu #endif
292635291c22SDavid C Somayajulu 	ha->hw.enable_9kb = 0;
292735291c22SDavid C Somayajulu 
292835291c22SDavid C Somayajulu 	return;
292935291c22SDavid C Somayajulu }
293035291c22SDavid C Somayajulu 
2931f10a77bbSDavid C Somayajulu /*
2932f10a77bbSDavid C Somayajulu  * Name: ql_init_hw_if
2933f10a77bbSDavid C Somayajulu  * Function: Creates the hardware specific entities corresponding to an
2934f10a77bbSDavid C Somayajulu  *	Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
2935f10a77bbSDavid C Somayajulu  *	corresponding to the interface. Enables LRO if allowed.
2936f10a77bbSDavid C Somayajulu  */
2937f10a77bbSDavid C Somayajulu int
2938f10a77bbSDavid C Somayajulu ql_init_hw_if(qla_host_t *ha)
2939f10a77bbSDavid C Somayajulu {
2940f10a77bbSDavid C Somayajulu 	device_t	dev;
2941f10a77bbSDavid C Somayajulu 	uint32_t	i;
2942f10a77bbSDavid C Somayajulu 	uint8_t		bcast_mac[6];
2943f10a77bbSDavid C Somayajulu 	qla_rdesc_t	*rdesc;
294435291c22SDavid C Somayajulu 	uint32_t	num_msix;
2945f10a77bbSDavid C Somayajulu 
2946f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
2947f10a77bbSDavid C Somayajulu 
2948f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; i++) {
2949f10a77bbSDavid C Somayajulu 		bzero(ha->hw.dma_buf.sds_ring[i].dma_b,
2950f10a77bbSDavid C Somayajulu 			ha->hw.dma_buf.sds_ring[i].size);
2951f10a77bbSDavid C Somayajulu 	}
2952f10a77bbSDavid C Somayajulu 
295335291c22SDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; ) {
2954f10a77bbSDavid C Somayajulu 
295535291c22SDavid C Somayajulu 		if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
295635291c22SDavid C Somayajulu 			num_msix = Q8_MAX_INTR_VECTORS;
295735291c22SDavid C Somayajulu 		else
295835291c22SDavid C Somayajulu 			num_msix = ha->hw.num_sds_rings - i;
2959f10a77bbSDavid C Somayajulu 
296035291c22SDavid C Somayajulu 		if (qla_config_intr_cntxt(ha, i, num_msix, 1)) {
296135291c22SDavid C Somayajulu 
296235291c22SDavid C Somayajulu 			if (i > 0) {
296335291c22SDavid C Somayajulu 
296435291c22SDavid C Somayajulu 				num_msix = i;
296535291c22SDavid C Somayajulu 
296635291c22SDavid C Somayajulu 				for (i = 0; i < num_msix; ) {
296735291c22SDavid C Somayajulu 					qla_config_intr_cntxt(ha, i,
296835291c22SDavid C Somayajulu 						Q8_MAX_INTR_VECTORS, 0);
296935291c22SDavid C Somayajulu 					i += Q8_MAX_INTR_VECTORS;
297035291c22SDavid C Somayajulu 				}
297135291c22SDavid C Somayajulu 			}
2972f10a77bbSDavid C Somayajulu 			return (-1);
297335291c22SDavid C Somayajulu 		}
297435291c22SDavid C Somayajulu 
297535291c22SDavid C Somayajulu 		i = i + num_msix;
297635291c22SDavid C Somayajulu 	}
297735291c22SDavid C Somayajulu 
297835291c22SDavid C Somayajulu         ha->hw.flags.init_intr_cnxt = 1;
2979f10a77bbSDavid C Somayajulu 
2980f10a77bbSDavid C Somayajulu 	/*
2981f10a77bbSDavid C Somayajulu 	 * Create Receive Context
2982f10a77bbSDavid C Somayajulu 	 */
2983f10a77bbSDavid C Somayajulu 	if (qla_init_rcv_cntxt(ha)) {
2984f10a77bbSDavid C Somayajulu 		return (-1);
2985f10a77bbSDavid C Somayajulu 	}
2986f10a77bbSDavid C Somayajulu 
2987f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_rds_rings; i++) {
2988f10a77bbSDavid C Somayajulu 		rdesc = &ha->hw.rds[i];
2989f10a77bbSDavid C Somayajulu 		rdesc->rx_next = NUM_RX_DESCRIPTORS - 2;
2990f10a77bbSDavid C Somayajulu 		rdesc->rx_in = 0;
2991f10a77bbSDavid C Somayajulu 		/* Update the RDS Producer Indices */
2992f10a77bbSDavid C Somayajulu 		QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\
2993f10a77bbSDavid C Somayajulu 			rdesc->rx_next);
2994f10a77bbSDavid C Somayajulu 	}
2995f10a77bbSDavid C Somayajulu 
2996f10a77bbSDavid C Somayajulu 	/*
2997f10a77bbSDavid C Somayajulu 	 * Create Transmit Context
2998f10a77bbSDavid C Somayajulu 	 */
2999f10a77bbSDavid C Somayajulu 	if (qla_init_xmt_cntxt(ha)) {
3000f10a77bbSDavid C Somayajulu 		qla_del_rcv_cntxt(ha);
3001f10a77bbSDavid C Somayajulu 		return (-1);
3002f10a77bbSDavid C Somayajulu 	}
3003f10a77bbSDavid C Somayajulu 	ha->hw.max_tx_segs = 0;
3004f10a77bbSDavid C Somayajulu 
3005da834d52SDavid C Somayajulu 	if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1, 1))
3006f10a77bbSDavid C Somayajulu 		return(-1);
3007f10a77bbSDavid C Somayajulu 
3008f10a77bbSDavid C Somayajulu 	ha->hw.flags.unicast_mac = 1;
3009f10a77bbSDavid C Somayajulu 
3010f10a77bbSDavid C Somayajulu 	bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
3011f10a77bbSDavid C Somayajulu 	bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
3012f10a77bbSDavid C Somayajulu 
3013da834d52SDavid C Somayajulu 	if (qla_config_mac_addr(ha, bcast_mac, 1, 1))
3014f10a77bbSDavid C Somayajulu 		return (-1);
3015f10a77bbSDavid C Somayajulu 
3016f10a77bbSDavid C Somayajulu 	ha->hw.flags.bcast_mac = 1;
3017f10a77bbSDavid C Somayajulu 
3018f10a77bbSDavid C Somayajulu 	/*
3019f10a77bbSDavid C Somayajulu 	 * program any cached multicast addresses
3020f10a77bbSDavid C Somayajulu 	 */
3021f10a77bbSDavid C Somayajulu 	if (qla_hw_add_all_mcast(ha))
3022f10a77bbSDavid C Somayajulu 		return (-1);
3023f10a77bbSDavid C Somayajulu 
3024b5c2be72SDavid C Somayajulu 	if (ql_set_max_mtu(ha, ha->max_frame_size, ha->hw.rcv_cntxt_id))
3025b5c2be72SDavid C Somayajulu 		return (-1);
3026b5c2be72SDavid C Somayajulu 
3027f10a77bbSDavid C Somayajulu 	if (qla_config_rss(ha, ha->hw.rcv_cntxt_id))
3028f10a77bbSDavid C Somayajulu 		return (-1);
3029f10a77bbSDavid C Somayajulu 
3030f10a77bbSDavid C Somayajulu 	if (qla_config_rss_ind_table(ha))
3031f10a77bbSDavid C Somayajulu 		return (-1);
3032f10a77bbSDavid C Somayajulu 
303335291c22SDavid C Somayajulu 	if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1))
3034f10a77bbSDavid C Somayajulu 		return (-1);
3035f10a77bbSDavid C Somayajulu 
3036f10a77bbSDavid C Somayajulu 	if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
3037f10a77bbSDavid C Somayajulu 		return (-1);
3038f10a77bbSDavid C Somayajulu 
3039a7c62c11SDavid C Somayajulu 	if (ha->ifp->if_capenable & IFCAP_LRO) {
3040a7c62c11SDavid C Somayajulu 		if (ha->hw.enable_hw_lro) {
3041a7c62c11SDavid C Somayajulu 			ha->hw.enable_soft_lro = 0;
3042a7c62c11SDavid C Somayajulu 
3043f10a77bbSDavid C Somayajulu 			if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
3044f10a77bbSDavid C Somayajulu 				return (-1);
3045a7c62c11SDavid C Somayajulu 		} else {
3046a7c62c11SDavid C Somayajulu 			ha->hw.enable_soft_lro = 1;
3047a7c62c11SDavid C Somayajulu 
3048a7c62c11SDavid C Somayajulu 			if (qla_config_soft_lro(ha))
3049a7c62c11SDavid C Somayajulu 				return (-1);
3050a7c62c11SDavid C Somayajulu 		}
3051a7c62c11SDavid C Somayajulu 	}
3052f10a77bbSDavid C Somayajulu 
305335291c22SDavid C Somayajulu         if (qla_init_nic_func(ha))
305435291c22SDavid C Somayajulu                 return (-1);
305535291c22SDavid C Somayajulu 
305635291c22SDavid C Somayajulu         if (qla_query_fw_dcbx_caps(ha))
305735291c22SDavid C Somayajulu                 return (-1);
305835291c22SDavid C Somayajulu 
3059f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_sds_rings; i++)
3060f10a77bbSDavid C Somayajulu 		QL_ENABLE_INTERRUPTS(ha, i);
3061f10a77bbSDavid C Somayajulu 
3062f10a77bbSDavid C Somayajulu 	return (0);
3063f10a77bbSDavid C Somayajulu }
3064f10a77bbSDavid C Somayajulu 
3065f10a77bbSDavid C Somayajulu static int
306635291c22SDavid C Somayajulu qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx)
3067f10a77bbSDavid C Somayajulu {
3068f10a77bbSDavid C Somayajulu         device_t                dev = ha->pci_dev;
3069f10a77bbSDavid C Somayajulu         q80_rq_map_sds_to_rds_t *map_rings;
307035291c22SDavid C Somayajulu 	q80_rsp_map_sds_to_rds_t *map_rings_rsp;
3071f10a77bbSDavid C Somayajulu         uint32_t                i, err;
3072f10a77bbSDavid C Somayajulu         qla_hw_t                *hw = &ha->hw;
3073f10a77bbSDavid C Somayajulu 
3074f10a77bbSDavid C Somayajulu         map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox;
3075f10a77bbSDavid C Somayajulu         bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t));
3076f10a77bbSDavid C Somayajulu 
3077f10a77bbSDavid C Somayajulu         map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS;
3078f10a77bbSDavid C Somayajulu         map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2);
3079f10a77bbSDavid C Somayajulu         map_rings->count_version |= Q8_MBX_CMD_VERSION;
3080f10a77bbSDavid C Somayajulu 
3081f10a77bbSDavid C Somayajulu         map_rings->cntxt_id = hw->rcv_cntxt_id;
308235291c22SDavid C Somayajulu         map_rings->num_rings = num_idx;
3083f10a77bbSDavid C Somayajulu 
308435291c22SDavid C Somayajulu 	for (i = 0; i < num_idx; i++) {
308535291c22SDavid C Somayajulu 		map_rings->sds_rds[i].sds_ring = i + start_idx;
308635291c22SDavid C Somayajulu 		map_rings->sds_rds[i].rds_ring = i + start_idx;
3087f10a77bbSDavid C Somayajulu 	}
3088f10a77bbSDavid C Somayajulu 
3089f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)map_rings,
3090f10a77bbSDavid C Somayajulu                 (sizeof (q80_rq_map_sds_to_rds_t) >> 2),
3091f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
3092f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
3093f10a77bbSDavid C Somayajulu                 return (-1);
3094f10a77bbSDavid C Somayajulu         }
3095f10a77bbSDavid C Somayajulu 
309635291c22SDavid C Somayajulu         map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox;
3097f10a77bbSDavid C Somayajulu 
3098f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status);
3099f10a77bbSDavid C Somayajulu 
3100f10a77bbSDavid C Somayajulu         if (err) {
3101f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3102f10a77bbSDavid C Somayajulu                 return (-1);
3103f10a77bbSDavid C Somayajulu         }
3104f10a77bbSDavid C Somayajulu 
3105f10a77bbSDavid C Somayajulu         return (0);
3106f10a77bbSDavid C Somayajulu }
3107f10a77bbSDavid C Somayajulu 
3108f10a77bbSDavid C Somayajulu /*
3109f10a77bbSDavid C Somayajulu  * Name: qla_init_rcv_cntxt
3110f10a77bbSDavid C Somayajulu  * Function: Creates the Receive Context.
3111f10a77bbSDavid C Somayajulu  */
3112f10a77bbSDavid C Somayajulu static int
3113f10a77bbSDavid C Somayajulu qla_init_rcv_cntxt(qla_host_t *ha)
3114f10a77bbSDavid C Somayajulu {
3115f10a77bbSDavid C Somayajulu 	q80_rq_rcv_cntxt_t	*rcntxt;
3116f10a77bbSDavid C Somayajulu 	q80_rsp_rcv_cntxt_t	*rcntxt_rsp;
3117f10a77bbSDavid C Somayajulu 	q80_stat_desc_t		*sdesc;
3118f10a77bbSDavid C Somayajulu 	int			i, j;
3119f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
3120f10a77bbSDavid C Somayajulu 	device_t		dev;
3121f10a77bbSDavid C Somayajulu 	uint32_t		err;
3122f10a77bbSDavid C Somayajulu 	uint32_t		rcntxt_sds_rings;
3123f10a77bbSDavid C Somayajulu 	uint32_t		rcntxt_rds_rings;
312435291c22SDavid C Somayajulu 	uint32_t		max_idx;
3125f10a77bbSDavid C Somayajulu 
3126f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
3127f10a77bbSDavid C Somayajulu 
3128f10a77bbSDavid C Somayajulu 	/*
3129f10a77bbSDavid C Somayajulu 	 * Create Receive Context
3130f10a77bbSDavid C Somayajulu 	 */
3131f10a77bbSDavid C Somayajulu 
3132f10a77bbSDavid C Somayajulu 	for (i = 0; i < hw->num_sds_rings; i++) {
3133f10a77bbSDavid C Somayajulu 		sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0];
3134f10a77bbSDavid C Somayajulu 
3135f10a77bbSDavid C Somayajulu 		for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) {
3136f10a77bbSDavid C Somayajulu 			sdesc->data[0] = 1ULL;
3137f10a77bbSDavid C Somayajulu 			sdesc->data[1] = 1ULL;
3138f10a77bbSDavid C Somayajulu 		}
3139f10a77bbSDavid C Somayajulu 	}
3140f10a77bbSDavid C Somayajulu 
3141f10a77bbSDavid C Somayajulu 	rcntxt_sds_rings = hw->num_sds_rings;
3142f10a77bbSDavid C Somayajulu 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS)
3143f10a77bbSDavid C Somayajulu 		rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS;
3144f10a77bbSDavid C Somayajulu 
3145f10a77bbSDavid C Somayajulu 	rcntxt_rds_rings = hw->num_rds_rings;
3146f10a77bbSDavid C Somayajulu 
3147f10a77bbSDavid C Somayajulu 	if (hw->num_rds_rings > MAX_RDS_RING_SETS)
3148f10a77bbSDavid C Somayajulu 		rcntxt_rds_rings = MAX_RDS_RING_SETS;
3149f10a77bbSDavid C Somayajulu 
3150f10a77bbSDavid C Somayajulu 	rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox;
3151f10a77bbSDavid C Somayajulu 	bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t)));
3152f10a77bbSDavid C Somayajulu 
3153f10a77bbSDavid C Somayajulu 	rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT;
3154f10a77bbSDavid C Somayajulu 	rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2);
3155f10a77bbSDavid C Somayajulu 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
3156f10a77bbSDavid C Somayajulu 
3157f10a77bbSDavid C Somayajulu 	rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW |
3158f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_LRO |
3159f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_HW_LRO |
3160f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_RSS |
3161f10a77bbSDavid C Somayajulu 			Q8_RCV_CNTXT_CAP0_SGL_LRO;
3162f10a77bbSDavid C Somayajulu 
316335291c22SDavid C Somayajulu 	if (ha->hw.enable_9kb)
316435291c22SDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO;
316535291c22SDavid C Somayajulu 	else
316635291c22SDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO;
316735291c22SDavid C Somayajulu 
3168f10a77bbSDavid C Somayajulu 	if (ha->hw.num_rds_rings > 1) {
3169f10a77bbSDavid C Somayajulu 		rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5);
3170f10a77bbSDavid C Somayajulu 		rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS;
3171f10a77bbSDavid C Somayajulu 	} else
3172f10a77bbSDavid C Somayajulu 		rcntxt->nrds_sets_rings = 0x1 | (1 << 5);
3173f10a77bbSDavid C Somayajulu 
3174f10a77bbSDavid C Somayajulu 	rcntxt->nsds_rings = rcntxt_sds_rings;
3175f10a77bbSDavid C Somayajulu 
3176f10a77bbSDavid C Somayajulu 	rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE;
3177f10a77bbSDavid C Somayajulu 
3178f10a77bbSDavid C Somayajulu 	rcntxt->rcv_vpid = 0;
3179f10a77bbSDavid C Somayajulu 
3180f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_sds_rings; i++) {
3181f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].paddr =
3182f10a77bbSDavid C Somayajulu 			qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr);
3183f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].size =
3184f10a77bbSDavid C Somayajulu 			qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
3185b89f2279SDavid C Somayajulu 		rcntxt->sds[i].intr_id = qla_host_to_le16(hw->intr_id[i]);
3186f10a77bbSDavid C Somayajulu 		rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0);
3187f10a77bbSDavid C Somayajulu 	}
3188f10a77bbSDavid C Somayajulu 
3189f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_rds_rings; i++) {
3190f10a77bbSDavid C Somayajulu 		rcntxt->rds[i].paddr_std =
3191f10a77bbSDavid C Somayajulu 			qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr);
319235291c22SDavid C Somayajulu 
319335291c22SDavid C Somayajulu 		if (ha->hw.enable_9kb)
319435291c22SDavid C Somayajulu 			rcntxt->rds[i].std_bsize =
319535291c22SDavid C Somayajulu 				qla_host_to_le64(MJUM9BYTES);
319635291c22SDavid C Somayajulu 		else
3197f10a77bbSDavid C Somayajulu 			rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
319835291c22SDavid C Somayajulu 
3199f10a77bbSDavid C Somayajulu 		rcntxt->rds[i].std_nentries =
3200f10a77bbSDavid C Somayajulu 			qla_host_to_le32(NUM_RX_DESCRIPTORS);
3201f10a77bbSDavid C Somayajulu 	}
3202f10a77bbSDavid C Somayajulu 
3203f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
3204f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_rcv_cntxt_t) >> 2),
3205f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) {
3206f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
3207f10a77bbSDavid C Somayajulu                 return (-1);
3208f10a77bbSDavid C Somayajulu         }
3209f10a77bbSDavid C Somayajulu 
3210f10a77bbSDavid C Somayajulu         rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox;
3211f10a77bbSDavid C Somayajulu 
3212f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
3213f10a77bbSDavid C Somayajulu 
3214f10a77bbSDavid C Somayajulu         if (err) {
3215f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3216f10a77bbSDavid C Somayajulu                 return (-1);
3217f10a77bbSDavid C Somayajulu         }
3218f10a77bbSDavid C Somayajulu 
3219f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_sds_rings; i++) {
3220f10a77bbSDavid C Somayajulu 		hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i];
3221f10a77bbSDavid C Somayajulu 	}
3222f10a77bbSDavid C Somayajulu 
3223f10a77bbSDavid C Somayajulu 	for (i = 0; i <  rcntxt_rds_rings; i++) {
3224f10a77bbSDavid C Somayajulu 		hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std;
3225f10a77bbSDavid C Somayajulu 	}
3226f10a77bbSDavid C Somayajulu 
3227f10a77bbSDavid C Somayajulu 	hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id;
3228f10a77bbSDavid C Somayajulu 
3229f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_rx_cnxt = 1;
3230f10a77bbSDavid C Somayajulu 
3231f10a77bbSDavid C Somayajulu 	if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) {
323235291c22SDavid C Somayajulu 
323335291c22SDavid C Somayajulu 		for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) {
323435291c22SDavid C Somayajulu 
323535291c22SDavid C Somayajulu 			if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings)
323635291c22SDavid C Somayajulu 				max_idx = MAX_RCNTXT_SDS_RINGS;
323735291c22SDavid C Somayajulu 			else
323835291c22SDavid C Somayajulu 				max_idx = hw->num_sds_rings - i;
323935291c22SDavid C Somayajulu 
324035291c22SDavid C Somayajulu 			err = qla_add_rcv_rings(ha, i, max_idx);
3241f10a77bbSDavid C Somayajulu 			if (err)
3242f10a77bbSDavid C Somayajulu 				return -1;
324335291c22SDavid C Somayajulu 
324435291c22SDavid C Somayajulu 			i += max_idx;
324535291c22SDavid C Somayajulu 		}
3246f10a77bbSDavid C Somayajulu 	}
3247f10a77bbSDavid C Somayajulu 
3248f10a77bbSDavid C Somayajulu 	if (hw->num_rds_rings > 1) {
324935291c22SDavid C Somayajulu 
325035291c22SDavid C Somayajulu 		for (i = 0; i < hw->num_rds_rings; ) {
325135291c22SDavid C Somayajulu 
325235291c22SDavid C Somayajulu 			if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings)
325335291c22SDavid C Somayajulu 				max_idx = MAX_SDS_TO_RDS_MAP;
325435291c22SDavid C Somayajulu 			else
325535291c22SDavid C Somayajulu 				max_idx = hw->num_rds_rings - i;
325635291c22SDavid C Somayajulu 
325735291c22SDavid C Somayajulu 			err = qla_map_sds_to_rds(ha, i, max_idx);
3258f10a77bbSDavid C Somayajulu 			if (err)
3259f10a77bbSDavid C Somayajulu 				return -1;
326035291c22SDavid C Somayajulu 
326135291c22SDavid C Somayajulu 			i += max_idx;
326235291c22SDavid C Somayajulu 		}
3263f10a77bbSDavid C Somayajulu 	}
3264f10a77bbSDavid C Somayajulu 
3265f10a77bbSDavid C Somayajulu 	return (0);
3266f10a77bbSDavid C Somayajulu }
3267f10a77bbSDavid C Somayajulu 
3268f10a77bbSDavid C Somayajulu static int
326935291c22SDavid C Somayajulu qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds)
3270f10a77bbSDavid C Somayajulu {
3271f10a77bbSDavid C Somayajulu 	device_t		dev = ha->pci_dev;
3272f10a77bbSDavid C Somayajulu 	q80_rq_add_rcv_rings_t	*add_rcv;
3273f10a77bbSDavid C Somayajulu 	q80_rsp_add_rcv_rings_t	*add_rcv_rsp;
3274f10a77bbSDavid C Somayajulu 	uint32_t		i,j, err;
3275f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
3276f10a77bbSDavid C Somayajulu 
3277f10a77bbSDavid C Somayajulu 	add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox;
3278f10a77bbSDavid C Somayajulu 	bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t));
3279f10a77bbSDavid C Somayajulu 
3280f10a77bbSDavid C Somayajulu 	add_rcv->opcode = Q8_MBX_ADD_RX_RINGS;
3281f10a77bbSDavid C Somayajulu 	add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2);
3282f10a77bbSDavid C Somayajulu 	add_rcv->count_version |= Q8_MBX_CMD_VERSION;
3283f10a77bbSDavid C Somayajulu 
3284f10a77bbSDavid C Somayajulu 	add_rcv->nrds_sets_rings = nsds | (1 << 5);
3285f10a77bbSDavid C Somayajulu 	add_rcv->nsds_rings = nsds;
3286f10a77bbSDavid C Somayajulu 	add_rcv->cntxt_id = hw->rcv_cntxt_id;
3287f10a77bbSDavid C Somayajulu 
3288f10a77bbSDavid C Somayajulu         for (i = 0; i <  nsds; i++) {
3289f10a77bbSDavid C Somayajulu 
3290f10a77bbSDavid C Somayajulu 		j = i + sds_idx;
3291f10a77bbSDavid C Somayajulu 
3292f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].paddr =
3293f10a77bbSDavid C Somayajulu                         qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr);
3294f10a77bbSDavid C Somayajulu 
3295f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].size =
3296f10a77bbSDavid C Somayajulu                         qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
3297f10a77bbSDavid C Somayajulu 
3298b89f2279SDavid C Somayajulu                 add_rcv->sds[i].intr_id = qla_host_to_le16(hw->intr_id[j]);
3299f10a77bbSDavid C Somayajulu                 add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0);
3300f10a77bbSDavid C Somayajulu 
3301f10a77bbSDavid C Somayajulu         }
3302b89f2279SDavid C Somayajulu 
330335291c22SDavid C Somayajulu         for (i = 0; (i <  nsds); i++) {
3304f10a77bbSDavid C Somayajulu                 j = i + sds_idx;
330535291c22SDavid C Somayajulu 
3306f10a77bbSDavid C Somayajulu                 add_rcv->rds[i].paddr_std =
3307f10a77bbSDavid C Somayajulu                         qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr);
330835291c22SDavid C Somayajulu 
330935291c22SDavid C Somayajulu 		if (ha->hw.enable_9kb)
331035291c22SDavid C Somayajulu 			add_rcv->rds[i].std_bsize =
331135291c22SDavid C Somayajulu 				qla_host_to_le64(MJUM9BYTES);
331235291c22SDavid C Somayajulu 		else
3313f10a77bbSDavid C Somayajulu                 	add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
331435291c22SDavid C Somayajulu 
3315f10a77bbSDavid C Somayajulu                 add_rcv->rds[i].std_nentries =
3316f10a77bbSDavid C Somayajulu                         qla_host_to_le32(NUM_RX_DESCRIPTORS);
3317f10a77bbSDavid C Somayajulu         }
3318f10a77bbSDavid C Somayajulu 
3319f10a77bbSDavid C Somayajulu 
3320f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)add_rcv,
3321f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_add_rcv_rings_t) >> 2),
3322f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
3323f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
3324f10a77bbSDavid C Somayajulu                 return (-1);
3325f10a77bbSDavid C Somayajulu         }
3326f10a77bbSDavid C Somayajulu 
3327f10a77bbSDavid C Somayajulu         add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
3328f10a77bbSDavid C Somayajulu 
3329f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status);
3330f10a77bbSDavid C Somayajulu 
3331f10a77bbSDavid C Somayajulu         if (err) {
3332f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3333f10a77bbSDavid C Somayajulu                 return (-1);
3334f10a77bbSDavid C Somayajulu         }
3335f10a77bbSDavid C Somayajulu 
333635291c22SDavid C Somayajulu 	for (i = 0; i < nsds; i++) {
333735291c22SDavid C Somayajulu 		hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i];
3338f10a77bbSDavid C Somayajulu 	}
333935291c22SDavid C Somayajulu 
334035291c22SDavid C Somayajulu 	for (i = 0; i < nsds; i++) {
334135291c22SDavid C Somayajulu 		hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std;
3342f10a77bbSDavid C Somayajulu 	}
334335291c22SDavid C Somayajulu 
3344f10a77bbSDavid C Somayajulu 	return (0);
3345f10a77bbSDavid C Somayajulu }
3346f10a77bbSDavid C Somayajulu 
3347f10a77bbSDavid C Somayajulu /*
3348f10a77bbSDavid C Somayajulu  * Name: qla_del_rcv_cntxt
3349f10a77bbSDavid C Somayajulu  * Function: Destroys the Receive Context.
3350f10a77bbSDavid C Somayajulu  */
3351f10a77bbSDavid C Somayajulu static void
3352f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(qla_host_t *ha)
3353f10a77bbSDavid C Somayajulu {
3354f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
3355f10a77bbSDavid C Somayajulu 	q80_rcv_cntxt_destroy_t		*rcntxt;
3356f10a77bbSDavid C Somayajulu 	q80_rcv_cntxt_destroy_rsp_t	*rcntxt_rsp;
3357f10a77bbSDavid C Somayajulu 	uint32_t			err;
3358f10a77bbSDavid C Somayajulu 	uint8_t				bcast_mac[6];
3359f10a77bbSDavid C Somayajulu 
3360f10a77bbSDavid C Somayajulu 	if (!ha->hw.flags.init_rx_cnxt)
3361f10a77bbSDavid C Somayajulu 		return;
3362f10a77bbSDavid C Somayajulu 
3363f10a77bbSDavid C Somayajulu 	if (qla_hw_del_all_mcast(ha))
3364f10a77bbSDavid C Somayajulu 		return;
3365f10a77bbSDavid C Somayajulu 
3366f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.bcast_mac) {
3367f10a77bbSDavid C Somayajulu 
3368f10a77bbSDavid C Somayajulu 		bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
3369f10a77bbSDavid C Somayajulu 		bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
3370f10a77bbSDavid C Somayajulu 
3371da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, bcast_mac, 0, 1))
3372f10a77bbSDavid C Somayajulu 			return;
3373f10a77bbSDavid C Somayajulu 		ha->hw.flags.bcast_mac = 0;
3374f10a77bbSDavid C Somayajulu 
3375f10a77bbSDavid C Somayajulu 	}
3376f10a77bbSDavid C Somayajulu 
3377f10a77bbSDavid C Somayajulu 	if (ha->hw.flags.unicast_mac) {
3378da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0, 1))
3379f10a77bbSDavid C Somayajulu 			return;
3380f10a77bbSDavid C Somayajulu 		ha->hw.flags.unicast_mac = 0;
3381f10a77bbSDavid C Somayajulu 	}
3382f10a77bbSDavid C Somayajulu 
3383f10a77bbSDavid C Somayajulu 	rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox;
3384f10a77bbSDavid C Somayajulu 	bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t)));
3385f10a77bbSDavid C Somayajulu 
3386f10a77bbSDavid C Somayajulu 	rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT;
3387f10a77bbSDavid C Somayajulu 	rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2);
3388f10a77bbSDavid C Somayajulu 	rcntxt->count_version |= Q8_MBX_CMD_VERSION;
3389f10a77bbSDavid C Somayajulu 
3390f10a77bbSDavid C Somayajulu 	rcntxt->cntxt_id = ha->hw.rcv_cntxt_id;
3391f10a77bbSDavid C Somayajulu 
3392f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
3393f10a77bbSDavid C Somayajulu 		(sizeof (q80_rcv_cntxt_destroy_t) >> 2),
3394f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) {
3395f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
3396f10a77bbSDavid C Somayajulu                 return;
3397f10a77bbSDavid C Somayajulu         }
3398f10a77bbSDavid C Somayajulu         rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox;
3399f10a77bbSDavid C Somayajulu 
3400f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
3401f10a77bbSDavid C Somayajulu 
3402f10a77bbSDavid C Somayajulu         if (err) {
3403f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3404f10a77bbSDavid C Somayajulu         }
3405f10a77bbSDavid C Somayajulu 
3406f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_rx_cnxt = 0;
3407f10a77bbSDavid C Somayajulu 	return;
3408f10a77bbSDavid C Somayajulu }
3409f10a77bbSDavid C Somayajulu 
3410f10a77bbSDavid C Somayajulu /*
3411f10a77bbSDavid C Somayajulu  * Name: qla_init_xmt_cntxt
3412f10a77bbSDavid C Somayajulu  * Function: Creates the Transmit Context.
3413f10a77bbSDavid C Somayajulu  */
3414f10a77bbSDavid C Somayajulu static int
3415f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
3416f10a77bbSDavid C Somayajulu {
3417f10a77bbSDavid C Somayajulu 	device_t		dev;
3418f10a77bbSDavid C Somayajulu         qla_hw_t		*hw = &ha->hw;
3419f10a77bbSDavid C Somayajulu 	q80_rq_tx_cntxt_t	*tcntxt;
3420f10a77bbSDavid C Somayajulu 	q80_rsp_tx_cntxt_t	*tcntxt_rsp;
3421f10a77bbSDavid C Somayajulu 	uint32_t		err;
3422f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t       *hw_tx_cntxt;
3423b89f2279SDavid C Somayajulu 	uint32_t		intr_idx;
3424f10a77bbSDavid C Somayajulu 
3425f10a77bbSDavid C Somayajulu 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3426f10a77bbSDavid C Somayajulu 
3427f10a77bbSDavid C Somayajulu 	dev = ha->pci_dev;
3428f10a77bbSDavid C Somayajulu 
3429f10a77bbSDavid C Somayajulu 	/*
3430f10a77bbSDavid C Somayajulu 	 * Create Transmit Context
3431f10a77bbSDavid C Somayajulu 	 */
3432f10a77bbSDavid C Somayajulu 	tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox;
3433f10a77bbSDavid C Somayajulu 	bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t)));
3434f10a77bbSDavid C Somayajulu 
3435f10a77bbSDavid C Somayajulu 	tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT;
3436f10a77bbSDavid C Somayajulu 	tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2);
3437f10a77bbSDavid C Somayajulu 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
3438f10a77bbSDavid C Somayajulu 
3439b89f2279SDavid C Somayajulu 	intr_idx = txr_idx;
3440b89f2279SDavid C Somayajulu 
344135291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV
344235291c22SDavid C Somayajulu 
344335291c22SDavid C Somayajulu 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO |
344435291c22SDavid C Somayajulu 				Q8_TX_CNTXT_CAP0_TC;
344535291c22SDavid C Somayajulu 
344635291c22SDavid C Somayajulu 	if (txr_idx >= (ha->hw.num_tx_rings >> 1)) {
344735291c22SDavid C Somayajulu 		tcntxt->traffic_class = 1;
344835291c22SDavid C Somayajulu 	}
344935291c22SDavid C Somayajulu 
3450b89f2279SDavid C Somayajulu 	intr_idx = txr_idx % (ha->hw.num_tx_rings >> 1);
345135291c22SDavid C Somayajulu 
3452b89f2279SDavid C Somayajulu #else
3453f10a77bbSDavid C Somayajulu 	tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO;
3454f10a77bbSDavid C Somayajulu 
345535291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
345635291c22SDavid C Somayajulu 
3457f10a77bbSDavid C Somayajulu 	tcntxt->ntx_rings = 1;
3458f10a77bbSDavid C Somayajulu 
3459f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].paddr =
3460f10a77bbSDavid C Somayajulu 		qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr);
3461f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].tx_consumer =
3462f10a77bbSDavid C Somayajulu 		qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr);
3463f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS);
3464f10a77bbSDavid C Somayajulu 
3465b89f2279SDavid C Somayajulu 	tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[intr_idx]);
3466f10a77bbSDavid C Somayajulu 	tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0);
3467f10a77bbSDavid C Somayajulu 
3468f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS;
3469f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0;
3470c06073f5SDavid C Somayajulu 	*(hw_tx_cntxt->tx_cons) = 0;
3471f10a77bbSDavid C Somayajulu 
3472f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
3473f10a77bbSDavid C Somayajulu 		(sizeof (q80_rq_tx_cntxt_t) >> 2),
3474f10a77bbSDavid C Somayajulu                 ha->hw.mbox,
3475f10a77bbSDavid C Somayajulu 		(sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) {
3476f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
3477f10a77bbSDavid C Somayajulu                 return (-1);
3478f10a77bbSDavid C Somayajulu         }
3479f10a77bbSDavid C Somayajulu         tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox;
3480f10a77bbSDavid C Somayajulu 
3481f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
3482f10a77bbSDavid C Somayajulu 
3483f10a77bbSDavid C Somayajulu         if (err) {
3484f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3485f10a77bbSDavid C Somayajulu 		return -1;
3486f10a77bbSDavid C Somayajulu         }
3487f10a77bbSDavid C Somayajulu 
3488f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index;
3489f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id;
3490f10a77bbSDavid C Somayajulu 
349135291c22SDavid C Somayajulu 	if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0))
349235291c22SDavid C Somayajulu 		return (-1);
349335291c22SDavid C Somayajulu 
3494f10a77bbSDavid C Somayajulu 	return (0);
3495f10a77bbSDavid C Somayajulu }
3496f10a77bbSDavid C Somayajulu 
3497f10a77bbSDavid C Somayajulu 
3498f10a77bbSDavid C Somayajulu /*
3499f10a77bbSDavid C Somayajulu  * Name: qla_del_xmt_cntxt
3500f10a77bbSDavid C Somayajulu  * Function: Destroys the Transmit Context.
3501f10a77bbSDavid C Somayajulu  */
3502f10a77bbSDavid C Somayajulu static int
3503f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
3504f10a77bbSDavid C Somayajulu {
3505f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
3506f10a77bbSDavid C Somayajulu 	q80_tx_cntxt_destroy_t		*tcntxt;
3507f10a77bbSDavid C Somayajulu 	q80_tx_cntxt_destroy_rsp_t	*tcntxt_rsp;
3508f10a77bbSDavid C Somayajulu 	uint32_t			err;
3509f10a77bbSDavid C Somayajulu 
3510f10a77bbSDavid C Somayajulu 	tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox;
3511f10a77bbSDavid C Somayajulu 	bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t)));
3512f10a77bbSDavid C Somayajulu 
3513f10a77bbSDavid C Somayajulu 	tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT;
3514f10a77bbSDavid C Somayajulu 	tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2);
3515f10a77bbSDavid C Somayajulu 	tcntxt->count_version |= Q8_MBX_CMD_VERSION;
3516f10a77bbSDavid C Somayajulu 
3517f10a77bbSDavid C Somayajulu 	tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id;
3518f10a77bbSDavid C Somayajulu 
3519f10a77bbSDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
3520f10a77bbSDavid C Somayajulu 		(sizeof (q80_tx_cntxt_destroy_t) >> 2),
3521f10a77bbSDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) {
3522f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed0\n", __func__);
3523f10a77bbSDavid C Somayajulu                 return (-1);
3524f10a77bbSDavid C Somayajulu         }
3525f10a77bbSDavid C Somayajulu         tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox;
3526f10a77bbSDavid C Somayajulu 
3527f10a77bbSDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
3528f10a77bbSDavid C Somayajulu 
3529f10a77bbSDavid C Somayajulu         if (err) {
3530f10a77bbSDavid C Somayajulu                 device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3531f10a77bbSDavid C Somayajulu 		return (-1);
3532f10a77bbSDavid C Somayajulu         }
3533f10a77bbSDavid C Somayajulu 
3534f10a77bbSDavid C Somayajulu 	return (0);
3535f10a77bbSDavid C Somayajulu }
3536b65c0c07SDavid C Somayajulu static int
3537f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt(qla_host_t *ha)
3538f10a77bbSDavid C Somayajulu {
3539f10a77bbSDavid C Somayajulu 	uint32_t i;
3540b65c0c07SDavid C Somayajulu 	int ret = 0;
3541f10a77bbSDavid C Somayajulu 
3542f10a77bbSDavid C Somayajulu 	if (!ha->hw.flags.init_tx_cnxt)
3543b65c0c07SDavid C Somayajulu 		return (ret);
3544f10a77bbSDavid C Somayajulu 
3545f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
3546b65c0c07SDavid C Somayajulu 		if ((ret = qla_del_xmt_cntxt_i(ha, i)) != 0)
3547f10a77bbSDavid C Somayajulu 			break;
3548f10a77bbSDavid C Somayajulu 	}
3549f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_tx_cnxt = 0;
3550b65c0c07SDavid C Somayajulu 
3551b65c0c07SDavid C Somayajulu 	return (ret);
3552f10a77bbSDavid C Somayajulu }
3553f10a77bbSDavid C Somayajulu 
3554f10a77bbSDavid C Somayajulu static int
3555f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt(qla_host_t *ha)
3556f10a77bbSDavid C Somayajulu {
3557f10a77bbSDavid C Somayajulu 	uint32_t i, j;
3558f10a77bbSDavid C Somayajulu 
3559f10a77bbSDavid C Somayajulu 	for (i = 0; i < ha->hw.num_tx_rings; i++) {
3560f10a77bbSDavid C Somayajulu 		if (qla_init_xmt_cntxt_i(ha, i) != 0) {
3561b65c0c07SDavid C Somayajulu 			for (j = 0; j < i; j++) {
3562b65c0c07SDavid C Somayajulu 				if (qla_del_xmt_cntxt_i(ha, j))
3563b65c0c07SDavid C Somayajulu 					break;
3564b65c0c07SDavid C Somayajulu 			}
3565f10a77bbSDavid C Somayajulu 			return (-1);
3566f10a77bbSDavid C Somayajulu 		}
3567f10a77bbSDavid C Somayajulu 	}
3568f10a77bbSDavid C Somayajulu 	ha->hw.flags.init_tx_cnxt = 1;
3569f10a77bbSDavid C Somayajulu 	return (0);
3570f10a77bbSDavid C Somayajulu }
3571f10a77bbSDavid C Somayajulu 
3572f10a77bbSDavid C Somayajulu static int
3573da834d52SDavid C Somayajulu qla_hw_all_mcast(qla_host_t *ha, uint32_t add_mcast)
3574f10a77bbSDavid C Somayajulu {
3575f10a77bbSDavid C Somayajulu 	int i, nmcast;
3576da834d52SDavid C Somayajulu 	uint32_t count = 0;
3577da834d52SDavid C Somayajulu 	uint8_t *mcast;
3578f10a77bbSDavid C Somayajulu 
3579f10a77bbSDavid C Somayajulu 	nmcast = ha->hw.nmcast;
3580f10a77bbSDavid C Somayajulu 
3581da834d52SDavid C Somayajulu 	QL_DPRINT2(ha, (ha->pci_dev,
3582da834d52SDavid C Somayajulu 		"%s:[0x%x] enter nmcast = %d \n", __func__, add_mcast, nmcast));
3583da834d52SDavid C Somayajulu 
3584da834d52SDavid C Somayajulu 	mcast = ha->hw.mac_addr_arr;
3585da834d52SDavid C Somayajulu 	memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3586da834d52SDavid C Somayajulu 
3587f10a77bbSDavid C Somayajulu 	for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
3588f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] != 0) ||
3589f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] != 0) ||
3590f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] != 0) ||
3591f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] != 0) ||
3592f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] != 0) ||
3593f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] != 0)) {
3594f10a77bbSDavid C Somayajulu 
3595da834d52SDavid C Somayajulu 			bcopy(ha->hw.mcast[i].addr, mcast, ETHER_ADDR_LEN);
3596da834d52SDavid C Somayajulu 			mcast = mcast + ETHER_ADDR_LEN;
3597da834d52SDavid C Somayajulu 			count++;
3598da834d52SDavid C Somayajulu 
3599971e53c9SDavid C Somayajulu 			device_printf(ha->pci_dev,
3600971e53c9SDavid C Somayajulu 				"%s: %x:%x:%x:%x:%x:%x \n",
3601971e53c9SDavid C Somayajulu 				__func__, ha->hw.mcast[i].addr[0],
3602971e53c9SDavid C Somayajulu 				ha->hw.mcast[i].addr[1], ha->hw.mcast[i].addr[2],
3603971e53c9SDavid C Somayajulu 				ha->hw.mcast[i].addr[3], ha->hw.mcast[i].addr[4],
3604971e53c9SDavid C Somayajulu 				ha->hw.mcast[i].addr[5]);
3605971e53c9SDavid C Somayajulu 
3606da834d52SDavid C Somayajulu 			if (count == Q8_MAX_MAC_ADDRS) {
3607da834d52SDavid C Somayajulu 				if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3608da834d52SDavid C Somayajulu 					add_mcast, count)) {
3609da834d52SDavid C Somayajulu                 			device_printf(ha->pci_dev,
3610da834d52SDavid C Somayajulu 						"%s: failed\n", __func__);
3611f10a77bbSDavid C Somayajulu 					return (-1);
3612f10a77bbSDavid C Somayajulu 				}
3613f10a77bbSDavid C Somayajulu 
3614da834d52SDavid C Somayajulu 				count = 0;
3615da834d52SDavid C Somayajulu 				mcast = ha->hw.mac_addr_arr;
3616da834d52SDavid C Somayajulu 				memset(mcast, 0,
3617da834d52SDavid C Somayajulu 					(Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3618da834d52SDavid C Somayajulu 			}
3619da834d52SDavid C Somayajulu 
3620f10a77bbSDavid C Somayajulu 			nmcast--;
3621f10a77bbSDavid C Somayajulu 		}
3622f10a77bbSDavid C Somayajulu 	}
3623da834d52SDavid C Somayajulu 
3624da834d52SDavid C Somayajulu 	if (count) {
3625da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mcast,
3626da834d52SDavid C Somayajulu 			count)) {
3627da834d52SDavid C Somayajulu                 	device_printf(ha->pci_dev, "%s: failed\n", __func__);
3628da834d52SDavid C Somayajulu 			return (-1);
3629da834d52SDavid C Somayajulu 		}
3630da834d52SDavid C Somayajulu 	}
3631da834d52SDavid C Somayajulu 	QL_DPRINT2(ha, (ha->pci_dev,
3632da834d52SDavid C Somayajulu 		"%s:[0x%x] exit nmcast = %d \n", __func__, add_mcast, nmcast));
3633da834d52SDavid C Somayajulu 
3634f10a77bbSDavid C Somayajulu 	return 0;
3635f10a77bbSDavid C Somayajulu }
3636f10a77bbSDavid C Somayajulu 
3637f10a77bbSDavid C Somayajulu static int
3638da834d52SDavid C Somayajulu qla_hw_add_all_mcast(qla_host_t *ha)
3639da834d52SDavid C Somayajulu {
3640da834d52SDavid C Somayajulu 	int ret;
3641da834d52SDavid C Somayajulu 
3642da834d52SDavid C Somayajulu 	ret = qla_hw_all_mcast(ha, 1);
3643da834d52SDavid C Somayajulu 
3644da834d52SDavid C Somayajulu 	return (ret);
3645da834d52SDavid C Somayajulu }
3646da834d52SDavid C Somayajulu 
364761fb8de9SDavid C Somayajulu int
3648f10a77bbSDavid C Somayajulu qla_hw_del_all_mcast(qla_host_t *ha)
3649f10a77bbSDavid C Somayajulu {
3650da834d52SDavid C Somayajulu 	int ret;
3651f10a77bbSDavid C Somayajulu 
3652da834d52SDavid C Somayajulu 	ret = qla_hw_all_mcast(ha, 0);
3653f10a77bbSDavid C Somayajulu 
3654da834d52SDavid C Somayajulu 	bzero(ha->hw.mcast, (sizeof (qla_mcast_t) * Q8_MAX_NUM_MULTICAST_ADDRS));
3655da834d52SDavid C Somayajulu 	ha->hw.nmcast = 0;
3656f10a77bbSDavid C Somayajulu 
3657da834d52SDavid C Somayajulu 	return (ret);
3658f10a77bbSDavid C Somayajulu }
3659f10a77bbSDavid C Somayajulu 
3660f10a77bbSDavid C Somayajulu static int
3661da834d52SDavid C Somayajulu qla_hw_mac_addr_present(qla_host_t *ha, uint8_t *mta)
3662f10a77bbSDavid C Somayajulu {
3663f10a77bbSDavid C Somayajulu 	int i;
3664f10a77bbSDavid C Somayajulu 
3665f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3666f10a77bbSDavid C Somayajulu 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0)
3667da834d52SDavid C Somayajulu 			return (0); /* its been already added */
3668f10a77bbSDavid C Somayajulu 	}
3669da834d52SDavid C Somayajulu 	return (-1);
3670da834d52SDavid C Somayajulu }
3671da834d52SDavid C Somayajulu 
3672da834d52SDavid C Somayajulu static int
3673da834d52SDavid C Somayajulu qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3674da834d52SDavid C Somayajulu {
3675da834d52SDavid C Somayajulu 	int i;
3676f10a77bbSDavid C Somayajulu 
3677f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3678f10a77bbSDavid C Somayajulu 
3679f10a77bbSDavid C Somayajulu 		if ((ha->hw.mcast[i].addr[0] == 0) &&
3680f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[1] == 0) &&
3681f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[2] == 0) &&
3682f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[3] == 0) &&
3683f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[4] == 0) &&
3684f10a77bbSDavid C Somayajulu 			(ha->hw.mcast[i].addr[5] == 0)) {
3685f10a77bbSDavid C Somayajulu 
3686f10a77bbSDavid C Somayajulu 			bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN);
3687f10a77bbSDavid C Somayajulu 			ha->hw.nmcast++;
3688f10a77bbSDavid C Somayajulu 
3689da834d52SDavid C Somayajulu 			mta = mta + ETHER_ADDR_LEN;
3690da834d52SDavid C Somayajulu 			nmcast--;
3691da834d52SDavid C Somayajulu 
3692da834d52SDavid C Somayajulu 			if (nmcast == 0)
3693da834d52SDavid C Somayajulu 				break;
3694f10a77bbSDavid C Somayajulu 		}
3695da834d52SDavid C Somayajulu 
3696f10a77bbSDavid C Somayajulu 	}
3697f10a77bbSDavid C Somayajulu 	return 0;
3698f10a77bbSDavid C Somayajulu }
3699f10a77bbSDavid C Somayajulu 
3700f10a77bbSDavid C Somayajulu static int
3701da834d52SDavid C Somayajulu qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3702f10a77bbSDavid C Somayajulu {
3703f10a77bbSDavid C Somayajulu 	int i;
3704f10a77bbSDavid C Somayajulu 
3705f10a77bbSDavid C Somayajulu 	for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3706f10a77bbSDavid C Somayajulu 		if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) {
3707f10a77bbSDavid C Somayajulu 
3708f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[0] = 0;
3709f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[1] = 0;
3710f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[2] = 0;
3711f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[3] = 0;
3712f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[4] = 0;
3713f10a77bbSDavid C Somayajulu 			ha->hw.mcast[i].addr[5] = 0;
3714f10a77bbSDavid C Somayajulu 
3715f10a77bbSDavid C Somayajulu 			ha->hw.nmcast--;
3716f10a77bbSDavid C Somayajulu 
3717da834d52SDavid C Somayajulu 			mta = mta + ETHER_ADDR_LEN;
3718da834d52SDavid C Somayajulu 			nmcast--;
3719da834d52SDavid C Somayajulu 
3720da834d52SDavid C Somayajulu 			if (nmcast == 0)
3721da834d52SDavid C Somayajulu 				break;
3722f10a77bbSDavid C Somayajulu 		}
3723f10a77bbSDavid C Somayajulu 	}
3724f10a77bbSDavid C Somayajulu 	return 0;
3725f10a77bbSDavid C Somayajulu }
3726f10a77bbSDavid C Somayajulu 
3727f10a77bbSDavid C Somayajulu /*
3728f10a77bbSDavid C Somayajulu  * Name: ql_hw_set_multi
3729da834d52SDavid C Somayajulu  * Function: Sets the Multicast Addresses provided by the host O.S into the
3730f10a77bbSDavid C Somayajulu  *	hardware (for the given interface)
3731f10a77bbSDavid C Somayajulu  */
3732f10a77bbSDavid C Somayajulu int
3733da834d52SDavid C Somayajulu ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast_addr, uint32_t mcnt,
3734f10a77bbSDavid C Somayajulu 	uint32_t add_mac)
3735f10a77bbSDavid C Somayajulu {
3736da834d52SDavid C Somayajulu 	uint8_t *mta = mcast_addr;
3737f10a77bbSDavid C Somayajulu 	int i;
3738f10a77bbSDavid C Somayajulu 	int ret = 0;
3739da834d52SDavid C Somayajulu 	uint32_t count = 0;
3740da834d52SDavid C Somayajulu 	uint8_t *mcast;
3741da834d52SDavid C Somayajulu 
3742da834d52SDavid C Somayajulu 	mcast = ha->hw.mac_addr_arr;
3743da834d52SDavid C Somayajulu 	memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3744f10a77bbSDavid C Somayajulu 
3745f10a77bbSDavid C Somayajulu 	for (i = 0; i < mcnt; i++) {
3746da834d52SDavid C Somayajulu 		if (mta[0] || mta[1] || mta[2] || mta[3] || mta[4] || mta[5]) {
3747f10a77bbSDavid C Somayajulu 			if (add_mac) {
3748da834d52SDavid C Somayajulu 				if (qla_hw_mac_addr_present(ha, mta) != 0) {
3749da834d52SDavid C Somayajulu 					bcopy(mta, mcast, ETHER_ADDR_LEN);
3750da834d52SDavid C Somayajulu 					mcast = mcast + ETHER_ADDR_LEN;
3751da834d52SDavid C Somayajulu 					count++;
3752da834d52SDavid C Somayajulu 				}
3753f10a77bbSDavid C Somayajulu 			} else {
3754da834d52SDavid C Somayajulu 				if (qla_hw_mac_addr_present(ha, mta) == 0) {
3755da834d52SDavid C Somayajulu 					bcopy(mta, mcast, ETHER_ADDR_LEN);
3756da834d52SDavid C Somayajulu 					mcast = mcast + ETHER_ADDR_LEN;
3757da834d52SDavid C Somayajulu 					count++;
3758da834d52SDavid C Somayajulu 				}
3759da834d52SDavid C Somayajulu 			}
3760da834d52SDavid C Somayajulu 		}
3761da834d52SDavid C Somayajulu 		if (count == Q8_MAX_MAC_ADDRS) {
3762da834d52SDavid C Somayajulu 			if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3763da834d52SDavid C Somayajulu 				add_mac, count)) {
3764da834d52SDavid C Somayajulu                 		device_printf(ha->pci_dev, "%s: failed\n",
3765da834d52SDavid C Somayajulu 					__func__);
3766da834d52SDavid C Somayajulu 				return (-1);
3767da834d52SDavid C Somayajulu 			}
3768da834d52SDavid C Somayajulu 
3769da834d52SDavid C Somayajulu 			if (add_mac) {
3770da834d52SDavid C Somayajulu 				qla_hw_add_mcast(ha, ha->hw.mac_addr_arr,
3771da834d52SDavid C Somayajulu 					count);
3772da834d52SDavid C Somayajulu 			} else {
3773da834d52SDavid C Somayajulu 				qla_hw_del_mcast(ha, ha->hw.mac_addr_arr,
3774da834d52SDavid C Somayajulu 					count);
3775da834d52SDavid C Somayajulu 			}
3776da834d52SDavid C Somayajulu 
3777da834d52SDavid C Somayajulu 			count = 0;
3778da834d52SDavid C Somayajulu 			mcast = ha->hw.mac_addr_arr;
3779da834d52SDavid C Somayajulu 			memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3780f10a77bbSDavid C Somayajulu 		}
3781f10a77bbSDavid C Somayajulu 
3782f10a77bbSDavid C Somayajulu 		mta += Q8_MAC_ADDR_LEN;
3783f10a77bbSDavid C Somayajulu 	}
3784da834d52SDavid C Somayajulu 
3785da834d52SDavid C Somayajulu 	if (count) {
3786da834d52SDavid C Somayajulu 		if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mac,
3787da834d52SDavid C Somayajulu 			count)) {
3788da834d52SDavid C Somayajulu                 	device_printf(ha->pci_dev, "%s: failed\n", __func__);
3789da834d52SDavid C Somayajulu 			return (-1);
3790da834d52SDavid C Somayajulu 		}
3791da834d52SDavid C Somayajulu 		if (add_mac) {
3792da834d52SDavid C Somayajulu 			qla_hw_add_mcast(ha, ha->hw.mac_addr_arr, count);
3793da834d52SDavid C Somayajulu 		} else {
3794da834d52SDavid C Somayajulu 			qla_hw_del_mcast(ha, ha->hw.mac_addr_arr, count);
3795da834d52SDavid C Somayajulu 		}
3796da834d52SDavid C Somayajulu 	}
3797da834d52SDavid C Somayajulu 
3798f10a77bbSDavid C Somayajulu 	return (ret);
3799f10a77bbSDavid C Somayajulu }
3800f10a77bbSDavid C Somayajulu 
3801f10a77bbSDavid C Somayajulu /*
3802b89f2279SDavid C Somayajulu  * Name: ql_hw_tx_done_locked
3803f10a77bbSDavid C Somayajulu  * Function: Handle Transmit Completions
3804f10a77bbSDavid C Somayajulu  */
3805b89f2279SDavid C Somayajulu void
3806b89f2279SDavid C Somayajulu ql_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx)
3807f10a77bbSDavid C Somayajulu {
3808f10a77bbSDavid C Somayajulu 	qla_tx_buf_t *txb;
3809f10a77bbSDavid C Somayajulu         qla_hw_t *hw = &ha->hw;
3810f10a77bbSDavid C Somayajulu 	uint32_t comp_idx, comp_count = 0;
3811f10a77bbSDavid C Somayajulu 	qla_hw_tx_cntxt_t *hw_tx_cntxt;
3812f10a77bbSDavid C Somayajulu 
3813f10a77bbSDavid C Somayajulu 	hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3814f10a77bbSDavid C Somayajulu 
3815f10a77bbSDavid C Somayajulu 	/* retrieve index of last entry in tx ring completed */
3816f10a77bbSDavid C Somayajulu 	comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons));
3817f10a77bbSDavid C Somayajulu 
3818f10a77bbSDavid C Somayajulu 	while (comp_idx != hw_tx_cntxt->txr_comp) {
3819f10a77bbSDavid C Somayajulu 
3820f10a77bbSDavid C Somayajulu 		txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp];
3821f10a77bbSDavid C Somayajulu 
3822f10a77bbSDavid C Somayajulu 		hw_tx_cntxt->txr_comp++;
3823f10a77bbSDavid C Somayajulu 		if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS)
3824f10a77bbSDavid C Somayajulu 			hw_tx_cntxt->txr_comp = 0;
3825f10a77bbSDavid C Somayajulu 
3826f10a77bbSDavid C Somayajulu 		comp_count++;
3827f10a77bbSDavid C Somayajulu 
3828f10a77bbSDavid C Somayajulu 		if (txb->m_head) {
3829c8dfaf38SGleb Smirnoff 			if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1);
3830f10a77bbSDavid C Somayajulu 
3831f10a77bbSDavid C Somayajulu 			bus_dmamap_sync(ha->tx_tag, txb->map,
3832f10a77bbSDavid C Somayajulu 				BUS_DMASYNC_POSTWRITE);
3833f10a77bbSDavid C Somayajulu 			bus_dmamap_unload(ha->tx_tag, txb->map);
3834f10a77bbSDavid C Somayajulu 			m_freem(txb->m_head);
3835f10a77bbSDavid C Somayajulu 
3836f10a77bbSDavid C Somayajulu 			txb->m_head = NULL;
3837f10a77bbSDavid C Somayajulu 		}
3838f10a77bbSDavid C Somayajulu 	}
3839f10a77bbSDavid C Somayajulu 
3840f10a77bbSDavid C Somayajulu 	hw_tx_cntxt->txr_free += comp_count;
3841971e53c9SDavid C Somayajulu 
3842971e53c9SDavid C Somayajulu 	if (hw_tx_cntxt->txr_free > NUM_TX_DESCRIPTORS)
3843971e53c9SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s [%d]: txr_idx = %d txr_free = %d"
3844971e53c9SDavid C Somayajulu 			"txr_next = %d txr_comp = %d\n", __func__, __LINE__,
3845971e53c9SDavid C Somayajulu 			txr_idx, hw_tx_cntxt->txr_free,
3846971e53c9SDavid C Somayajulu 			hw_tx_cntxt->txr_next, hw_tx_cntxt->txr_comp);
3847971e53c9SDavid C Somayajulu 
3848971e53c9SDavid C Somayajulu 	QL_ASSERT(ha, (hw_tx_cntxt->txr_free <= NUM_TX_DESCRIPTORS), \
3849971e53c9SDavid C Somayajulu 		("%s [%d]: txr_idx = %d txr_free = %d txr_next = %d txr_comp = %d\n",\
3850971e53c9SDavid C Somayajulu 		__func__, __LINE__, txr_idx, hw_tx_cntxt->txr_free, \
3851971e53c9SDavid C Somayajulu 		hw_tx_cntxt->txr_next, hw_tx_cntxt->txr_comp));
3852971e53c9SDavid C Somayajulu 
3853f10a77bbSDavid C Somayajulu 	return;
3854f10a77bbSDavid C Somayajulu }
3855f10a77bbSDavid C Somayajulu 
3856f10a77bbSDavid C Somayajulu void
3857f10a77bbSDavid C Somayajulu ql_update_link_state(qla_host_t *ha)
3858f10a77bbSDavid C Somayajulu {
3859b65c0c07SDavid C Somayajulu 	uint32_t link_state = 0;
3860f10a77bbSDavid C Somayajulu 	uint32_t prev_link_state;
3861f10a77bbSDavid C Somayajulu 
3862f10a77bbSDavid C Somayajulu 	prev_link_state =  ha->hw.link_up;
3863f10a77bbSDavid C Somayajulu 
3864b65c0c07SDavid C Somayajulu 	if (ha->ifp->if_drv_flags & IFF_DRV_RUNNING) {
3865b65c0c07SDavid C Somayajulu 		link_state = READ_REG32(ha, Q8_LINK_STATE);
3866b65c0c07SDavid C Somayajulu 
3867b65c0c07SDavid C Somayajulu 		if (ha->pci_func == 0) {
3868b65c0c07SDavid C Somayajulu 			link_state = (((link_state & 0xF) == 1)? 1 : 0);
3869b65c0c07SDavid C Somayajulu 		} else {
3870b65c0c07SDavid C Somayajulu 			link_state = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
3871b65c0c07SDavid C Somayajulu 		}
3872b65c0c07SDavid C Somayajulu 	}
3873b65c0c07SDavid C Somayajulu 
3874b65c0c07SDavid C Somayajulu 	atomic_store_rel_8(&ha->hw.link_up, (uint8_t)link_state);
3875f10a77bbSDavid C Somayajulu 
3876f10a77bbSDavid C Somayajulu 	if (prev_link_state !=  ha->hw.link_up) {
3877f10a77bbSDavid C Somayajulu 		if (ha->hw.link_up) {
3878f10a77bbSDavid C Somayajulu 			if_link_state_change(ha->ifp, LINK_STATE_UP);
3879f10a77bbSDavid C Somayajulu 		} else {
3880f10a77bbSDavid C Somayajulu 			if_link_state_change(ha->ifp, LINK_STATE_DOWN);
3881f10a77bbSDavid C Somayajulu 		}
3882f10a77bbSDavid C Somayajulu 	}
3883f10a77bbSDavid C Somayajulu 	return;
3884f10a77bbSDavid C Somayajulu }
3885f10a77bbSDavid C Somayajulu 
3886f10a77bbSDavid C Somayajulu int
3887f10a77bbSDavid C Somayajulu ql_hw_check_health(qla_host_t *ha)
3888f10a77bbSDavid C Somayajulu {
3889f10a77bbSDavid C Somayajulu 	uint32_t val;
3890f10a77bbSDavid C Somayajulu 
3891f10a77bbSDavid C Somayajulu 	ha->hw.health_count++;
3892f10a77bbSDavid C Somayajulu 
389312e46badSDavid C Somayajulu 	if (ha->hw.health_count < 500)
3894f10a77bbSDavid C Somayajulu 		return 0;
3895f10a77bbSDavid C Somayajulu 
3896f10a77bbSDavid C Somayajulu 	ha->hw.health_count = 0;
3897f10a77bbSDavid C Somayajulu 
3898f10a77bbSDavid C Somayajulu 	val = READ_REG32(ha, Q8_ASIC_TEMPERATURE);
3899f10a77bbSDavid C Somayajulu 
3900f10a77bbSDavid C Somayajulu 	if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) ||
3901f10a77bbSDavid C Somayajulu 		(QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) {
3902b65c0c07SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Temperature Alert"
3903b65c0c07SDavid C Somayajulu 			" at ts_usecs %ld ts_reg = 0x%08x\n",
3904b65c0c07SDavid C Somayajulu 			__func__, qla_get_usec_timestamp(), val);
3905b65c0c07SDavid C Somayajulu 
3906b65c0c07SDavid C Somayajulu 		if (ha->hw.sp_log_stop_events & Q8_SP_LOG_STOP_TEMP_FAILURE)
3907b65c0c07SDavid C Somayajulu 			ha->hw.sp_log_stop = -1;
3908b65c0c07SDavid C Somayajulu 
3909b65c0c07SDavid C Somayajulu 		QL_INITIATE_RECOVERY(ha);
3910f10a77bbSDavid C Somayajulu 		return -1;
3911f10a77bbSDavid C Somayajulu 	}
3912f10a77bbSDavid C Somayajulu 
3913f10a77bbSDavid C Somayajulu 	val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
3914f10a77bbSDavid C Somayajulu 
3915f10a77bbSDavid C Somayajulu 	if ((val != ha->hw.hbeat_value) &&
3916467dcb5aSDavid C Somayajulu 		(!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) {
3917f10a77bbSDavid C Somayajulu 		ha->hw.hbeat_value = val;
391812e46badSDavid C Somayajulu 		ha->hw.hbeat_failure = 0;
3919f10a77bbSDavid C Somayajulu 		return 0;
3920f10a77bbSDavid C Somayajulu 	}
392112e46badSDavid C Somayajulu 
392212e46badSDavid C Somayajulu 	ha->hw.hbeat_failure++;
392312e46badSDavid C Somayajulu 
39247fb51846SDavid C Somayajulu 
39257fb51846SDavid C Somayajulu 	if ((ha->dbg_level & 0x8000) && (ha->hw.hbeat_failure == 1))
39267fb51846SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Heartbeat Failue 1[0x%08x]\n",
39277fb51846SDavid C Somayajulu 			__func__, val);
392812e46badSDavid C Somayajulu 	if (ha->hw.hbeat_failure < 2) /* we ignore the first failure */
392912e46badSDavid C Somayajulu 		return 0;
3930b65c0c07SDavid C Somayajulu 	else {
3931b65c0c07SDavid C Somayajulu 		uint32_t peg_halt_status1;
3932b65c0c07SDavid C Somayajulu 		uint32_t peg_halt_status2;
3933b65c0c07SDavid C Somayajulu 
3934b65c0c07SDavid C Somayajulu 		peg_halt_status1 = READ_REG32(ha, Q8_PEG_HALT_STATUS1);
3935b65c0c07SDavid C Somayajulu 		peg_halt_status2 = READ_REG32(ha, Q8_PEG_HALT_STATUS2);
3936b65c0c07SDavid C Somayajulu 
3937b65c0c07SDavid C Somayajulu 		device_printf(ha->pci_dev,
3938b65c0c07SDavid C Somayajulu 			"%s: Heartbeat Failue at ts_usecs = %ld "
3939b65c0c07SDavid C Somayajulu 			"fw_heart_beat = 0x%08x "
3940b65c0c07SDavid C Somayajulu 			"peg_halt_status1 = 0x%08x "
3941b65c0c07SDavid C Somayajulu 			"peg_halt_status2 = 0x%08x\n",
3942b65c0c07SDavid C Somayajulu 			__func__, qla_get_usec_timestamp(), val,
3943b65c0c07SDavid C Somayajulu 			peg_halt_status1, peg_halt_status2);
3944b65c0c07SDavid C Somayajulu 
3945b65c0c07SDavid C Somayajulu 		if (ha->hw.sp_log_stop_events & Q8_SP_LOG_STOP_HBEAT_FAILURE)
3946b65c0c07SDavid C Somayajulu 			ha->hw.sp_log_stop = -1;
3947b65c0c07SDavid C Somayajulu 	}
3948b65c0c07SDavid C Somayajulu 	QL_INITIATE_RECOVERY(ha);
3949f10a77bbSDavid C Somayajulu 
3950f10a77bbSDavid C Somayajulu 	return -1;
3951f10a77bbSDavid C Somayajulu }
3952f10a77bbSDavid C Somayajulu 
3953f10a77bbSDavid C Somayajulu static int
395435291c22SDavid C Somayajulu qla_init_nic_func(qla_host_t *ha)
395535291c22SDavid C Somayajulu {
395635291c22SDavid C Somayajulu         device_t                dev;
395735291c22SDavid C Somayajulu         q80_init_nic_func_t     *init_nic;
395835291c22SDavid C Somayajulu         q80_init_nic_func_rsp_t *init_nic_rsp;
395935291c22SDavid C Somayajulu         uint32_t                err;
396035291c22SDavid C Somayajulu 
396135291c22SDavid C Somayajulu         dev = ha->pci_dev;
396235291c22SDavid C Somayajulu 
396335291c22SDavid C Somayajulu         init_nic = (q80_init_nic_func_t *)ha->hw.mbox;
396435291c22SDavid C Somayajulu         bzero(init_nic, sizeof(q80_init_nic_func_t));
396535291c22SDavid C Somayajulu 
396635291c22SDavid C Somayajulu         init_nic->opcode = Q8_MBX_INIT_NIC_FUNC;
396735291c22SDavid C Somayajulu         init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2);
396835291c22SDavid C Somayajulu         init_nic->count_version |= Q8_MBX_CMD_VERSION;
396935291c22SDavid C Somayajulu 
397035291c22SDavid C Somayajulu         init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN;
397135291c22SDavid C Somayajulu         init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN;
397235291c22SDavid C Somayajulu         init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN;
397335291c22SDavid C Somayajulu 
397435291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t));
397535291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)init_nic,
397635291c22SDavid C Somayajulu                 (sizeof (q80_init_nic_func_t) >> 2),
397735291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) {
397835291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
397935291c22SDavid C Somayajulu                 return -1;
398035291c22SDavid C Somayajulu         }
398135291c22SDavid C Somayajulu 
398235291c22SDavid C Somayajulu         init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox;
398335291c22SDavid C Somayajulu // qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t));
398435291c22SDavid C Somayajulu 
398535291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status);
398635291c22SDavid C Somayajulu 
398735291c22SDavid C Somayajulu         if (err) {
398835291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3989971e53c9SDavid C Somayajulu         } else {
3990971e53c9SDavid C Somayajulu                 device_printf(dev, "%s: successful\n", __func__);
399135291c22SDavid C Somayajulu 	}
399235291c22SDavid C Somayajulu 
399335291c22SDavid C Somayajulu         return 0;
399435291c22SDavid C Somayajulu }
399535291c22SDavid C Somayajulu 
399635291c22SDavid C Somayajulu static int
399735291c22SDavid C Somayajulu qla_stop_nic_func(qla_host_t *ha)
399835291c22SDavid C Somayajulu {
399935291c22SDavid C Somayajulu         device_t                dev;
400035291c22SDavid C Somayajulu         q80_stop_nic_func_t     *stop_nic;
400135291c22SDavid C Somayajulu         q80_stop_nic_func_rsp_t *stop_nic_rsp;
400235291c22SDavid C Somayajulu         uint32_t                err;
400335291c22SDavid C Somayajulu 
400435291c22SDavid C Somayajulu         dev = ha->pci_dev;
400535291c22SDavid C Somayajulu 
400635291c22SDavid C Somayajulu         stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox;
400735291c22SDavid C Somayajulu         bzero(stop_nic, sizeof(q80_stop_nic_func_t));
400835291c22SDavid C Somayajulu 
400935291c22SDavid C Somayajulu         stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC;
401035291c22SDavid C Somayajulu         stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2);
401135291c22SDavid C Somayajulu         stop_nic->count_version |= Q8_MBX_CMD_VERSION;
401235291c22SDavid C Somayajulu 
401335291c22SDavid C Somayajulu         stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN;
401435291c22SDavid C Somayajulu         stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN;
401535291c22SDavid C Somayajulu 
401635291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t));
401735291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)stop_nic,
401835291c22SDavid C Somayajulu                 (sizeof (q80_stop_nic_func_t) >> 2),
401935291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) {
402035291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
402135291c22SDavid C Somayajulu                 return -1;
402235291c22SDavid C Somayajulu         }
402335291c22SDavid C Somayajulu 
402435291c22SDavid C Somayajulu         stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox;
402535291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t));
402635291c22SDavid C Somayajulu 
402735291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status);
402835291c22SDavid C Somayajulu 
402935291c22SDavid C Somayajulu         if (err) {
403035291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
403135291c22SDavid C Somayajulu         }
403235291c22SDavid C Somayajulu 
403335291c22SDavid C Somayajulu         return 0;
403435291c22SDavid C Somayajulu }
403535291c22SDavid C Somayajulu 
403635291c22SDavid C Somayajulu static int
403735291c22SDavid C Somayajulu qla_query_fw_dcbx_caps(qla_host_t *ha)
403835291c22SDavid C Somayajulu {
403935291c22SDavid C Somayajulu         device_t                        dev;
404035291c22SDavid C Somayajulu         q80_query_fw_dcbx_caps_t        *fw_dcbx;
404135291c22SDavid C Somayajulu         q80_query_fw_dcbx_caps_rsp_t    *fw_dcbx_rsp;
404235291c22SDavid C Somayajulu         uint32_t                        err;
404335291c22SDavid C Somayajulu 
404435291c22SDavid C Somayajulu         dev = ha->pci_dev;
404535291c22SDavid C Somayajulu 
404635291c22SDavid C Somayajulu         fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox;
404735291c22SDavid C Somayajulu         bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t));
404835291c22SDavid C Somayajulu 
404935291c22SDavid C Somayajulu         fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS;
405035291c22SDavid C Somayajulu         fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2);
405135291c22SDavid C Somayajulu         fw_dcbx->count_version |= Q8_MBX_CMD_VERSION;
405235291c22SDavid C Somayajulu 
405335291c22SDavid C Somayajulu         ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t));
405435291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx,
405535291c22SDavid C Somayajulu                 (sizeof (q80_query_fw_dcbx_caps_t) >> 2),
405635291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) {
405735291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
405835291c22SDavid C Somayajulu                 return -1;
405935291c22SDavid C Somayajulu         }
406035291c22SDavid C Somayajulu 
406135291c22SDavid C Somayajulu         fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox;
406235291c22SDavid C Somayajulu         ql_dump_buf8(ha, __func__, fw_dcbx_rsp,
406335291c22SDavid C Somayajulu                 sizeof (q80_query_fw_dcbx_caps_rsp_t));
406435291c22SDavid C Somayajulu 
406535291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status);
406635291c22SDavid C Somayajulu 
406735291c22SDavid C Somayajulu         if (err) {
406835291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
406935291c22SDavid C Somayajulu         }
407035291c22SDavid C Somayajulu 
407135291c22SDavid C Somayajulu         return 0;
407235291c22SDavid C Somayajulu }
407335291c22SDavid C Somayajulu 
407435291c22SDavid C Somayajulu static int
407535291c22SDavid C Somayajulu qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2,
407635291c22SDavid C Somayajulu         uint32_t aen_mb3, uint32_t aen_mb4)
407735291c22SDavid C Somayajulu {
407835291c22SDavid C Somayajulu         device_t                dev;
407935291c22SDavid C Somayajulu         q80_idc_ack_t           *idc_ack;
408035291c22SDavid C Somayajulu         q80_idc_ack_rsp_t       *idc_ack_rsp;
408135291c22SDavid C Somayajulu         uint32_t                err;
408235291c22SDavid C Somayajulu         int                     count = 300;
408335291c22SDavid C Somayajulu 
408435291c22SDavid C Somayajulu         dev = ha->pci_dev;
408535291c22SDavid C Somayajulu 
408635291c22SDavid C Somayajulu         idc_ack = (q80_idc_ack_t *)ha->hw.mbox;
408735291c22SDavid C Somayajulu         bzero(idc_ack, sizeof(q80_idc_ack_t));
408835291c22SDavid C Somayajulu 
408935291c22SDavid C Somayajulu         idc_ack->opcode = Q8_MBX_IDC_ACK;
409035291c22SDavid C Somayajulu         idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2);
409135291c22SDavid C Somayajulu         idc_ack->count_version |= Q8_MBX_CMD_VERSION;
409235291c22SDavid C Somayajulu 
409335291c22SDavid C Somayajulu         idc_ack->aen_mb1 = aen_mb1;
409435291c22SDavid C Somayajulu         idc_ack->aen_mb2 = aen_mb2;
409535291c22SDavid C Somayajulu         idc_ack->aen_mb3 = aen_mb3;
409635291c22SDavid C Somayajulu         idc_ack->aen_mb4 = aen_mb4;
409735291c22SDavid C Somayajulu 
409835291c22SDavid C Somayajulu         ha->hw.imd_compl= 0;
409935291c22SDavid C Somayajulu 
410035291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)idc_ack,
410135291c22SDavid C Somayajulu                 (sizeof (q80_idc_ack_t) >> 2),
410235291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) {
410335291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
410435291c22SDavid C Somayajulu                 return -1;
410535291c22SDavid C Somayajulu         }
410635291c22SDavid C Somayajulu 
410735291c22SDavid C Somayajulu         idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox;
410835291c22SDavid C Somayajulu 
410935291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status);
411035291c22SDavid C Somayajulu 
411135291c22SDavid C Somayajulu         if (err) {
411235291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
411335291c22SDavid C Somayajulu                 return(-1);
411435291c22SDavid C Somayajulu         }
411535291c22SDavid C Somayajulu 
411635291c22SDavid C Somayajulu         while (count && !ha->hw.imd_compl) {
411735291c22SDavid C Somayajulu                 qla_mdelay(__func__, 100);
411835291c22SDavid C Somayajulu                 count--;
411935291c22SDavid C Somayajulu         }
412035291c22SDavid C Somayajulu 
412135291c22SDavid C Somayajulu         if (!count)
412235291c22SDavid C Somayajulu                 return -1;
412335291c22SDavid C Somayajulu         else
412435291c22SDavid C Somayajulu                 device_printf(dev, "%s: count %d\n", __func__, count);
412535291c22SDavid C Somayajulu 
412635291c22SDavid C Somayajulu         return (0);
412735291c22SDavid C Somayajulu }
412835291c22SDavid C Somayajulu 
412935291c22SDavid C Somayajulu static int
413035291c22SDavid C Somayajulu qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits)
413135291c22SDavid C Somayajulu {
413235291c22SDavid C Somayajulu         device_t                dev;
413335291c22SDavid C Somayajulu         q80_set_port_cfg_t      *pcfg;
413435291c22SDavid C Somayajulu         q80_set_port_cfg_rsp_t  *pfg_rsp;
413535291c22SDavid C Somayajulu         uint32_t                err;
413635291c22SDavid C Somayajulu         int                     count = 300;
413735291c22SDavid C Somayajulu 
413835291c22SDavid C Somayajulu         dev = ha->pci_dev;
413935291c22SDavid C Somayajulu 
414035291c22SDavid C Somayajulu         pcfg = (q80_set_port_cfg_t *)ha->hw.mbox;
414135291c22SDavid C Somayajulu         bzero(pcfg, sizeof(q80_set_port_cfg_t));
414235291c22SDavid C Somayajulu 
414335291c22SDavid C Somayajulu         pcfg->opcode = Q8_MBX_SET_PORT_CONFIG;
414435291c22SDavid C Somayajulu         pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2);
414535291c22SDavid C Somayajulu         pcfg->count_version |= Q8_MBX_CMD_VERSION;
414635291c22SDavid C Somayajulu 
414735291c22SDavid C Somayajulu         pcfg->cfg_bits = cfg_bits;
414835291c22SDavid C Somayajulu 
414935291c22SDavid C Somayajulu         device_printf(dev, "%s: cfg_bits"
415035291c22SDavid C Somayajulu                 " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
415135291c22SDavid C Somayajulu                 " [0x%x, 0x%x, 0x%x]\n", __func__,
415235291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
415335291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
415435291c22SDavid C Somayajulu                 ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0));
415535291c22SDavid C Somayajulu 
415635291c22SDavid C Somayajulu         ha->hw.imd_compl= 0;
415735291c22SDavid C Somayajulu 
415835291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
415935291c22SDavid C Somayajulu                 (sizeof (q80_set_port_cfg_t) >> 2),
416035291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) {
416135291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
416235291c22SDavid C Somayajulu                 return -1;
416335291c22SDavid C Somayajulu         }
416435291c22SDavid C Somayajulu 
416535291c22SDavid C Somayajulu         pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox;
416635291c22SDavid C Somayajulu 
416735291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status);
416835291c22SDavid C Somayajulu 
416935291c22SDavid C Somayajulu         if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) {
417035291c22SDavid C Somayajulu                 while (count && !ha->hw.imd_compl) {
417135291c22SDavid C Somayajulu                         qla_mdelay(__func__, 100);
417235291c22SDavid C Somayajulu                         count--;
417335291c22SDavid C Somayajulu                 }
417435291c22SDavid C Somayajulu                 if (count) {
417535291c22SDavid C Somayajulu                         device_printf(dev, "%s: count %d\n", __func__, count);
417635291c22SDavid C Somayajulu 
417735291c22SDavid C Somayajulu                         err = 0;
417835291c22SDavid C Somayajulu                 }
417935291c22SDavid C Somayajulu         }
418035291c22SDavid C Somayajulu 
418135291c22SDavid C Somayajulu         if (err) {
418235291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
418335291c22SDavid C Somayajulu                 return(-1);
418435291c22SDavid C Somayajulu         }
418535291c22SDavid C Somayajulu 
418635291c22SDavid C Somayajulu         return (0);
418735291c22SDavid C Somayajulu }
418835291c22SDavid C Somayajulu 
418935291c22SDavid C Somayajulu 
419035291c22SDavid C Somayajulu static int
4191f10a77bbSDavid C Somayajulu qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size)
4192f10a77bbSDavid C Somayajulu {
4193f10a77bbSDavid C Somayajulu 	uint32_t			err;
4194f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
4195f10a77bbSDavid C Somayajulu 	q80_config_md_templ_size_t	*md_size;
4196f10a77bbSDavid C Somayajulu 	q80_config_md_templ_size_rsp_t	*md_size_rsp;
4197f10a77bbSDavid C Somayajulu 
41986a62bec0SDavid C Somayajulu #ifndef QL_LDFLASH_FW
419935291c22SDavid C Somayajulu 
42006a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *hdr;
42016a62bec0SDavid C Somayajulu 
42026a62bec0SDavid C Somayajulu 	hdr = (ql_minidump_template_hdr_t *)ql83xx_minidump;
42036a62bec0SDavid C Somayajulu 	*size = hdr->size_of_template;
420435291c22SDavid C Somayajulu 	return (0);
420535291c22SDavid C Somayajulu 
420635291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
420735291c22SDavid C Somayajulu 
4208f10a77bbSDavid C Somayajulu 	md_size = (q80_config_md_templ_size_t *) ha->hw.mbox;
4209f10a77bbSDavid C Somayajulu 	bzero(md_size, sizeof(q80_config_md_templ_size_t));
4210f10a77bbSDavid C Somayajulu 
4211f10a77bbSDavid C Somayajulu 	md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE;
4212f10a77bbSDavid C Somayajulu 	md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2);
4213f10a77bbSDavid C Somayajulu 	md_size->count_version |= Q8_MBX_CMD_VERSION;
4214f10a77bbSDavid C Somayajulu 
4215f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *) md_size,
4216f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox,
4217f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) {
4218f10a77bbSDavid C Somayajulu 
4219f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
4220f10a77bbSDavid C Somayajulu 
4221f10a77bbSDavid C Somayajulu 		return (-1);
4222f10a77bbSDavid C Somayajulu 	}
4223f10a77bbSDavid C Somayajulu 
4224f10a77bbSDavid C Somayajulu 	md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox;
4225f10a77bbSDavid C Somayajulu 
4226f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status);
4227f10a77bbSDavid C Somayajulu 
4228f10a77bbSDavid C Somayajulu         if (err) {
4229f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4230f10a77bbSDavid C Somayajulu 		return(-1);
4231f10a77bbSDavid C Somayajulu         }
4232f10a77bbSDavid C Somayajulu 
4233f10a77bbSDavid C Somayajulu 	*size = md_size_rsp->templ_size;
4234f10a77bbSDavid C Somayajulu 
4235f10a77bbSDavid C Somayajulu 	return (0);
4236f10a77bbSDavid C Somayajulu }
4237f10a77bbSDavid C Somayajulu 
4238f10a77bbSDavid C Somayajulu static int
423935291c22SDavid C Somayajulu qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits)
424035291c22SDavid C Somayajulu {
424135291c22SDavid C Somayajulu         device_t                dev;
424235291c22SDavid C Somayajulu         q80_get_port_cfg_t      *pcfg;
424335291c22SDavid C Somayajulu         q80_get_port_cfg_rsp_t  *pcfg_rsp;
424435291c22SDavid C Somayajulu         uint32_t                err;
424535291c22SDavid C Somayajulu 
424635291c22SDavid C Somayajulu         dev = ha->pci_dev;
424735291c22SDavid C Somayajulu 
424835291c22SDavid C Somayajulu         pcfg = (q80_get_port_cfg_t *)ha->hw.mbox;
424935291c22SDavid C Somayajulu         bzero(pcfg, sizeof(q80_get_port_cfg_t));
425035291c22SDavid C Somayajulu 
425135291c22SDavid C Somayajulu         pcfg->opcode = Q8_MBX_GET_PORT_CONFIG;
425235291c22SDavid C Somayajulu         pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2);
425335291c22SDavid C Somayajulu         pcfg->count_version |= Q8_MBX_CMD_VERSION;
425435291c22SDavid C Somayajulu 
425535291c22SDavid C Somayajulu         if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
425635291c22SDavid C Somayajulu                 (sizeof (q80_get_port_cfg_t) >> 2),
425735291c22SDavid C Somayajulu                 ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) {
425835291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed\n", __func__);
425935291c22SDavid C Somayajulu                 return -1;
426035291c22SDavid C Somayajulu         }
426135291c22SDavid C Somayajulu 
426235291c22SDavid C Somayajulu         pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox;
426335291c22SDavid C Somayajulu 
426435291c22SDavid C Somayajulu         err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status);
426535291c22SDavid C Somayajulu 
426635291c22SDavid C Somayajulu         if (err) {
426735291c22SDavid C Somayajulu                 device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
426835291c22SDavid C Somayajulu                 return(-1);
426935291c22SDavid C Somayajulu         }
427035291c22SDavid C Somayajulu 
427135291c22SDavid C Somayajulu         device_printf(dev, "%s: [cfg_bits, port type]"
427235291c22SDavid C Somayajulu                 " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
427335291c22SDavid C Somayajulu                 " [0x%x, 0x%x, 0x%x]\n", __func__,
427435291c22SDavid C Somayajulu                 pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type,
427535291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
427635291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
427735291c22SDavid C Somayajulu                 ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)
427835291c22SDavid C Somayajulu                 );
427935291c22SDavid C Somayajulu 
428035291c22SDavid C Somayajulu         *cfg_bits = pcfg_rsp->cfg_bits;
428135291c22SDavid C Somayajulu 
428235291c22SDavid C Somayajulu         return (0);
428335291c22SDavid C Somayajulu }
428435291c22SDavid C Somayajulu 
428535291c22SDavid C Somayajulu int
4286b89f2279SDavid C Somayajulu ql_iscsi_pdu(qla_host_t *ha, struct mbuf *mp)
428735291c22SDavid C Somayajulu {
428835291c22SDavid C Somayajulu         struct ether_vlan_header        *eh;
428935291c22SDavid C Somayajulu         uint16_t                        etype;
429035291c22SDavid C Somayajulu         struct ip                       *ip = NULL;
429135291c22SDavid C Somayajulu         struct ip6_hdr                  *ip6 = NULL;
429235291c22SDavid C Somayajulu         struct tcphdr                   *th = NULL;
429335291c22SDavid C Somayajulu         uint32_t                        hdrlen;
429435291c22SDavid C Somayajulu         uint32_t                        offset;
429535291c22SDavid C Somayajulu         uint8_t                         buf[sizeof(struct ip6_hdr)];
429635291c22SDavid C Somayajulu 
429735291c22SDavid C Somayajulu         eh = mtod(mp, struct ether_vlan_header *);
429835291c22SDavid C Somayajulu 
429935291c22SDavid C Somayajulu         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
430035291c22SDavid C Somayajulu                 hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
430135291c22SDavid C Somayajulu                 etype = ntohs(eh->evl_proto);
430235291c22SDavid C Somayajulu         } else {
430335291c22SDavid C Somayajulu                 hdrlen = ETHER_HDR_LEN;
430435291c22SDavid C Somayajulu                 etype = ntohs(eh->evl_encap_proto);
430535291c22SDavid C Somayajulu         }
430635291c22SDavid C Somayajulu 
430735291c22SDavid C Somayajulu 	if (etype == ETHERTYPE_IP) {
430835291c22SDavid C Somayajulu 
430935291c22SDavid C Somayajulu 		offset = (hdrlen + sizeof (struct ip));
431035291c22SDavid C Somayajulu 
431135291c22SDavid C Somayajulu 		if (mp->m_len >= offset) {
431235291c22SDavid C Somayajulu                         ip = (struct ip *)(mp->m_data + hdrlen);
431335291c22SDavid C Somayajulu 		} else {
431435291c22SDavid C Somayajulu 			m_copydata(mp, hdrlen, sizeof (struct ip), buf);
431535291c22SDavid C Somayajulu                         ip = (struct ip *)buf;
431635291c22SDavid C Somayajulu 		}
431735291c22SDavid C Somayajulu 
431835291c22SDavid C Somayajulu                 if (ip->ip_p == IPPROTO_TCP) {
431935291c22SDavid C Somayajulu 
432035291c22SDavid C Somayajulu 			hdrlen += ip->ip_hl << 2;
432135291c22SDavid C Somayajulu 			offset = hdrlen + 4;
432235291c22SDavid C Somayajulu 
432335291c22SDavid C Somayajulu 			if (mp->m_len >= offset) {
43246a62bec0SDavid C Somayajulu 				th = (struct tcphdr *)(mp->m_data + hdrlen);;
432535291c22SDavid C Somayajulu 			} else {
432635291c22SDavid C Somayajulu                                 m_copydata(mp, hdrlen, 4, buf);
432735291c22SDavid C Somayajulu 				th = (struct tcphdr *)buf;
432835291c22SDavid C Somayajulu 			}
432935291c22SDavid C Somayajulu                 }
433035291c22SDavid C Somayajulu 
433135291c22SDavid C Somayajulu 	} else if (etype == ETHERTYPE_IPV6) {
433235291c22SDavid C Somayajulu 
433335291c22SDavid C Somayajulu 		offset = (hdrlen + sizeof (struct ip6_hdr));
433435291c22SDavid C Somayajulu 
433535291c22SDavid C Somayajulu 		if (mp->m_len >= offset) {
433635291c22SDavid C Somayajulu                         ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen);
433735291c22SDavid C Somayajulu 		} else {
433835291c22SDavid C Somayajulu                         m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf);
433935291c22SDavid C Somayajulu                         ip6 = (struct ip6_hdr *)buf;
434035291c22SDavid C Somayajulu 		}
434135291c22SDavid C Somayajulu 
434235291c22SDavid C Somayajulu                 if (ip6->ip6_nxt == IPPROTO_TCP) {
434335291c22SDavid C Somayajulu 
434435291c22SDavid C Somayajulu 			hdrlen += sizeof(struct ip6_hdr);
434535291c22SDavid C Somayajulu 			offset = hdrlen + 4;
434635291c22SDavid C Somayajulu 
434735291c22SDavid C Somayajulu 			if (mp->m_len >= offset) {
43486a62bec0SDavid C Somayajulu 				th = (struct tcphdr *)(mp->m_data + hdrlen);;
434935291c22SDavid C Somayajulu 			} else {
435035291c22SDavid C Somayajulu 				m_copydata(mp, hdrlen, 4, buf);
435135291c22SDavid C Somayajulu 				th = (struct tcphdr *)buf;
435235291c22SDavid C Somayajulu 			}
435335291c22SDavid C Somayajulu                 }
435435291c22SDavid C Somayajulu 	}
435535291c22SDavid C Somayajulu 
435635291c22SDavid C Somayajulu         if (th != NULL) {
435735291c22SDavid C Somayajulu                 if ((th->th_sport == htons(3260)) ||
435835291c22SDavid C Somayajulu                         (th->th_dport == htons(3260)))
435935291c22SDavid C Somayajulu                         return 0;
436035291c22SDavid C Somayajulu         }
436135291c22SDavid C Somayajulu         return (-1);
436235291c22SDavid C Somayajulu }
436335291c22SDavid C Somayajulu 
436435291c22SDavid C Somayajulu void
436535291c22SDavid C Somayajulu qla_hw_async_event(qla_host_t *ha)
436635291c22SDavid C Somayajulu {
436735291c22SDavid C Somayajulu         switch (ha->hw.aen_mb0) {
436835291c22SDavid C Somayajulu         case 0x8101:
436935291c22SDavid C Somayajulu                 (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2,
437035291c22SDavid C Somayajulu                         ha->hw.aen_mb3, ha->hw.aen_mb4);
437135291c22SDavid C Somayajulu 
437235291c22SDavid C Somayajulu                 break;
437335291c22SDavid C Somayajulu 
437435291c22SDavid C Somayajulu         default:
437535291c22SDavid C Somayajulu                 break;
437635291c22SDavid C Somayajulu         }
437735291c22SDavid C Somayajulu 
437835291c22SDavid C Somayajulu         return;
437935291c22SDavid C Somayajulu }
438035291c22SDavid C Somayajulu 
438135291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
438235291c22SDavid C Somayajulu static int
43836a62bec0SDavid C Somayajulu ql_get_minidump_template(qla_host_t *ha)
4384f10a77bbSDavid C Somayajulu {
4385f10a77bbSDavid C Somayajulu 	uint32_t			err;
4386f10a77bbSDavid C Somayajulu 	device_t			dev = ha->pci_dev;
4387f10a77bbSDavid C Somayajulu 	q80_config_md_templ_cmd_t	*md_templ;
4388f10a77bbSDavid C Somayajulu 	q80_config_md_templ_cmd_rsp_t	*md_templ_rsp;
4389f10a77bbSDavid C Somayajulu 
4390f10a77bbSDavid C Somayajulu 	md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox;
4391f10a77bbSDavid C Somayajulu 	bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t)));
4392f10a77bbSDavid C Somayajulu 
4393f10a77bbSDavid C Somayajulu 	md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT;
4394f10a77bbSDavid C Somayajulu 	md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2);
4395f10a77bbSDavid C Somayajulu 	md_templ->count_version |= Q8_MBX_CMD_VERSION;
4396f10a77bbSDavid C Somayajulu 
4397f10a77bbSDavid C Somayajulu 	md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr;
4398f10a77bbSDavid C Somayajulu 	md_templ->buff_size = ha->hw.dma_buf.minidump.size;
4399f10a77bbSDavid C Somayajulu 
4400f10a77bbSDavid C Somayajulu 	if (qla_mbx_cmd(ha, (uint32_t *) md_templ,
4401f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_cmd_t) >> 2),
4402f10a77bbSDavid C Somayajulu 		 ha->hw.mbox,
4403f10a77bbSDavid C Somayajulu 		(sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) {
4404f10a77bbSDavid C Somayajulu 
4405f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed\n", __func__);
4406f10a77bbSDavid C Somayajulu 
4407f10a77bbSDavid C Somayajulu 		return (-1);
4408f10a77bbSDavid C Somayajulu 	}
4409f10a77bbSDavid C Somayajulu 
4410f10a77bbSDavid C Somayajulu 	md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox;
4411f10a77bbSDavid C Somayajulu 
4412f10a77bbSDavid C Somayajulu 	err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status);
4413f10a77bbSDavid C Somayajulu 
4414f10a77bbSDavid C Somayajulu 	if (err) {
4415f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4416f10a77bbSDavid C Somayajulu 		return (-1);
4417f10a77bbSDavid C Somayajulu 	}
4418f10a77bbSDavid C Somayajulu 
4419f10a77bbSDavid C Somayajulu 	return (0);
4420f10a77bbSDavid C Somayajulu 
4421f10a77bbSDavid C Somayajulu }
442235291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
4423f10a77bbSDavid C Somayajulu 
44246a62bec0SDavid C Somayajulu /*
44256a62bec0SDavid C Somayajulu  * Minidump related functionality
44266a62bec0SDavid C Somayajulu  */
44276a62bec0SDavid C Somayajulu 
44286a62bec0SDavid C Somayajulu static int ql_parse_template(qla_host_t *ha);
44296a62bec0SDavid C Somayajulu 
44306a62bec0SDavid C Somayajulu static uint32_t ql_rdcrb(qla_host_t *ha,
44316a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdcrb_t *crb_entry,
44326a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
44336a62bec0SDavid C Somayajulu 
44346a62bec0SDavid C Somayajulu static uint32_t ql_pollrd(qla_host_t *ha,
44356a62bec0SDavid C Somayajulu 			ql_minidump_entry_pollrd_t *entry,
44366a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
44376a62bec0SDavid C Somayajulu 
44386a62bec0SDavid C Somayajulu static uint32_t ql_pollrd_modify_write(qla_host_t *ha,
44396a62bec0SDavid C Somayajulu 			ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
44406a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
44416a62bec0SDavid C Somayajulu 
44426a62bec0SDavid C Somayajulu static uint32_t ql_L2Cache(qla_host_t *ha,
44436a62bec0SDavid C Somayajulu 			ql_minidump_entry_cache_t *cacheEntry,
44446a62bec0SDavid C Somayajulu 			uint32_t * data_buff);
44456a62bec0SDavid C Somayajulu 
44466a62bec0SDavid C Somayajulu static uint32_t ql_L1Cache(qla_host_t *ha,
44476a62bec0SDavid C Somayajulu 			ql_minidump_entry_cache_t *cacheEntry,
44486a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
44496a62bec0SDavid C Somayajulu 
44506a62bec0SDavid C Somayajulu static uint32_t ql_rdocm(qla_host_t *ha,
44516a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdocm_t *ocmEntry,
44526a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
44536a62bec0SDavid C Somayajulu 
44546a62bec0SDavid C Somayajulu static uint32_t ql_rdmem(qla_host_t *ha,
44556a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdmem_t *mem_entry,
44566a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
44576a62bec0SDavid C Somayajulu 
44586a62bec0SDavid C Somayajulu static uint32_t ql_rdrom(qla_host_t *ha,
44596a62bec0SDavid C Somayajulu 			ql_minidump_entry_rdrom_t *romEntry,
44606a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
44616a62bec0SDavid C Somayajulu 
44626a62bec0SDavid C Somayajulu static uint32_t ql_rdmux(qla_host_t *ha,
44636a62bec0SDavid C Somayajulu 			ql_minidump_entry_mux_t *muxEntry,
44646a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
44656a62bec0SDavid C Somayajulu 
44666a62bec0SDavid C Somayajulu static uint32_t ql_rdmux2(qla_host_t *ha,
44676a62bec0SDavid C Somayajulu 			ql_minidump_entry_mux2_t *muxEntry,
44686a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
44696a62bec0SDavid C Somayajulu 
44706a62bec0SDavid C Somayajulu static uint32_t ql_rdqueue(qla_host_t *ha,
44716a62bec0SDavid C Somayajulu 			ql_minidump_entry_queue_t *queueEntry,
44726a62bec0SDavid C Somayajulu 			uint32_t *data_buff);
44736a62bec0SDavid C Somayajulu 
44746a62bec0SDavid C Somayajulu static uint32_t ql_cntrl(qla_host_t *ha,
44756a62bec0SDavid C Somayajulu 			ql_minidump_template_hdr_t *template_hdr,
44766a62bec0SDavid C Somayajulu 			ql_minidump_entry_cntrl_t *crbEntry);
44776a62bec0SDavid C Somayajulu 
44786a62bec0SDavid C Somayajulu 
44796a62bec0SDavid C Somayajulu static uint32_t
44806a62bec0SDavid C Somayajulu ql_minidump_size(qla_host_t *ha)
44816a62bec0SDavid C Somayajulu {
44826a62bec0SDavid C Somayajulu 	uint32_t i, k;
44836a62bec0SDavid C Somayajulu 	uint32_t size = 0;
44846a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *hdr;
44856a62bec0SDavid C Somayajulu 
44866a62bec0SDavid C Somayajulu 	hdr = (ql_minidump_template_hdr_t *)ha->hw.dma_buf.minidump.dma_b;
44876a62bec0SDavid C Somayajulu 
44886a62bec0SDavid C Somayajulu 	i = 0x2;
44896a62bec0SDavid C Somayajulu 
44906a62bec0SDavid C Somayajulu 	for (k = 1; k < QL_DBG_CAP_SIZE_ARRAY_LEN; k++) {
44916a62bec0SDavid C Somayajulu 		if (i & ha->hw.mdump_capture_mask)
44926a62bec0SDavid C Somayajulu 			size += hdr->capture_size_array[k];
44936a62bec0SDavid C Somayajulu 		i = i << 1;
44946a62bec0SDavid C Somayajulu 	}
44956a62bec0SDavid C Somayajulu 	return (size);
44966a62bec0SDavid C Somayajulu }
44976a62bec0SDavid C Somayajulu 
44986a62bec0SDavid C Somayajulu static void
44996a62bec0SDavid C Somayajulu ql_free_minidump_buffer(qla_host_t *ha)
45006a62bec0SDavid C Somayajulu {
45016a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_buffer != NULL) {
45026a62bec0SDavid C Somayajulu 		free(ha->hw.mdump_buffer, M_QLA83XXBUF);
45036a62bec0SDavid C Somayajulu 		ha->hw.mdump_buffer = NULL;
45046a62bec0SDavid C Somayajulu 		ha->hw.mdump_buffer_size = 0;
45056a62bec0SDavid C Somayajulu 	}
45066a62bec0SDavid C Somayajulu 	return;
45076a62bec0SDavid C Somayajulu }
45086a62bec0SDavid C Somayajulu 
4509f10a77bbSDavid C Somayajulu static int
45106a62bec0SDavid C Somayajulu ql_alloc_minidump_buffer(qla_host_t *ha)
45116a62bec0SDavid C Somayajulu {
45126a62bec0SDavid C Somayajulu 	ha->hw.mdump_buffer_size = ql_minidump_size(ha);
45136a62bec0SDavid C Somayajulu 
45146a62bec0SDavid C Somayajulu 	if (!ha->hw.mdump_buffer_size)
45156a62bec0SDavid C Somayajulu 		return (-1);
45166a62bec0SDavid C Somayajulu 
45176a62bec0SDavid C Somayajulu 	ha->hw.mdump_buffer = malloc(ha->hw.mdump_buffer_size, M_QLA83XXBUF,
45186a62bec0SDavid C Somayajulu 					M_NOWAIT);
45196a62bec0SDavid C Somayajulu 
45206a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_buffer == NULL)
45216a62bec0SDavid C Somayajulu 		return (-1);
45226a62bec0SDavid C Somayajulu 
45236a62bec0SDavid C Somayajulu 	return (0);
45246a62bec0SDavid C Somayajulu }
45256a62bec0SDavid C Somayajulu 
45266a62bec0SDavid C Somayajulu static void
45276a62bec0SDavid C Somayajulu ql_free_minidump_template_buffer(qla_host_t *ha)
45286a62bec0SDavid C Somayajulu {
45296a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_template != NULL) {
45306a62bec0SDavid C Somayajulu 		free(ha->hw.mdump_template, M_QLA83XXBUF);
45316a62bec0SDavid C Somayajulu 		ha->hw.mdump_template = NULL;
45326a62bec0SDavid C Somayajulu 		ha->hw.mdump_template_size = 0;
45336a62bec0SDavid C Somayajulu 	}
45346a62bec0SDavid C Somayajulu 	return;
45356a62bec0SDavid C Somayajulu }
45366a62bec0SDavid C Somayajulu 
45376a62bec0SDavid C Somayajulu static int
45386a62bec0SDavid C Somayajulu ql_alloc_minidump_template_buffer(qla_host_t *ha)
45396a62bec0SDavid C Somayajulu {
45406a62bec0SDavid C Somayajulu 	ha->hw.mdump_template_size = ha->hw.dma_buf.minidump.size;
45416a62bec0SDavid C Somayajulu 
45426a62bec0SDavid C Somayajulu 	ha->hw.mdump_template = malloc(ha->hw.mdump_template_size,
45436a62bec0SDavid C Somayajulu 					M_QLA83XXBUF, M_NOWAIT);
45446a62bec0SDavid C Somayajulu 
45456a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_template == NULL)
45466a62bec0SDavid C Somayajulu 		return (-1);
45476a62bec0SDavid C Somayajulu 
45486a62bec0SDavid C Somayajulu 	return (0);
45496a62bec0SDavid C Somayajulu }
45506a62bec0SDavid C Somayajulu 
45516a62bec0SDavid C Somayajulu static int
45526a62bec0SDavid C Somayajulu ql_alloc_minidump_buffers(qla_host_t *ha)
45536a62bec0SDavid C Somayajulu {
45546a62bec0SDavid C Somayajulu 	int ret;
45556a62bec0SDavid C Somayajulu 
45566a62bec0SDavid C Somayajulu 	ret = ql_alloc_minidump_template_buffer(ha);
45576a62bec0SDavid C Somayajulu 
45586a62bec0SDavid C Somayajulu 	if (ret)
45596a62bec0SDavid C Somayajulu 		return (ret);
45606a62bec0SDavid C Somayajulu 
45616a62bec0SDavid C Somayajulu 	ret = ql_alloc_minidump_buffer(ha);
45626a62bec0SDavid C Somayajulu 
45636a62bec0SDavid C Somayajulu 	if (ret)
45646a62bec0SDavid C Somayajulu 		ql_free_minidump_template_buffer(ha);
45656a62bec0SDavid C Somayajulu 
45666a62bec0SDavid C Somayajulu 	return (ret);
45676a62bec0SDavid C Somayajulu }
45686a62bec0SDavid C Somayajulu 
45696a62bec0SDavid C Somayajulu 
45706a62bec0SDavid C Somayajulu static uint32_t
45716a62bec0SDavid C Somayajulu ql_validate_minidump_checksum(qla_host_t *ha)
45726a62bec0SDavid C Somayajulu {
45736a62bec0SDavid C Somayajulu         uint64_t sum = 0;
45746a62bec0SDavid C Somayajulu 	int count;
45756a62bec0SDavid C Somayajulu 	uint32_t *template_buff;
45766a62bec0SDavid C Somayajulu 
45776a62bec0SDavid C Somayajulu 	count = ha->hw.dma_buf.minidump.size / sizeof (uint32_t);
45786a62bec0SDavid C Somayajulu 	template_buff = ha->hw.dma_buf.minidump.dma_b;
45796a62bec0SDavid C Somayajulu 
45806a62bec0SDavid C Somayajulu 	while (count-- > 0) {
45816a62bec0SDavid C Somayajulu 		sum += *template_buff++;
45826a62bec0SDavid C Somayajulu 	}
45836a62bec0SDavid C Somayajulu 
45846a62bec0SDavid C Somayajulu 	while (sum >> 32) {
45856a62bec0SDavid C Somayajulu 		sum = (sum & 0xFFFFFFFF) + (sum >> 32);
45866a62bec0SDavid C Somayajulu 	}
45876a62bec0SDavid C Somayajulu 
45886a62bec0SDavid C Somayajulu 	return (~sum);
45896a62bec0SDavid C Somayajulu }
45906a62bec0SDavid C Somayajulu 
45916a62bec0SDavid C Somayajulu int
45926a62bec0SDavid C Somayajulu ql_minidump_init(qla_host_t *ha)
4593f10a77bbSDavid C Somayajulu {
459435291c22SDavid C Somayajulu 	int		ret = 0;
4595f10a77bbSDavid C Somayajulu 	uint32_t	template_size = 0;
4596f10a77bbSDavid C Somayajulu 	device_t	dev = ha->pci_dev;
4597f10a77bbSDavid C Somayajulu 
4598f10a77bbSDavid C Somayajulu 	/*
4599f10a77bbSDavid C Somayajulu 	 * Get Minidump Template Size
4600f10a77bbSDavid C Somayajulu  	 */
4601f10a77bbSDavid C Somayajulu 	ret = qla_get_minidump_tmplt_size(ha, &template_size);
4602f10a77bbSDavid C Somayajulu 
4603f10a77bbSDavid C Somayajulu 	if (ret || (template_size == 0)) {
4604f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret,
4605f10a77bbSDavid C Somayajulu 			template_size);
4606f10a77bbSDavid C Somayajulu 		return (-1);
4607f10a77bbSDavid C Somayajulu 	}
4608f10a77bbSDavid C Somayajulu 
4609f10a77bbSDavid C Somayajulu 	/*
4610f10a77bbSDavid C Somayajulu 	 * Allocate Memory for Minidump Template
4611f10a77bbSDavid C Somayajulu 	 */
4612f10a77bbSDavid C Somayajulu 
4613f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.minidump.alignment = 8;
4614f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.minidump.size = template_size;
4615f10a77bbSDavid C Somayajulu 
461635291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
4617f10a77bbSDavid C Somayajulu 	if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) {
4618f10a77bbSDavid C Somayajulu 
4619f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: minidump dma alloc failed\n", __func__);
4620f10a77bbSDavid C Somayajulu 
4621f10a77bbSDavid C Somayajulu 		return (-1);
4622f10a77bbSDavid C Somayajulu 	}
4623f10a77bbSDavid C Somayajulu 	ha->hw.dma_buf.flags.minidump = 1;
4624f10a77bbSDavid C Somayajulu 
4625f10a77bbSDavid C Somayajulu 	/*
4626f10a77bbSDavid C Somayajulu 	 * Retrieve Minidump Template
4627f10a77bbSDavid C Somayajulu 	 */
46286a62bec0SDavid C Somayajulu 	ret = ql_get_minidump_template(ha);
462935291c22SDavid C Somayajulu #else
463035291c22SDavid C Somayajulu 	ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump;
46316a62bec0SDavid C Somayajulu 
463235291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
4633f10a77bbSDavid C Somayajulu 
46346a62bec0SDavid C Somayajulu 	if (ret == 0) {
46356a62bec0SDavid C Somayajulu 
46366a62bec0SDavid C Somayajulu 		ret = ql_validate_minidump_checksum(ha);
46376a62bec0SDavid C Somayajulu 
46386a62bec0SDavid C Somayajulu 		if (ret == 0) {
46396a62bec0SDavid C Somayajulu 
46406a62bec0SDavid C Somayajulu 			ret = ql_alloc_minidump_buffers(ha);
46416a62bec0SDavid C Somayajulu 
46426a62bec0SDavid C Somayajulu 			if (ret == 0)
4643f10a77bbSDavid C Somayajulu 		ha->hw.mdump_init = 1;
46446a62bec0SDavid C Somayajulu 			else
46456a62bec0SDavid C Somayajulu 				device_printf(dev,
46466a62bec0SDavid C Somayajulu 					"%s: ql_alloc_minidump_buffers"
46476a62bec0SDavid C Somayajulu 					" failed\n", __func__);
46486a62bec0SDavid C Somayajulu 		} else {
46496a62bec0SDavid C Somayajulu 			device_printf(dev, "%s: ql_validate_minidump_checksum"
46506a62bec0SDavid C Somayajulu 				" failed\n", __func__);
4651f10a77bbSDavid C Somayajulu 		}
46526a62bec0SDavid C Somayajulu 	} else {
46536a62bec0SDavid C Somayajulu 		device_printf(dev, "%s: ql_get_minidump_template failed\n",
46546a62bec0SDavid C Somayajulu 			 __func__);
46556a62bec0SDavid C Somayajulu 	}
46566a62bec0SDavid C Somayajulu 
46576a62bec0SDavid C Somayajulu 	if (ret)
46586a62bec0SDavid C Somayajulu 		ql_minidump_free(ha);
4659f10a77bbSDavid C Somayajulu 
4660f10a77bbSDavid C Somayajulu 	return (ret);
4661f10a77bbSDavid C Somayajulu }
4662f10a77bbSDavid C Somayajulu 
4663f10a77bbSDavid C Somayajulu static void
46646a62bec0SDavid C Somayajulu ql_minidump_free(qla_host_t *ha)
4665f10a77bbSDavid C Somayajulu {
4666f10a77bbSDavid C Somayajulu 	ha->hw.mdump_init = 0;
4667f10a77bbSDavid C Somayajulu 	if (ha->hw.dma_buf.flags.minidump) {
4668f10a77bbSDavid C Somayajulu 		ha->hw.dma_buf.flags.minidump = 0;
4669f10a77bbSDavid C Somayajulu 		ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump);
4670f10a77bbSDavid C Somayajulu 	}
46716a62bec0SDavid C Somayajulu 
46726a62bec0SDavid C Somayajulu 	ql_free_minidump_template_buffer(ha);
46736a62bec0SDavid C Somayajulu 	ql_free_minidump_buffer(ha);
46746a62bec0SDavid C Somayajulu 
4675f10a77bbSDavid C Somayajulu 	return;
4676f10a77bbSDavid C Somayajulu }
4677f10a77bbSDavid C Somayajulu 
4678f10a77bbSDavid C Somayajulu void
4679f10a77bbSDavid C Somayajulu ql_minidump(qla_host_t *ha)
4680f10a77bbSDavid C Somayajulu {
4681f10a77bbSDavid C Somayajulu 	if (!ha->hw.mdump_init)
4682f10a77bbSDavid C Somayajulu 		return;
4683f10a77bbSDavid C Somayajulu 
46846a62bec0SDavid C Somayajulu 	if (ha->hw.mdump_done)
4685f10a77bbSDavid C Somayajulu 		return;
4686b65c0c07SDavid C Somayajulu 	ha->hw.mdump_usec_ts = qla_get_usec_timestamp();
4687f10a77bbSDavid C Somayajulu 	ha->hw.mdump_start_seq_index = ql_stop_sequence(ha);
4688f10a77bbSDavid C Somayajulu 
46896a62bec0SDavid C Somayajulu 	bzero(ha->hw.mdump_buffer, ha->hw.mdump_buffer_size);
46906a62bec0SDavid C Somayajulu 	bzero(ha->hw.mdump_template, ha->hw.mdump_template_size);
46916a62bec0SDavid C Somayajulu 
46926a62bec0SDavid C Somayajulu 	bcopy(ha->hw.dma_buf.minidump.dma_b, ha->hw.mdump_template,
46936a62bec0SDavid C Somayajulu 		ha->hw.mdump_template_size);
46946a62bec0SDavid C Somayajulu 
46956a62bec0SDavid C Somayajulu 	ql_parse_template(ha);
46966a62bec0SDavid C Somayajulu 
4697f10a77bbSDavid C Somayajulu 	ql_start_sequence(ha, ha->hw.mdump_start_seq_index);
4698f10a77bbSDavid C Somayajulu 
46996a62bec0SDavid C Somayajulu 	ha->hw.mdump_done = 1;
47006a62bec0SDavid C Somayajulu 
4701f10a77bbSDavid C Somayajulu 	return;
4702f10a77bbSDavid C Somayajulu }
47036a62bec0SDavid C Somayajulu 
47046a62bec0SDavid C Somayajulu 
47056a62bec0SDavid C Somayajulu /*
47066a62bec0SDavid C Somayajulu  * helper routines
47076a62bec0SDavid C Somayajulu  */
47086a62bec0SDavid C Somayajulu static void
47096a62bec0SDavid C Somayajulu ql_entry_err_chk(ql_minidump_entry_t *entry, uint32_t esize)
47106a62bec0SDavid C Somayajulu {
47116a62bec0SDavid C Somayajulu 	if (esize != entry->hdr.entry_capture_size) {
47126a62bec0SDavid C Somayajulu 		entry->hdr.entry_capture_size = esize;
47136a62bec0SDavid C Somayajulu 		entry->hdr.driver_flags |= QL_DBG_SIZE_ERR_FLAG;
47146a62bec0SDavid C Somayajulu 	}
47156a62bec0SDavid C Somayajulu 	return;
47166a62bec0SDavid C Somayajulu }
47176a62bec0SDavid C Somayajulu 
47186a62bec0SDavid C Somayajulu 
47196a62bec0SDavid C Somayajulu static int
47206a62bec0SDavid C Somayajulu ql_parse_template(qla_host_t *ha)
47216a62bec0SDavid C Somayajulu {
47226a62bec0SDavid C Somayajulu 	uint32_t num_of_entries, buff_level, e_cnt, esize;
47236a62bec0SDavid C Somayajulu 	uint32_t end_cnt, rv = 0;
47246a62bec0SDavid C Somayajulu 	char *dump_buff, *dbuff;
47256a62bec0SDavid C Somayajulu 	int sane_start = 0, sane_end = 0;
47266a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *template_hdr;
47276a62bec0SDavid C Somayajulu 	ql_minidump_entry_t *entry;
47286a62bec0SDavid C Somayajulu 	uint32_t capture_mask;
47296a62bec0SDavid C Somayajulu 	uint32_t dump_size;
47306a62bec0SDavid C Somayajulu 
47316a62bec0SDavid C Somayajulu 	/* Setup parameters */
47326a62bec0SDavid C Somayajulu 	template_hdr = (ql_minidump_template_hdr_t *)ha->hw.mdump_template;
47336a62bec0SDavid C Somayajulu 
47346a62bec0SDavid C Somayajulu 	if (template_hdr->entry_type == TLHDR)
47356a62bec0SDavid C Somayajulu 		sane_start = 1;
47366a62bec0SDavid C Somayajulu 
47376a62bec0SDavid C Somayajulu 	dump_buff = (char *) ha->hw.mdump_buffer;
47386a62bec0SDavid C Somayajulu 
47396a62bec0SDavid C Somayajulu 	num_of_entries = template_hdr->num_of_entries;
47406a62bec0SDavid C Somayajulu 
47416a62bec0SDavid C Somayajulu 	entry = (ql_minidump_entry_t *) ((char *)template_hdr
47426a62bec0SDavid C Somayajulu 			+ template_hdr->first_entry_offset );
47436a62bec0SDavid C Somayajulu 
47446a62bec0SDavid C Somayajulu 	template_hdr->saved_state_array[QL_OCM0_ADDR_INDX] =
47456a62bec0SDavid C Somayajulu 		template_hdr->ocm_window_array[ha->pci_func];
47466a62bec0SDavid C Somayajulu 	template_hdr->saved_state_array[QL_PCIE_FUNC_INDX] = ha->pci_func;
47476a62bec0SDavid C Somayajulu 
47486a62bec0SDavid C Somayajulu 	capture_mask = ha->hw.mdump_capture_mask;
47496a62bec0SDavid C Somayajulu 	dump_size = ha->hw.mdump_buffer_size;
47506a62bec0SDavid C Somayajulu 
47516a62bec0SDavid C Somayajulu 	template_hdr->driver_capture_mask = capture_mask;
47526a62bec0SDavid C Somayajulu 
47536a62bec0SDavid C Somayajulu 	QL_DPRINT80(ha, (ha->pci_dev,
47546a62bec0SDavid C Somayajulu 		"%s: sane_start = %d num_of_entries = %d "
47556a62bec0SDavid C Somayajulu 		"capture_mask = 0x%x dump_size = %d \n",
47566a62bec0SDavid C Somayajulu 		__func__, sane_start, num_of_entries, capture_mask, dump_size));
47576a62bec0SDavid C Somayajulu 
47586a62bec0SDavid C Somayajulu 	for (buff_level = 0, e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
47596a62bec0SDavid C Somayajulu 
47606a62bec0SDavid C Somayajulu 		/*
47616a62bec0SDavid C Somayajulu 		 * If the capture_mask of the entry does not match capture mask
47626a62bec0SDavid C Somayajulu 		 * skip the entry after marking the driver_flags indicator.
47636a62bec0SDavid C Somayajulu 		 */
47646a62bec0SDavid C Somayajulu 
47656a62bec0SDavid C Somayajulu 		if (!(entry->hdr.entry_capture_mask & capture_mask)) {
47666a62bec0SDavid C Somayajulu 
47676a62bec0SDavid C Somayajulu 			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
47686a62bec0SDavid C Somayajulu 			entry = (ql_minidump_entry_t *) ((char *) entry
47696a62bec0SDavid C Somayajulu 					+ entry->hdr.entry_size);
47706a62bec0SDavid C Somayajulu 			continue;
47716a62bec0SDavid C Somayajulu 		}
47726a62bec0SDavid C Somayajulu 
47736a62bec0SDavid C Somayajulu 		/*
47746a62bec0SDavid C Somayajulu 		 * This is ONLY needed in implementations where
47756a62bec0SDavid C Somayajulu 		 * the capture buffer allocated is too small to capture
47766a62bec0SDavid C Somayajulu 		 * all of the required entries for a given capture mask.
47776a62bec0SDavid C Somayajulu 		 * We need to empty the buffer contents to a file
47786a62bec0SDavid C Somayajulu 		 * if possible, before processing the next entry
47796a62bec0SDavid C Somayajulu 		 * If the buff_full_flag is set, no further capture will happen
47806a62bec0SDavid C Somayajulu 		 * and all remaining non-control entries will be skipped.
47816a62bec0SDavid C Somayajulu 		 */
47826a62bec0SDavid C Somayajulu 		if (entry->hdr.entry_capture_size != 0) {
47836a62bec0SDavid C Somayajulu 			if ((buff_level + entry->hdr.entry_capture_size) >
47846a62bec0SDavid C Somayajulu 				dump_size) {
47856a62bec0SDavid C Somayajulu 				/*  Try to recover by emptying buffer to file */
47866a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
47876a62bec0SDavid C Somayajulu 				entry = (ql_minidump_entry_t *) ((char *) entry
47886a62bec0SDavid C Somayajulu 						+ entry->hdr.entry_size);
47896a62bec0SDavid C Somayajulu 				continue;
47906a62bec0SDavid C Somayajulu 			}
47916a62bec0SDavid C Somayajulu 		}
47926a62bec0SDavid C Somayajulu 
47936a62bec0SDavid C Somayajulu 		/*
47946a62bec0SDavid C Somayajulu 		 * Decode the entry type and process it accordingly
47956a62bec0SDavid C Somayajulu 		 */
47966a62bec0SDavid C Somayajulu 
47976a62bec0SDavid C Somayajulu 		switch (entry->hdr.entry_type) {
47986a62bec0SDavid C Somayajulu 		case RDNOP:
47996a62bec0SDavid C Somayajulu 			break;
48006a62bec0SDavid C Somayajulu 
48016a62bec0SDavid C Somayajulu 		case RDEND:
48026a62bec0SDavid C Somayajulu 			if (sane_end == 0) {
48036a62bec0SDavid C Somayajulu 				end_cnt = e_cnt;
48046a62bec0SDavid C Somayajulu 			}
48056a62bec0SDavid C Somayajulu 			sane_end++;
48066a62bec0SDavid C Somayajulu 			break;
48076a62bec0SDavid C Somayajulu 
48086a62bec0SDavid C Somayajulu 		case RDCRB:
48096a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
48106a62bec0SDavid C Somayajulu 			esize = ql_rdcrb(ha, (void *)entry, (void *)dbuff);
48116a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
48126a62bec0SDavid C Somayajulu 			buff_level += esize;
48136a62bec0SDavid C Somayajulu 			break;
48146a62bec0SDavid C Somayajulu 
48156a62bec0SDavid C Somayajulu                 case POLLRD:
48166a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
48176a62bec0SDavid C Somayajulu                         esize = ql_pollrd(ha, (void *)entry, (void *)dbuff);
48186a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
48196a62bec0SDavid C Somayajulu                         buff_level += esize;
48206a62bec0SDavid C Somayajulu                         break;
48216a62bec0SDavid C Somayajulu 
48226a62bec0SDavid C Somayajulu                 case POLLRDMWR:
48236a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
48246a62bec0SDavid C Somayajulu                         esize = ql_pollrd_modify_write(ha, (void *)entry,
48256a62bec0SDavid C Somayajulu 					(void *)dbuff);
48266a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
48276a62bec0SDavid C Somayajulu                         buff_level += esize;
48286a62bec0SDavid C Somayajulu                         break;
48296a62bec0SDavid C Somayajulu 
48306a62bec0SDavid C Somayajulu 		case L2ITG:
48316a62bec0SDavid C Somayajulu 		case L2DTG:
48326a62bec0SDavid C Somayajulu 		case L2DAT:
48336a62bec0SDavid C Somayajulu 		case L2INS:
48346a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
48356a62bec0SDavid C Somayajulu 			esize = ql_L2Cache(ha, (void *)entry, (void *)dbuff);
48366a62bec0SDavid C Somayajulu 			if (esize == -1) {
48376a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
48386a62bec0SDavid C Somayajulu 			} else {
48396a62bec0SDavid C Somayajulu 				ql_entry_err_chk(entry, esize);
48406a62bec0SDavid C Somayajulu 				buff_level += esize;
48416a62bec0SDavid C Somayajulu 			}
48426a62bec0SDavid C Somayajulu 			break;
48436a62bec0SDavid C Somayajulu 
48446a62bec0SDavid C Somayajulu 		case L1DAT:
48456a62bec0SDavid C Somayajulu 		case L1INS:
48466a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
48476a62bec0SDavid C Somayajulu 			esize = ql_L1Cache(ha, (void *)entry, (void *)dbuff);
48486a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
48496a62bec0SDavid C Somayajulu 			buff_level += esize;
48506a62bec0SDavid C Somayajulu 			break;
48516a62bec0SDavid C Somayajulu 
48526a62bec0SDavid C Somayajulu 		case RDOCM:
48536a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
48546a62bec0SDavid C Somayajulu 			esize = ql_rdocm(ha, (void *)entry, (void *)dbuff);
48556a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
48566a62bec0SDavid C Somayajulu 			buff_level += esize;
48576a62bec0SDavid C Somayajulu 			break;
48586a62bec0SDavid C Somayajulu 
48596a62bec0SDavid C Somayajulu 		case RDMEM:
48606a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
48616a62bec0SDavid C Somayajulu 			esize = ql_rdmem(ha, (void *)entry, (void *)dbuff);
48626a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
48636a62bec0SDavid C Somayajulu 			buff_level += esize;
48646a62bec0SDavid C Somayajulu 			break;
48656a62bec0SDavid C Somayajulu 
48666a62bec0SDavid C Somayajulu 		case BOARD:
48676a62bec0SDavid C Somayajulu 		case RDROM:
48686a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
48696a62bec0SDavid C Somayajulu 			esize = ql_rdrom(ha, (void *)entry, (void *)dbuff);
48706a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
48716a62bec0SDavid C Somayajulu 			buff_level += esize;
48726a62bec0SDavid C Somayajulu 			break;
48736a62bec0SDavid C Somayajulu 
48746a62bec0SDavid C Somayajulu 		case RDMUX:
48756a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
48766a62bec0SDavid C Somayajulu 			esize = ql_rdmux(ha, (void *)entry, (void *)dbuff);
48776a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
48786a62bec0SDavid C Somayajulu 			buff_level += esize;
48796a62bec0SDavid C Somayajulu 			break;
48806a62bec0SDavid C Somayajulu 
48816a62bec0SDavid C Somayajulu                 case RDMUX2:
48826a62bec0SDavid C Somayajulu                         dbuff = dump_buff + buff_level;
48836a62bec0SDavid C Somayajulu                         esize = ql_rdmux2(ha, (void *)entry, (void *)dbuff);
48846a62bec0SDavid C Somayajulu                         ql_entry_err_chk(entry, esize);
48856a62bec0SDavid C Somayajulu                         buff_level += esize;
48866a62bec0SDavid C Somayajulu                         break;
48876a62bec0SDavid C Somayajulu 
48886a62bec0SDavid C Somayajulu 		case QUEUE:
48896a62bec0SDavid C Somayajulu 			dbuff = dump_buff + buff_level;
48906a62bec0SDavid C Somayajulu 			esize = ql_rdqueue(ha, (void *)entry, (void *)dbuff);
48916a62bec0SDavid C Somayajulu 			ql_entry_err_chk(entry, esize);
48926a62bec0SDavid C Somayajulu 			buff_level += esize;
48936a62bec0SDavid C Somayajulu 			break;
48946a62bec0SDavid C Somayajulu 
48956a62bec0SDavid C Somayajulu 		case CNTRL:
48966a62bec0SDavid C Somayajulu 			if ((rv = ql_cntrl(ha, template_hdr, (void *)entry))) {
48976a62bec0SDavid C Somayajulu 				entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
48986a62bec0SDavid C Somayajulu 			}
48996a62bec0SDavid C Somayajulu 			break;
49006a62bec0SDavid C Somayajulu 		default:
49016a62bec0SDavid C Somayajulu 			entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
49026a62bec0SDavid C Somayajulu 			break;
49036a62bec0SDavid C Somayajulu 		}
49046a62bec0SDavid C Somayajulu 		/*  next entry in the template */
49056a62bec0SDavid C Somayajulu 		entry = (ql_minidump_entry_t *) ((char *) entry
49066a62bec0SDavid C Somayajulu 						+ entry->hdr.entry_size);
49076a62bec0SDavid C Somayajulu 	}
49086a62bec0SDavid C Somayajulu 
49096a62bec0SDavid C Somayajulu 	if (!sane_start || (sane_end > 1)) {
49106a62bec0SDavid C Somayajulu 		device_printf(ha->pci_dev,
49116a62bec0SDavid C Somayajulu 			"\n%s: Template configuration error. Check Template\n",
49126a62bec0SDavid C Somayajulu 			__func__);
49136a62bec0SDavid C Somayajulu 	}
49146a62bec0SDavid C Somayajulu 
49156a62bec0SDavid C Somayajulu 	QL_DPRINT80(ha, (ha->pci_dev, "%s: Minidump num of entries = %d\n",
49166a62bec0SDavid C Somayajulu 		__func__, template_hdr->num_of_entries));
49176a62bec0SDavid C Somayajulu 
49186a62bec0SDavid C Somayajulu 	return 0;
49196a62bec0SDavid C Somayajulu }
49206a62bec0SDavid C Somayajulu 
49216a62bec0SDavid C Somayajulu /*
49226a62bec0SDavid C Somayajulu  * Read CRB operation.
49236a62bec0SDavid C Somayajulu  */
49246a62bec0SDavid C Somayajulu static uint32_t
49256a62bec0SDavid C Somayajulu ql_rdcrb(qla_host_t *ha, ql_minidump_entry_rdcrb_t * crb_entry,
49266a62bec0SDavid C Somayajulu 	uint32_t * data_buff)
49276a62bec0SDavid C Somayajulu {
49286a62bec0SDavid C Somayajulu 	int loop_cnt;
49296a62bec0SDavid C Somayajulu 	int ret;
49306a62bec0SDavid C Somayajulu 	uint32_t op_count, addr, stride, value = 0;
49316a62bec0SDavid C Somayajulu 
49326a62bec0SDavid C Somayajulu 	addr = crb_entry->addr;
49336a62bec0SDavid C Somayajulu 	op_count = crb_entry->op_count;
49346a62bec0SDavid C Somayajulu 	stride = crb_entry->addr_stride;
49356a62bec0SDavid C Somayajulu 
49366a62bec0SDavid C Somayajulu 	for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
49376a62bec0SDavid C Somayajulu 
49386a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr, &value, 1);
49396a62bec0SDavid C Somayajulu 
49406a62bec0SDavid C Somayajulu 		if (ret)
49416a62bec0SDavid C Somayajulu 			return (0);
49426a62bec0SDavid C Somayajulu 
49436a62bec0SDavid C Somayajulu 		*data_buff++ = addr;
49446a62bec0SDavid C Somayajulu 		*data_buff++ = value;
49456a62bec0SDavid C Somayajulu 		addr = addr + stride;
49466a62bec0SDavid C Somayajulu 	}
49476a62bec0SDavid C Somayajulu 
49486a62bec0SDavid C Somayajulu 	/*
49496a62bec0SDavid C Somayajulu 	 * for testing purpose we return amount of data written
49506a62bec0SDavid C Somayajulu 	 */
49516a62bec0SDavid C Somayajulu 	return (op_count * (2 * sizeof(uint32_t)));
49526a62bec0SDavid C Somayajulu }
49536a62bec0SDavid C Somayajulu 
49546a62bec0SDavid C Somayajulu /*
49556a62bec0SDavid C Somayajulu  * Handle L2 Cache.
49566a62bec0SDavid C Somayajulu  */
49576a62bec0SDavid C Somayajulu 
49586a62bec0SDavid C Somayajulu static uint32_t
49596a62bec0SDavid C Somayajulu ql_L2Cache(qla_host_t *ha, ql_minidump_entry_cache_t *cacheEntry,
49606a62bec0SDavid C Somayajulu 	uint32_t * data_buff)
49616a62bec0SDavid C Somayajulu {
49626a62bec0SDavid C Somayajulu 	int i, k;
49636a62bec0SDavid C Somayajulu 	int loop_cnt;
49646a62bec0SDavid C Somayajulu 	int ret;
49656a62bec0SDavid C Somayajulu 
49666a62bec0SDavid C Somayajulu 	uint32_t read_value;
49676a62bec0SDavid C Somayajulu 	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr, cntl_value_w;
49686a62bec0SDavid C Somayajulu 	uint32_t tag_value, read_cnt;
49696a62bec0SDavid C Somayajulu 	volatile uint8_t cntl_value_r;
49706a62bec0SDavid C Somayajulu 	long timeout;
49716a62bec0SDavid C Somayajulu 	uint32_t data;
49726a62bec0SDavid C Somayajulu 
49736a62bec0SDavid C Somayajulu 	loop_cnt = cacheEntry->op_count;
49746a62bec0SDavid C Somayajulu 
49756a62bec0SDavid C Somayajulu 	read_addr = cacheEntry->read_addr;
49766a62bec0SDavid C Somayajulu 	cntrl_addr = cacheEntry->control_addr;
49776a62bec0SDavid C Somayajulu 	cntl_value_w = (uint32_t) cacheEntry->write_value;
49786a62bec0SDavid C Somayajulu 
49796a62bec0SDavid C Somayajulu 	tag_reg_addr = cacheEntry->tag_reg_addr;
49806a62bec0SDavid C Somayajulu 
49816a62bec0SDavid C Somayajulu 	tag_value = cacheEntry->init_tag_value;
49826a62bec0SDavid C Somayajulu 	read_cnt = cacheEntry->read_addr_cnt;
49836a62bec0SDavid C Somayajulu 
49846a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
49856a62bec0SDavid C Somayajulu 
49866a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
49876a62bec0SDavid C Somayajulu 		if (ret)
49886a62bec0SDavid C Somayajulu 			return (0);
49896a62bec0SDavid C Somayajulu 
49906a62bec0SDavid C Somayajulu 		if (cacheEntry->write_value != 0) {
49916a62bec0SDavid C Somayajulu 
49926a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, cntrl_addr,
49936a62bec0SDavid C Somayajulu 					&cntl_value_w, 0);
49946a62bec0SDavid C Somayajulu 			if (ret)
49956a62bec0SDavid C Somayajulu 				return (0);
49966a62bec0SDavid C Somayajulu 		}
49976a62bec0SDavid C Somayajulu 
49986a62bec0SDavid C Somayajulu 		if (cacheEntry->poll_mask != 0) {
49996a62bec0SDavid C Somayajulu 
50006a62bec0SDavid C Somayajulu 			timeout = cacheEntry->poll_wait;
50016a62bec0SDavid C Somayajulu 
50026a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, cntrl_addr, &data, 1);
50036a62bec0SDavid C Somayajulu 			if (ret)
50046a62bec0SDavid C Somayajulu 				return (0);
50056a62bec0SDavid C Somayajulu 
50066a62bec0SDavid C Somayajulu 			cntl_value_r = (uint8_t)data;
50076a62bec0SDavid C Somayajulu 
50086a62bec0SDavid C Somayajulu 			while ((cntl_value_r & cacheEntry->poll_mask) != 0) {
50096a62bec0SDavid C Somayajulu 
50106a62bec0SDavid C Somayajulu 				if (timeout) {
50116a62bec0SDavid C Somayajulu 					qla_mdelay(__func__, 1);
50126a62bec0SDavid C Somayajulu 					timeout--;
50136a62bec0SDavid C Somayajulu 				} else
50146a62bec0SDavid C Somayajulu 					break;
50156a62bec0SDavid C Somayajulu 
50166a62bec0SDavid C Somayajulu 				ret = ql_rdwr_indreg32(ha, cntrl_addr,
50176a62bec0SDavid C Somayajulu 						&data, 1);
50186a62bec0SDavid C Somayajulu 				if (ret)
50196a62bec0SDavid C Somayajulu 					return (0);
50206a62bec0SDavid C Somayajulu 
50216a62bec0SDavid C Somayajulu 				cntl_value_r = (uint8_t)data;
50226a62bec0SDavid C Somayajulu 			}
50236a62bec0SDavid C Somayajulu 			if (!timeout) {
50246a62bec0SDavid C Somayajulu 				/* Report timeout error.
50256a62bec0SDavid C Somayajulu 				 * core dump capture failed
50266a62bec0SDavid C Somayajulu 				 * Skip remaining entries.
50276a62bec0SDavid C Somayajulu 				 * Write buffer out to file
50286a62bec0SDavid C Somayajulu 				 * Use driver specific fields in template header
50296a62bec0SDavid C Somayajulu 				 * to report this error.
50306a62bec0SDavid C Somayajulu 				 */
50316a62bec0SDavid C Somayajulu 				return (-1);
50326a62bec0SDavid C Somayajulu 			}
50336a62bec0SDavid C Somayajulu 		}
50346a62bec0SDavid C Somayajulu 
50356a62bec0SDavid C Somayajulu 		addr = read_addr;
50366a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
50376a62bec0SDavid C Somayajulu 
50386a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
50396a62bec0SDavid C Somayajulu 			if (ret)
50406a62bec0SDavid C Somayajulu 				return (0);
50416a62bec0SDavid C Somayajulu 
50426a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
50436a62bec0SDavid C Somayajulu 			addr += cacheEntry->read_addr_stride;
50446a62bec0SDavid C Somayajulu 		}
50456a62bec0SDavid C Somayajulu 
50466a62bec0SDavid C Somayajulu 		tag_value += cacheEntry->tag_value_stride;
50476a62bec0SDavid C Somayajulu 	}
50486a62bec0SDavid C Somayajulu 
50496a62bec0SDavid C Somayajulu 	return (read_cnt * loop_cnt * sizeof(uint32_t));
50506a62bec0SDavid C Somayajulu }
50516a62bec0SDavid C Somayajulu 
50526a62bec0SDavid C Somayajulu /*
50536a62bec0SDavid C Somayajulu  * Handle L1 Cache.
50546a62bec0SDavid C Somayajulu  */
50556a62bec0SDavid C Somayajulu 
50566a62bec0SDavid C Somayajulu static uint32_t
50576a62bec0SDavid C Somayajulu ql_L1Cache(qla_host_t *ha,
50586a62bec0SDavid C Somayajulu 	ql_minidump_entry_cache_t *cacheEntry,
50596a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
50606a62bec0SDavid C Somayajulu {
50616a62bec0SDavid C Somayajulu 	int ret;
50626a62bec0SDavid C Somayajulu 	int i, k;
50636a62bec0SDavid C Somayajulu 	int loop_cnt;
50646a62bec0SDavid C Somayajulu 
50656a62bec0SDavid C Somayajulu 	uint32_t read_value;
50666a62bec0SDavid C Somayajulu 	uint32_t addr, read_addr, cntrl_addr, tag_reg_addr;
50676a62bec0SDavid C Somayajulu 	uint32_t tag_value, read_cnt;
50686a62bec0SDavid C Somayajulu 	uint32_t cntl_value_w;
50696a62bec0SDavid C Somayajulu 
50706a62bec0SDavid C Somayajulu 	loop_cnt = cacheEntry->op_count;
50716a62bec0SDavid C Somayajulu 
50726a62bec0SDavid C Somayajulu 	read_addr = cacheEntry->read_addr;
50736a62bec0SDavid C Somayajulu 	cntrl_addr = cacheEntry->control_addr;
50746a62bec0SDavid C Somayajulu 	cntl_value_w = (uint32_t) cacheEntry->write_value;
50756a62bec0SDavid C Somayajulu 
50766a62bec0SDavid C Somayajulu 	tag_reg_addr = cacheEntry->tag_reg_addr;
50776a62bec0SDavid C Somayajulu 
50786a62bec0SDavid C Somayajulu 	tag_value = cacheEntry->init_tag_value;
50796a62bec0SDavid C Somayajulu 	read_cnt = cacheEntry->read_addr_cnt;
50806a62bec0SDavid C Somayajulu 
50816a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
50826a62bec0SDavid C Somayajulu 
50836a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
50846a62bec0SDavid C Somayajulu 		if (ret)
50856a62bec0SDavid C Somayajulu 			return (0);
50866a62bec0SDavid C Somayajulu 
50876a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, cntrl_addr, &cntl_value_w, 0);
50886a62bec0SDavid C Somayajulu 		if (ret)
50896a62bec0SDavid C Somayajulu 			return (0);
50906a62bec0SDavid C Somayajulu 
50916a62bec0SDavid C Somayajulu 		addr = read_addr;
50926a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
50936a62bec0SDavid C Somayajulu 
50946a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
50956a62bec0SDavid C Somayajulu 			if (ret)
50966a62bec0SDavid C Somayajulu 				return (0);
50976a62bec0SDavid C Somayajulu 
50986a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
50996a62bec0SDavid C Somayajulu 			addr += cacheEntry->read_addr_stride;
51006a62bec0SDavid C Somayajulu 		}
51016a62bec0SDavid C Somayajulu 
51026a62bec0SDavid C Somayajulu 		tag_value += cacheEntry->tag_value_stride;
51036a62bec0SDavid C Somayajulu 	}
51046a62bec0SDavid C Somayajulu 
51056a62bec0SDavid C Somayajulu 	return (read_cnt * loop_cnt * sizeof(uint32_t));
51066a62bec0SDavid C Somayajulu }
51076a62bec0SDavid C Somayajulu 
51086a62bec0SDavid C Somayajulu /*
51096a62bec0SDavid C Somayajulu  * Reading OCM memory
51106a62bec0SDavid C Somayajulu  */
51116a62bec0SDavid C Somayajulu 
51126a62bec0SDavid C Somayajulu static uint32_t
51136a62bec0SDavid C Somayajulu ql_rdocm(qla_host_t *ha,
51146a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdocm_t *ocmEntry,
51156a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
51166a62bec0SDavid C Somayajulu {
51176a62bec0SDavid C Somayajulu 	int i, loop_cnt;
51186a62bec0SDavid C Somayajulu 	volatile uint32_t addr;
51196a62bec0SDavid C Somayajulu 	volatile uint32_t value;
51206a62bec0SDavid C Somayajulu 
51216a62bec0SDavid C Somayajulu 	addr = ocmEntry->read_addr;
51226a62bec0SDavid C Somayajulu 	loop_cnt = ocmEntry->op_count;
51236a62bec0SDavid C Somayajulu 
51246a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
51256a62bec0SDavid C Somayajulu 		value = READ_REG32(ha, addr);
51266a62bec0SDavid C Somayajulu 		*data_buff++ = value;
51276a62bec0SDavid C Somayajulu 		addr += ocmEntry->read_addr_stride;
51286a62bec0SDavid C Somayajulu 	}
51296a62bec0SDavid C Somayajulu 	return (loop_cnt * sizeof(value));
51306a62bec0SDavid C Somayajulu }
51316a62bec0SDavid C Somayajulu 
51326a62bec0SDavid C Somayajulu /*
51336a62bec0SDavid C Somayajulu  * Read memory
51346a62bec0SDavid C Somayajulu  */
51356a62bec0SDavid C Somayajulu 
51366a62bec0SDavid C Somayajulu static uint32_t
51376a62bec0SDavid C Somayajulu ql_rdmem(qla_host_t *ha,
51386a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdmem_t *mem_entry,
51396a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
51406a62bec0SDavid C Somayajulu {
51416a62bec0SDavid C Somayajulu 	int ret;
51426a62bec0SDavid C Somayajulu         int i, loop_cnt;
51436a62bec0SDavid C Somayajulu         volatile uint32_t addr;
51446a62bec0SDavid C Somayajulu 	q80_offchip_mem_val_t val;
51456a62bec0SDavid C Somayajulu 
51466a62bec0SDavid C Somayajulu         addr = mem_entry->read_addr;
51476a62bec0SDavid C Somayajulu 
51486a62bec0SDavid C Somayajulu 	/* size in bytes / 16 */
51496a62bec0SDavid C Somayajulu         loop_cnt = mem_entry->read_data_size / (sizeof(uint32_t) * 4);
51506a62bec0SDavid C Somayajulu 
51516a62bec0SDavid C Somayajulu         for (i = 0; i < loop_cnt; i++) {
51526a62bec0SDavid C Somayajulu 
51536a62bec0SDavid C Somayajulu 		ret = ql_rdwr_offchip_mem(ha, (addr & 0x0ffffffff), &val, 1);
51546a62bec0SDavid C Somayajulu 		if (ret)
51556a62bec0SDavid C Somayajulu 			return (0);
51566a62bec0SDavid C Somayajulu 
51576a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_lo;
51586a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_hi;
51596a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_ulo;
51606a62bec0SDavid C Somayajulu                 *data_buff++ = val.data_uhi;
51616a62bec0SDavid C Somayajulu 
51626a62bec0SDavid C Somayajulu                 addr += (sizeof(uint32_t) * 4);
51636a62bec0SDavid C Somayajulu         }
51646a62bec0SDavid C Somayajulu 
51656a62bec0SDavid C Somayajulu         return (loop_cnt * (sizeof(uint32_t) * 4));
51666a62bec0SDavid C Somayajulu }
51676a62bec0SDavid C Somayajulu 
51686a62bec0SDavid C Somayajulu /*
51696a62bec0SDavid C Somayajulu  * Read Rom
51706a62bec0SDavid C Somayajulu  */
51716a62bec0SDavid C Somayajulu 
51726a62bec0SDavid C Somayajulu static uint32_t
51736a62bec0SDavid C Somayajulu ql_rdrom(qla_host_t *ha,
51746a62bec0SDavid C Somayajulu 	ql_minidump_entry_rdrom_t *romEntry,
51756a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
51766a62bec0SDavid C Somayajulu {
51776a62bec0SDavid C Somayajulu 	int ret;
51786a62bec0SDavid C Somayajulu 	int i, loop_cnt;
51796a62bec0SDavid C Somayajulu 	uint32_t addr;
51806a62bec0SDavid C Somayajulu 	uint32_t value;
51816a62bec0SDavid C Somayajulu 
51826a62bec0SDavid C Somayajulu 	addr = romEntry->read_addr;
51836a62bec0SDavid C Somayajulu 	loop_cnt = romEntry->read_data_size; /* This is size in bytes */
51846a62bec0SDavid C Somayajulu 	loop_cnt /= sizeof(value);
51856a62bec0SDavid C Somayajulu 
51866a62bec0SDavid C Somayajulu 	for (i = 0; i < loop_cnt; i++) {
51876a62bec0SDavid C Somayajulu 
51886a62bec0SDavid C Somayajulu 		ret = ql_rd_flash32(ha, addr, &value);
51896a62bec0SDavid C Somayajulu 		if (ret)
51906a62bec0SDavid C Somayajulu 			return (0);
51916a62bec0SDavid C Somayajulu 
51926a62bec0SDavid C Somayajulu 		*data_buff++ = value;
51936a62bec0SDavid C Somayajulu 		addr += sizeof(value);
51946a62bec0SDavid C Somayajulu 	}
51956a62bec0SDavid C Somayajulu 
51966a62bec0SDavid C Somayajulu 	return (loop_cnt * sizeof(value));
51976a62bec0SDavid C Somayajulu }
51986a62bec0SDavid C Somayajulu 
51996a62bec0SDavid C Somayajulu /*
52006a62bec0SDavid C Somayajulu  * Read MUX data
52016a62bec0SDavid C Somayajulu  */
52026a62bec0SDavid C Somayajulu 
52036a62bec0SDavid C Somayajulu static uint32_t
52046a62bec0SDavid C Somayajulu ql_rdmux(qla_host_t *ha,
52056a62bec0SDavid C Somayajulu 	ql_minidump_entry_mux_t *muxEntry,
52066a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
52076a62bec0SDavid C Somayajulu {
52086a62bec0SDavid C Somayajulu 	int ret;
52096a62bec0SDavid C Somayajulu 	int loop_cnt;
52106a62bec0SDavid C Somayajulu 	uint32_t read_value, sel_value;
52116a62bec0SDavid C Somayajulu 	uint32_t read_addr, select_addr;
52126a62bec0SDavid C Somayajulu 
52136a62bec0SDavid C Somayajulu 	select_addr = muxEntry->select_addr;
52146a62bec0SDavid C Somayajulu 	sel_value = muxEntry->select_value;
52156a62bec0SDavid C Somayajulu 	read_addr = muxEntry->read_addr;
52166a62bec0SDavid C Somayajulu 
52176a62bec0SDavid C Somayajulu 	for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
52186a62bec0SDavid C Somayajulu 
52196a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr, &sel_value, 0);
52206a62bec0SDavid C Somayajulu 		if (ret)
52216a62bec0SDavid C Somayajulu 			return (0);
52226a62bec0SDavid C Somayajulu 
52236a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
52246a62bec0SDavid C Somayajulu 		if (ret)
52256a62bec0SDavid C Somayajulu 			return (0);
52266a62bec0SDavid C Somayajulu 
52276a62bec0SDavid C Somayajulu 		*data_buff++ = sel_value;
52286a62bec0SDavid C Somayajulu 		*data_buff++ = read_value;
52296a62bec0SDavid C Somayajulu 
52306a62bec0SDavid C Somayajulu 		sel_value += muxEntry->select_value_stride;
52316a62bec0SDavid C Somayajulu 	}
52326a62bec0SDavid C Somayajulu 
52336a62bec0SDavid C Somayajulu 	return (loop_cnt * (2 * sizeof(uint32_t)));
52346a62bec0SDavid C Somayajulu }
52356a62bec0SDavid C Somayajulu 
52366a62bec0SDavid C Somayajulu static uint32_t
52376a62bec0SDavid C Somayajulu ql_rdmux2(qla_host_t *ha,
52386a62bec0SDavid C Somayajulu 	ql_minidump_entry_mux2_t *muxEntry,
52396a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
52406a62bec0SDavid C Somayajulu {
52416a62bec0SDavid C Somayajulu 	int ret;
52426a62bec0SDavid C Somayajulu         int loop_cnt;
52436a62bec0SDavid C Somayajulu 
52446a62bec0SDavid C Somayajulu         uint32_t select_addr_1, select_addr_2;
52456a62bec0SDavid C Somayajulu         uint32_t select_value_1, select_value_2;
52466a62bec0SDavid C Somayajulu         uint32_t select_value_count, select_value_mask;
52476a62bec0SDavid C Somayajulu         uint32_t read_addr, read_value;
52486a62bec0SDavid C Somayajulu 
52496a62bec0SDavid C Somayajulu         select_addr_1 = muxEntry->select_addr_1;
52506a62bec0SDavid C Somayajulu         select_addr_2 = muxEntry->select_addr_2;
52516a62bec0SDavid C Somayajulu         select_value_1 = muxEntry->select_value_1;
52526a62bec0SDavid C Somayajulu         select_value_2 = muxEntry->select_value_2;
52536a62bec0SDavid C Somayajulu         select_value_count = muxEntry->select_value_count;
52546a62bec0SDavid C Somayajulu         select_value_mask  = muxEntry->select_value_mask;
52556a62bec0SDavid C Somayajulu 
52566a62bec0SDavid C Somayajulu         read_addr = muxEntry->read_addr;
52576a62bec0SDavid C Somayajulu 
52586a62bec0SDavid C Somayajulu         for (loop_cnt = 0; loop_cnt < muxEntry->select_value_count;
52596a62bec0SDavid C Somayajulu 		loop_cnt++) {
52606a62bec0SDavid C Somayajulu 
52616a62bec0SDavid C Somayajulu                 uint32_t temp_sel_val;
52626a62bec0SDavid C Somayajulu 
52636a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_1, 0);
52646a62bec0SDavid C Somayajulu 		if (ret)
52656a62bec0SDavid C Somayajulu 			return (0);
52666a62bec0SDavid C Somayajulu 
52676a62bec0SDavid C Somayajulu                 temp_sel_val = select_value_1 & select_value_mask;
52686a62bec0SDavid C Somayajulu 
52696a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
52706a62bec0SDavid C Somayajulu 		if (ret)
52716a62bec0SDavid C Somayajulu 			return (0);
52726a62bec0SDavid C Somayajulu 
52736a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
52746a62bec0SDavid C Somayajulu 		if (ret)
52756a62bec0SDavid C Somayajulu 			return (0);
52766a62bec0SDavid C Somayajulu 
52776a62bec0SDavid C Somayajulu                 *data_buff++ = temp_sel_val;
52786a62bec0SDavid C Somayajulu                 *data_buff++ = read_value;
52796a62bec0SDavid C Somayajulu 
52806a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_2, 0);
52816a62bec0SDavid C Somayajulu 		if (ret)
52826a62bec0SDavid C Somayajulu 			return (0);
52836a62bec0SDavid C Somayajulu 
52846a62bec0SDavid C Somayajulu                 temp_sel_val = select_value_2 & select_value_mask;
52856a62bec0SDavid C Somayajulu 
52866a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
52876a62bec0SDavid C Somayajulu 		if (ret)
52886a62bec0SDavid C Somayajulu 			return (0);
52896a62bec0SDavid C Somayajulu 
52906a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
52916a62bec0SDavid C Somayajulu 		if (ret)
52926a62bec0SDavid C Somayajulu 			return (0);
52936a62bec0SDavid C Somayajulu 
52946a62bec0SDavid C Somayajulu                 *data_buff++ = temp_sel_val;
52956a62bec0SDavid C Somayajulu                 *data_buff++ = read_value;
52966a62bec0SDavid C Somayajulu 
52976a62bec0SDavid C Somayajulu                 select_value_1 += muxEntry->select_value_stride;
52986a62bec0SDavid C Somayajulu                 select_value_2 += muxEntry->select_value_stride;
52996a62bec0SDavid C Somayajulu         }
53006a62bec0SDavid C Somayajulu 
53016a62bec0SDavid C Somayajulu         return (loop_cnt * (4 * sizeof(uint32_t)));
53026a62bec0SDavid C Somayajulu }
53036a62bec0SDavid C Somayajulu 
53046a62bec0SDavid C Somayajulu /*
53056a62bec0SDavid C Somayajulu  * Handling Queue State Reads.
53066a62bec0SDavid C Somayajulu  */
53076a62bec0SDavid C Somayajulu 
53086a62bec0SDavid C Somayajulu static uint32_t
53096a62bec0SDavid C Somayajulu ql_rdqueue(qla_host_t *ha,
53106a62bec0SDavid C Somayajulu 	ql_minidump_entry_queue_t *queueEntry,
53116a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
53126a62bec0SDavid C Somayajulu {
53136a62bec0SDavid C Somayajulu 	int ret;
53146a62bec0SDavid C Somayajulu 	int loop_cnt, k;
53156a62bec0SDavid C Somayajulu 	uint32_t read_value;
53166a62bec0SDavid C Somayajulu 	uint32_t read_addr, read_stride, select_addr;
53176a62bec0SDavid C Somayajulu 	uint32_t queue_id, read_cnt;
53186a62bec0SDavid C Somayajulu 
53196a62bec0SDavid C Somayajulu 	read_cnt = queueEntry->read_addr_cnt;
53206a62bec0SDavid C Somayajulu 	read_stride = queueEntry->read_addr_stride;
53216a62bec0SDavid C Somayajulu 	select_addr = queueEntry->select_addr;
53226a62bec0SDavid C Somayajulu 
53236a62bec0SDavid C Somayajulu 	for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
53246a62bec0SDavid C Somayajulu 		loop_cnt++) {
53256a62bec0SDavid C Somayajulu 
53266a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, select_addr, &queue_id, 0);
53276a62bec0SDavid C Somayajulu 		if (ret)
53286a62bec0SDavid C Somayajulu 			return (0);
53296a62bec0SDavid C Somayajulu 
53306a62bec0SDavid C Somayajulu 		read_addr = queueEntry->read_addr;
53316a62bec0SDavid C Somayajulu 
53326a62bec0SDavid C Somayajulu 		for (k = 0; k < read_cnt; k++) {
53336a62bec0SDavid C Somayajulu 
53346a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
53356a62bec0SDavid C Somayajulu 			if (ret)
53366a62bec0SDavid C Somayajulu 				return (0);
53376a62bec0SDavid C Somayajulu 
53386a62bec0SDavid C Somayajulu 			*data_buff++ = read_value;
53396a62bec0SDavid C Somayajulu 			read_addr += read_stride;
53406a62bec0SDavid C Somayajulu 		}
53416a62bec0SDavid C Somayajulu 
53426a62bec0SDavid C Somayajulu 		queue_id += queueEntry->queue_id_stride;
53436a62bec0SDavid C Somayajulu 	}
53446a62bec0SDavid C Somayajulu 
53456a62bec0SDavid C Somayajulu 	return (loop_cnt * (read_cnt * sizeof(uint32_t)));
53466a62bec0SDavid C Somayajulu }
53476a62bec0SDavid C Somayajulu 
53486a62bec0SDavid C Somayajulu /*
53496a62bec0SDavid C Somayajulu  * Handling control entries.
53506a62bec0SDavid C Somayajulu  */
53516a62bec0SDavid C Somayajulu 
53526a62bec0SDavid C Somayajulu static uint32_t
53536a62bec0SDavid C Somayajulu ql_cntrl(qla_host_t *ha,
53546a62bec0SDavid C Somayajulu 	ql_minidump_template_hdr_t *template_hdr,
53556a62bec0SDavid C Somayajulu 	ql_minidump_entry_cntrl_t *crbEntry)
53566a62bec0SDavid C Somayajulu {
53576a62bec0SDavid C Somayajulu 	int ret;
53586a62bec0SDavid C Somayajulu 	int count;
53596a62bec0SDavid C Somayajulu 	uint32_t opcode, read_value, addr, entry_addr;
53606a62bec0SDavid C Somayajulu 	long timeout;
53616a62bec0SDavid C Somayajulu 
53626a62bec0SDavid C Somayajulu 	entry_addr = crbEntry->addr;
53636a62bec0SDavid C Somayajulu 
53646a62bec0SDavid C Somayajulu 	for (count = 0; count < crbEntry->op_count; count++) {
53656a62bec0SDavid C Somayajulu 		opcode = crbEntry->opcode;
53666a62bec0SDavid C Somayajulu 
53676a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_WR) {
53686a62bec0SDavid C Somayajulu 
53696a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr,
53706a62bec0SDavid C Somayajulu 					&crbEntry->value_1, 0);
53716a62bec0SDavid C Somayajulu 			if (ret)
53726a62bec0SDavid C Somayajulu 				return (0);
53736a62bec0SDavid C Somayajulu 
53746a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_WR;
53756a62bec0SDavid C Somayajulu 		}
53766a62bec0SDavid C Somayajulu 
53776a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_RW) {
53786a62bec0SDavid C Somayajulu 
53796a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
53806a62bec0SDavid C Somayajulu 			if (ret)
53816a62bec0SDavid C Somayajulu 				return (0);
53826a62bec0SDavid C Somayajulu 
53836a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
53846a62bec0SDavid C Somayajulu 			if (ret)
53856a62bec0SDavid C Somayajulu 				return (0);
53866a62bec0SDavid C Somayajulu 
53876a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_RW;
53886a62bec0SDavid C Somayajulu 		}
53896a62bec0SDavid C Somayajulu 
53906a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_AND) {
53916a62bec0SDavid C Somayajulu 
53926a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
53936a62bec0SDavid C Somayajulu 			if (ret)
53946a62bec0SDavid C Somayajulu 				return (0);
53956a62bec0SDavid C Somayajulu 
53966a62bec0SDavid C Somayajulu 			read_value &= crbEntry->value_2;
53976a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_AND;
53986a62bec0SDavid C Somayajulu 
53996a62bec0SDavid C Somayajulu 			if (opcode & QL_DBG_OPCODE_OR) {
54006a62bec0SDavid C Somayajulu 				read_value |= crbEntry->value_3;
54016a62bec0SDavid C Somayajulu 				opcode &= ~QL_DBG_OPCODE_OR;
54026a62bec0SDavid C Somayajulu 			}
54036a62bec0SDavid C Somayajulu 
54046a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
54056a62bec0SDavid C Somayajulu 			if (ret)
54066a62bec0SDavid C Somayajulu 				return (0);
54076a62bec0SDavid C Somayajulu 		}
54086a62bec0SDavid C Somayajulu 
54096a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_OR) {
54106a62bec0SDavid C Somayajulu 
54116a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
54126a62bec0SDavid C Somayajulu 			if (ret)
54136a62bec0SDavid C Somayajulu 				return (0);
54146a62bec0SDavid C Somayajulu 
54156a62bec0SDavid C Somayajulu 			read_value |= crbEntry->value_3;
54166a62bec0SDavid C Somayajulu 
54176a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
54186a62bec0SDavid C Somayajulu 			if (ret)
54196a62bec0SDavid C Somayajulu 				return (0);
54206a62bec0SDavid C Somayajulu 
54216a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_OR;
54226a62bec0SDavid C Somayajulu 		}
54236a62bec0SDavid C Somayajulu 
54246a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_POLL) {
54256a62bec0SDavid C Somayajulu 
54266a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_POLL;
54276a62bec0SDavid C Somayajulu 			timeout = crbEntry->poll_timeout;
54286a62bec0SDavid C Somayajulu 			addr = entry_addr;
54296a62bec0SDavid C Somayajulu 
54306a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
54316a62bec0SDavid C Somayajulu 			if (ret)
54326a62bec0SDavid C Somayajulu 				return (0);
54336a62bec0SDavid C Somayajulu 
54346a62bec0SDavid C Somayajulu 			while ((read_value & crbEntry->value_2)
54356a62bec0SDavid C Somayajulu 				!= crbEntry->value_1) {
54366a62bec0SDavid C Somayajulu 
54376a62bec0SDavid C Somayajulu 				if (timeout) {
54386a62bec0SDavid C Somayajulu 					qla_mdelay(__func__, 1);
54396a62bec0SDavid C Somayajulu 					timeout--;
54406a62bec0SDavid C Somayajulu 				} else
54416a62bec0SDavid C Somayajulu 					break;
54426a62bec0SDavid C Somayajulu 
54436a62bec0SDavid C Somayajulu                 		ret = ql_rdwr_indreg32(ha, addr,
54446a62bec0SDavid C Somayajulu 						&read_value, 1);
54456a62bec0SDavid C Somayajulu 				if (ret)
54466a62bec0SDavid C Somayajulu 					return (0);
54476a62bec0SDavid C Somayajulu 			}
54486a62bec0SDavid C Somayajulu 
54496a62bec0SDavid C Somayajulu 			if (!timeout) {
54506a62bec0SDavid C Somayajulu 				/*
54516a62bec0SDavid C Somayajulu 				 * Report timeout error.
54526a62bec0SDavid C Somayajulu 				 * core dump capture failed
54536a62bec0SDavid C Somayajulu 				 * Skip remaining entries.
54546a62bec0SDavid C Somayajulu 				 * Write buffer out to file
54556a62bec0SDavid C Somayajulu 				 * Use driver specific fields in template header
54566a62bec0SDavid C Somayajulu 				 * to report this error.
54576a62bec0SDavid C Somayajulu 				 */
54586a62bec0SDavid C Somayajulu 				return (-1);
54596a62bec0SDavid C Somayajulu 			}
54606a62bec0SDavid C Somayajulu 		}
54616a62bec0SDavid C Somayajulu 
54626a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_RDSTATE) {
54636a62bec0SDavid C Somayajulu 			/*
54646a62bec0SDavid C Somayajulu 			 * decide which address to use.
54656a62bec0SDavid C Somayajulu 			 */
54666a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_a) {
54676a62bec0SDavid C Somayajulu 				addr = template_hdr->saved_state_array[
54686a62bec0SDavid C Somayajulu 						crbEntry-> state_index_a];
54696a62bec0SDavid C Somayajulu 			} else {
54706a62bec0SDavid C Somayajulu 				addr = entry_addr;
54716a62bec0SDavid C Somayajulu 			}
54726a62bec0SDavid C Somayajulu 
54736a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
54746a62bec0SDavid C Somayajulu 			if (ret)
54756a62bec0SDavid C Somayajulu 				return (0);
54766a62bec0SDavid C Somayajulu 
54776a62bec0SDavid C Somayajulu 			template_hdr->saved_state_array[crbEntry->state_index_v]
54786a62bec0SDavid C Somayajulu 					= read_value;
54796a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_RDSTATE;
54806a62bec0SDavid C Somayajulu 		}
54816a62bec0SDavid C Somayajulu 
54826a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_WRSTATE) {
54836a62bec0SDavid C Somayajulu 			/*
54846a62bec0SDavid C Somayajulu 			 * decide which value to use.
54856a62bec0SDavid C Somayajulu 			 */
54866a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_v) {
54876a62bec0SDavid C Somayajulu 				read_value = template_hdr->saved_state_array[
54886a62bec0SDavid C Somayajulu 						crbEntry->state_index_v];
54896a62bec0SDavid C Somayajulu 			} else {
54906a62bec0SDavid C Somayajulu 				read_value = crbEntry->value_1;
54916a62bec0SDavid C Somayajulu 			}
54926a62bec0SDavid C Somayajulu 			/*
54936a62bec0SDavid C Somayajulu 			 * decide which address to use.
54946a62bec0SDavid C Somayajulu 			 */
54956a62bec0SDavid C Somayajulu 			if (crbEntry->state_index_a) {
54966a62bec0SDavid C Somayajulu 				addr = template_hdr->saved_state_array[
54976a62bec0SDavid C Somayajulu 						crbEntry-> state_index_a];
54986a62bec0SDavid C Somayajulu 			} else {
54996a62bec0SDavid C Somayajulu 				addr = entry_addr;
55006a62bec0SDavid C Somayajulu 			}
55016a62bec0SDavid C Somayajulu 
55026a62bec0SDavid C Somayajulu                 	ret = ql_rdwr_indreg32(ha, addr, &read_value, 0);
55036a62bec0SDavid C Somayajulu 			if (ret)
55046a62bec0SDavid C Somayajulu 				return (0);
55056a62bec0SDavid C Somayajulu 
55066a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_WRSTATE;
55076a62bec0SDavid C Somayajulu 		}
55086a62bec0SDavid C Somayajulu 
55096a62bec0SDavid C Somayajulu 		if (opcode & QL_DBG_OPCODE_MDSTATE) {
55106a62bec0SDavid C Somayajulu 			/*  Read value from saved state using index */
55116a62bec0SDavid C Somayajulu 			read_value = template_hdr->saved_state_array[
55126a62bec0SDavid C Somayajulu 						crbEntry->state_index_v];
55136a62bec0SDavid C Somayajulu 
55146a62bec0SDavid C Somayajulu 			read_value <<= crbEntry->shl; /*Shift left operation */
55156a62bec0SDavid C Somayajulu 			read_value >>= crbEntry->shr; /*Shift right operation */
55166a62bec0SDavid C Somayajulu 
55176a62bec0SDavid C Somayajulu 			if (crbEntry->value_2) {
55186a62bec0SDavid C Somayajulu 				/* check if AND mask is provided */
55196a62bec0SDavid C Somayajulu 				read_value &= crbEntry->value_2;
55206a62bec0SDavid C Somayajulu 			}
55216a62bec0SDavid C Somayajulu 
55226a62bec0SDavid C Somayajulu 			read_value |= crbEntry->value_3; /* OR operation */
55236a62bec0SDavid C Somayajulu 			read_value += crbEntry->value_1; /* increment op */
55246a62bec0SDavid C Somayajulu 
55256a62bec0SDavid C Somayajulu 			/* Write value back to state area. */
55266a62bec0SDavid C Somayajulu 
55276a62bec0SDavid C Somayajulu 			template_hdr->saved_state_array[crbEntry->state_index_v]
55286a62bec0SDavid C Somayajulu 					= read_value;
55296a62bec0SDavid C Somayajulu 			opcode &= ~QL_DBG_OPCODE_MDSTATE;
55306a62bec0SDavid C Somayajulu 		}
55316a62bec0SDavid C Somayajulu 
55326a62bec0SDavid C Somayajulu 		entry_addr += crbEntry->addr_stride;
55336a62bec0SDavid C Somayajulu 	}
55346a62bec0SDavid C Somayajulu 
55356a62bec0SDavid C Somayajulu 	return (0);
55366a62bec0SDavid C Somayajulu }
55376a62bec0SDavid C Somayajulu 
55386a62bec0SDavid C Somayajulu /*
55396a62bec0SDavid C Somayajulu  * Handling rd poll entry.
55406a62bec0SDavid C Somayajulu  */
55416a62bec0SDavid C Somayajulu 
55426a62bec0SDavid C Somayajulu static uint32_t
55436a62bec0SDavid C Somayajulu ql_pollrd(qla_host_t *ha, ql_minidump_entry_pollrd_t *entry,
55446a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
55456a62bec0SDavid C Somayajulu {
55466a62bec0SDavid C Somayajulu         int ret;
55476a62bec0SDavid C Somayajulu         int loop_cnt;
55486a62bec0SDavid C Somayajulu         uint32_t op_count, select_addr, select_value_stride, select_value;
55496a62bec0SDavid C Somayajulu         uint32_t read_addr, poll, mask, data_size, data;
55506a62bec0SDavid C Somayajulu         uint32_t wait_count = 0;
55516a62bec0SDavid C Somayajulu 
55526a62bec0SDavid C Somayajulu         select_addr            = entry->select_addr;
55536a62bec0SDavid C Somayajulu         read_addr              = entry->read_addr;
55546a62bec0SDavid C Somayajulu         select_value           = entry->select_value;
55556a62bec0SDavid C Somayajulu         select_value_stride    = entry->select_value_stride;
55566a62bec0SDavid C Somayajulu         op_count               = entry->op_count;
55576a62bec0SDavid C Somayajulu         poll                   = entry->poll;
55586a62bec0SDavid C Somayajulu         mask                   = entry->mask;
55596a62bec0SDavid C Somayajulu         data_size              = entry->data_size;
55606a62bec0SDavid C Somayajulu 
55616a62bec0SDavid C Somayajulu         for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
55626a62bec0SDavid C Somayajulu 
55636a62bec0SDavid C Somayajulu                 ret = ql_rdwr_indreg32(ha, select_addr, &select_value, 0);
55646a62bec0SDavid C Somayajulu 		if (ret)
55656a62bec0SDavid C Somayajulu 			return (0);
55666a62bec0SDavid C Somayajulu 
55676a62bec0SDavid C Somayajulu                 wait_count = 0;
55686a62bec0SDavid C Somayajulu 
55696a62bec0SDavid C Somayajulu                 while (wait_count < poll) {
55706a62bec0SDavid C Somayajulu 
55716a62bec0SDavid C Somayajulu                         uint32_t temp;
55726a62bec0SDavid C Somayajulu 
55736a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, select_addr, &temp, 1);
55746a62bec0SDavid C Somayajulu 			if (ret)
55756a62bec0SDavid C Somayajulu 				return (0);
55766a62bec0SDavid C Somayajulu 
55776a62bec0SDavid C Somayajulu                         if ( (temp & mask) != 0 ) {
55786a62bec0SDavid C Somayajulu                                 break;
55796a62bec0SDavid C Somayajulu                         }
55806a62bec0SDavid C Somayajulu                         wait_count++;
55816a62bec0SDavid C Somayajulu                 }
55826a62bec0SDavid C Somayajulu 
55836a62bec0SDavid C Somayajulu                 if (wait_count == poll) {
55846a62bec0SDavid C Somayajulu                         device_printf(ha->pci_dev,
55856a62bec0SDavid C Somayajulu 				"%s: Error in processing entry\n", __func__);
55866a62bec0SDavid C Somayajulu                         device_printf(ha->pci_dev,
55876a62bec0SDavid C Somayajulu 				"%s: wait_count <0x%x> poll <0x%x>\n",
55886a62bec0SDavid C Somayajulu 				__func__, wait_count, poll);
55896a62bec0SDavid C Somayajulu                         return 0;
55906a62bec0SDavid C Somayajulu                 }
55916a62bec0SDavid C Somayajulu 
55926a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, read_addr, &data, 1);
55936a62bec0SDavid C Somayajulu 		if (ret)
55946a62bec0SDavid C Somayajulu 			return (0);
55956a62bec0SDavid C Somayajulu 
55966a62bec0SDavid C Somayajulu                 *data_buff++ = select_value;
55976a62bec0SDavid C Somayajulu                 *data_buff++ = data;
55986a62bec0SDavid C Somayajulu                 select_value = select_value + select_value_stride;
55996a62bec0SDavid C Somayajulu         }
56006a62bec0SDavid C Somayajulu 
56016a62bec0SDavid C Somayajulu         /*
56026a62bec0SDavid C Somayajulu          * for testing purpose we return amount of data written
56036a62bec0SDavid C Somayajulu          */
56046a62bec0SDavid C Somayajulu         return (loop_cnt * (2 * sizeof(uint32_t)));
56056a62bec0SDavid C Somayajulu }
56066a62bec0SDavid C Somayajulu 
56076a62bec0SDavid C Somayajulu 
56086a62bec0SDavid C Somayajulu /*
56096a62bec0SDavid C Somayajulu  * Handling rd modify write poll entry.
56106a62bec0SDavid C Somayajulu  */
56116a62bec0SDavid C Somayajulu 
56126a62bec0SDavid C Somayajulu static uint32_t
56136a62bec0SDavid C Somayajulu ql_pollrd_modify_write(qla_host_t *ha,
56146a62bec0SDavid C Somayajulu 	ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
56156a62bec0SDavid C Somayajulu 	uint32_t *data_buff)
56166a62bec0SDavid C Somayajulu {
56176a62bec0SDavid C Somayajulu 	int ret;
56186a62bec0SDavid C Somayajulu         uint32_t addr_1, addr_2, value_1, value_2, data;
56196a62bec0SDavid C Somayajulu         uint32_t poll, mask, data_size, modify_mask;
56206a62bec0SDavid C Somayajulu         uint32_t wait_count = 0;
56216a62bec0SDavid C Somayajulu 
56226a62bec0SDavid C Somayajulu         addr_1		= entry->addr_1;
56236a62bec0SDavid C Somayajulu         addr_2		= entry->addr_2;
56246a62bec0SDavid C Somayajulu         value_1		= entry->value_1;
56256a62bec0SDavid C Somayajulu         value_2		= entry->value_2;
56266a62bec0SDavid C Somayajulu 
56276a62bec0SDavid C Somayajulu         poll		= entry->poll;
56286a62bec0SDavid C Somayajulu         mask		= entry->mask;
56296a62bec0SDavid C Somayajulu         modify_mask	= entry->modify_mask;
56306a62bec0SDavid C Somayajulu         data_size	= entry->data_size;
56316a62bec0SDavid C Somayajulu 
56326a62bec0SDavid C Somayajulu 
56336a62bec0SDavid C Somayajulu 	ret = ql_rdwr_indreg32(ha, addr_1, &value_1, 0);
56346a62bec0SDavid C Somayajulu 	if (ret)
56356a62bec0SDavid C Somayajulu 		return (0);
56366a62bec0SDavid C Somayajulu 
56376a62bec0SDavid C Somayajulu         wait_count = 0;
56386a62bec0SDavid C Somayajulu         while (wait_count < poll) {
56396a62bec0SDavid C Somayajulu 
56406a62bec0SDavid C Somayajulu 		uint32_t temp;
56416a62bec0SDavid C Somayajulu 
56426a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
56436a62bec0SDavid C Somayajulu 		if (ret)
56446a62bec0SDavid C Somayajulu 			return (0);
56456a62bec0SDavid C Somayajulu 
56466a62bec0SDavid C Somayajulu                 if ( (temp & mask) != 0 ) {
56476a62bec0SDavid C Somayajulu                         break;
56486a62bec0SDavid C Somayajulu                 }
56496a62bec0SDavid C Somayajulu                 wait_count++;
56506a62bec0SDavid C Somayajulu         }
56516a62bec0SDavid C Somayajulu 
56526a62bec0SDavid C Somayajulu         if (wait_count == poll) {
56536a62bec0SDavid C Somayajulu                 device_printf(ha->pci_dev, "%s Error in processing entry\n",
56546a62bec0SDavid C Somayajulu 			__func__);
56556a62bec0SDavid C Somayajulu         } else {
56566a62bec0SDavid C Somayajulu 
56576a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_2, &data, 1);
56586a62bec0SDavid C Somayajulu 		if (ret)
56596a62bec0SDavid C Somayajulu 			return (0);
56606a62bec0SDavid C Somayajulu 
56616a62bec0SDavid C Somayajulu                 data = (data & modify_mask);
56626a62bec0SDavid C Somayajulu 
56636a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_2, &data, 0);
56646a62bec0SDavid C Somayajulu 		if (ret)
56656a62bec0SDavid C Somayajulu 			return (0);
56666a62bec0SDavid C Somayajulu 
56676a62bec0SDavid C Somayajulu 		ret = ql_rdwr_indreg32(ha, addr_1, &value_2, 0);
56686a62bec0SDavid C Somayajulu 		if (ret)
56696a62bec0SDavid C Somayajulu 			return (0);
56706a62bec0SDavid C Somayajulu 
56716a62bec0SDavid C Somayajulu                 /* Poll again */
56726a62bec0SDavid C Somayajulu                 wait_count = 0;
56736a62bec0SDavid C Somayajulu                 while (wait_count < poll) {
56746a62bec0SDavid C Somayajulu 
56756a62bec0SDavid C Somayajulu                         uint32_t temp;
56766a62bec0SDavid C Somayajulu 
56776a62bec0SDavid C Somayajulu 			ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
56786a62bec0SDavid C Somayajulu 			if (ret)
56796a62bec0SDavid C Somayajulu 				return (0);
56806a62bec0SDavid C Somayajulu 
56816a62bec0SDavid C Somayajulu                         if ( (temp & mask) != 0 ) {
56826a62bec0SDavid C Somayajulu                                 break;
56836a62bec0SDavid C Somayajulu                         }
56846a62bec0SDavid C Somayajulu                         wait_count++;
56856a62bec0SDavid C Somayajulu                 }
56866a62bec0SDavid C Somayajulu                 *data_buff++ = addr_2;
56876a62bec0SDavid C Somayajulu                 *data_buff++ = data;
56886a62bec0SDavid C Somayajulu         }
56896a62bec0SDavid C Somayajulu 
56906a62bec0SDavid C Somayajulu         /*
56916a62bec0SDavid C Somayajulu          * for testing purpose we return amount of data written
56926a62bec0SDavid C Somayajulu          */
56936a62bec0SDavid C Somayajulu         return (2 * sizeof(uint32_t));
56946a62bec0SDavid C Somayajulu }
56956a62bec0SDavid C Somayajulu 
56966a62bec0SDavid C Somayajulu 
5697