1718cf2ccSPedro F. Giffuni /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
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 #include "ql_os.h"
38f10a77bbSDavid C Somayajulu #include "ql_hw.h"
39f10a77bbSDavid C Somayajulu #include "ql_def.h"
40f10a77bbSDavid C Somayajulu #include "ql_inline.h"
41f10a77bbSDavid C Somayajulu #include "ql_ver.h"
42f10a77bbSDavid C Somayajulu #include "ql_glbl.h"
43f10a77bbSDavid C Somayajulu #include "ql_dbg.h"
446a62bec0SDavid C Somayajulu #include "ql_minidump.h"
45f10a77bbSDavid C Somayajulu
46f10a77bbSDavid C Somayajulu /*
47f10a77bbSDavid C Somayajulu * Static Functions
48f10a77bbSDavid C Somayajulu */
49f10a77bbSDavid C Somayajulu
50f10a77bbSDavid C Somayajulu static void qla_del_rcv_cntxt(qla_host_t *ha);
51f10a77bbSDavid C Somayajulu static int qla_init_rcv_cntxt(qla_host_t *ha);
52b65c0c07SDavid C Somayajulu static int qla_del_xmt_cntxt(qla_host_t *ha);
53f10a77bbSDavid C Somayajulu static int qla_init_xmt_cntxt(qla_host_t *ha);
54f10a77bbSDavid C Somayajulu static int qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
55f10a77bbSDavid C Somayajulu uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause);
5635291c22SDavid C Somayajulu static int qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx,
5735291c22SDavid C Somayajulu uint32_t num_intrs, uint32_t create);
58f10a77bbSDavid C Somayajulu static int qla_config_rss(qla_host_t *ha, uint16_t cntxt_id);
59f10a77bbSDavid C Somayajulu static int qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id,
6035291c22SDavid C Somayajulu int tenable, int rcv);
61f10a77bbSDavid C Somayajulu static int qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode);
62f10a77bbSDavid C Somayajulu static int qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id);
63f10a77bbSDavid C Somayajulu
64f10a77bbSDavid C Somayajulu static int qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd,
65f10a77bbSDavid C Somayajulu uint8_t *hdr);
66f10a77bbSDavid C Somayajulu static int qla_hw_add_all_mcast(qla_host_t *ha);
6735291c22SDavid C Somayajulu static int qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds);
6835291c22SDavid C Somayajulu
6935291c22SDavid C Somayajulu static int qla_init_nic_func(qla_host_t *ha);
7035291c22SDavid C Somayajulu static int qla_stop_nic_func(qla_host_t *ha);
7135291c22SDavid C Somayajulu static int qla_query_fw_dcbx_caps(qla_host_t *ha);
7235291c22SDavid C Somayajulu static int qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits);
7335291c22SDavid C Somayajulu static int qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits);
7400caeec7SDavid C Somayajulu static int qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode);
7500caeec7SDavid C Somayajulu static int qla_get_cam_search_mode(qla_host_t *ha);
76f10a77bbSDavid C Somayajulu
776a62bec0SDavid C Somayajulu static void ql_minidump_free(qla_host_t *ha);
78f10a77bbSDavid C Somayajulu
79f10a77bbSDavid C Somayajulu #ifdef QL_DBG
80f10a77bbSDavid C Somayajulu
81f10a77bbSDavid C Somayajulu static void
qla_stop_pegs(qla_host_t * ha)82f10a77bbSDavid C Somayajulu qla_stop_pegs(qla_host_t *ha)
83f10a77bbSDavid C Somayajulu {
84f10a77bbSDavid C Somayajulu uint32_t val = 1;
85f10a77bbSDavid C Somayajulu
86f10a77bbSDavid C Somayajulu ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0);
87f10a77bbSDavid C Somayajulu ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0);
88f10a77bbSDavid C Somayajulu ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0);
89f10a77bbSDavid C Somayajulu ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0);
90f10a77bbSDavid C Somayajulu ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0);
91f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__);
92f10a77bbSDavid C Somayajulu }
93f10a77bbSDavid C Somayajulu
94f10a77bbSDavid C Somayajulu static int
qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)95f10a77bbSDavid C Somayajulu qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS)
96f10a77bbSDavid C Somayajulu {
97f10a77bbSDavid C Somayajulu int err, ret = 0;
98f10a77bbSDavid C Somayajulu qla_host_t *ha;
99f10a77bbSDavid C Somayajulu
100f10a77bbSDavid C Somayajulu err = sysctl_handle_int(oidp, &ret, 0, req);
101f10a77bbSDavid C Somayajulu
102f10a77bbSDavid C Somayajulu if (err || !req->newptr)
103f10a77bbSDavid C Somayajulu return (err);
104f10a77bbSDavid C Somayajulu
105f10a77bbSDavid C Somayajulu if (ret == 1) {
106f10a77bbSDavid C Somayajulu ha = (qla_host_t *)arg1;
1077fb51846SDavid C Somayajulu if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
108f10a77bbSDavid C Somayajulu qla_stop_pegs(ha);
1097fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__);
1107fb51846SDavid C Somayajulu }
111f10a77bbSDavid C Somayajulu }
112f10a77bbSDavid C Somayajulu
113f10a77bbSDavid C Somayajulu return err;
114f10a77bbSDavid C Somayajulu }
115f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */
116f10a77bbSDavid C Somayajulu
11735291c22SDavid C Somayajulu static int
qla_validate_set_port_cfg_bit(uint32_t bits)11835291c22SDavid C Somayajulu qla_validate_set_port_cfg_bit(uint32_t bits)
11935291c22SDavid C Somayajulu {
12035291c22SDavid C Somayajulu if ((bits & 0xF) > 1)
12135291c22SDavid C Somayajulu return (-1);
12235291c22SDavid C Somayajulu
12335291c22SDavid C Somayajulu if (((bits >> 4) & 0xF) > 2)
12435291c22SDavid C Somayajulu return (-1);
12535291c22SDavid C Somayajulu
12635291c22SDavid C Somayajulu if (((bits >> 8) & 0xF) > 2)
12735291c22SDavid C Somayajulu return (-1);
12835291c22SDavid C Somayajulu
12935291c22SDavid C Somayajulu return (0);
13035291c22SDavid C Somayajulu }
13135291c22SDavid C Somayajulu
13235291c22SDavid C Somayajulu static int
qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS)13335291c22SDavid C Somayajulu qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS)
13435291c22SDavid C Somayajulu {
13535291c22SDavid C Somayajulu int err, ret = 0;
13635291c22SDavid C Somayajulu qla_host_t *ha;
13735291c22SDavid C Somayajulu uint32_t cfg_bits;
13835291c22SDavid C Somayajulu
13935291c22SDavid C Somayajulu err = sysctl_handle_int(oidp, &ret, 0, req);
14035291c22SDavid C Somayajulu
14135291c22SDavid C Somayajulu if (err || !req->newptr)
14235291c22SDavid C Somayajulu return (err);
14335291c22SDavid C Somayajulu
14435291c22SDavid C Somayajulu ha = (qla_host_t *)arg1;
14535291c22SDavid C Somayajulu
1467fb51846SDavid C Somayajulu if ((qla_validate_set_port_cfg_bit((uint32_t)ret) == 0)) {
14735291c22SDavid C Somayajulu err = qla_get_port_config(ha, &cfg_bits);
14835291c22SDavid C Somayajulu
14935291c22SDavid C Somayajulu if (err)
15035291c22SDavid C Somayajulu goto qla_sysctl_set_port_cfg_exit;
15135291c22SDavid C Somayajulu
15235291c22SDavid C Somayajulu if (ret & 0x1) {
15335291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_DCBX_ENABLE;
15435291c22SDavid C Somayajulu } else {
15535291c22SDavid C Somayajulu cfg_bits &= ~Q8_PORT_CFG_BITS_DCBX_ENABLE;
15635291c22SDavid C Somayajulu }
15735291c22SDavid C Somayajulu
15835291c22SDavid C Somayajulu ret = ret >> 4;
15935291c22SDavid C Somayajulu cfg_bits &= ~Q8_PORT_CFG_BITS_PAUSE_CFG_MASK;
16035291c22SDavid C Somayajulu
16135291c22SDavid C Somayajulu if ((ret & 0xF) == 0) {
16235291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_DISABLED;
16335291c22SDavid C Somayajulu } else if ((ret & 0xF) == 1){
16435291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_STD;
16535291c22SDavid C Somayajulu } else {
16635291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_PPM;
16735291c22SDavid C Somayajulu }
16835291c22SDavid C Somayajulu
16935291c22SDavid C Somayajulu ret = ret >> 4;
17035291c22SDavid C Somayajulu cfg_bits &= ~Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK;
17135291c22SDavid C Somayajulu
17235291c22SDavid C Somayajulu if (ret == 0) {
17335291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT_RCV;
17435291c22SDavid C Somayajulu } else if (ret == 1){
17535291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT;
17635291c22SDavid C Somayajulu } else {
17735291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_RCV;
17835291c22SDavid C Somayajulu }
17935291c22SDavid C Somayajulu
1807fb51846SDavid C Somayajulu if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
18135291c22SDavid C Somayajulu err = qla_set_port_config(ha, cfg_bits);
1827fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__);
18335291c22SDavid C Somayajulu } else {
1847fb51846SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", __func__);
1857fb51846SDavid C Somayajulu }
1867fb51846SDavid C Somayajulu } else {
1877fb51846SDavid C Somayajulu if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
18835291c22SDavid C Somayajulu err = qla_get_port_config(ha, &cfg_bits);
1897fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__);
1907fb51846SDavid C Somayajulu } else {
1917fb51846SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", __func__);
1927fb51846SDavid C Somayajulu }
19335291c22SDavid C Somayajulu }
19435291c22SDavid C Somayajulu
19535291c22SDavid C Somayajulu qla_sysctl_set_port_cfg_exit:
19635291c22SDavid C Somayajulu return err;
19735291c22SDavid C Somayajulu }
19835291c22SDavid C Somayajulu
19900caeec7SDavid C Somayajulu static int
qla_sysctl_set_cam_search_mode(SYSCTL_HANDLER_ARGS)20000caeec7SDavid C Somayajulu qla_sysctl_set_cam_search_mode(SYSCTL_HANDLER_ARGS)
20100caeec7SDavid C Somayajulu {
20200caeec7SDavid C Somayajulu int err, ret = 0;
20300caeec7SDavid C Somayajulu qla_host_t *ha;
20400caeec7SDavid C Somayajulu
20500caeec7SDavid C Somayajulu err = sysctl_handle_int(oidp, &ret, 0, req);
20600caeec7SDavid C Somayajulu
20700caeec7SDavid C Somayajulu if (err || !req->newptr)
20800caeec7SDavid C Somayajulu return (err);
20900caeec7SDavid C Somayajulu
21000caeec7SDavid C Somayajulu ha = (qla_host_t *)arg1;
21100caeec7SDavid C Somayajulu
21200caeec7SDavid C Somayajulu if ((ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_INTERNAL) ||
21300caeec7SDavid C Somayajulu (ret == Q8_HW_CONFIG_CAM_SEARCH_MODE_AUTO)) {
2147fb51846SDavid C Somayajulu if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
21500caeec7SDavid C Somayajulu err = qla_set_cam_search_mode(ha, (uint32_t)ret);
2167fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__);
2177fb51846SDavid C Somayajulu } else {
2187fb51846SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", __func__);
2197fb51846SDavid C Somayajulu }
2207fb51846SDavid C Somayajulu
22100caeec7SDavid C Somayajulu } else {
22200caeec7SDavid C Somayajulu device_printf(ha->pci_dev, "%s: ret = %d\n", __func__, ret);
22300caeec7SDavid C Somayajulu }
22400caeec7SDavid C Somayajulu
22500caeec7SDavid C Somayajulu return (err);
22600caeec7SDavid C Somayajulu }
22700caeec7SDavid C Somayajulu
22800caeec7SDavid C Somayajulu static int
qla_sysctl_get_cam_search_mode(SYSCTL_HANDLER_ARGS)22900caeec7SDavid C Somayajulu qla_sysctl_get_cam_search_mode(SYSCTL_HANDLER_ARGS)
23000caeec7SDavid C Somayajulu {
23100caeec7SDavid C Somayajulu int err, ret = 0;
23200caeec7SDavid C Somayajulu qla_host_t *ha;
23300caeec7SDavid C Somayajulu
23400caeec7SDavid C Somayajulu err = sysctl_handle_int(oidp, &ret, 0, req);
23500caeec7SDavid C Somayajulu
23600caeec7SDavid C Somayajulu if (err || !req->newptr)
23700caeec7SDavid C Somayajulu return (err);
23800caeec7SDavid C Somayajulu
23900caeec7SDavid C Somayajulu ha = (qla_host_t *)arg1;
2407fb51846SDavid C Somayajulu if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) {
24100caeec7SDavid C Somayajulu err = qla_get_cam_search_mode(ha);
2427fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__);
2437fb51846SDavid C Somayajulu } else {
2447fb51846SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", __func__);
2457fb51846SDavid C Somayajulu }
24600caeec7SDavid C Somayajulu
24700caeec7SDavid C Somayajulu return (err);
24800caeec7SDavid C Somayajulu }
24900caeec7SDavid C Somayajulu
2507fb51846SDavid C Somayajulu static void
qlnx_add_hw_mac_stats_sysctls(qla_host_t * ha)2517fb51846SDavid C Somayajulu qlnx_add_hw_mac_stats_sysctls(qla_host_t *ha)
2527fb51846SDavid C Somayajulu {
2537fb51846SDavid C Somayajulu struct sysctl_ctx_list *ctx;
2547fb51846SDavid C Somayajulu struct sysctl_oid_list *children;
2557fb51846SDavid C Somayajulu struct sysctl_oid *ctx_oid;
2567fb51846SDavid C Somayajulu
2577fb51846SDavid C Somayajulu ctx = device_get_sysctl_ctx(ha->pci_dev);
2587fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
2597fb51846SDavid C Somayajulu
2607fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_mac",
2617029da5cSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_hw_mac");
2627fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(ctx_oid);
2637fb51846SDavid C Somayajulu
2647fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
2657fb51846SDavid C Somayajulu OID_AUTO, "xmt_frames",
2667fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_frames,
2677fb51846SDavid C Somayajulu "xmt_frames");
2687fb51846SDavid C Somayajulu
2697fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
2707fb51846SDavid C Somayajulu OID_AUTO, "xmt_bytes",
2717fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_bytes,
2727fb51846SDavid C Somayajulu "xmt_frames");
2737fb51846SDavid C Somayajulu
2747fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
2757fb51846SDavid C Somayajulu OID_AUTO, "xmt_mcast_pkts",
2767fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_mcast_pkts,
2777fb51846SDavid C Somayajulu "xmt_mcast_pkts");
2787fb51846SDavid C Somayajulu
2797fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
2807fb51846SDavid C Somayajulu OID_AUTO, "xmt_bcast_pkts",
2817fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_bcast_pkts,
2827fb51846SDavid C Somayajulu "xmt_bcast_pkts");
2837fb51846SDavid C Somayajulu
2847fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
2857fb51846SDavid C Somayajulu OID_AUTO, "xmt_pause_frames",
2867fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_pause_frames,
2877fb51846SDavid C Somayajulu "xmt_pause_frames");
2887fb51846SDavid C Somayajulu
2897fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
2907fb51846SDavid C Somayajulu OID_AUTO, "xmt_cntrl_pkts",
2917fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_cntrl_pkts,
2927fb51846SDavid C Somayajulu "xmt_cntrl_pkts");
2937fb51846SDavid C Somayajulu
2947fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
2957fb51846SDavid C Somayajulu OID_AUTO, "xmt_pkt_lt_64bytes",
2967fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_64bytes,
2977fb51846SDavid C Somayajulu "xmt_pkt_lt_64bytes");
2987fb51846SDavid C Somayajulu
2997fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3007fb51846SDavid C Somayajulu OID_AUTO, "xmt_pkt_lt_127bytes",
3017fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_127bytes,
3027fb51846SDavid C Somayajulu "xmt_pkt_lt_127bytes");
3037fb51846SDavid C Somayajulu
3047fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3057fb51846SDavid C Somayajulu OID_AUTO, "xmt_pkt_lt_255bytes",
3067fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_255bytes,
3077fb51846SDavid C Somayajulu "xmt_pkt_lt_255bytes");
3087fb51846SDavid C Somayajulu
3097fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3107fb51846SDavid C Somayajulu OID_AUTO, "xmt_pkt_lt_511bytes",
3117fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_511bytes,
3127fb51846SDavid C Somayajulu "xmt_pkt_lt_511bytes");
3137fb51846SDavid C Somayajulu
3147fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3157fb51846SDavid C Somayajulu OID_AUTO, "xmt_pkt_lt_1023bytes",
3167fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_1023bytes,
3177fb51846SDavid C Somayajulu "xmt_pkt_lt_1023bytes");
3187fb51846SDavid C Somayajulu
3197fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3207fb51846SDavid C Somayajulu OID_AUTO, "xmt_pkt_lt_1518bytes",
3217fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_pkt_lt_1518bytes,
3227fb51846SDavid C Somayajulu "xmt_pkt_lt_1518bytes");
3237fb51846SDavid C Somayajulu
3247fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3257fb51846SDavid C Somayajulu OID_AUTO, "xmt_pkt_gt_1518bytes",
3267fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.xmt_pkt_gt_1518bytes,
3277fb51846SDavid C Somayajulu "xmt_pkt_gt_1518bytes");
3287fb51846SDavid C Somayajulu
3297fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3307fb51846SDavid C Somayajulu OID_AUTO, "rcv_frames",
3317fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_frames,
3327fb51846SDavid C Somayajulu "rcv_frames");
3337fb51846SDavid C Somayajulu
3347fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3357fb51846SDavid C Somayajulu OID_AUTO, "rcv_bytes",
3367fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_bytes,
3377fb51846SDavid C Somayajulu "rcv_bytes");
3387fb51846SDavid C Somayajulu
3397fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3407fb51846SDavid C Somayajulu OID_AUTO, "rcv_mcast_pkts",
3417fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_mcast_pkts,
3427fb51846SDavid C Somayajulu "rcv_mcast_pkts");
3437fb51846SDavid C Somayajulu
3447fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3457fb51846SDavid C Somayajulu OID_AUTO, "rcv_bcast_pkts",
3467fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_bcast_pkts,
3477fb51846SDavid C Somayajulu "rcv_bcast_pkts");
3487fb51846SDavid C Somayajulu
3497fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3507fb51846SDavid C Somayajulu OID_AUTO, "rcv_pause_frames",
3517fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_pause_frames,
3527fb51846SDavid C Somayajulu "rcv_pause_frames");
3537fb51846SDavid C Somayajulu
3547fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3557fb51846SDavid C Somayajulu OID_AUTO, "rcv_cntrl_pkts",
3567fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_cntrl_pkts,
3577fb51846SDavid C Somayajulu "rcv_cntrl_pkts");
3587fb51846SDavid C Somayajulu
3597fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3607fb51846SDavid C Somayajulu OID_AUTO, "rcv_pkt_lt_64bytes",
3617fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_64bytes,
3627fb51846SDavid C Somayajulu "rcv_pkt_lt_64bytes");
3637fb51846SDavid C Somayajulu
3647fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3657fb51846SDavid C Somayajulu OID_AUTO, "rcv_pkt_lt_127bytes",
3667fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_127bytes,
3677fb51846SDavid C Somayajulu "rcv_pkt_lt_127bytes");
3687fb51846SDavid C Somayajulu
3697fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3707fb51846SDavid C Somayajulu OID_AUTO, "rcv_pkt_lt_255bytes",
3717fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_255bytes,
3727fb51846SDavid C Somayajulu "rcv_pkt_lt_255bytes");
3737fb51846SDavid C Somayajulu
3747fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3757fb51846SDavid C Somayajulu OID_AUTO, "rcv_pkt_lt_511bytes",
3767fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_511bytes,
3777fb51846SDavid C Somayajulu "rcv_pkt_lt_511bytes");
3787fb51846SDavid C Somayajulu
3797fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3807fb51846SDavid C Somayajulu OID_AUTO, "rcv_pkt_lt_1023bytes",
3817fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_1023bytes,
3827fb51846SDavid C Somayajulu "rcv_pkt_lt_1023bytes");
3837fb51846SDavid C Somayajulu
3847fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3857fb51846SDavid C Somayajulu OID_AUTO, "rcv_pkt_lt_1518bytes",
3867fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_pkt_lt_1518bytes,
3877fb51846SDavid C Somayajulu "rcv_pkt_lt_1518bytes");
3887fb51846SDavid C Somayajulu
3897fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3907fb51846SDavid C Somayajulu OID_AUTO, "rcv_pkt_gt_1518bytes",
3917fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_pkt_gt_1518bytes,
3927fb51846SDavid C Somayajulu "rcv_pkt_gt_1518bytes");
3937fb51846SDavid C Somayajulu
3947fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
3957fb51846SDavid C Somayajulu OID_AUTO, "rcv_len_error",
3967fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_len_error,
3977fb51846SDavid C Somayajulu "rcv_len_error");
3987fb51846SDavid C Somayajulu
3997fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4007fb51846SDavid C Somayajulu OID_AUTO, "rcv_len_small",
4017fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_len_small,
4027fb51846SDavid C Somayajulu "rcv_len_small");
4037fb51846SDavid C Somayajulu
4047fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4057fb51846SDavid C Somayajulu OID_AUTO, "rcv_len_large",
4067fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_len_large,
4077fb51846SDavid C Somayajulu "rcv_len_large");
4087fb51846SDavid C Somayajulu
4097fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4107fb51846SDavid C Somayajulu OID_AUTO, "rcv_jabber",
4117fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_jabber,
4127fb51846SDavid C Somayajulu "rcv_jabber");
4137fb51846SDavid C Somayajulu
4147fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4157fb51846SDavid C Somayajulu OID_AUTO, "rcv_dropped",
4167fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.rcv_dropped,
4177fb51846SDavid C Somayajulu "rcv_dropped");
4187fb51846SDavid C Somayajulu
4197fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4207fb51846SDavid C Somayajulu OID_AUTO, "fcs_error",
4217fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.fcs_error,
4227fb51846SDavid C Somayajulu "fcs_error");
4237fb51846SDavid C Somayajulu
4247fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4257fb51846SDavid C Somayajulu OID_AUTO, "align_error",
4267fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.align_error,
4277fb51846SDavid C Somayajulu "align_error");
4287fb51846SDavid C Somayajulu
4297fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4307fb51846SDavid C Somayajulu OID_AUTO, "eswitched_frames",
4317fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.eswitched_frames,
4327fb51846SDavid C Somayajulu "eswitched_frames");
4337fb51846SDavid C Somayajulu
4347fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4357fb51846SDavid C Somayajulu OID_AUTO, "eswitched_bytes",
4367fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.eswitched_bytes,
4377fb51846SDavid C Somayajulu "eswitched_bytes");
4387fb51846SDavid C Somayajulu
4397fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4407fb51846SDavid C Somayajulu OID_AUTO, "eswitched_mcast_frames",
4417fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.eswitched_mcast_frames,
4427fb51846SDavid C Somayajulu "eswitched_mcast_frames");
4437fb51846SDavid C Somayajulu
4447fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4457fb51846SDavid C Somayajulu OID_AUTO, "eswitched_bcast_frames",
4467fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.eswitched_bcast_frames,
4477fb51846SDavid C Somayajulu "eswitched_bcast_frames");
4487fb51846SDavid C Somayajulu
4497fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4507fb51846SDavid C Somayajulu OID_AUTO, "eswitched_ucast_frames",
4517fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.eswitched_ucast_frames,
4527fb51846SDavid C Somayajulu "eswitched_ucast_frames");
4537fb51846SDavid C Somayajulu
4547fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4557fb51846SDavid C Somayajulu OID_AUTO, "eswitched_err_free_frames",
4567fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.eswitched_err_free_frames,
4577fb51846SDavid C Somayajulu "eswitched_err_free_frames");
4587fb51846SDavid C Somayajulu
4597fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4607fb51846SDavid C Somayajulu OID_AUTO, "eswitched_err_free_bytes",
4617fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mac.eswitched_err_free_bytes,
4627fb51846SDavid C Somayajulu "eswitched_err_free_bytes");
4637fb51846SDavid C Somayajulu
4647fb51846SDavid C Somayajulu return;
4657fb51846SDavid C Somayajulu }
4667fb51846SDavid C Somayajulu
4677fb51846SDavid C Somayajulu static void
qlnx_add_hw_rcv_stats_sysctls(qla_host_t * ha)4687fb51846SDavid C Somayajulu qlnx_add_hw_rcv_stats_sysctls(qla_host_t *ha)
4697fb51846SDavid C Somayajulu {
4707fb51846SDavid C Somayajulu struct sysctl_ctx_list *ctx;
4717fb51846SDavid C Somayajulu struct sysctl_oid_list *children;
4727fb51846SDavid C Somayajulu struct sysctl_oid *ctx_oid;
4737fb51846SDavid C Somayajulu
4747fb51846SDavid C Somayajulu ctx = device_get_sysctl_ctx(ha->pci_dev);
4757fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
4767fb51846SDavid C Somayajulu
4777fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_rcv",
4787029da5cSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_hw_rcv");
4797fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(ctx_oid);
4807fb51846SDavid C Somayajulu
4817fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4827fb51846SDavid C Somayajulu OID_AUTO, "total_bytes",
4837fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.total_bytes,
4847fb51846SDavid C Somayajulu "total_bytes");
4857fb51846SDavid C Somayajulu
4867fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4877fb51846SDavid C Somayajulu OID_AUTO, "total_pkts",
4887fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.total_pkts,
4897fb51846SDavid C Somayajulu "total_pkts");
4907fb51846SDavid C Somayajulu
4917fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4927fb51846SDavid C Somayajulu OID_AUTO, "lro_pkt_count",
4937fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.lro_pkt_count,
4947fb51846SDavid C Somayajulu "lro_pkt_count");
4957fb51846SDavid C Somayajulu
4967fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
4977fb51846SDavid C Somayajulu OID_AUTO, "sw_pkt_count",
4987fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.sw_pkt_count,
4997fb51846SDavid C Somayajulu "sw_pkt_count");
5007fb51846SDavid C Somayajulu
5017fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5027fb51846SDavid C Somayajulu OID_AUTO, "ip_chksum_err",
5037fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.ip_chksum_err,
5047fb51846SDavid C Somayajulu "ip_chksum_err");
5057fb51846SDavid C Somayajulu
5067fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5077fb51846SDavid C Somayajulu OID_AUTO, "pkts_wo_acntxts",
5087fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.pkts_wo_acntxts,
5097fb51846SDavid C Somayajulu "pkts_wo_acntxts");
5107fb51846SDavid C Somayajulu
5117fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5127fb51846SDavid C Somayajulu OID_AUTO, "pkts_dropped_no_sds_card",
5137fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_sds_card,
5147fb51846SDavid C Somayajulu "pkts_dropped_no_sds_card");
5157fb51846SDavid C Somayajulu
5167fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5177fb51846SDavid C Somayajulu OID_AUTO, "pkts_dropped_no_sds_host",
5187fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_sds_host,
5197fb51846SDavid C Somayajulu "pkts_dropped_no_sds_host");
5207fb51846SDavid C Somayajulu
5217fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5227fb51846SDavid C Somayajulu OID_AUTO, "oversized_pkts",
5237fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.oversized_pkts,
5247fb51846SDavid C Somayajulu "oversized_pkts");
5257fb51846SDavid C Somayajulu
5267fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5277fb51846SDavid C Somayajulu OID_AUTO, "pkts_dropped_no_rds",
5287fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.pkts_dropped_no_rds,
5297fb51846SDavid C Somayajulu "pkts_dropped_no_rds");
5307fb51846SDavid C Somayajulu
5317fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5327fb51846SDavid C Somayajulu OID_AUTO, "unxpctd_mcast_pkts",
5337fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.unxpctd_mcast_pkts,
5347fb51846SDavid C Somayajulu "unxpctd_mcast_pkts");
5357fb51846SDavid C Somayajulu
5367fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5377fb51846SDavid C Somayajulu OID_AUTO, "re1_fbq_error",
5387fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.re1_fbq_error,
5397fb51846SDavid C Somayajulu "re1_fbq_error");
5407fb51846SDavid C Somayajulu
5417fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5427fb51846SDavid C Somayajulu OID_AUTO, "invalid_mac_addr",
5437fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.invalid_mac_addr,
5447fb51846SDavid C Somayajulu "invalid_mac_addr");
5457fb51846SDavid C Somayajulu
5467fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5477fb51846SDavid C Somayajulu OID_AUTO, "rds_prime_trys",
5487fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.rds_prime_trys,
5497fb51846SDavid C Somayajulu "rds_prime_trys");
5507fb51846SDavid C Somayajulu
5517fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5527fb51846SDavid C Somayajulu OID_AUTO, "rds_prime_success",
5537fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.rds_prime_success,
5547fb51846SDavid C Somayajulu "rds_prime_success");
5557fb51846SDavid C Somayajulu
5567fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5577fb51846SDavid C Somayajulu OID_AUTO, "lro_flows_added",
5587fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.lro_flows_added,
5597fb51846SDavid C Somayajulu "lro_flows_added");
5607fb51846SDavid C Somayajulu
5617fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5627fb51846SDavid C Somayajulu OID_AUTO, "lro_flows_deleted",
5637fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.lro_flows_deleted,
5647fb51846SDavid C Somayajulu "lro_flows_deleted");
5657fb51846SDavid C Somayajulu
5667fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5677fb51846SDavid C Somayajulu OID_AUTO, "lro_flows_active",
5687fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.lro_flows_active,
5697fb51846SDavid C Somayajulu "lro_flows_active");
5707fb51846SDavid C Somayajulu
5717fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5727fb51846SDavid C Somayajulu OID_AUTO, "pkts_droped_unknown",
5737fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.pkts_droped_unknown,
5747fb51846SDavid C Somayajulu "pkts_droped_unknown");
5757fb51846SDavid C Somayajulu
5767fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, children,
5777fb51846SDavid C Somayajulu OID_AUTO, "pkts_cnt_oversized",
5787fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rcv.pkts_cnt_oversized,
5797fb51846SDavid C Somayajulu "pkts_cnt_oversized");
5807fb51846SDavid C Somayajulu
5817fb51846SDavid C Somayajulu return;
5827fb51846SDavid C Somayajulu }
5837fb51846SDavid C Somayajulu
5847fb51846SDavid C Somayajulu static void
qlnx_add_hw_xmt_stats_sysctls(qla_host_t * ha)5857fb51846SDavid C Somayajulu qlnx_add_hw_xmt_stats_sysctls(qla_host_t *ha)
5867fb51846SDavid C Somayajulu {
5877fb51846SDavid C Somayajulu struct sysctl_ctx_list *ctx;
5887fb51846SDavid C Somayajulu struct sysctl_oid_list *children;
5897fb51846SDavid C Somayajulu struct sysctl_oid_list *node_children;
5907fb51846SDavid C Somayajulu struct sysctl_oid *ctx_oid;
5917fb51846SDavid C Somayajulu int i;
5927fb51846SDavid C Somayajulu uint8_t name_str[16];
5937fb51846SDavid C Somayajulu
5947fb51846SDavid C Somayajulu ctx = device_get_sysctl_ctx(ha->pci_dev);
5957fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
5967fb51846SDavid C Somayajulu
5977fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_hw_xmt",
5987029da5cSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_hw_xmt");
5997fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(ctx_oid);
6007fb51846SDavid C Somayajulu
6017fb51846SDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) {
6027fb51846SDavid C Somayajulu bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
6037fb51846SDavid C Somayajulu snprintf(name_str, sizeof(name_str), "%d", i);
6047fb51846SDavid C Somayajulu
6057fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
6067029da5cSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, name_str);
6077fb51846SDavid C Somayajulu node_children = SYSCTL_CHILDREN(ctx_oid);
6087fb51846SDavid C Somayajulu
6097fb51846SDavid C Somayajulu /* Tx Related */
6107fb51846SDavid C Somayajulu
6117fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
6127fb51846SDavid C Somayajulu OID_AUTO, "total_bytes",
6137fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.xmt[i].total_bytes,
6147fb51846SDavid C Somayajulu "total_bytes");
6157fb51846SDavid C Somayajulu
6167fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
6177fb51846SDavid C Somayajulu OID_AUTO, "total_pkts",
6187fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.xmt[i].total_pkts,
6197fb51846SDavid C Somayajulu "total_pkts");
6207fb51846SDavid C Somayajulu
6217fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
6227fb51846SDavid C Somayajulu OID_AUTO, "errors",
6237fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.xmt[i].errors,
6247fb51846SDavid C Somayajulu "errors");
6257fb51846SDavid C Somayajulu
6267fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
6277fb51846SDavid C Somayajulu OID_AUTO, "pkts_dropped",
6287fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.xmt[i].pkts_dropped,
6297fb51846SDavid C Somayajulu "pkts_dropped");
6307fb51846SDavid C Somayajulu
6317fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
6327fb51846SDavid C Somayajulu OID_AUTO, "switch_pkts",
6337fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.xmt[i].switch_pkts,
6347fb51846SDavid C Somayajulu "switch_pkts");
6357fb51846SDavid C Somayajulu
6367fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
6377fb51846SDavid C Somayajulu OID_AUTO, "num_buffers",
6387fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.xmt[i].num_buffers,
6397fb51846SDavid C Somayajulu "num_buffers");
6407fb51846SDavid C Somayajulu }
6417fb51846SDavid C Somayajulu
6427fb51846SDavid C Somayajulu return;
6437fb51846SDavid C Somayajulu }
6447fb51846SDavid C Somayajulu
6457fb51846SDavid C Somayajulu static void
qlnx_add_hw_mbx_cmpl_stats_sysctls(qla_host_t * ha)646b65c0c07SDavid C Somayajulu qlnx_add_hw_mbx_cmpl_stats_sysctls(qla_host_t *ha)
647b65c0c07SDavid C Somayajulu {
648b65c0c07SDavid C Somayajulu struct sysctl_ctx_list *ctx;
649b65c0c07SDavid C Somayajulu struct sysctl_oid_list *node_children;
650b65c0c07SDavid C Somayajulu
651b65c0c07SDavid C Somayajulu ctx = device_get_sysctl_ctx(ha->pci_dev);
652b65c0c07SDavid C Somayajulu node_children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
653b65c0c07SDavid C Somayajulu
654b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
655b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_lt_200ms",
656b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[0],
657b65c0c07SDavid C Somayajulu "mbx_completion_time_lt_200ms");
658b65c0c07SDavid C Somayajulu
659b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
660b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_200ms_400ms",
661b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[1],
662b65c0c07SDavid C Somayajulu "mbx_completion_time_200ms_400ms");
663b65c0c07SDavid C Somayajulu
664b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
665b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_400ms_600ms",
666b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[2],
667b65c0c07SDavid C Somayajulu "mbx_completion_time_400ms_600ms");
668b65c0c07SDavid C Somayajulu
669b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
670b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_600ms_800ms",
671b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[3],
672b65c0c07SDavid C Somayajulu "mbx_completion_time_600ms_800ms");
673b65c0c07SDavid C Somayajulu
674b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
675b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_800ms_1000ms",
676b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[4],
677b65c0c07SDavid C Somayajulu "mbx_completion_time_800ms_1000ms");
678b65c0c07SDavid C Somayajulu
679b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
680b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_1000ms_1200ms",
681b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[5],
682b65c0c07SDavid C Somayajulu "mbx_completion_time_1000ms_1200ms");
683b65c0c07SDavid C Somayajulu
684b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
685b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_1200ms_1400ms",
686b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[6],
687b65c0c07SDavid C Somayajulu "mbx_completion_time_1200ms_1400ms");
688b65c0c07SDavid C Somayajulu
689b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
690b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_1400ms_1600ms",
691b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[7],
692b65c0c07SDavid C Somayajulu "mbx_completion_time_1400ms_1600ms");
693b65c0c07SDavid C Somayajulu
694b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
695b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_1600ms_1800ms",
696b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[8],
697b65c0c07SDavid C Somayajulu "mbx_completion_time_1600ms_1800ms");
698b65c0c07SDavid C Somayajulu
699b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
700b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_1800ms_2000ms",
701b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[9],
702b65c0c07SDavid C Somayajulu "mbx_completion_time_1800ms_2000ms");
703b65c0c07SDavid C Somayajulu
704b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
705b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_2000ms_2200ms",
706b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[10],
707b65c0c07SDavid C Somayajulu "mbx_completion_time_2000ms_2200ms");
708b65c0c07SDavid C Somayajulu
709b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
710b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_2200ms_2400ms",
711b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[11],
712b65c0c07SDavid C Somayajulu "mbx_completion_time_2200ms_2400ms");
713b65c0c07SDavid C Somayajulu
714b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
715b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_2400ms_2600ms",
716b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[12],
717b65c0c07SDavid C Somayajulu "mbx_completion_time_2400ms_2600ms");
718b65c0c07SDavid C Somayajulu
719b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
720b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_2600ms_2800ms",
721b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[13],
722b65c0c07SDavid C Somayajulu "mbx_completion_time_2600ms_2800ms");
723b65c0c07SDavid C Somayajulu
724b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
725b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_2800ms_3000ms",
726b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[14],
727b65c0c07SDavid C Somayajulu "mbx_completion_time_2800ms_3000ms");
728b65c0c07SDavid C Somayajulu
729b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
730b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_3000ms_4000ms",
731b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[15],
732b65c0c07SDavid C Somayajulu "mbx_completion_time_3000ms_4000ms");
733b65c0c07SDavid C Somayajulu
734b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
735b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_time_4000ms_5000ms",
736b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[16],
737b65c0c07SDavid C Somayajulu "mbx_completion_time_4000ms_5000ms");
738b65c0c07SDavid C Somayajulu
739b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
740b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_host_mbx_cntrl_timeout",
741b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[17],
742b65c0c07SDavid C Somayajulu "mbx_completion_host_mbx_cntrl_timeout");
743b65c0c07SDavid C Somayajulu
744b65c0c07SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
745b65c0c07SDavid C Somayajulu OID_AUTO, "mbx_completion_fw_mbx_cntrl_timeout",
746b65c0c07SDavid C Somayajulu CTLFLAG_RD, &ha->hw.mbx_comp_msecs[18],
747b65c0c07SDavid C Somayajulu "mbx_completion_fw_mbx_cntrl_timeout");
748b65c0c07SDavid C Somayajulu return;
749b65c0c07SDavid C Somayajulu }
750b65c0c07SDavid C Somayajulu
751b65c0c07SDavid C Somayajulu static void
qlnx_add_hw_stats_sysctls(qla_host_t * ha)7527fb51846SDavid C Somayajulu qlnx_add_hw_stats_sysctls(qla_host_t *ha)
7537fb51846SDavid C Somayajulu {
7547fb51846SDavid C Somayajulu qlnx_add_hw_mac_stats_sysctls(ha);
7557fb51846SDavid C Somayajulu qlnx_add_hw_rcv_stats_sysctls(ha);
7567fb51846SDavid C Somayajulu qlnx_add_hw_xmt_stats_sysctls(ha);
757b65c0c07SDavid C Somayajulu qlnx_add_hw_mbx_cmpl_stats_sysctls(ha);
7587fb51846SDavid C Somayajulu
7597fb51846SDavid C Somayajulu return;
7607fb51846SDavid C Somayajulu }
7617fb51846SDavid C Somayajulu
7627fb51846SDavid C Somayajulu static void
qlnx_add_drvr_sds_stats(qla_host_t * ha)7637fb51846SDavid C Somayajulu qlnx_add_drvr_sds_stats(qla_host_t *ha)
7647fb51846SDavid C Somayajulu {
7657fb51846SDavid C Somayajulu struct sysctl_ctx_list *ctx;
7667fb51846SDavid C Somayajulu struct sysctl_oid_list *children;
7677fb51846SDavid C Somayajulu struct sysctl_oid_list *node_children;
7687fb51846SDavid C Somayajulu struct sysctl_oid *ctx_oid;
7697fb51846SDavid C Somayajulu int i;
7707fb51846SDavid C Somayajulu uint8_t name_str[16];
7717fb51846SDavid C Somayajulu
7727fb51846SDavid C Somayajulu ctx = device_get_sysctl_ctx(ha->pci_dev);
7737fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
7747fb51846SDavid C Somayajulu
7757fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_sds",
7767029da5cSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_drvr_sds");
7777fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(ctx_oid);
7787fb51846SDavid C Somayajulu
7797fb51846SDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) {
7807fb51846SDavid C Somayajulu bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
7817fb51846SDavid C Somayajulu snprintf(name_str, sizeof(name_str), "%d", i);
7827fb51846SDavid C Somayajulu
7837fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
7847029da5cSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, name_str);
7857fb51846SDavid C Somayajulu node_children = SYSCTL_CHILDREN(ctx_oid);
7867fb51846SDavid C Somayajulu
7877fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
7887fb51846SDavid C Somayajulu OID_AUTO, "intr_count",
7897fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.sds[i].intr_count,
7907fb51846SDavid C Somayajulu "intr_count");
7917fb51846SDavid C Somayajulu
7927fb51846SDavid C Somayajulu SYSCTL_ADD_UINT(ctx, node_children,
7937fb51846SDavid C Somayajulu OID_AUTO, "rx_free",
7947fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.sds[i].rx_free,
7957fb51846SDavid C Somayajulu ha->hw.sds[i].rx_free, "rx_free");
7967fb51846SDavid C Somayajulu }
7977fb51846SDavid C Somayajulu
7987fb51846SDavid C Somayajulu return;
7997fb51846SDavid C Somayajulu }
8007fb51846SDavid C Somayajulu static void
qlnx_add_drvr_rds_stats(qla_host_t * ha)8017fb51846SDavid C Somayajulu qlnx_add_drvr_rds_stats(qla_host_t *ha)
8027fb51846SDavid C Somayajulu {
8037fb51846SDavid C Somayajulu struct sysctl_ctx_list *ctx;
8047fb51846SDavid C Somayajulu struct sysctl_oid_list *children;
8057fb51846SDavid C Somayajulu struct sysctl_oid_list *node_children;
8067fb51846SDavid C Somayajulu struct sysctl_oid *ctx_oid;
8077fb51846SDavid C Somayajulu int i;
8087fb51846SDavid C Somayajulu uint8_t name_str[16];
8097fb51846SDavid C Somayajulu
8107fb51846SDavid C Somayajulu ctx = device_get_sysctl_ctx(ha->pci_dev);
8117fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
8127fb51846SDavid C Somayajulu
8137fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_rds",
8147029da5cSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_drvr_rds");
8157fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(ctx_oid);
8167fb51846SDavid C Somayajulu
8177fb51846SDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) {
8187fb51846SDavid C Somayajulu bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
8197fb51846SDavid C Somayajulu snprintf(name_str, sizeof(name_str), "%d", i);
8207fb51846SDavid C Somayajulu
8217fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
8227029da5cSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, name_str);
8237fb51846SDavid C Somayajulu node_children = SYSCTL_CHILDREN(ctx_oid);
8247fb51846SDavid C Somayajulu
8257fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
8267fb51846SDavid C Somayajulu OID_AUTO, "count",
8277fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rds[i].count,
8287fb51846SDavid C Somayajulu "count");
8297fb51846SDavid C Somayajulu
8307fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
8317fb51846SDavid C Somayajulu OID_AUTO, "lro_pkt_count",
8327fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rds[i].lro_pkt_count,
8337fb51846SDavid C Somayajulu "lro_pkt_count");
8347fb51846SDavid C Somayajulu
8357fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
8367fb51846SDavid C Somayajulu OID_AUTO, "lro_bytes",
8377fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rds[i].lro_bytes,
8387fb51846SDavid C Somayajulu "lro_bytes");
8397fb51846SDavid C Somayajulu }
8407fb51846SDavid C Somayajulu
8417fb51846SDavid C Somayajulu return;
8427fb51846SDavid C Somayajulu }
8437fb51846SDavid C Somayajulu
8447fb51846SDavid C Somayajulu static void
qlnx_add_drvr_tx_stats(qla_host_t * ha)8457fb51846SDavid C Somayajulu qlnx_add_drvr_tx_stats(qla_host_t *ha)
8467fb51846SDavid C Somayajulu {
8477fb51846SDavid C Somayajulu struct sysctl_ctx_list *ctx;
8487fb51846SDavid C Somayajulu struct sysctl_oid_list *children;
8497fb51846SDavid C Somayajulu struct sysctl_oid_list *node_children;
8507fb51846SDavid C Somayajulu struct sysctl_oid *ctx_oid;
8517fb51846SDavid C Somayajulu int i;
8527fb51846SDavid C Somayajulu uint8_t name_str[16];
8537fb51846SDavid C Somayajulu
8547fb51846SDavid C Somayajulu ctx = device_get_sysctl_ctx(ha->pci_dev);
8557fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
8567fb51846SDavid C Somayajulu
8577fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_xmt",
8587029da5cSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "stats_drvr_xmt");
8597fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(ctx_oid);
8607fb51846SDavid C Somayajulu
8617fb51846SDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) {
8627fb51846SDavid C Somayajulu bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
8637fb51846SDavid C Somayajulu snprintf(name_str, sizeof(name_str), "%d", i);
8647fb51846SDavid C Somayajulu
8657fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
8667029da5cSPawel Biernacki CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, name_str);
8677fb51846SDavid C Somayajulu node_children = SYSCTL_CHILDREN(ctx_oid);
8687fb51846SDavid C Somayajulu
8697fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
8707fb51846SDavid C Somayajulu OID_AUTO, "count",
8717fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->tx_ring[i].count,
8727fb51846SDavid C Somayajulu "count");
8737fb51846SDavid C Somayajulu
8747fb51846SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV
8757fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children,
8767fb51846SDavid C Somayajulu OID_AUTO, "iscsi_pkt_count",
8777fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->tx_ring[i].iscsi_pkt_count,
8787fb51846SDavid C Somayajulu "iscsi_pkt_count");
8797fb51846SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
8807fb51846SDavid C Somayajulu }
8817fb51846SDavid C Somayajulu
8827fb51846SDavid C Somayajulu return;
8837fb51846SDavid C Somayajulu }
8847fb51846SDavid C Somayajulu
8857fb51846SDavid C Somayajulu static void
qlnx_add_drvr_stats_sysctls(qla_host_t * ha)8867fb51846SDavid C Somayajulu qlnx_add_drvr_stats_sysctls(qla_host_t *ha)
8877fb51846SDavid C Somayajulu {
8887fb51846SDavid C Somayajulu qlnx_add_drvr_sds_stats(ha);
8897fb51846SDavid C Somayajulu qlnx_add_drvr_rds_stats(ha);
8907fb51846SDavid C Somayajulu qlnx_add_drvr_tx_stats(ha);
8917fb51846SDavid C Somayajulu return;
8927fb51846SDavid C Somayajulu }
89300caeec7SDavid C Somayajulu
894f10a77bbSDavid C Somayajulu /*
895f10a77bbSDavid C Somayajulu * Name: ql_hw_add_sysctls
896f10a77bbSDavid C Somayajulu * Function: Add P3Plus specific sysctls
897f10a77bbSDavid C Somayajulu */
898f10a77bbSDavid C Somayajulu void
ql_hw_add_sysctls(qla_host_t * ha)899f10a77bbSDavid C Somayajulu ql_hw_add_sysctls(qla_host_t *ha)
900f10a77bbSDavid C Somayajulu {
901f10a77bbSDavid C Somayajulu device_t dev;
902f10a77bbSDavid C Somayajulu
903f10a77bbSDavid C Somayajulu dev = ha->pci_dev;
904f10a77bbSDavid C Somayajulu
905f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
906f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
907f10a77bbSDavid C Somayajulu OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings,
908f10a77bbSDavid C Somayajulu ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings");
909f10a77bbSDavid C Somayajulu
910f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
911f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
912f10a77bbSDavid C Somayajulu OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings,
913f10a77bbSDavid C Somayajulu ha->hw.num_sds_rings, "Number of Status Descriptor Rings");
914f10a77bbSDavid C Somayajulu
915f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
916f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
917f10a77bbSDavid C Somayajulu OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings,
918f10a77bbSDavid C Somayajulu ha->hw.num_tx_rings, "Number of Transmit Rings");
919f10a77bbSDavid C Somayajulu
920f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
921f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
922f10a77bbSDavid C Somayajulu OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx,
923f10a77bbSDavid C Somayajulu ha->txr_idx, "Tx Ring Used");
924f10a77bbSDavid C Somayajulu
925f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
926f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
927f10a77bbSDavid C Somayajulu OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs,
928f10a77bbSDavid C Somayajulu ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt");
929f10a77bbSDavid C Somayajulu
930f10a77bbSDavid C Somayajulu ha->hw.sds_cidx_thres = 32;
931f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
932f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
933f10a77bbSDavid C Somayajulu OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres,
934f10a77bbSDavid C Somayajulu ha->hw.sds_cidx_thres,
935f10a77bbSDavid C Somayajulu "Number of SDS entries to process before updating"
936f10a77bbSDavid C Somayajulu " SDS Ring Consumer Index");
937f10a77bbSDavid C Somayajulu
938f10a77bbSDavid C Somayajulu ha->hw.rds_pidx_thres = 32;
939f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
940f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
941f10a77bbSDavid C Somayajulu OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres,
942f10a77bbSDavid C Somayajulu ha->hw.rds_pidx_thres,
943f10a77bbSDavid C Somayajulu "Number of Rcv Rings Entries to post before updating"
944f10a77bbSDavid C Somayajulu " RDS Ring Producer Index");
945f10a77bbSDavid C Somayajulu
94635291c22SDavid C Somayajulu ha->hw.rcv_intr_coalesce = (3 << 16) | 256;
947c12c5bfbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
948c12c5bfbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
94935291c22SDavid C Somayajulu OID_AUTO, "rcv_intr_coalesce", CTLFLAG_RW,
95035291c22SDavid C Somayajulu &ha->hw.rcv_intr_coalesce,
95135291c22SDavid C Somayajulu ha->hw.rcv_intr_coalesce,
95235291c22SDavid C Somayajulu "Rcv Intr Coalescing Parameters\n"
95335291c22SDavid C Somayajulu "\tbits 15:0 max packets\n"
95435291c22SDavid C Somayajulu "\tbits 31:16 max micro-seconds to wait\n"
95535291c22SDavid C Somayajulu "\tplease run\n"
95635291c22SDavid C Somayajulu "\tifconfig <if> down && ifconfig <if> up\n"
95735291c22SDavid C Somayajulu "\tto take effect \n");
95835291c22SDavid C Somayajulu
95935291c22SDavid C Somayajulu ha->hw.xmt_intr_coalesce = (64 << 16) | 64;
96035291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
96135291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
96235291c22SDavid C Somayajulu OID_AUTO, "xmt_intr_coalesce", CTLFLAG_RW,
96335291c22SDavid C Somayajulu &ha->hw.xmt_intr_coalesce,
96435291c22SDavid C Somayajulu ha->hw.xmt_intr_coalesce,
96535291c22SDavid C Somayajulu "Xmt Intr Coalescing Parameters\n"
96635291c22SDavid C Somayajulu "\tbits 15:0 max packets\n"
96735291c22SDavid C Somayajulu "\tbits 31:16 max micro-seconds to wait\n"
96835291c22SDavid C Somayajulu "\tplease run\n"
96935291c22SDavid C Somayajulu "\tifconfig <if> down && ifconfig <if> up\n"
97035291c22SDavid C Somayajulu "\tto take effect \n");
97135291c22SDavid C Somayajulu
97235291c22SDavid C Somayajulu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
9737029da5cSPawel Biernacki SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
9747029da5cSPawel Biernacki "port_cfg", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
9757029da5cSPawel Biernacki (void *)ha, 0, qla_sysctl_port_cfg, "I",
97635291c22SDavid C Somayajulu "Set Port Configuration if values below "
97735291c22SDavid C Somayajulu "otherwise Get Port Configuration\n"
97835291c22SDavid C Somayajulu "\tBits 0-3 ; 1 = DCBX Enable; 0 = DCBX Disable\n"
97935291c22SDavid C Somayajulu "\tBits 4-7 : 0 = no pause; 1 = std ; 2 = ppm \n"
98035291c22SDavid C Somayajulu "\tBits 8-11: std pause cfg; 0 = xmt and rcv;"
9817029da5cSPawel Biernacki " 1 = xmt only; 2 = rcv only;\n");
98235291c22SDavid C Somayajulu
98300caeec7SDavid C Somayajulu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
9847029da5cSPawel Biernacki SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
9857029da5cSPawel Biernacki "set_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
9867029da5cSPawel Biernacki (void *)ha, 0, qla_sysctl_set_cam_search_mode, "I",
98700caeec7SDavid C Somayajulu "Set CAM Search Mode"
98800caeec7SDavid C Somayajulu "\t 1 = search mode internal\n"
98900caeec7SDavid C Somayajulu "\t 2 = search mode auto\n");
99000caeec7SDavid C Somayajulu
99100caeec7SDavid C Somayajulu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
9927029da5cSPawel Biernacki SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
9937029da5cSPawel Biernacki "get_cam_search_mode",
9947029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, (void *)ha, 0,
99500caeec7SDavid C Somayajulu qla_sysctl_get_cam_search_mode, "I",
99600caeec7SDavid C Somayajulu "Get CAM Search Mode"
99700caeec7SDavid C Somayajulu "\t 1 = search mode internal\n"
99800caeec7SDavid C Somayajulu "\t 2 = search mode auto\n");
99900caeec7SDavid C Somayajulu
100035291c22SDavid C Somayajulu ha->hw.enable_9kb = 1;
100135291c22SDavid C Somayajulu
100235291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
100335291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
100435291c22SDavid C Somayajulu OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb,
100535291c22SDavid C Somayajulu ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000");
1006c12c5bfbSDavid C Somayajulu
1007a7c62c11SDavid C Somayajulu ha->hw.enable_hw_lro = 1;
1008a7c62c11SDavid C Somayajulu
1009a7c62c11SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1010a7c62c11SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1011a7c62c11SDavid C Somayajulu OID_AUTO, "enable_hw_lro", CTLFLAG_RW, &ha->hw.enable_hw_lro,
1012a7c62c11SDavid C Somayajulu ha->hw.enable_hw_lro, "Enable Hardware LRO; Default is true \n"
1013a7c62c11SDavid C Somayajulu "\t 1 : Hardware LRO if LRO is enabled\n"
1014a7c62c11SDavid C Somayajulu "\t 0 : Software LRO if LRO is enabled\n"
1015a7c62c11SDavid C Somayajulu "\t Any change requires ifconfig down/up to take effect\n"
1016a7c62c11SDavid C Somayajulu "\t Note that LRO may be turned off/on via ifconfig\n");
1017a7c62c11SDavid C Somayajulu
1018b65c0c07SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1019b65c0c07SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1020b65c0c07SDavid C Somayajulu OID_AUTO, "sp_log_index", CTLFLAG_RW, &ha->hw.sp_log_index,
1021b65c0c07SDavid C Somayajulu ha->hw.sp_log_index, "sp_log_index");
1022b65c0c07SDavid C Somayajulu
1023b65c0c07SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1024b65c0c07SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1025b65c0c07SDavid C Somayajulu OID_AUTO, "sp_log_stop", CTLFLAG_RW, &ha->hw.sp_log_stop,
1026b65c0c07SDavid C Somayajulu ha->hw.sp_log_stop, "sp_log_stop");
1027b65c0c07SDavid C Somayajulu
1028b65c0c07SDavid C Somayajulu ha->hw.sp_log_stop_events = 0;
1029b65c0c07SDavid 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_stop_events", CTLFLAG_RW,
1033b65c0c07SDavid C Somayajulu &ha->hw.sp_log_stop_events,
1034b65c0c07SDavid C Somayajulu ha->hw.sp_log_stop_events, "Slow path event log is stopped"
1035b65c0c07SDavid C Somayajulu " when OR of the following events occur \n"
1036b65c0c07SDavid C Somayajulu "\t 0x01 : Heart beat Failure\n"
1037b65c0c07SDavid C Somayajulu "\t 0x02 : Temperature Failure\n"
1038b65c0c07SDavid C Somayajulu "\t 0x04 : HW Initialization Failure\n"
1039b65c0c07SDavid C Somayajulu "\t 0x08 : Interface Initialization Failure\n"
1040b65c0c07SDavid C Somayajulu "\t 0x10 : Error Recovery Failure\n");
1041b65c0c07SDavid C Somayajulu
1042f10a77bbSDavid C Somayajulu ha->hw.mdump_active = 0;
1043f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1044f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1045f10a77bbSDavid C Somayajulu OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active,
1046f10a77bbSDavid C Somayajulu ha->hw.mdump_active,
10476a62bec0SDavid C Somayajulu "Minidump retrieval is Active");
1048f10a77bbSDavid C Somayajulu
10496a62bec0SDavid C Somayajulu ha->hw.mdump_done = 0;
1050f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1051f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
10526a62bec0SDavid C Somayajulu OID_AUTO, "mdump_done", CTLFLAG_RW,
10536a62bec0SDavid C Somayajulu &ha->hw.mdump_done, ha->hw.mdump_done,
10546a62bec0SDavid C Somayajulu "Minidump has been done and available for retrieval");
10556a62bec0SDavid C Somayajulu
10566a62bec0SDavid C Somayajulu ha->hw.mdump_capture_mask = 0xF;
10576a62bec0SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
10586a62bec0SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
10596a62bec0SDavid C Somayajulu OID_AUTO, "minidump_capture_mask", CTLFLAG_RW,
10606a62bec0SDavid C Somayajulu &ha->hw.mdump_capture_mask, ha->hw.mdump_capture_mask,
10616a62bec0SDavid C Somayajulu "Minidump capture mask");
1062f10a77bbSDavid C Somayajulu #ifdef QL_DBG
1063f10a77bbSDavid C Somayajulu
1064467dcb5aSDavid C Somayajulu ha->err_inject = 0;
1065f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1066f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1067f10a77bbSDavid C Somayajulu OID_AUTO, "err_inject",
1068f10a77bbSDavid C Somayajulu CTLFLAG_RW, &ha->err_inject, ha->err_inject,
1069f10a77bbSDavid C Somayajulu "Error to be injected\n"
1070f10a77bbSDavid C Somayajulu "\t\t\t 0: No Errors\n"
1071f10a77bbSDavid C Somayajulu "\t\t\t 1: rcv: rxb struct invalid\n"
1072f10a77bbSDavid C Somayajulu "\t\t\t 2: rcv: mp == NULL\n"
1073f10a77bbSDavid C Somayajulu "\t\t\t 3: lro: rxb struct invalid\n"
1074f10a77bbSDavid C Somayajulu "\t\t\t 4: lro: mp == NULL\n"
1075f10a77bbSDavid C Somayajulu "\t\t\t 5: rcv: num handles invalid\n"
1076f10a77bbSDavid C Somayajulu "\t\t\t 6: reg: indirect reg rd_wr failure\n"
1077f10a77bbSDavid C Somayajulu "\t\t\t 7: ocm: offchip memory rd_wr failure\n"
1078f10a77bbSDavid C Somayajulu "\t\t\t 8: mbx: mailbox command failure\n"
1079f10a77bbSDavid C Somayajulu "\t\t\t 9: heartbeat failure\n"
108000caeec7SDavid C Somayajulu "\t\t\t A: temperature failure\n"
1081971e53c9SDavid C Somayajulu "\t\t\t 11: m_getcl or m_getjcl failure\n"
1082971e53c9SDavid C Somayajulu "\t\t\t 13: Invalid Descriptor Count in SGL Receive\n"
1083971e53c9SDavid C Somayajulu "\t\t\t 14: Invalid Descriptor Count in LRO Receive\n"
1084971e53c9SDavid C Somayajulu "\t\t\t 15: peer port error recovery failure\n"
1085971e53c9SDavid C Somayajulu "\t\t\t 16: tx_buf[next_prod_index].mbuf != NULL\n" );
1086f10a77bbSDavid C Somayajulu
1087f10a77bbSDavid C Somayajulu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
10887029da5cSPawel Biernacki SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
10897029da5cSPawel Biernacki "peg_stop", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
10907029da5cSPawel Biernacki (void *)ha, 0, qla_sysctl_stop_pegs, "I", "Peg Stop");
1091f10a77bbSDavid C Somayajulu
1092f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */
1093f10a77bbSDavid C Somayajulu
109435291c22SDavid C Somayajulu ha->hw.user_pri_nic = 0;
109535291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
109635291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
109735291c22SDavid C Somayajulu OID_AUTO, "user_pri_nic", CTLFLAG_RW, &ha->hw.user_pri_nic,
109835291c22SDavid C Somayajulu ha->hw.user_pri_nic,
109935291c22SDavid C Somayajulu "VLAN Tag User Priority for Normal Ethernet Packets");
110035291c22SDavid C Somayajulu
110135291c22SDavid C Somayajulu ha->hw.user_pri_iscsi = 4;
110235291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
110335291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
110435291c22SDavid C Somayajulu OID_AUTO, "user_pri_iscsi", CTLFLAG_RW, &ha->hw.user_pri_iscsi,
110535291c22SDavid C Somayajulu ha->hw.user_pri_iscsi,
110635291c22SDavid C Somayajulu "VLAN Tag User Priority for iSCSI Packets");
110735291c22SDavid C Somayajulu
11087fb51846SDavid C Somayajulu qlnx_add_hw_stats_sysctls(ha);
11097fb51846SDavid C Somayajulu qlnx_add_drvr_stats_sysctls(ha);
11107fb51846SDavid C Somayajulu
11117fb51846SDavid C Somayajulu return;
1112f10a77bbSDavid C Somayajulu }
1113f10a77bbSDavid C Somayajulu
1114f10a77bbSDavid C Somayajulu void
ql_hw_link_status(qla_host_t * ha)1115f10a77bbSDavid C Somayajulu ql_hw_link_status(qla_host_t *ha)
1116f10a77bbSDavid C Somayajulu {
1117f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui);
1118f10a77bbSDavid C Somayajulu
1119f10a77bbSDavid C Somayajulu if (ha->hw.link_up) {
1120f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link Up\n");
1121f10a77bbSDavid C Somayajulu } else {
1122f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link Down\n");
1123f10a77bbSDavid C Somayajulu }
1124f10a77bbSDavid C Somayajulu
1125b65c0c07SDavid C Somayajulu if (ha->hw.fduplex) {
1126f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Full Duplex\n");
1127f10a77bbSDavid C Somayajulu } else {
1128f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Half Duplex\n");
1129f10a77bbSDavid C Somayajulu }
1130f10a77bbSDavid C Somayajulu
1131b65c0c07SDavid C Somayajulu if (ha->hw.autoneg) {
1132f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Auto Negotiation Enabled\n");
1133f10a77bbSDavid C Somayajulu } else {
1134f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Auto Negotiation Disabled\n");
1135f10a77bbSDavid C Somayajulu }
1136f10a77bbSDavid C Somayajulu
1137f10a77bbSDavid C Somayajulu switch (ha->hw.link_speed) {
1138f10a77bbSDavid C Somayajulu case 0x710:
1139f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t 10Gps\n");
1140f10a77bbSDavid C Somayajulu break;
1141f10a77bbSDavid C Somayajulu
1142f10a77bbSDavid C Somayajulu case 0x3E8:
1143f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t 1Gps\n");
1144f10a77bbSDavid C Somayajulu break;
1145f10a77bbSDavid C Somayajulu
1146f10a77bbSDavid C Somayajulu case 0x64:
1147f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n");
1148f10a77bbSDavid C Somayajulu break;
1149f10a77bbSDavid C Somayajulu
1150f10a77bbSDavid C Somayajulu default:
1151f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t Unknown\n");
1152f10a77bbSDavid C Somayajulu break;
1153f10a77bbSDavid C Somayajulu }
1154f10a77bbSDavid C Somayajulu
1155f10a77bbSDavid C Somayajulu switch (ha->hw.module_type) {
1156f10a77bbSDavid C Somayajulu case 0x01:
1157f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n");
1158f10a77bbSDavid C Somayajulu break;
1159f10a77bbSDavid C Somayajulu
1160f10a77bbSDavid C Somayajulu case 0x02:
1161f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GBase-LR\n");
1162f10a77bbSDavid C Somayajulu break;
1163f10a77bbSDavid C Somayajulu
1164f10a77bbSDavid C Somayajulu case 0x03:
1165f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GBase-SR\n");
1166f10a77bbSDavid C Somayajulu break;
1167f10a77bbSDavid C Somayajulu
1168f10a77bbSDavid C Somayajulu case 0x04:
1169f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev,
1170f10a77bbSDavid C Somayajulu "Module Type 10GE Passive Copper(Compliant)[%d m]\n",
1171f10a77bbSDavid C Somayajulu ha->hw.cable_length);
1172f10a77bbSDavid C Somayajulu break;
1173f10a77bbSDavid C Somayajulu
1174f10a77bbSDavid C Somayajulu case 0x05:
1175f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GE Active"
1176f10a77bbSDavid C Somayajulu " Limiting Copper(Compliant)[%d m]\n",
1177f10a77bbSDavid C Somayajulu ha->hw.cable_length);
1178f10a77bbSDavid C Somayajulu break;
1179f10a77bbSDavid C Somayajulu
1180f10a77bbSDavid C Somayajulu case 0x06:
1181f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev,
1182f10a77bbSDavid C Somayajulu "Module Type 10GE Passive Copper"
1183f10a77bbSDavid C Somayajulu " (Legacy, Best Effort)[%d m]\n",
1184f10a77bbSDavid C Somayajulu ha->hw.cable_length);
1185f10a77bbSDavid C Somayajulu break;
1186f10a77bbSDavid C Somayajulu
1187f10a77bbSDavid C Somayajulu case 0x07:
1188f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-SX\n");
1189f10a77bbSDavid C Somayajulu break;
1190f10a77bbSDavid C Somayajulu
1191f10a77bbSDavid C Somayajulu case 0x08:
1192f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-LX\n");
1193f10a77bbSDavid C Somayajulu break;
1194f10a77bbSDavid C Somayajulu
1195f10a77bbSDavid C Somayajulu case 0x09:
1196f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-CX\n");
1197f10a77bbSDavid C Somayajulu break;
1198f10a77bbSDavid C Somayajulu
1199f10a77bbSDavid C Somayajulu case 0x0A:
1200f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-T\n");
1201f10a77bbSDavid C Somayajulu break;
1202f10a77bbSDavid C Somayajulu
1203f10a77bbSDavid C Somayajulu case 0x0B:
1204f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1GE Passive Copper"
1205f10a77bbSDavid C Somayajulu "(Legacy, Best Effort)\n");
1206f10a77bbSDavid C Somayajulu break;
1207f10a77bbSDavid C Somayajulu
1208f10a77bbSDavid C Somayajulu default:
1209f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n",
1210f10a77bbSDavid C Somayajulu ha->hw.module_type);
1211f10a77bbSDavid C Somayajulu break;
1212f10a77bbSDavid C Somayajulu }
1213f10a77bbSDavid C Somayajulu
1214f10a77bbSDavid C Somayajulu if (ha->hw.link_faults == 1)
1215f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "SFP Power Fault\n");
1216f10a77bbSDavid C Somayajulu }
1217f10a77bbSDavid C Somayajulu
1218f10a77bbSDavid C Somayajulu /*
1219f10a77bbSDavid C Somayajulu * Name: ql_free_dma
1220f10a77bbSDavid C Somayajulu * Function: Frees the DMA'able memory allocated in ql_alloc_dma()
1221f10a77bbSDavid C Somayajulu */
1222f10a77bbSDavid C Somayajulu void
ql_free_dma(qla_host_t * ha)1223f10a77bbSDavid C Somayajulu ql_free_dma(qla_host_t *ha)
1224f10a77bbSDavid C Somayajulu {
1225f10a77bbSDavid C Somayajulu uint32_t i;
1226f10a77bbSDavid C Somayajulu
1227f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.sds_ring) {
1228f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) {
1229f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]);
1230f10a77bbSDavid C Somayajulu }
1231f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.sds_ring = 0;
1232f10a77bbSDavid C Somayajulu }
1233f10a77bbSDavid C Somayajulu
1234f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.rds_ring) {
1235f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) {
1236f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]);
1237f10a77bbSDavid C Somayajulu }
1238f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.rds_ring = 0;
1239f10a77bbSDavid C Somayajulu }
1240f10a77bbSDavid C Somayajulu
1241f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.tx_ring) {
1242f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring);
1243f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.tx_ring = 0;
1244f10a77bbSDavid C Somayajulu }
12456a62bec0SDavid C Somayajulu ql_minidump_free(ha);
1246f10a77bbSDavid C Somayajulu }
1247f10a77bbSDavid C Somayajulu
1248f10a77bbSDavid C Somayajulu /*
1249f10a77bbSDavid C Somayajulu * Name: ql_alloc_dma
1250f10a77bbSDavid C Somayajulu * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts.
1251f10a77bbSDavid C Somayajulu */
1252f10a77bbSDavid C Somayajulu int
ql_alloc_dma(qla_host_t * ha)1253f10a77bbSDavid C Somayajulu ql_alloc_dma(qla_host_t *ha)
1254f10a77bbSDavid C Somayajulu {
1255f10a77bbSDavid C Somayajulu device_t dev;
1256f10a77bbSDavid C Somayajulu uint32_t i, j, size, tx_ring_size;
1257f10a77bbSDavid C Somayajulu qla_hw_t *hw;
1258f10a77bbSDavid C Somayajulu qla_hw_tx_cntxt_t *tx_cntxt;
1259f10a77bbSDavid C Somayajulu uint8_t *vaddr;
1260f10a77bbSDavid C Somayajulu bus_addr_t paddr;
1261f10a77bbSDavid C Somayajulu
1262f10a77bbSDavid C Somayajulu dev = ha->pci_dev;
1263f10a77bbSDavid C Somayajulu
1264f10a77bbSDavid C Somayajulu QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
1265f10a77bbSDavid C Somayajulu
1266f10a77bbSDavid C Somayajulu hw = &ha->hw;
1267f10a77bbSDavid C Somayajulu /*
1268f10a77bbSDavid C Somayajulu * Allocate Transmit Ring
1269f10a77bbSDavid C Somayajulu */
1270f10a77bbSDavid C Somayajulu tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS);
1271f10a77bbSDavid C Somayajulu size = (tx_ring_size * ha->hw.num_tx_rings);
1272f10a77bbSDavid C Somayajulu
1273f10a77bbSDavid C Somayajulu hw->dma_buf.tx_ring.alignment = 8;
1274f10a77bbSDavid C Somayajulu hw->dma_buf.tx_ring.size = size + PAGE_SIZE;
1275f10a77bbSDavid C Somayajulu
1276f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) {
1277f10a77bbSDavid C Somayajulu device_printf(dev, "%s: tx ring alloc failed\n", __func__);
1278f10a77bbSDavid C Somayajulu goto ql_alloc_dma_exit;
1279f10a77bbSDavid C Somayajulu }
1280f10a77bbSDavid C Somayajulu
1281f10a77bbSDavid C Somayajulu vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b;
1282f10a77bbSDavid C Somayajulu paddr = hw->dma_buf.tx_ring.dma_addr;
1283f10a77bbSDavid C Somayajulu
1284f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) {
1285f10a77bbSDavid C Somayajulu tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
1286f10a77bbSDavid C Somayajulu
1287f10a77bbSDavid C Somayajulu tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr;
1288f10a77bbSDavid C Somayajulu tx_cntxt->tx_ring_paddr = paddr;
1289f10a77bbSDavid C Somayajulu
1290f10a77bbSDavid C Somayajulu vaddr += tx_ring_size;
1291f10a77bbSDavid C Somayajulu paddr += tx_ring_size;
1292f10a77bbSDavid C Somayajulu }
1293f10a77bbSDavid C Somayajulu
1294f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) {
1295f10a77bbSDavid C Somayajulu tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i];
1296f10a77bbSDavid C Somayajulu
1297f10a77bbSDavid C Somayajulu tx_cntxt->tx_cons = (uint32_t *)vaddr;
1298f10a77bbSDavid C Somayajulu tx_cntxt->tx_cons_paddr = paddr;
1299f10a77bbSDavid C Somayajulu
1300f10a77bbSDavid C Somayajulu vaddr += sizeof (uint32_t);
1301f10a77bbSDavid C Somayajulu paddr += sizeof (uint32_t);
1302f10a77bbSDavid C Somayajulu }
1303f10a77bbSDavid C Somayajulu
1304f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.tx_ring = 1;
1305f10a77bbSDavid C Somayajulu
1306f10a77bbSDavid C Somayajulu QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n",
1307f10a77bbSDavid C Somayajulu __func__, (void *)(hw->dma_buf.tx_ring.dma_addr),
1308f10a77bbSDavid C Somayajulu hw->dma_buf.tx_ring.dma_b));
1309f10a77bbSDavid C Somayajulu /*
1310f10a77bbSDavid C Somayajulu * Allocate Receive Descriptor Rings
1311f10a77bbSDavid C Somayajulu */
1312f10a77bbSDavid C Somayajulu
1313f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_rds_rings; i++) {
1314f10a77bbSDavid C Somayajulu hw->dma_buf.rds_ring[i].alignment = 8;
1315f10a77bbSDavid C Somayajulu hw->dma_buf.rds_ring[i].size =
1316f10a77bbSDavid C Somayajulu (sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS;
1317f10a77bbSDavid C Somayajulu
1318f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) {
1319f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rds ring[%d] alloc failed\n",
1320f10a77bbSDavid C Somayajulu __func__, i);
1321f10a77bbSDavid C Somayajulu
1322f10a77bbSDavid C Somayajulu for (j = 0; j < i; j++)
1323f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]);
1324f10a77bbSDavid C Somayajulu
1325f10a77bbSDavid C Somayajulu goto ql_alloc_dma_exit;
1326f10a77bbSDavid C Somayajulu }
1327f10a77bbSDavid C Somayajulu QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n",
1328f10a77bbSDavid C Somayajulu __func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr),
1329f10a77bbSDavid C Somayajulu hw->dma_buf.rds_ring[i].dma_b));
1330f10a77bbSDavid C Somayajulu }
1331f10a77bbSDavid C Somayajulu
1332f10a77bbSDavid C Somayajulu hw->dma_buf.flags.rds_ring = 1;
1333f10a77bbSDavid C Somayajulu
1334f10a77bbSDavid C Somayajulu /*
1335f10a77bbSDavid C Somayajulu * Allocate Status Descriptor Rings
1336f10a77bbSDavid C Somayajulu */
1337f10a77bbSDavid C Somayajulu
1338f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) {
1339f10a77bbSDavid C Somayajulu hw->dma_buf.sds_ring[i].alignment = 8;
1340f10a77bbSDavid C Somayajulu hw->dma_buf.sds_ring[i].size =
1341f10a77bbSDavid C Somayajulu (sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS;
1342f10a77bbSDavid C Somayajulu
1343f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) {
1344f10a77bbSDavid C Somayajulu device_printf(dev, "%s: sds ring alloc failed\n",
1345f10a77bbSDavid C Somayajulu __func__);
1346f10a77bbSDavid C Somayajulu
1347f10a77bbSDavid C Somayajulu for (j = 0; j < i; j++)
1348f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]);
1349f10a77bbSDavid C Somayajulu
1350f10a77bbSDavid C Somayajulu goto ql_alloc_dma_exit;
1351f10a77bbSDavid C Somayajulu }
1352f10a77bbSDavid C Somayajulu QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n",
1353f10a77bbSDavid C Somayajulu __func__, i,
1354f10a77bbSDavid C Somayajulu (void *)(hw->dma_buf.sds_ring[i].dma_addr),
1355f10a77bbSDavid C Somayajulu hw->dma_buf.sds_ring[i].dma_b));
1356f10a77bbSDavid C Somayajulu }
1357f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) {
1358f10a77bbSDavid C Somayajulu hw->sds[i].sds_ring_base =
1359f10a77bbSDavid C Somayajulu (q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b;
1360f10a77bbSDavid C Somayajulu }
1361f10a77bbSDavid C Somayajulu
1362f10a77bbSDavid C Somayajulu hw->dma_buf.flags.sds_ring = 1;
1363f10a77bbSDavid C Somayajulu
1364f10a77bbSDavid C Somayajulu return 0;
1365f10a77bbSDavid C Somayajulu
1366f10a77bbSDavid C Somayajulu ql_alloc_dma_exit:
1367f10a77bbSDavid C Somayajulu ql_free_dma(ha);
1368f10a77bbSDavid C Somayajulu return -1;
1369f10a77bbSDavid C Somayajulu }
1370f10a77bbSDavid C Somayajulu
1371f10a77bbSDavid C Somayajulu #define Q8_MBX_MSEC_DELAY 5000
1372f10a77bbSDavid C Somayajulu
1373f10a77bbSDavid C Somayajulu static int
qla_mbx_cmd(qla_host_t * ha,uint32_t * h_mbox,uint32_t n_hmbox,uint32_t * fw_mbox,uint32_t n_fwmbox,uint32_t no_pause)1374f10a77bbSDavid C Somayajulu qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox,
1375f10a77bbSDavid C Somayajulu uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause)
1376f10a77bbSDavid C Somayajulu {
1377f10a77bbSDavid C Somayajulu uint32_t i;
1378f10a77bbSDavid C Somayajulu uint32_t data;
1379f10a77bbSDavid C Somayajulu int ret = 0;
1380b65c0c07SDavid C Somayajulu uint64_t start_usecs;
1381b65c0c07SDavid C Somayajulu uint64_t end_usecs;
1382b65c0c07SDavid C Somayajulu uint64_t msecs_200;
1383f10a77bbSDavid C Somayajulu
1384b65c0c07SDavid C Somayajulu ql_sp_log(ha, 0, 5, no_pause, h_mbox[0], h_mbox[1], h_mbox[2], h_mbox[3]);
1385b65c0c07SDavid C Somayajulu
1386b65c0c07SDavid C Somayajulu if (ha->offline || ha->qla_initiate_recovery) {
1387b65c0c07SDavid C Somayajulu ql_sp_log(ha, 1, 2, ha->offline, ha->qla_initiate_recovery, 0, 0, 0);
1388f10a77bbSDavid C Somayajulu goto exit_qla_mbx_cmd;
1389f10a77bbSDavid C Somayajulu }
1390f10a77bbSDavid C Somayajulu
1391b65c0c07SDavid C Somayajulu if (((ha->err_inject & 0xFFFF) == INJCT_MBX_CMD_FAILURE) &&
1392b65c0c07SDavid C Somayajulu (((ha->err_inject & ~0xFFFF) == ((h_mbox[0] & 0xFFFF) << 16))||
1393b65c0c07SDavid C Somayajulu !(ha->err_inject & ~0xFFFF))) {
1394b65c0c07SDavid C Somayajulu ret = -3;
1395b65c0c07SDavid C Somayajulu QL_INITIATE_RECOVERY(ha);
1396b65c0c07SDavid C Somayajulu goto exit_qla_mbx_cmd;
1397b65c0c07SDavid C Somayajulu }
1398b65c0c07SDavid C Somayajulu
1399b65c0c07SDavid C Somayajulu start_usecs = qla_get_usec_timestamp();
1400b65c0c07SDavid C Somayajulu
1401f10a77bbSDavid C Somayajulu if (no_pause)
1402f10a77bbSDavid C Somayajulu i = 1000;
1403f10a77bbSDavid C Somayajulu else
1404f10a77bbSDavid C Somayajulu i = Q8_MBX_MSEC_DELAY;
1405f10a77bbSDavid C Somayajulu
1406f10a77bbSDavid C Somayajulu while (i) {
1407b65c0c07SDavid C Somayajulu if (ha->qla_initiate_recovery) {
1408b65c0c07SDavid C Somayajulu ql_sp_log(ha, 2, 1, ha->qla_initiate_recovery, 0, 0, 0, 0);
1409b65c0c07SDavid C Somayajulu return (-1);
1410b65c0c07SDavid C Somayajulu }
1411b65c0c07SDavid C Somayajulu
1412f10a77bbSDavid C Somayajulu data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL);
1413f10a77bbSDavid C Somayajulu if (data == 0)
1414f10a77bbSDavid C Somayajulu break;
1415f10a77bbSDavid C Somayajulu if (no_pause) {
1416f10a77bbSDavid C Somayajulu DELAY(1000);
1417f10a77bbSDavid C Somayajulu } else {
1418f10a77bbSDavid C Somayajulu qla_mdelay(__func__, 1);
1419f10a77bbSDavid C Somayajulu }
1420f10a77bbSDavid C Somayajulu i--;
1421f10a77bbSDavid C Somayajulu }
1422f10a77bbSDavid C Somayajulu
1423f10a77bbSDavid C Somayajulu if (i == 0) {
1424f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n",
1425f10a77bbSDavid C Somayajulu __func__, data);
1426b65c0c07SDavid C Somayajulu ql_sp_log(ha, 3, 1, data, 0, 0, 0, 0);
1427f10a77bbSDavid C Somayajulu ret = -1;
1428b65c0c07SDavid C Somayajulu ha->hw.mbx_comp_msecs[(Q8_MBX_COMP_MSECS - 2)]++;
1429b65c0c07SDavid C Somayajulu QL_INITIATE_RECOVERY(ha);
1430f10a77bbSDavid C Somayajulu goto exit_qla_mbx_cmd;
1431f10a77bbSDavid C Somayajulu }
1432f10a77bbSDavid C Somayajulu
1433f10a77bbSDavid C Somayajulu for (i = 0; i < n_hmbox; i++) {
1434f10a77bbSDavid C Somayajulu WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox);
1435f10a77bbSDavid C Somayajulu h_mbox++;
1436f10a77bbSDavid C Somayajulu }
1437f10a77bbSDavid C Somayajulu
1438f10a77bbSDavid C Somayajulu WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1);
1439f10a77bbSDavid C Somayajulu
1440f10a77bbSDavid C Somayajulu i = Q8_MBX_MSEC_DELAY;
1441f10a77bbSDavid C Somayajulu while (i) {
1442b65c0c07SDavid C Somayajulu if (ha->qla_initiate_recovery) {
1443b65c0c07SDavid C Somayajulu ql_sp_log(ha, 4, 1, ha->qla_initiate_recovery, 0, 0, 0, 0);
1444b65c0c07SDavid C Somayajulu return (-1);
1445b65c0c07SDavid C Somayajulu }
1446b65c0c07SDavid C Somayajulu
1447f10a77bbSDavid C Somayajulu data = READ_REG32(ha, Q8_FW_MBOX_CNTRL);
1448f10a77bbSDavid C Somayajulu
1449f10a77bbSDavid C Somayajulu if ((data & 0x3) == 1) {
1450f10a77bbSDavid C Somayajulu data = READ_REG32(ha, Q8_FW_MBOX0);
1451f10a77bbSDavid C Somayajulu if ((data & 0xF000) != 0x8000)
1452f10a77bbSDavid C Somayajulu break;
1453f10a77bbSDavid C Somayajulu }
1454f10a77bbSDavid C Somayajulu if (no_pause) {
1455f10a77bbSDavid C Somayajulu DELAY(1000);
1456f10a77bbSDavid C Somayajulu } else {
1457f10a77bbSDavid C Somayajulu qla_mdelay(__func__, 1);
1458f10a77bbSDavid C Somayajulu }
1459f10a77bbSDavid C Somayajulu i--;
1460f10a77bbSDavid C Somayajulu }
1461f10a77bbSDavid C Somayajulu if (i == 0) {
1462f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n",
1463f10a77bbSDavid C Somayajulu __func__, data);
1464b65c0c07SDavid C Somayajulu ql_sp_log(ha, 5, 1, data, 0, 0, 0, 0);
1465f10a77bbSDavid C Somayajulu ret = -2;
1466b65c0c07SDavid C Somayajulu ha->hw.mbx_comp_msecs[(Q8_MBX_COMP_MSECS - 1)]++;
1467b65c0c07SDavid C Somayajulu QL_INITIATE_RECOVERY(ha);
1468f10a77bbSDavid C Somayajulu goto exit_qla_mbx_cmd;
1469f10a77bbSDavid C Somayajulu }
1470f10a77bbSDavid C Somayajulu
1471f10a77bbSDavid C Somayajulu for (i = 0; i < n_fwmbox; i++) {
1472b65c0c07SDavid C Somayajulu if (ha->qla_initiate_recovery) {
1473b65c0c07SDavid C Somayajulu ql_sp_log(ha, 6, 1, ha->qla_initiate_recovery, 0, 0, 0, 0);
1474b65c0c07SDavid C Somayajulu return (-1);
1475b65c0c07SDavid C Somayajulu }
1476b65c0c07SDavid C Somayajulu
1477f10a77bbSDavid C Somayajulu *fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2)));
1478f10a77bbSDavid C Somayajulu }
1479f10a77bbSDavid C Somayajulu
1480f10a77bbSDavid C Somayajulu WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0);
1481f10a77bbSDavid C Somayajulu WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
1482f10a77bbSDavid C Somayajulu
1483b65c0c07SDavid C Somayajulu end_usecs = qla_get_usec_timestamp();
1484b65c0c07SDavid C Somayajulu
1485b65c0c07SDavid C Somayajulu if (end_usecs > start_usecs) {
1486b65c0c07SDavid C Somayajulu msecs_200 = (end_usecs - start_usecs)/(1000 * 200);
1487b65c0c07SDavid C Somayajulu
1488b65c0c07SDavid C Somayajulu if (msecs_200 < 15)
1489b65c0c07SDavid C Somayajulu ha->hw.mbx_comp_msecs[msecs_200]++;
1490b65c0c07SDavid C Somayajulu else if (msecs_200 < 20)
1491b65c0c07SDavid C Somayajulu ha->hw.mbx_comp_msecs[15]++;
1492b65c0c07SDavid C Somayajulu else {
1493b65c0c07SDavid C Somayajulu device_printf(ha->pci_dev, "%s: [%ld, %ld] %ld\n", __func__,
1494b65c0c07SDavid C Somayajulu start_usecs, end_usecs, msecs_200);
1495b65c0c07SDavid C Somayajulu ha->hw.mbx_comp_msecs[16]++;
1496b65c0c07SDavid C Somayajulu }
1497b65c0c07SDavid C Somayajulu }
1498b65c0c07SDavid C Somayajulu ql_sp_log(ha, 7, 5, fw_mbox[0], fw_mbox[1], fw_mbox[2], fw_mbox[3], fw_mbox[4]);
1499b65c0c07SDavid C Somayajulu
1500f10a77bbSDavid C Somayajulu exit_qla_mbx_cmd:
1501f10a77bbSDavid C Somayajulu return (ret);
1502f10a77bbSDavid C Somayajulu }
1503f10a77bbSDavid C Somayajulu
150435291c22SDavid C Somayajulu int
qla_get_nic_partition(qla_host_t * ha,uint32_t * supports_9kb,uint32_t * num_rcvq)150535291c22SDavid C Somayajulu qla_get_nic_partition(qla_host_t *ha, uint32_t *supports_9kb,
150635291c22SDavid C Somayajulu uint32_t *num_rcvq)
1507f10a77bbSDavid C Somayajulu {
1508f10a77bbSDavid C Somayajulu uint32_t *mbox, err;
1509f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
1510f10a77bbSDavid C Somayajulu
1511f10a77bbSDavid C Somayajulu bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX));
1512f10a77bbSDavid C Somayajulu
1513f10a77bbSDavid C Somayajulu mbox = ha->hw.mbox;
1514f10a77bbSDavid C Somayajulu
1515f10a77bbSDavid C Somayajulu mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29);
1516f10a77bbSDavid C Somayajulu
1517f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) {
1518f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__);
1519f10a77bbSDavid C Somayajulu return (-1);
1520f10a77bbSDavid C Somayajulu }
1521f10a77bbSDavid C Somayajulu err = mbox[0] >> 25;
1522f10a77bbSDavid C Somayajulu
152335291c22SDavid C Somayajulu if (supports_9kb != NULL) {
152435291c22SDavid C Somayajulu if (mbox[16] & 0x80) /* bit 7 of mbox 16 */
152535291c22SDavid C Somayajulu *supports_9kb = 1;
152635291c22SDavid C Somayajulu else
152735291c22SDavid C Somayajulu *supports_9kb = 0;
152835291c22SDavid C Somayajulu }
152935291c22SDavid C Somayajulu
153035291c22SDavid C Somayajulu if (num_rcvq != NULL)
153135291c22SDavid C Somayajulu *num_rcvq = ((mbox[6] >> 16) & 0xFFFF);
153235291c22SDavid C Somayajulu
1533f10a77bbSDavid C Somayajulu if ((err != 1) && (err != 0)) {
1534f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1535f10a77bbSDavid C Somayajulu return (-1);
1536f10a77bbSDavid C Somayajulu }
1537f10a77bbSDavid C Somayajulu return 0;
1538f10a77bbSDavid C Somayajulu }
1539f10a77bbSDavid C Somayajulu
1540f10a77bbSDavid C Somayajulu static int
qla_config_intr_cntxt(qla_host_t * ha,uint32_t start_idx,uint32_t num_intrs,uint32_t create)154135291c22SDavid C Somayajulu qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, uint32_t num_intrs,
154235291c22SDavid C Somayajulu uint32_t create)
1543f10a77bbSDavid C Somayajulu {
1544f10a77bbSDavid C Somayajulu uint32_t i, err;
1545f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
1546f10a77bbSDavid C Somayajulu q80_config_intr_t *c_intr;
1547f10a77bbSDavid C Somayajulu q80_config_intr_rsp_t *c_intr_rsp;
1548f10a77bbSDavid C Somayajulu
1549f10a77bbSDavid C Somayajulu c_intr = (q80_config_intr_t *)ha->hw.mbox;
1550f10a77bbSDavid C Somayajulu bzero(c_intr, (sizeof (q80_config_intr_t)));
1551f10a77bbSDavid C Somayajulu
1552f10a77bbSDavid C Somayajulu c_intr->opcode = Q8_MBX_CONFIG_INTR;
1553f10a77bbSDavid C Somayajulu
1554f10a77bbSDavid C Somayajulu c_intr->count_version = (sizeof (q80_config_intr_t) >> 2);
1555f10a77bbSDavid C Somayajulu c_intr->count_version |= Q8_MBX_CMD_VERSION;
1556f10a77bbSDavid C Somayajulu
1557f10a77bbSDavid C Somayajulu c_intr->nentries = num_intrs;
1558f10a77bbSDavid C Somayajulu
1559f10a77bbSDavid C Somayajulu for (i = 0; i < num_intrs; i++) {
1560f10a77bbSDavid C Somayajulu if (create) {
1561f10a77bbSDavid C Somayajulu c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE;
156235291c22SDavid C Somayajulu c_intr->intr[i].msix_index = start_idx + 1 + i;
1563f10a77bbSDavid C Somayajulu } else {
1564f10a77bbSDavid C Somayajulu c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE;
156535291c22SDavid C Somayajulu c_intr->intr[i].msix_index =
156635291c22SDavid C Somayajulu ha->hw.intr_id[(start_idx + i)];
1567f10a77bbSDavid C Somayajulu }
1568f10a77bbSDavid C Somayajulu
1569f10a77bbSDavid C Somayajulu c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X;
1570f10a77bbSDavid C Somayajulu }
1571f10a77bbSDavid C Somayajulu
1572f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)c_intr,
1573f10a77bbSDavid C Somayajulu (sizeof (q80_config_intr_t) >> 2),
1574f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) {
1575b65c0c07SDavid C Somayajulu device_printf(dev, "%s: %s failed0\n", __func__,
1576b65c0c07SDavid C Somayajulu (create ? "create" : "delete"));
1577f10a77bbSDavid C Somayajulu return (-1);
1578f10a77bbSDavid C Somayajulu }
1579f10a77bbSDavid C Somayajulu
1580f10a77bbSDavid C Somayajulu c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox;
1581f10a77bbSDavid C Somayajulu
1582f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status);
1583f10a77bbSDavid C Somayajulu
1584f10a77bbSDavid C Somayajulu if (err) {
1585b65c0c07SDavid C Somayajulu device_printf(dev, "%s: %s failed1 [0x%08x, %d]\n", __func__,
1586b65c0c07SDavid C Somayajulu (create ? "create" : "delete"), err, c_intr_rsp->nentries);
1587f10a77bbSDavid C Somayajulu
1588f10a77bbSDavid C Somayajulu for (i = 0; i < c_intr_rsp->nentries; i++) {
1589f10a77bbSDavid C Somayajulu device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n",
1590f10a77bbSDavid C Somayajulu __func__, i,
1591f10a77bbSDavid C Somayajulu c_intr_rsp->intr[i].status,
1592f10a77bbSDavid C Somayajulu c_intr_rsp->intr[i].intr_id,
1593f10a77bbSDavid C Somayajulu c_intr_rsp->intr[i].intr_src);
1594f10a77bbSDavid C Somayajulu }
1595f10a77bbSDavid C Somayajulu
1596f10a77bbSDavid C Somayajulu return (-1);
1597f10a77bbSDavid C Somayajulu }
1598f10a77bbSDavid C Somayajulu
1599f10a77bbSDavid C Somayajulu for (i = 0; ((i < num_intrs) && create); i++) {
1600f10a77bbSDavid C Somayajulu if (!c_intr_rsp->intr[i].status) {
160135291c22SDavid C Somayajulu ha->hw.intr_id[(start_idx + i)] =
160235291c22SDavid C Somayajulu c_intr_rsp->intr[i].intr_id;
160335291c22SDavid C Somayajulu ha->hw.intr_src[(start_idx + i)] =
160435291c22SDavid C Somayajulu c_intr_rsp->intr[i].intr_src;
1605f10a77bbSDavid C Somayajulu }
1606f10a77bbSDavid C Somayajulu }
1607f10a77bbSDavid C Somayajulu
1608f10a77bbSDavid C Somayajulu return (0);
1609f10a77bbSDavid C Somayajulu }
1610f10a77bbSDavid C Somayajulu
1611f10a77bbSDavid C Somayajulu /*
1612f10a77bbSDavid C Somayajulu * Name: qla_config_rss
1613f10a77bbSDavid C Somayajulu * Function: Configure RSS for the context/interface.
1614f10a77bbSDavid C Somayajulu */
1615f10a77bbSDavid C Somayajulu static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL,
1616f10a77bbSDavid C Somayajulu 0x8030f20c77cb2da3ULL,
1617f10a77bbSDavid C Somayajulu 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
1618f10a77bbSDavid C Somayajulu 0x255b0ec26d5a56daULL };
1619f10a77bbSDavid C Somayajulu
1620f10a77bbSDavid C Somayajulu static int
qla_config_rss(qla_host_t * ha,uint16_t cntxt_id)1621f10a77bbSDavid C Somayajulu qla_config_rss(qla_host_t *ha, uint16_t cntxt_id)
1622f10a77bbSDavid C Somayajulu {
1623f10a77bbSDavid C Somayajulu q80_config_rss_t *c_rss;
1624f10a77bbSDavid C Somayajulu q80_config_rss_rsp_t *c_rss_rsp;
1625f10a77bbSDavid C Somayajulu uint32_t err, i;
1626f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
1627f10a77bbSDavid C Somayajulu
1628f10a77bbSDavid C Somayajulu c_rss = (q80_config_rss_t *)ha->hw.mbox;
1629f10a77bbSDavid C Somayajulu bzero(c_rss, (sizeof (q80_config_rss_t)));
1630f10a77bbSDavid C Somayajulu
1631f10a77bbSDavid C Somayajulu c_rss->opcode = Q8_MBX_CONFIG_RSS;
1632f10a77bbSDavid C Somayajulu
1633f10a77bbSDavid C Somayajulu c_rss->count_version = (sizeof (q80_config_rss_t) >> 2);
1634f10a77bbSDavid C Somayajulu c_rss->count_version |= Q8_MBX_CMD_VERSION;
1635f10a77bbSDavid C Somayajulu
1636f10a77bbSDavid C Somayajulu c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP |
1637f10a77bbSDavid C Somayajulu Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP);
163835291c22SDavid C Somayajulu //c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP |
163935291c22SDavid C Somayajulu // Q8_MBX_RSS_HASH_TYPE_IPV6_TCP);
1640f10a77bbSDavid C Somayajulu
1641f10a77bbSDavid C Somayajulu c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS;
1642f10a77bbSDavid C Somayajulu c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE;
1643f10a77bbSDavid C Somayajulu
1644f10a77bbSDavid C Somayajulu c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK;
1645f10a77bbSDavid C Somayajulu
1646f10a77bbSDavid C Somayajulu c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID;
1647f10a77bbSDavid C Somayajulu c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS;
1648f10a77bbSDavid C Somayajulu
1649f10a77bbSDavid C Somayajulu c_rss->cntxt_id = cntxt_id;
1650f10a77bbSDavid C Somayajulu
1651f10a77bbSDavid C Somayajulu for (i = 0; i < 5; i++) {
1652f10a77bbSDavid C Somayajulu c_rss->rss_key[i] = rss_key[i];
1653f10a77bbSDavid C Somayajulu }
1654f10a77bbSDavid C Somayajulu
1655f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)c_rss,
1656f10a77bbSDavid C Somayajulu (sizeof (q80_config_rss_t) >> 2),
1657f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) {
1658f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__);
1659f10a77bbSDavid C Somayajulu return (-1);
1660f10a77bbSDavid C Somayajulu }
1661f10a77bbSDavid C Somayajulu c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox;
1662f10a77bbSDavid C Somayajulu
1663f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status);
1664f10a77bbSDavid C Somayajulu
1665f10a77bbSDavid C Somayajulu if (err) {
1666f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1667f10a77bbSDavid C Somayajulu return (-1);
1668f10a77bbSDavid C Somayajulu }
1669f10a77bbSDavid C Somayajulu return 0;
1670f10a77bbSDavid C Somayajulu }
1671f10a77bbSDavid C Somayajulu
1672f10a77bbSDavid C Somayajulu static int
qla_set_rss_ind_table(qla_host_t * ha,uint32_t start_idx,uint32_t count,uint16_t cntxt_id,uint8_t * ind_table)1673f10a77bbSDavid C Somayajulu qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count,
1674f10a77bbSDavid C Somayajulu uint16_t cntxt_id, uint8_t *ind_table)
1675f10a77bbSDavid C Somayajulu {
1676f10a77bbSDavid C Somayajulu q80_config_rss_ind_table_t *c_rss_ind;
1677f10a77bbSDavid C Somayajulu q80_config_rss_ind_table_rsp_t *c_rss_ind_rsp;
1678f10a77bbSDavid C Somayajulu uint32_t err;
1679f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
1680f10a77bbSDavid C Somayajulu
1681f10a77bbSDavid C Somayajulu if ((count > Q8_RSS_IND_TBL_SIZE) ||
1682f10a77bbSDavid C Somayajulu ((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) {
1683f10a77bbSDavid C Somayajulu device_printf(dev, "%s: illegal count [%d, %d]\n", __func__,
1684f10a77bbSDavid C Somayajulu start_idx, count);
1685f10a77bbSDavid C Somayajulu return (-1);
1686f10a77bbSDavid C Somayajulu }
1687f10a77bbSDavid C Somayajulu
1688f10a77bbSDavid C Somayajulu c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox;
1689f10a77bbSDavid C Somayajulu bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t));
1690f10a77bbSDavid C Somayajulu
1691f10a77bbSDavid C Somayajulu c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE;
1692f10a77bbSDavid C Somayajulu c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2);
1693f10a77bbSDavid C Somayajulu c_rss_ind->count_version |= Q8_MBX_CMD_VERSION;
1694f10a77bbSDavid C Somayajulu
1695f10a77bbSDavid C Somayajulu c_rss_ind->start_idx = start_idx;
1696f10a77bbSDavid C Somayajulu c_rss_ind->end_idx = start_idx + count - 1;
1697f10a77bbSDavid C Somayajulu c_rss_ind->cntxt_id = cntxt_id;
1698f10a77bbSDavid C Somayajulu bcopy(ind_table, c_rss_ind->ind_table, count);
1699f10a77bbSDavid C Somayajulu
1700f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind,
1701f10a77bbSDavid C Somayajulu (sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox,
1702f10a77bbSDavid C Somayajulu (sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) {
1703f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__);
1704f10a77bbSDavid C Somayajulu return (-1);
1705f10a77bbSDavid C Somayajulu }
1706f10a77bbSDavid C Somayajulu
1707f10a77bbSDavid C Somayajulu c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox;
1708f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status);
1709f10a77bbSDavid C Somayajulu
1710f10a77bbSDavid C Somayajulu if (err) {
1711f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1712f10a77bbSDavid C Somayajulu return (-1);
1713f10a77bbSDavid C Somayajulu }
1714f10a77bbSDavid C Somayajulu return 0;
1715f10a77bbSDavid C Somayajulu }
1716f10a77bbSDavid C Somayajulu
1717f10a77bbSDavid C Somayajulu /*
1718f10a77bbSDavid C Somayajulu * Name: qla_config_intr_coalesce
1719f10a77bbSDavid C Somayajulu * Function: Configure Interrupt Coalescing.
1720f10a77bbSDavid C Somayajulu */
1721f10a77bbSDavid C Somayajulu static int
qla_config_intr_coalesce(qla_host_t * ha,uint16_t cntxt_id,int tenable,int rcv)172235291c22SDavid C Somayajulu qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable,
172335291c22SDavid C Somayajulu int rcv)
1724f10a77bbSDavid C Somayajulu {
1725f10a77bbSDavid C Somayajulu q80_config_intr_coalesc_t *intrc;
1726f10a77bbSDavid C Somayajulu q80_config_intr_coalesc_rsp_t *intrc_rsp;
1727f10a77bbSDavid C Somayajulu uint32_t err, i;
1728f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
1729f10a77bbSDavid C Somayajulu
1730f10a77bbSDavid C Somayajulu intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox;
1731f10a77bbSDavid C Somayajulu bzero(intrc, (sizeof (q80_config_intr_coalesc_t)));
1732f10a77bbSDavid C Somayajulu
1733f10a77bbSDavid C Somayajulu intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE;
1734f10a77bbSDavid C Somayajulu intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2);
1735f10a77bbSDavid C Somayajulu intrc->count_version |= Q8_MBX_CMD_VERSION;
1736f10a77bbSDavid C Somayajulu
173735291c22SDavid C Somayajulu if (rcv) {
1738f10a77bbSDavid C Somayajulu intrc->flags = Q8_MBX_INTRC_FLAGS_RCV;
173935291c22SDavid C Somayajulu intrc->max_pkts = ha->hw.rcv_intr_coalesce & 0xFFFF;
174035291c22SDavid C Somayajulu intrc->max_mswait = (ha->hw.rcv_intr_coalesce >> 16) & 0xFFFF;
174135291c22SDavid C Somayajulu } else {
174235291c22SDavid C Somayajulu intrc->flags = Q8_MBX_INTRC_FLAGS_XMT;
174335291c22SDavid C Somayajulu intrc->max_pkts = ha->hw.xmt_intr_coalesce & 0xFFFF;
174435291c22SDavid C Somayajulu intrc->max_mswait = (ha->hw.xmt_intr_coalesce >> 16) & 0xFFFF;
174535291c22SDavid C Somayajulu }
1746f10a77bbSDavid C Somayajulu
174735291c22SDavid C Somayajulu intrc->cntxt_id = cntxt_id;
1748f10a77bbSDavid C Somayajulu
1749f10a77bbSDavid C Somayajulu if (tenable) {
1750f10a77bbSDavid C Somayajulu intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC;
1751f10a77bbSDavid C Somayajulu intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC;
1752f10a77bbSDavid C Somayajulu
1753f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) {
1754f10a77bbSDavid C Somayajulu intrc->sds_ring_mask |= (1 << i);
1755f10a77bbSDavid C Somayajulu }
1756f10a77bbSDavid C Somayajulu intrc->ms_timeout = 1000;
1757f10a77bbSDavid C Somayajulu }
1758f10a77bbSDavid C Somayajulu
1759f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)intrc,
1760f10a77bbSDavid C Somayajulu (sizeof (q80_config_intr_coalesc_t) >> 2),
1761f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) {
1762f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__);
1763f10a77bbSDavid C Somayajulu return (-1);
1764f10a77bbSDavid C Somayajulu }
1765f10a77bbSDavid C Somayajulu intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox;
1766f10a77bbSDavid C Somayajulu
1767f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status);
1768f10a77bbSDavid C Somayajulu
1769f10a77bbSDavid C Somayajulu if (err) {
1770f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1771f10a77bbSDavid C Somayajulu return (-1);
1772f10a77bbSDavid C Somayajulu }
1773f10a77bbSDavid C Somayajulu
1774f10a77bbSDavid C Somayajulu return 0;
1775f10a77bbSDavid C Somayajulu }
1776f10a77bbSDavid C Somayajulu
1777f10a77bbSDavid C Somayajulu /*
1778f10a77bbSDavid C Somayajulu * Name: qla_config_mac_addr
1779f10a77bbSDavid C Somayajulu * Function: binds a MAC address to the context/interface.
1780f10a77bbSDavid C Somayajulu * Can be unicast, multicast or broadcast.
1781f10a77bbSDavid C Somayajulu */
1782f10a77bbSDavid C Somayajulu static int
qla_config_mac_addr(qla_host_t * ha,uint8_t * mac_addr,uint32_t add_mac,uint32_t num_mac)1783da834d52SDavid C Somayajulu qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac,
1784da834d52SDavid C Somayajulu uint32_t num_mac)
1785f10a77bbSDavid C Somayajulu {
1786f10a77bbSDavid C Somayajulu q80_config_mac_addr_t *cmac;
1787f10a77bbSDavid C Somayajulu q80_config_mac_addr_rsp_t *cmac_rsp;
1788f10a77bbSDavid C Somayajulu uint32_t err;
1789f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
1790da834d52SDavid C Somayajulu int i;
1791da834d52SDavid C Somayajulu uint8_t *mac_cpy = mac_addr;
1792da834d52SDavid C Somayajulu
1793da834d52SDavid C Somayajulu if (num_mac > Q8_MAX_MAC_ADDRS) {
1794da834d52SDavid C Somayajulu device_printf(dev, "%s: %s num_mac [0x%x] > Q8_MAX_MAC_ADDRS\n",
1795da834d52SDavid C Somayajulu __func__, (add_mac ? "Add" : "Del"), num_mac);
1796da834d52SDavid C Somayajulu return (-1);
1797da834d52SDavid C Somayajulu }
1798f10a77bbSDavid C Somayajulu
1799f10a77bbSDavid C Somayajulu cmac = (q80_config_mac_addr_t *)ha->hw.mbox;
1800f10a77bbSDavid C Somayajulu bzero(cmac, (sizeof (q80_config_mac_addr_t)));
1801f10a77bbSDavid C Somayajulu
1802f10a77bbSDavid C Somayajulu cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR;
1803f10a77bbSDavid C Somayajulu cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2;
1804f10a77bbSDavid C Somayajulu cmac->count_version |= Q8_MBX_CMD_VERSION;
1805f10a77bbSDavid C Somayajulu
1806f10a77bbSDavid C Somayajulu if (add_mac)
1807f10a77bbSDavid C Somayajulu cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR;
1808f10a77bbSDavid C Somayajulu else
1809f10a77bbSDavid C Somayajulu cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR;
1810f10a77bbSDavid C Somayajulu
1811f10a77bbSDavid C Somayajulu cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS;
1812f10a77bbSDavid C Somayajulu
1813da834d52SDavid C Somayajulu cmac->nmac_entries = num_mac;
1814f10a77bbSDavid C Somayajulu cmac->cntxt_id = ha->hw.rcv_cntxt_id;
1815da834d52SDavid C Somayajulu
1816da834d52SDavid C Somayajulu for (i = 0; i < num_mac; i++) {
1817da834d52SDavid C Somayajulu bcopy(mac_addr, cmac->mac_addr[i].addr, Q8_ETHER_ADDR_LEN);
1818da834d52SDavid C Somayajulu mac_addr = mac_addr + ETHER_ADDR_LEN;
1819da834d52SDavid C Somayajulu }
1820f10a77bbSDavid C Somayajulu
1821f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)cmac,
1822f10a77bbSDavid C Somayajulu (sizeof (q80_config_mac_addr_t) >> 2),
1823f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) {
1824f10a77bbSDavid C Somayajulu device_printf(dev, "%s: %s failed0\n", __func__,
1825f10a77bbSDavid C Somayajulu (add_mac ? "Add" : "Del"));
1826f10a77bbSDavid C Somayajulu return (-1);
1827f10a77bbSDavid C Somayajulu }
1828f10a77bbSDavid C Somayajulu cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox;
1829f10a77bbSDavid C Somayajulu
1830f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status);
1831f10a77bbSDavid C Somayajulu
1832f10a77bbSDavid C Somayajulu if (err) {
1833da834d52SDavid C Somayajulu device_printf(dev, "%s: %s failed1 [0x%08x]\n", __func__,
1834da834d52SDavid C Somayajulu (add_mac ? "Add" : "Del"), err);
1835da834d52SDavid C Somayajulu for (i = 0; i < num_mac; i++) {
1836da834d52SDavid C Somayajulu device_printf(dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
1837da834d52SDavid C Somayajulu __func__, mac_cpy[0], mac_cpy[1], mac_cpy[2],
1838da834d52SDavid C Somayajulu mac_cpy[3], mac_cpy[4], mac_cpy[5]);
1839da834d52SDavid C Somayajulu mac_cpy += ETHER_ADDR_LEN;
1840da834d52SDavid C Somayajulu }
1841f10a77bbSDavid C Somayajulu return (-1);
1842f10a77bbSDavid C Somayajulu }
1843f10a77bbSDavid C Somayajulu
1844f10a77bbSDavid C Somayajulu return 0;
1845f10a77bbSDavid C Somayajulu }
1846f10a77bbSDavid C Somayajulu
1847f10a77bbSDavid C Somayajulu /*
1848f10a77bbSDavid C Somayajulu * Name: qla_set_mac_rcv_mode
18496a62bec0SDavid C Somayajulu * Function: Enable/Disable AllMulticast and Promiscous Modes.
1850f10a77bbSDavid C Somayajulu */
1851f10a77bbSDavid C Somayajulu static int
qla_set_mac_rcv_mode(qla_host_t * ha,uint32_t mode)1852f10a77bbSDavid C Somayajulu qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode)
1853f10a77bbSDavid C Somayajulu {
1854f10a77bbSDavid C Somayajulu q80_config_mac_rcv_mode_t *rcv_mode;
1855f10a77bbSDavid C Somayajulu uint32_t err;
1856f10a77bbSDavid C Somayajulu q80_config_mac_rcv_mode_rsp_t *rcv_mode_rsp;
1857f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
1858f10a77bbSDavid C Somayajulu
1859f10a77bbSDavid C Somayajulu rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox;
1860f10a77bbSDavid C Somayajulu bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t)));
1861f10a77bbSDavid C Somayajulu
1862f10a77bbSDavid C Somayajulu rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE;
1863f10a77bbSDavid C Somayajulu rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2;
1864f10a77bbSDavid C Somayajulu rcv_mode->count_version |= Q8_MBX_CMD_VERSION;
1865f10a77bbSDavid C Somayajulu
1866f10a77bbSDavid C Somayajulu rcv_mode->mode = mode;
1867f10a77bbSDavid C Somayajulu
1868f10a77bbSDavid C Somayajulu rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id;
1869f10a77bbSDavid C Somayajulu
1870f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode,
1871f10a77bbSDavid C Somayajulu (sizeof (q80_config_mac_rcv_mode_t) >> 2),
1872f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) {
1873f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__);
1874f10a77bbSDavid C Somayajulu return (-1);
1875f10a77bbSDavid C Somayajulu }
1876f10a77bbSDavid C Somayajulu rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox;
1877f10a77bbSDavid C Somayajulu
1878f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status);
1879f10a77bbSDavid C Somayajulu
1880f10a77bbSDavid C Somayajulu if (err) {
1881f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
1882f10a77bbSDavid C Somayajulu return (-1);
1883f10a77bbSDavid C Somayajulu }
1884f10a77bbSDavid C Somayajulu
1885f10a77bbSDavid C Somayajulu return 0;
1886f10a77bbSDavid C Somayajulu }
1887f10a77bbSDavid C Somayajulu
1888f10a77bbSDavid C Somayajulu int
ql_set_promisc(qla_host_t * ha)1889f10a77bbSDavid C Somayajulu ql_set_promisc(qla_host_t *ha)
1890f10a77bbSDavid C Somayajulu {
1891f10a77bbSDavid C Somayajulu int ret;
1892f10a77bbSDavid C Somayajulu
1893f10a77bbSDavid C Somayajulu ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE;
1894f10a77bbSDavid C Somayajulu ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1895f10a77bbSDavid C Somayajulu return (ret);
1896f10a77bbSDavid C Somayajulu }
1897f10a77bbSDavid C Somayajulu
189835291c22SDavid C Somayajulu void
qla_reset_promisc(qla_host_t * ha)189935291c22SDavid C Somayajulu qla_reset_promisc(qla_host_t *ha)
190035291c22SDavid C Somayajulu {
190135291c22SDavid C Somayajulu ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE;
190235291c22SDavid C Somayajulu (void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
190335291c22SDavid C Somayajulu }
190435291c22SDavid C Somayajulu
1905f10a77bbSDavid C Somayajulu int
ql_set_allmulti(qla_host_t * ha)1906f10a77bbSDavid C Somayajulu ql_set_allmulti(qla_host_t *ha)
1907f10a77bbSDavid C Somayajulu {
1908f10a77bbSDavid C Somayajulu int ret;
1909f10a77bbSDavid C Somayajulu
1910f10a77bbSDavid C Somayajulu ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE;
1911f10a77bbSDavid C Somayajulu ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
1912f10a77bbSDavid C Somayajulu return (ret);
1913f10a77bbSDavid C Somayajulu }
1914f10a77bbSDavid C Somayajulu
191535291c22SDavid C Somayajulu void
qla_reset_allmulti(qla_host_t * ha)191635291c22SDavid C Somayajulu qla_reset_allmulti(qla_host_t *ha)
191735291c22SDavid C Somayajulu {
191835291c22SDavid C Somayajulu ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE;
191935291c22SDavid C Somayajulu (void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode);
192035291c22SDavid C Somayajulu }
1921f10a77bbSDavid C Somayajulu
1922f10a77bbSDavid C Somayajulu /*
1923f10a77bbSDavid C Somayajulu * Name: ql_set_max_mtu
1924f10a77bbSDavid C Somayajulu * Function:
1925f10a77bbSDavid C Somayajulu * Sets the maximum transfer unit size for the specified rcv context.
1926f10a77bbSDavid C Somayajulu */
1927f10a77bbSDavid C Somayajulu int
ql_set_max_mtu(qla_host_t * ha,uint32_t mtu,uint16_t cntxt_id)1928f10a77bbSDavid C Somayajulu ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id)
1929f10a77bbSDavid C Somayajulu {
1930f10a77bbSDavid C Somayajulu device_t dev;
1931f10a77bbSDavid C Somayajulu q80_set_max_mtu_t *max_mtu;
1932f10a77bbSDavid C Somayajulu q80_set_max_mtu_rsp_t *max_mtu_rsp;
1933f10a77bbSDavid C Somayajulu uint32_t err;
1934f10a77bbSDavid C Somayajulu
1935f10a77bbSDavid C Somayajulu dev = ha->pci_dev;
1936f10a77bbSDavid C Somayajulu
1937f10a77bbSDavid C Somayajulu max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox;
1938f10a77bbSDavid C Somayajulu bzero(max_mtu, (sizeof (q80_set_max_mtu_t)));
1939f10a77bbSDavid C Somayajulu
1940f10a77bbSDavid C Somayajulu max_mtu->opcode = Q8_MBX_SET_MAX_MTU;
1941f10a77bbSDavid C Somayajulu max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2);
1942f10a77bbSDavid C Somayajulu max_mtu->count_version |= Q8_MBX_CMD_VERSION;
1943f10a77bbSDavid C Somayajulu
1944f10a77bbSDavid C Somayajulu max_mtu->cntxt_id = cntxt_id;
1945f10a77bbSDavid C Somayajulu max_mtu->mtu = mtu;
1946f10a77bbSDavid C Somayajulu
1947f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)max_mtu,
1948f10a77bbSDavid C Somayajulu (sizeof (q80_set_max_mtu_t) >> 2),
1949f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) {
1950f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
1951f10a77bbSDavid C Somayajulu return -1;
1952f10a77bbSDavid C Somayajulu }
1953f10a77bbSDavid C Somayajulu
1954f10a77bbSDavid C Somayajulu max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox;
1955f10a77bbSDavid C Somayajulu
1956f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status);
1957f10a77bbSDavid C Somayajulu
1958f10a77bbSDavid C Somayajulu if (err) {
1959f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1960f10a77bbSDavid C Somayajulu }
1961f10a77bbSDavid C Somayajulu
1962f10a77bbSDavid C Somayajulu return 0;
1963f10a77bbSDavid C Somayajulu }
1964f10a77bbSDavid C Somayajulu
1965f10a77bbSDavid C Somayajulu static int
qla_link_event_req(qla_host_t * ha,uint16_t cntxt_id)1966f10a77bbSDavid C Somayajulu qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id)
1967f10a77bbSDavid C Somayajulu {
1968f10a77bbSDavid C Somayajulu device_t dev;
1969f10a77bbSDavid C Somayajulu q80_link_event_t *lnk;
1970f10a77bbSDavid C Somayajulu q80_link_event_rsp_t *lnk_rsp;
1971f10a77bbSDavid C Somayajulu uint32_t err;
1972f10a77bbSDavid C Somayajulu
1973f10a77bbSDavid C Somayajulu dev = ha->pci_dev;
1974f10a77bbSDavid C Somayajulu
1975f10a77bbSDavid C Somayajulu lnk = (q80_link_event_t *)ha->hw.mbox;
1976f10a77bbSDavid C Somayajulu bzero(lnk, (sizeof (q80_link_event_t)));
1977f10a77bbSDavid C Somayajulu
1978f10a77bbSDavid C Somayajulu lnk->opcode = Q8_MBX_LINK_EVENT_REQ;
1979f10a77bbSDavid C Somayajulu lnk->count_version = (sizeof (q80_link_event_t) >> 2);
1980f10a77bbSDavid C Somayajulu lnk->count_version |= Q8_MBX_CMD_VERSION;
1981f10a77bbSDavid C Somayajulu
1982f10a77bbSDavid C Somayajulu lnk->cntxt_id = cntxt_id;
1983f10a77bbSDavid C Somayajulu lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC;
1984f10a77bbSDavid C Somayajulu
1985f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2),
1986f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) {
1987f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
1988f10a77bbSDavid C Somayajulu return -1;
1989f10a77bbSDavid C Somayajulu }
1990f10a77bbSDavid C Somayajulu
1991f10a77bbSDavid C Somayajulu lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox;
1992f10a77bbSDavid C Somayajulu
1993f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status);
1994f10a77bbSDavid C Somayajulu
1995f10a77bbSDavid C Somayajulu if (err) {
1996f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
1997f10a77bbSDavid C Somayajulu }
1998f10a77bbSDavid C Somayajulu
1999f10a77bbSDavid C Somayajulu return 0;
2000f10a77bbSDavid C Somayajulu }
2001f10a77bbSDavid C Somayajulu
2002f10a77bbSDavid C Somayajulu static int
qla_config_fw_lro(qla_host_t * ha,uint16_t cntxt_id)2003f10a77bbSDavid C Somayajulu qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id)
2004f10a77bbSDavid C Somayajulu {
2005f10a77bbSDavid C Somayajulu device_t dev;
2006f10a77bbSDavid C Somayajulu q80_config_fw_lro_t *fw_lro;
2007f10a77bbSDavid C Somayajulu q80_config_fw_lro_rsp_t *fw_lro_rsp;
2008f10a77bbSDavid C Somayajulu uint32_t err;
2009f10a77bbSDavid C Somayajulu
2010f10a77bbSDavid C Somayajulu dev = ha->pci_dev;
2011f10a77bbSDavid C Somayajulu
2012f10a77bbSDavid C Somayajulu fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox;
2013f10a77bbSDavid C Somayajulu bzero(fw_lro, sizeof(q80_config_fw_lro_t));
2014f10a77bbSDavid C Somayajulu
2015f10a77bbSDavid C Somayajulu fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO;
2016f10a77bbSDavid C Somayajulu fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2);
2017f10a77bbSDavid C Somayajulu fw_lro->count_version |= Q8_MBX_CMD_VERSION;
2018f10a77bbSDavid C Somayajulu
2019f10a77bbSDavid C Somayajulu fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK;
202035291c22SDavid C Somayajulu fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK;
2021f10a77bbSDavid C Somayajulu
2022f10a77bbSDavid C Somayajulu fw_lro->cntxt_id = cntxt_id;
2023f10a77bbSDavid C Somayajulu
2024f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)fw_lro,
2025f10a77bbSDavid C Somayajulu (sizeof (q80_config_fw_lro_t) >> 2),
2026f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) {
2027f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
2028f10a77bbSDavid C Somayajulu return -1;
2029f10a77bbSDavid C Somayajulu }
2030f10a77bbSDavid C Somayajulu
2031f10a77bbSDavid C Somayajulu fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox;
2032f10a77bbSDavid C Somayajulu
2033f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status);
2034f10a77bbSDavid C Somayajulu
2035f10a77bbSDavid C Somayajulu if (err) {
2036f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
2037f10a77bbSDavid C Somayajulu }
2038f10a77bbSDavid C Somayajulu
2039f10a77bbSDavid C Somayajulu return 0;
2040f10a77bbSDavid C Somayajulu }
2041f10a77bbSDavid C Somayajulu
204200caeec7SDavid C Somayajulu static int
qla_set_cam_search_mode(qla_host_t * ha,uint32_t search_mode)204300caeec7SDavid C Somayajulu qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode)
204400caeec7SDavid C Somayajulu {
204500caeec7SDavid C Somayajulu device_t dev;
204600caeec7SDavid C Somayajulu q80_hw_config_t *hw_config;
204700caeec7SDavid C Somayajulu q80_hw_config_rsp_t *hw_config_rsp;
204800caeec7SDavid C Somayajulu uint32_t err;
204900caeec7SDavid C Somayajulu
205000caeec7SDavid C Somayajulu dev = ha->pci_dev;
205100caeec7SDavid C Somayajulu
205200caeec7SDavid C Somayajulu hw_config = (q80_hw_config_t *)ha->hw.mbox;
205300caeec7SDavid C Somayajulu bzero(hw_config, sizeof (q80_hw_config_t));
205400caeec7SDavid C Somayajulu
205500caeec7SDavid C Somayajulu hw_config->opcode = Q8_MBX_HW_CONFIG;
205600caeec7SDavid C Somayajulu hw_config->count_version = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE_COUNT;
205700caeec7SDavid C Somayajulu hw_config->count_version |= Q8_MBX_CMD_VERSION;
205800caeec7SDavid C Somayajulu
205900caeec7SDavid C Somayajulu hw_config->cmd = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE;
206000caeec7SDavid C Somayajulu
206100caeec7SDavid C Somayajulu hw_config->u.set_cam_search_mode.mode = search_mode;
206200caeec7SDavid C Somayajulu
206300caeec7SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
206400caeec7SDavid C Somayajulu (sizeof (q80_hw_config_t) >> 2),
206500caeec7SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
206600caeec7SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
206700caeec7SDavid C Somayajulu return -1;
206800caeec7SDavid C Somayajulu }
206900caeec7SDavid C Somayajulu hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
207000caeec7SDavid C Somayajulu
207100caeec7SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
207200caeec7SDavid C Somayajulu
207300caeec7SDavid C Somayajulu if (err) {
207400caeec7SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
207500caeec7SDavid C Somayajulu }
207600caeec7SDavid C Somayajulu
207700caeec7SDavid C Somayajulu return 0;
207800caeec7SDavid C Somayajulu }
207900caeec7SDavid C Somayajulu
208000caeec7SDavid C Somayajulu static int
qla_get_cam_search_mode(qla_host_t * ha)208100caeec7SDavid C Somayajulu qla_get_cam_search_mode(qla_host_t *ha)
208200caeec7SDavid C Somayajulu {
208300caeec7SDavid C Somayajulu device_t dev;
208400caeec7SDavid C Somayajulu q80_hw_config_t *hw_config;
208500caeec7SDavid C Somayajulu q80_hw_config_rsp_t *hw_config_rsp;
208600caeec7SDavid C Somayajulu uint32_t err;
208700caeec7SDavid C Somayajulu
208800caeec7SDavid C Somayajulu dev = ha->pci_dev;
208900caeec7SDavid C Somayajulu
209000caeec7SDavid C Somayajulu hw_config = (q80_hw_config_t *)ha->hw.mbox;
209100caeec7SDavid C Somayajulu bzero(hw_config, sizeof (q80_hw_config_t));
209200caeec7SDavid C Somayajulu
209300caeec7SDavid C Somayajulu hw_config->opcode = Q8_MBX_HW_CONFIG;
209400caeec7SDavid C Somayajulu hw_config->count_version = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE_COUNT;
209500caeec7SDavid C Somayajulu hw_config->count_version |= Q8_MBX_CMD_VERSION;
209600caeec7SDavid C Somayajulu
209700caeec7SDavid C Somayajulu hw_config->cmd = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE;
209800caeec7SDavid C Somayajulu
209900caeec7SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)hw_config,
210000caeec7SDavid C Somayajulu (sizeof (q80_hw_config_t) >> 2),
210100caeec7SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) {
210200caeec7SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
210300caeec7SDavid C Somayajulu return -1;
210400caeec7SDavid C Somayajulu }
210500caeec7SDavid C Somayajulu hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox;
210600caeec7SDavid C Somayajulu
210700caeec7SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status);
210800caeec7SDavid C Somayajulu
210900caeec7SDavid C Somayajulu if (err) {
211000caeec7SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
211100caeec7SDavid C Somayajulu } else {
211200caeec7SDavid C Somayajulu device_printf(dev, "%s: cam search mode [0x%08x]\n", __func__,
211300caeec7SDavid C Somayajulu hw_config_rsp->u.get_cam_search_mode.mode);
211400caeec7SDavid C Somayajulu }
211500caeec7SDavid C Somayajulu
211600caeec7SDavid C Somayajulu return 0;
211700caeec7SDavid C Somayajulu }
211800caeec7SDavid C Somayajulu
2119f10a77bbSDavid C Somayajulu static int
qla_get_hw_stats(qla_host_t * ha,uint32_t cmd,uint32_t rsp_size)212035291c22SDavid C Somayajulu qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size)
2121f10a77bbSDavid C Somayajulu {
2122f10a77bbSDavid C Somayajulu device_t dev;
2123f10a77bbSDavid C Somayajulu q80_get_stats_t *stat;
2124f10a77bbSDavid C Somayajulu q80_get_stats_rsp_t *stat_rsp;
2125f10a77bbSDavid C Somayajulu uint32_t err;
2126f10a77bbSDavid C Somayajulu
2127f10a77bbSDavid C Somayajulu dev = ha->pci_dev;
2128f10a77bbSDavid C Somayajulu
2129f10a77bbSDavid C Somayajulu stat = (q80_get_stats_t *)ha->hw.mbox;
2130f10a77bbSDavid C Somayajulu bzero(stat, (sizeof (q80_get_stats_t)));
2131f10a77bbSDavid C Somayajulu
2132f10a77bbSDavid C Somayajulu stat->opcode = Q8_MBX_GET_STATS;
2133f10a77bbSDavid C Somayajulu stat->count_version = 2;
2134f10a77bbSDavid C Somayajulu stat->count_version |= Q8_MBX_CMD_VERSION;
2135f10a77bbSDavid C Somayajulu
2136f10a77bbSDavid C Somayajulu stat->cmd = cmd;
2137f10a77bbSDavid C Somayajulu
2138f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)stat, 2,
213935291c22SDavid C Somayajulu ha->hw.mbox, (rsp_size >> 2), 0)) {
2140f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
2141f10a77bbSDavid C Somayajulu return -1;
2142f10a77bbSDavid C Somayajulu }
2143f10a77bbSDavid C Somayajulu
2144f10a77bbSDavid C Somayajulu stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
2145f10a77bbSDavid C Somayajulu
2146f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status);
2147f10a77bbSDavid C Somayajulu
2148f10a77bbSDavid C Somayajulu if (err) {
2149f10a77bbSDavid C Somayajulu return -1;
2150f10a77bbSDavid C Somayajulu }
2151f10a77bbSDavid C Somayajulu
2152f10a77bbSDavid C Somayajulu return 0;
2153f10a77bbSDavid C Somayajulu }
2154f10a77bbSDavid C Somayajulu
2155f10a77bbSDavid C Somayajulu void
ql_get_stats(qla_host_t * ha)2156f10a77bbSDavid C Somayajulu ql_get_stats(qla_host_t *ha)
2157f10a77bbSDavid C Somayajulu {
2158f10a77bbSDavid C Somayajulu q80_get_stats_rsp_t *stat_rsp;
2159f10a77bbSDavid C Somayajulu q80_mac_stats_t *mstat;
2160f10a77bbSDavid C Somayajulu q80_xmt_stats_t *xstat;
2161f10a77bbSDavid C Somayajulu q80_rcv_stats_t *rstat;
2162f10a77bbSDavid C Somayajulu uint32_t cmd;
216335291c22SDavid C Somayajulu int i;
216454ab3b4aSJustin Hibbits if_t ifp = ha->ifp;
21657fb51846SDavid C Somayajulu
21667fb51846SDavid C Somayajulu if (ifp == NULL)
21677fb51846SDavid C Somayajulu return;
21687fb51846SDavid C Somayajulu
21697fb51846SDavid C Somayajulu if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) != 0) {
21707fb51846SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", __func__);
21717fb51846SDavid C Somayajulu return;
21727fb51846SDavid C Somayajulu }
21737fb51846SDavid C Somayajulu
217454ab3b4aSJustin Hibbits if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) {
21757fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__);
21767fb51846SDavid C Somayajulu return;
21777fb51846SDavid C Somayajulu }
2178f10a77bbSDavid C Somayajulu
2179f10a77bbSDavid C Somayajulu stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox;
2180f10a77bbSDavid C Somayajulu /*
2181f10a77bbSDavid C Somayajulu * Get MAC Statistics
2182f10a77bbSDavid C Somayajulu */
2183f10a77bbSDavid C Somayajulu cmd = Q8_GET_STATS_CMD_TYPE_MAC;
218435291c22SDavid C Somayajulu // cmd |= Q8_GET_STATS_CMD_CLEAR;
2185f10a77bbSDavid C Somayajulu
2186f10a77bbSDavid C Somayajulu cmd |= ((ha->pci_func & 0x1) << 16);
2187f10a77bbSDavid C Somayajulu
218854ab3b4aSJustin Hibbits if (ha->qla_watchdog_pause || (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) ||
2189b65c0c07SDavid C Somayajulu ha->offline)
21907fb51846SDavid C Somayajulu goto ql_get_stats_exit;
21917fb51846SDavid C Somayajulu
219235291c22SDavid C Somayajulu if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
2193f10a77bbSDavid C Somayajulu mstat = (q80_mac_stats_t *)&stat_rsp->u.mac;
21947fb51846SDavid C Somayajulu bcopy(mstat, &ha->hw.mac, sizeof(q80_mac_stats_t));
2195f10a77bbSDavid C Somayajulu } else {
2196f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n",
2197f10a77bbSDavid C Somayajulu __func__, ha->hw.mbox[0]);
2198f10a77bbSDavid C Somayajulu }
2199f10a77bbSDavid C Somayajulu /*
2200f10a77bbSDavid C Somayajulu * Get RCV Statistics
2201f10a77bbSDavid C Somayajulu */
2202f10a77bbSDavid C Somayajulu cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT;
220335291c22SDavid C Somayajulu // cmd |= Q8_GET_STATS_CMD_CLEAR;
2204f10a77bbSDavid C Somayajulu cmd |= (ha->hw.rcv_cntxt_id << 16);
2205f10a77bbSDavid C Somayajulu
220654ab3b4aSJustin Hibbits if (ha->qla_watchdog_pause || (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) ||
2207b65c0c07SDavid C Somayajulu ha->offline)
22087fb51846SDavid C Somayajulu goto ql_get_stats_exit;
22097fb51846SDavid C Somayajulu
221035291c22SDavid C Somayajulu if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) {
2211f10a77bbSDavid C Somayajulu rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv;
22127fb51846SDavid C Somayajulu bcopy(rstat, &ha->hw.rcv, sizeof(q80_rcv_stats_t));
2213f10a77bbSDavid C Somayajulu } else {
2214f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n",
2215f10a77bbSDavid C Somayajulu __func__, ha->hw.mbox[0]);
2216f10a77bbSDavid C Somayajulu }
22177fb51846SDavid C Somayajulu
221854ab3b4aSJustin Hibbits if (ha->qla_watchdog_pause || (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) ||
2219b65c0c07SDavid C Somayajulu ha->offline)
22207fb51846SDavid C Somayajulu goto ql_get_stats_exit;
2221f10a77bbSDavid C Somayajulu /*
2222f10a77bbSDavid C Somayajulu * Get XMT Statistics
2223f10a77bbSDavid C Somayajulu */
2224b65c0c07SDavid C Somayajulu for (i = 0 ; (i < ha->hw.num_tx_rings); i++) {
2225b65c0c07SDavid C Somayajulu if (ha->qla_watchdog_pause ||
222654ab3b4aSJustin Hibbits (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) ||
2227b65c0c07SDavid C Somayajulu ha->offline)
2228b65c0c07SDavid C Somayajulu goto ql_get_stats_exit;
2229b65c0c07SDavid C Somayajulu
2230f10a77bbSDavid C Somayajulu cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT;
223135291c22SDavid C Somayajulu // cmd |= Q8_GET_STATS_CMD_CLEAR;
223235291c22SDavid C Somayajulu cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16);
2233f10a77bbSDavid C Somayajulu
223435291c22SDavid C Somayajulu if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t))
223535291c22SDavid C Somayajulu == 0) {
2236f10a77bbSDavid C Somayajulu xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt;
22377fb51846SDavid C Somayajulu bcopy(xstat, &ha->hw.xmt[i], sizeof(q80_xmt_stats_t));
2238f10a77bbSDavid C Somayajulu } else {
2239f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n",
2240f10a77bbSDavid C Somayajulu __func__, ha->hw.mbox[0]);
2241f10a77bbSDavid C Somayajulu }
2242f10a77bbSDavid C Somayajulu }
224335291c22SDavid C Somayajulu
22447fb51846SDavid C Somayajulu ql_get_stats_exit:
22457fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__);
224635291c22SDavid C Somayajulu
224735291c22SDavid C Somayajulu return;
224835291c22SDavid C Somayajulu }
2249f10a77bbSDavid C Somayajulu
2250f10a77bbSDavid C Somayajulu /*
2251f10a77bbSDavid C Somayajulu * Name: qla_tx_tso
2252f10a77bbSDavid C Somayajulu * Function: Checks if the packet to be transmitted is a candidate for
2253f10a77bbSDavid C Somayajulu * Large TCP Segment Offload. If yes, the appropriate fields in the Tx
2254f10a77bbSDavid C Somayajulu * Ring Structure are plugged in.
2255f10a77bbSDavid C Somayajulu */
2256f10a77bbSDavid C Somayajulu static int
qla_tx_tso(qla_host_t * ha,struct mbuf * mp,q80_tx_cmd_t * tx_cmd,uint8_t * hdr)2257f10a77bbSDavid C Somayajulu qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
2258f10a77bbSDavid C Somayajulu {
2259f10a77bbSDavid C Somayajulu struct ether_vlan_header *eh;
2260f10a77bbSDavid C Somayajulu struct ip *ip = NULL;
2261f10a77bbSDavid C Somayajulu struct ip6_hdr *ip6 = NULL;
2262f10a77bbSDavid C Somayajulu struct tcphdr *th = NULL;
2263f10a77bbSDavid C Somayajulu uint32_t ehdrlen, hdrlen, ip_hlen, tcp_hlen, tcp_opt_off;
2264f10a77bbSDavid C Somayajulu uint16_t etype, opcode, offload = 1;
2265f10a77bbSDavid C Somayajulu
2266f10a77bbSDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *);
2267f10a77bbSDavid C Somayajulu
2268f10a77bbSDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2269f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
2270f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_proto);
2271f10a77bbSDavid C Somayajulu } else {
2272f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN;
2273f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_encap_proto);
2274f10a77bbSDavid C Somayajulu }
2275f10a77bbSDavid C Somayajulu
2276f10a77bbSDavid C Somayajulu hdrlen = 0;
2277f10a77bbSDavid C Somayajulu
2278f10a77bbSDavid C Somayajulu switch (etype) {
2279f10a77bbSDavid C Somayajulu case ETHERTYPE_IP:
2280f10a77bbSDavid C Somayajulu
2281f10a77bbSDavid C Somayajulu tcp_opt_off = ehdrlen + sizeof(struct ip) +
2282f10a77bbSDavid C Somayajulu sizeof(struct tcphdr);
2283f10a77bbSDavid C Somayajulu
2284f10a77bbSDavid C Somayajulu if (mp->m_len < tcp_opt_off) {
2285f10a77bbSDavid C Somayajulu m_copydata(mp, 0, tcp_opt_off, hdr);
2286f10a77bbSDavid C Somayajulu ip = (struct ip *)(hdr + ehdrlen);
2287f10a77bbSDavid C Somayajulu } else {
2288f10a77bbSDavid C Somayajulu ip = (struct ip *)(mp->m_data + ehdrlen);
2289f10a77bbSDavid C Somayajulu }
2290f10a77bbSDavid C Somayajulu
2291f10a77bbSDavid C Somayajulu ip_hlen = ip->ip_hl << 2;
2292f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
2293f10a77bbSDavid C Somayajulu
2294f10a77bbSDavid C Somayajulu
2295f10a77bbSDavid C Somayajulu if ((ip->ip_p != IPPROTO_TCP) ||
2296f10a77bbSDavid C Somayajulu (ip_hlen != sizeof (struct ip))){
2297f10a77bbSDavid C Somayajulu /* IP Options are not supported */
2298f10a77bbSDavid C Somayajulu
2299f10a77bbSDavid C Somayajulu offload = 0;
2300f10a77bbSDavid C Somayajulu } else
2301f10a77bbSDavid C Somayajulu th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
2302f10a77bbSDavid C Somayajulu
2303f10a77bbSDavid C Somayajulu break;
2304f10a77bbSDavid C Somayajulu
2305f10a77bbSDavid C Somayajulu case ETHERTYPE_IPV6:
2306f10a77bbSDavid C Somayajulu
2307f10a77bbSDavid C Somayajulu tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) +
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 ip6 = (struct ip6_hdr *)(hdr + ehdrlen);
2313f10a77bbSDavid C Somayajulu } else {
2314f10a77bbSDavid C Somayajulu ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
2315f10a77bbSDavid C Somayajulu }
2316f10a77bbSDavid C Somayajulu
2317f10a77bbSDavid C Somayajulu ip_hlen = sizeof(struct ip6_hdr);
2318f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6;
2319f10a77bbSDavid C Somayajulu
2320f10a77bbSDavid C Somayajulu if (ip6->ip6_nxt != IPPROTO_TCP) {
2321f10a77bbSDavid C Somayajulu //device_printf(dev, "%s: ipv6\n", __func__);
2322f10a77bbSDavid C Somayajulu offload = 0;
2323f10a77bbSDavid C Somayajulu } else
2324f10a77bbSDavid C Somayajulu th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen);
2325f10a77bbSDavid C Somayajulu break;
2326f10a77bbSDavid C Somayajulu
2327f10a77bbSDavid C Somayajulu default:
23289fa72d33SJohn Baldwin QL_DPRINT8(ha, (ha->pci_dev, "%s: type!=ip\n", __func__));
2329f10a77bbSDavid C Somayajulu offload = 0;
2330f10a77bbSDavid C Somayajulu break;
2331f10a77bbSDavid C Somayajulu }
2332f10a77bbSDavid C Somayajulu
2333f10a77bbSDavid C Somayajulu if (!offload)
2334f10a77bbSDavid C Somayajulu return (-1);
2335f10a77bbSDavid C Somayajulu
2336f10a77bbSDavid C Somayajulu tcp_hlen = th->th_off << 2;
2337f10a77bbSDavid C Somayajulu hdrlen = ehdrlen + ip_hlen + tcp_hlen;
2338f10a77bbSDavid C Somayajulu
2339f10a77bbSDavid C Somayajulu if (mp->m_len < hdrlen) {
2340f10a77bbSDavid C Somayajulu if (mp->m_len < tcp_opt_off) {
2341f10a77bbSDavid C Somayajulu if (tcp_hlen > sizeof(struct tcphdr)) {
2342f10a77bbSDavid C Somayajulu m_copydata(mp, tcp_opt_off,
2343f10a77bbSDavid C Somayajulu (tcp_hlen - sizeof(struct tcphdr)),
2344f10a77bbSDavid C Somayajulu &hdr[tcp_opt_off]);
2345f10a77bbSDavid C Somayajulu }
2346f10a77bbSDavid C Somayajulu } else {
2347f10a77bbSDavid C Somayajulu m_copydata(mp, 0, hdrlen, hdr);
2348f10a77bbSDavid C Somayajulu }
2349f10a77bbSDavid C Somayajulu }
2350f10a77bbSDavid C Somayajulu
2351f10a77bbSDavid C Somayajulu tx_cmd->mss = mp->m_pkthdr.tso_segsz;
2352f10a77bbSDavid C Somayajulu
2353f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode = opcode ;
2354f10a77bbSDavid C Somayajulu tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen;
2355f10a77bbSDavid C Somayajulu tx_cmd->total_hdr_len = hdrlen;
2356f10a77bbSDavid C Somayajulu
2357f10a77bbSDavid C Somayajulu /* Check for Multicast least significant bit of MSB == 1 */
2358f10a77bbSDavid C Somayajulu if (eh->evl_dhost[0] & 0x01) {
2359f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST;
2360f10a77bbSDavid C Somayajulu }
2361f10a77bbSDavid C Somayajulu
2362f10a77bbSDavid C Somayajulu if (mp->m_len < hdrlen) {
2363f10a77bbSDavid C Somayajulu printf("%d\n", hdrlen);
2364f10a77bbSDavid C Somayajulu return (1);
2365f10a77bbSDavid C Somayajulu }
2366f10a77bbSDavid C Somayajulu
2367f10a77bbSDavid C Somayajulu return (0);
2368f10a77bbSDavid C Somayajulu }
2369f10a77bbSDavid C Somayajulu
2370f10a77bbSDavid C Somayajulu /*
2371f10a77bbSDavid C Somayajulu * Name: qla_tx_chksum
2372f10a77bbSDavid C Somayajulu * Function: Checks if the packet to be transmitted is a candidate for
2373f10a77bbSDavid C Somayajulu * TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx
2374f10a77bbSDavid C Somayajulu * Ring Structure are plugged in.
2375f10a77bbSDavid C Somayajulu */
2376f10a77bbSDavid C Somayajulu static int
qla_tx_chksum(qla_host_t * ha,struct mbuf * mp,uint32_t * op_code,uint32_t * tcp_hdr_off)2377f10a77bbSDavid C Somayajulu qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code,
2378f10a77bbSDavid C Somayajulu uint32_t *tcp_hdr_off)
2379f10a77bbSDavid C Somayajulu {
2380f10a77bbSDavid C Somayajulu struct ether_vlan_header *eh;
2381f10a77bbSDavid C Somayajulu struct ip *ip;
2382f10a77bbSDavid C Somayajulu struct ip6_hdr *ip6;
2383f10a77bbSDavid C Somayajulu uint32_t ehdrlen, ip_hlen;
2384f10a77bbSDavid C Somayajulu uint16_t etype, opcode, offload = 1;
2385f10a77bbSDavid C Somayajulu uint8_t buf[sizeof(struct ip6_hdr)];
2386f10a77bbSDavid C Somayajulu
2387f10a77bbSDavid C Somayajulu *op_code = 0;
2388f10a77bbSDavid C Somayajulu
23897fb51846SDavid C Somayajulu if ((mp->m_pkthdr.csum_flags &
23907fb51846SDavid C Somayajulu (CSUM_TCP|CSUM_UDP|CSUM_TCP_IPV6 | CSUM_UDP_IPV6)) == 0)
2391f10a77bbSDavid C Somayajulu return (-1);
2392f10a77bbSDavid C Somayajulu
2393f10a77bbSDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *);
2394f10a77bbSDavid C Somayajulu
2395f10a77bbSDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2396f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
2397f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_proto);
2398f10a77bbSDavid C Somayajulu } else {
2399f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN;
2400f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_encap_proto);
2401f10a77bbSDavid C Somayajulu }
2402f10a77bbSDavid C Somayajulu
2403f10a77bbSDavid C Somayajulu
2404f10a77bbSDavid C Somayajulu switch (etype) {
2405f10a77bbSDavid C Somayajulu case ETHERTYPE_IP:
2406f10a77bbSDavid C Somayajulu ip = (struct ip *)(mp->m_data + ehdrlen);
2407f10a77bbSDavid C Somayajulu
2408f10a77bbSDavid C Somayajulu ip_hlen = sizeof (struct ip);
2409f10a77bbSDavid C Somayajulu
2410f10a77bbSDavid C Somayajulu if (mp->m_len < (ehdrlen + ip_hlen)) {
2411f10a77bbSDavid C Somayajulu m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
2412f10a77bbSDavid C Somayajulu ip = (struct ip *)buf;
2413f10a77bbSDavid C Somayajulu }
2414f10a77bbSDavid C Somayajulu
2415f10a77bbSDavid C Somayajulu if (ip->ip_p == IPPROTO_TCP)
2416f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM;
2417f10a77bbSDavid C Somayajulu else if (ip->ip_p == IPPROTO_UDP)
2418f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM;
2419f10a77bbSDavid C Somayajulu else {
2420f10a77bbSDavid C Somayajulu //device_printf(dev, "%s: ipv4\n", __func__);
2421f10a77bbSDavid C Somayajulu offload = 0;
2422f10a77bbSDavid C Somayajulu }
2423f10a77bbSDavid C Somayajulu break;
2424f10a77bbSDavid C Somayajulu
2425f10a77bbSDavid C Somayajulu case ETHERTYPE_IPV6:
2426f10a77bbSDavid C Somayajulu ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
2427f10a77bbSDavid C Somayajulu
2428f10a77bbSDavid C Somayajulu ip_hlen = sizeof(struct ip6_hdr);
2429f10a77bbSDavid C Somayajulu
2430f10a77bbSDavid C Somayajulu if (mp->m_len < (ehdrlen + ip_hlen)) {
2431f10a77bbSDavid C Somayajulu m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
2432f10a77bbSDavid C Somayajulu buf);
2433f10a77bbSDavid C Somayajulu ip6 = (struct ip6_hdr *)buf;
2434f10a77bbSDavid C Somayajulu }
2435f10a77bbSDavid C Somayajulu
2436f10a77bbSDavid C Somayajulu if (ip6->ip6_nxt == IPPROTO_TCP)
2437f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6;
2438f10a77bbSDavid C Somayajulu else if (ip6->ip6_nxt == IPPROTO_UDP)
2439f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6;
2440f10a77bbSDavid C Somayajulu else {
2441f10a77bbSDavid C Somayajulu //device_printf(dev, "%s: ipv6\n", __func__);
2442f10a77bbSDavid C Somayajulu offload = 0;
2443f10a77bbSDavid C Somayajulu }
2444f10a77bbSDavid C Somayajulu break;
2445f10a77bbSDavid C Somayajulu
2446f10a77bbSDavid C Somayajulu default:
2447f10a77bbSDavid C Somayajulu offload = 0;
2448f10a77bbSDavid C Somayajulu break;
2449f10a77bbSDavid C Somayajulu }
2450f10a77bbSDavid C Somayajulu if (!offload)
2451f10a77bbSDavid C Somayajulu return (-1);
2452f10a77bbSDavid C Somayajulu
2453f10a77bbSDavid C Somayajulu *op_code = opcode;
2454f10a77bbSDavid C Somayajulu *tcp_hdr_off = (ip_hlen + ehdrlen);
2455f10a77bbSDavid C Somayajulu
2456f10a77bbSDavid C Somayajulu return (0);
2457f10a77bbSDavid C Somayajulu }
2458f10a77bbSDavid C Somayajulu
2459f10a77bbSDavid C Somayajulu #define QLA_TX_MIN_FREE 2
2460f10a77bbSDavid C Somayajulu /*
2461f10a77bbSDavid C Somayajulu * Name: ql_hw_send
2462f10a77bbSDavid C Somayajulu * Function: Transmits a packet. It first checks if the packet is a
2463f10a77bbSDavid C Somayajulu * candidate for Large TCP Segment Offload and then for UDP/TCP checksum
2464f10a77bbSDavid C Somayajulu * offload. If either of these creteria are not met, it is transmitted
2465f10a77bbSDavid C Somayajulu * as a regular ethernet frame.
2466f10a77bbSDavid C Somayajulu */
2467f10a77bbSDavid C Somayajulu int
ql_hw_send(qla_host_t * ha,bus_dma_segment_t * segs,int nsegs,uint32_t tx_idx,struct mbuf * mp,uint32_t txr_idx,uint32_t iscsi_pdu)2468f10a77bbSDavid C Somayajulu ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
246935291c22SDavid C Somayajulu uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu)
2470f10a77bbSDavid C Somayajulu {
2471f10a77bbSDavid C Somayajulu struct ether_vlan_header *eh;
2472f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw;
2473f10a77bbSDavid C Somayajulu q80_tx_cmd_t *tx_cmd, tso_cmd;
2474f10a77bbSDavid C Somayajulu bus_dma_segment_t *c_seg;
2475f10a77bbSDavid C Somayajulu uint32_t num_tx_cmds, hdr_len = 0;
2476f10a77bbSDavid C Somayajulu uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next;
2477f10a77bbSDavid C Somayajulu device_t dev;
2478f10a77bbSDavid C Somayajulu int i, ret;
2479f10a77bbSDavid C Somayajulu uint8_t *src = NULL, *dst = NULL;
2480f10a77bbSDavid C Somayajulu uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
2481f10a77bbSDavid C Somayajulu uint32_t op_code = 0;
2482f10a77bbSDavid C Somayajulu uint32_t tcp_hdr_off = 0;
2483f10a77bbSDavid C Somayajulu
2484f10a77bbSDavid C Somayajulu dev = ha->pci_dev;
2485f10a77bbSDavid C Somayajulu
2486f10a77bbSDavid C Somayajulu /*
2487f10a77bbSDavid C Somayajulu * Always make sure there is atleast one empty slot in the tx_ring
2488f10a77bbSDavid C Somayajulu * tx_ring is considered full when there only one entry available
2489f10a77bbSDavid C Somayajulu */
2490f10a77bbSDavid C Somayajulu num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2;
2491f10a77bbSDavid C Somayajulu
2492f10a77bbSDavid C Somayajulu total_length = mp->m_pkthdr.len;
2493f10a77bbSDavid C Somayajulu if (total_length > QLA_MAX_TSO_FRAME_SIZE) {
2494f10a77bbSDavid C Somayajulu device_printf(dev, "%s: total length exceeds maxlen(%d)\n",
2495f10a77bbSDavid C Somayajulu __func__, total_length);
2496203f9d18SDavid C Somayajulu return (EINVAL);
2497f10a77bbSDavid C Somayajulu }
2498f10a77bbSDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *);
2499f10a77bbSDavid C Somayajulu
2500f10a77bbSDavid C Somayajulu if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2501f10a77bbSDavid C Somayajulu bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
2502f10a77bbSDavid C Somayajulu
2503f10a77bbSDavid C Somayajulu src = frame_hdr;
2504f10a77bbSDavid C Somayajulu ret = qla_tx_tso(ha, mp, &tso_cmd, src);
2505f10a77bbSDavid C Somayajulu
2506f10a77bbSDavid C Somayajulu if (!(ret & ~1)) {
2507f10a77bbSDavid C Somayajulu /* find the additional tx_cmd descriptors required */
2508f10a77bbSDavid C Somayajulu
2509f10a77bbSDavid C Somayajulu if (mp->m_flags & M_VLANTAG)
2510f10a77bbSDavid C Somayajulu tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN;
2511f10a77bbSDavid C Somayajulu
2512f10a77bbSDavid C Somayajulu hdr_len = tso_cmd.total_hdr_len;
2513f10a77bbSDavid C Somayajulu
2514f10a77bbSDavid C Somayajulu bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2515f10a77bbSDavid C Somayajulu bytes = QL_MIN(bytes, hdr_len);
2516f10a77bbSDavid C Somayajulu
2517f10a77bbSDavid C Somayajulu num_tx_cmds++;
2518f10a77bbSDavid C Somayajulu hdr_len -= bytes;
2519f10a77bbSDavid C Somayajulu
2520f10a77bbSDavid C Somayajulu while (hdr_len) {
2521f10a77bbSDavid C Somayajulu bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2522f10a77bbSDavid C Somayajulu hdr_len -= bytes;
2523f10a77bbSDavid C Somayajulu num_tx_cmds++;
2524f10a77bbSDavid C Somayajulu }
2525f10a77bbSDavid C Somayajulu hdr_len = tso_cmd.total_hdr_len;
2526f10a77bbSDavid C Somayajulu
2527f10a77bbSDavid C Somayajulu if (ret == 0)
2528f10a77bbSDavid C Somayajulu src = (uint8_t *)eh;
2529f10a77bbSDavid C Somayajulu } else
2530f10a77bbSDavid C Somayajulu return (EINVAL);
2531f10a77bbSDavid C Somayajulu } else {
2532f10a77bbSDavid C Somayajulu (void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off);
2533f10a77bbSDavid C Somayajulu }
2534f10a77bbSDavid C Somayajulu
2535f10a77bbSDavid C Somayajulu if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
2536b89f2279SDavid C Somayajulu ql_hw_tx_done_locked(ha, txr_idx);
2537f10a77bbSDavid C Somayajulu if (hw->tx_cntxt[txr_idx].txr_free <=
2538f10a77bbSDavid C Somayajulu (num_tx_cmds + QLA_TX_MIN_FREE)) {
2539f10a77bbSDavid C Somayajulu QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= "
2540f10a77bbSDavid C Somayajulu "(num_tx_cmds + QLA_TX_MIN_FREE))\n",
2541f10a77bbSDavid C Somayajulu __func__));
2542f10a77bbSDavid C Somayajulu return (-1);
2543f10a77bbSDavid C Somayajulu }
2544f10a77bbSDavid C Somayajulu }
2545f10a77bbSDavid C Somayajulu
2546c6acf96aSDavid C Somayajulu for (i = 0; i < num_tx_cmds; i++) {
2547c6acf96aSDavid C Somayajulu int j;
2548c6acf96aSDavid C Somayajulu
2549c6acf96aSDavid C Somayajulu j = (tx_idx+i) & (NUM_TX_DESCRIPTORS - 1);
2550c6acf96aSDavid C Somayajulu
2551c6acf96aSDavid C Somayajulu if (NULL != ha->tx_ring[txr_idx].tx_buf[j].m_head) {
2552c6acf96aSDavid C Somayajulu QL_ASSERT(ha, 0, \
2553c6acf96aSDavid C Somayajulu ("%s [%d]: txr_idx = %d tx_idx = %d mbuf = %p\n",\
2554c6acf96aSDavid C Somayajulu __func__, __LINE__, txr_idx, j,\
2555c6acf96aSDavid C Somayajulu ha->tx_ring[txr_idx].tx_buf[j].m_head));
2556c6acf96aSDavid C Somayajulu return (EINVAL);
2557c6acf96aSDavid C Somayajulu }
2558c6acf96aSDavid C Somayajulu }
2559c6acf96aSDavid C Somayajulu
2560f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx];
2561f10a77bbSDavid C Somayajulu
2562f10a77bbSDavid C Somayajulu if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) {
2563f10a77bbSDavid C Somayajulu if (nsegs > ha->hw.max_tx_segs)
2564f10a77bbSDavid C Somayajulu ha->hw.max_tx_segs = nsegs;
2565f10a77bbSDavid C Somayajulu
2566f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2567f10a77bbSDavid C Somayajulu
2568f10a77bbSDavid C Somayajulu if (op_code) {
2569f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode = op_code;
2570f10a77bbSDavid C Somayajulu tx_cmd->tcp_hdr_off = tcp_hdr_off;
2571f10a77bbSDavid C Somayajulu
2572f10a77bbSDavid C Somayajulu } else {
2573f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER;
2574f10a77bbSDavid C Somayajulu }
2575f10a77bbSDavid C Somayajulu } else {
2576f10a77bbSDavid C Somayajulu bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
2577f10a77bbSDavid C Somayajulu ha->tx_tso_frames++;
2578f10a77bbSDavid C Somayajulu }
2579f10a77bbSDavid C Somayajulu
2580f10a77bbSDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2581f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
258235291c22SDavid C Somayajulu
258335291c22SDavid C Somayajulu if (iscsi_pdu)
258435291c22SDavid C Somayajulu eh->evl_tag |= ha->hw.user_pri_iscsi << 13;
258535291c22SDavid C Somayajulu
2586f10a77bbSDavid C Somayajulu } else if (mp->m_flags & M_VLANTAG) {
2587f10a77bbSDavid C Somayajulu if (hdr_len) { /* TSO */
2588f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED |
2589f10a77bbSDavid C Somayajulu Q8_TX_CMD_FLAGS_HW_VLAN_ID);
2590f10a77bbSDavid C Somayajulu tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN;
2591f10a77bbSDavid C Somayajulu } else
2592f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID;
2593f10a77bbSDavid C Somayajulu
2594f10a77bbSDavid C Somayajulu ha->hw_vlan_tx_frames++;
2595f10a77bbSDavid C Somayajulu tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag;
259635291c22SDavid C Somayajulu
259735291c22SDavid C Somayajulu if (iscsi_pdu) {
259835291c22SDavid C Somayajulu tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13;
259935291c22SDavid C Somayajulu mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci;
260035291c22SDavid C Somayajulu }
2601f10a77bbSDavid C Somayajulu }
2602f10a77bbSDavid C Somayajulu
2603f10a77bbSDavid C Somayajulu tx_cmd->n_bufs = (uint8_t)nsegs;
2604f10a77bbSDavid C Somayajulu tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF);
2605f10a77bbSDavid C Somayajulu tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8)));
2606f10a77bbSDavid C Somayajulu tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func);
2607f10a77bbSDavid C Somayajulu
2608f10a77bbSDavid C Somayajulu c_seg = segs;
2609f10a77bbSDavid C Somayajulu
2610f10a77bbSDavid C Somayajulu while (1) {
2611f10a77bbSDavid C Somayajulu for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) {
2612f10a77bbSDavid C Somayajulu switch (i) {
2613f10a77bbSDavid C Somayajulu case 0:
2614f10a77bbSDavid C Somayajulu tx_cmd->buf1_addr = c_seg->ds_addr;
2615f10a77bbSDavid C Somayajulu tx_cmd->buf1_len = c_seg->ds_len;
2616f10a77bbSDavid C Somayajulu break;
2617f10a77bbSDavid C Somayajulu
2618f10a77bbSDavid C Somayajulu case 1:
2619f10a77bbSDavid C Somayajulu tx_cmd->buf2_addr = c_seg->ds_addr;
2620f10a77bbSDavid C Somayajulu tx_cmd->buf2_len = c_seg->ds_len;
2621f10a77bbSDavid C Somayajulu break;
2622f10a77bbSDavid C Somayajulu
2623f10a77bbSDavid C Somayajulu case 2:
2624f10a77bbSDavid C Somayajulu tx_cmd->buf3_addr = c_seg->ds_addr;
2625f10a77bbSDavid C Somayajulu tx_cmd->buf3_len = c_seg->ds_len;
2626f10a77bbSDavid C Somayajulu break;
2627f10a77bbSDavid C Somayajulu
2628f10a77bbSDavid C Somayajulu case 3:
2629f10a77bbSDavid C Somayajulu tx_cmd->buf4_addr = c_seg->ds_addr;
2630f10a77bbSDavid C Somayajulu tx_cmd->buf4_len = c_seg->ds_len;
2631f10a77bbSDavid C Somayajulu break;
2632f10a77bbSDavid C Somayajulu }
2633f10a77bbSDavid C Somayajulu
2634f10a77bbSDavid C Somayajulu c_seg++;
2635f10a77bbSDavid C Somayajulu nsegs--;
2636f10a77bbSDavid C Somayajulu }
2637f10a77bbSDavid C Somayajulu
2638f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next =
2639f10a77bbSDavid C Somayajulu (hw->tx_cntxt[txr_idx].txr_next + 1) &
2640f10a77bbSDavid C Somayajulu (NUM_TX_DESCRIPTORS - 1);
2641f10a77bbSDavid C Somayajulu tx_cmd_count++;
2642f10a77bbSDavid C Somayajulu
2643f10a77bbSDavid C Somayajulu if (!nsegs)
2644f10a77bbSDavid C Somayajulu break;
2645f10a77bbSDavid C Somayajulu
2646f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2647f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2648f10a77bbSDavid C Somayajulu }
2649f10a77bbSDavid C Somayajulu
2650f10a77bbSDavid C Somayajulu if (mp->m_pkthdr.csum_flags & CSUM_TSO) {
2651f10a77bbSDavid C Somayajulu /* TSO : Copy the header in the following tx cmd descriptors */
2652f10a77bbSDavid C Somayajulu
2653f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next;
2654f10a77bbSDavid C Somayajulu
2655f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2656f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2657f10a77bbSDavid C Somayajulu
2658f10a77bbSDavid C Somayajulu bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
2659f10a77bbSDavid C Somayajulu bytes = QL_MIN(bytes, hdr_len);
2660f10a77bbSDavid C Somayajulu
2661f10a77bbSDavid C Somayajulu dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN;
2662f10a77bbSDavid C Somayajulu
2663f10a77bbSDavid C Somayajulu if (mp->m_flags & M_VLANTAG) {
2664f10a77bbSDavid C Somayajulu /* first copy the src/dst MAC addresses */
2665f10a77bbSDavid C Somayajulu bcopy(src, dst, (ETHER_ADDR_LEN * 2));
2666f10a77bbSDavid C Somayajulu dst += (ETHER_ADDR_LEN * 2);
2667f10a77bbSDavid C Somayajulu src += (ETHER_ADDR_LEN * 2);
2668f10a77bbSDavid C Somayajulu
2669f10a77bbSDavid C Somayajulu *((uint16_t *)dst) = htons(ETHERTYPE_VLAN);
2670f10a77bbSDavid C Somayajulu dst += 2;
2671f10a77bbSDavid C Somayajulu *((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag);
2672f10a77bbSDavid C Somayajulu dst += 2;
2673f10a77bbSDavid C Somayajulu
2674f10a77bbSDavid C Somayajulu /* bytes left in src header */
2675f10a77bbSDavid C Somayajulu hdr_len -= ((ETHER_ADDR_LEN * 2) +
2676f10a77bbSDavid C Somayajulu ETHER_VLAN_ENCAP_LEN);
2677f10a77bbSDavid C Somayajulu
2678f10a77bbSDavid C Somayajulu /* bytes left in TxCmd Entry */
2679f10a77bbSDavid C Somayajulu bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN);
2680f10a77bbSDavid C Somayajulu
2681f10a77bbSDavid C Somayajulu bcopy(src, dst, bytes);
2682f10a77bbSDavid C Somayajulu src += bytes;
2683f10a77bbSDavid C Somayajulu hdr_len -= bytes;
2684f10a77bbSDavid C Somayajulu } else {
2685f10a77bbSDavid C Somayajulu bcopy(src, dst, bytes);
2686f10a77bbSDavid C Somayajulu src += bytes;
2687f10a77bbSDavid C Somayajulu hdr_len -= bytes;
2688f10a77bbSDavid C Somayajulu }
2689f10a77bbSDavid C Somayajulu
2690f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next =
2691f10a77bbSDavid C Somayajulu (hw->tx_cntxt[txr_idx].txr_next + 1) &
2692f10a77bbSDavid C Somayajulu (NUM_TX_DESCRIPTORS - 1);
2693f10a77bbSDavid C Somayajulu tx_cmd_count++;
2694f10a77bbSDavid C Somayajulu
2695f10a77bbSDavid C Somayajulu while (hdr_len) {
2696f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next];
2697f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
2698f10a77bbSDavid C Somayajulu
2699f10a77bbSDavid C Somayajulu bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
2700f10a77bbSDavid C Somayajulu
2701f10a77bbSDavid C Somayajulu bcopy(src, tx_cmd, bytes);
2702f10a77bbSDavid C Somayajulu src += bytes;
2703f10a77bbSDavid C Somayajulu hdr_len -= bytes;
2704f10a77bbSDavid C Somayajulu
2705f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next =
2706f10a77bbSDavid C Somayajulu (hw->tx_cntxt[txr_idx].txr_next + 1) &
2707f10a77bbSDavid C Somayajulu (NUM_TX_DESCRIPTORS - 1);
2708f10a77bbSDavid C Somayajulu tx_cmd_count++;
2709f10a77bbSDavid C Somayajulu }
2710f10a77bbSDavid C Somayajulu }
2711f10a77bbSDavid C Somayajulu
2712f10a77bbSDavid C Somayajulu hw->tx_cntxt[txr_idx].txr_free =
2713f10a77bbSDavid C Somayajulu hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count;
2714f10a77bbSDavid C Somayajulu
2715f10a77bbSDavid C Somayajulu QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\
2716f10a77bbSDavid C Somayajulu txr_idx);
2717f10a77bbSDavid C Somayajulu QL_DPRINT8(ha, (dev, "%s: return\n", __func__));
2718f10a77bbSDavid C Somayajulu
2719f10a77bbSDavid C Somayajulu return (0);
2720f10a77bbSDavid C Somayajulu }
2721f10a77bbSDavid C Somayajulu
272235291c22SDavid C Somayajulu #define Q8_CONFIG_IND_TBL_SIZE 32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */
2723f10a77bbSDavid C Somayajulu static int
qla_config_rss_ind_table(qla_host_t * ha)2724f10a77bbSDavid C Somayajulu qla_config_rss_ind_table(qla_host_t *ha)
2725f10a77bbSDavid C Somayajulu {
2726f10a77bbSDavid C Somayajulu uint32_t i, count;
272735291c22SDavid C Somayajulu uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE];
2728f10a77bbSDavid C Somayajulu
272935291c22SDavid C Somayajulu for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) {
2730f10a77bbSDavid C Somayajulu rss_ind_tbl[i] = i % ha->hw.num_sds_rings;
2731f10a77bbSDavid C Somayajulu }
2732f10a77bbSDavid C Somayajulu
273335291c22SDavid C Somayajulu for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ;
273435291c22SDavid C Somayajulu i = i + Q8_CONFIG_IND_TBL_SIZE) {
273535291c22SDavid C Somayajulu if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) {
2736f10a77bbSDavid C Somayajulu count = Q8_RSS_IND_TBL_MAX_IDX - i + 1;
2737f10a77bbSDavid C Somayajulu } else {
273835291c22SDavid C Somayajulu count = Q8_CONFIG_IND_TBL_SIZE;
2739f10a77bbSDavid C Somayajulu }
2740f10a77bbSDavid C Somayajulu
2741f10a77bbSDavid C Somayajulu if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id,
2742f10a77bbSDavid C Somayajulu rss_ind_tbl))
2743f10a77bbSDavid C Somayajulu return (-1);
2744f10a77bbSDavid C Somayajulu }
2745f10a77bbSDavid C Somayajulu
2746f10a77bbSDavid C Somayajulu return (0);
2747f10a77bbSDavid C Somayajulu }
2748f10a77bbSDavid C Somayajulu
2749a7c62c11SDavid C Somayajulu static int
qla_config_soft_lro(qla_host_t * ha)2750a7c62c11SDavid C Somayajulu qla_config_soft_lro(qla_host_t *ha)
2751a7c62c11SDavid C Somayajulu {
2752618aa8cdSJohn Baldwin #if defined(INET) || defined(INET6)
2753a7c62c11SDavid C Somayajulu int i;
2754a7c62c11SDavid C Somayajulu qla_hw_t *hw = &ha->hw;
2755a7c62c11SDavid C Somayajulu struct lro_ctrl *lro;
2756a7c62c11SDavid C Somayajulu
2757a7c62c11SDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) {
2758a7c62c11SDavid C Somayajulu lro = &hw->sds[i].lro;
2759a7c62c11SDavid C Somayajulu
2760a7c62c11SDavid C Somayajulu bzero(lro, sizeof(struct lro_ctrl));
2761a7c62c11SDavid C Somayajulu
2762a7c62c11SDavid C Somayajulu if (tcp_lro_init_args(lro, ha->ifp, 0, NUM_RX_DESCRIPTORS)) {
2763a7c62c11SDavid C Somayajulu device_printf(ha->pci_dev,
2764a7c62c11SDavid C Somayajulu "%s: tcp_lro_init_args [%d] failed\n",
2765a7c62c11SDavid C Somayajulu __func__, i);
2766a7c62c11SDavid C Somayajulu return (-1);
2767a7c62c11SDavid C Somayajulu }
2768a7c62c11SDavid C Somayajulu
2769a7c62c11SDavid C Somayajulu lro->ifp = ha->ifp;
2770a7c62c11SDavid C Somayajulu }
2771a7c62c11SDavid C Somayajulu
2772a7c62c11SDavid C Somayajulu QL_DPRINT2(ha, (ha->pci_dev, "%s: LRO initialized\n", __func__));
2773618aa8cdSJohn Baldwin #endif
2774a7c62c11SDavid C Somayajulu return (0);
2775a7c62c11SDavid C Somayajulu }
2776a7c62c11SDavid C Somayajulu
2777a7c62c11SDavid C Somayajulu static void
qla_drain_soft_lro(qla_host_t * ha)2778a7c62c11SDavid C Somayajulu qla_drain_soft_lro(qla_host_t *ha)
2779a7c62c11SDavid C Somayajulu {
2780618aa8cdSJohn Baldwin #if defined(INET) || defined(INET6)
2781a7c62c11SDavid C Somayajulu int i;
2782a7c62c11SDavid C Somayajulu qla_hw_t *hw = &ha->hw;
2783a7c62c11SDavid C Somayajulu struct lro_ctrl *lro;
2784a7c62c11SDavid C Somayajulu
2785a7c62c11SDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) {
2786a7c62c11SDavid C Somayajulu lro = &hw->sds[i].lro;
2787a7c62c11SDavid C Somayajulu
2788a7c62c11SDavid C Somayajulu tcp_lro_flush_all(lro);
2789a7c62c11SDavid C Somayajulu }
2790618aa8cdSJohn Baldwin #endif
2791a7c62c11SDavid C Somayajulu
2792a7c62c11SDavid C Somayajulu return;
2793a7c62c11SDavid C Somayajulu }
2794a7c62c11SDavid C Somayajulu
2795a7c62c11SDavid C Somayajulu static void
qla_free_soft_lro(qla_host_t * ha)2796a7c62c11SDavid C Somayajulu qla_free_soft_lro(qla_host_t *ha)
2797a7c62c11SDavid C Somayajulu {
2798618aa8cdSJohn Baldwin #if defined(INET) || defined(INET6)
2799a7c62c11SDavid C Somayajulu int i;
2800a7c62c11SDavid C Somayajulu qla_hw_t *hw = &ha->hw;
2801a7c62c11SDavid C Somayajulu struct lro_ctrl *lro;
2802a7c62c11SDavid C Somayajulu
2803a7c62c11SDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) {
2804a7c62c11SDavid C Somayajulu lro = &hw->sds[i].lro;
2805a7c62c11SDavid C Somayajulu tcp_lro_free(lro);
2806a7c62c11SDavid C Somayajulu }
2807618aa8cdSJohn Baldwin #endif
2808a7c62c11SDavid C Somayajulu
2809a7c62c11SDavid C Somayajulu return;
2810a7c62c11SDavid C Somayajulu }
2811a7c62c11SDavid C Somayajulu
2812f10a77bbSDavid C Somayajulu /*
2813f10a77bbSDavid C Somayajulu * Name: ql_del_hw_if
2814f10a77bbSDavid C Somayajulu * Function: Destroys the hardware specific entities corresponding to an
2815f10a77bbSDavid C Somayajulu * Ethernet Interface
2816f10a77bbSDavid C Somayajulu */
2817f10a77bbSDavid C Somayajulu void
ql_del_hw_if(qla_host_t * ha)2818f10a77bbSDavid C Somayajulu ql_del_hw_if(qla_host_t *ha)
2819f10a77bbSDavid C Somayajulu {
282035291c22SDavid C Somayajulu uint32_t i;
282135291c22SDavid C Somayajulu uint32_t num_msix;
282235291c22SDavid C Somayajulu
282335291c22SDavid C Somayajulu (void)qla_stop_nic_func(ha);
2824f10a77bbSDavid C Somayajulu
2825f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(ha);
2826da834d52SDavid C Somayajulu
2827b65c0c07SDavid C Somayajulu if(qla_del_xmt_cntxt(ha))
2828b65c0c07SDavid C Somayajulu goto ql_del_hw_if_exit;
2829f10a77bbSDavid C Somayajulu
2830f10a77bbSDavid C Somayajulu if (ha->hw.flags.init_intr_cnxt) {
283135291c22SDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; ) {
283235291c22SDavid C Somayajulu if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
283335291c22SDavid C Somayajulu num_msix = Q8_MAX_INTR_VECTORS;
283435291c22SDavid C Somayajulu else
283535291c22SDavid C Somayajulu num_msix = ha->hw.num_sds_rings - i;
2836b65c0c07SDavid C Somayajulu
2837b65c0c07SDavid C Somayajulu if (qla_config_intr_cntxt(ha, i, num_msix, 0))
2838b65c0c07SDavid C Somayajulu break;
283935291c22SDavid C Somayajulu
284035291c22SDavid C Somayajulu i += num_msix;
284135291c22SDavid C Somayajulu }
284235291c22SDavid C Somayajulu
2843f10a77bbSDavid C Somayajulu ha->hw.flags.init_intr_cnxt = 0;
2844f10a77bbSDavid C Somayajulu }
2845da834d52SDavid C Somayajulu
2846b65c0c07SDavid C Somayajulu ql_del_hw_if_exit:
2847a7c62c11SDavid C Somayajulu if (ha->hw.enable_soft_lro) {
2848a7c62c11SDavid C Somayajulu qla_drain_soft_lro(ha);
2849a7c62c11SDavid C Somayajulu qla_free_soft_lro(ha);
2850a7c62c11SDavid C Somayajulu }
2851a7c62c11SDavid C Somayajulu
285235291c22SDavid C Somayajulu return;
2853f10a77bbSDavid C Somayajulu }
2854f10a77bbSDavid C Somayajulu
285535291c22SDavid C Somayajulu void
qla_confirm_9kb_enable(qla_host_t * ha)285635291c22SDavid C Somayajulu qla_confirm_9kb_enable(qla_host_t *ha)
285735291c22SDavid C Somayajulu {
2858971e53c9SDavid C Somayajulu // uint32_t supports_9kb = 0;
285935291c22SDavid C Somayajulu
286035291c22SDavid C Somayajulu ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX);
286135291c22SDavid C Somayajulu
286235291c22SDavid C Somayajulu /* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */
286335291c22SDavid C Somayajulu WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2);
286435291c22SDavid C Somayajulu WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
286535291c22SDavid C Somayajulu
2866971e53c9SDavid C Somayajulu #if 0
286735291c22SDavid C Somayajulu qla_get_nic_partition(ha, &supports_9kb, NULL);
286835291c22SDavid C Somayajulu
286935291c22SDavid C Somayajulu if (!supports_9kb)
2870971e53c9SDavid C Somayajulu #endif
287135291c22SDavid C Somayajulu ha->hw.enable_9kb = 0;
287235291c22SDavid C Somayajulu
287335291c22SDavid C Somayajulu return;
287435291c22SDavid C Somayajulu }
287535291c22SDavid C Somayajulu
2876f10a77bbSDavid C Somayajulu /*
2877f10a77bbSDavid C Somayajulu * Name: ql_init_hw_if
2878f10a77bbSDavid C Somayajulu * Function: Creates the hardware specific entities corresponding to an
2879f10a77bbSDavid C Somayajulu * Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address
2880f10a77bbSDavid C Somayajulu * corresponding to the interface. Enables LRO if allowed.
2881f10a77bbSDavid C Somayajulu */
2882f10a77bbSDavid C Somayajulu int
ql_init_hw_if(qla_host_t * ha)2883f10a77bbSDavid C Somayajulu ql_init_hw_if(qla_host_t *ha)
2884f10a77bbSDavid C Somayajulu {
2885f10a77bbSDavid C Somayajulu uint32_t i;
2886f10a77bbSDavid C Somayajulu uint8_t bcast_mac[6];
2887f10a77bbSDavid C Somayajulu qla_rdesc_t *rdesc;
288835291c22SDavid C Somayajulu uint32_t num_msix;
2889f10a77bbSDavid C Somayajulu
2890f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) {
2891f10a77bbSDavid C Somayajulu bzero(ha->hw.dma_buf.sds_ring[i].dma_b,
2892f10a77bbSDavid C Somayajulu ha->hw.dma_buf.sds_ring[i].size);
2893f10a77bbSDavid C Somayajulu }
2894f10a77bbSDavid C Somayajulu
289535291c22SDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; ) {
289635291c22SDavid C Somayajulu if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings)
289735291c22SDavid C Somayajulu num_msix = Q8_MAX_INTR_VECTORS;
289835291c22SDavid C Somayajulu else
289935291c22SDavid C Somayajulu num_msix = ha->hw.num_sds_rings - i;
2900f10a77bbSDavid C Somayajulu
290135291c22SDavid C Somayajulu if (qla_config_intr_cntxt(ha, i, num_msix, 1)) {
290235291c22SDavid C Somayajulu if (i > 0) {
290335291c22SDavid C Somayajulu num_msix = i;
290435291c22SDavid C Somayajulu
290535291c22SDavid C Somayajulu for (i = 0; i < num_msix; ) {
290635291c22SDavid C Somayajulu qla_config_intr_cntxt(ha, i,
290735291c22SDavid C Somayajulu Q8_MAX_INTR_VECTORS, 0);
290835291c22SDavid C Somayajulu i += Q8_MAX_INTR_VECTORS;
290935291c22SDavid C Somayajulu }
291035291c22SDavid C Somayajulu }
2911f10a77bbSDavid C Somayajulu return (-1);
291235291c22SDavid C Somayajulu }
291335291c22SDavid C Somayajulu
291435291c22SDavid C Somayajulu i = i + num_msix;
291535291c22SDavid C Somayajulu }
291635291c22SDavid C Somayajulu
291735291c22SDavid C Somayajulu ha->hw.flags.init_intr_cnxt = 1;
2918f10a77bbSDavid C Somayajulu
2919f10a77bbSDavid C Somayajulu /*
2920f10a77bbSDavid C Somayajulu * Create Receive Context
2921f10a77bbSDavid C Somayajulu */
2922f10a77bbSDavid C Somayajulu if (qla_init_rcv_cntxt(ha)) {
2923f10a77bbSDavid C Somayajulu return (-1);
2924f10a77bbSDavid C Somayajulu }
2925f10a77bbSDavid C Somayajulu
2926f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) {
2927f10a77bbSDavid C Somayajulu rdesc = &ha->hw.rds[i];
2928f10a77bbSDavid C Somayajulu rdesc->rx_next = NUM_RX_DESCRIPTORS - 2;
2929f10a77bbSDavid C Somayajulu rdesc->rx_in = 0;
2930f10a77bbSDavid C Somayajulu /* Update the RDS Producer Indices */
2931f10a77bbSDavid C Somayajulu QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\
2932f10a77bbSDavid C Somayajulu rdesc->rx_next);
2933f10a77bbSDavid C Somayajulu }
2934f10a77bbSDavid C Somayajulu
2935f10a77bbSDavid C Somayajulu /*
2936f10a77bbSDavid C Somayajulu * Create Transmit Context
2937f10a77bbSDavid C Somayajulu */
2938f10a77bbSDavid C Somayajulu if (qla_init_xmt_cntxt(ha)) {
2939f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(ha);
2940f10a77bbSDavid C Somayajulu return (-1);
2941f10a77bbSDavid C Somayajulu }
2942f10a77bbSDavid C Somayajulu ha->hw.max_tx_segs = 0;
2943f10a77bbSDavid C Somayajulu
2944da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1, 1))
2945f10a77bbSDavid C Somayajulu return(-1);
2946f10a77bbSDavid C Somayajulu
2947f10a77bbSDavid C Somayajulu ha->hw.flags.unicast_mac = 1;
2948f10a77bbSDavid C Somayajulu
2949f10a77bbSDavid C Somayajulu bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
2950f10a77bbSDavid C Somayajulu bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
2951f10a77bbSDavid C Somayajulu
2952da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, bcast_mac, 1, 1))
2953f10a77bbSDavid C Somayajulu return (-1);
2954f10a77bbSDavid C Somayajulu
2955f10a77bbSDavid C Somayajulu ha->hw.flags.bcast_mac = 1;
2956f10a77bbSDavid C Somayajulu
2957f10a77bbSDavid C Somayajulu /*
2958f10a77bbSDavid C Somayajulu * program any cached multicast addresses
2959f10a77bbSDavid C Somayajulu */
2960f10a77bbSDavid C Somayajulu if (qla_hw_add_all_mcast(ha))
2961f10a77bbSDavid C Somayajulu return (-1);
2962f10a77bbSDavid C Somayajulu
2963b5c2be72SDavid C Somayajulu if (ql_set_max_mtu(ha, ha->max_frame_size, ha->hw.rcv_cntxt_id))
2964b5c2be72SDavid C Somayajulu return (-1);
2965b5c2be72SDavid C Somayajulu
2966f10a77bbSDavid C Somayajulu if (qla_config_rss(ha, ha->hw.rcv_cntxt_id))
2967f10a77bbSDavid C Somayajulu return (-1);
2968f10a77bbSDavid C Somayajulu
2969f10a77bbSDavid C Somayajulu if (qla_config_rss_ind_table(ha))
2970f10a77bbSDavid C Somayajulu return (-1);
2971f10a77bbSDavid C Somayajulu
297235291c22SDavid C Somayajulu if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1))
2973f10a77bbSDavid C Somayajulu return (-1);
2974f10a77bbSDavid C Somayajulu
2975f10a77bbSDavid C Somayajulu if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id))
2976f10a77bbSDavid C Somayajulu return (-1);
2977f10a77bbSDavid C Somayajulu
297854ab3b4aSJustin Hibbits if (if_getcapenable(ha->ifp) & IFCAP_LRO) {
2979a7c62c11SDavid C Somayajulu if (ha->hw.enable_hw_lro) {
2980a7c62c11SDavid C Somayajulu ha->hw.enable_soft_lro = 0;
2981a7c62c11SDavid C Somayajulu
2982f10a77bbSDavid C Somayajulu if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id))
2983f10a77bbSDavid C Somayajulu return (-1);
2984a7c62c11SDavid C Somayajulu } else {
2985a7c62c11SDavid C Somayajulu ha->hw.enable_soft_lro = 1;
2986a7c62c11SDavid C Somayajulu
2987a7c62c11SDavid C Somayajulu if (qla_config_soft_lro(ha))
2988a7c62c11SDavid C Somayajulu return (-1);
2989a7c62c11SDavid C Somayajulu }
2990a7c62c11SDavid C Somayajulu }
2991f10a77bbSDavid C Somayajulu
299235291c22SDavid C Somayajulu if (qla_init_nic_func(ha))
299335291c22SDavid C Somayajulu return (-1);
299435291c22SDavid C Somayajulu
299535291c22SDavid C Somayajulu if (qla_query_fw_dcbx_caps(ha))
299635291c22SDavid C Somayajulu return (-1);
299735291c22SDavid C Somayajulu
2998f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++)
2999f10a77bbSDavid C Somayajulu QL_ENABLE_INTERRUPTS(ha, i);
3000f10a77bbSDavid C Somayajulu
3001f10a77bbSDavid C Somayajulu return (0);
3002f10a77bbSDavid C Somayajulu }
3003f10a77bbSDavid C Somayajulu
3004f10a77bbSDavid C Somayajulu static int
qla_map_sds_to_rds(qla_host_t * ha,uint32_t start_idx,uint32_t num_idx)300535291c22SDavid C Somayajulu qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx)
3006f10a77bbSDavid C Somayajulu {
3007f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
3008f10a77bbSDavid C Somayajulu q80_rq_map_sds_to_rds_t *map_rings;
300935291c22SDavid C Somayajulu q80_rsp_map_sds_to_rds_t *map_rings_rsp;
3010f10a77bbSDavid C Somayajulu uint32_t i, err;
3011f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw;
3012f10a77bbSDavid C Somayajulu
3013f10a77bbSDavid C Somayajulu map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox;
3014f10a77bbSDavid C Somayajulu bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t));
3015f10a77bbSDavid C Somayajulu
3016f10a77bbSDavid C Somayajulu map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS;
3017f10a77bbSDavid C Somayajulu map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2);
3018f10a77bbSDavid C Somayajulu map_rings->count_version |= Q8_MBX_CMD_VERSION;
3019f10a77bbSDavid C Somayajulu
3020f10a77bbSDavid C Somayajulu map_rings->cntxt_id = hw->rcv_cntxt_id;
302135291c22SDavid C Somayajulu map_rings->num_rings = num_idx;
3022f10a77bbSDavid C Somayajulu
302335291c22SDavid C Somayajulu for (i = 0; i < num_idx; i++) {
302435291c22SDavid C Somayajulu map_rings->sds_rds[i].sds_ring = i + start_idx;
302535291c22SDavid C Somayajulu map_rings->sds_rds[i].rds_ring = i + start_idx;
3026f10a77bbSDavid C Somayajulu }
3027f10a77bbSDavid C Somayajulu
3028f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)map_rings,
3029f10a77bbSDavid C Somayajulu (sizeof (q80_rq_map_sds_to_rds_t) >> 2),
3030f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
3031f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__);
3032f10a77bbSDavid C Somayajulu return (-1);
3033f10a77bbSDavid C Somayajulu }
3034f10a77bbSDavid C Somayajulu
303535291c22SDavid C Somayajulu map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox;
3036f10a77bbSDavid C Somayajulu
3037f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status);
3038f10a77bbSDavid C Somayajulu
3039f10a77bbSDavid C Somayajulu if (err) {
3040f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3041f10a77bbSDavid C Somayajulu return (-1);
3042f10a77bbSDavid C Somayajulu }
3043f10a77bbSDavid C Somayajulu
3044f10a77bbSDavid C Somayajulu return (0);
3045f10a77bbSDavid C Somayajulu }
3046f10a77bbSDavid C Somayajulu
3047f10a77bbSDavid C Somayajulu /*
3048f10a77bbSDavid C Somayajulu * Name: qla_init_rcv_cntxt
3049f10a77bbSDavid C Somayajulu * Function: Creates the Receive Context.
3050f10a77bbSDavid C Somayajulu */
3051f10a77bbSDavid C Somayajulu static int
qla_init_rcv_cntxt(qla_host_t * ha)3052f10a77bbSDavid C Somayajulu qla_init_rcv_cntxt(qla_host_t *ha)
3053f10a77bbSDavid C Somayajulu {
3054f10a77bbSDavid C Somayajulu q80_rq_rcv_cntxt_t *rcntxt;
3055f10a77bbSDavid C Somayajulu q80_rsp_rcv_cntxt_t *rcntxt_rsp;
3056f10a77bbSDavid C Somayajulu q80_stat_desc_t *sdesc;
3057f10a77bbSDavid C Somayajulu int i, j;
3058f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw;
3059f10a77bbSDavid C Somayajulu device_t dev;
3060f10a77bbSDavid C Somayajulu uint32_t err;
3061f10a77bbSDavid C Somayajulu uint32_t rcntxt_sds_rings;
3062f10a77bbSDavid C Somayajulu uint32_t rcntxt_rds_rings;
306335291c22SDavid C Somayajulu uint32_t max_idx;
3064f10a77bbSDavid C Somayajulu
3065f10a77bbSDavid C Somayajulu dev = ha->pci_dev;
3066f10a77bbSDavid C Somayajulu
3067f10a77bbSDavid C Somayajulu /*
3068f10a77bbSDavid C Somayajulu * Create Receive Context
3069f10a77bbSDavid C Somayajulu */
3070f10a77bbSDavid C Somayajulu
3071f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) {
3072f10a77bbSDavid C Somayajulu sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0];
3073f10a77bbSDavid C Somayajulu
3074f10a77bbSDavid C Somayajulu for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) {
3075f10a77bbSDavid C Somayajulu sdesc->data[0] = 1ULL;
3076f10a77bbSDavid C Somayajulu sdesc->data[1] = 1ULL;
3077f10a77bbSDavid C Somayajulu }
3078f10a77bbSDavid C Somayajulu }
3079f10a77bbSDavid C Somayajulu
3080f10a77bbSDavid C Somayajulu rcntxt_sds_rings = hw->num_sds_rings;
3081f10a77bbSDavid C Somayajulu if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS)
3082f10a77bbSDavid C Somayajulu rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS;
3083f10a77bbSDavid C Somayajulu
3084f10a77bbSDavid C Somayajulu rcntxt_rds_rings = hw->num_rds_rings;
3085f10a77bbSDavid C Somayajulu
3086f10a77bbSDavid C Somayajulu if (hw->num_rds_rings > MAX_RDS_RING_SETS)
3087f10a77bbSDavid C Somayajulu rcntxt_rds_rings = MAX_RDS_RING_SETS;
3088f10a77bbSDavid C Somayajulu
3089f10a77bbSDavid C Somayajulu rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox;
3090f10a77bbSDavid C Somayajulu bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t)));
3091f10a77bbSDavid C Somayajulu
3092f10a77bbSDavid C Somayajulu rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT;
3093f10a77bbSDavid C Somayajulu rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2);
3094f10a77bbSDavid C Somayajulu rcntxt->count_version |= Q8_MBX_CMD_VERSION;
3095f10a77bbSDavid C Somayajulu
3096f10a77bbSDavid C Somayajulu rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW |
3097f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_LRO |
3098f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_HW_LRO |
3099f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_RSS |
3100f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_SGL_LRO;
3101f10a77bbSDavid C Somayajulu
310235291c22SDavid C Somayajulu if (ha->hw.enable_9kb)
310335291c22SDavid C Somayajulu rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO;
310435291c22SDavid C Somayajulu else
310535291c22SDavid C Somayajulu rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO;
310635291c22SDavid C Somayajulu
3107f10a77bbSDavid C Somayajulu if (ha->hw.num_rds_rings > 1) {
3108f10a77bbSDavid C Somayajulu rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5);
3109f10a77bbSDavid C Somayajulu rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS;
3110f10a77bbSDavid C Somayajulu } else
3111f10a77bbSDavid C Somayajulu rcntxt->nrds_sets_rings = 0x1 | (1 << 5);
3112f10a77bbSDavid C Somayajulu
3113f10a77bbSDavid C Somayajulu rcntxt->nsds_rings = rcntxt_sds_rings;
3114f10a77bbSDavid C Somayajulu
3115f10a77bbSDavid C Somayajulu rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE;
3116f10a77bbSDavid C Somayajulu
3117f10a77bbSDavid C Somayajulu rcntxt->rcv_vpid = 0;
3118f10a77bbSDavid C Somayajulu
3119f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_sds_rings; i++) {
3120f10a77bbSDavid C Somayajulu rcntxt->sds[i].paddr =
3121f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr);
3122f10a77bbSDavid C Somayajulu rcntxt->sds[i].size =
3123f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
3124b89f2279SDavid C Somayajulu rcntxt->sds[i].intr_id = qla_host_to_le16(hw->intr_id[i]);
3125f10a77bbSDavid C Somayajulu rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0);
3126f10a77bbSDavid C Somayajulu }
3127f10a77bbSDavid C Somayajulu
3128f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_rds_rings; i++) {
3129f10a77bbSDavid C Somayajulu rcntxt->rds[i].paddr_std =
3130f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr);
313135291c22SDavid C Somayajulu
313235291c22SDavid C Somayajulu if (ha->hw.enable_9kb)
313335291c22SDavid C Somayajulu rcntxt->rds[i].std_bsize =
313435291c22SDavid C Somayajulu qla_host_to_le64(MJUM9BYTES);
313535291c22SDavid C Somayajulu else
3136f10a77bbSDavid C Somayajulu rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
313735291c22SDavid C Somayajulu
3138f10a77bbSDavid C Somayajulu rcntxt->rds[i].std_nentries =
3139f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_RX_DESCRIPTORS);
3140f10a77bbSDavid C Somayajulu }
3141f10a77bbSDavid C Somayajulu
3142f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
3143f10a77bbSDavid C Somayajulu (sizeof (q80_rq_rcv_cntxt_t) >> 2),
3144f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) {
3145f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__);
3146f10a77bbSDavid C Somayajulu return (-1);
3147f10a77bbSDavid C Somayajulu }
3148f10a77bbSDavid C Somayajulu
3149f10a77bbSDavid C Somayajulu rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox;
3150f10a77bbSDavid C Somayajulu
3151f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
3152f10a77bbSDavid C Somayajulu
3153f10a77bbSDavid C Somayajulu if (err) {
3154f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3155f10a77bbSDavid C Somayajulu return (-1);
3156f10a77bbSDavid C Somayajulu }
3157f10a77bbSDavid C Somayajulu
3158f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_sds_rings; i++) {
3159f10a77bbSDavid C Somayajulu hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i];
3160f10a77bbSDavid C Somayajulu }
3161f10a77bbSDavid C Somayajulu
3162f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_rds_rings; i++) {
3163f10a77bbSDavid C Somayajulu hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std;
3164f10a77bbSDavid C Somayajulu }
3165f10a77bbSDavid C Somayajulu
3166f10a77bbSDavid C Somayajulu hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id;
3167f10a77bbSDavid C Somayajulu
3168f10a77bbSDavid C Somayajulu ha->hw.flags.init_rx_cnxt = 1;
3169f10a77bbSDavid C Somayajulu
3170f10a77bbSDavid C Somayajulu if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) {
317135291c22SDavid C Somayajulu for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) {
317235291c22SDavid C Somayajulu if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings)
317335291c22SDavid C Somayajulu max_idx = MAX_RCNTXT_SDS_RINGS;
317435291c22SDavid C Somayajulu else
317535291c22SDavid C Somayajulu max_idx = hw->num_sds_rings - i;
317635291c22SDavid C Somayajulu
317735291c22SDavid C Somayajulu err = qla_add_rcv_rings(ha, i, max_idx);
3178f10a77bbSDavid C Somayajulu if (err)
3179f10a77bbSDavid C Somayajulu return -1;
318035291c22SDavid C Somayajulu
318135291c22SDavid C Somayajulu i += max_idx;
318235291c22SDavid C Somayajulu }
3183f10a77bbSDavid C Somayajulu }
3184f10a77bbSDavid C Somayajulu
3185f10a77bbSDavid C Somayajulu if (hw->num_rds_rings > 1) {
318635291c22SDavid C Somayajulu for (i = 0; i < hw->num_rds_rings; ) {
318735291c22SDavid C Somayajulu if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings)
318835291c22SDavid C Somayajulu max_idx = MAX_SDS_TO_RDS_MAP;
318935291c22SDavid C Somayajulu else
319035291c22SDavid C Somayajulu max_idx = hw->num_rds_rings - i;
319135291c22SDavid C Somayajulu
319235291c22SDavid C Somayajulu err = qla_map_sds_to_rds(ha, i, max_idx);
3193f10a77bbSDavid C Somayajulu if (err)
3194f10a77bbSDavid C Somayajulu return -1;
319535291c22SDavid C Somayajulu
319635291c22SDavid C Somayajulu i += max_idx;
319735291c22SDavid C Somayajulu }
3198f10a77bbSDavid C Somayajulu }
3199f10a77bbSDavid C Somayajulu
3200f10a77bbSDavid C Somayajulu return (0);
3201f10a77bbSDavid C Somayajulu }
3202f10a77bbSDavid C Somayajulu
3203f10a77bbSDavid C Somayajulu static int
qla_add_rcv_rings(qla_host_t * ha,uint32_t sds_idx,uint32_t nsds)320435291c22SDavid C Somayajulu qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds)
3205f10a77bbSDavid C Somayajulu {
3206f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
3207f10a77bbSDavid C Somayajulu q80_rq_add_rcv_rings_t *add_rcv;
3208f10a77bbSDavid C Somayajulu q80_rsp_add_rcv_rings_t *add_rcv_rsp;
3209f10a77bbSDavid C Somayajulu uint32_t i,j, err;
3210f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw;
3211f10a77bbSDavid C Somayajulu
3212f10a77bbSDavid C Somayajulu add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox;
3213f10a77bbSDavid C Somayajulu bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t));
3214f10a77bbSDavid C Somayajulu
3215f10a77bbSDavid C Somayajulu add_rcv->opcode = Q8_MBX_ADD_RX_RINGS;
3216f10a77bbSDavid C Somayajulu add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2);
3217f10a77bbSDavid C Somayajulu add_rcv->count_version |= Q8_MBX_CMD_VERSION;
3218f10a77bbSDavid C Somayajulu
3219f10a77bbSDavid C Somayajulu add_rcv->nrds_sets_rings = nsds | (1 << 5);
3220f10a77bbSDavid C Somayajulu add_rcv->nsds_rings = nsds;
3221f10a77bbSDavid C Somayajulu add_rcv->cntxt_id = hw->rcv_cntxt_id;
3222f10a77bbSDavid C Somayajulu
3223f10a77bbSDavid C Somayajulu for (i = 0; i < nsds; i++) {
3224f10a77bbSDavid C Somayajulu j = i + sds_idx;
3225f10a77bbSDavid C Somayajulu
3226f10a77bbSDavid C Somayajulu add_rcv->sds[i].paddr =
3227f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr);
3228f10a77bbSDavid C Somayajulu
3229f10a77bbSDavid C Somayajulu add_rcv->sds[i].size =
3230f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_STATUS_DESCRIPTORS);
3231f10a77bbSDavid C Somayajulu
3232b89f2279SDavid C Somayajulu add_rcv->sds[i].intr_id = qla_host_to_le16(hw->intr_id[j]);
3233f10a77bbSDavid C Somayajulu add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0);
3234f10a77bbSDavid C Somayajulu }
3235b89f2279SDavid C Somayajulu
323635291c22SDavid C Somayajulu for (i = 0; (i < nsds); i++) {
3237f10a77bbSDavid C Somayajulu j = i + sds_idx;
323835291c22SDavid C Somayajulu
3239f10a77bbSDavid C Somayajulu add_rcv->rds[i].paddr_std =
3240f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr);
324135291c22SDavid C Somayajulu
324235291c22SDavid C Somayajulu if (ha->hw.enable_9kb)
324335291c22SDavid C Somayajulu add_rcv->rds[i].std_bsize =
324435291c22SDavid C Somayajulu qla_host_to_le64(MJUM9BYTES);
324535291c22SDavid C Somayajulu else
3246f10a77bbSDavid C Somayajulu add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES);
324735291c22SDavid C Somayajulu
3248f10a77bbSDavid C Somayajulu add_rcv->rds[i].std_nentries =
3249f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_RX_DESCRIPTORS);
3250f10a77bbSDavid C Somayajulu }
3251f10a77bbSDavid C Somayajulu
3252f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)add_rcv,
3253f10a77bbSDavid C Somayajulu (sizeof (q80_rq_add_rcv_rings_t) >> 2),
3254f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) {
3255f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__);
3256f10a77bbSDavid C Somayajulu return (-1);
3257f10a77bbSDavid C Somayajulu }
3258f10a77bbSDavid C Somayajulu
3259f10a77bbSDavid C Somayajulu add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox;
3260f10a77bbSDavid C Somayajulu
3261f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status);
3262f10a77bbSDavid C Somayajulu
3263f10a77bbSDavid C Somayajulu if (err) {
3264f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3265f10a77bbSDavid C Somayajulu return (-1);
3266f10a77bbSDavid C Somayajulu }
3267f10a77bbSDavid C Somayajulu
326835291c22SDavid C Somayajulu for (i = 0; i < nsds; i++) {
326935291c22SDavid C Somayajulu hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i];
3270f10a77bbSDavid C Somayajulu }
327135291c22SDavid C Somayajulu
327235291c22SDavid C Somayajulu for (i = 0; i < nsds; i++) {
327335291c22SDavid C Somayajulu hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std;
3274f10a77bbSDavid C Somayajulu }
327535291c22SDavid C Somayajulu
3276f10a77bbSDavid C Somayajulu return (0);
3277f10a77bbSDavid C Somayajulu }
3278f10a77bbSDavid C Somayajulu
3279f10a77bbSDavid C Somayajulu /*
3280f10a77bbSDavid C Somayajulu * Name: qla_del_rcv_cntxt
3281f10a77bbSDavid C Somayajulu * Function: Destroys the Receive Context.
3282f10a77bbSDavid C Somayajulu */
3283f10a77bbSDavid C Somayajulu static void
qla_del_rcv_cntxt(qla_host_t * ha)3284f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(qla_host_t *ha)
3285f10a77bbSDavid C Somayajulu {
3286f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
3287f10a77bbSDavid C Somayajulu q80_rcv_cntxt_destroy_t *rcntxt;
3288f10a77bbSDavid C Somayajulu q80_rcv_cntxt_destroy_rsp_t *rcntxt_rsp;
3289f10a77bbSDavid C Somayajulu uint32_t err;
3290f10a77bbSDavid C Somayajulu uint8_t bcast_mac[6];
3291f10a77bbSDavid C Somayajulu
3292f10a77bbSDavid C Somayajulu if (!ha->hw.flags.init_rx_cnxt)
3293f10a77bbSDavid C Somayajulu return;
3294f10a77bbSDavid C Somayajulu
3295f10a77bbSDavid C Somayajulu if (qla_hw_del_all_mcast(ha))
3296f10a77bbSDavid C Somayajulu return;
3297f10a77bbSDavid C Somayajulu
3298f10a77bbSDavid C Somayajulu if (ha->hw.flags.bcast_mac) {
3299f10a77bbSDavid C Somayajulu bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF;
3300f10a77bbSDavid C Somayajulu bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF;
3301f10a77bbSDavid C Somayajulu
3302da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, bcast_mac, 0, 1))
3303f10a77bbSDavid C Somayajulu return;
3304f10a77bbSDavid C Somayajulu ha->hw.flags.bcast_mac = 0;
3305f10a77bbSDavid C Somayajulu }
3306f10a77bbSDavid C Somayajulu
3307f10a77bbSDavid C Somayajulu if (ha->hw.flags.unicast_mac) {
3308da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0, 1))
3309f10a77bbSDavid C Somayajulu return;
3310f10a77bbSDavid C Somayajulu ha->hw.flags.unicast_mac = 0;
3311f10a77bbSDavid C Somayajulu }
3312f10a77bbSDavid C Somayajulu
3313f10a77bbSDavid C Somayajulu rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox;
3314f10a77bbSDavid C Somayajulu bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t)));
3315f10a77bbSDavid C Somayajulu
3316f10a77bbSDavid C Somayajulu rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT;
3317f10a77bbSDavid C Somayajulu rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2);
3318f10a77bbSDavid C Somayajulu rcntxt->count_version |= Q8_MBX_CMD_VERSION;
3319f10a77bbSDavid C Somayajulu
3320f10a77bbSDavid C Somayajulu rcntxt->cntxt_id = ha->hw.rcv_cntxt_id;
3321f10a77bbSDavid C Somayajulu
3322f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)rcntxt,
3323f10a77bbSDavid C Somayajulu (sizeof (q80_rcv_cntxt_destroy_t) >> 2),
3324f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) {
3325f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__);
3326f10a77bbSDavid C Somayajulu return;
3327f10a77bbSDavid C Somayajulu }
3328f10a77bbSDavid C Somayajulu rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox;
3329f10a77bbSDavid C Somayajulu
3330f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status);
3331f10a77bbSDavid C Somayajulu
3332f10a77bbSDavid C Somayajulu if (err) {
3333f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3334f10a77bbSDavid C Somayajulu }
3335f10a77bbSDavid C Somayajulu
3336f10a77bbSDavid C Somayajulu ha->hw.flags.init_rx_cnxt = 0;
3337f10a77bbSDavid C Somayajulu return;
3338f10a77bbSDavid C Somayajulu }
3339f10a77bbSDavid C Somayajulu
3340f10a77bbSDavid C Somayajulu /*
3341f10a77bbSDavid C Somayajulu * Name: qla_init_xmt_cntxt
3342f10a77bbSDavid C Somayajulu * Function: Creates the Transmit Context.
3343f10a77bbSDavid C Somayajulu */
3344f10a77bbSDavid C Somayajulu static int
qla_init_xmt_cntxt_i(qla_host_t * ha,uint32_t txr_idx)3345f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
3346f10a77bbSDavid C Somayajulu {
3347f10a77bbSDavid C Somayajulu device_t dev;
3348f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw;
3349f10a77bbSDavid C Somayajulu q80_rq_tx_cntxt_t *tcntxt;
3350f10a77bbSDavid C Somayajulu q80_rsp_tx_cntxt_t *tcntxt_rsp;
3351f10a77bbSDavid C Somayajulu uint32_t err;
3352f10a77bbSDavid C Somayajulu qla_hw_tx_cntxt_t *hw_tx_cntxt;
3353b89f2279SDavid C Somayajulu uint32_t intr_idx;
3354f10a77bbSDavid C Somayajulu
3355f10a77bbSDavid C Somayajulu hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3356f10a77bbSDavid C Somayajulu
3357f10a77bbSDavid C Somayajulu dev = ha->pci_dev;
3358f10a77bbSDavid C Somayajulu
3359f10a77bbSDavid C Somayajulu /*
3360f10a77bbSDavid C Somayajulu * Create Transmit Context
3361f10a77bbSDavid C Somayajulu */
3362f10a77bbSDavid C Somayajulu tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox;
3363f10a77bbSDavid C Somayajulu bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t)));
3364f10a77bbSDavid C Somayajulu
3365f10a77bbSDavid C Somayajulu tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT;
3366f10a77bbSDavid C Somayajulu tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2);
3367f10a77bbSDavid C Somayajulu tcntxt->count_version |= Q8_MBX_CMD_VERSION;
3368f10a77bbSDavid C Somayajulu
3369b89f2279SDavid C Somayajulu intr_idx = txr_idx;
3370b89f2279SDavid C Somayajulu
337135291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV
337235291c22SDavid C Somayajulu
337335291c22SDavid C Somayajulu tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO |
337435291c22SDavid C Somayajulu Q8_TX_CNTXT_CAP0_TC;
337535291c22SDavid C Somayajulu
337635291c22SDavid C Somayajulu if (txr_idx >= (ha->hw.num_tx_rings >> 1)) {
337735291c22SDavid C Somayajulu tcntxt->traffic_class = 1;
337835291c22SDavid C Somayajulu }
337935291c22SDavid C Somayajulu
3380b89f2279SDavid C Somayajulu intr_idx = txr_idx % (ha->hw.num_tx_rings >> 1);
338135291c22SDavid C Somayajulu
3382b89f2279SDavid C Somayajulu #else
3383f10a77bbSDavid C Somayajulu tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO;
3384f10a77bbSDavid C Somayajulu
338535291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
338635291c22SDavid C Somayajulu
3387f10a77bbSDavid C Somayajulu tcntxt->ntx_rings = 1;
3388f10a77bbSDavid C Somayajulu
3389f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].paddr =
3390f10a77bbSDavid C Somayajulu qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr);
3391f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].tx_consumer =
3392f10a77bbSDavid C Somayajulu qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr);
3393f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS);
3394f10a77bbSDavid C Somayajulu
3395b89f2279SDavid C Somayajulu tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[intr_idx]);
3396f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0);
3397f10a77bbSDavid C Somayajulu
3398f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS;
3399f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0;
3400c06073f5SDavid C Somayajulu *(hw_tx_cntxt->tx_cons) = 0;
3401f10a77bbSDavid C Somayajulu
3402f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
3403f10a77bbSDavid C Somayajulu (sizeof (q80_rq_tx_cntxt_t) >> 2),
3404f10a77bbSDavid C Somayajulu ha->hw.mbox,
3405f10a77bbSDavid C Somayajulu (sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) {
3406f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__);
3407f10a77bbSDavid C Somayajulu return (-1);
3408f10a77bbSDavid C Somayajulu }
3409f10a77bbSDavid C Somayajulu tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox;
3410f10a77bbSDavid C Somayajulu
3411f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
3412f10a77bbSDavid C Somayajulu
3413f10a77bbSDavid C Somayajulu if (err) {
3414f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3415f10a77bbSDavid C Somayajulu return -1;
3416f10a77bbSDavid C Somayajulu }
3417f10a77bbSDavid C Somayajulu
3418f10a77bbSDavid C Somayajulu hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index;
3419f10a77bbSDavid C Somayajulu hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id;
3420f10a77bbSDavid C Somayajulu
342135291c22SDavid C Somayajulu if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0))
342235291c22SDavid C Somayajulu return (-1);
342335291c22SDavid C Somayajulu
3424f10a77bbSDavid C Somayajulu return (0);
3425f10a77bbSDavid C Somayajulu }
3426f10a77bbSDavid C Somayajulu
3427f10a77bbSDavid C Somayajulu /*
3428f10a77bbSDavid C Somayajulu * Name: qla_del_xmt_cntxt
3429f10a77bbSDavid C Somayajulu * Function: Destroys the Transmit Context.
3430f10a77bbSDavid C Somayajulu */
3431f10a77bbSDavid C Somayajulu static int
qla_del_xmt_cntxt_i(qla_host_t * ha,uint32_t txr_idx)3432f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx)
3433f10a77bbSDavid C Somayajulu {
3434f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
3435f10a77bbSDavid C Somayajulu q80_tx_cntxt_destroy_t *tcntxt;
3436f10a77bbSDavid C Somayajulu q80_tx_cntxt_destroy_rsp_t *tcntxt_rsp;
3437f10a77bbSDavid C Somayajulu uint32_t err;
3438f10a77bbSDavid C Somayajulu
3439f10a77bbSDavid C Somayajulu tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox;
3440f10a77bbSDavid C Somayajulu bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t)));
3441f10a77bbSDavid C Somayajulu
3442f10a77bbSDavid C Somayajulu tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT;
3443f10a77bbSDavid C Somayajulu tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2);
3444f10a77bbSDavid C Somayajulu tcntxt->count_version |= Q8_MBX_CMD_VERSION;
3445f10a77bbSDavid C Somayajulu
3446f10a77bbSDavid C Somayajulu tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id;
3447f10a77bbSDavid C Somayajulu
3448f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)tcntxt,
3449f10a77bbSDavid C Somayajulu (sizeof (q80_tx_cntxt_destroy_t) >> 2),
3450f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) {
3451f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__);
3452f10a77bbSDavid C Somayajulu return (-1);
3453f10a77bbSDavid C Somayajulu }
3454f10a77bbSDavid C Somayajulu tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox;
3455f10a77bbSDavid C Somayajulu
3456f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status);
3457f10a77bbSDavid C Somayajulu
3458f10a77bbSDavid C Somayajulu if (err) {
3459f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err);
3460f10a77bbSDavid C Somayajulu return (-1);
3461f10a77bbSDavid C Somayajulu }
3462f10a77bbSDavid C Somayajulu
3463f10a77bbSDavid C Somayajulu return (0);
3464f10a77bbSDavid C Somayajulu }
3465b65c0c07SDavid C Somayajulu static int
qla_del_xmt_cntxt(qla_host_t * ha)3466f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt(qla_host_t *ha)
3467f10a77bbSDavid C Somayajulu {
3468f10a77bbSDavid C Somayajulu uint32_t i;
3469b65c0c07SDavid C Somayajulu int ret = 0;
3470f10a77bbSDavid C Somayajulu
3471f10a77bbSDavid C Somayajulu if (!ha->hw.flags.init_tx_cnxt)
3472b65c0c07SDavid C Somayajulu return (ret);
3473f10a77bbSDavid C Somayajulu
3474f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) {
3475b65c0c07SDavid C Somayajulu if ((ret = qla_del_xmt_cntxt_i(ha, i)) != 0)
3476f10a77bbSDavid C Somayajulu break;
3477f10a77bbSDavid C Somayajulu }
3478f10a77bbSDavid C Somayajulu ha->hw.flags.init_tx_cnxt = 0;
3479b65c0c07SDavid C Somayajulu
3480b65c0c07SDavid C Somayajulu return (ret);
3481f10a77bbSDavid C Somayajulu }
3482f10a77bbSDavid C Somayajulu
3483f10a77bbSDavid C Somayajulu static int
qla_init_xmt_cntxt(qla_host_t * ha)3484f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt(qla_host_t *ha)
3485f10a77bbSDavid C Somayajulu {
3486f10a77bbSDavid C Somayajulu uint32_t i, j;
3487f10a77bbSDavid C Somayajulu
3488f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) {
3489f10a77bbSDavid C Somayajulu if (qla_init_xmt_cntxt_i(ha, i) != 0) {
3490b65c0c07SDavid C Somayajulu for (j = 0; j < i; j++) {
3491b65c0c07SDavid C Somayajulu if (qla_del_xmt_cntxt_i(ha, j))
3492b65c0c07SDavid C Somayajulu break;
3493b65c0c07SDavid C Somayajulu }
3494f10a77bbSDavid C Somayajulu return (-1);
3495f10a77bbSDavid C Somayajulu }
3496f10a77bbSDavid C Somayajulu }
3497f10a77bbSDavid C Somayajulu ha->hw.flags.init_tx_cnxt = 1;
3498f10a77bbSDavid C Somayajulu return (0);
3499f10a77bbSDavid C Somayajulu }
3500f10a77bbSDavid C Somayajulu
3501f10a77bbSDavid C Somayajulu static int
qla_hw_all_mcast(qla_host_t * ha,uint32_t add_mcast)3502da834d52SDavid C Somayajulu qla_hw_all_mcast(qla_host_t *ha, uint32_t add_mcast)
3503f10a77bbSDavid C Somayajulu {
3504f10a77bbSDavid C Somayajulu int i, nmcast;
3505da834d52SDavid C Somayajulu uint32_t count = 0;
3506da834d52SDavid C Somayajulu uint8_t *mcast;
3507f10a77bbSDavid C Somayajulu
3508f10a77bbSDavid C Somayajulu nmcast = ha->hw.nmcast;
3509f10a77bbSDavid C Somayajulu
3510da834d52SDavid C Somayajulu QL_DPRINT2(ha, (ha->pci_dev,
3511da834d52SDavid C Somayajulu "%s:[0x%x] enter nmcast = %d \n", __func__, add_mcast, nmcast));
3512da834d52SDavid C Somayajulu
3513da834d52SDavid C Somayajulu mcast = ha->hw.mac_addr_arr;
3514da834d52SDavid C Somayajulu memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3515da834d52SDavid C Somayajulu
3516f10a77bbSDavid C Somayajulu for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) {
3517f10a77bbSDavid C Somayajulu if ((ha->hw.mcast[i].addr[0] != 0) ||
3518f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[1] != 0) ||
3519f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[2] != 0) ||
3520f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[3] != 0) ||
3521f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[4] != 0) ||
3522f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[5] != 0)) {
3523da834d52SDavid C Somayajulu bcopy(ha->hw.mcast[i].addr, mcast, ETHER_ADDR_LEN);
3524da834d52SDavid C Somayajulu mcast = mcast + ETHER_ADDR_LEN;
3525da834d52SDavid C Somayajulu count++;
3526da834d52SDavid C Somayajulu
3527971e53c9SDavid C Somayajulu device_printf(ha->pci_dev,
3528971e53c9SDavid C Somayajulu "%s: %x:%x:%x:%x:%x:%x \n",
3529971e53c9SDavid C Somayajulu __func__, ha->hw.mcast[i].addr[0],
3530971e53c9SDavid C Somayajulu ha->hw.mcast[i].addr[1], ha->hw.mcast[i].addr[2],
3531971e53c9SDavid C Somayajulu ha->hw.mcast[i].addr[3], ha->hw.mcast[i].addr[4],
3532971e53c9SDavid C Somayajulu ha->hw.mcast[i].addr[5]);
3533971e53c9SDavid C Somayajulu
3534da834d52SDavid C Somayajulu if (count == Q8_MAX_MAC_ADDRS) {
3535da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3536da834d52SDavid C Somayajulu add_mcast, count)) {
3537da834d52SDavid C Somayajulu device_printf(ha->pci_dev,
3538da834d52SDavid C Somayajulu "%s: failed\n", __func__);
3539f10a77bbSDavid C Somayajulu return (-1);
3540f10a77bbSDavid C Somayajulu }
3541f10a77bbSDavid C Somayajulu
3542da834d52SDavid C Somayajulu count = 0;
3543da834d52SDavid C Somayajulu mcast = ha->hw.mac_addr_arr;
3544da834d52SDavid C Somayajulu memset(mcast, 0,
3545da834d52SDavid C Somayajulu (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3546da834d52SDavid C Somayajulu }
3547da834d52SDavid C Somayajulu
3548f10a77bbSDavid C Somayajulu nmcast--;
3549f10a77bbSDavid C Somayajulu }
3550f10a77bbSDavid C Somayajulu }
3551da834d52SDavid C Somayajulu
3552da834d52SDavid C Somayajulu if (count) {
3553da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mcast,
3554da834d52SDavid C Somayajulu count)) {
3555da834d52SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", __func__);
3556da834d52SDavid C Somayajulu return (-1);
3557da834d52SDavid C Somayajulu }
3558da834d52SDavid C Somayajulu }
3559da834d52SDavid C Somayajulu QL_DPRINT2(ha, (ha->pci_dev,
3560da834d52SDavid C Somayajulu "%s:[0x%x] exit nmcast = %d \n", __func__, add_mcast, nmcast));
3561da834d52SDavid C Somayajulu
3562f10a77bbSDavid C Somayajulu return 0;
3563f10a77bbSDavid C Somayajulu }
3564f10a77bbSDavid C Somayajulu
3565f10a77bbSDavid C Somayajulu static int
qla_hw_add_all_mcast(qla_host_t * ha)3566da834d52SDavid C Somayajulu qla_hw_add_all_mcast(qla_host_t *ha)
3567da834d52SDavid C Somayajulu {
3568da834d52SDavid C Somayajulu int ret;
3569da834d52SDavid C Somayajulu
3570da834d52SDavid C Somayajulu ret = qla_hw_all_mcast(ha, 1);
3571da834d52SDavid C Somayajulu
3572da834d52SDavid C Somayajulu return (ret);
3573da834d52SDavid C Somayajulu }
3574da834d52SDavid C Somayajulu
357561fb8de9SDavid C Somayajulu int
qla_hw_del_all_mcast(qla_host_t * ha)3576f10a77bbSDavid C Somayajulu qla_hw_del_all_mcast(qla_host_t *ha)
3577f10a77bbSDavid C Somayajulu {
3578da834d52SDavid C Somayajulu int ret;
3579f10a77bbSDavid C Somayajulu
3580da834d52SDavid C Somayajulu ret = qla_hw_all_mcast(ha, 0);
3581f10a77bbSDavid C Somayajulu
3582da834d52SDavid C Somayajulu bzero(ha->hw.mcast, (sizeof (qla_mcast_t) * Q8_MAX_NUM_MULTICAST_ADDRS));
3583da834d52SDavid C Somayajulu ha->hw.nmcast = 0;
3584f10a77bbSDavid C Somayajulu
3585da834d52SDavid C Somayajulu return (ret);
3586f10a77bbSDavid C Somayajulu }
3587f10a77bbSDavid C Somayajulu
3588f10a77bbSDavid C Somayajulu static int
qla_hw_mac_addr_present(qla_host_t * ha,uint8_t * mta)3589da834d52SDavid C Somayajulu qla_hw_mac_addr_present(qla_host_t *ha, uint8_t *mta)
3590f10a77bbSDavid C Somayajulu {
3591f10a77bbSDavid C Somayajulu int i;
3592f10a77bbSDavid C Somayajulu
3593f10a77bbSDavid C Somayajulu for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3594f10a77bbSDavid C Somayajulu if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0)
3595da834d52SDavid C Somayajulu return (0); /* its been already added */
3596f10a77bbSDavid C Somayajulu }
3597da834d52SDavid C Somayajulu return (-1);
3598da834d52SDavid C Somayajulu }
3599da834d52SDavid C Somayajulu
3600da834d52SDavid C Somayajulu static int
qla_hw_add_mcast(qla_host_t * ha,uint8_t * mta,uint32_t nmcast)3601da834d52SDavid C Somayajulu qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3602da834d52SDavid C Somayajulu {
3603da834d52SDavid C Somayajulu int i;
3604f10a77bbSDavid C Somayajulu
3605f10a77bbSDavid C Somayajulu for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3606f10a77bbSDavid C Somayajulu if ((ha->hw.mcast[i].addr[0] == 0) &&
3607f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[1] == 0) &&
3608f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[2] == 0) &&
3609f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[3] == 0) &&
3610f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[4] == 0) &&
3611f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[5] == 0)) {
3612f10a77bbSDavid C Somayajulu bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN);
3613f10a77bbSDavid C Somayajulu ha->hw.nmcast++;
3614f10a77bbSDavid C Somayajulu
3615da834d52SDavid C Somayajulu mta = mta + ETHER_ADDR_LEN;
3616da834d52SDavid C Somayajulu nmcast--;
3617da834d52SDavid C Somayajulu
3618da834d52SDavid C Somayajulu if (nmcast == 0)
3619da834d52SDavid C Somayajulu break;
3620f10a77bbSDavid C Somayajulu }
3621f10a77bbSDavid C Somayajulu }
3622f10a77bbSDavid C Somayajulu return 0;
3623f10a77bbSDavid C Somayajulu }
3624f10a77bbSDavid C Somayajulu
3625f10a77bbSDavid C Somayajulu static int
qla_hw_del_mcast(qla_host_t * ha,uint8_t * mta,uint32_t nmcast)3626da834d52SDavid C Somayajulu qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast)
3627f10a77bbSDavid C Somayajulu {
3628f10a77bbSDavid C Somayajulu int i;
3629f10a77bbSDavid C Somayajulu
3630f10a77bbSDavid C Somayajulu for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) {
3631f10a77bbSDavid C Somayajulu if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) {
3632f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[0] = 0;
3633f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[1] = 0;
3634f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[2] = 0;
3635f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[3] = 0;
3636f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[4] = 0;
3637f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[5] = 0;
3638f10a77bbSDavid C Somayajulu
3639f10a77bbSDavid C Somayajulu ha->hw.nmcast--;
3640f10a77bbSDavid C Somayajulu
3641da834d52SDavid C Somayajulu mta = mta + ETHER_ADDR_LEN;
3642da834d52SDavid C Somayajulu nmcast--;
3643da834d52SDavid C Somayajulu
3644da834d52SDavid C Somayajulu if (nmcast == 0)
3645da834d52SDavid C Somayajulu break;
3646f10a77bbSDavid C Somayajulu }
3647f10a77bbSDavid C Somayajulu }
3648f10a77bbSDavid C Somayajulu return 0;
3649f10a77bbSDavid C Somayajulu }
3650f10a77bbSDavid C Somayajulu
3651f10a77bbSDavid C Somayajulu /*
3652f10a77bbSDavid C Somayajulu * Name: ql_hw_set_multi
3653da834d52SDavid C Somayajulu * Function: Sets the Multicast Addresses provided by the host O.S into the
3654f10a77bbSDavid C Somayajulu * hardware (for the given interface)
3655f10a77bbSDavid C Somayajulu */
3656f10a77bbSDavid C Somayajulu int
ql_hw_set_multi(qla_host_t * ha,uint8_t * mcast_addr,uint32_t mcnt,uint32_t add_mac)3657da834d52SDavid C Somayajulu ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast_addr, uint32_t mcnt,
3658f10a77bbSDavid C Somayajulu uint32_t add_mac)
3659f10a77bbSDavid C Somayajulu {
3660da834d52SDavid C Somayajulu uint8_t *mta = mcast_addr;
3661f10a77bbSDavid C Somayajulu int i;
3662f10a77bbSDavid C Somayajulu int ret = 0;
3663da834d52SDavid C Somayajulu uint32_t count = 0;
3664da834d52SDavid C Somayajulu uint8_t *mcast;
3665da834d52SDavid C Somayajulu
3666da834d52SDavid C Somayajulu mcast = ha->hw.mac_addr_arr;
3667da834d52SDavid C Somayajulu memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3668f10a77bbSDavid C Somayajulu
3669f10a77bbSDavid C Somayajulu for (i = 0; i < mcnt; i++) {
3670da834d52SDavid C Somayajulu if (mta[0] || mta[1] || mta[2] || mta[3] || mta[4] || mta[5]) {
3671f10a77bbSDavid C Somayajulu if (add_mac) {
3672da834d52SDavid C Somayajulu if (qla_hw_mac_addr_present(ha, mta) != 0) {
3673da834d52SDavid C Somayajulu bcopy(mta, mcast, ETHER_ADDR_LEN);
3674da834d52SDavid C Somayajulu mcast = mcast + ETHER_ADDR_LEN;
3675da834d52SDavid C Somayajulu count++;
3676da834d52SDavid C Somayajulu }
3677f10a77bbSDavid C Somayajulu } else {
3678da834d52SDavid C Somayajulu if (qla_hw_mac_addr_present(ha, mta) == 0) {
3679da834d52SDavid C Somayajulu bcopy(mta, mcast, ETHER_ADDR_LEN);
3680da834d52SDavid C Somayajulu mcast = mcast + ETHER_ADDR_LEN;
3681da834d52SDavid C Somayajulu count++;
3682da834d52SDavid C Somayajulu }
3683da834d52SDavid C Somayajulu }
3684da834d52SDavid C Somayajulu }
3685da834d52SDavid C Somayajulu if (count == Q8_MAX_MAC_ADDRS) {
3686da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr,
3687da834d52SDavid C Somayajulu add_mac, count)) {
3688da834d52SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n",
3689da834d52SDavid C Somayajulu __func__);
3690da834d52SDavid C Somayajulu return (-1);
3691da834d52SDavid C Somayajulu }
3692da834d52SDavid C Somayajulu
3693da834d52SDavid C Somayajulu if (add_mac) {
3694da834d52SDavid C Somayajulu qla_hw_add_mcast(ha, ha->hw.mac_addr_arr,
3695da834d52SDavid C Somayajulu count);
3696da834d52SDavid C Somayajulu } else {
3697da834d52SDavid C Somayajulu qla_hw_del_mcast(ha, ha->hw.mac_addr_arr,
3698da834d52SDavid C Somayajulu count);
3699da834d52SDavid C Somayajulu }
3700da834d52SDavid C Somayajulu
3701da834d52SDavid C Somayajulu count = 0;
3702da834d52SDavid C Somayajulu mcast = ha->hw.mac_addr_arr;
3703da834d52SDavid C Somayajulu memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN));
3704f10a77bbSDavid C Somayajulu }
3705f10a77bbSDavid C Somayajulu
3706f10a77bbSDavid C Somayajulu mta += Q8_MAC_ADDR_LEN;
3707f10a77bbSDavid C Somayajulu }
3708da834d52SDavid C Somayajulu
3709da834d52SDavid C Somayajulu if (count) {
3710da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mac,
3711da834d52SDavid C Somayajulu count)) {
3712da834d52SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", __func__);
3713da834d52SDavid C Somayajulu return (-1);
3714da834d52SDavid C Somayajulu }
3715da834d52SDavid C Somayajulu if (add_mac) {
3716da834d52SDavid C Somayajulu qla_hw_add_mcast(ha, ha->hw.mac_addr_arr, count);
3717da834d52SDavid C Somayajulu } else {
3718da834d52SDavid C Somayajulu qla_hw_del_mcast(ha, ha->hw.mac_addr_arr, count);
3719da834d52SDavid C Somayajulu }
3720da834d52SDavid C Somayajulu }
3721da834d52SDavid C Somayajulu
3722f10a77bbSDavid C Somayajulu return (ret);
3723f10a77bbSDavid C Somayajulu }
3724f10a77bbSDavid C Somayajulu
3725f10a77bbSDavid C Somayajulu /*
3726b89f2279SDavid C Somayajulu * Name: ql_hw_tx_done_locked
3727f10a77bbSDavid C Somayajulu * Function: Handle Transmit Completions
3728f10a77bbSDavid C Somayajulu */
3729b89f2279SDavid C Somayajulu void
ql_hw_tx_done_locked(qla_host_t * ha,uint32_t txr_idx)3730b89f2279SDavid C Somayajulu ql_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx)
3731f10a77bbSDavid C Somayajulu {
3732f10a77bbSDavid C Somayajulu qla_tx_buf_t *txb;
3733f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw;
3734f10a77bbSDavid C Somayajulu uint32_t comp_idx, comp_count = 0;
3735f10a77bbSDavid C Somayajulu qla_hw_tx_cntxt_t *hw_tx_cntxt;
3736f10a77bbSDavid C Somayajulu
3737f10a77bbSDavid C Somayajulu hw_tx_cntxt = &hw->tx_cntxt[txr_idx];
3738f10a77bbSDavid C Somayajulu
3739f10a77bbSDavid C Somayajulu /* retrieve index of last entry in tx ring completed */
3740f10a77bbSDavid C Somayajulu comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons));
3741f10a77bbSDavid C Somayajulu
3742f10a77bbSDavid C Somayajulu while (comp_idx != hw_tx_cntxt->txr_comp) {
3743f10a77bbSDavid C Somayajulu txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp];
3744f10a77bbSDavid C Somayajulu
3745f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_comp++;
3746f10a77bbSDavid C Somayajulu if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS)
3747f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_comp = 0;
3748f10a77bbSDavid C Somayajulu
3749f10a77bbSDavid C Somayajulu comp_count++;
3750f10a77bbSDavid C Somayajulu
3751f10a77bbSDavid C Somayajulu if (txb->m_head) {
3752c8dfaf38SGleb Smirnoff if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1);
3753f10a77bbSDavid C Somayajulu
3754f10a77bbSDavid C Somayajulu bus_dmamap_sync(ha->tx_tag, txb->map,
3755f10a77bbSDavid C Somayajulu BUS_DMASYNC_POSTWRITE);
3756f10a77bbSDavid C Somayajulu bus_dmamap_unload(ha->tx_tag, txb->map);
3757f10a77bbSDavid C Somayajulu m_freem(txb->m_head);
3758f10a77bbSDavid C Somayajulu
3759f10a77bbSDavid C Somayajulu txb->m_head = NULL;
3760f10a77bbSDavid C Somayajulu }
3761f10a77bbSDavid C Somayajulu }
3762f10a77bbSDavid C Somayajulu
3763f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_free += comp_count;
3764971e53c9SDavid C Somayajulu
3765971e53c9SDavid C Somayajulu if (hw_tx_cntxt->txr_free > NUM_TX_DESCRIPTORS)
3766971e53c9SDavid C Somayajulu device_printf(ha->pci_dev, "%s [%d]: txr_idx = %d txr_free = %d"
3767971e53c9SDavid C Somayajulu "txr_next = %d txr_comp = %d\n", __func__, __LINE__,
3768971e53c9SDavid C Somayajulu txr_idx, hw_tx_cntxt->txr_free,
3769971e53c9SDavid C Somayajulu hw_tx_cntxt->txr_next, hw_tx_cntxt->txr_comp);
3770971e53c9SDavid C Somayajulu
3771971e53c9SDavid C Somayajulu QL_ASSERT(ha, (hw_tx_cntxt->txr_free <= NUM_TX_DESCRIPTORS), \
3772971e53c9SDavid C Somayajulu ("%s [%d]: txr_idx = %d txr_free = %d txr_next = %d txr_comp = %d\n",\
3773971e53c9SDavid C Somayajulu __func__, __LINE__, txr_idx, hw_tx_cntxt->txr_free, \
3774971e53c9SDavid C Somayajulu hw_tx_cntxt->txr_next, hw_tx_cntxt->txr_comp));
3775971e53c9SDavid C Somayajulu
3776f10a77bbSDavid C Somayajulu return;
3777f10a77bbSDavid C Somayajulu }
3778f10a77bbSDavid C Somayajulu
3779f10a77bbSDavid C Somayajulu void
ql_update_link_state(qla_host_t * ha)3780f10a77bbSDavid C Somayajulu ql_update_link_state(qla_host_t *ha)
3781f10a77bbSDavid C Somayajulu {
3782b65c0c07SDavid C Somayajulu uint32_t link_state = 0;
3783f10a77bbSDavid C Somayajulu uint32_t prev_link_state;
3784f10a77bbSDavid C Somayajulu
3785f10a77bbSDavid C Somayajulu prev_link_state = ha->hw.link_up;
3786f10a77bbSDavid C Somayajulu
378754ab3b4aSJustin Hibbits if (if_getdrvflags(ha->ifp) & IFF_DRV_RUNNING) {
3788b65c0c07SDavid C Somayajulu link_state = READ_REG32(ha, Q8_LINK_STATE);
3789b65c0c07SDavid C Somayajulu
3790b65c0c07SDavid C Somayajulu if (ha->pci_func == 0) {
3791b65c0c07SDavid C Somayajulu link_state = (((link_state & 0xF) == 1)? 1 : 0);
3792b65c0c07SDavid C Somayajulu } else {
3793b65c0c07SDavid C Somayajulu link_state = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
3794b65c0c07SDavid C Somayajulu }
3795b65c0c07SDavid C Somayajulu }
3796b65c0c07SDavid C Somayajulu
3797b65c0c07SDavid C Somayajulu atomic_store_rel_8(&ha->hw.link_up, (uint8_t)link_state);
3798f10a77bbSDavid C Somayajulu
3799f10a77bbSDavid C Somayajulu if (prev_link_state != ha->hw.link_up) {
3800f10a77bbSDavid C Somayajulu if (ha->hw.link_up) {
3801f10a77bbSDavid C Somayajulu if_link_state_change(ha->ifp, LINK_STATE_UP);
3802f10a77bbSDavid C Somayajulu } else {
3803f10a77bbSDavid C Somayajulu if_link_state_change(ha->ifp, LINK_STATE_DOWN);
3804f10a77bbSDavid C Somayajulu }
3805f10a77bbSDavid C Somayajulu }
3806f10a77bbSDavid C Somayajulu return;
3807f10a77bbSDavid C Somayajulu }
3808f10a77bbSDavid C Somayajulu
3809f10a77bbSDavid C Somayajulu int
ql_hw_check_health(qla_host_t * ha)3810f10a77bbSDavid C Somayajulu ql_hw_check_health(qla_host_t *ha)
3811f10a77bbSDavid C Somayajulu {
3812f10a77bbSDavid C Somayajulu uint32_t val;
3813f10a77bbSDavid C Somayajulu
3814f10a77bbSDavid C Somayajulu ha->hw.health_count++;
3815f10a77bbSDavid C Somayajulu
381612e46badSDavid C Somayajulu if (ha->hw.health_count < 500)
3817f10a77bbSDavid C Somayajulu return 0;
3818f10a77bbSDavid C Somayajulu
3819f10a77bbSDavid C Somayajulu ha->hw.health_count = 0;
3820f10a77bbSDavid C Somayajulu
3821f10a77bbSDavid C Somayajulu val = READ_REG32(ha, Q8_ASIC_TEMPERATURE);
3822f10a77bbSDavid C Somayajulu
3823f10a77bbSDavid C Somayajulu if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) ||
3824f10a77bbSDavid C Somayajulu (QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) {
3825b65c0c07SDavid C Somayajulu device_printf(ha->pci_dev, "%s: Temperature Alert"
3826b65c0c07SDavid C Somayajulu " at ts_usecs %ld ts_reg = 0x%08x\n",
3827b65c0c07SDavid C Somayajulu __func__, qla_get_usec_timestamp(), val);
3828b65c0c07SDavid C Somayajulu
3829b65c0c07SDavid C Somayajulu if (ha->hw.sp_log_stop_events & Q8_SP_LOG_STOP_TEMP_FAILURE)
3830b65c0c07SDavid C Somayajulu ha->hw.sp_log_stop = -1;
3831b65c0c07SDavid C Somayajulu
3832b65c0c07SDavid C Somayajulu QL_INITIATE_RECOVERY(ha);
3833f10a77bbSDavid C Somayajulu return -1;
3834f10a77bbSDavid C Somayajulu }
3835f10a77bbSDavid C Somayajulu
3836f10a77bbSDavid C Somayajulu val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
3837f10a77bbSDavid C Somayajulu
3838f10a77bbSDavid C Somayajulu if ((val != ha->hw.hbeat_value) &&
3839467dcb5aSDavid C Somayajulu (!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) {
3840f10a77bbSDavid C Somayajulu ha->hw.hbeat_value = val;
384112e46badSDavid C Somayajulu ha->hw.hbeat_failure = 0;
3842f10a77bbSDavid C Somayajulu return 0;
3843f10a77bbSDavid C Somayajulu }
384412e46badSDavid C Somayajulu
384512e46badSDavid C Somayajulu ha->hw.hbeat_failure++;
384612e46badSDavid C Somayajulu
38477fb51846SDavid C Somayajulu if ((ha->dbg_level & 0x8000) && (ha->hw.hbeat_failure == 1))
38487fb51846SDavid C Somayajulu device_printf(ha->pci_dev, "%s: Heartbeat Failue 1[0x%08x]\n",
38497fb51846SDavid C Somayajulu __func__, val);
385012e46badSDavid C Somayajulu if (ha->hw.hbeat_failure < 2) /* we ignore the first failure */
385112e46badSDavid C Somayajulu return 0;
3852b65c0c07SDavid C Somayajulu else {
3853b65c0c07SDavid C Somayajulu uint32_t peg_halt_status1;
3854b65c0c07SDavid C Somayajulu uint32_t peg_halt_status2;
3855b65c0c07SDavid C Somayajulu
3856b65c0c07SDavid C Somayajulu peg_halt_status1 = READ_REG32(ha, Q8_PEG_HALT_STATUS1);
3857b65c0c07SDavid C Somayajulu peg_halt_status2 = READ_REG32(ha, Q8_PEG_HALT_STATUS2);
3858b65c0c07SDavid C Somayajulu
3859b65c0c07SDavid C Somayajulu device_printf(ha->pci_dev,
3860b65c0c07SDavid C Somayajulu "%s: Heartbeat Failue at ts_usecs = %ld "
3861b65c0c07SDavid C Somayajulu "fw_heart_beat = 0x%08x "
3862b65c0c07SDavid C Somayajulu "peg_halt_status1 = 0x%08x "
3863b65c0c07SDavid C Somayajulu "peg_halt_status2 = 0x%08x\n",
3864b65c0c07SDavid C Somayajulu __func__, qla_get_usec_timestamp(), val,
3865b65c0c07SDavid C Somayajulu peg_halt_status1, peg_halt_status2);
3866b65c0c07SDavid C Somayajulu
3867b65c0c07SDavid C Somayajulu if (ha->hw.sp_log_stop_events & Q8_SP_LOG_STOP_HBEAT_FAILURE)
3868b65c0c07SDavid C Somayajulu ha->hw.sp_log_stop = -1;
3869b65c0c07SDavid C Somayajulu }
3870b65c0c07SDavid C Somayajulu QL_INITIATE_RECOVERY(ha);
3871f10a77bbSDavid C Somayajulu
3872f10a77bbSDavid C Somayajulu return -1;
3873f10a77bbSDavid C Somayajulu }
3874f10a77bbSDavid C Somayajulu
3875f10a77bbSDavid C Somayajulu static int
qla_init_nic_func(qla_host_t * ha)387635291c22SDavid C Somayajulu qla_init_nic_func(qla_host_t *ha)
387735291c22SDavid C Somayajulu {
387835291c22SDavid C Somayajulu device_t dev;
387935291c22SDavid C Somayajulu q80_init_nic_func_t *init_nic;
388035291c22SDavid C Somayajulu q80_init_nic_func_rsp_t *init_nic_rsp;
388135291c22SDavid C Somayajulu uint32_t err;
388235291c22SDavid C Somayajulu
388335291c22SDavid C Somayajulu dev = ha->pci_dev;
388435291c22SDavid C Somayajulu
388535291c22SDavid C Somayajulu init_nic = (q80_init_nic_func_t *)ha->hw.mbox;
388635291c22SDavid C Somayajulu bzero(init_nic, sizeof(q80_init_nic_func_t));
388735291c22SDavid C Somayajulu
388835291c22SDavid C Somayajulu init_nic->opcode = Q8_MBX_INIT_NIC_FUNC;
388935291c22SDavid C Somayajulu init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2);
389035291c22SDavid C Somayajulu init_nic->count_version |= Q8_MBX_CMD_VERSION;
389135291c22SDavid C Somayajulu
389235291c22SDavid C Somayajulu init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN;
389335291c22SDavid C Somayajulu init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN;
389435291c22SDavid C Somayajulu init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN;
389535291c22SDavid C Somayajulu
389635291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t));
389735291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)init_nic,
389835291c22SDavid C Somayajulu (sizeof (q80_init_nic_func_t) >> 2),
389935291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) {
390035291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
390135291c22SDavid C Somayajulu return -1;
390235291c22SDavid C Somayajulu }
390335291c22SDavid C Somayajulu
390435291c22SDavid C Somayajulu init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox;
390535291c22SDavid C Somayajulu // qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t));
390635291c22SDavid C Somayajulu
390735291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status);
390835291c22SDavid C Somayajulu
390935291c22SDavid C Somayajulu if (err) {
391035291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
3911971e53c9SDavid C Somayajulu } else {
3912971e53c9SDavid C Somayajulu device_printf(dev, "%s: successful\n", __func__);
391335291c22SDavid C Somayajulu }
391435291c22SDavid C Somayajulu
391535291c22SDavid C Somayajulu return 0;
391635291c22SDavid C Somayajulu }
391735291c22SDavid C Somayajulu
391835291c22SDavid C Somayajulu static int
qla_stop_nic_func(qla_host_t * ha)391935291c22SDavid C Somayajulu qla_stop_nic_func(qla_host_t *ha)
392035291c22SDavid C Somayajulu {
392135291c22SDavid C Somayajulu device_t dev;
392235291c22SDavid C Somayajulu q80_stop_nic_func_t *stop_nic;
392335291c22SDavid C Somayajulu q80_stop_nic_func_rsp_t *stop_nic_rsp;
392435291c22SDavid C Somayajulu uint32_t err;
392535291c22SDavid C Somayajulu
392635291c22SDavid C Somayajulu dev = ha->pci_dev;
392735291c22SDavid C Somayajulu
392835291c22SDavid C Somayajulu stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox;
392935291c22SDavid C Somayajulu bzero(stop_nic, sizeof(q80_stop_nic_func_t));
393035291c22SDavid C Somayajulu
393135291c22SDavid C Somayajulu stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC;
393235291c22SDavid C Somayajulu stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2);
393335291c22SDavid C Somayajulu stop_nic->count_version |= Q8_MBX_CMD_VERSION;
393435291c22SDavid C Somayajulu
393535291c22SDavid C Somayajulu stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN;
393635291c22SDavid C Somayajulu stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN;
393735291c22SDavid C Somayajulu
393835291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t));
393935291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)stop_nic,
394035291c22SDavid C Somayajulu (sizeof (q80_stop_nic_func_t) >> 2),
394135291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) {
394235291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
394335291c22SDavid C Somayajulu return -1;
394435291c22SDavid C Somayajulu }
394535291c22SDavid C Somayajulu
394635291c22SDavid C Somayajulu stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox;
394735291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t));
394835291c22SDavid C Somayajulu
394935291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status);
395035291c22SDavid C Somayajulu
395135291c22SDavid C Somayajulu if (err) {
395235291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
395335291c22SDavid C Somayajulu }
395435291c22SDavid C Somayajulu
395535291c22SDavid C Somayajulu return 0;
395635291c22SDavid C Somayajulu }
395735291c22SDavid C Somayajulu
395835291c22SDavid C Somayajulu static int
qla_query_fw_dcbx_caps(qla_host_t * ha)395935291c22SDavid C Somayajulu qla_query_fw_dcbx_caps(qla_host_t *ha)
396035291c22SDavid C Somayajulu {
396135291c22SDavid C Somayajulu device_t dev;
396235291c22SDavid C Somayajulu q80_query_fw_dcbx_caps_t *fw_dcbx;
396335291c22SDavid C Somayajulu q80_query_fw_dcbx_caps_rsp_t *fw_dcbx_rsp;
396435291c22SDavid C Somayajulu uint32_t err;
396535291c22SDavid C Somayajulu
396635291c22SDavid C Somayajulu dev = ha->pci_dev;
396735291c22SDavid C Somayajulu
396835291c22SDavid C Somayajulu fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox;
396935291c22SDavid C Somayajulu bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t));
397035291c22SDavid C Somayajulu
397135291c22SDavid C Somayajulu fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS;
397235291c22SDavid C Somayajulu fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2);
397335291c22SDavid C Somayajulu fw_dcbx->count_version |= Q8_MBX_CMD_VERSION;
397435291c22SDavid C Somayajulu
397535291c22SDavid C Somayajulu ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t));
397635291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx,
397735291c22SDavid C Somayajulu (sizeof (q80_query_fw_dcbx_caps_t) >> 2),
397835291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) {
397935291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
398035291c22SDavid C Somayajulu return -1;
398135291c22SDavid C Somayajulu }
398235291c22SDavid C Somayajulu
398335291c22SDavid C Somayajulu fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox;
398435291c22SDavid C Somayajulu ql_dump_buf8(ha, __func__, fw_dcbx_rsp,
398535291c22SDavid C Somayajulu sizeof (q80_query_fw_dcbx_caps_rsp_t));
398635291c22SDavid C Somayajulu
398735291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status);
398835291c22SDavid C Somayajulu
398935291c22SDavid C Somayajulu if (err) {
399035291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
399135291c22SDavid C Somayajulu }
399235291c22SDavid C Somayajulu
399335291c22SDavid C Somayajulu return 0;
399435291c22SDavid C Somayajulu }
399535291c22SDavid C Somayajulu
399635291c22SDavid C Somayajulu static int
qla_idc_ack(qla_host_t * ha,uint32_t aen_mb1,uint32_t aen_mb2,uint32_t aen_mb3,uint32_t aen_mb4)399735291c22SDavid C Somayajulu qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2,
399835291c22SDavid C Somayajulu uint32_t aen_mb3, uint32_t aen_mb4)
399935291c22SDavid C Somayajulu {
400035291c22SDavid C Somayajulu device_t dev;
400135291c22SDavid C Somayajulu q80_idc_ack_t *idc_ack;
400235291c22SDavid C Somayajulu q80_idc_ack_rsp_t *idc_ack_rsp;
400335291c22SDavid C Somayajulu uint32_t err;
400435291c22SDavid C Somayajulu int count = 300;
400535291c22SDavid C Somayajulu
400635291c22SDavid C Somayajulu dev = ha->pci_dev;
400735291c22SDavid C Somayajulu
400835291c22SDavid C Somayajulu idc_ack = (q80_idc_ack_t *)ha->hw.mbox;
400935291c22SDavid C Somayajulu bzero(idc_ack, sizeof(q80_idc_ack_t));
401035291c22SDavid C Somayajulu
401135291c22SDavid C Somayajulu idc_ack->opcode = Q8_MBX_IDC_ACK;
401235291c22SDavid C Somayajulu idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2);
401335291c22SDavid C Somayajulu idc_ack->count_version |= Q8_MBX_CMD_VERSION;
401435291c22SDavid C Somayajulu
401535291c22SDavid C Somayajulu idc_ack->aen_mb1 = aen_mb1;
401635291c22SDavid C Somayajulu idc_ack->aen_mb2 = aen_mb2;
401735291c22SDavid C Somayajulu idc_ack->aen_mb3 = aen_mb3;
401835291c22SDavid C Somayajulu idc_ack->aen_mb4 = aen_mb4;
401935291c22SDavid C Somayajulu
402035291c22SDavid C Somayajulu ha->hw.imd_compl= 0;
402135291c22SDavid C Somayajulu
402235291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)idc_ack,
402335291c22SDavid C Somayajulu (sizeof (q80_idc_ack_t) >> 2),
402435291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) {
402535291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
402635291c22SDavid C Somayajulu return -1;
402735291c22SDavid C Somayajulu }
402835291c22SDavid C Somayajulu
402935291c22SDavid C Somayajulu idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox;
403035291c22SDavid C Somayajulu
403135291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status);
403235291c22SDavid C Somayajulu
403335291c22SDavid C Somayajulu if (err) {
403435291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
403535291c22SDavid C Somayajulu return(-1);
403635291c22SDavid C Somayajulu }
403735291c22SDavid C Somayajulu
403835291c22SDavid C Somayajulu while (count && !ha->hw.imd_compl) {
403935291c22SDavid C Somayajulu qla_mdelay(__func__, 100);
404035291c22SDavid C Somayajulu count--;
404135291c22SDavid C Somayajulu }
404235291c22SDavid C Somayajulu
404335291c22SDavid C Somayajulu if (!count)
404435291c22SDavid C Somayajulu return -1;
404535291c22SDavid C Somayajulu else
404635291c22SDavid C Somayajulu device_printf(dev, "%s: count %d\n", __func__, count);
404735291c22SDavid C Somayajulu
404835291c22SDavid C Somayajulu return (0);
404935291c22SDavid C Somayajulu }
405035291c22SDavid C Somayajulu
405135291c22SDavid C Somayajulu static int
qla_set_port_config(qla_host_t * ha,uint32_t cfg_bits)405235291c22SDavid C Somayajulu qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits)
405335291c22SDavid C Somayajulu {
405435291c22SDavid C Somayajulu device_t dev;
405535291c22SDavid C Somayajulu q80_set_port_cfg_t *pcfg;
405635291c22SDavid C Somayajulu q80_set_port_cfg_rsp_t *pfg_rsp;
405735291c22SDavid C Somayajulu uint32_t err;
405835291c22SDavid C Somayajulu int count = 300;
405935291c22SDavid C Somayajulu
406035291c22SDavid C Somayajulu dev = ha->pci_dev;
406135291c22SDavid C Somayajulu
406235291c22SDavid C Somayajulu pcfg = (q80_set_port_cfg_t *)ha->hw.mbox;
406335291c22SDavid C Somayajulu bzero(pcfg, sizeof(q80_set_port_cfg_t));
406435291c22SDavid C Somayajulu
406535291c22SDavid C Somayajulu pcfg->opcode = Q8_MBX_SET_PORT_CONFIG;
406635291c22SDavid C Somayajulu pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2);
406735291c22SDavid C Somayajulu pcfg->count_version |= Q8_MBX_CMD_VERSION;
406835291c22SDavid C Somayajulu
406935291c22SDavid C Somayajulu pcfg->cfg_bits = cfg_bits;
407035291c22SDavid C Somayajulu
407135291c22SDavid C Somayajulu device_printf(dev, "%s: cfg_bits"
407235291c22SDavid C Somayajulu " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
407335291c22SDavid C Somayajulu " [0x%x, 0x%x, 0x%x]\n", __func__,
407435291c22SDavid C Somayajulu ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
407535291c22SDavid C Somayajulu ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
407635291c22SDavid C Somayajulu ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0));
407735291c22SDavid C Somayajulu
407835291c22SDavid C Somayajulu ha->hw.imd_compl= 0;
407935291c22SDavid C Somayajulu
408035291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
408135291c22SDavid C Somayajulu (sizeof (q80_set_port_cfg_t) >> 2),
408235291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) {
408335291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
408435291c22SDavid C Somayajulu return -1;
408535291c22SDavid C Somayajulu }
408635291c22SDavid C Somayajulu
408735291c22SDavid C Somayajulu pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox;
408835291c22SDavid C Somayajulu
408935291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status);
409035291c22SDavid C Somayajulu
409135291c22SDavid C Somayajulu if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) {
409235291c22SDavid C Somayajulu while (count && !ha->hw.imd_compl) {
409335291c22SDavid C Somayajulu qla_mdelay(__func__, 100);
409435291c22SDavid C Somayajulu count--;
409535291c22SDavid C Somayajulu }
409635291c22SDavid C Somayajulu if (count) {
409735291c22SDavid C Somayajulu device_printf(dev, "%s: count %d\n", __func__, count);
409835291c22SDavid C Somayajulu
409935291c22SDavid C Somayajulu err = 0;
410035291c22SDavid C Somayajulu }
410135291c22SDavid C Somayajulu }
410235291c22SDavid C Somayajulu
410335291c22SDavid C Somayajulu if (err) {
410435291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
410535291c22SDavid C Somayajulu return(-1);
410635291c22SDavid C Somayajulu }
410735291c22SDavid C Somayajulu
410835291c22SDavid C Somayajulu return (0);
410935291c22SDavid C Somayajulu }
411035291c22SDavid C Somayajulu
411135291c22SDavid C Somayajulu static int
qla_get_minidump_tmplt_size(qla_host_t * ha,uint32_t * size)4112f10a77bbSDavid C Somayajulu qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size)
4113f10a77bbSDavid C Somayajulu {
4114f10a77bbSDavid C Somayajulu uint32_t err;
4115f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
4116f10a77bbSDavid C Somayajulu q80_config_md_templ_size_t *md_size;
4117f10a77bbSDavid C Somayajulu q80_config_md_templ_size_rsp_t *md_size_rsp;
4118f10a77bbSDavid C Somayajulu
41196a62bec0SDavid C Somayajulu #ifndef QL_LDFLASH_FW
412035291c22SDavid C Somayajulu
41216a62bec0SDavid C Somayajulu ql_minidump_template_hdr_t *hdr;
41226a62bec0SDavid C Somayajulu
41236a62bec0SDavid C Somayajulu hdr = (ql_minidump_template_hdr_t *)ql83xx_minidump;
41246a62bec0SDavid C Somayajulu *size = hdr->size_of_template;
412535291c22SDavid C Somayajulu return (0);
412635291c22SDavid C Somayajulu
412735291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
412835291c22SDavid C Somayajulu
4129f10a77bbSDavid C Somayajulu md_size = (q80_config_md_templ_size_t *) ha->hw.mbox;
4130f10a77bbSDavid C Somayajulu bzero(md_size, sizeof(q80_config_md_templ_size_t));
4131f10a77bbSDavid C Somayajulu
4132f10a77bbSDavid C Somayajulu md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE;
4133f10a77bbSDavid C Somayajulu md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2);
4134f10a77bbSDavid C Somayajulu md_size->count_version |= Q8_MBX_CMD_VERSION;
4135f10a77bbSDavid C Somayajulu
4136f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *) md_size,
4137f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox,
4138f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) {
4139f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
4140f10a77bbSDavid C Somayajulu
4141f10a77bbSDavid C Somayajulu return (-1);
4142f10a77bbSDavid C Somayajulu }
4143f10a77bbSDavid C Somayajulu
4144f10a77bbSDavid C Somayajulu md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox;
4145f10a77bbSDavid C Somayajulu
4146f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status);
4147f10a77bbSDavid C Somayajulu
4148f10a77bbSDavid C Somayajulu if (err) {
4149f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4150f10a77bbSDavid C Somayajulu return(-1);
4151f10a77bbSDavid C Somayajulu }
4152f10a77bbSDavid C Somayajulu
4153f10a77bbSDavid C Somayajulu *size = md_size_rsp->templ_size;
4154f10a77bbSDavid C Somayajulu
4155f10a77bbSDavid C Somayajulu return (0);
4156f10a77bbSDavid C Somayajulu }
4157f10a77bbSDavid C Somayajulu
4158f10a77bbSDavid C Somayajulu static int
qla_get_port_config(qla_host_t * ha,uint32_t * cfg_bits)415935291c22SDavid C Somayajulu qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits)
416035291c22SDavid C Somayajulu {
416135291c22SDavid C Somayajulu device_t dev;
416235291c22SDavid C Somayajulu q80_get_port_cfg_t *pcfg;
416335291c22SDavid C Somayajulu q80_get_port_cfg_rsp_t *pcfg_rsp;
416435291c22SDavid C Somayajulu uint32_t err;
416535291c22SDavid C Somayajulu
416635291c22SDavid C Somayajulu dev = ha->pci_dev;
416735291c22SDavid C Somayajulu
416835291c22SDavid C Somayajulu pcfg = (q80_get_port_cfg_t *)ha->hw.mbox;
416935291c22SDavid C Somayajulu bzero(pcfg, sizeof(q80_get_port_cfg_t));
417035291c22SDavid C Somayajulu
417135291c22SDavid C Somayajulu pcfg->opcode = Q8_MBX_GET_PORT_CONFIG;
417235291c22SDavid C Somayajulu pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2);
417335291c22SDavid C Somayajulu pcfg->count_version |= Q8_MBX_CMD_VERSION;
417435291c22SDavid C Somayajulu
417535291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)pcfg,
417635291c22SDavid C Somayajulu (sizeof (q80_get_port_cfg_t) >> 2),
417735291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) {
417835291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
417935291c22SDavid C Somayajulu return -1;
418035291c22SDavid C Somayajulu }
418135291c22SDavid C Somayajulu
418235291c22SDavid C Somayajulu pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox;
418335291c22SDavid C Somayajulu
418435291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status);
418535291c22SDavid C Somayajulu
418635291c22SDavid C Somayajulu if (err) {
418735291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
418835291c22SDavid C Somayajulu return(-1);
418935291c22SDavid C Somayajulu }
419035291c22SDavid C Somayajulu
419135291c22SDavid C Somayajulu device_printf(dev, "%s: [cfg_bits, port type]"
419235291c22SDavid C Somayajulu " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]"
419335291c22SDavid C Somayajulu " [0x%x, 0x%x, 0x%x]\n", __func__,
419435291c22SDavid C Somayajulu pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type,
419535291c22SDavid C Somayajulu ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20),
419635291c22SDavid C Somayajulu ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5),
419735291c22SDavid C Somayajulu ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)
419835291c22SDavid C Somayajulu );
419935291c22SDavid C Somayajulu
420035291c22SDavid C Somayajulu *cfg_bits = pcfg_rsp->cfg_bits;
420135291c22SDavid C Somayajulu
420235291c22SDavid C Somayajulu return (0);
420335291c22SDavid C Somayajulu }
420435291c22SDavid C Somayajulu
420535291c22SDavid C Somayajulu int
ql_iscsi_pdu(qla_host_t * ha,struct mbuf * mp)4206b89f2279SDavid C Somayajulu ql_iscsi_pdu(qla_host_t *ha, struct mbuf *mp)
420735291c22SDavid C Somayajulu {
420835291c22SDavid C Somayajulu struct ether_vlan_header *eh;
420935291c22SDavid C Somayajulu uint16_t etype;
421035291c22SDavid C Somayajulu struct ip *ip = NULL;
421135291c22SDavid C Somayajulu struct ip6_hdr *ip6 = NULL;
421235291c22SDavid C Somayajulu struct tcphdr *th = NULL;
421335291c22SDavid C Somayajulu uint32_t hdrlen;
421435291c22SDavid C Somayajulu uint32_t offset;
421535291c22SDavid C Somayajulu uint8_t buf[sizeof(struct ip6_hdr)];
421635291c22SDavid C Somayajulu
421735291c22SDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *);
421835291c22SDavid C Somayajulu
421935291c22SDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
422035291c22SDavid C Somayajulu hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
422135291c22SDavid C Somayajulu etype = ntohs(eh->evl_proto);
422235291c22SDavid C Somayajulu } else {
422335291c22SDavid C Somayajulu hdrlen = ETHER_HDR_LEN;
422435291c22SDavid C Somayajulu etype = ntohs(eh->evl_encap_proto);
422535291c22SDavid C Somayajulu }
422635291c22SDavid C Somayajulu
422735291c22SDavid C Somayajulu if (etype == ETHERTYPE_IP) {
422835291c22SDavid C Somayajulu offset = (hdrlen + sizeof (struct ip));
422935291c22SDavid C Somayajulu
423035291c22SDavid C Somayajulu if (mp->m_len >= offset) {
423135291c22SDavid C Somayajulu ip = (struct ip *)(mp->m_data + hdrlen);
423235291c22SDavid C Somayajulu } else {
423335291c22SDavid C Somayajulu m_copydata(mp, hdrlen, sizeof (struct ip), buf);
423435291c22SDavid C Somayajulu ip = (struct ip *)buf;
423535291c22SDavid C Somayajulu }
423635291c22SDavid C Somayajulu
423735291c22SDavid C Somayajulu if (ip->ip_p == IPPROTO_TCP) {
423835291c22SDavid C Somayajulu hdrlen += ip->ip_hl << 2;
423935291c22SDavid C Somayajulu offset = hdrlen + 4;
424035291c22SDavid C Somayajulu
424135291c22SDavid C Somayajulu if (mp->m_len >= offset) {
4242aeb665b5SEd Maste th = (struct tcphdr *)(mp->m_data + hdrlen);
424335291c22SDavid C Somayajulu } else {
424435291c22SDavid C Somayajulu m_copydata(mp, hdrlen, 4, buf);
424535291c22SDavid C Somayajulu th = (struct tcphdr *)buf;
424635291c22SDavid C Somayajulu }
424735291c22SDavid C Somayajulu }
424835291c22SDavid C Somayajulu
424935291c22SDavid C Somayajulu } else if (etype == ETHERTYPE_IPV6) {
425035291c22SDavid C Somayajulu offset = (hdrlen + sizeof (struct ip6_hdr));
425135291c22SDavid C Somayajulu
425235291c22SDavid C Somayajulu if (mp->m_len >= offset) {
425335291c22SDavid C Somayajulu ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen);
425435291c22SDavid C Somayajulu } else {
425535291c22SDavid C Somayajulu m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf);
425635291c22SDavid C Somayajulu ip6 = (struct ip6_hdr *)buf;
425735291c22SDavid C Somayajulu }
425835291c22SDavid C Somayajulu
425935291c22SDavid C Somayajulu if (ip6->ip6_nxt == IPPROTO_TCP) {
426035291c22SDavid C Somayajulu hdrlen += sizeof(struct ip6_hdr);
426135291c22SDavid C Somayajulu offset = hdrlen + 4;
426235291c22SDavid C Somayajulu
426335291c22SDavid C Somayajulu if (mp->m_len >= offset) {
4264aeb665b5SEd Maste th = (struct tcphdr *)(mp->m_data + hdrlen);
426535291c22SDavid C Somayajulu } else {
426635291c22SDavid C Somayajulu m_copydata(mp, hdrlen, 4, buf);
426735291c22SDavid C Somayajulu th = (struct tcphdr *)buf;
426835291c22SDavid C Somayajulu }
426935291c22SDavid C Somayajulu }
427035291c22SDavid C Somayajulu }
427135291c22SDavid C Somayajulu
427235291c22SDavid C Somayajulu if (th != NULL) {
427335291c22SDavid C Somayajulu if ((th->th_sport == htons(3260)) ||
427435291c22SDavid C Somayajulu (th->th_dport == htons(3260)))
427535291c22SDavid C Somayajulu return 0;
427635291c22SDavid C Somayajulu }
427735291c22SDavid C Somayajulu return (-1);
427835291c22SDavid C Somayajulu }
427935291c22SDavid C Somayajulu
428035291c22SDavid C Somayajulu void
qla_hw_async_event(qla_host_t * ha)428135291c22SDavid C Somayajulu qla_hw_async_event(qla_host_t *ha)
428235291c22SDavid C Somayajulu {
428335291c22SDavid C Somayajulu switch (ha->hw.aen_mb0) {
428435291c22SDavid C Somayajulu case 0x8101:
428535291c22SDavid C Somayajulu (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2,
428635291c22SDavid C Somayajulu ha->hw.aen_mb3, ha->hw.aen_mb4);
428735291c22SDavid C Somayajulu
428835291c22SDavid C Somayajulu break;
428935291c22SDavid C Somayajulu
429035291c22SDavid C Somayajulu default:
429135291c22SDavid C Somayajulu break;
429235291c22SDavid C Somayajulu }
429335291c22SDavid C Somayajulu
429435291c22SDavid C Somayajulu return;
429535291c22SDavid C Somayajulu }
429635291c22SDavid C Somayajulu
429735291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
429835291c22SDavid C Somayajulu static int
ql_get_minidump_template(qla_host_t * ha)42996a62bec0SDavid C Somayajulu ql_get_minidump_template(qla_host_t *ha)
4300f10a77bbSDavid C Somayajulu {
4301f10a77bbSDavid C Somayajulu uint32_t err;
4302f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
4303f10a77bbSDavid C Somayajulu q80_config_md_templ_cmd_t *md_templ;
4304f10a77bbSDavid C Somayajulu q80_config_md_templ_cmd_rsp_t *md_templ_rsp;
4305f10a77bbSDavid C Somayajulu
4306f10a77bbSDavid C Somayajulu md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox;
4307f10a77bbSDavid C Somayajulu bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t)));
4308f10a77bbSDavid C Somayajulu
4309f10a77bbSDavid C Somayajulu md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT;
4310f10a77bbSDavid C Somayajulu md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2);
4311f10a77bbSDavid C Somayajulu md_templ->count_version |= Q8_MBX_CMD_VERSION;
4312f10a77bbSDavid C Somayajulu
4313f10a77bbSDavid C Somayajulu md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr;
4314f10a77bbSDavid C Somayajulu md_templ->buff_size = ha->hw.dma_buf.minidump.size;
4315f10a77bbSDavid C Somayajulu
4316f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *) md_templ,
4317f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_cmd_t) >> 2),
4318f10a77bbSDavid C Somayajulu ha->hw.mbox,
4319f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) {
4320f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__);
4321f10a77bbSDavid C Somayajulu
4322f10a77bbSDavid C Somayajulu return (-1);
4323f10a77bbSDavid C Somayajulu }
4324f10a77bbSDavid C Somayajulu
4325f10a77bbSDavid C Somayajulu md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox;
4326f10a77bbSDavid C Somayajulu
4327f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status);
4328f10a77bbSDavid C Somayajulu
4329f10a77bbSDavid C Somayajulu if (err) {
4330f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err);
4331f10a77bbSDavid C Somayajulu return (-1);
4332f10a77bbSDavid C Somayajulu }
4333f10a77bbSDavid C Somayajulu
4334f10a77bbSDavid C Somayajulu return (0);
4335f10a77bbSDavid C Somayajulu
4336f10a77bbSDavid C Somayajulu }
433735291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
4338f10a77bbSDavid C Somayajulu
43396a62bec0SDavid C Somayajulu /*
43406a62bec0SDavid C Somayajulu * Minidump related functionality
43416a62bec0SDavid C Somayajulu */
43426a62bec0SDavid C Somayajulu
43436a62bec0SDavid C Somayajulu static int ql_parse_template(qla_host_t *ha);
43446a62bec0SDavid C Somayajulu
43456a62bec0SDavid C Somayajulu static uint32_t ql_rdcrb(qla_host_t *ha,
43466a62bec0SDavid C Somayajulu ql_minidump_entry_rdcrb_t *crb_entry,
43476a62bec0SDavid C Somayajulu uint32_t * data_buff);
43486a62bec0SDavid C Somayajulu
43496a62bec0SDavid C Somayajulu static uint32_t ql_pollrd(qla_host_t *ha,
43506a62bec0SDavid C Somayajulu ql_minidump_entry_pollrd_t *entry,
43516a62bec0SDavid C Somayajulu uint32_t * data_buff);
43526a62bec0SDavid C Somayajulu
43536a62bec0SDavid C Somayajulu static uint32_t ql_pollrd_modify_write(qla_host_t *ha,
43546a62bec0SDavid C Somayajulu ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
43556a62bec0SDavid C Somayajulu uint32_t *data_buff);
43566a62bec0SDavid C Somayajulu
43576a62bec0SDavid C Somayajulu static uint32_t ql_L2Cache(qla_host_t *ha,
43586a62bec0SDavid C Somayajulu ql_minidump_entry_cache_t *cacheEntry,
43596a62bec0SDavid C Somayajulu uint32_t * data_buff);
43606a62bec0SDavid C Somayajulu
43616a62bec0SDavid C Somayajulu static uint32_t ql_L1Cache(qla_host_t *ha,
43626a62bec0SDavid C Somayajulu ql_minidump_entry_cache_t *cacheEntry,
43636a62bec0SDavid C Somayajulu uint32_t *data_buff);
43646a62bec0SDavid C Somayajulu
43656a62bec0SDavid C Somayajulu static uint32_t ql_rdocm(qla_host_t *ha,
43666a62bec0SDavid C Somayajulu ql_minidump_entry_rdocm_t *ocmEntry,
43676a62bec0SDavid C Somayajulu uint32_t *data_buff);
43686a62bec0SDavid C Somayajulu
43696a62bec0SDavid C Somayajulu static uint32_t ql_rdmem(qla_host_t *ha,
43706a62bec0SDavid C Somayajulu ql_minidump_entry_rdmem_t *mem_entry,
43716a62bec0SDavid C Somayajulu uint32_t *data_buff);
43726a62bec0SDavid C Somayajulu
43736a62bec0SDavid C Somayajulu static uint32_t ql_rdrom(qla_host_t *ha,
43746a62bec0SDavid C Somayajulu ql_minidump_entry_rdrom_t *romEntry,
43756a62bec0SDavid C Somayajulu uint32_t *data_buff);
43766a62bec0SDavid C Somayajulu
43776a62bec0SDavid C Somayajulu static uint32_t ql_rdmux(qla_host_t *ha,
43786a62bec0SDavid C Somayajulu ql_minidump_entry_mux_t *muxEntry,
43796a62bec0SDavid C Somayajulu uint32_t *data_buff);
43806a62bec0SDavid C Somayajulu
43816a62bec0SDavid C Somayajulu static uint32_t ql_rdmux2(qla_host_t *ha,
43826a62bec0SDavid C Somayajulu ql_minidump_entry_mux2_t *muxEntry,
43836a62bec0SDavid C Somayajulu uint32_t *data_buff);
43846a62bec0SDavid C Somayajulu
43856a62bec0SDavid C Somayajulu static uint32_t ql_rdqueue(qla_host_t *ha,
43866a62bec0SDavid C Somayajulu ql_minidump_entry_queue_t *queueEntry,
43876a62bec0SDavid C Somayajulu uint32_t *data_buff);
43886a62bec0SDavid C Somayajulu
43896a62bec0SDavid C Somayajulu static uint32_t ql_cntrl(qla_host_t *ha,
43906a62bec0SDavid C Somayajulu ql_minidump_template_hdr_t *template_hdr,
43916a62bec0SDavid C Somayajulu ql_minidump_entry_cntrl_t *crbEntry);
43926a62bec0SDavid C Somayajulu
43936a62bec0SDavid C Somayajulu static uint32_t
ql_minidump_size(qla_host_t * ha)43946a62bec0SDavid C Somayajulu ql_minidump_size(qla_host_t *ha)
43956a62bec0SDavid C Somayajulu {
43966a62bec0SDavid C Somayajulu uint32_t i, k;
43976a62bec0SDavid C Somayajulu uint32_t size = 0;
43986a62bec0SDavid C Somayajulu ql_minidump_template_hdr_t *hdr;
43996a62bec0SDavid C Somayajulu
44006a62bec0SDavid C Somayajulu hdr = (ql_minidump_template_hdr_t *)ha->hw.dma_buf.minidump.dma_b;
44016a62bec0SDavid C Somayajulu
44026a62bec0SDavid C Somayajulu i = 0x2;
44036a62bec0SDavid C Somayajulu
44046a62bec0SDavid C Somayajulu for (k = 1; k < QL_DBG_CAP_SIZE_ARRAY_LEN; k++) {
44056a62bec0SDavid C Somayajulu if (i & ha->hw.mdump_capture_mask)
44066a62bec0SDavid C Somayajulu size += hdr->capture_size_array[k];
44076a62bec0SDavid C Somayajulu i = i << 1;
44086a62bec0SDavid C Somayajulu }
44096a62bec0SDavid C Somayajulu return (size);
44106a62bec0SDavid C Somayajulu }
44116a62bec0SDavid C Somayajulu
44126a62bec0SDavid C Somayajulu static void
ql_free_minidump_buffer(qla_host_t * ha)44136a62bec0SDavid C Somayajulu ql_free_minidump_buffer(qla_host_t *ha)
44146a62bec0SDavid C Somayajulu {
44156a62bec0SDavid C Somayajulu if (ha->hw.mdump_buffer != NULL) {
44166a62bec0SDavid C Somayajulu free(ha->hw.mdump_buffer, M_QLA83XXBUF);
44176a62bec0SDavid C Somayajulu ha->hw.mdump_buffer = NULL;
44186a62bec0SDavid C Somayajulu ha->hw.mdump_buffer_size = 0;
44196a62bec0SDavid C Somayajulu }
44206a62bec0SDavid C Somayajulu return;
44216a62bec0SDavid C Somayajulu }
44226a62bec0SDavid C Somayajulu
4423f10a77bbSDavid C Somayajulu static int
ql_alloc_minidump_buffer(qla_host_t * ha)44246a62bec0SDavid C Somayajulu ql_alloc_minidump_buffer(qla_host_t *ha)
44256a62bec0SDavid C Somayajulu {
44266a62bec0SDavid C Somayajulu ha->hw.mdump_buffer_size = ql_minidump_size(ha);
44276a62bec0SDavid C Somayajulu
44286a62bec0SDavid C Somayajulu if (!ha->hw.mdump_buffer_size)
44296a62bec0SDavid C Somayajulu return (-1);
44306a62bec0SDavid C Somayajulu
44316a62bec0SDavid C Somayajulu ha->hw.mdump_buffer = malloc(ha->hw.mdump_buffer_size, M_QLA83XXBUF,
44326a62bec0SDavid C Somayajulu M_NOWAIT);
44336a62bec0SDavid C Somayajulu
44346a62bec0SDavid C Somayajulu if (ha->hw.mdump_buffer == NULL)
44356a62bec0SDavid C Somayajulu return (-1);
44366a62bec0SDavid C Somayajulu
44376a62bec0SDavid C Somayajulu return (0);
44386a62bec0SDavid C Somayajulu }
44396a62bec0SDavid C Somayajulu
44406a62bec0SDavid C Somayajulu static void
ql_free_minidump_template_buffer(qla_host_t * ha)44416a62bec0SDavid C Somayajulu ql_free_minidump_template_buffer(qla_host_t *ha)
44426a62bec0SDavid C Somayajulu {
44436a62bec0SDavid C Somayajulu if (ha->hw.mdump_template != NULL) {
44446a62bec0SDavid C Somayajulu free(ha->hw.mdump_template, M_QLA83XXBUF);
44456a62bec0SDavid C Somayajulu ha->hw.mdump_template = NULL;
44466a62bec0SDavid C Somayajulu ha->hw.mdump_template_size = 0;
44476a62bec0SDavid C Somayajulu }
44486a62bec0SDavid C Somayajulu return;
44496a62bec0SDavid C Somayajulu }
44506a62bec0SDavid C Somayajulu
44516a62bec0SDavid C Somayajulu static int
ql_alloc_minidump_template_buffer(qla_host_t * ha)44526a62bec0SDavid C Somayajulu ql_alloc_minidump_template_buffer(qla_host_t *ha)
44536a62bec0SDavid C Somayajulu {
44546a62bec0SDavid C Somayajulu ha->hw.mdump_template_size = ha->hw.dma_buf.minidump.size;
44556a62bec0SDavid C Somayajulu
44566a62bec0SDavid C Somayajulu ha->hw.mdump_template = malloc(ha->hw.mdump_template_size,
44576a62bec0SDavid C Somayajulu M_QLA83XXBUF, M_NOWAIT);
44586a62bec0SDavid C Somayajulu
44596a62bec0SDavid C Somayajulu if (ha->hw.mdump_template == NULL)
44606a62bec0SDavid C Somayajulu return (-1);
44616a62bec0SDavid C Somayajulu
44626a62bec0SDavid C Somayajulu return (0);
44636a62bec0SDavid C Somayajulu }
44646a62bec0SDavid C Somayajulu
44656a62bec0SDavid C Somayajulu static int
ql_alloc_minidump_buffers(qla_host_t * ha)44666a62bec0SDavid C Somayajulu ql_alloc_minidump_buffers(qla_host_t *ha)
44676a62bec0SDavid C Somayajulu {
44686a62bec0SDavid C Somayajulu int ret;
44696a62bec0SDavid C Somayajulu
44706a62bec0SDavid C Somayajulu ret = ql_alloc_minidump_template_buffer(ha);
44716a62bec0SDavid C Somayajulu
44726a62bec0SDavid C Somayajulu if (ret)
44736a62bec0SDavid C Somayajulu return (ret);
44746a62bec0SDavid C Somayajulu
44756a62bec0SDavid C Somayajulu ret = ql_alloc_minidump_buffer(ha);
44766a62bec0SDavid C Somayajulu
44776a62bec0SDavid C Somayajulu if (ret)
44786a62bec0SDavid C Somayajulu ql_free_minidump_template_buffer(ha);
44796a62bec0SDavid C Somayajulu
44806a62bec0SDavid C Somayajulu return (ret);
44816a62bec0SDavid C Somayajulu }
44826a62bec0SDavid C Somayajulu
44836a62bec0SDavid C Somayajulu static uint32_t
ql_validate_minidump_checksum(qla_host_t * ha)44846a62bec0SDavid C Somayajulu ql_validate_minidump_checksum(qla_host_t *ha)
44856a62bec0SDavid C Somayajulu {
44866a62bec0SDavid C Somayajulu uint64_t sum = 0;
44876a62bec0SDavid C Somayajulu int count;
44886a62bec0SDavid C Somayajulu uint32_t *template_buff;
44896a62bec0SDavid C Somayajulu
44906a62bec0SDavid C Somayajulu count = ha->hw.dma_buf.minidump.size / sizeof (uint32_t);
44916a62bec0SDavid C Somayajulu template_buff = ha->hw.dma_buf.minidump.dma_b;
44926a62bec0SDavid C Somayajulu
44936a62bec0SDavid C Somayajulu while (count-- > 0) {
44946a62bec0SDavid C Somayajulu sum += *template_buff++;
44956a62bec0SDavid C Somayajulu }
44966a62bec0SDavid C Somayajulu
44976a62bec0SDavid C Somayajulu while (sum >> 32) {
44986a62bec0SDavid C Somayajulu sum = (sum & 0xFFFFFFFF) + (sum >> 32);
44996a62bec0SDavid C Somayajulu }
45006a62bec0SDavid C Somayajulu
45016a62bec0SDavid C Somayajulu return (~sum);
45026a62bec0SDavid C Somayajulu }
45036a62bec0SDavid C Somayajulu
45046a62bec0SDavid C Somayajulu int
ql_minidump_init(qla_host_t * ha)45056a62bec0SDavid C Somayajulu ql_minidump_init(qla_host_t *ha)
4506f10a77bbSDavid C Somayajulu {
450735291c22SDavid C Somayajulu int ret = 0;
4508f10a77bbSDavid C Somayajulu uint32_t template_size = 0;
4509f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev;
4510f10a77bbSDavid C Somayajulu
4511f10a77bbSDavid C Somayajulu /*
4512f10a77bbSDavid C Somayajulu * Get Minidump Template Size
4513f10a77bbSDavid C Somayajulu */
4514f10a77bbSDavid C Somayajulu ret = qla_get_minidump_tmplt_size(ha, &template_size);
4515f10a77bbSDavid C Somayajulu
4516f10a77bbSDavid C Somayajulu if (ret || (template_size == 0)) {
4517f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret,
4518f10a77bbSDavid C Somayajulu template_size);
4519f10a77bbSDavid C Somayajulu return (-1);
4520f10a77bbSDavid C Somayajulu }
4521f10a77bbSDavid C Somayajulu
4522f10a77bbSDavid C Somayajulu /*
4523f10a77bbSDavid C Somayajulu * Allocate Memory for Minidump Template
4524f10a77bbSDavid C Somayajulu */
4525f10a77bbSDavid C Somayajulu
4526f10a77bbSDavid C Somayajulu ha->hw.dma_buf.minidump.alignment = 8;
4527f10a77bbSDavid C Somayajulu ha->hw.dma_buf.minidump.size = template_size;
4528f10a77bbSDavid C Somayajulu
452935291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
4530f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) {
4531f10a77bbSDavid C Somayajulu device_printf(dev, "%s: minidump dma alloc failed\n", __func__);
4532f10a77bbSDavid C Somayajulu
4533f10a77bbSDavid C Somayajulu return (-1);
4534f10a77bbSDavid C Somayajulu }
4535f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.minidump = 1;
4536f10a77bbSDavid C Somayajulu
4537f10a77bbSDavid C Somayajulu /*
4538f10a77bbSDavid C Somayajulu * Retrieve Minidump Template
4539f10a77bbSDavid C Somayajulu */
45406a62bec0SDavid C Somayajulu ret = ql_get_minidump_template(ha);
454135291c22SDavid C Somayajulu #else
454235291c22SDavid C Somayajulu ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump;
45436a62bec0SDavid C Somayajulu
454435291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
4545f10a77bbSDavid C Somayajulu
45466a62bec0SDavid C Somayajulu if (ret == 0) {
45476a62bec0SDavid C Somayajulu ret = ql_validate_minidump_checksum(ha);
45486a62bec0SDavid C Somayajulu
45496a62bec0SDavid C Somayajulu if (ret == 0) {
45506a62bec0SDavid C Somayajulu ret = ql_alloc_minidump_buffers(ha);
45516a62bec0SDavid C Somayajulu
45526a62bec0SDavid C Somayajulu if (ret == 0)
4553f10a77bbSDavid C Somayajulu ha->hw.mdump_init = 1;
45546a62bec0SDavid C Somayajulu else
45556a62bec0SDavid C Somayajulu device_printf(dev,
45566a62bec0SDavid C Somayajulu "%s: ql_alloc_minidump_buffers"
45576a62bec0SDavid C Somayajulu " failed\n", __func__);
45586a62bec0SDavid C Somayajulu } else {
45596a62bec0SDavid C Somayajulu device_printf(dev, "%s: ql_validate_minidump_checksum"
45606a62bec0SDavid C Somayajulu " failed\n", __func__);
4561f10a77bbSDavid C Somayajulu }
45626a62bec0SDavid C Somayajulu } else {
45636a62bec0SDavid C Somayajulu device_printf(dev, "%s: ql_get_minidump_template failed\n",
45646a62bec0SDavid C Somayajulu __func__);
45656a62bec0SDavid C Somayajulu }
45666a62bec0SDavid C Somayajulu
45676a62bec0SDavid C Somayajulu if (ret)
45686a62bec0SDavid C Somayajulu ql_minidump_free(ha);
4569f10a77bbSDavid C Somayajulu
4570f10a77bbSDavid C Somayajulu return (ret);
4571f10a77bbSDavid C Somayajulu }
4572f10a77bbSDavid C Somayajulu
4573f10a77bbSDavid C Somayajulu static void
ql_minidump_free(qla_host_t * ha)45746a62bec0SDavid C Somayajulu ql_minidump_free(qla_host_t *ha)
4575f10a77bbSDavid C Somayajulu {
4576f10a77bbSDavid C Somayajulu ha->hw.mdump_init = 0;
4577f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.minidump) {
4578f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.minidump = 0;
4579f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump);
4580f10a77bbSDavid C Somayajulu }
45816a62bec0SDavid C Somayajulu
45826a62bec0SDavid C Somayajulu ql_free_minidump_template_buffer(ha);
45836a62bec0SDavid C Somayajulu ql_free_minidump_buffer(ha);
45846a62bec0SDavid C Somayajulu
4585f10a77bbSDavid C Somayajulu return;
4586f10a77bbSDavid C Somayajulu }
4587f10a77bbSDavid C Somayajulu
4588f10a77bbSDavid C Somayajulu void
ql_minidump(qla_host_t * ha)4589f10a77bbSDavid C Somayajulu ql_minidump(qla_host_t *ha)
4590f10a77bbSDavid C Somayajulu {
4591f10a77bbSDavid C Somayajulu if (!ha->hw.mdump_init)
4592f10a77bbSDavid C Somayajulu return;
4593f10a77bbSDavid C Somayajulu
45946a62bec0SDavid C Somayajulu if (ha->hw.mdump_done)
4595f10a77bbSDavid C Somayajulu return;
4596b65c0c07SDavid C Somayajulu ha->hw.mdump_usec_ts = qla_get_usec_timestamp();
4597f10a77bbSDavid C Somayajulu ha->hw.mdump_start_seq_index = ql_stop_sequence(ha);
4598f10a77bbSDavid C Somayajulu
45996a62bec0SDavid C Somayajulu bzero(ha->hw.mdump_buffer, ha->hw.mdump_buffer_size);
46006a62bec0SDavid C Somayajulu bzero(ha->hw.mdump_template, ha->hw.mdump_template_size);
46016a62bec0SDavid C Somayajulu
46026a62bec0SDavid C Somayajulu bcopy(ha->hw.dma_buf.minidump.dma_b, ha->hw.mdump_template,
46036a62bec0SDavid C Somayajulu ha->hw.mdump_template_size);
46046a62bec0SDavid C Somayajulu
46056a62bec0SDavid C Somayajulu ql_parse_template(ha);
46066a62bec0SDavid C Somayajulu
4607f10a77bbSDavid C Somayajulu ql_start_sequence(ha, ha->hw.mdump_start_seq_index);
4608f10a77bbSDavid C Somayajulu
46096a62bec0SDavid C Somayajulu ha->hw.mdump_done = 1;
46106a62bec0SDavid C Somayajulu
4611f10a77bbSDavid C Somayajulu return;
4612f10a77bbSDavid C Somayajulu }
46136a62bec0SDavid C Somayajulu
46146a62bec0SDavid C Somayajulu /*
46156a62bec0SDavid C Somayajulu * helper routines
46166a62bec0SDavid C Somayajulu */
46176a62bec0SDavid C Somayajulu static void
ql_entry_err_chk(ql_minidump_entry_t * entry,uint32_t esize)46186a62bec0SDavid C Somayajulu ql_entry_err_chk(ql_minidump_entry_t *entry, uint32_t esize)
46196a62bec0SDavid C Somayajulu {
46206a62bec0SDavid C Somayajulu if (esize != entry->hdr.entry_capture_size) {
46216a62bec0SDavid C Somayajulu entry->hdr.entry_capture_size = esize;
46226a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SIZE_ERR_FLAG;
46236a62bec0SDavid C Somayajulu }
46246a62bec0SDavid C Somayajulu return;
46256a62bec0SDavid C Somayajulu }
46266a62bec0SDavid C Somayajulu
46276a62bec0SDavid C Somayajulu static int
ql_parse_template(qla_host_t * ha)46286a62bec0SDavid C Somayajulu ql_parse_template(qla_host_t *ha)
46296a62bec0SDavid C Somayajulu {
46306a62bec0SDavid C Somayajulu uint32_t num_of_entries, buff_level, e_cnt, esize;
46319fa72d33SJohn Baldwin uint32_t rv = 0;
46326a62bec0SDavid C Somayajulu char *dump_buff, *dbuff;
46336a62bec0SDavid C Somayajulu int sane_start = 0, sane_end = 0;
46346a62bec0SDavid C Somayajulu ql_minidump_template_hdr_t *template_hdr;
46356a62bec0SDavid C Somayajulu ql_minidump_entry_t *entry;
46366a62bec0SDavid C Somayajulu uint32_t capture_mask;
46376a62bec0SDavid C Somayajulu uint32_t dump_size;
46386a62bec0SDavid C Somayajulu
46396a62bec0SDavid C Somayajulu /* Setup parameters */
46406a62bec0SDavid C Somayajulu template_hdr = (ql_minidump_template_hdr_t *)ha->hw.mdump_template;
46416a62bec0SDavid C Somayajulu
46426a62bec0SDavid C Somayajulu if (template_hdr->entry_type == TLHDR)
46436a62bec0SDavid C Somayajulu sane_start = 1;
46446a62bec0SDavid C Somayajulu
46456a62bec0SDavid C Somayajulu dump_buff = (char *) ha->hw.mdump_buffer;
46466a62bec0SDavid C Somayajulu
46476a62bec0SDavid C Somayajulu num_of_entries = template_hdr->num_of_entries;
46486a62bec0SDavid C Somayajulu
46496a62bec0SDavid C Somayajulu entry = (ql_minidump_entry_t *) ((char *)template_hdr
46506a62bec0SDavid C Somayajulu + template_hdr->first_entry_offset );
46516a62bec0SDavid C Somayajulu
46526a62bec0SDavid C Somayajulu template_hdr->saved_state_array[QL_OCM0_ADDR_INDX] =
46536a62bec0SDavid C Somayajulu template_hdr->ocm_window_array[ha->pci_func];
46546a62bec0SDavid C Somayajulu template_hdr->saved_state_array[QL_PCIE_FUNC_INDX] = ha->pci_func;
46556a62bec0SDavid C Somayajulu
46566a62bec0SDavid C Somayajulu capture_mask = ha->hw.mdump_capture_mask;
46576a62bec0SDavid C Somayajulu dump_size = ha->hw.mdump_buffer_size;
46586a62bec0SDavid C Somayajulu
46596a62bec0SDavid C Somayajulu template_hdr->driver_capture_mask = capture_mask;
46606a62bec0SDavid C Somayajulu
46616a62bec0SDavid C Somayajulu QL_DPRINT80(ha, (ha->pci_dev,
46626a62bec0SDavid C Somayajulu "%s: sane_start = %d num_of_entries = %d "
46636a62bec0SDavid C Somayajulu "capture_mask = 0x%x dump_size = %d \n",
46646a62bec0SDavid C Somayajulu __func__, sane_start, num_of_entries, capture_mask, dump_size));
46656a62bec0SDavid C Somayajulu
46666a62bec0SDavid C Somayajulu for (buff_level = 0, e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
46676a62bec0SDavid C Somayajulu /*
46686a62bec0SDavid C Somayajulu * If the capture_mask of the entry does not match capture mask
46696a62bec0SDavid C Somayajulu * skip the entry after marking the driver_flags indicator.
46706a62bec0SDavid C Somayajulu */
46716a62bec0SDavid C Somayajulu
46726a62bec0SDavid C Somayajulu if (!(entry->hdr.entry_capture_mask & capture_mask)) {
46736a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
46746a62bec0SDavid C Somayajulu entry = (ql_minidump_entry_t *) ((char *) entry
46756a62bec0SDavid C Somayajulu + entry->hdr.entry_size);
46766a62bec0SDavid C Somayajulu continue;
46776a62bec0SDavid C Somayajulu }
46786a62bec0SDavid C Somayajulu
46796a62bec0SDavid C Somayajulu /*
46806a62bec0SDavid C Somayajulu * This is ONLY needed in implementations where
46816a62bec0SDavid C Somayajulu * the capture buffer allocated is too small to capture
46826a62bec0SDavid C Somayajulu * all of the required entries for a given capture mask.
46836a62bec0SDavid C Somayajulu * We need to empty the buffer contents to a file
46846a62bec0SDavid C Somayajulu * if possible, before processing the next entry
46856a62bec0SDavid C Somayajulu * If the buff_full_flag is set, no further capture will happen
46866a62bec0SDavid C Somayajulu * and all remaining non-control entries will be skipped.
46876a62bec0SDavid C Somayajulu */
46886a62bec0SDavid C Somayajulu if (entry->hdr.entry_capture_size != 0) {
46896a62bec0SDavid C Somayajulu if ((buff_level + entry->hdr.entry_capture_size) >
46906a62bec0SDavid C Somayajulu dump_size) {
46916a62bec0SDavid C Somayajulu /* Try to recover by emptying buffer to file */
46926a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
46936a62bec0SDavid C Somayajulu entry = (ql_minidump_entry_t *) ((char *) entry
46946a62bec0SDavid C Somayajulu + entry->hdr.entry_size);
46956a62bec0SDavid C Somayajulu continue;
46966a62bec0SDavid C Somayajulu }
46976a62bec0SDavid C Somayajulu }
46986a62bec0SDavid C Somayajulu
46996a62bec0SDavid C Somayajulu /*
47006a62bec0SDavid C Somayajulu * Decode the entry type and process it accordingly
47016a62bec0SDavid C Somayajulu */
47026a62bec0SDavid C Somayajulu
47036a62bec0SDavid C Somayajulu switch (entry->hdr.entry_type) {
47046a62bec0SDavid C Somayajulu case RDNOP:
47056a62bec0SDavid C Somayajulu break;
47066a62bec0SDavid C Somayajulu
47076a62bec0SDavid C Somayajulu case RDEND:
47086a62bec0SDavid C Somayajulu sane_end++;
47096a62bec0SDavid C Somayajulu break;
47106a62bec0SDavid C Somayajulu
47116a62bec0SDavid C Somayajulu case RDCRB:
47126a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level;
47136a62bec0SDavid C Somayajulu esize = ql_rdcrb(ha, (void *)entry, (void *)dbuff);
47146a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize);
47156a62bec0SDavid C Somayajulu buff_level += esize;
47166a62bec0SDavid C Somayajulu break;
47176a62bec0SDavid C Somayajulu
47186a62bec0SDavid C Somayajulu case POLLRD:
47196a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level;
47206a62bec0SDavid C Somayajulu esize = ql_pollrd(ha, (void *)entry, (void *)dbuff);
47216a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize);
47226a62bec0SDavid C Somayajulu buff_level += esize;
47236a62bec0SDavid C Somayajulu break;
47246a62bec0SDavid C Somayajulu
47256a62bec0SDavid C Somayajulu case POLLRDMWR:
47266a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level;
47276a62bec0SDavid C Somayajulu esize = ql_pollrd_modify_write(ha, (void *)entry,
47286a62bec0SDavid C Somayajulu (void *)dbuff);
47296a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize);
47306a62bec0SDavid C Somayajulu buff_level += esize;
47316a62bec0SDavid C Somayajulu break;
47326a62bec0SDavid C Somayajulu
47336a62bec0SDavid C Somayajulu case L2ITG:
47346a62bec0SDavid C Somayajulu case L2DTG:
47356a62bec0SDavid C Somayajulu case L2DAT:
47366a62bec0SDavid C Somayajulu case L2INS:
47376a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level;
47386a62bec0SDavid C Somayajulu esize = ql_L2Cache(ha, (void *)entry, (void *)dbuff);
47396a62bec0SDavid C Somayajulu if (esize == -1) {
47406a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
47416a62bec0SDavid C Somayajulu } else {
47426a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize);
47436a62bec0SDavid C Somayajulu buff_level += esize;
47446a62bec0SDavid C Somayajulu }
47456a62bec0SDavid C Somayajulu break;
47466a62bec0SDavid C Somayajulu
47476a62bec0SDavid C Somayajulu case L1DAT:
47486a62bec0SDavid C Somayajulu case L1INS:
47496a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level;
47506a62bec0SDavid C Somayajulu esize = ql_L1Cache(ha, (void *)entry, (void *)dbuff);
47516a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize);
47526a62bec0SDavid C Somayajulu buff_level += esize;
47536a62bec0SDavid C Somayajulu break;
47546a62bec0SDavid C Somayajulu
47556a62bec0SDavid C Somayajulu case RDOCM:
47566a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level;
47576a62bec0SDavid C Somayajulu esize = ql_rdocm(ha, (void *)entry, (void *)dbuff);
47586a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize);
47596a62bec0SDavid C Somayajulu buff_level += esize;
47606a62bec0SDavid C Somayajulu break;
47616a62bec0SDavid C Somayajulu
47626a62bec0SDavid C Somayajulu case RDMEM:
47636a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level;
47646a62bec0SDavid C Somayajulu esize = ql_rdmem(ha, (void *)entry, (void *)dbuff);
47656a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize);
47666a62bec0SDavid C Somayajulu buff_level += esize;
47676a62bec0SDavid C Somayajulu break;
47686a62bec0SDavid C Somayajulu
47696a62bec0SDavid C Somayajulu case BOARD:
47706a62bec0SDavid C Somayajulu case RDROM:
47716a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level;
47726a62bec0SDavid C Somayajulu esize = ql_rdrom(ha, (void *)entry, (void *)dbuff);
47736a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize);
47746a62bec0SDavid C Somayajulu buff_level += esize;
47756a62bec0SDavid C Somayajulu break;
47766a62bec0SDavid C Somayajulu
47776a62bec0SDavid C Somayajulu case RDMUX:
47786a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level;
47796a62bec0SDavid C Somayajulu esize = ql_rdmux(ha, (void *)entry, (void *)dbuff);
47806a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize);
47816a62bec0SDavid C Somayajulu buff_level += esize;
47826a62bec0SDavid C Somayajulu break;
47836a62bec0SDavid C Somayajulu
47846a62bec0SDavid C Somayajulu case RDMUX2:
47856a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level;
47866a62bec0SDavid C Somayajulu esize = ql_rdmux2(ha, (void *)entry, (void *)dbuff);
47876a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize);
47886a62bec0SDavid C Somayajulu buff_level += esize;
47896a62bec0SDavid C Somayajulu break;
47906a62bec0SDavid C Somayajulu
47916a62bec0SDavid C Somayajulu case QUEUE:
47926a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level;
47936a62bec0SDavid C Somayajulu esize = ql_rdqueue(ha, (void *)entry, (void *)dbuff);
47946a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize);
47956a62bec0SDavid C Somayajulu buff_level += esize;
47966a62bec0SDavid C Somayajulu break;
47976a62bec0SDavid C Somayajulu
47986a62bec0SDavid C Somayajulu case CNTRL:
47996a62bec0SDavid C Somayajulu if ((rv = ql_cntrl(ha, template_hdr, (void *)entry))) {
48006a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
48016a62bec0SDavid C Somayajulu }
48026a62bec0SDavid C Somayajulu break;
48036a62bec0SDavid C Somayajulu default:
48046a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG;
48056a62bec0SDavid C Somayajulu break;
48066a62bec0SDavid C Somayajulu }
48076a62bec0SDavid C Somayajulu /* next entry in the template */
48086a62bec0SDavid C Somayajulu entry = (ql_minidump_entry_t *) ((char *) entry
48096a62bec0SDavid C Somayajulu + entry->hdr.entry_size);
48106a62bec0SDavid C Somayajulu }
48116a62bec0SDavid C Somayajulu
48126a62bec0SDavid C Somayajulu if (!sane_start || (sane_end > 1)) {
48136a62bec0SDavid C Somayajulu device_printf(ha->pci_dev,
48146a62bec0SDavid C Somayajulu "\n%s: Template configuration error. Check Template\n",
48156a62bec0SDavid C Somayajulu __func__);
48166a62bec0SDavid C Somayajulu }
48176a62bec0SDavid C Somayajulu
48186a62bec0SDavid C Somayajulu QL_DPRINT80(ha, (ha->pci_dev, "%s: Minidump num of entries = %d\n",
48196a62bec0SDavid C Somayajulu __func__, template_hdr->num_of_entries));
48206a62bec0SDavid C Somayajulu
48216a62bec0SDavid C Somayajulu return 0;
48226a62bec0SDavid C Somayajulu }
48236a62bec0SDavid C Somayajulu
48246a62bec0SDavid C Somayajulu /*
48256a62bec0SDavid C Somayajulu * Read CRB operation.
48266a62bec0SDavid C Somayajulu */
48276a62bec0SDavid C Somayajulu static uint32_t
ql_rdcrb(qla_host_t * ha,ql_minidump_entry_rdcrb_t * crb_entry,uint32_t * data_buff)48286a62bec0SDavid C Somayajulu ql_rdcrb(qla_host_t *ha, ql_minidump_entry_rdcrb_t * crb_entry,
48296a62bec0SDavid C Somayajulu uint32_t * data_buff)
48306a62bec0SDavid C Somayajulu {
48316a62bec0SDavid C Somayajulu int loop_cnt;
48326a62bec0SDavid C Somayajulu int ret;
48336a62bec0SDavid C Somayajulu uint32_t op_count, addr, stride, value = 0;
48346a62bec0SDavid C Somayajulu
48356a62bec0SDavid C Somayajulu addr = crb_entry->addr;
48366a62bec0SDavid C Somayajulu op_count = crb_entry->op_count;
48376a62bec0SDavid C Somayajulu stride = crb_entry->addr_stride;
48386a62bec0SDavid C Somayajulu
48396a62bec0SDavid C Somayajulu for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
48406a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &value, 1);
48416a62bec0SDavid C Somayajulu
48426a62bec0SDavid C Somayajulu if (ret)
48436a62bec0SDavid C Somayajulu return (0);
48446a62bec0SDavid C Somayajulu
48456a62bec0SDavid C Somayajulu *data_buff++ = addr;
48466a62bec0SDavid C Somayajulu *data_buff++ = value;
48476a62bec0SDavid C Somayajulu addr = addr + stride;
48486a62bec0SDavid C Somayajulu }
48496a62bec0SDavid C Somayajulu
48506a62bec0SDavid C Somayajulu /*
48516a62bec0SDavid C Somayajulu * for testing purpose we return amount of data written
48526a62bec0SDavid C Somayajulu */
48536a62bec0SDavid C Somayajulu return (op_count * (2 * sizeof(uint32_t)));
48546a62bec0SDavid C Somayajulu }
48556a62bec0SDavid C Somayajulu
48566a62bec0SDavid C Somayajulu /*
48576a62bec0SDavid C Somayajulu * Handle L2 Cache.
48586a62bec0SDavid C Somayajulu */
48596a62bec0SDavid C Somayajulu
48606a62bec0SDavid C Somayajulu static uint32_t
ql_L2Cache(qla_host_t * ha,ql_minidump_entry_cache_t * cacheEntry,uint32_t * data_buff)48616a62bec0SDavid C Somayajulu ql_L2Cache(qla_host_t *ha, ql_minidump_entry_cache_t *cacheEntry,
48626a62bec0SDavid C Somayajulu uint32_t * data_buff)
48636a62bec0SDavid C Somayajulu {
48646a62bec0SDavid C Somayajulu int i, k;
48656a62bec0SDavid C Somayajulu int loop_cnt;
48666a62bec0SDavid C Somayajulu int ret;
48676a62bec0SDavid C Somayajulu
48686a62bec0SDavid C Somayajulu uint32_t read_value;
48696a62bec0SDavid C Somayajulu uint32_t addr, read_addr, cntrl_addr, tag_reg_addr, cntl_value_w;
48706a62bec0SDavid C Somayajulu uint32_t tag_value, read_cnt;
48716a62bec0SDavid C Somayajulu volatile uint8_t cntl_value_r;
48726a62bec0SDavid C Somayajulu long timeout;
48736a62bec0SDavid C Somayajulu uint32_t data;
48746a62bec0SDavid C Somayajulu
48756a62bec0SDavid C Somayajulu loop_cnt = cacheEntry->op_count;
48766a62bec0SDavid C Somayajulu
48776a62bec0SDavid C Somayajulu read_addr = cacheEntry->read_addr;
48786a62bec0SDavid C Somayajulu cntrl_addr = cacheEntry->control_addr;
48796a62bec0SDavid C Somayajulu cntl_value_w = (uint32_t) cacheEntry->write_value;
48806a62bec0SDavid C Somayajulu
48816a62bec0SDavid C Somayajulu tag_reg_addr = cacheEntry->tag_reg_addr;
48826a62bec0SDavid C Somayajulu
48836a62bec0SDavid C Somayajulu tag_value = cacheEntry->init_tag_value;
48846a62bec0SDavid C Somayajulu read_cnt = cacheEntry->read_addr_cnt;
48856a62bec0SDavid C Somayajulu
48866a62bec0SDavid C Somayajulu for (i = 0; i < loop_cnt; i++) {
48876a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
48886a62bec0SDavid C Somayajulu if (ret)
48896a62bec0SDavid C Somayajulu return (0);
48906a62bec0SDavid C Somayajulu
48916a62bec0SDavid C Somayajulu if (cacheEntry->write_value != 0) {
48926a62bec0SDavid C Somayajulu
48936a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, cntrl_addr,
48946a62bec0SDavid C Somayajulu &cntl_value_w, 0);
48956a62bec0SDavid C Somayajulu if (ret)
48966a62bec0SDavid C Somayajulu return (0);
48976a62bec0SDavid C Somayajulu }
48986a62bec0SDavid C Somayajulu
48996a62bec0SDavid C Somayajulu if (cacheEntry->poll_mask != 0) {
49006a62bec0SDavid C Somayajulu
49016a62bec0SDavid C Somayajulu timeout = cacheEntry->poll_wait;
49026a62bec0SDavid C Somayajulu
49036a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, cntrl_addr, &data, 1);
49046a62bec0SDavid C Somayajulu if (ret)
49056a62bec0SDavid C Somayajulu return (0);
49066a62bec0SDavid C Somayajulu
49076a62bec0SDavid C Somayajulu cntl_value_r = (uint8_t)data;
49086a62bec0SDavid C Somayajulu
49096a62bec0SDavid C Somayajulu while ((cntl_value_r & cacheEntry->poll_mask) != 0) {
49106a62bec0SDavid C Somayajulu if (timeout) {
49116a62bec0SDavid C Somayajulu qla_mdelay(__func__, 1);
49126a62bec0SDavid C Somayajulu timeout--;
49136a62bec0SDavid C Somayajulu } else
49146a62bec0SDavid C Somayajulu break;
49156a62bec0SDavid C Somayajulu
49166a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, cntrl_addr,
49176a62bec0SDavid C Somayajulu &data, 1);
49186a62bec0SDavid C Somayajulu if (ret)
49196a62bec0SDavid C Somayajulu return (0);
49206a62bec0SDavid C Somayajulu
49216a62bec0SDavid C Somayajulu cntl_value_r = (uint8_t)data;
49226a62bec0SDavid C Somayajulu }
49236a62bec0SDavid C Somayajulu if (!timeout) {
49246a62bec0SDavid C Somayajulu /* Report timeout error.
49256a62bec0SDavid C Somayajulu * core dump capture failed
49266a62bec0SDavid C Somayajulu * Skip remaining entries.
49276a62bec0SDavid C Somayajulu * Write buffer out to file
49286a62bec0SDavid C Somayajulu * Use driver specific fields in template header
49296a62bec0SDavid C Somayajulu * to report this error.
49306a62bec0SDavid C Somayajulu */
49316a62bec0SDavid C Somayajulu return (-1);
49326a62bec0SDavid C Somayajulu }
49336a62bec0SDavid C Somayajulu }
49346a62bec0SDavid C Somayajulu
49356a62bec0SDavid C Somayajulu addr = read_addr;
49366a62bec0SDavid C Somayajulu for (k = 0; k < read_cnt; k++) {
49376a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
49386a62bec0SDavid C Somayajulu if (ret)
49396a62bec0SDavid C Somayajulu return (0);
49406a62bec0SDavid C Somayajulu
49416a62bec0SDavid C Somayajulu *data_buff++ = read_value;
49426a62bec0SDavid C Somayajulu addr += cacheEntry->read_addr_stride;
49436a62bec0SDavid C Somayajulu }
49446a62bec0SDavid C Somayajulu
49456a62bec0SDavid C Somayajulu tag_value += cacheEntry->tag_value_stride;
49466a62bec0SDavid C Somayajulu }
49476a62bec0SDavid C Somayajulu
49486a62bec0SDavid C Somayajulu return (read_cnt * loop_cnt * sizeof(uint32_t));
49496a62bec0SDavid C Somayajulu }
49506a62bec0SDavid C Somayajulu
49516a62bec0SDavid C Somayajulu /*
49526a62bec0SDavid C Somayajulu * Handle L1 Cache.
49536a62bec0SDavid C Somayajulu */
49546a62bec0SDavid C Somayajulu
49556a62bec0SDavid C Somayajulu static uint32_t
ql_L1Cache(qla_host_t * ha,ql_minidump_entry_cache_t * cacheEntry,uint32_t * data_buff)49566a62bec0SDavid C Somayajulu ql_L1Cache(qla_host_t *ha,
49576a62bec0SDavid C Somayajulu ql_minidump_entry_cache_t *cacheEntry,
49586a62bec0SDavid C Somayajulu uint32_t *data_buff)
49596a62bec0SDavid C Somayajulu {
49606a62bec0SDavid C Somayajulu int ret;
49616a62bec0SDavid C Somayajulu int i, k;
49626a62bec0SDavid C Somayajulu int loop_cnt;
49636a62bec0SDavid C Somayajulu
49646a62bec0SDavid C Somayajulu uint32_t read_value;
49656a62bec0SDavid C Somayajulu uint32_t addr, read_addr, cntrl_addr, tag_reg_addr;
49666a62bec0SDavid C Somayajulu uint32_t tag_value, read_cnt;
49676a62bec0SDavid C Somayajulu uint32_t cntl_value_w;
49686a62bec0SDavid C Somayajulu
49696a62bec0SDavid C Somayajulu loop_cnt = cacheEntry->op_count;
49706a62bec0SDavid C Somayajulu
49716a62bec0SDavid C Somayajulu read_addr = cacheEntry->read_addr;
49726a62bec0SDavid C Somayajulu cntrl_addr = cacheEntry->control_addr;
49736a62bec0SDavid C Somayajulu cntl_value_w = (uint32_t) cacheEntry->write_value;
49746a62bec0SDavid C Somayajulu
49756a62bec0SDavid C Somayajulu tag_reg_addr = cacheEntry->tag_reg_addr;
49766a62bec0SDavid C Somayajulu
49776a62bec0SDavid C Somayajulu tag_value = cacheEntry->init_tag_value;
49786a62bec0SDavid C Somayajulu read_cnt = cacheEntry->read_addr_cnt;
49796a62bec0SDavid C Somayajulu
49806a62bec0SDavid C Somayajulu for (i = 0; i < loop_cnt; i++) {
49816a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0);
49826a62bec0SDavid C Somayajulu if (ret)
49836a62bec0SDavid C Somayajulu return (0);
49846a62bec0SDavid C Somayajulu
49856a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, cntrl_addr, &cntl_value_w, 0);
49866a62bec0SDavid C Somayajulu if (ret)
49876a62bec0SDavid C Somayajulu return (0);
49886a62bec0SDavid C Somayajulu
49896a62bec0SDavid C Somayajulu addr = read_addr;
49906a62bec0SDavid C Somayajulu for (k = 0; k < read_cnt; k++) {
49916a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
49926a62bec0SDavid C Somayajulu if (ret)
49936a62bec0SDavid C Somayajulu return (0);
49946a62bec0SDavid C Somayajulu
49956a62bec0SDavid C Somayajulu *data_buff++ = read_value;
49966a62bec0SDavid C Somayajulu addr += cacheEntry->read_addr_stride;
49976a62bec0SDavid C Somayajulu }
49986a62bec0SDavid C Somayajulu
49996a62bec0SDavid C Somayajulu tag_value += cacheEntry->tag_value_stride;
50006a62bec0SDavid C Somayajulu }
50016a62bec0SDavid C Somayajulu
50026a62bec0SDavid C Somayajulu return (read_cnt * loop_cnt * sizeof(uint32_t));
50036a62bec0SDavid C Somayajulu }
50046a62bec0SDavid C Somayajulu
50056a62bec0SDavid C Somayajulu /*
50066a62bec0SDavid C Somayajulu * Reading OCM memory
50076a62bec0SDavid C Somayajulu */
50086a62bec0SDavid C Somayajulu
50096a62bec0SDavid C Somayajulu static uint32_t
ql_rdocm(qla_host_t * ha,ql_minidump_entry_rdocm_t * ocmEntry,uint32_t * data_buff)50106a62bec0SDavid C Somayajulu ql_rdocm(qla_host_t *ha,
50116a62bec0SDavid C Somayajulu ql_minidump_entry_rdocm_t *ocmEntry,
50126a62bec0SDavid C Somayajulu uint32_t *data_buff)
50136a62bec0SDavid C Somayajulu {
50146a62bec0SDavid C Somayajulu int i, loop_cnt;
50156a62bec0SDavid C Somayajulu volatile uint32_t addr;
50166a62bec0SDavid C Somayajulu volatile uint32_t value;
50176a62bec0SDavid C Somayajulu
50186a62bec0SDavid C Somayajulu addr = ocmEntry->read_addr;
50196a62bec0SDavid C Somayajulu loop_cnt = ocmEntry->op_count;
50206a62bec0SDavid C Somayajulu
50216a62bec0SDavid C Somayajulu for (i = 0; i < loop_cnt; i++) {
50226a62bec0SDavid C Somayajulu value = READ_REG32(ha, addr);
50236a62bec0SDavid C Somayajulu *data_buff++ = value;
50246a62bec0SDavid C Somayajulu addr += ocmEntry->read_addr_stride;
50256a62bec0SDavid C Somayajulu }
50266a62bec0SDavid C Somayajulu return (loop_cnt * sizeof(value));
50276a62bec0SDavid C Somayajulu }
50286a62bec0SDavid C Somayajulu
50296a62bec0SDavid C Somayajulu /*
50306a62bec0SDavid C Somayajulu * Read memory
50316a62bec0SDavid C Somayajulu */
50326a62bec0SDavid C Somayajulu
50336a62bec0SDavid C Somayajulu static uint32_t
ql_rdmem(qla_host_t * ha,ql_minidump_entry_rdmem_t * mem_entry,uint32_t * data_buff)50346a62bec0SDavid C Somayajulu ql_rdmem(qla_host_t *ha,
50356a62bec0SDavid C Somayajulu ql_minidump_entry_rdmem_t *mem_entry,
50366a62bec0SDavid C Somayajulu uint32_t *data_buff)
50376a62bec0SDavid C Somayajulu {
50386a62bec0SDavid C Somayajulu int ret;
50396a62bec0SDavid C Somayajulu int i, loop_cnt;
50406a62bec0SDavid C Somayajulu volatile uint32_t addr;
50416a62bec0SDavid C Somayajulu q80_offchip_mem_val_t val;
50426a62bec0SDavid C Somayajulu
50436a62bec0SDavid C Somayajulu addr = mem_entry->read_addr;
50446a62bec0SDavid C Somayajulu
50456a62bec0SDavid C Somayajulu /* size in bytes / 16 */
50466a62bec0SDavid C Somayajulu loop_cnt = mem_entry->read_data_size / (sizeof(uint32_t) * 4);
50476a62bec0SDavid C Somayajulu
50486a62bec0SDavid C Somayajulu for (i = 0; i < loop_cnt; i++) {
50496a62bec0SDavid C Somayajulu ret = ql_rdwr_offchip_mem(ha, (addr & 0x0ffffffff), &val, 1);
50506a62bec0SDavid C Somayajulu if (ret)
50516a62bec0SDavid C Somayajulu return (0);
50526a62bec0SDavid C Somayajulu
50536a62bec0SDavid C Somayajulu *data_buff++ = val.data_lo;
50546a62bec0SDavid C Somayajulu *data_buff++ = val.data_hi;
50556a62bec0SDavid C Somayajulu *data_buff++ = val.data_ulo;
50566a62bec0SDavid C Somayajulu *data_buff++ = val.data_uhi;
50576a62bec0SDavid C Somayajulu
50586a62bec0SDavid C Somayajulu addr += (sizeof(uint32_t) * 4);
50596a62bec0SDavid C Somayajulu }
50606a62bec0SDavid C Somayajulu
50616a62bec0SDavid C Somayajulu return (loop_cnt * (sizeof(uint32_t) * 4));
50626a62bec0SDavid C Somayajulu }
50636a62bec0SDavid C Somayajulu
50646a62bec0SDavid C Somayajulu /*
50656a62bec0SDavid C Somayajulu * Read Rom
50666a62bec0SDavid C Somayajulu */
50676a62bec0SDavid C Somayajulu
50686a62bec0SDavid C Somayajulu static uint32_t
ql_rdrom(qla_host_t * ha,ql_minidump_entry_rdrom_t * romEntry,uint32_t * data_buff)50696a62bec0SDavid C Somayajulu ql_rdrom(qla_host_t *ha,
50706a62bec0SDavid C Somayajulu ql_minidump_entry_rdrom_t *romEntry,
50716a62bec0SDavid C Somayajulu uint32_t *data_buff)
50726a62bec0SDavid C Somayajulu {
50736a62bec0SDavid C Somayajulu int ret;
50746a62bec0SDavid C Somayajulu int i, loop_cnt;
50756a62bec0SDavid C Somayajulu uint32_t addr;
50766a62bec0SDavid C Somayajulu uint32_t value;
50776a62bec0SDavid C Somayajulu
50786a62bec0SDavid C Somayajulu addr = romEntry->read_addr;
50796a62bec0SDavid C Somayajulu loop_cnt = romEntry->read_data_size; /* This is size in bytes */
50806a62bec0SDavid C Somayajulu loop_cnt /= sizeof(value);
50816a62bec0SDavid C Somayajulu
50826a62bec0SDavid C Somayajulu for (i = 0; i < loop_cnt; i++) {
50836a62bec0SDavid C Somayajulu ret = ql_rd_flash32(ha, addr, &value);
50846a62bec0SDavid C Somayajulu if (ret)
50856a62bec0SDavid C Somayajulu return (0);
50866a62bec0SDavid C Somayajulu
50876a62bec0SDavid C Somayajulu *data_buff++ = value;
50886a62bec0SDavid C Somayajulu addr += sizeof(value);
50896a62bec0SDavid C Somayajulu }
50906a62bec0SDavid C Somayajulu
50916a62bec0SDavid C Somayajulu return (loop_cnt * sizeof(value));
50926a62bec0SDavid C Somayajulu }
50936a62bec0SDavid C Somayajulu
50946a62bec0SDavid C Somayajulu /*
50956a62bec0SDavid C Somayajulu * Read MUX data
50966a62bec0SDavid C Somayajulu */
50976a62bec0SDavid C Somayajulu
50986a62bec0SDavid C Somayajulu static uint32_t
ql_rdmux(qla_host_t * ha,ql_minidump_entry_mux_t * muxEntry,uint32_t * data_buff)50996a62bec0SDavid C Somayajulu ql_rdmux(qla_host_t *ha,
51006a62bec0SDavid C Somayajulu ql_minidump_entry_mux_t *muxEntry,
51016a62bec0SDavid C Somayajulu uint32_t *data_buff)
51026a62bec0SDavid C Somayajulu {
51036a62bec0SDavid C Somayajulu int ret;
51046a62bec0SDavid C Somayajulu int loop_cnt;
51056a62bec0SDavid C Somayajulu uint32_t read_value, sel_value;
51066a62bec0SDavid C Somayajulu uint32_t read_addr, select_addr;
51076a62bec0SDavid C Somayajulu
51086a62bec0SDavid C Somayajulu select_addr = muxEntry->select_addr;
51096a62bec0SDavid C Somayajulu sel_value = muxEntry->select_value;
51106a62bec0SDavid C Somayajulu read_addr = muxEntry->read_addr;
51116a62bec0SDavid C Somayajulu
51126a62bec0SDavid C Somayajulu for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
51136a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr, &sel_value, 0);
51146a62bec0SDavid C Somayajulu if (ret)
51156a62bec0SDavid C Somayajulu return (0);
51166a62bec0SDavid C Somayajulu
51176a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
51186a62bec0SDavid C Somayajulu if (ret)
51196a62bec0SDavid C Somayajulu return (0);
51206a62bec0SDavid C Somayajulu
51216a62bec0SDavid C Somayajulu *data_buff++ = sel_value;
51226a62bec0SDavid C Somayajulu *data_buff++ = read_value;
51236a62bec0SDavid C Somayajulu
51246a62bec0SDavid C Somayajulu sel_value += muxEntry->select_value_stride;
51256a62bec0SDavid C Somayajulu }
51266a62bec0SDavid C Somayajulu
51276a62bec0SDavid C Somayajulu return (loop_cnt * (2 * sizeof(uint32_t)));
51286a62bec0SDavid C Somayajulu }
51296a62bec0SDavid C Somayajulu
51306a62bec0SDavid C Somayajulu static uint32_t
ql_rdmux2(qla_host_t * ha,ql_minidump_entry_mux2_t * muxEntry,uint32_t * data_buff)51316a62bec0SDavid C Somayajulu ql_rdmux2(qla_host_t *ha,
51326a62bec0SDavid C Somayajulu ql_minidump_entry_mux2_t *muxEntry,
51336a62bec0SDavid C Somayajulu uint32_t *data_buff)
51346a62bec0SDavid C Somayajulu {
51356a62bec0SDavid C Somayajulu int ret;
51366a62bec0SDavid C Somayajulu int loop_cnt;
51376a62bec0SDavid C Somayajulu
51386a62bec0SDavid C Somayajulu uint32_t select_addr_1, select_addr_2;
51396a62bec0SDavid C Somayajulu uint32_t select_value_1, select_value_2;
51406a62bec0SDavid C Somayajulu uint32_t select_value_count, select_value_mask;
51416a62bec0SDavid C Somayajulu uint32_t read_addr, read_value;
51426a62bec0SDavid C Somayajulu
51436a62bec0SDavid C Somayajulu select_addr_1 = muxEntry->select_addr_1;
51446a62bec0SDavid C Somayajulu select_addr_2 = muxEntry->select_addr_2;
51456a62bec0SDavid C Somayajulu select_value_1 = muxEntry->select_value_1;
51466a62bec0SDavid C Somayajulu select_value_2 = muxEntry->select_value_2;
51476a62bec0SDavid C Somayajulu select_value_count = muxEntry->select_value_count;
51486a62bec0SDavid C Somayajulu select_value_mask = muxEntry->select_value_mask;
51496a62bec0SDavid C Somayajulu
51506a62bec0SDavid C Somayajulu read_addr = muxEntry->read_addr;
51516a62bec0SDavid C Somayajulu
515210e3e53dSJohn Baldwin for (loop_cnt = 0; loop_cnt < select_value_count; loop_cnt++) {
51536a62bec0SDavid C Somayajulu uint32_t temp_sel_val;
51546a62bec0SDavid C Somayajulu
51556a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_1, 0);
51566a62bec0SDavid C Somayajulu if (ret)
51576a62bec0SDavid C Somayajulu return (0);
51586a62bec0SDavid C Somayajulu
51596a62bec0SDavid C Somayajulu temp_sel_val = select_value_1 & select_value_mask;
51606a62bec0SDavid C Somayajulu
51616a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
51626a62bec0SDavid C Somayajulu if (ret)
51636a62bec0SDavid C Somayajulu return (0);
51646a62bec0SDavid C Somayajulu
51656a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
51666a62bec0SDavid C Somayajulu if (ret)
51676a62bec0SDavid C Somayajulu return (0);
51686a62bec0SDavid C Somayajulu
51696a62bec0SDavid C Somayajulu *data_buff++ = temp_sel_val;
51706a62bec0SDavid C Somayajulu *data_buff++ = read_value;
51716a62bec0SDavid C Somayajulu
51726a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_2, 0);
51736a62bec0SDavid C Somayajulu if (ret)
51746a62bec0SDavid C Somayajulu return (0);
51756a62bec0SDavid C Somayajulu
51766a62bec0SDavid C Somayajulu temp_sel_val = select_value_2 & select_value_mask;
51776a62bec0SDavid C Somayajulu
51786a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0);
51796a62bec0SDavid C Somayajulu if (ret)
51806a62bec0SDavid C Somayajulu return (0);
51816a62bec0SDavid C Somayajulu
51826a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
51836a62bec0SDavid C Somayajulu if (ret)
51846a62bec0SDavid C Somayajulu return (0);
51856a62bec0SDavid C Somayajulu
51866a62bec0SDavid C Somayajulu *data_buff++ = temp_sel_val;
51876a62bec0SDavid C Somayajulu *data_buff++ = read_value;
51886a62bec0SDavid C Somayajulu
51896a62bec0SDavid C Somayajulu select_value_1 += muxEntry->select_value_stride;
51906a62bec0SDavid C Somayajulu select_value_2 += muxEntry->select_value_stride;
51916a62bec0SDavid C Somayajulu }
51926a62bec0SDavid C Somayajulu
51936a62bec0SDavid C Somayajulu return (loop_cnt * (4 * sizeof(uint32_t)));
51946a62bec0SDavid C Somayajulu }
51956a62bec0SDavid C Somayajulu
51966a62bec0SDavid C Somayajulu /*
51976a62bec0SDavid C Somayajulu * Handling Queue State Reads.
51986a62bec0SDavid C Somayajulu */
51996a62bec0SDavid C Somayajulu
52006a62bec0SDavid C Somayajulu static uint32_t
ql_rdqueue(qla_host_t * ha,ql_minidump_entry_queue_t * queueEntry,uint32_t * data_buff)52016a62bec0SDavid C Somayajulu ql_rdqueue(qla_host_t *ha,
52026a62bec0SDavid C Somayajulu ql_minidump_entry_queue_t *queueEntry,
52036a62bec0SDavid C Somayajulu uint32_t *data_buff)
52046a62bec0SDavid C Somayajulu {
52056a62bec0SDavid C Somayajulu int ret;
52066a62bec0SDavid C Somayajulu int loop_cnt, k;
52076a62bec0SDavid C Somayajulu uint32_t read_value;
52086a62bec0SDavid C Somayajulu uint32_t read_addr, read_stride, select_addr;
52096a62bec0SDavid C Somayajulu uint32_t queue_id, read_cnt;
52106a62bec0SDavid C Somayajulu
52116a62bec0SDavid C Somayajulu read_cnt = queueEntry->read_addr_cnt;
52126a62bec0SDavid C Somayajulu read_stride = queueEntry->read_addr_stride;
52136a62bec0SDavid C Somayajulu select_addr = queueEntry->select_addr;
52146a62bec0SDavid C Somayajulu
52156a62bec0SDavid C Somayajulu for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
52166a62bec0SDavid C Somayajulu loop_cnt++) {
52176a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr, &queue_id, 0);
52186a62bec0SDavid C Somayajulu if (ret)
52196a62bec0SDavid C Somayajulu return (0);
52206a62bec0SDavid C Somayajulu
52216a62bec0SDavid C Somayajulu read_addr = queueEntry->read_addr;
52226a62bec0SDavid C Somayajulu
52236a62bec0SDavid C Somayajulu for (k = 0; k < read_cnt; k++) {
52246a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1);
52256a62bec0SDavid C Somayajulu if (ret)
52266a62bec0SDavid C Somayajulu return (0);
52276a62bec0SDavid C Somayajulu
52286a62bec0SDavid C Somayajulu *data_buff++ = read_value;
52296a62bec0SDavid C Somayajulu read_addr += read_stride;
52306a62bec0SDavid C Somayajulu }
52316a62bec0SDavid C Somayajulu
52326a62bec0SDavid C Somayajulu queue_id += queueEntry->queue_id_stride;
52336a62bec0SDavid C Somayajulu }
52346a62bec0SDavid C Somayajulu
52356a62bec0SDavid C Somayajulu return (loop_cnt * (read_cnt * sizeof(uint32_t)));
52366a62bec0SDavid C Somayajulu }
52376a62bec0SDavid C Somayajulu
52386a62bec0SDavid C Somayajulu /*
52396a62bec0SDavid C Somayajulu * Handling control entries.
52406a62bec0SDavid C Somayajulu */
52416a62bec0SDavid C Somayajulu
52426a62bec0SDavid C Somayajulu static uint32_t
ql_cntrl(qla_host_t * ha,ql_minidump_template_hdr_t * template_hdr,ql_minidump_entry_cntrl_t * crbEntry)52436a62bec0SDavid C Somayajulu ql_cntrl(qla_host_t *ha,
52446a62bec0SDavid C Somayajulu ql_minidump_template_hdr_t *template_hdr,
52456a62bec0SDavid C Somayajulu ql_minidump_entry_cntrl_t *crbEntry)
52466a62bec0SDavid C Somayajulu {
52476a62bec0SDavid C Somayajulu int ret;
52486a62bec0SDavid C Somayajulu int count;
52496a62bec0SDavid C Somayajulu uint32_t opcode, read_value, addr, entry_addr;
52506a62bec0SDavid C Somayajulu long timeout;
52516a62bec0SDavid C Somayajulu
52526a62bec0SDavid C Somayajulu entry_addr = crbEntry->addr;
52536a62bec0SDavid C Somayajulu
52546a62bec0SDavid C Somayajulu for (count = 0; count < crbEntry->op_count; count++) {
52556a62bec0SDavid C Somayajulu opcode = crbEntry->opcode;
52566a62bec0SDavid C Somayajulu
52576a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_WR) {
52586a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr,
52596a62bec0SDavid C Somayajulu &crbEntry->value_1, 0);
52606a62bec0SDavid C Somayajulu if (ret)
52616a62bec0SDavid C Somayajulu return (0);
52626a62bec0SDavid C Somayajulu
52636a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_WR;
52646a62bec0SDavid C Somayajulu }
52656a62bec0SDavid C Somayajulu
52666a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_RW) {
52676a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
52686a62bec0SDavid C Somayajulu if (ret)
52696a62bec0SDavid C Somayajulu return (0);
52706a62bec0SDavid C Somayajulu
52716a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
52726a62bec0SDavid C Somayajulu if (ret)
52736a62bec0SDavid C Somayajulu return (0);
52746a62bec0SDavid C Somayajulu
52756a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_RW;
52766a62bec0SDavid C Somayajulu }
52776a62bec0SDavid C Somayajulu
52786a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_AND) {
52796a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
52806a62bec0SDavid C Somayajulu if (ret)
52816a62bec0SDavid C Somayajulu return (0);
52826a62bec0SDavid C Somayajulu
52836a62bec0SDavid C Somayajulu read_value &= crbEntry->value_2;
52846a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_AND;
52856a62bec0SDavid C Somayajulu
52866a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_OR) {
52876a62bec0SDavid C Somayajulu read_value |= crbEntry->value_3;
52886a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_OR;
52896a62bec0SDavid C Somayajulu }
52906a62bec0SDavid C Somayajulu
52916a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
52926a62bec0SDavid C Somayajulu if (ret)
52936a62bec0SDavid C Somayajulu return (0);
52946a62bec0SDavid C Somayajulu }
52956a62bec0SDavid C Somayajulu
52966a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_OR) {
52976a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1);
52986a62bec0SDavid C Somayajulu if (ret)
52996a62bec0SDavid C Somayajulu return (0);
53006a62bec0SDavid C Somayajulu
53016a62bec0SDavid C Somayajulu read_value |= crbEntry->value_3;
53026a62bec0SDavid C Somayajulu
53036a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0);
53046a62bec0SDavid C Somayajulu if (ret)
53056a62bec0SDavid C Somayajulu return (0);
53066a62bec0SDavid C Somayajulu
53076a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_OR;
53086a62bec0SDavid C Somayajulu }
53096a62bec0SDavid C Somayajulu
53106a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_POLL) {
53116a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_POLL;
53126a62bec0SDavid C Somayajulu timeout = crbEntry->poll_timeout;
53136a62bec0SDavid C Somayajulu addr = entry_addr;
53146a62bec0SDavid C Somayajulu
53156a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
53166a62bec0SDavid C Somayajulu if (ret)
53176a62bec0SDavid C Somayajulu return (0);
53186a62bec0SDavid C Somayajulu
53196a62bec0SDavid C Somayajulu while ((read_value & crbEntry->value_2)
53206a62bec0SDavid C Somayajulu != crbEntry->value_1) {
53216a62bec0SDavid C Somayajulu if (timeout) {
53226a62bec0SDavid C Somayajulu qla_mdelay(__func__, 1);
53236a62bec0SDavid C Somayajulu timeout--;
53246a62bec0SDavid C Somayajulu } else
53256a62bec0SDavid C Somayajulu break;
53266a62bec0SDavid C Somayajulu
53276a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr,
53286a62bec0SDavid C Somayajulu &read_value, 1);
53296a62bec0SDavid C Somayajulu if (ret)
53306a62bec0SDavid C Somayajulu return (0);
53316a62bec0SDavid C Somayajulu }
53326a62bec0SDavid C Somayajulu
53336a62bec0SDavid C Somayajulu if (!timeout) {
53346a62bec0SDavid C Somayajulu /*
53356a62bec0SDavid C Somayajulu * Report timeout error.
53366a62bec0SDavid C Somayajulu * core dump capture failed
53376a62bec0SDavid C Somayajulu * Skip remaining entries.
53386a62bec0SDavid C Somayajulu * Write buffer out to file
53396a62bec0SDavid C Somayajulu * Use driver specific fields in template header
53406a62bec0SDavid C Somayajulu * to report this error.
53416a62bec0SDavid C Somayajulu */
53426a62bec0SDavid C Somayajulu return (-1);
53436a62bec0SDavid C Somayajulu }
53446a62bec0SDavid C Somayajulu }
53456a62bec0SDavid C Somayajulu
53466a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_RDSTATE) {
53476a62bec0SDavid C Somayajulu /*
53486a62bec0SDavid C Somayajulu * decide which address to use.
53496a62bec0SDavid C Somayajulu */
53506a62bec0SDavid C Somayajulu if (crbEntry->state_index_a) {
53516a62bec0SDavid C Somayajulu addr = template_hdr->saved_state_array[
53526a62bec0SDavid C Somayajulu crbEntry-> state_index_a];
53536a62bec0SDavid C Somayajulu } else {
53546a62bec0SDavid C Somayajulu addr = entry_addr;
53556a62bec0SDavid C Somayajulu }
53566a62bec0SDavid C Somayajulu
53576a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &read_value, 1);
53586a62bec0SDavid C Somayajulu if (ret)
53596a62bec0SDavid C Somayajulu return (0);
53606a62bec0SDavid C Somayajulu
53616a62bec0SDavid C Somayajulu template_hdr->saved_state_array[crbEntry->state_index_v]
53626a62bec0SDavid C Somayajulu = read_value;
53636a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_RDSTATE;
53646a62bec0SDavid C Somayajulu }
53656a62bec0SDavid C Somayajulu
53666a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_WRSTATE) {
53676a62bec0SDavid C Somayajulu /*
53686a62bec0SDavid C Somayajulu * decide which value to use.
53696a62bec0SDavid C Somayajulu */
53706a62bec0SDavid C Somayajulu if (crbEntry->state_index_v) {
53716a62bec0SDavid C Somayajulu read_value = template_hdr->saved_state_array[
53726a62bec0SDavid C Somayajulu crbEntry->state_index_v];
53736a62bec0SDavid C Somayajulu } else {
53746a62bec0SDavid C Somayajulu read_value = crbEntry->value_1;
53756a62bec0SDavid C Somayajulu }
53766a62bec0SDavid C Somayajulu /*
53776a62bec0SDavid C Somayajulu * decide which address to use.
53786a62bec0SDavid C Somayajulu */
53796a62bec0SDavid C Somayajulu if (crbEntry->state_index_a) {
53806a62bec0SDavid C Somayajulu addr = template_hdr->saved_state_array[
53816a62bec0SDavid C Somayajulu crbEntry-> state_index_a];
53826a62bec0SDavid C Somayajulu } else {
53836a62bec0SDavid C Somayajulu addr = entry_addr;
53846a62bec0SDavid C Somayajulu }
53856a62bec0SDavid C Somayajulu
53866a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &read_value, 0);
53876a62bec0SDavid C Somayajulu if (ret)
53886a62bec0SDavid C Somayajulu return (0);
53896a62bec0SDavid C Somayajulu
53906a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_WRSTATE;
53916a62bec0SDavid C Somayajulu }
53926a62bec0SDavid C Somayajulu
53936a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_MDSTATE) {
53946a62bec0SDavid C Somayajulu /* Read value from saved state using index */
53956a62bec0SDavid C Somayajulu read_value = template_hdr->saved_state_array[
53966a62bec0SDavid C Somayajulu crbEntry->state_index_v];
53976a62bec0SDavid C Somayajulu
53986a62bec0SDavid C Somayajulu read_value <<= crbEntry->shl; /*Shift left operation */
53996a62bec0SDavid C Somayajulu read_value >>= crbEntry->shr; /*Shift right operation */
54006a62bec0SDavid C Somayajulu
54016a62bec0SDavid C Somayajulu if (crbEntry->value_2) {
54026a62bec0SDavid C Somayajulu /* check if AND mask is provided */
54036a62bec0SDavid C Somayajulu read_value &= crbEntry->value_2;
54046a62bec0SDavid C Somayajulu }
54056a62bec0SDavid C Somayajulu
54066a62bec0SDavid C Somayajulu read_value |= crbEntry->value_3; /* OR operation */
54076a62bec0SDavid C Somayajulu read_value += crbEntry->value_1; /* increment op */
54086a62bec0SDavid C Somayajulu
54096a62bec0SDavid C Somayajulu /* Write value back to state area. */
54106a62bec0SDavid C Somayajulu
54116a62bec0SDavid C Somayajulu template_hdr->saved_state_array[crbEntry->state_index_v]
54126a62bec0SDavid C Somayajulu = read_value;
54136a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_MDSTATE;
54146a62bec0SDavid C Somayajulu }
54156a62bec0SDavid C Somayajulu
54166a62bec0SDavid C Somayajulu entry_addr += crbEntry->addr_stride;
54176a62bec0SDavid C Somayajulu }
54186a62bec0SDavid C Somayajulu
54196a62bec0SDavid C Somayajulu return (0);
54206a62bec0SDavid C Somayajulu }
54216a62bec0SDavid C Somayajulu
54226a62bec0SDavid C Somayajulu /*
54236a62bec0SDavid C Somayajulu * Handling rd poll entry.
54246a62bec0SDavid C Somayajulu */
54256a62bec0SDavid C Somayajulu
54266a62bec0SDavid C Somayajulu static uint32_t
ql_pollrd(qla_host_t * ha,ql_minidump_entry_pollrd_t * entry,uint32_t * data_buff)54276a62bec0SDavid C Somayajulu ql_pollrd(qla_host_t *ha, ql_minidump_entry_pollrd_t *entry,
54286a62bec0SDavid C Somayajulu uint32_t *data_buff)
54296a62bec0SDavid C Somayajulu {
54306a62bec0SDavid C Somayajulu int ret;
54316a62bec0SDavid C Somayajulu int loop_cnt;
54326a62bec0SDavid C Somayajulu uint32_t op_count, select_addr, select_value_stride, select_value;
54339fa72d33SJohn Baldwin uint32_t read_addr, poll, mask, data;
54346a62bec0SDavid C Somayajulu uint32_t wait_count = 0;
54356a62bec0SDavid C Somayajulu
54366a62bec0SDavid C Somayajulu select_addr = entry->select_addr;
54376a62bec0SDavid C Somayajulu read_addr = entry->read_addr;
54386a62bec0SDavid C Somayajulu select_value = entry->select_value;
54396a62bec0SDavid C Somayajulu select_value_stride = entry->select_value_stride;
54406a62bec0SDavid C Somayajulu op_count = entry->op_count;
54416a62bec0SDavid C Somayajulu poll = entry->poll;
54426a62bec0SDavid C Somayajulu mask = entry->mask;
54436a62bec0SDavid C Somayajulu
54446a62bec0SDavid C Somayajulu for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
54456a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr, &select_value, 0);
54466a62bec0SDavid C Somayajulu if (ret)
54476a62bec0SDavid C Somayajulu return (0);
54486a62bec0SDavid C Somayajulu
54496a62bec0SDavid C Somayajulu wait_count = 0;
54506a62bec0SDavid C Somayajulu
54516a62bec0SDavid C Somayajulu while (wait_count < poll) {
54526a62bec0SDavid C Somayajulu uint32_t temp;
54536a62bec0SDavid C Somayajulu
54546a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr, &temp, 1);
54556a62bec0SDavid C Somayajulu if (ret)
54566a62bec0SDavid C Somayajulu return (0);
54576a62bec0SDavid C Somayajulu
54586a62bec0SDavid C Somayajulu if ( (temp & mask) != 0 ) {
54596a62bec0SDavid C Somayajulu break;
54606a62bec0SDavid C Somayajulu }
54616a62bec0SDavid C Somayajulu wait_count++;
54626a62bec0SDavid C Somayajulu }
54636a62bec0SDavid C Somayajulu
54646a62bec0SDavid C Somayajulu if (wait_count == poll) {
54656a62bec0SDavid C Somayajulu device_printf(ha->pci_dev,
54666a62bec0SDavid C Somayajulu "%s: Error in processing entry\n", __func__);
54676a62bec0SDavid C Somayajulu device_printf(ha->pci_dev,
54686a62bec0SDavid C Somayajulu "%s: wait_count <0x%x> poll <0x%x>\n",
54696a62bec0SDavid C Somayajulu __func__, wait_count, poll);
54706a62bec0SDavid C Somayajulu return 0;
54716a62bec0SDavid C Somayajulu }
54726a62bec0SDavid C Somayajulu
54736a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, read_addr, &data, 1);
54746a62bec0SDavid C Somayajulu if (ret)
54756a62bec0SDavid C Somayajulu return (0);
54766a62bec0SDavid C Somayajulu
54776a62bec0SDavid C Somayajulu *data_buff++ = select_value;
54786a62bec0SDavid C Somayajulu *data_buff++ = data;
54796a62bec0SDavid C Somayajulu select_value = select_value + select_value_stride;
54806a62bec0SDavid C Somayajulu }
54816a62bec0SDavid C Somayajulu
54826a62bec0SDavid C Somayajulu /*
54836a62bec0SDavid C Somayajulu * for testing purpose we return amount of data written
54846a62bec0SDavid C Somayajulu */
54856a62bec0SDavid C Somayajulu return (loop_cnt * (2 * sizeof(uint32_t)));
54866a62bec0SDavid C Somayajulu }
54876a62bec0SDavid C Somayajulu
54886a62bec0SDavid C Somayajulu /*
54896a62bec0SDavid C Somayajulu * Handling rd modify write poll entry.
54906a62bec0SDavid C Somayajulu */
54916a62bec0SDavid C Somayajulu
54926a62bec0SDavid C Somayajulu static uint32_t
ql_pollrd_modify_write(qla_host_t * ha,ql_minidump_entry_rd_modify_wr_with_poll_t * entry,uint32_t * data_buff)54936a62bec0SDavid C Somayajulu ql_pollrd_modify_write(qla_host_t *ha,
54946a62bec0SDavid C Somayajulu ql_minidump_entry_rd_modify_wr_with_poll_t *entry,
54956a62bec0SDavid C Somayajulu uint32_t *data_buff)
54966a62bec0SDavid C Somayajulu {
54976a62bec0SDavid C Somayajulu int ret;
54986a62bec0SDavid C Somayajulu uint32_t addr_1, addr_2, value_1, value_2, data;
54999fa72d33SJohn Baldwin uint32_t poll, mask, modify_mask;
55006a62bec0SDavid C Somayajulu uint32_t wait_count = 0;
55016a62bec0SDavid C Somayajulu
55026a62bec0SDavid C Somayajulu addr_1 = entry->addr_1;
55036a62bec0SDavid C Somayajulu addr_2 = entry->addr_2;
55046a62bec0SDavid C Somayajulu value_1 = entry->value_1;
55056a62bec0SDavid C Somayajulu value_2 = entry->value_2;
55066a62bec0SDavid C Somayajulu
55076a62bec0SDavid C Somayajulu poll = entry->poll;
55086a62bec0SDavid C Somayajulu mask = entry->mask;
55096a62bec0SDavid C Somayajulu modify_mask = entry->modify_mask;
55106a62bec0SDavid C Somayajulu
55116a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_1, &value_1, 0);
55126a62bec0SDavid C Somayajulu if (ret)
55136a62bec0SDavid C Somayajulu return (0);
55146a62bec0SDavid C Somayajulu
55156a62bec0SDavid C Somayajulu wait_count = 0;
55166a62bec0SDavid C Somayajulu while (wait_count < poll) {
55176a62bec0SDavid C Somayajulu uint32_t temp;
55186a62bec0SDavid C Somayajulu
55196a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
55206a62bec0SDavid C Somayajulu if (ret)
55216a62bec0SDavid C Somayajulu return (0);
55226a62bec0SDavid C Somayajulu
55236a62bec0SDavid C Somayajulu if ( (temp & mask) != 0 ) {
55246a62bec0SDavid C Somayajulu break;
55256a62bec0SDavid C Somayajulu }
55266a62bec0SDavid C Somayajulu wait_count++;
55276a62bec0SDavid C Somayajulu }
55286a62bec0SDavid C Somayajulu
55296a62bec0SDavid C Somayajulu if (wait_count == poll) {
55306a62bec0SDavid C Somayajulu device_printf(ha->pci_dev, "%s Error in processing entry\n",
55316a62bec0SDavid C Somayajulu __func__);
55326a62bec0SDavid C Somayajulu } else {
55336a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_2, &data, 1);
55346a62bec0SDavid C Somayajulu if (ret)
55356a62bec0SDavid C Somayajulu return (0);
55366a62bec0SDavid C Somayajulu
55376a62bec0SDavid C Somayajulu data = (data & modify_mask);
55386a62bec0SDavid C Somayajulu
55396a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_2, &data, 0);
55406a62bec0SDavid C Somayajulu if (ret)
55416a62bec0SDavid C Somayajulu return (0);
55426a62bec0SDavid C Somayajulu
55436a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_1, &value_2, 0);
55446a62bec0SDavid C Somayajulu if (ret)
55456a62bec0SDavid C Somayajulu return (0);
55466a62bec0SDavid C Somayajulu
55476a62bec0SDavid C Somayajulu /* Poll again */
55486a62bec0SDavid C Somayajulu wait_count = 0;
55496a62bec0SDavid C Somayajulu while (wait_count < poll) {
55506a62bec0SDavid C Somayajulu uint32_t temp;
55516a62bec0SDavid C Somayajulu
55526a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1);
55536a62bec0SDavid C Somayajulu if (ret)
55546a62bec0SDavid C Somayajulu return (0);
55556a62bec0SDavid C Somayajulu
55566a62bec0SDavid C Somayajulu if ( (temp & mask) != 0 ) {
55576a62bec0SDavid C Somayajulu break;
55586a62bec0SDavid C Somayajulu }
55596a62bec0SDavid C Somayajulu wait_count++;
55606a62bec0SDavid C Somayajulu }
55616a62bec0SDavid C Somayajulu *data_buff++ = addr_2;
55626a62bec0SDavid C Somayajulu *data_buff++ = data;
55636a62bec0SDavid C Somayajulu }
55646a62bec0SDavid C Somayajulu
55656a62bec0SDavid C Somayajulu /*
55666a62bec0SDavid C Somayajulu * for testing purpose we return amount of data written
55676a62bec0SDavid C Somayajulu */
55686a62bec0SDavid C Somayajulu return (2 * sizeof(uint32_t));
55696a62bec0SDavid C Somayajulu }
5570