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