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); 54f10a77bbSDavid C Somayajulu static void 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 6527fb51846SDavid C Somayajulu qlnx_add_hw_stats_sysctls(qla_host_t *ha) 6537fb51846SDavid C Somayajulu { 6547fb51846SDavid C Somayajulu qlnx_add_hw_mac_stats_sysctls(ha); 6557fb51846SDavid C Somayajulu qlnx_add_hw_rcv_stats_sysctls(ha); 6567fb51846SDavid C Somayajulu qlnx_add_hw_xmt_stats_sysctls(ha); 6577fb51846SDavid C Somayajulu 6587fb51846SDavid C Somayajulu return; 6597fb51846SDavid C Somayajulu } 6607fb51846SDavid C Somayajulu 6617fb51846SDavid C Somayajulu static void 6627fb51846SDavid C Somayajulu qlnx_add_drvr_sds_stats(qla_host_t *ha) 6637fb51846SDavid C Somayajulu { 6647fb51846SDavid C Somayajulu struct sysctl_ctx_list *ctx; 6657fb51846SDavid C Somayajulu struct sysctl_oid_list *children; 6667fb51846SDavid C Somayajulu struct sysctl_oid_list *node_children; 6677fb51846SDavid C Somayajulu struct sysctl_oid *ctx_oid; 6687fb51846SDavid C Somayajulu int i; 6697fb51846SDavid C Somayajulu uint8_t name_str[16]; 6707fb51846SDavid C Somayajulu 6717fb51846SDavid C Somayajulu ctx = device_get_sysctl_ctx(ha->pci_dev); 6727fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev)); 6737fb51846SDavid C Somayajulu 6747fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_sds", 6757fb51846SDavid C Somayajulu CTLFLAG_RD, NULL, "stats_drvr_sds"); 6767fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(ctx_oid); 6777fb51846SDavid C Somayajulu 6787fb51846SDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 6797fb51846SDavid C Somayajulu 6807fb51846SDavid C Somayajulu bzero(name_str, (sizeof(uint8_t) * sizeof(name_str))); 6817fb51846SDavid C Somayajulu snprintf(name_str, sizeof(name_str), "%d", i); 6827fb51846SDavid C Somayajulu 6837fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str, 6847fb51846SDavid C Somayajulu CTLFLAG_RD, NULL, name_str); 6857fb51846SDavid C Somayajulu node_children = SYSCTL_CHILDREN(ctx_oid); 6867fb51846SDavid C Somayajulu 6877fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children, 6887fb51846SDavid C Somayajulu OID_AUTO, "intr_count", 6897fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.sds[i].intr_count, 6907fb51846SDavid C Somayajulu "intr_count"); 6917fb51846SDavid C Somayajulu 6927fb51846SDavid C Somayajulu SYSCTL_ADD_UINT(ctx, node_children, 6937fb51846SDavid C Somayajulu OID_AUTO, "rx_free", 6947fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.sds[i].rx_free, 6957fb51846SDavid C Somayajulu ha->hw.sds[i].rx_free, "rx_free"); 6967fb51846SDavid C Somayajulu } 6977fb51846SDavid C Somayajulu 6987fb51846SDavid C Somayajulu return; 6997fb51846SDavid C Somayajulu } 7007fb51846SDavid C Somayajulu static void 7017fb51846SDavid C Somayajulu qlnx_add_drvr_rds_stats(qla_host_t *ha) 7027fb51846SDavid C Somayajulu { 7037fb51846SDavid C Somayajulu struct sysctl_ctx_list *ctx; 7047fb51846SDavid C Somayajulu struct sysctl_oid_list *children; 7057fb51846SDavid C Somayajulu struct sysctl_oid_list *node_children; 7067fb51846SDavid C Somayajulu struct sysctl_oid *ctx_oid; 7077fb51846SDavid C Somayajulu int i; 7087fb51846SDavid C Somayajulu uint8_t name_str[16]; 7097fb51846SDavid C Somayajulu 7107fb51846SDavid C Somayajulu ctx = device_get_sysctl_ctx(ha->pci_dev); 7117fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev)); 7127fb51846SDavid C Somayajulu 7137fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_rds", 7147fb51846SDavid C Somayajulu CTLFLAG_RD, NULL, "stats_drvr_rds"); 7157fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(ctx_oid); 7167fb51846SDavid C Somayajulu 7177fb51846SDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) { 7187fb51846SDavid C Somayajulu 7197fb51846SDavid C Somayajulu bzero(name_str, (sizeof(uint8_t) * sizeof(name_str))); 7207fb51846SDavid C Somayajulu snprintf(name_str, sizeof(name_str), "%d", i); 7217fb51846SDavid C Somayajulu 7227fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str, 7237fb51846SDavid C Somayajulu CTLFLAG_RD, NULL, name_str); 7247fb51846SDavid C Somayajulu node_children = SYSCTL_CHILDREN(ctx_oid); 7257fb51846SDavid C Somayajulu 7267fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children, 7277fb51846SDavid C Somayajulu OID_AUTO, "count", 7287fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rds[i].count, 7297fb51846SDavid C Somayajulu "count"); 7307fb51846SDavid C Somayajulu 7317fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children, 7327fb51846SDavid C Somayajulu OID_AUTO, "lro_pkt_count", 7337fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rds[i].lro_pkt_count, 7347fb51846SDavid C Somayajulu "lro_pkt_count"); 7357fb51846SDavid C Somayajulu 7367fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children, 7377fb51846SDavid C Somayajulu OID_AUTO, "lro_bytes", 7387fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->hw.rds[i].lro_bytes, 7397fb51846SDavid C Somayajulu "lro_bytes"); 7407fb51846SDavid C Somayajulu } 7417fb51846SDavid C Somayajulu 7427fb51846SDavid C Somayajulu return; 7437fb51846SDavid C Somayajulu } 7447fb51846SDavid C Somayajulu 7457fb51846SDavid C Somayajulu static void 7467fb51846SDavid C Somayajulu qlnx_add_drvr_tx_stats(qla_host_t *ha) 7477fb51846SDavid C Somayajulu { 7487fb51846SDavid C Somayajulu struct sysctl_ctx_list *ctx; 7497fb51846SDavid C Somayajulu struct sysctl_oid_list *children; 7507fb51846SDavid C Somayajulu struct sysctl_oid_list *node_children; 7517fb51846SDavid C Somayajulu struct sysctl_oid *ctx_oid; 7527fb51846SDavid C Somayajulu int i; 7537fb51846SDavid C Somayajulu uint8_t name_str[16]; 7547fb51846SDavid C Somayajulu 7557fb51846SDavid C Somayajulu ctx = device_get_sysctl_ctx(ha->pci_dev); 7567fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev)); 7577fb51846SDavid C Somayajulu 7587fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats_drvr_xmt", 7597fb51846SDavid C Somayajulu CTLFLAG_RD, NULL, "stats_drvr_xmt"); 7607fb51846SDavid C Somayajulu children = SYSCTL_CHILDREN(ctx_oid); 7617fb51846SDavid C Somayajulu 7627fb51846SDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 7637fb51846SDavid C Somayajulu 7647fb51846SDavid C Somayajulu bzero(name_str, (sizeof(uint8_t) * sizeof(name_str))); 7657fb51846SDavid C Somayajulu snprintf(name_str, sizeof(name_str), "%d", i); 7667fb51846SDavid C Somayajulu 7677fb51846SDavid C Somayajulu ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str, 7687fb51846SDavid C Somayajulu CTLFLAG_RD, NULL, name_str); 7697fb51846SDavid C Somayajulu node_children = SYSCTL_CHILDREN(ctx_oid); 7707fb51846SDavid C Somayajulu 7717fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children, 7727fb51846SDavid C Somayajulu OID_AUTO, "count", 7737fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->tx_ring[i].count, 7747fb51846SDavid C Somayajulu "count"); 7757fb51846SDavid C Somayajulu 7767fb51846SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV 7777fb51846SDavid C Somayajulu SYSCTL_ADD_QUAD(ctx, node_children, 7787fb51846SDavid C Somayajulu OID_AUTO, "iscsi_pkt_count", 7797fb51846SDavid C Somayajulu CTLFLAG_RD, &ha->tx_ring[i].iscsi_pkt_count, 7807fb51846SDavid C Somayajulu "iscsi_pkt_count"); 7817fb51846SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */ 7827fb51846SDavid C Somayajulu } 7837fb51846SDavid C Somayajulu 7847fb51846SDavid C Somayajulu return; 7857fb51846SDavid C Somayajulu } 7867fb51846SDavid C Somayajulu 7877fb51846SDavid C Somayajulu static void 7887fb51846SDavid C Somayajulu qlnx_add_drvr_stats_sysctls(qla_host_t *ha) 7897fb51846SDavid C Somayajulu { 7907fb51846SDavid C Somayajulu qlnx_add_drvr_sds_stats(ha); 7917fb51846SDavid C Somayajulu qlnx_add_drvr_rds_stats(ha); 7927fb51846SDavid C Somayajulu qlnx_add_drvr_tx_stats(ha); 7937fb51846SDavid C Somayajulu return; 7947fb51846SDavid C Somayajulu } 79500caeec7SDavid C Somayajulu 796f10a77bbSDavid C Somayajulu /* 797f10a77bbSDavid C Somayajulu * Name: ql_hw_add_sysctls 798f10a77bbSDavid C Somayajulu * Function: Add P3Plus specific sysctls 799f10a77bbSDavid C Somayajulu */ 800f10a77bbSDavid C Somayajulu void 801f10a77bbSDavid C Somayajulu ql_hw_add_sysctls(qla_host_t *ha) 802f10a77bbSDavid C Somayajulu { 803f10a77bbSDavid C Somayajulu device_t dev; 804f10a77bbSDavid C Somayajulu 805f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 806f10a77bbSDavid C Somayajulu 807f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 808f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 809f10a77bbSDavid C Somayajulu OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings, 810f10a77bbSDavid C Somayajulu ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings"); 811f10a77bbSDavid C Somayajulu 812f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 813f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 814f10a77bbSDavid C Somayajulu OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings, 815f10a77bbSDavid C Somayajulu ha->hw.num_sds_rings, "Number of Status Descriptor Rings"); 816f10a77bbSDavid C Somayajulu 817f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 818f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 819f10a77bbSDavid C Somayajulu OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings, 820f10a77bbSDavid C Somayajulu ha->hw.num_tx_rings, "Number of Transmit Rings"); 821f10a77bbSDavid C Somayajulu 822f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 823f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 824f10a77bbSDavid C Somayajulu OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx, 825f10a77bbSDavid C Somayajulu ha->txr_idx, "Tx Ring Used"); 826f10a77bbSDavid C Somayajulu 827f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 828f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 829f10a77bbSDavid C Somayajulu OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs, 830f10a77bbSDavid C Somayajulu ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt"); 831f10a77bbSDavid C Somayajulu 832f10a77bbSDavid C Somayajulu ha->hw.sds_cidx_thres = 32; 833f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 834f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 835f10a77bbSDavid C Somayajulu OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres, 836f10a77bbSDavid C Somayajulu ha->hw.sds_cidx_thres, 837f10a77bbSDavid C Somayajulu "Number of SDS entries to process before updating" 838f10a77bbSDavid C Somayajulu " SDS Ring Consumer Index"); 839f10a77bbSDavid C Somayajulu 840f10a77bbSDavid C Somayajulu ha->hw.rds_pidx_thres = 32; 841f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 842f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 843f10a77bbSDavid C Somayajulu OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres, 844f10a77bbSDavid C Somayajulu ha->hw.rds_pidx_thres, 845f10a77bbSDavid C Somayajulu "Number of Rcv Rings Entries to post before updating" 846f10a77bbSDavid C Somayajulu " RDS Ring Producer Index"); 847f10a77bbSDavid C Somayajulu 84835291c22SDavid C Somayajulu ha->hw.rcv_intr_coalesce = (3 << 16) | 256; 849c12c5bfbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 850c12c5bfbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 85135291c22SDavid C Somayajulu OID_AUTO, "rcv_intr_coalesce", CTLFLAG_RW, 85235291c22SDavid C Somayajulu &ha->hw.rcv_intr_coalesce, 85335291c22SDavid C Somayajulu ha->hw.rcv_intr_coalesce, 85435291c22SDavid C Somayajulu "Rcv Intr Coalescing Parameters\n" 85535291c22SDavid C Somayajulu "\tbits 15:0 max packets\n" 85635291c22SDavid C Somayajulu "\tbits 31:16 max micro-seconds to wait\n" 85735291c22SDavid C Somayajulu "\tplease run\n" 85835291c22SDavid C Somayajulu "\tifconfig <if> down && ifconfig <if> up\n" 85935291c22SDavid C Somayajulu "\tto take effect \n"); 86035291c22SDavid C Somayajulu 86135291c22SDavid C Somayajulu ha->hw.xmt_intr_coalesce = (64 << 16) | 64; 86235291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 86335291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 86435291c22SDavid C Somayajulu OID_AUTO, "xmt_intr_coalesce", CTLFLAG_RW, 86535291c22SDavid C Somayajulu &ha->hw.xmt_intr_coalesce, 86635291c22SDavid C Somayajulu ha->hw.xmt_intr_coalesce, 86735291c22SDavid C Somayajulu "Xmt Intr Coalescing Parameters\n" 86835291c22SDavid C Somayajulu "\tbits 15:0 max packets\n" 86935291c22SDavid C Somayajulu "\tbits 31:16 max micro-seconds to wait\n" 87035291c22SDavid C Somayajulu "\tplease run\n" 87135291c22SDavid C Somayajulu "\tifconfig <if> down && ifconfig <if> up\n" 87235291c22SDavid C Somayajulu "\tto take effect \n"); 87335291c22SDavid C Somayajulu 87435291c22SDavid C Somayajulu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 87535291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 87635291c22SDavid C Somayajulu OID_AUTO, "port_cfg", CTLTYPE_INT | CTLFLAG_RW, 87735291c22SDavid C Somayajulu (void *)ha, 0, 87835291c22SDavid C Somayajulu qla_sysctl_port_cfg, "I", 87935291c22SDavid C Somayajulu "Set Port Configuration if values below " 88035291c22SDavid C Somayajulu "otherwise Get Port Configuration\n" 88135291c22SDavid C Somayajulu "\tBits 0-3 ; 1 = DCBX Enable; 0 = DCBX Disable\n" 88235291c22SDavid C Somayajulu "\tBits 4-7 : 0 = no pause; 1 = std ; 2 = ppm \n" 88335291c22SDavid C Somayajulu "\tBits 8-11: std pause cfg; 0 = xmt and rcv;" 88435291c22SDavid C Somayajulu " 1 = xmt only; 2 = rcv only;\n" 88535291c22SDavid C Somayajulu ); 88635291c22SDavid C Somayajulu 88700caeec7SDavid C Somayajulu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 88800caeec7SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 88900caeec7SDavid C Somayajulu OID_AUTO, "set_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW, 89000caeec7SDavid C Somayajulu (void *)ha, 0, 89100caeec7SDavid C Somayajulu qla_sysctl_set_cam_search_mode, "I", 89200caeec7SDavid C Somayajulu "Set CAM Search Mode" 89300caeec7SDavid C Somayajulu "\t 1 = search mode internal\n" 89400caeec7SDavid C Somayajulu "\t 2 = search mode auto\n"); 89500caeec7SDavid C Somayajulu 89600caeec7SDavid C Somayajulu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 89700caeec7SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 89800caeec7SDavid C Somayajulu OID_AUTO, "get_cam_search_mode", CTLTYPE_INT | CTLFLAG_RW, 89900caeec7SDavid C Somayajulu (void *)ha, 0, 90000caeec7SDavid C Somayajulu qla_sysctl_get_cam_search_mode, "I", 90100caeec7SDavid C Somayajulu "Get CAM Search Mode" 90200caeec7SDavid C Somayajulu "\t 1 = search mode internal\n" 90300caeec7SDavid C Somayajulu "\t 2 = search mode auto\n"); 90400caeec7SDavid C Somayajulu 90535291c22SDavid C Somayajulu ha->hw.enable_9kb = 1; 90635291c22SDavid C Somayajulu 90735291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 90835291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 90935291c22SDavid C Somayajulu OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb, 91035291c22SDavid C Somayajulu ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000"); 911c12c5bfbSDavid C Somayajulu 912a7c62c11SDavid C Somayajulu ha->hw.enable_hw_lro = 1; 913a7c62c11SDavid C Somayajulu 914a7c62c11SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 915a7c62c11SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 916a7c62c11SDavid C Somayajulu OID_AUTO, "enable_hw_lro", CTLFLAG_RW, &ha->hw.enable_hw_lro, 917a7c62c11SDavid C Somayajulu ha->hw.enable_hw_lro, "Enable Hardware LRO; Default is true \n" 918a7c62c11SDavid C Somayajulu "\t 1 : Hardware LRO if LRO is enabled\n" 919a7c62c11SDavid C Somayajulu "\t 0 : Software LRO if LRO is enabled\n" 920a7c62c11SDavid C Somayajulu "\t Any change requires ifconfig down/up to take effect\n" 921a7c62c11SDavid C Somayajulu "\t Note that LRO may be turned off/on via ifconfig\n"); 922a7c62c11SDavid C Somayajulu 923f10a77bbSDavid C Somayajulu ha->hw.mdump_active = 0; 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, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active, 927f10a77bbSDavid C Somayajulu ha->hw.mdump_active, 9286a62bec0SDavid C Somayajulu "Minidump retrieval is Active"); 929f10a77bbSDavid C Somayajulu 9306a62bec0SDavid C Somayajulu ha->hw.mdump_done = 0; 931f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 932f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 9336a62bec0SDavid C Somayajulu OID_AUTO, "mdump_done", CTLFLAG_RW, 9346a62bec0SDavid C Somayajulu &ha->hw.mdump_done, ha->hw.mdump_done, 9356a62bec0SDavid C Somayajulu "Minidump has been done and available for retrieval"); 9366a62bec0SDavid C Somayajulu 9376a62bec0SDavid C Somayajulu ha->hw.mdump_capture_mask = 0xF; 9386a62bec0SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 9396a62bec0SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 9406a62bec0SDavid C Somayajulu OID_AUTO, "minidump_capture_mask", CTLFLAG_RW, 9416a62bec0SDavid C Somayajulu &ha->hw.mdump_capture_mask, ha->hw.mdump_capture_mask, 9426a62bec0SDavid C Somayajulu "Minidump capture mask"); 943f10a77bbSDavid C Somayajulu #ifdef QL_DBG 944f10a77bbSDavid C Somayajulu 945467dcb5aSDavid C Somayajulu ha->err_inject = 0; 946f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 947f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 948f10a77bbSDavid C Somayajulu OID_AUTO, "err_inject", 949f10a77bbSDavid C Somayajulu CTLFLAG_RW, &ha->err_inject, ha->err_inject, 950f10a77bbSDavid C Somayajulu "Error to be injected\n" 951f10a77bbSDavid C Somayajulu "\t\t\t 0: No Errors\n" 952f10a77bbSDavid C Somayajulu "\t\t\t 1: rcv: rxb struct invalid\n" 953f10a77bbSDavid C Somayajulu "\t\t\t 2: rcv: mp == NULL\n" 954f10a77bbSDavid C Somayajulu "\t\t\t 3: lro: rxb struct invalid\n" 955f10a77bbSDavid C Somayajulu "\t\t\t 4: lro: mp == NULL\n" 956f10a77bbSDavid C Somayajulu "\t\t\t 5: rcv: num handles invalid\n" 957f10a77bbSDavid C Somayajulu "\t\t\t 6: reg: indirect reg rd_wr failure\n" 958f10a77bbSDavid C Somayajulu "\t\t\t 7: ocm: offchip memory rd_wr failure\n" 959f10a77bbSDavid C Somayajulu "\t\t\t 8: mbx: mailbox command failure\n" 960f10a77bbSDavid C Somayajulu "\t\t\t 9: heartbeat failure\n" 96100caeec7SDavid C Somayajulu "\t\t\t A: temperature failure\n" 96200caeec7SDavid C Somayajulu "\t\t\t 11: m_getcl or m_getjcl failure\n" ); 963f10a77bbSDavid C Somayajulu 964f10a77bbSDavid C Somayajulu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 965f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 966f10a77bbSDavid C Somayajulu OID_AUTO, "peg_stop", CTLTYPE_INT | CTLFLAG_RW, 967f10a77bbSDavid C Somayajulu (void *)ha, 0, 968f10a77bbSDavid C Somayajulu qla_sysctl_stop_pegs, "I", "Peg Stop"); 969f10a77bbSDavid C Somayajulu 970f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */ 971f10a77bbSDavid C Somayajulu 97235291c22SDavid C Somayajulu ha->hw.user_pri_nic = 0; 97335291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 97435291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 97535291c22SDavid C Somayajulu OID_AUTO, "user_pri_nic", CTLFLAG_RW, &ha->hw.user_pri_nic, 97635291c22SDavid C Somayajulu ha->hw.user_pri_nic, 97735291c22SDavid C Somayajulu "VLAN Tag User Priority for Normal Ethernet Packets"); 97835291c22SDavid C Somayajulu 97935291c22SDavid C Somayajulu ha->hw.user_pri_iscsi = 4; 98035291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 98135291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 98235291c22SDavid C Somayajulu OID_AUTO, "user_pri_iscsi", CTLFLAG_RW, &ha->hw.user_pri_iscsi, 98335291c22SDavid C Somayajulu ha->hw.user_pri_iscsi, 98435291c22SDavid C Somayajulu "VLAN Tag User Priority for iSCSI Packets"); 98535291c22SDavid C Somayajulu 9867fb51846SDavid C Somayajulu qlnx_add_hw_stats_sysctls(ha); 9877fb51846SDavid C Somayajulu qlnx_add_drvr_stats_sysctls(ha); 9887fb51846SDavid C Somayajulu 9897fb51846SDavid C Somayajulu return; 990f10a77bbSDavid C Somayajulu } 991f10a77bbSDavid C Somayajulu 992f10a77bbSDavid C Somayajulu void 993f10a77bbSDavid C Somayajulu ql_hw_link_status(qla_host_t *ha) 994f10a77bbSDavid C Somayajulu { 995f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui); 996f10a77bbSDavid C Somayajulu 997f10a77bbSDavid C Somayajulu if (ha->hw.link_up) { 998f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link Up\n"); 999f10a77bbSDavid C Somayajulu } else { 1000f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link Down\n"); 1001f10a77bbSDavid C Somayajulu } 1002f10a77bbSDavid C Somayajulu 1003f10a77bbSDavid C Somayajulu if (ha->hw.flags.fduplex) { 1004f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Full Duplex\n"); 1005f10a77bbSDavid C Somayajulu } else { 1006f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Half Duplex\n"); 1007f10a77bbSDavid C Somayajulu } 1008f10a77bbSDavid C Somayajulu 1009f10a77bbSDavid C Somayajulu if (ha->hw.flags.autoneg) { 1010f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Auto Negotiation Enabled\n"); 1011f10a77bbSDavid C Somayajulu } else { 1012f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Auto Negotiation Disabled\n"); 1013f10a77bbSDavid C Somayajulu } 1014f10a77bbSDavid C Somayajulu 1015f10a77bbSDavid C Somayajulu switch (ha->hw.link_speed) { 1016f10a77bbSDavid C Somayajulu case 0x710: 1017f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t 10Gps\n"); 1018f10a77bbSDavid C Somayajulu break; 1019f10a77bbSDavid C Somayajulu 1020f10a77bbSDavid C Somayajulu case 0x3E8: 1021f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t 1Gps\n"); 1022f10a77bbSDavid C Somayajulu break; 1023f10a77bbSDavid C Somayajulu 1024f10a77bbSDavid C Somayajulu case 0x64: 1025f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n"); 1026f10a77bbSDavid C Somayajulu break; 1027f10a77bbSDavid C Somayajulu 1028f10a77bbSDavid C Somayajulu default: 1029f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t Unknown\n"); 1030f10a77bbSDavid C Somayajulu break; 1031f10a77bbSDavid C Somayajulu } 1032f10a77bbSDavid C Somayajulu 1033f10a77bbSDavid C Somayajulu switch (ha->hw.module_type) { 1034f10a77bbSDavid C Somayajulu 1035f10a77bbSDavid C Somayajulu case 0x01: 1036f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n"); 1037f10a77bbSDavid C Somayajulu break; 1038f10a77bbSDavid C Somayajulu 1039f10a77bbSDavid C Somayajulu case 0x02: 1040f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GBase-LR\n"); 1041f10a77bbSDavid C Somayajulu break; 1042f10a77bbSDavid C Somayajulu 1043f10a77bbSDavid C Somayajulu case 0x03: 1044f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GBase-SR\n"); 1045f10a77bbSDavid C Somayajulu break; 1046f10a77bbSDavid C Somayajulu 1047f10a77bbSDavid C Somayajulu case 0x04: 1048f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, 1049f10a77bbSDavid C Somayajulu "Module Type 10GE Passive Copper(Compliant)[%d m]\n", 1050f10a77bbSDavid C Somayajulu ha->hw.cable_length); 1051f10a77bbSDavid C Somayajulu break; 1052f10a77bbSDavid C Somayajulu 1053f10a77bbSDavid C Somayajulu case 0x05: 1054f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GE Active" 1055f10a77bbSDavid C Somayajulu " Limiting Copper(Compliant)[%d m]\n", 1056f10a77bbSDavid C Somayajulu ha->hw.cable_length); 1057f10a77bbSDavid C Somayajulu break; 1058f10a77bbSDavid C Somayajulu 1059f10a77bbSDavid C Somayajulu case 0x06: 1060f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, 1061f10a77bbSDavid C Somayajulu "Module Type 10GE Passive Copper" 1062f10a77bbSDavid C Somayajulu " (Legacy, Best Effort)[%d m]\n", 1063f10a77bbSDavid C Somayajulu ha->hw.cable_length); 1064f10a77bbSDavid C Somayajulu break; 1065f10a77bbSDavid C Somayajulu 1066f10a77bbSDavid C Somayajulu case 0x07: 1067f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-SX\n"); 1068f10a77bbSDavid C Somayajulu break; 1069f10a77bbSDavid C Somayajulu 1070f10a77bbSDavid C Somayajulu case 0x08: 1071f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-LX\n"); 1072f10a77bbSDavid C Somayajulu break; 1073f10a77bbSDavid C Somayajulu 1074f10a77bbSDavid C Somayajulu case 0x09: 1075f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-CX\n"); 1076f10a77bbSDavid C Somayajulu break; 1077f10a77bbSDavid C Somayajulu 1078f10a77bbSDavid C Somayajulu case 0x0A: 1079f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-T\n"); 1080f10a77bbSDavid C Somayajulu break; 1081f10a77bbSDavid C Somayajulu 1082f10a77bbSDavid C Somayajulu case 0x0B: 1083f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1GE Passive Copper" 1084f10a77bbSDavid C Somayajulu "(Legacy, Best Effort)\n"); 1085f10a77bbSDavid C Somayajulu break; 1086f10a77bbSDavid C Somayajulu 1087f10a77bbSDavid C Somayajulu default: 1088f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n", 1089f10a77bbSDavid C Somayajulu ha->hw.module_type); 1090f10a77bbSDavid C Somayajulu break; 1091f10a77bbSDavid C Somayajulu } 1092f10a77bbSDavid C Somayajulu 1093f10a77bbSDavid C Somayajulu if (ha->hw.link_faults == 1) 1094f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "SFP Power Fault\n"); 1095f10a77bbSDavid C Somayajulu } 1096f10a77bbSDavid C Somayajulu 1097f10a77bbSDavid C Somayajulu /* 1098f10a77bbSDavid C Somayajulu * Name: ql_free_dma 1099f10a77bbSDavid C Somayajulu * Function: Frees the DMA'able memory allocated in ql_alloc_dma() 1100f10a77bbSDavid C Somayajulu */ 1101f10a77bbSDavid C Somayajulu void 1102f10a77bbSDavid C Somayajulu ql_free_dma(qla_host_t *ha) 1103f10a77bbSDavid C Somayajulu { 1104f10a77bbSDavid C Somayajulu uint32_t i; 1105f10a77bbSDavid C Somayajulu 1106f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.sds_ring) { 1107f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 1108f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]); 1109f10a77bbSDavid C Somayajulu } 1110f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.sds_ring = 0; 1111f10a77bbSDavid C Somayajulu } 1112f10a77bbSDavid C Somayajulu 1113f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.rds_ring) { 1114f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) { 1115f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]); 1116f10a77bbSDavid C Somayajulu } 1117f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.rds_ring = 0; 1118f10a77bbSDavid C Somayajulu } 1119f10a77bbSDavid C Somayajulu 1120f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.tx_ring) { 1121f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring); 1122f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.tx_ring = 0; 1123f10a77bbSDavid C Somayajulu } 11246a62bec0SDavid C Somayajulu ql_minidump_free(ha); 1125f10a77bbSDavid C Somayajulu } 1126f10a77bbSDavid C Somayajulu 1127f10a77bbSDavid C Somayajulu /* 1128f10a77bbSDavid C Somayajulu * Name: ql_alloc_dma 1129f10a77bbSDavid C Somayajulu * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts. 1130f10a77bbSDavid C Somayajulu */ 1131f10a77bbSDavid C Somayajulu int 1132f10a77bbSDavid C Somayajulu ql_alloc_dma(qla_host_t *ha) 1133f10a77bbSDavid C Somayajulu { 1134f10a77bbSDavid C Somayajulu device_t dev; 1135f10a77bbSDavid C Somayajulu uint32_t i, j, size, tx_ring_size; 1136f10a77bbSDavid C Somayajulu qla_hw_t *hw; 1137f10a77bbSDavid C Somayajulu qla_hw_tx_cntxt_t *tx_cntxt; 1138f10a77bbSDavid C Somayajulu uint8_t *vaddr; 1139f10a77bbSDavid C Somayajulu bus_addr_t paddr; 1140f10a77bbSDavid C Somayajulu 1141f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1142f10a77bbSDavid C Somayajulu 1143f10a77bbSDavid C Somayajulu QL_DPRINT2(ha, (dev, "%s: enter\n", __func__)); 1144f10a77bbSDavid C Somayajulu 1145f10a77bbSDavid C Somayajulu hw = &ha->hw; 1146f10a77bbSDavid C Somayajulu /* 1147f10a77bbSDavid C Somayajulu * Allocate Transmit Ring 1148f10a77bbSDavid C Somayajulu */ 1149f10a77bbSDavid C Somayajulu tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS); 1150f10a77bbSDavid C Somayajulu size = (tx_ring_size * ha->hw.num_tx_rings); 1151f10a77bbSDavid C Somayajulu 1152f10a77bbSDavid C Somayajulu hw->dma_buf.tx_ring.alignment = 8; 1153f10a77bbSDavid C Somayajulu hw->dma_buf.tx_ring.size = size + PAGE_SIZE; 1154f10a77bbSDavid C Somayajulu 1155f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) { 1156f10a77bbSDavid C Somayajulu device_printf(dev, "%s: tx ring alloc failed\n", __func__); 1157f10a77bbSDavid C Somayajulu goto ql_alloc_dma_exit; 1158f10a77bbSDavid C Somayajulu } 1159f10a77bbSDavid C Somayajulu 1160f10a77bbSDavid C Somayajulu vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b; 1161f10a77bbSDavid C Somayajulu paddr = hw->dma_buf.tx_ring.dma_addr; 1162f10a77bbSDavid C Somayajulu 1163f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 1164f10a77bbSDavid C Somayajulu tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i]; 1165f10a77bbSDavid C Somayajulu 1166f10a77bbSDavid C Somayajulu tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr; 1167f10a77bbSDavid C Somayajulu tx_cntxt->tx_ring_paddr = paddr; 1168f10a77bbSDavid C Somayajulu 1169f10a77bbSDavid C Somayajulu vaddr += tx_ring_size; 1170f10a77bbSDavid C Somayajulu paddr += tx_ring_size; 1171f10a77bbSDavid C Somayajulu } 1172f10a77bbSDavid C Somayajulu 1173f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 1174f10a77bbSDavid C Somayajulu tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i]; 1175f10a77bbSDavid C Somayajulu 1176f10a77bbSDavid C Somayajulu tx_cntxt->tx_cons = (uint32_t *)vaddr; 1177f10a77bbSDavid C Somayajulu tx_cntxt->tx_cons_paddr = paddr; 1178f10a77bbSDavid C Somayajulu 1179f10a77bbSDavid C Somayajulu vaddr += sizeof (uint32_t); 1180f10a77bbSDavid C Somayajulu paddr += sizeof (uint32_t); 1181f10a77bbSDavid C Somayajulu } 1182f10a77bbSDavid C Somayajulu 1183f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.tx_ring = 1; 1184f10a77bbSDavid C Somayajulu 1185f10a77bbSDavid C Somayajulu QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n", 1186f10a77bbSDavid C Somayajulu __func__, (void *)(hw->dma_buf.tx_ring.dma_addr), 1187f10a77bbSDavid C Somayajulu hw->dma_buf.tx_ring.dma_b)); 1188f10a77bbSDavid C Somayajulu /* 1189f10a77bbSDavid C Somayajulu * Allocate Receive Descriptor Rings 1190f10a77bbSDavid C Somayajulu */ 1191f10a77bbSDavid C Somayajulu 1192f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_rds_rings; i++) { 1193f10a77bbSDavid C Somayajulu 1194f10a77bbSDavid C Somayajulu hw->dma_buf.rds_ring[i].alignment = 8; 1195f10a77bbSDavid C Somayajulu hw->dma_buf.rds_ring[i].size = 1196f10a77bbSDavid C Somayajulu (sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS; 1197f10a77bbSDavid C Somayajulu 1198f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) { 1199f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rds ring[%d] alloc failed\n", 1200f10a77bbSDavid C Somayajulu __func__, i); 1201f10a77bbSDavid C Somayajulu 1202f10a77bbSDavid C Somayajulu for (j = 0; j < i; j++) 1203f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]); 1204f10a77bbSDavid C Somayajulu 1205f10a77bbSDavid C Somayajulu goto ql_alloc_dma_exit; 1206f10a77bbSDavid C Somayajulu } 1207f10a77bbSDavid C Somayajulu QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n", 1208f10a77bbSDavid C Somayajulu __func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr), 1209f10a77bbSDavid C Somayajulu hw->dma_buf.rds_ring[i].dma_b)); 1210f10a77bbSDavid C Somayajulu } 1211f10a77bbSDavid C Somayajulu 1212f10a77bbSDavid C Somayajulu hw->dma_buf.flags.rds_ring = 1; 1213f10a77bbSDavid C Somayajulu 1214f10a77bbSDavid C Somayajulu /* 1215f10a77bbSDavid C Somayajulu * Allocate Status Descriptor Rings 1216f10a77bbSDavid C Somayajulu */ 1217f10a77bbSDavid C Somayajulu 1218f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) { 1219f10a77bbSDavid C Somayajulu hw->dma_buf.sds_ring[i].alignment = 8; 1220f10a77bbSDavid C Somayajulu hw->dma_buf.sds_ring[i].size = 1221f10a77bbSDavid C Somayajulu (sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS; 1222f10a77bbSDavid C Somayajulu 1223f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) { 1224f10a77bbSDavid C Somayajulu device_printf(dev, "%s: sds ring alloc failed\n", 1225f10a77bbSDavid C Somayajulu __func__); 1226f10a77bbSDavid C Somayajulu 1227f10a77bbSDavid C Somayajulu for (j = 0; j < i; j++) 1228f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]); 1229f10a77bbSDavid C Somayajulu 1230f10a77bbSDavid C Somayajulu goto ql_alloc_dma_exit; 1231f10a77bbSDavid C Somayajulu } 1232f10a77bbSDavid C Somayajulu QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n", 1233f10a77bbSDavid C Somayajulu __func__, i, 1234f10a77bbSDavid C Somayajulu (void *)(hw->dma_buf.sds_ring[i].dma_addr), 1235f10a77bbSDavid C Somayajulu hw->dma_buf.sds_ring[i].dma_b)); 1236f10a77bbSDavid C Somayajulu } 1237f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) { 1238f10a77bbSDavid C Somayajulu hw->sds[i].sds_ring_base = 1239f10a77bbSDavid C Somayajulu (q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b; 1240f10a77bbSDavid C Somayajulu } 1241f10a77bbSDavid C Somayajulu 1242f10a77bbSDavid C Somayajulu hw->dma_buf.flags.sds_ring = 1; 1243f10a77bbSDavid C Somayajulu 1244f10a77bbSDavid C Somayajulu return 0; 1245f10a77bbSDavid C Somayajulu 1246f10a77bbSDavid C Somayajulu ql_alloc_dma_exit: 1247f10a77bbSDavid C Somayajulu ql_free_dma(ha); 1248f10a77bbSDavid C Somayajulu return -1; 1249f10a77bbSDavid C Somayajulu } 1250f10a77bbSDavid C Somayajulu 1251f10a77bbSDavid C Somayajulu #define Q8_MBX_MSEC_DELAY 5000 1252f10a77bbSDavid C Somayajulu 1253f10a77bbSDavid C Somayajulu static int 1254f10a77bbSDavid C Somayajulu qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox, 1255f10a77bbSDavid C Somayajulu uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause) 1256f10a77bbSDavid C Somayajulu { 1257f10a77bbSDavid C Somayajulu uint32_t i; 1258f10a77bbSDavid C Somayajulu uint32_t data; 1259f10a77bbSDavid C Somayajulu int ret = 0; 1260f10a77bbSDavid C Somayajulu 1261f10a77bbSDavid C Somayajulu if (QL_ERR_INJECT(ha, INJCT_MBX_CMD_FAILURE)) { 1262f10a77bbSDavid C Somayajulu ret = -3; 1263f10a77bbSDavid C Somayajulu ha->qla_initiate_recovery = 1; 1264f10a77bbSDavid C Somayajulu goto exit_qla_mbx_cmd; 1265f10a77bbSDavid C Somayajulu } 1266f10a77bbSDavid C Somayajulu 1267f10a77bbSDavid C Somayajulu if (no_pause) 1268f10a77bbSDavid C Somayajulu i = 1000; 1269f10a77bbSDavid C Somayajulu else 1270f10a77bbSDavid C Somayajulu i = Q8_MBX_MSEC_DELAY; 1271f10a77bbSDavid C Somayajulu 1272f10a77bbSDavid C Somayajulu while (i) { 1273f10a77bbSDavid C Somayajulu data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL); 1274f10a77bbSDavid C Somayajulu if (data == 0) 1275f10a77bbSDavid C Somayajulu break; 1276f10a77bbSDavid C Somayajulu if (no_pause) { 1277f10a77bbSDavid C Somayajulu DELAY(1000); 1278f10a77bbSDavid C Somayajulu } else { 1279f10a77bbSDavid C Somayajulu qla_mdelay(__func__, 1); 1280f10a77bbSDavid C Somayajulu } 1281f10a77bbSDavid C Somayajulu i--; 1282f10a77bbSDavid C Somayajulu } 1283f10a77bbSDavid C Somayajulu 1284f10a77bbSDavid C Somayajulu if (i == 0) { 1285f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n", 1286f10a77bbSDavid C Somayajulu __func__, data); 1287f10a77bbSDavid C Somayajulu ret = -1; 1288f10a77bbSDavid C Somayajulu ha->qla_initiate_recovery = 1; 1289f10a77bbSDavid C Somayajulu goto exit_qla_mbx_cmd; 1290f10a77bbSDavid C Somayajulu } 1291f10a77bbSDavid C Somayajulu 1292f10a77bbSDavid C Somayajulu for (i = 0; i < n_hmbox; i++) { 1293f10a77bbSDavid C Somayajulu WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox); 1294f10a77bbSDavid C Somayajulu h_mbox++; 1295f10a77bbSDavid C Somayajulu } 1296f10a77bbSDavid C Somayajulu 1297f10a77bbSDavid C Somayajulu WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1); 1298f10a77bbSDavid C Somayajulu 1299f10a77bbSDavid C Somayajulu 1300f10a77bbSDavid C Somayajulu i = Q8_MBX_MSEC_DELAY; 1301f10a77bbSDavid C Somayajulu while (i) { 1302f10a77bbSDavid C Somayajulu data = READ_REG32(ha, Q8_FW_MBOX_CNTRL); 1303f10a77bbSDavid C Somayajulu 1304f10a77bbSDavid C Somayajulu if ((data & 0x3) == 1) { 1305f10a77bbSDavid C Somayajulu data = READ_REG32(ha, Q8_FW_MBOX0); 1306f10a77bbSDavid C Somayajulu if ((data & 0xF000) != 0x8000) 1307f10a77bbSDavid C Somayajulu break; 1308f10a77bbSDavid C Somayajulu } 1309f10a77bbSDavid C Somayajulu if (no_pause) { 1310f10a77bbSDavid C Somayajulu DELAY(1000); 1311f10a77bbSDavid C Somayajulu } else { 1312f10a77bbSDavid C Somayajulu qla_mdelay(__func__, 1); 1313f10a77bbSDavid C Somayajulu } 1314f10a77bbSDavid C Somayajulu i--; 1315f10a77bbSDavid C Somayajulu } 1316f10a77bbSDavid C Somayajulu if (i == 0) { 1317f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n", 1318f10a77bbSDavid C Somayajulu __func__, data); 1319f10a77bbSDavid C Somayajulu ret = -2; 1320f10a77bbSDavid C Somayajulu ha->qla_initiate_recovery = 1; 1321f10a77bbSDavid C Somayajulu goto exit_qla_mbx_cmd; 1322f10a77bbSDavid C Somayajulu } 1323f10a77bbSDavid C Somayajulu 1324f10a77bbSDavid C Somayajulu for (i = 0; i < n_fwmbox; i++) { 1325f10a77bbSDavid C Somayajulu *fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2))); 1326f10a77bbSDavid C Somayajulu } 1327f10a77bbSDavid C Somayajulu 1328f10a77bbSDavid C Somayajulu WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0); 1329f10a77bbSDavid C Somayajulu WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0); 1330f10a77bbSDavid C Somayajulu 1331f10a77bbSDavid C Somayajulu exit_qla_mbx_cmd: 1332f10a77bbSDavid C Somayajulu return (ret); 1333f10a77bbSDavid C Somayajulu } 1334f10a77bbSDavid C Somayajulu 133535291c22SDavid C Somayajulu int 133635291c22SDavid C Somayajulu qla_get_nic_partition(qla_host_t *ha, uint32_t *supports_9kb, 133735291c22SDavid C Somayajulu uint32_t *num_rcvq) 1338f10a77bbSDavid C Somayajulu { 1339f10a77bbSDavid C Somayajulu uint32_t *mbox, err; 1340f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1341f10a77bbSDavid C Somayajulu 1342f10a77bbSDavid C Somayajulu bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX)); 1343f10a77bbSDavid C Somayajulu 1344f10a77bbSDavid C Somayajulu mbox = ha->hw.mbox; 1345f10a77bbSDavid C Somayajulu 1346f10a77bbSDavid C Somayajulu mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29); 1347f10a77bbSDavid C Somayajulu 1348f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) { 1349f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 1350f10a77bbSDavid C Somayajulu return (-1); 1351f10a77bbSDavid C Somayajulu } 1352f10a77bbSDavid C Somayajulu err = mbox[0] >> 25; 1353f10a77bbSDavid C Somayajulu 135435291c22SDavid C Somayajulu if (supports_9kb != NULL) { 135535291c22SDavid C Somayajulu if (mbox[16] & 0x80) /* bit 7 of mbox 16 */ 135635291c22SDavid C Somayajulu *supports_9kb = 1; 135735291c22SDavid C Somayajulu else 135835291c22SDavid C Somayajulu *supports_9kb = 0; 135935291c22SDavid C Somayajulu } 136035291c22SDavid C Somayajulu 136135291c22SDavid C Somayajulu if (num_rcvq != NULL) 136235291c22SDavid C Somayajulu *num_rcvq = ((mbox[6] >> 16) & 0xFFFF); 136335291c22SDavid C Somayajulu 1364f10a77bbSDavid C Somayajulu if ((err != 1) && (err != 0)) { 1365f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 1366f10a77bbSDavid C Somayajulu return (-1); 1367f10a77bbSDavid C Somayajulu } 1368f10a77bbSDavid C Somayajulu return 0; 1369f10a77bbSDavid C Somayajulu } 1370f10a77bbSDavid C Somayajulu 1371f10a77bbSDavid C Somayajulu static int 137235291c22SDavid C Somayajulu qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, uint32_t num_intrs, 137335291c22SDavid C Somayajulu uint32_t create) 1374f10a77bbSDavid C Somayajulu { 1375f10a77bbSDavid C Somayajulu uint32_t i, err; 1376f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1377f10a77bbSDavid C Somayajulu q80_config_intr_t *c_intr; 1378f10a77bbSDavid C Somayajulu q80_config_intr_rsp_t *c_intr_rsp; 1379f10a77bbSDavid C Somayajulu 1380f10a77bbSDavid C Somayajulu c_intr = (q80_config_intr_t *)ha->hw.mbox; 1381f10a77bbSDavid C Somayajulu bzero(c_intr, (sizeof (q80_config_intr_t))); 1382f10a77bbSDavid C Somayajulu 1383f10a77bbSDavid C Somayajulu c_intr->opcode = Q8_MBX_CONFIG_INTR; 1384f10a77bbSDavid C Somayajulu 1385f10a77bbSDavid C Somayajulu c_intr->count_version = (sizeof (q80_config_intr_t) >> 2); 1386f10a77bbSDavid C Somayajulu c_intr->count_version |= Q8_MBX_CMD_VERSION; 1387f10a77bbSDavid C Somayajulu 1388f10a77bbSDavid C Somayajulu c_intr->nentries = num_intrs; 1389f10a77bbSDavid C Somayajulu 1390f10a77bbSDavid C Somayajulu for (i = 0; i < num_intrs; i++) { 1391f10a77bbSDavid C Somayajulu if (create) { 1392f10a77bbSDavid C Somayajulu c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE; 139335291c22SDavid C Somayajulu c_intr->intr[i].msix_index = start_idx + 1 + i; 1394f10a77bbSDavid C Somayajulu } else { 1395f10a77bbSDavid C Somayajulu c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE; 139635291c22SDavid C Somayajulu c_intr->intr[i].msix_index = 139735291c22SDavid C Somayajulu ha->hw.intr_id[(start_idx + i)]; 1398f10a77bbSDavid C Somayajulu } 1399f10a77bbSDavid C Somayajulu 1400f10a77bbSDavid C Somayajulu c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X; 1401f10a77bbSDavid C Somayajulu } 1402f10a77bbSDavid C Somayajulu 1403f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)c_intr, 1404f10a77bbSDavid C Somayajulu (sizeof (q80_config_intr_t) >> 2), 1405f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) { 1406f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 1407f10a77bbSDavid C Somayajulu return (-1); 1408f10a77bbSDavid C Somayajulu } 1409f10a77bbSDavid C Somayajulu 1410f10a77bbSDavid C Somayajulu c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox; 1411f10a77bbSDavid C Somayajulu 1412f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status); 1413f10a77bbSDavid C Somayajulu 1414f10a77bbSDavid C Somayajulu if (err) { 1415f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x, %d]\n", __func__, err, 1416f10a77bbSDavid C Somayajulu c_intr_rsp->nentries); 1417f10a77bbSDavid C Somayajulu 1418f10a77bbSDavid C Somayajulu for (i = 0; i < c_intr_rsp->nentries; i++) { 1419f10a77bbSDavid C Somayajulu device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n", 1420f10a77bbSDavid C Somayajulu __func__, i, 1421f10a77bbSDavid C Somayajulu c_intr_rsp->intr[i].status, 1422f10a77bbSDavid C Somayajulu c_intr_rsp->intr[i].intr_id, 1423f10a77bbSDavid C Somayajulu c_intr_rsp->intr[i].intr_src); 1424f10a77bbSDavid C Somayajulu } 1425f10a77bbSDavid C Somayajulu 1426f10a77bbSDavid C Somayajulu return (-1); 1427f10a77bbSDavid C Somayajulu } 1428f10a77bbSDavid C Somayajulu 1429f10a77bbSDavid C Somayajulu for (i = 0; ((i < num_intrs) && create); i++) { 1430f10a77bbSDavid C Somayajulu if (!c_intr_rsp->intr[i].status) { 143135291c22SDavid C Somayajulu ha->hw.intr_id[(start_idx + i)] = 143235291c22SDavid C Somayajulu c_intr_rsp->intr[i].intr_id; 143335291c22SDavid C Somayajulu ha->hw.intr_src[(start_idx + i)] = 143435291c22SDavid C Somayajulu c_intr_rsp->intr[i].intr_src; 1435f10a77bbSDavid C Somayajulu } 1436f10a77bbSDavid C Somayajulu } 1437f10a77bbSDavid C Somayajulu 1438f10a77bbSDavid C Somayajulu return (0); 1439f10a77bbSDavid C Somayajulu } 1440f10a77bbSDavid C Somayajulu 1441f10a77bbSDavid C Somayajulu /* 1442f10a77bbSDavid C Somayajulu * Name: qla_config_rss 1443f10a77bbSDavid C Somayajulu * Function: Configure RSS for the context/interface. 1444f10a77bbSDavid C Somayajulu */ 1445f10a77bbSDavid C Somayajulu static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL, 1446f10a77bbSDavid C Somayajulu 0x8030f20c77cb2da3ULL, 1447f10a77bbSDavid C Somayajulu 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL, 1448f10a77bbSDavid C Somayajulu 0x255b0ec26d5a56daULL }; 1449f10a77bbSDavid C Somayajulu 1450f10a77bbSDavid C Somayajulu static int 1451f10a77bbSDavid C Somayajulu qla_config_rss(qla_host_t *ha, uint16_t cntxt_id) 1452f10a77bbSDavid C Somayajulu { 1453f10a77bbSDavid C Somayajulu q80_config_rss_t *c_rss; 1454f10a77bbSDavid C Somayajulu q80_config_rss_rsp_t *c_rss_rsp; 1455f10a77bbSDavid C Somayajulu uint32_t err, i; 1456f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1457f10a77bbSDavid C Somayajulu 1458f10a77bbSDavid C Somayajulu c_rss = (q80_config_rss_t *)ha->hw.mbox; 1459f10a77bbSDavid C Somayajulu bzero(c_rss, (sizeof (q80_config_rss_t))); 1460f10a77bbSDavid C Somayajulu 1461f10a77bbSDavid C Somayajulu c_rss->opcode = Q8_MBX_CONFIG_RSS; 1462f10a77bbSDavid C Somayajulu 1463f10a77bbSDavid C Somayajulu c_rss->count_version = (sizeof (q80_config_rss_t) >> 2); 1464f10a77bbSDavid C Somayajulu c_rss->count_version |= Q8_MBX_CMD_VERSION; 1465f10a77bbSDavid C Somayajulu 1466f10a77bbSDavid C Somayajulu c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP | 1467f10a77bbSDavid C Somayajulu Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP); 146835291c22SDavid C Somayajulu //c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP | 146935291c22SDavid C Somayajulu // Q8_MBX_RSS_HASH_TYPE_IPV6_TCP); 1470f10a77bbSDavid C Somayajulu 1471f10a77bbSDavid C Somayajulu c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS; 1472f10a77bbSDavid C Somayajulu c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE; 1473f10a77bbSDavid C Somayajulu 1474f10a77bbSDavid C Somayajulu c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK; 1475f10a77bbSDavid C Somayajulu 1476f10a77bbSDavid C Somayajulu c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID; 1477f10a77bbSDavid C Somayajulu c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS; 1478f10a77bbSDavid C Somayajulu 1479f10a77bbSDavid C Somayajulu c_rss->cntxt_id = cntxt_id; 1480f10a77bbSDavid C Somayajulu 1481f10a77bbSDavid C Somayajulu for (i = 0; i < 5; i++) { 1482f10a77bbSDavid C Somayajulu c_rss->rss_key[i] = rss_key[i]; 1483f10a77bbSDavid C Somayajulu } 1484f10a77bbSDavid C Somayajulu 1485f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)c_rss, 1486f10a77bbSDavid C Somayajulu (sizeof (q80_config_rss_t) >> 2), 1487f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) { 1488f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 1489f10a77bbSDavid C Somayajulu return (-1); 1490f10a77bbSDavid C Somayajulu } 1491f10a77bbSDavid C Somayajulu c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox; 1492f10a77bbSDavid C Somayajulu 1493f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status); 1494f10a77bbSDavid C Somayajulu 1495f10a77bbSDavid C Somayajulu if (err) { 1496f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 1497f10a77bbSDavid C Somayajulu return (-1); 1498f10a77bbSDavid C Somayajulu } 1499f10a77bbSDavid C Somayajulu return 0; 1500f10a77bbSDavid C Somayajulu } 1501f10a77bbSDavid C Somayajulu 1502f10a77bbSDavid C Somayajulu static int 1503f10a77bbSDavid C Somayajulu qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count, 1504f10a77bbSDavid C Somayajulu uint16_t cntxt_id, uint8_t *ind_table) 1505f10a77bbSDavid C Somayajulu { 1506f10a77bbSDavid C Somayajulu q80_config_rss_ind_table_t *c_rss_ind; 1507f10a77bbSDavid C Somayajulu q80_config_rss_ind_table_rsp_t *c_rss_ind_rsp; 1508f10a77bbSDavid C Somayajulu uint32_t err; 1509f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1510f10a77bbSDavid C Somayajulu 1511f10a77bbSDavid C Somayajulu if ((count > Q8_RSS_IND_TBL_SIZE) || 1512f10a77bbSDavid C Somayajulu ((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) { 1513f10a77bbSDavid C Somayajulu device_printf(dev, "%s: illegal count [%d, %d]\n", __func__, 1514f10a77bbSDavid C Somayajulu start_idx, count); 1515f10a77bbSDavid C Somayajulu return (-1); 1516f10a77bbSDavid C Somayajulu } 1517f10a77bbSDavid C Somayajulu 1518f10a77bbSDavid C Somayajulu c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox; 1519f10a77bbSDavid C Somayajulu bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t)); 1520f10a77bbSDavid C Somayajulu 1521f10a77bbSDavid C Somayajulu c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE; 1522f10a77bbSDavid C Somayajulu c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2); 1523f10a77bbSDavid C Somayajulu c_rss_ind->count_version |= Q8_MBX_CMD_VERSION; 1524f10a77bbSDavid C Somayajulu 1525f10a77bbSDavid C Somayajulu c_rss_ind->start_idx = start_idx; 1526f10a77bbSDavid C Somayajulu c_rss_ind->end_idx = start_idx + count - 1; 1527f10a77bbSDavid C Somayajulu c_rss_ind->cntxt_id = cntxt_id; 1528f10a77bbSDavid C Somayajulu bcopy(ind_table, c_rss_ind->ind_table, count); 1529f10a77bbSDavid C Somayajulu 1530f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind, 1531f10a77bbSDavid C Somayajulu (sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox, 1532f10a77bbSDavid C Somayajulu (sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) { 1533f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 1534f10a77bbSDavid C Somayajulu return (-1); 1535f10a77bbSDavid C Somayajulu } 1536f10a77bbSDavid C Somayajulu 1537f10a77bbSDavid C Somayajulu c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox; 1538f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status); 1539f10a77bbSDavid C Somayajulu 1540f10a77bbSDavid C Somayajulu if (err) { 1541f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 1542f10a77bbSDavid C Somayajulu return (-1); 1543f10a77bbSDavid C Somayajulu } 1544f10a77bbSDavid C Somayajulu return 0; 1545f10a77bbSDavid C Somayajulu } 1546f10a77bbSDavid C Somayajulu 1547f10a77bbSDavid C Somayajulu /* 1548f10a77bbSDavid C Somayajulu * Name: qla_config_intr_coalesce 1549f10a77bbSDavid C Somayajulu * Function: Configure Interrupt Coalescing. 1550f10a77bbSDavid C Somayajulu */ 1551f10a77bbSDavid C Somayajulu static int 155235291c22SDavid C Somayajulu qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable, 155335291c22SDavid C Somayajulu int rcv) 1554f10a77bbSDavid C Somayajulu { 1555f10a77bbSDavid C Somayajulu q80_config_intr_coalesc_t *intrc; 1556f10a77bbSDavid C Somayajulu q80_config_intr_coalesc_rsp_t *intrc_rsp; 1557f10a77bbSDavid C Somayajulu uint32_t err, i; 1558f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1559f10a77bbSDavid C Somayajulu 1560f10a77bbSDavid C Somayajulu intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox; 1561f10a77bbSDavid C Somayajulu bzero(intrc, (sizeof (q80_config_intr_coalesc_t))); 1562f10a77bbSDavid C Somayajulu 1563f10a77bbSDavid C Somayajulu intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE; 1564f10a77bbSDavid C Somayajulu intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2); 1565f10a77bbSDavid C Somayajulu intrc->count_version |= Q8_MBX_CMD_VERSION; 1566f10a77bbSDavid C Somayajulu 156735291c22SDavid C Somayajulu if (rcv) { 1568f10a77bbSDavid C Somayajulu intrc->flags = Q8_MBX_INTRC_FLAGS_RCV; 156935291c22SDavid C Somayajulu intrc->max_pkts = ha->hw.rcv_intr_coalesce & 0xFFFF; 157035291c22SDavid C Somayajulu intrc->max_mswait = (ha->hw.rcv_intr_coalesce >> 16) & 0xFFFF; 157135291c22SDavid C Somayajulu } else { 157235291c22SDavid C Somayajulu intrc->flags = Q8_MBX_INTRC_FLAGS_XMT; 157335291c22SDavid C Somayajulu intrc->max_pkts = ha->hw.xmt_intr_coalesce & 0xFFFF; 157435291c22SDavid C Somayajulu intrc->max_mswait = (ha->hw.xmt_intr_coalesce >> 16) & 0xFFFF; 157535291c22SDavid C Somayajulu } 1576f10a77bbSDavid C Somayajulu 157735291c22SDavid C Somayajulu intrc->cntxt_id = cntxt_id; 1578f10a77bbSDavid C Somayajulu 1579f10a77bbSDavid C Somayajulu if (tenable) { 1580f10a77bbSDavid C Somayajulu intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC; 1581f10a77bbSDavid C Somayajulu intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC; 1582f10a77bbSDavid C Somayajulu 1583f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 1584f10a77bbSDavid C Somayajulu intrc->sds_ring_mask |= (1 << i); 1585f10a77bbSDavid C Somayajulu } 1586f10a77bbSDavid C Somayajulu intrc->ms_timeout = 1000; 1587f10a77bbSDavid C Somayajulu } 1588f10a77bbSDavid C Somayajulu 1589f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)intrc, 1590f10a77bbSDavid C Somayajulu (sizeof (q80_config_intr_coalesc_t) >> 2), 1591f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) { 1592f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 1593f10a77bbSDavid C Somayajulu return (-1); 1594f10a77bbSDavid C Somayajulu } 1595f10a77bbSDavid C Somayajulu intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox; 1596f10a77bbSDavid C Somayajulu 1597f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status); 1598f10a77bbSDavid C Somayajulu 1599f10a77bbSDavid C Somayajulu if (err) { 1600f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 1601f10a77bbSDavid C Somayajulu return (-1); 1602f10a77bbSDavid C Somayajulu } 1603f10a77bbSDavid C Somayajulu 1604f10a77bbSDavid C Somayajulu return 0; 1605f10a77bbSDavid C Somayajulu } 1606f10a77bbSDavid C Somayajulu 1607f10a77bbSDavid C Somayajulu 1608f10a77bbSDavid C Somayajulu /* 1609f10a77bbSDavid C Somayajulu * Name: qla_config_mac_addr 1610f10a77bbSDavid C Somayajulu * Function: binds a MAC address to the context/interface. 1611f10a77bbSDavid C Somayajulu * Can be unicast, multicast or broadcast. 1612f10a77bbSDavid C Somayajulu */ 1613f10a77bbSDavid C Somayajulu static int 1614da834d52SDavid C Somayajulu qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac, 1615da834d52SDavid C Somayajulu uint32_t num_mac) 1616f10a77bbSDavid C Somayajulu { 1617f10a77bbSDavid C Somayajulu q80_config_mac_addr_t *cmac; 1618f10a77bbSDavid C Somayajulu q80_config_mac_addr_rsp_t *cmac_rsp; 1619f10a77bbSDavid C Somayajulu uint32_t err; 1620f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1621da834d52SDavid C Somayajulu int i; 1622da834d52SDavid C Somayajulu uint8_t *mac_cpy = mac_addr; 1623da834d52SDavid C Somayajulu 1624da834d52SDavid C Somayajulu if (num_mac > Q8_MAX_MAC_ADDRS) { 1625da834d52SDavid C Somayajulu device_printf(dev, "%s: %s num_mac [0x%x] > Q8_MAX_MAC_ADDRS\n", 1626da834d52SDavid C Somayajulu __func__, (add_mac ? "Add" : "Del"), num_mac); 1627da834d52SDavid C Somayajulu return (-1); 1628da834d52SDavid C Somayajulu } 1629f10a77bbSDavid C Somayajulu 1630f10a77bbSDavid C Somayajulu cmac = (q80_config_mac_addr_t *)ha->hw.mbox; 1631f10a77bbSDavid C Somayajulu bzero(cmac, (sizeof (q80_config_mac_addr_t))); 1632f10a77bbSDavid C Somayajulu 1633f10a77bbSDavid C Somayajulu cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR; 1634f10a77bbSDavid C Somayajulu cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2; 1635f10a77bbSDavid C Somayajulu cmac->count_version |= Q8_MBX_CMD_VERSION; 1636f10a77bbSDavid C Somayajulu 1637f10a77bbSDavid C Somayajulu if (add_mac) 1638f10a77bbSDavid C Somayajulu cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR; 1639f10a77bbSDavid C Somayajulu else 1640f10a77bbSDavid C Somayajulu cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR; 1641f10a77bbSDavid C Somayajulu 1642f10a77bbSDavid C Somayajulu cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS; 1643f10a77bbSDavid C Somayajulu 1644da834d52SDavid C Somayajulu cmac->nmac_entries = num_mac; 1645f10a77bbSDavid C Somayajulu cmac->cntxt_id = ha->hw.rcv_cntxt_id; 1646da834d52SDavid C Somayajulu 1647da834d52SDavid C Somayajulu for (i = 0; i < num_mac; i++) { 1648da834d52SDavid C Somayajulu bcopy(mac_addr, cmac->mac_addr[i].addr, Q8_ETHER_ADDR_LEN); 1649da834d52SDavid C Somayajulu mac_addr = mac_addr + ETHER_ADDR_LEN; 1650da834d52SDavid C Somayajulu } 1651f10a77bbSDavid C Somayajulu 1652f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)cmac, 1653f10a77bbSDavid C Somayajulu (sizeof (q80_config_mac_addr_t) >> 2), 1654f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) { 1655f10a77bbSDavid C Somayajulu device_printf(dev, "%s: %s failed0\n", __func__, 1656f10a77bbSDavid C Somayajulu (add_mac ? "Add" : "Del")); 1657f10a77bbSDavid C Somayajulu return (-1); 1658f10a77bbSDavid C Somayajulu } 1659f10a77bbSDavid C Somayajulu cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox; 1660f10a77bbSDavid C Somayajulu 1661f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status); 1662f10a77bbSDavid C Somayajulu 1663f10a77bbSDavid C Somayajulu if (err) { 1664da834d52SDavid C Somayajulu device_printf(dev, "%s: %s failed1 [0x%08x]\n", __func__, 1665da834d52SDavid C Somayajulu (add_mac ? "Add" : "Del"), err); 1666da834d52SDavid C Somayajulu for (i = 0; i < num_mac; i++) { 1667da834d52SDavid C Somayajulu device_printf(dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n", 1668da834d52SDavid C Somayajulu __func__, mac_cpy[0], mac_cpy[1], mac_cpy[2], 1669da834d52SDavid C Somayajulu mac_cpy[3], mac_cpy[4], mac_cpy[5]); 1670da834d52SDavid C Somayajulu mac_cpy += ETHER_ADDR_LEN; 1671da834d52SDavid C Somayajulu } 1672f10a77bbSDavid C Somayajulu return (-1); 1673f10a77bbSDavid C Somayajulu } 1674f10a77bbSDavid C Somayajulu 1675f10a77bbSDavid C Somayajulu return 0; 1676f10a77bbSDavid C Somayajulu } 1677f10a77bbSDavid C Somayajulu 1678f10a77bbSDavid C Somayajulu 1679f10a77bbSDavid C Somayajulu /* 1680f10a77bbSDavid C Somayajulu * Name: qla_set_mac_rcv_mode 16816a62bec0SDavid C Somayajulu * Function: Enable/Disable AllMulticast and Promiscous Modes. 1682f10a77bbSDavid C Somayajulu */ 1683f10a77bbSDavid C Somayajulu static int 1684f10a77bbSDavid C Somayajulu qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode) 1685f10a77bbSDavid C Somayajulu { 1686f10a77bbSDavid C Somayajulu q80_config_mac_rcv_mode_t *rcv_mode; 1687f10a77bbSDavid C Somayajulu uint32_t err; 1688f10a77bbSDavid C Somayajulu q80_config_mac_rcv_mode_rsp_t *rcv_mode_rsp; 1689f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1690f10a77bbSDavid C Somayajulu 1691f10a77bbSDavid C Somayajulu rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox; 1692f10a77bbSDavid C Somayajulu bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t))); 1693f10a77bbSDavid C Somayajulu 1694f10a77bbSDavid C Somayajulu rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE; 1695f10a77bbSDavid C Somayajulu rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2; 1696f10a77bbSDavid C Somayajulu rcv_mode->count_version |= Q8_MBX_CMD_VERSION; 1697f10a77bbSDavid C Somayajulu 1698f10a77bbSDavid C Somayajulu rcv_mode->mode = mode; 1699f10a77bbSDavid C Somayajulu 1700f10a77bbSDavid C Somayajulu rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id; 1701f10a77bbSDavid C Somayajulu 1702f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode, 1703f10a77bbSDavid C Somayajulu (sizeof (q80_config_mac_rcv_mode_t) >> 2), 1704f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) { 1705f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 1706f10a77bbSDavid C Somayajulu return (-1); 1707f10a77bbSDavid C Somayajulu } 1708f10a77bbSDavid C Somayajulu rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox; 1709f10a77bbSDavid C Somayajulu 1710f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status); 1711f10a77bbSDavid C Somayajulu 1712f10a77bbSDavid C Somayajulu if (err) { 1713f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 1714f10a77bbSDavid C Somayajulu return (-1); 1715f10a77bbSDavid C Somayajulu } 1716f10a77bbSDavid C Somayajulu 1717f10a77bbSDavid C Somayajulu return 0; 1718f10a77bbSDavid C Somayajulu } 1719f10a77bbSDavid C Somayajulu 1720f10a77bbSDavid C Somayajulu int 1721f10a77bbSDavid C Somayajulu ql_set_promisc(qla_host_t *ha) 1722f10a77bbSDavid C Somayajulu { 1723f10a77bbSDavid C Somayajulu int ret; 1724f10a77bbSDavid C Somayajulu 1725f10a77bbSDavid C Somayajulu ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE; 1726f10a77bbSDavid C Somayajulu ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 1727f10a77bbSDavid C Somayajulu return (ret); 1728f10a77bbSDavid C Somayajulu } 1729f10a77bbSDavid C Somayajulu 173035291c22SDavid C Somayajulu void 173135291c22SDavid C Somayajulu qla_reset_promisc(qla_host_t *ha) 173235291c22SDavid C Somayajulu { 173335291c22SDavid C Somayajulu ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE; 173435291c22SDavid C Somayajulu (void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 173535291c22SDavid C Somayajulu } 173635291c22SDavid C Somayajulu 1737f10a77bbSDavid C Somayajulu int 1738f10a77bbSDavid C Somayajulu ql_set_allmulti(qla_host_t *ha) 1739f10a77bbSDavid C Somayajulu { 1740f10a77bbSDavid C Somayajulu int ret; 1741f10a77bbSDavid C Somayajulu 1742f10a77bbSDavid C Somayajulu ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE; 1743f10a77bbSDavid C Somayajulu ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 1744f10a77bbSDavid C Somayajulu return (ret); 1745f10a77bbSDavid C Somayajulu } 1746f10a77bbSDavid C Somayajulu 174735291c22SDavid C Somayajulu void 174835291c22SDavid C Somayajulu qla_reset_allmulti(qla_host_t *ha) 174935291c22SDavid C Somayajulu { 175035291c22SDavid C Somayajulu ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE; 175135291c22SDavid C Somayajulu (void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 175235291c22SDavid C Somayajulu } 1753f10a77bbSDavid C Somayajulu 1754f10a77bbSDavid C Somayajulu /* 1755f10a77bbSDavid C Somayajulu * Name: ql_set_max_mtu 1756f10a77bbSDavid C Somayajulu * Function: 1757f10a77bbSDavid C Somayajulu * Sets the maximum transfer unit size for the specified rcv context. 1758f10a77bbSDavid C Somayajulu */ 1759f10a77bbSDavid C Somayajulu int 1760f10a77bbSDavid C Somayajulu ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id) 1761f10a77bbSDavid C Somayajulu { 1762f10a77bbSDavid C Somayajulu device_t dev; 1763f10a77bbSDavid C Somayajulu q80_set_max_mtu_t *max_mtu; 1764f10a77bbSDavid C Somayajulu q80_set_max_mtu_rsp_t *max_mtu_rsp; 1765f10a77bbSDavid C Somayajulu uint32_t err; 1766f10a77bbSDavid C Somayajulu 1767f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1768f10a77bbSDavid C Somayajulu 1769f10a77bbSDavid C Somayajulu max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox; 1770f10a77bbSDavid C Somayajulu bzero(max_mtu, (sizeof (q80_set_max_mtu_t))); 1771f10a77bbSDavid C Somayajulu 1772f10a77bbSDavid C Somayajulu max_mtu->opcode = Q8_MBX_SET_MAX_MTU; 1773f10a77bbSDavid C Somayajulu max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2); 1774f10a77bbSDavid C Somayajulu max_mtu->count_version |= Q8_MBX_CMD_VERSION; 1775f10a77bbSDavid C Somayajulu 1776f10a77bbSDavid C Somayajulu max_mtu->cntxt_id = cntxt_id; 1777f10a77bbSDavid C Somayajulu max_mtu->mtu = mtu; 1778f10a77bbSDavid C Somayajulu 1779f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)max_mtu, 1780f10a77bbSDavid C Somayajulu (sizeof (q80_set_max_mtu_t) >> 2), 1781f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) { 1782f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 1783f10a77bbSDavid C Somayajulu return -1; 1784f10a77bbSDavid C Somayajulu } 1785f10a77bbSDavid C Somayajulu 1786f10a77bbSDavid C Somayajulu max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox; 1787f10a77bbSDavid C Somayajulu 1788f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status); 1789f10a77bbSDavid C Somayajulu 1790f10a77bbSDavid C Somayajulu if (err) { 1791f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 1792f10a77bbSDavid C Somayajulu } 1793f10a77bbSDavid C Somayajulu 1794f10a77bbSDavid C Somayajulu return 0; 1795f10a77bbSDavid C Somayajulu } 1796f10a77bbSDavid C Somayajulu 1797f10a77bbSDavid C Somayajulu static int 1798f10a77bbSDavid C Somayajulu qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id) 1799f10a77bbSDavid C Somayajulu { 1800f10a77bbSDavid C Somayajulu device_t dev; 1801f10a77bbSDavid C Somayajulu q80_link_event_t *lnk; 1802f10a77bbSDavid C Somayajulu q80_link_event_rsp_t *lnk_rsp; 1803f10a77bbSDavid C Somayajulu uint32_t err; 1804f10a77bbSDavid C Somayajulu 1805f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1806f10a77bbSDavid C Somayajulu 1807f10a77bbSDavid C Somayajulu lnk = (q80_link_event_t *)ha->hw.mbox; 1808f10a77bbSDavid C Somayajulu bzero(lnk, (sizeof (q80_link_event_t))); 1809f10a77bbSDavid C Somayajulu 1810f10a77bbSDavid C Somayajulu lnk->opcode = Q8_MBX_LINK_EVENT_REQ; 1811f10a77bbSDavid C Somayajulu lnk->count_version = (sizeof (q80_link_event_t) >> 2); 1812f10a77bbSDavid C Somayajulu lnk->count_version |= Q8_MBX_CMD_VERSION; 1813f10a77bbSDavid C Somayajulu 1814f10a77bbSDavid C Somayajulu lnk->cntxt_id = cntxt_id; 1815f10a77bbSDavid C Somayajulu lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC; 1816f10a77bbSDavid C Somayajulu 1817f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2), 1818f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) { 1819f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 1820f10a77bbSDavid C Somayajulu return -1; 1821f10a77bbSDavid C Somayajulu } 1822f10a77bbSDavid C Somayajulu 1823f10a77bbSDavid C Somayajulu lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox; 1824f10a77bbSDavid C Somayajulu 1825f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status); 1826f10a77bbSDavid C Somayajulu 1827f10a77bbSDavid C Somayajulu if (err) { 1828f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 1829f10a77bbSDavid C Somayajulu } 1830f10a77bbSDavid C Somayajulu 1831f10a77bbSDavid C Somayajulu return 0; 1832f10a77bbSDavid C Somayajulu } 1833f10a77bbSDavid C Somayajulu 1834f10a77bbSDavid C Somayajulu static int 1835f10a77bbSDavid C Somayajulu qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id) 1836f10a77bbSDavid C Somayajulu { 1837f10a77bbSDavid C Somayajulu device_t dev; 1838f10a77bbSDavid C Somayajulu q80_config_fw_lro_t *fw_lro; 1839f10a77bbSDavid C Somayajulu q80_config_fw_lro_rsp_t *fw_lro_rsp; 1840f10a77bbSDavid C Somayajulu uint32_t err; 1841f10a77bbSDavid C Somayajulu 1842f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1843f10a77bbSDavid C Somayajulu 1844f10a77bbSDavid C Somayajulu fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox; 1845f10a77bbSDavid C Somayajulu bzero(fw_lro, sizeof(q80_config_fw_lro_t)); 1846f10a77bbSDavid C Somayajulu 1847f10a77bbSDavid C Somayajulu fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO; 1848f10a77bbSDavid C Somayajulu fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2); 1849f10a77bbSDavid C Somayajulu fw_lro->count_version |= Q8_MBX_CMD_VERSION; 1850f10a77bbSDavid C Somayajulu 1851f10a77bbSDavid C Somayajulu fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK; 185235291c22SDavid C Somayajulu fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK; 1853f10a77bbSDavid C Somayajulu 1854f10a77bbSDavid C Somayajulu fw_lro->cntxt_id = cntxt_id; 1855f10a77bbSDavid C Somayajulu 1856f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)fw_lro, 1857f10a77bbSDavid C Somayajulu (sizeof (q80_config_fw_lro_t) >> 2), 1858f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) { 1859f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 1860f10a77bbSDavid C Somayajulu return -1; 1861f10a77bbSDavid C Somayajulu } 1862f10a77bbSDavid C Somayajulu 1863f10a77bbSDavid C Somayajulu fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox; 1864f10a77bbSDavid C Somayajulu 1865f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status); 1866f10a77bbSDavid C Somayajulu 1867f10a77bbSDavid C Somayajulu if (err) { 1868f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 1869f10a77bbSDavid C Somayajulu } 1870f10a77bbSDavid C Somayajulu 1871f10a77bbSDavid C Somayajulu return 0; 1872f10a77bbSDavid C Somayajulu } 1873f10a77bbSDavid C Somayajulu 187400caeec7SDavid C Somayajulu static int 187500caeec7SDavid C Somayajulu qla_set_cam_search_mode(qla_host_t *ha, uint32_t search_mode) 187600caeec7SDavid C Somayajulu { 187700caeec7SDavid C Somayajulu device_t dev; 187800caeec7SDavid C Somayajulu q80_hw_config_t *hw_config; 187900caeec7SDavid C Somayajulu q80_hw_config_rsp_t *hw_config_rsp; 188000caeec7SDavid C Somayajulu uint32_t err; 188100caeec7SDavid C Somayajulu 188200caeec7SDavid C Somayajulu dev = ha->pci_dev; 188300caeec7SDavid C Somayajulu 188400caeec7SDavid C Somayajulu hw_config = (q80_hw_config_t *)ha->hw.mbox; 188500caeec7SDavid C Somayajulu bzero(hw_config, sizeof (q80_hw_config_t)); 188600caeec7SDavid C Somayajulu 188700caeec7SDavid C Somayajulu hw_config->opcode = Q8_MBX_HW_CONFIG; 188800caeec7SDavid C Somayajulu hw_config->count_version = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE_COUNT; 188900caeec7SDavid C Somayajulu hw_config->count_version |= Q8_MBX_CMD_VERSION; 189000caeec7SDavid C Somayajulu 189100caeec7SDavid C Somayajulu hw_config->cmd = Q8_HW_CONFIG_SET_CAM_SEARCH_MODE; 189200caeec7SDavid C Somayajulu 189300caeec7SDavid C Somayajulu hw_config->u.set_cam_search_mode.mode = search_mode; 189400caeec7SDavid C Somayajulu 189500caeec7SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)hw_config, 189600caeec7SDavid C Somayajulu (sizeof (q80_hw_config_t) >> 2), 189700caeec7SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) { 189800caeec7SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 189900caeec7SDavid C Somayajulu return -1; 190000caeec7SDavid C Somayajulu } 190100caeec7SDavid C Somayajulu hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox; 190200caeec7SDavid C Somayajulu 190300caeec7SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status); 190400caeec7SDavid C Somayajulu 190500caeec7SDavid C Somayajulu if (err) { 190600caeec7SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 190700caeec7SDavid C Somayajulu } 190800caeec7SDavid C Somayajulu 190900caeec7SDavid C Somayajulu return 0; 191000caeec7SDavid C Somayajulu } 191100caeec7SDavid C Somayajulu 191200caeec7SDavid C Somayajulu static int 191300caeec7SDavid C Somayajulu qla_get_cam_search_mode(qla_host_t *ha) 191400caeec7SDavid C Somayajulu { 191500caeec7SDavid C Somayajulu device_t dev; 191600caeec7SDavid C Somayajulu q80_hw_config_t *hw_config; 191700caeec7SDavid C Somayajulu q80_hw_config_rsp_t *hw_config_rsp; 191800caeec7SDavid C Somayajulu uint32_t err; 191900caeec7SDavid C Somayajulu 192000caeec7SDavid C Somayajulu dev = ha->pci_dev; 192100caeec7SDavid C Somayajulu 192200caeec7SDavid C Somayajulu hw_config = (q80_hw_config_t *)ha->hw.mbox; 192300caeec7SDavid C Somayajulu bzero(hw_config, sizeof (q80_hw_config_t)); 192400caeec7SDavid C Somayajulu 192500caeec7SDavid C Somayajulu hw_config->opcode = Q8_MBX_HW_CONFIG; 192600caeec7SDavid C Somayajulu hw_config->count_version = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE_COUNT; 192700caeec7SDavid C Somayajulu hw_config->count_version |= Q8_MBX_CMD_VERSION; 192800caeec7SDavid C Somayajulu 192900caeec7SDavid C Somayajulu hw_config->cmd = Q8_HW_CONFIG_GET_CAM_SEARCH_MODE; 193000caeec7SDavid C Somayajulu 193100caeec7SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)hw_config, 193200caeec7SDavid C Somayajulu (sizeof (q80_hw_config_t) >> 2), 193300caeec7SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_hw_config_rsp_t) >> 2), 0)) { 193400caeec7SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 193500caeec7SDavid C Somayajulu return -1; 193600caeec7SDavid C Somayajulu } 193700caeec7SDavid C Somayajulu hw_config_rsp = (q80_hw_config_rsp_t *)ha->hw.mbox; 193800caeec7SDavid C Somayajulu 193900caeec7SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(hw_config_rsp->regcnt_status); 194000caeec7SDavid C Somayajulu 194100caeec7SDavid C Somayajulu if (err) { 194200caeec7SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 194300caeec7SDavid C Somayajulu } else { 194400caeec7SDavid C Somayajulu device_printf(dev, "%s: cam search mode [0x%08x]\n", __func__, 194500caeec7SDavid C Somayajulu hw_config_rsp->u.get_cam_search_mode.mode); 194600caeec7SDavid C Somayajulu } 194700caeec7SDavid C Somayajulu 194800caeec7SDavid C Somayajulu return 0; 194900caeec7SDavid C Somayajulu } 195000caeec7SDavid C Somayajulu 1951f10a77bbSDavid C Somayajulu static int 195235291c22SDavid C Somayajulu qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size) 1953f10a77bbSDavid C Somayajulu { 1954f10a77bbSDavid C Somayajulu device_t dev; 1955f10a77bbSDavid C Somayajulu q80_get_stats_t *stat; 1956f10a77bbSDavid C Somayajulu q80_get_stats_rsp_t *stat_rsp; 1957f10a77bbSDavid C Somayajulu uint32_t err; 1958f10a77bbSDavid C Somayajulu 1959f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1960f10a77bbSDavid C Somayajulu 1961f10a77bbSDavid C Somayajulu stat = (q80_get_stats_t *)ha->hw.mbox; 1962f10a77bbSDavid C Somayajulu bzero(stat, (sizeof (q80_get_stats_t))); 1963f10a77bbSDavid C Somayajulu 1964f10a77bbSDavid C Somayajulu stat->opcode = Q8_MBX_GET_STATS; 1965f10a77bbSDavid C Somayajulu stat->count_version = 2; 1966f10a77bbSDavid C Somayajulu stat->count_version |= Q8_MBX_CMD_VERSION; 1967f10a77bbSDavid C Somayajulu 1968f10a77bbSDavid C Somayajulu stat->cmd = cmd; 1969f10a77bbSDavid C Somayajulu 1970f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)stat, 2, 197135291c22SDavid C Somayajulu ha->hw.mbox, (rsp_size >> 2), 0)) { 1972f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 1973f10a77bbSDavid C Somayajulu return -1; 1974f10a77bbSDavid C Somayajulu } 1975f10a77bbSDavid C Somayajulu 1976f10a77bbSDavid C Somayajulu stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox; 1977f10a77bbSDavid C Somayajulu 1978f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status); 1979f10a77bbSDavid C Somayajulu 1980f10a77bbSDavid C Somayajulu if (err) { 1981f10a77bbSDavid C Somayajulu return -1; 1982f10a77bbSDavid C Somayajulu } 1983f10a77bbSDavid C Somayajulu 1984f10a77bbSDavid C Somayajulu return 0; 1985f10a77bbSDavid C Somayajulu } 1986f10a77bbSDavid C Somayajulu 1987f10a77bbSDavid C Somayajulu void 1988f10a77bbSDavid C Somayajulu ql_get_stats(qla_host_t *ha) 1989f10a77bbSDavid C Somayajulu { 1990f10a77bbSDavid C Somayajulu q80_get_stats_rsp_t *stat_rsp; 1991f10a77bbSDavid C Somayajulu q80_mac_stats_t *mstat; 1992f10a77bbSDavid C Somayajulu q80_xmt_stats_t *xstat; 1993f10a77bbSDavid C Somayajulu q80_rcv_stats_t *rstat; 1994f10a77bbSDavid C Somayajulu uint32_t cmd; 199535291c22SDavid C Somayajulu int i; 19967fb51846SDavid C Somayajulu struct ifnet *ifp = ha->ifp; 19977fb51846SDavid C Somayajulu 19987fb51846SDavid C Somayajulu if (ifp == NULL) 19997fb51846SDavid C Somayajulu return; 20007fb51846SDavid C Somayajulu 20017fb51846SDavid C Somayajulu if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) != 0) { 20027fb51846SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", __func__); 20037fb51846SDavid C Somayajulu return; 20047fb51846SDavid C Somayajulu } 20057fb51846SDavid C Somayajulu 20067fb51846SDavid C Somayajulu if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 20077fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__); 20087fb51846SDavid C Somayajulu return; 20097fb51846SDavid C Somayajulu } 2010f10a77bbSDavid C Somayajulu 2011f10a77bbSDavid C Somayajulu stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox; 2012f10a77bbSDavid C Somayajulu /* 2013f10a77bbSDavid C Somayajulu * Get MAC Statistics 2014f10a77bbSDavid C Somayajulu */ 2015f10a77bbSDavid C Somayajulu cmd = Q8_GET_STATS_CMD_TYPE_MAC; 201635291c22SDavid C Somayajulu // cmd |= Q8_GET_STATS_CMD_CLEAR; 2017f10a77bbSDavid C Somayajulu 2018f10a77bbSDavid C Somayajulu cmd |= ((ha->pci_func & 0x1) << 16); 2019f10a77bbSDavid C Somayajulu 20207fb51846SDavid C Somayajulu if (ha->qla_watchdog_pause) 20217fb51846SDavid C Somayajulu goto ql_get_stats_exit; 20227fb51846SDavid C Somayajulu 202335291c22SDavid C Somayajulu if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) { 2024f10a77bbSDavid C Somayajulu mstat = (q80_mac_stats_t *)&stat_rsp->u.mac; 20257fb51846SDavid C Somayajulu bcopy(mstat, &ha->hw.mac, sizeof(q80_mac_stats_t)); 2026f10a77bbSDavid C Somayajulu } else { 2027f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n", 2028f10a77bbSDavid C Somayajulu __func__, ha->hw.mbox[0]); 2029f10a77bbSDavid C Somayajulu } 2030f10a77bbSDavid C Somayajulu /* 2031f10a77bbSDavid C Somayajulu * Get RCV Statistics 2032f10a77bbSDavid C Somayajulu */ 2033f10a77bbSDavid C Somayajulu cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT; 203435291c22SDavid C Somayajulu // cmd |= Q8_GET_STATS_CMD_CLEAR; 2035f10a77bbSDavid C Somayajulu cmd |= (ha->hw.rcv_cntxt_id << 16); 2036f10a77bbSDavid C Somayajulu 20377fb51846SDavid C Somayajulu if (ha->qla_watchdog_pause) 20387fb51846SDavid C Somayajulu goto ql_get_stats_exit; 20397fb51846SDavid C Somayajulu 204035291c22SDavid C Somayajulu if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) { 2041f10a77bbSDavid C Somayajulu rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv; 20427fb51846SDavid C Somayajulu bcopy(rstat, &ha->hw.rcv, sizeof(q80_rcv_stats_t)); 2043f10a77bbSDavid C Somayajulu } else { 2044f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n", 2045f10a77bbSDavid C Somayajulu __func__, ha->hw.mbox[0]); 2046f10a77bbSDavid C Somayajulu } 20477fb51846SDavid C Somayajulu 20487fb51846SDavid C Somayajulu if (ha->qla_watchdog_pause) 20497fb51846SDavid C Somayajulu goto ql_get_stats_exit; 2050f10a77bbSDavid C Somayajulu /* 2051f10a77bbSDavid C Somayajulu * Get XMT Statistics 2052f10a77bbSDavid C Somayajulu */ 20537fb51846SDavid C Somayajulu for (i = 0 ; ((i < ha->hw.num_tx_rings) && (!ha->qla_watchdog_pause)); 20547fb51846SDavid C Somayajulu i++) { 2055f10a77bbSDavid C Somayajulu cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT; 205635291c22SDavid C Somayajulu // cmd |= Q8_GET_STATS_CMD_CLEAR; 205735291c22SDavid C Somayajulu cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16); 2058f10a77bbSDavid C Somayajulu 205935291c22SDavid C Somayajulu if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t)) 206035291c22SDavid C Somayajulu == 0) { 2061f10a77bbSDavid C Somayajulu xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt; 20627fb51846SDavid C Somayajulu bcopy(xstat, &ha->hw.xmt[i], sizeof(q80_xmt_stats_t)); 2063f10a77bbSDavid C Somayajulu } else { 2064f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n", 2065f10a77bbSDavid C Somayajulu __func__, ha->hw.mbox[0]); 2066f10a77bbSDavid C Somayajulu } 2067f10a77bbSDavid C Somayajulu } 206835291c22SDavid C Somayajulu 20697fb51846SDavid C Somayajulu ql_get_stats_exit: 20707fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__); 207135291c22SDavid C Somayajulu 207235291c22SDavid C Somayajulu return; 207335291c22SDavid C Somayajulu } 2074f10a77bbSDavid C Somayajulu 2075f10a77bbSDavid C Somayajulu /* 2076f10a77bbSDavid C Somayajulu * Name: qla_tx_tso 2077f10a77bbSDavid C Somayajulu * Function: Checks if the packet to be transmitted is a candidate for 2078f10a77bbSDavid C Somayajulu * Large TCP Segment Offload. If yes, the appropriate fields in the Tx 2079f10a77bbSDavid C Somayajulu * Ring Structure are plugged in. 2080f10a77bbSDavid C Somayajulu */ 2081f10a77bbSDavid C Somayajulu static int 2082f10a77bbSDavid C Somayajulu qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr) 2083f10a77bbSDavid C Somayajulu { 2084f10a77bbSDavid C Somayajulu struct ether_vlan_header *eh; 2085f10a77bbSDavid C Somayajulu struct ip *ip = NULL; 2086f10a77bbSDavid C Somayajulu struct ip6_hdr *ip6 = NULL; 2087f10a77bbSDavid C Somayajulu struct tcphdr *th = NULL; 2088f10a77bbSDavid C Somayajulu uint32_t ehdrlen, hdrlen, ip_hlen, tcp_hlen, tcp_opt_off; 2089f10a77bbSDavid C Somayajulu uint16_t etype, opcode, offload = 1; 2090f10a77bbSDavid C Somayajulu device_t dev; 2091f10a77bbSDavid C Somayajulu 2092f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 2093f10a77bbSDavid C Somayajulu 2094f10a77bbSDavid C Somayajulu 2095f10a77bbSDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *); 2096f10a77bbSDavid C Somayajulu 2097f10a77bbSDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 2098f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 2099f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_proto); 2100f10a77bbSDavid C Somayajulu } else { 2101f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN; 2102f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_encap_proto); 2103f10a77bbSDavid C Somayajulu } 2104f10a77bbSDavid C Somayajulu 2105f10a77bbSDavid C Somayajulu hdrlen = 0; 2106f10a77bbSDavid C Somayajulu 2107f10a77bbSDavid C Somayajulu switch (etype) { 2108f10a77bbSDavid C Somayajulu case ETHERTYPE_IP: 2109f10a77bbSDavid C Somayajulu 2110f10a77bbSDavid C Somayajulu tcp_opt_off = ehdrlen + sizeof(struct ip) + 2111f10a77bbSDavid C Somayajulu sizeof(struct tcphdr); 2112f10a77bbSDavid C Somayajulu 2113f10a77bbSDavid C Somayajulu if (mp->m_len < tcp_opt_off) { 2114f10a77bbSDavid C Somayajulu m_copydata(mp, 0, tcp_opt_off, hdr); 2115f10a77bbSDavid C Somayajulu ip = (struct ip *)(hdr + ehdrlen); 2116f10a77bbSDavid C Somayajulu } else { 2117f10a77bbSDavid C Somayajulu ip = (struct ip *)(mp->m_data + ehdrlen); 2118f10a77bbSDavid C Somayajulu } 2119f10a77bbSDavid C Somayajulu 2120f10a77bbSDavid C Somayajulu ip_hlen = ip->ip_hl << 2; 2121f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_LSO; 2122f10a77bbSDavid C Somayajulu 2123f10a77bbSDavid C Somayajulu 2124f10a77bbSDavid C Somayajulu if ((ip->ip_p != IPPROTO_TCP) || 2125f10a77bbSDavid C Somayajulu (ip_hlen != sizeof (struct ip))){ 2126f10a77bbSDavid C Somayajulu /* IP Options are not supported */ 2127f10a77bbSDavid C Somayajulu 2128f10a77bbSDavid C Somayajulu offload = 0; 2129f10a77bbSDavid C Somayajulu } else 2130f10a77bbSDavid C Somayajulu th = (struct tcphdr *)((caddr_t)ip + ip_hlen); 2131f10a77bbSDavid C Somayajulu 2132f10a77bbSDavid C Somayajulu break; 2133f10a77bbSDavid C Somayajulu 2134f10a77bbSDavid C Somayajulu case ETHERTYPE_IPV6: 2135f10a77bbSDavid C Somayajulu 2136f10a77bbSDavid C Somayajulu tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) + 2137f10a77bbSDavid C Somayajulu sizeof (struct tcphdr); 2138f10a77bbSDavid C Somayajulu 2139f10a77bbSDavid C Somayajulu if (mp->m_len < tcp_opt_off) { 2140f10a77bbSDavid C Somayajulu m_copydata(mp, 0, tcp_opt_off, hdr); 2141f10a77bbSDavid C Somayajulu ip6 = (struct ip6_hdr *)(hdr + ehdrlen); 2142f10a77bbSDavid C Somayajulu } else { 2143f10a77bbSDavid C Somayajulu ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); 2144f10a77bbSDavid C Somayajulu } 2145f10a77bbSDavid C Somayajulu 2146f10a77bbSDavid C Somayajulu ip_hlen = sizeof(struct ip6_hdr); 2147f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6; 2148f10a77bbSDavid C Somayajulu 2149f10a77bbSDavid C Somayajulu if (ip6->ip6_nxt != IPPROTO_TCP) { 2150f10a77bbSDavid C Somayajulu //device_printf(dev, "%s: ipv6\n", __func__); 2151f10a77bbSDavid C Somayajulu offload = 0; 2152f10a77bbSDavid C Somayajulu } else 2153f10a77bbSDavid C Somayajulu th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen); 2154f10a77bbSDavid C Somayajulu break; 2155f10a77bbSDavid C Somayajulu 2156f10a77bbSDavid C Somayajulu default: 2157f10a77bbSDavid C Somayajulu QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__)); 2158f10a77bbSDavid C Somayajulu offload = 0; 2159f10a77bbSDavid C Somayajulu break; 2160f10a77bbSDavid C Somayajulu } 2161f10a77bbSDavid C Somayajulu 2162f10a77bbSDavid C Somayajulu if (!offload) 2163f10a77bbSDavid C Somayajulu return (-1); 2164f10a77bbSDavid C Somayajulu 2165f10a77bbSDavid C Somayajulu tcp_hlen = th->th_off << 2; 2166f10a77bbSDavid C Somayajulu hdrlen = ehdrlen + ip_hlen + tcp_hlen; 2167f10a77bbSDavid C Somayajulu 2168f10a77bbSDavid C Somayajulu if (mp->m_len < hdrlen) { 2169f10a77bbSDavid C Somayajulu if (mp->m_len < tcp_opt_off) { 2170f10a77bbSDavid C Somayajulu if (tcp_hlen > sizeof(struct tcphdr)) { 2171f10a77bbSDavid C Somayajulu m_copydata(mp, tcp_opt_off, 2172f10a77bbSDavid C Somayajulu (tcp_hlen - sizeof(struct tcphdr)), 2173f10a77bbSDavid C Somayajulu &hdr[tcp_opt_off]); 2174f10a77bbSDavid C Somayajulu } 2175f10a77bbSDavid C Somayajulu } else { 2176f10a77bbSDavid C Somayajulu m_copydata(mp, 0, hdrlen, hdr); 2177f10a77bbSDavid C Somayajulu } 2178f10a77bbSDavid C Somayajulu } 2179f10a77bbSDavid C Somayajulu 2180f10a77bbSDavid C Somayajulu tx_cmd->mss = mp->m_pkthdr.tso_segsz; 2181f10a77bbSDavid C Somayajulu 2182f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode = opcode ; 2183f10a77bbSDavid C Somayajulu tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen; 2184f10a77bbSDavid C Somayajulu tx_cmd->total_hdr_len = hdrlen; 2185f10a77bbSDavid C Somayajulu 2186f10a77bbSDavid C Somayajulu /* Check for Multicast least significant bit of MSB == 1 */ 2187f10a77bbSDavid C Somayajulu if (eh->evl_dhost[0] & 0x01) { 2188f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST; 2189f10a77bbSDavid C Somayajulu } 2190f10a77bbSDavid C Somayajulu 2191f10a77bbSDavid C Somayajulu if (mp->m_len < hdrlen) { 2192f10a77bbSDavid C Somayajulu printf("%d\n", hdrlen); 2193f10a77bbSDavid C Somayajulu return (1); 2194f10a77bbSDavid C Somayajulu } 2195f10a77bbSDavid C Somayajulu 2196f10a77bbSDavid C Somayajulu return (0); 2197f10a77bbSDavid C Somayajulu } 2198f10a77bbSDavid C Somayajulu 2199f10a77bbSDavid C Somayajulu /* 2200f10a77bbSDavid C Somayajulu * Name: qla_tx_chksum 2201f10a77bbSDavid C Somayajulu * Function: Checks if the packet to be transmitted is a candidate for 2202f10a77bbSDavid C Somayajulu * TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx 2203f10a77bbSDavid C Somayajulu * Ring Structure are plugged in. 2204f10a77bbSDavid C Somayajulu */ 2205f10a77bbSDavid C Somayajulu static int 2206f10a77bbSDavid C Somayajulu qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code, 2207f10a77bbSDavid C Somayajulu uint32_t *tcp_hdr_off) 2208f10a77bbSDavid C Somayajulu { 2209f10a77bbSDavid C Somayajulu struct ether_vlan_header *eh; 2210f10a77bbSDavid C Somayajulu struct ip *ip; 2211f10a77bbSDavid C Somayajulu struct ip6_hdr *ip6; 2212f10a77bbSDavid C Somayajulu uint32_t ehdrlen, ip_hlen; 2213f10a77bbSDavid C Somayajulu uint16_t etype, opcode, offload = 1; 2214f10a77bbSDavid C Somayajulu device_t dev; 2215f10a77bbSDavid C Somayajulu uint8_t buf[sizeof(struct ip6_hdr)]; 2216f10a77bbSDavid C Somayajulu 2217f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 2218f10a77bbSDavid C Somayajulu 2219f10a77bbSDavid C Somayajulu *op_code = 0; 2220f10a77bbSDavid C Somayajulu 22217fb51846SDavid C Somayajulu if ((mp->m_pkthdr.csum_flags & 22227fb51846SDavid C Somayajulu (CSUM_TCP|CSUM_UDP|CSUM_TCP_IPV6 | CSUM_UDP_IPV6)) == 0) 2223f10a77bbSDavid C Somayajulu return (-1); 2224f10a77bbSDavid C Somayajulu 2225f10a77bbSDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *); 2226f10a77bbSDavid C Somayajulu 2227f10a77bbSDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 2228f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 2229f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_proto); 2230f10a77bbSDavid C Somayajulu } else { 2231f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN; 2232f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_encap_proto); 2233f10a77bbSDavid C Somayajulu } 2234f10a77bbSDavid C Somayajulu 2235f10a77bbSDavid C Somayajulu 2236f10a77bbSDavid C Somayajulu switch (etype) { 2237f10a77bbSDavid C Somayajulu case ETHERTYPE_IP: 2238f10a77bbSDavid C Somayajulu ip = (struct ip *)(mp->m_data + ehdrlen); 2239f10a77bbSDavid C Somayajulu 2240f10a77bbSDavid C Somayajulu ip_hlen = sizeof (struct ip); 2241f10a77bbSDavid C Somayajulu 2242f10a77bbSDavid C Somayajulu if (mp->m_len < (ehdrlen + ip_hlen)) { 2243f10a77bbSDavid C Somayajulu m_copydata(mp, ehdrlen, sizeof(struct ip), buf); 2244f10a77bbSDavid C Somayajulu ip = (struct ip *)buf; 2245f10a77bbSDavid C Somayajulu } 2246f10a77bbSDavid C Somayajulu 2247f10a77bbSDavid C Somayajulu if (ip->ip_p == IPPROTO_TCP) 2248f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM; 2249f10a77bbSDavid C Somayajulu else if (ip->ip_p == IPPROTO_UDP) 2250f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM; 2251f10a77bbSDavid C Somayajulu else { 2252f10a77bbSDavid C Somayajulu //device_printf(dev, "%s: ipv4\n", __func__); 2253f10a77bbSDavid C Somayajulu offload = 0; 2254f10a77bbSDavid C Somayajulu } 2255f10a77bbSDavid C Somayajulu break; 2256f10a77bbSDavid C Somayajulu 2257f10a77bbSDavid C Somayajulu case ETHERTYPE_IPV6: 2258f10a77bbSDavid C Somayajulu ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); 2259f10a77bbSDavid C Somayajulu 2260f10a77bbSDavid C Somayajulu ip_hlen = sizeof(struct ip6_hdr); 2261f10a77bbSDavid C Somayajulu 2262f10a77bbSDavid C Somayajulu if (mp->m_len < (ehdrlen + ip_hlen)) { 2263f10a77bbSDavid C Somayajulu m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr), 2264f10a77bbSDavid C Somayajulu buf); 2265f10a77bbSDavid C Somayajulu ip6 = (struct ip6_hdr *)buf; 2266f10a77bbSDavid C Somayajulu } 2267f10a77bbSDavid C Somayajulu 2268f10a77bbSDavid C Somayajulu if (ip6->ip6_nxt == IPPROTO_TCP) 2269f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6; 2270f10a77bbSDavid C Somayajulu else if (ip6->ip6_nxt == IPPROTO_UDP) 2271f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6; 2272f10a77bbSDavid C Somayajulu else { 2273f10a77bbSDavid C Somayajulu //device_printf(dev, "%s: ipv6\n", __func__); 2274f10a77bbSDavid C Somayajulu offload = 0; 2275f10a77bbSDavid C Somayajulu } 2276f10a77bbSDavid C Somayajulu break; 2277f10a77bbSDavid C Somayajulu 2278f10a77bbSDavid C Somayajulu default: 2279f10a77bbSDavid C Somayajulu offload = 0; 2280f10a77bbSDavid C Somayajulu break; 2281f10a77bbSDavid C Somayajulu } 2282f10a77bbSDavid C Somayajulu if (!offload) 2283f10a77bbSDavid C Somayajulu return (-1); 2284f10a77bbSDavid C Somayajulu 2285f10a77bbSDavid C Somayajulu *op_code = opcode; 2286f10a77bbSDavid C Somayajulu *tcp_hdr_off = (ip_hlen + ehdrlen); 2287f10a77bbSDavid C Somayajulu 2288f10a77bbSDavid C Somayajulu return (0); 2289f10a77bbSDavid C Somayajulu } 2290f10a77bbSDavid C Somayajulu 2291f10a77bbSDavid C Somayajulu #define QLA_TX_MIN_FREE 2 2292f10a77bbSDavid C Somayajulu /* 2293f10a77bbSDavid C Somayajulu * Name: ql_hw_send 2294f10a77bbSDavid C Somayajulu * Function: Transmits a packet. It first checks if the packet is a 2295f10a77bbSDavid C Somayajulu * candidate for Large TCP Segment Offload and then for UDP/TCP checksum 2296f10a77bbSDavid C Somayajulu * offload. If either of these creteria are not met, it is transmitted 2297f10a77bbSDavid C Somayajulu * as a regular ethernet frame. 2298f10a77bbSDavid C Somayajulu */ 2299f10a77bbSDavid C Somayajulu int 2300f10a77bbSDavid C Somayajulu ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs, 230135291c22SDavid C Somayajulu uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu) 2302f10a77bbSDavid C Somayajulu { 2303f10a77bbSDavid C Somayajulu struct ether_vlan_header *eh; 2304f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 2305f10a77bbSDavid C Somayajulu q80_tx_cmd_t *tx_cmd, tso_cmd; 2306f10a77bbSDavid C Somayajulu bus_dma_segment_t *c_seg; 2307f10a77bbSDavid C Somayajulu uint32_t num_tx_cmds, hdr_len = 0; 2308f10a77bbSDavid C Somayajulu uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next; 2309f10a77bbSDavid C Somayajulu device_t dev; 2310f10a77bbSDavid C Somayajulu int i, ret; 2311f10a77bbSDavid C Somayajulu uint8_t *src = NULL, *dst = NULL; 2312f10a77bbSDavid C Somayajulu uint8_t frame_hdr[QL_FRAME_HDR_SIZE]; 2313f10a77bbSDavid C Somayajulu uint32_t op_code = 0; 2314f10a77bbSDavid C Somayajulu uint32_t tcp_hdr_off = 0; 2315f10a77bbSDavid C Somayajulu 2316f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 2317f10a77bbSDavid C Somayajulu 2318f10a77bbSDavid C Somayajulu /* 2319f10a77bbSDavid C Somayajulu * Always make sure there is atleast one empty slot in the tx_ring 2320f10a77bbSDavid C Somayajulu * tx_ring is considered full when there only one entry available 2321f10a77bbSDavid C Somayajulu */ 2322f10a77bbSDavid C Somayajulu num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2; 2323f10a77bbSDavid C Somayajulu 2324f10a77bbSDavid C Somayajulu total_length = mp->m_pkthdr.len; 2325f10a77bbSDavid C Somayajulu if (total_length > QLA_MAX_TSO_FRAME_SIZE) { 2326f10a77bbSDavid C Somayajulu device_printf(dev, "%s: total length exceeds maxlen(%d)\n", 2327f10a77bbSDavid C Somayajulu __func__, total_length); 2328203f9d18SDavid C Somayajulu return (EINVAL); 2329f10a77bbSDavid C Somayajulu } 2330f10a77bbSDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *); 2331f10a77bbSDavid C Somayajulu 2332f10a77bbSDavid C Somayajulu if (mp->m_pkthdr.csum_flags & CSUM_TSO) { 2333f10a77bbSDavid C Somayajulu 2334f10a77bbSDavid C Somayajulu bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t)); 2335f10a77bbSDavid C Somayajulu 2336f10a77bbSDavid C Somayajulu src = frame_hdr; 2337f10a77bbSDavid C Somayajulu ret = qla_tx_tso(ha, mp, &tso_cmd, src); 2338f10a77bbSDavid C Somayajulu 2339f10a77bbSDavid C Somayajulu if (!(ret & ~1)) { 2340f10a77bbSDavid C Somayajulu /* find the additional tx_cmd descriptors required */ 2341f10a77bbSDavid C Somayajulu 2342f10a77bbSDavid C Somayajulu if (mp->m_flags & M_VLANTAG) 2343f10a77bbSDavid C Somayajulu tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN; 2344f10a77bbSDavid C Somayajulu 2345f10a77bbSDavid C Somayajulu hdr_len = tso_cmd.total_hdr_len; 2346f10a77bbSDavid C Somayajulu 2347f10a77bbSDavid C Somayajulu bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN; 2348f10a77bbSDavid C Somayajulu bytes = QL_MIN(bytes, hdr_len); 2349f10a77bbSDavid C Somayajulu 2350f10a77bbSDavid C Somayajulu num_tx_cmds++; 2351f10a77bbSDavid C Somayajulu hdr_len -= bytes; 2352f10a77bbSDavid C Somayajulu 2353f10a77bbSDavid C Somayajulu while (hdr_len) { 2354f10a77bbSDavid C Somayajulu bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len); 2355f10a77bbSDavid C Somayajulu hdr_len -= bytes; 2356f10a77bbSDavid C Somayajulu num_tx_cmds++; 2357f10a77bbSDavid C Somayajulu } 2358f10a77bbSDavid C Somayajulu hdr_len = tso_cmd.total_hdr_len; 2359f10a77bbSDavid C Somayajulu 2360f10a77bbSDavid C Somayajulu if (ret == 0) 2361f10a77bbSDavid C Somayajulu src = (uint8_t *)eh; 2362f10a77bbSDavid C Somayajulu } else 2363f10a77bbSDavid C Somayajulu return (EINVAL); 2364f10a77bbSDavid C Somayajulu } else { 2365f10a77bbSDavid C Somayajulu (void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off); 2366f10a77bbSDavid C Somayajulu } 2367f10a77bbSDavid C Somayajulu 2368f10a77bbSDavid C Somayajulu if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) { 2369b89f2279SDavid C Somayajulu ql_hw_tx_done_locked(ha, txr_idx); 2370f10a77bbSDavid C Somayajulu if (hw->tx_cntxt[txr_idx].txr_free <= 2371f10a77bbSDavid C Somayajulu (num_tx_cmds + QLA_TX_MIN_FREE)) { 2372f10a77bbSDavid C Somayajulu QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= " 2373f10a77bbSDavid C Somayajulu "(num_tx_cmds + QLA_TX_MIN_FREE))\n", 2374f10a77bbSDavid C Somayajulu __func__)); 2375f10a77bbSDavid C Somayajulu return (-1); 2376f10a77bbSDavid C Somayajulu } 2377f10a77bbSDavid C Somayajulu } 2378f10a77bbSDavid C Somayajulu 2379c6acf96aSDavid C Somayajulu for (i = 0; i < num_tx_cmds; i++) { 2380c6acf96aSDavid C Somayajulu int j; 2381c6acf96aSDavid C Somayajulu 2382c6acf96aSDavid C Somayajulu j = (tx_idx+i) & (NUM_TX_DESCRIPTORS - 1); 2383c6acf96aSDavid C Somayajulu 2384c6acf96aSDavid C Somayajulu if (NULL != ha->tx_ring[txr_idx].tx_buf[j].m_head) { 2385c6acf96aSDavid C Somayajulu QL_ASSERT(ha, 0, \ 2386c6acf96aSDavid C Somayajulu ("%s [%d]: txr_idx = %d tx_idx = %d mbuf = %p\n",\ 2387c6acf96aSDavid C Somayajulu __func__, __LINE__, txr_idx, j,\ 2388c6acf96aSDavid C Somayajulu ha->tx_ring[txr_idx].tx_buf[j].m_head)); 2389c6acf96aSDavid C Somayajulu return (EINVAL); 2390c6acf96aSDavid C Somayajulu } 2391c6acf96aSDavid C Somayajulu } 2392c6acf96aSDavid C Somayajulu 2393f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx]; 2394f10a77bbSDavid C Somayajulu 2395f10a77bbSDavid C Somayajulu if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) { 2396f10a77bbSDavid C Somayajulu 2397f10a77bbSDavid C Somayajulu if (nsegs > ha->hw.max_tx_segs) 2398f10a77bbSDavid C Somayajulu ha->hw.max_tx_segs = nsegs; 2399f10a77bbSDavid C Somayajulu 2400f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 2401f10a77bbSDavid C Somayajulu 2402f10a77bbSDavid C Somayajulu if (op_code) { 2403f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode = op_code; 2404f10a77bbSDavid C Somayajulu tx_cmd->tcp_hdr_off = tcp_hdr_off; 2405f10a77bbSDavid C Somayajulu 2406f10a77bbSDavid C Somayajulu } else { 2407f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER; 2408f10a77bbSDavid C Somayajulu } 2409f10a77bbSDavid C Somayajulu } else { 2410f10a77bbSDavid C Somayajulu bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t)); 2411f10a77bbSDavid C Somayajulu ha->tx_tso_frames++; 2412f10a77bbSDavid C Somayajulu } 2413f10a77bbSDavid C Somayajulu 2414f10a77bbSDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 2415f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED; 241635291c22SDavid C Somayajulu 241735291c22SDavid C Somayajulu if (iscsi_pdu) 241835291c22SDavid C Somayajulu eh->evl_tag |= ha->hw.user_pri_iscsi << 13; 241935291c22SDavid C Somayajulu 2420f10a77bbSDavid C Somayajulu } else if (mp->m_flags & M_VLANTAG) { 2421f10a77bbSDavid C Somayajulu 2422f10a77bbSDavid C Somayajulu if (hdr_len) { /* TSO */ 2423f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED | 2424f10a77bbSDavid C Somayajulu Q8_TX_CMD_FLAGS_HW_VLAN_ID); 2425f10a77bbSDavid C Somayajulu tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN; 2426f10a77bbSDavid C Somayajulu } else 2427f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID; 2428f10a77bbSDavid C Somayajulu 2429f10a77bbSDavid C Somayajulu ha->hw_vlan_tx_frames++; 2430f10a77bbSDavid C Somayajulu tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag; 243135291c22SDavid C Somayajulu 243235291c22SDavid C Somayajulu if (iscsi_pdu) { 243335291c22SDavid C Somayajulu tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13; 243435291c22SDavid C Somayajulu mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci; 243535291c22SDavid C Somayajulu } 2436f10a77bbSDavid C Somayajulu } 2437f10a77bbSDavid C Somayajulu 2438f10a77bbSDavid C Somayajulu 2439f10a77bbSDavid C Somayajulu tx_cmd->n_bufs = (uint8_t)nsegs; 2440f10a77bbSDavid C Somayajulu tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF); 2441f10a77bbSDavid C Somayajulu tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8))); 2442f10a77bbSDavid C Somayajulu tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func); 2443f10a77bbSDavid C Somayajulu 2444f10a77bbSDavid C Somayajulu c_seg = segs; 2445f10a77bbSDavid C Somayajulu 2446f10a77bbSDavid C Somayajulu while (1) { 2447f10a77bbSDavid C Somayajulu for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) { 2448f10a77bbSDavid C Somayajulu 2449f10a77bbSDavid C Somayajulu switch (i) { 2450f10a77bbSDavid C Somayajulu case 0: 2451f10a77bbSDavid C Somayajulu tx_cmd->buf1_addr = c_seg->ds_addr; 2452f10a77bbSDavid C Somayajulu tx_cmd->buf1_len = c_seg->ds_len; 2453f10a77bbSDavid C Somayajulu break; 2454f10a77bbSDavid C Somayajulu 2455f10a77bbSDavid C Somayajulu case 1: 2456f10a77bbSDavid C Somayajulu tx_cmd->buf2_addr = c_seg->ds_addr; 2457f10a77bbSDavid C Somayajulu tx_cmd->buf2_len = c_seg->ds_len; 2458f10a77bbSDavid C Somayajulu break; 2459f10a77bbSDavid C Somayajulu 2460f10a77bbSDavid C Somayajulu case 2: 2461f10a77bbSDavid C Somayajulu tx_cmd->buf3_addr = c_seg->ds_addr; 2462f10a77bbSDavid C Somayajulu tx_cmd->buf3_len = c_seg->ds_len; 2463f10a77bbSDavid C Somayajulu break; 2464f10a77bbSDavid C Somayajulu 2465f10a77bbSDavid C Somayajulu case 3: 2466f10a77bbSDavid C Somayajulu tx_cmd->buf4_addr = c_seg->ds_addr; 2467f10a77bbSDavid C Somayajulu tx_cmd->buf4_len = c_seg->ds_len; 2468f10a77bbSDavid C Somayajulu break; 2469f10a77bbSDavid C Somayajulu } 2470f10a77bbSDavid C Somayajulu 2471f10a77bbSDavid C Somayajulu c_seg++; 2472f10a77bbSDavid C Somayajulu nsegs--; 2473f10a77bbSDavid C Somayajulu } 2474f10a77bbSDavid C Somayajulu 2475f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next = 2476f10a77bbSDavid C Somayajulu (hw->tx_cntxt[txr_idx].txr_next + 1) & 2477f10a77bbSDavid C Somayajulu (NUM_TX_DESCRIPTORS - 1); 2478f10a77bbSDavid C Somayajulu tx_cmd_count++; 2479f10a77bbSDavid C Somayajulu 2480f10a77bbSDavid C Somayajulu if (!nsegs) 2481f10a77bbSDavid C Somayajulu break; 2482f10a77bbSDavid C Somayajulu 2483f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next]; 2484f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 2485f10a77bbSDavid C Somayajulu } 2486f10a77bbSDavid C Somayajulu 2487f10a77bbSDavid C Somayajulu if (mp->m_pkthdr.csum_flags & CSUM_TSO) { 2488f10a77bbSDavid C Somayajulu 2489f10a77bbSDavid C Somayajulu /* TSO : Copy the header in the following tx cmd descriptors */ 2490f10a77bbSDavid C Somayajulu 2491f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next; 2492f10a77bbSDavid C Somayajulu 2493f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next]; 2494f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 2495f10a77bbSDavid C Somayajulu 2496f10a77bbSDavid C Somayajulu bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN; 2497f10a77bbSDavid C Somayajulu bytes = QL_MIN(bytes, hdr_len); 2498f10a77bbSDavid C Somayajulu 2499f10a77bbSDavid C Somayajulu dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN; 2500f10a77bbSDavid C Somayajulu 2501f10a77bbSDavid C Somayajulu if (mp->m_flags & M_VLANTAG) { 2502f10a77bbSDavid C Somayajulu /* first copy the src/dst MAC addresses */ 2503f10a77bbSDavid C Somayajulu bcopy(src, dst, (ETHER_ADDR_LEN * 2)); 2504f10a77bbSDavid C Somayajulu dst += (ETHER_ADDR_LEN * 2); 2505f10a77bbSDavid C Somayajulu src += (ETHER_ADDR_LEN * 2); 2506f10a77bbSDavid C Somayajulu 2507f10a77bbSDavid C Somayajulu *((uint16_t *)dst) = htons(ETHERTYPE_VLAN); 2508f10a77bbSDavid C Somayajulu dst += 2; 2509f10a77bbSDavid C Somayajulu *((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag); 2510f10a77bbSDavid C Somayajulu dst += 2; 2511f10a77bbSDavid C Somayajulu 2512f10a77bbSDavid C Somayajulu /* bytes left in src header */ 2513f10a77bbSDavid C Somayajulu hdr_len -= ((ETHER_ADDR_LEN * 2) + 2514f10a77bbSDavid C Somayajulu ETHER_VLAN_ENCAP_LEN); 2515f10a77bbSDavid C Somayajulu 2516f10a77bbSDavid C Somayajulu /* bytes left in TxCmd Entry */ 2517f10a77bbSDavid C Somayajulu bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN); 2518f10a77bbSDavid C Somayajulu 2519f10a77bbSDavid C Somayajulu 2520f10a77bbSDavid C Somayajulu bcopy(src, dst, bytes); 2521f10a77bbSDavid C Somayajulu src += bytes; 2522f10a77bbSDavid C Somayajulu hdr_len -= bytes; 2523f10a77bbSDavid C Somayajulu } else { 2524f10a77bbSDavid C Somayajulu bcopy(src, dst, bytes); 2525f10a77bbSDavid C Somayajulu src += bytes; 2526f10a77bbSDavid C Somayajulu hdr_len -= bytes; 2527f10a77bbSDavid C Somayajulu } 2528f10a77bbSDavid C Somayajulu 2529f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next = 2530f10a77bbSDavid C Somayajulu (hw->tx_cntxt[txr_idx].txr_next + 1) & 2531f10a77bbSDavid C Somayajulu (NUM_TX_DESCRIPTORS - 1); 2532f10a77bbSDavid C Somayajulu tx_cmd_count++; 2533f10a77bbSDavid C Somayajulu 2534f10a77bbSDavid C Somayajulu while (hdr_len) { 2535f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next]; 2536f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 2537f10a77bbSDavid C Somayajulu 2538f10a77bbSDavid C Somayajulu bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len); 2539f10a77bbSDavid C Somayajulu 2540f10a77bbSDavid C Somayajulu bcopy(src, tx_cmd, bytes); 2541f10a77bbSDavid C Somayajulu src += bytes; 2542f10a77bbSDavid C Somayajulu hdr_len -= bytes; 2543f10a77bbSDavid C Somayajulu 2544f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next = 2545f10a77bbSDavid C Somayajulu (hw->tx_cntxt[txr_idx].txr_next + 1) & 2546f10a77bbSDavid C Somayajulu (NUM_TX_DESCRIPTORS - 1); 2547f10a77bbSDavid C Somayajulu tx_cmd_count++; 2548f10a77bbSDavid C Somayajulu } 2549f10a77bbSDavid C Somayajulu } 2550f10a77bbSDavid C Somayajulu 2551f10a77bbSDavid C Somayajulu hw->tx_cntxt[txr_idx].txr_free = 2552f10a77bbSDavid C Somayajulu hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count; 2553f10a77bbSDavid C Somayajulu 2554f10a77bbSDavid C Somayajulu QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\ 2555f10a77bbSDavid C Somayajulu txr_idx); 2556f10a77bbSDavid C Somayajulu QL_DPRINT8(ha, (dev, "%s: return\n", __func__)); 2557f10a77bbSDavid C Somayajulu 2558f10a77bbSDavid C Somayajulu return (0); 2559f10a77bbSDavid C Somayajulu } 2560f10a77bbSDavid C Somayajulu 2561f10a77bbSDavid C Somayajulu 256235291c22SDavid C Somayajulu 256335291c22SDavid C Somayajulu #define Q8_CONFIG_IND_TBL_SIZE 32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */ 2564f10a77bbSDavid C Somayajulu static int 2565f10a77bbSDavid C Somayajulu qla_config_rss_ind_table(qla_host_t *ha) 2566f10a77bbSDavid C Somayajulu { 2567f10a77bbSDavid C Somayajulu uint32_t i, count; 256835291c22SDavid C Somayajulu uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE]; 2569f10a77bbSDavid C Somayajulu 2570f10a77bbSDavid C Somayajulu 257135291c22SDavid C Somayajulu for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) { 2572f10a77bbSDavid C Somayajulu rss_ind_tbl[i] = i % ha->hw.num_sds_rings; 2573f10a77bbSDavid C Somayajulu } 2574f10a77bbSDavid C Somayajulu 257535291c22SDavid C Somayajulu for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ; 257635291c22SDavid C Somayajulu i = i + Q8_CONFIG_IND_TBL_SIZE) { 2577f10a77bbSDavid C Somayajulu 257835291c22SDavid C Somayajulu if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) { 2579f10a77bbSDavid C Somayajulu count = Q8_RSS_IND_TBL_MAX_IDX - i + 1; 2580f10a77bbSDavid C Somayajulu } else { 258135291c22SDavid C Somayajulu count = Q8_CONFIG_IND_TBL_SIZE; 2582f10a77bbSDavid C Somayajulu } 2583f10a77bbSDavid C Somayajulu 2584f10a77bbSDavid C Somayajulu if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id, 2585f10a77bbSDavid C Somayajulu rss_ind_tbl)) 2586f10a77bbSDavid C Somayajulu return (-1); 2587f10a77bbSDavid C Somayajulu } 2588f10a77bbSDavid C Somayajulu 2589f10a77bbSDavid C Somayajulu return (0); 2590f10a77bbSDavid C Somayajulu } 2591f10a77bbSDavid C Somayajulu 2592a7c62c11SDavid C Somayajulu static int 2593a7c62c11SDavid C Somayajulu qla_config_soft_lro(qla_host_t *ha) 2594a7c62c11SDavid C Somayajulu { 2595a7c62c11SDavid C Somayajulu int i; 2596a7c62c11SDavid C Somayajulu qla_hw_t *hw = &ha->hw; 2597a7c62c11SDavid C Somayajulu struct lro_ctrl *lro; 2598a7c62c11SDavid C Somayajulu 2599a7c62c11SDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) { 2600a7c62c11SDavid C Somayajulu lro = &hw->sds[i].lro; 2601a7c62c11SDavid C Somayajulu 2602a7c62c11SDavid C Somayajulu bzero(lro, sizeof(struct lro_ctrl)); 2603a7c62c11SDavid C Somayajulu 2604a7c62c11SDavid C Somayajulu #if (__FreeBSD_version >= 1100101) 2605a7c62c11SDavid C Somayajulu if (tcp_lro_init_args(lro, ha->ifp, 0, NUM_RX_DESCRIPTORS)) { 2606a7c62c11SDavid C Somayajulu device_printf(ha->pci_dev, 2607a7c62c11SDavid C Somayajulu "%s: tcp_lro_init_args [%d] failed\n", 2608a7c62c11SDavid C Somayajulu __func__, i); 2609a7c62c11SDavid C Somayajulu return (-1); 2610a7c62c11SDavid C Somayajulu } 2611a7c62c11SDavid C Somayajulu #else 2612a7c62c11SDavid C Somayajulu if (tcp_lro_init(lro)) { 2613a7c62c11SDavid C Somayajulu device_printf(ha->pci_dev, 2614a7c62c11SDavid C Somayajulu "%s: tcp_lro_init [%d] failed\n", 2615a7c62c11SDavid C Somayajulu __func__, i); 2616a7c62c11SDavid C Somayajulu return (-1); 2617a7c62c11SDavid C Somayajulu } 2618a7c62c11SDavid C Somayajulu #endif /* #if (__FreeBSD_version >= 1100101) */ 2619a7c62c11SDavid C Somayajulu 2620a7c62c11SDavid C Somayajulu lro->ifp = ha->ifp; 2621a7c62c11SDavid C Somayajulu } 2622a7c62c11SDavid C Somayajulu 2623a7c62c11SDavid C Somayajulu QL_DPRINT2(ha, (ha->pci_dev, "%s: LRO initialized\n", __func__)); 2624a7c62c11SDavid C Somayajulu return (0); 2625a7c62c11SDavid C Somayajulu } 2626a7c62c11SDavid C Somayajulu 2627a7c62c11SDavid C Somayajulu static void 2628a7c62c11SDavid C Somayajulu qla_drain_soft_lro(qla_host_t *ha) 2629a7c62c11SDavid C Somayajulu { 2630a7c62c11SDavid C Somayajulu int i; 2631a7c62c11SDavid C Somayajulu qla_hw_t *hw = &ha->hw; 2632a7c62c11SDavid C Somayajulu struct lro_ctrl *lro; 2633a7c62c11SDavid C Somayajulu 2634a7c62c11SDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) { 2635a7c62c11SDavid C Somayajulu lro = &hw->sds[i].lro; 2636a7c62c11SDavid C Somayajulu 2637a7c62c11SDavid C Somayajulu #if (__FreeBSD_version >= 1100101) 2638a7c62c11SDavid C Somayajulu tcp_lro_flush_all(lro); 2639a7c62c11SDavid C Somayajulu #else 2640a7c62c11SDavid C Somayajulu struct lro_entry *queued; 2641a7c62c11SDavid C Somayajulu 2642a7c62c11SDavid C Somayajulu while ((!SLIST_EMPTY(&lro->lro_active))) { 2643a7c62c11SDavid C Somayajulu queued = SLIST_FIRST(&lro->lro_active); 2644a7c62c11SDavid C Somayajulu SLIST_REMOVE_HEAD(&lro->lro_active, next); 2645a7c62c11SDavid C Somayajulu tcp_lro_flush(lro, queued); 2646a7c62c11SDavid C Somayajulu } 2647a7c62c11SDavid C Somayajulu #endif /* #if (__FreeBSD_version >= 1100101) */ 2648a7c62c11SDavid C Somayajulu } 2649a7c62c11SDavid C Somayajulu 2650a7c62c11SDavid C Somayajulu return; 2651a7c62c11SDavid C Somayajulu } 2652a7c62c11SDavid C Somayajulu 2653a7c62c11SDavid C Somayajulu static void 2654a7c62c11SDavid C Somayajulu qla_free_soft_lro(qla_host_t *ha) 2655a7c62c11SDavid C Somayajulu { 2656a7c62c11SDavid C Somayajulu int i; 2657a7c62c11SDavid C Somayajulu qla_hw_t *hw = &ha->hw; 2658a7c62c11SDavid C Somayajulu struct lro_ctrl *lro; 2659a7c62c11SDavid C Somayajulu 2660a7c62c11SDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) { 2661a7c62c11SDavid C Somayajulu lro = &hw->sds[i].lro; 2662a7c62c11SDavid C Somayajulu tcp_lro_free(lro); 2663a7c62c11SDavid C Somayajulu } 2664a7c62c11SDavid C Somayajulu 2665a7c62c11SDavid C Somayajulu return; 2666a7c62c11SDavid C Somayajulu } 2667a7c62c11SDavid C Somayajulu 2668a7c62c11SDavid C Somayajulu 2669f10a77bbSDavid C Somayajulu /* 2670f10a77bbSDavid C Somayajulu * Name: ql_del_hw_if 2671f10a77bbSDavid C Somayajulu * Function: Destroys the hardware specific entities corresponding to an 2672f10a77bbSDavid C Somayajulu * Ethernet Interface 2673f10a77bbSDavid C Somayajulu */ 2674f10a77bbSDavid C Somayajulu void 2675f10a77bbSDavid C Somayajulu ql_del_hw_if(qla_host_t *ha) 2676f10a77bbSDavid C Somayajulu { 267735291c22SDavid C Somayajulu uint32_t i; 267835291c22SDavid C Somayajulu uint32_t num_msix; 267935291c22SDavid C Somayajulu 268035291c22SDavid C Somayajulu (void)qla_stop_nic_func(ha); 2681f10a77bbSDavid C Somayajulu 2682f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(ha); 2683da834d52SDavid C Somayajulu 2684f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt(ha); 2685f10a77bbSDavid C Somayajulu 2686f10a77bbSDavid C Somayajulu if (ha->hw.flags.init_intr_cnxt) { 268735291c22SDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; ) { 268835291c22SDavid C Somayajulu 268935291c22SDavid C Somayajulu if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings) 269035291c22SDavid C Somayajulu num_msix = Q8_MAX_INTR_VECTORS; 269135291c22SDavid C Somayajulu else 269235291c22SDavid C Somayajulu num_msix = ha->hw.num_sds_rings - i; 269335291c22SDavid C Somayajulu qla_config_intr_cntxt(ha, i, num_msix, 0); 269435291c22SDavid C Somayajulu 269535291c22SDavid C Somayajulu i += num_msix; 269635291c22SDavid C Somayajulu } 269735291c22SDavid C Somayajulu 2698f10a77bbSDavid C Somayajulu ha->hw.flags.init_intr_cnxt = 0; 2699f10a77bbSDavid C Somayajulu } 2700da834d52SDavid C Somayajulu 2701a7c62c11SDavid C Somayajulu if (ha->hw.enable_soft_lro) { 2702a7c62c11SDavid C Somayajulu qla_drain_soft_lro(ha); 2703a7c62c11SDavid C Somayajulu qla_free_soft_lro(ha); 2704a7c62c11SDavid C Somayajulu } 2705a7c62c11SDavid C Somayajulu 270635291c22SDavid C Somayajulu return; 2707f10a77bbSDavid C Somayajulu } 2708f10a77bbSDavid C Somayajulu 270935291c22SDavid C Somayajulu void 271035291c22SDavid C Somayajulu qla_confirm_9kb_enable(qla_host_t *ha) 271135291c22SDavid C Somayajulu { 271235291c22SDavid C Somayajulu uint32_t supports_9kb = 0; 271335291c22SDavid C Somayajulu 271435291c22SDavid C Somayajulu ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX); 271535291c22SDavid C Somayajulu 271635291c22SDavid C Somayajulu /* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */ 271735291c22SDavid C Somayajulu WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2); 271835291c22SDavid C Somayajulu WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0); 271935291c22SDavid C Somayajulu 272035291c22SDavid C Somayajulu qla_get_nic_partition(ha, &supports_9kb, NULL); 272135291c22SDavid C Somayajulu 272235291c22SDavid C Somayajulu if (!supports_9kb) 272335291c22SDavid C Somayajulu ha->hw.enable_9kb = 0; 272435291c22SDavid C Somayajulu 272535291c22SDavid C Somayajulu return; 272635291c22SDavid C Somayajulu } 272735291c22SDavid C Somayajulu 2728f10a77bbSDavid C Somayajulu /* 2729f10a77bbSDavid C Somayajulu * Name: ql_init_hw_if 2730f10a77bbSDavid C Somayajulu * Function: Creates the hardware specific entities corresponding to an 2731f10a77bbSDavid C Somayajulu * Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address 2732f10a77bbSDavid C Somayajulu * corresponding to the interface. Enables LRO if allowed. 2733f10a77bbSDavid C Somayajulu */ 2734f10a77bbSDavid C Somayajulu int 2735f10a77bbSDavid C Somayajulu ql_init_hw_if(qla_host_t *ha) 2736f10a77bbSDavid C Somayajulu { 2737f10a77bbSDavid C Somayajulu device_t dev; 2738f10a77bbSDavid C Somayajulu uint32_t i; 2739f10a77bbSDavid C Somayajulu uint8_t bcast_mac[6]; 2740f10a77bbSDavid C Somayajulu qla_rdesc_t *rdesc; 274135291c22SDavid C Somayajulu uint32_t num_msix; 2742f10a77bbSDavid C Somayajulu 2743f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 2744f10a77bbSDavid C Somayajulu 2745f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 2746f10a77bbSDavid C Somayajulu bzero(ha->hw.dma_buf.sds_ring[i].dma_b, 2747f10a77bbSDavid C Somayajulu ha->hw.dma_buf.sds_ring[i].size); 2748f10a77bbSDavid C Somayajulu } 2749f10a77bbSDavid C Somayajulu 275035291c22SDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; ) { 2751f10a77bbSDavid C Somayajulu 275235291c22SDavid C Somayajulu if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings) 275335291c22SDavid C Somayajulu num_msix = Q8_MAX_INTR_VECTORS; 275435291c22SDavid C Somayajulu else 275535291c22SDavid C Somayajulu num_msix = ha->hw.num_sds_rings - i; 2756f10a77bbSDavid C Somayajulu 275735291c22SDavid C Somayajulu if (qla_config_intr_cntxt(ha, i, num_msix, 1)) { 275835291c22SDavid C Somayajulu 275935291c22SDavid C Somayajulu if (i > 0) { 276035291c22SDavid C Somayajulu 276135291c22SDavid C Somayajulu num_msix = i; 276235291c22SDavid C Somayajulu 276335291c22SDavid C Somayajulu for (i = 0; i < num_msix; ) { 276435291c22SDavid C Somayajulu qla_config_intr_cntxt(ha, i, 276535291c22SDavid C Somayajulu Q8_MAX_INTR_VECTORS, 0); 276635291c22SDavid C Somayajulu i += Q8_MAX_INTR_VECTORS; 276735291c22SDavid C Somayajulu } 276835291c22SDavid C Somayajulu } 2769f10a77bbSDavid C Somayajulu return (-1); 277035291c22SDavid C Somayajulu } 277135291c22SDavid C Somayajulu 277235291c22SDavid C Somayajulu i = i + num_msix; 277335291c22SDavid C Somayajulu } 277435291c22SDavid C Somayajulu 277535291c22SDavid C Somayajulu ha->hw.flags.init_intr_cnxt = 1; 2776f10a77bbSDavid C Somayajulu 2777f10a77bbSDavid C Somayajulu /* 2778f10a77bbSDavid C Somayajulu * Create Receive Context 2779f10a77bbSDavid C Somayajulu */ 2780f10a77bbSDavid C Somayajulu if (qla_init_rcv_cntxt(ha)) { 2781f10a77bbSDavid C Somayajulu return (-1); 2782f10a77bbSDavid C Somayajulu } 2783f10a77bbSDavid C Somayajulu 2784f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) { 2785f10a77bbSDavid C Somayajulu rdesc = &ha->hw.rds[i]; 2786f10a77bbSDavid C Somayajulu rdesc->rx_next = NUM_RX_DESCRIPTORS - 2; 2787f10a77bbSDavid C Somayajulu rdesc->rx_in = 0; 2788f10a77bbSDavid C Somayajulu /* Update the RDS Producer Indices */ 2789f10a77bbSDavid C Somayajulu QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\ 2790f10a77bbSDavid C Somayajulu rdesc->rx_next); 2791f10a77bbSDavid C Somayajulu } 2792f10a77bbSDavid C Somayajulu 2793f10a77bbSDavid C Somayajulu /* 2794f10a77bbSDavid C Somayajulu * Create Transmit Context 2795f10a77bbSDavid C Somayajulu */ 2796f10a77bbSDavid C Somayajulu if (qla_init_xmt_cntxt(ha)) { 2797f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(ha); 2798f10a77bbSDavid C Somayajulu return (-1); 2799f10a77bbSDavid C Somayajulu } 2800f10a77bbSDavid C Somayajulu ha->hw.max_tx_segs = 0; 2801f10a77bbSDavid C Somayajulu 2802da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1, 1)) 2803f10a77bbSDavid C Somayajulu return(-1); 2804f10a77bbSDavid C Somayajulu 2805f10a77bbSDavid C Somayajulu ha->hw.flags.unicast_mac = 1; 2806f10a77bbSDavid C Somayajulu 2807f10a77bbSDavid C Somayajulu bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF; 2808f10a77bbSDavid C Somayajulu bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF; 2809f10a77bbSDavid C Somayajulu 2810da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, bcast_mac, 1, 1)) 2811f10a77bbSDavid C Somayajulu return (-1); 2812f10a77bbSDavid C Somayajulu 2813f10a77bbSDavid C Somayajulu ha->hw.flags.bcast_mac = 1; 2814f10a77bbSDavid C Somayajulu 2815f10a77bbSDavid C Somayajulu /* 2816f10a77bbSDavid C Somayajulu * program any cached multicast addresses 2817f10a77bbSDavid C Somayajulu */ 2818f10a77bbSDavid C Somayajulu if (qla_hw_add_all_mcast(ha)) 2819f10a77bbSDavid C Somayajulu return (-1); 2820f10a77bbSDavid C Somayajulu 2821b5c2be72SDavid C Somayajulu if (ql_set_max_mtu(ha, ha->max_frame_size, ha->hw.rcv_cntxt_id)) 2822b5c2be72SDavid C Somayajulu return (-1); 2823b5c2be72SDavid C Somayajulu 2824f10a77bbSDavid C Somayajulu if (qla_config_rss(ha, ha->hw.rcv_cntxt_id)) 2825f10a77bbSDavid C Somayajulu return (-1); 2826f10a77bbSDavid C Somayajulu 2827f10a77bbSDavid C Somayajulu if (qla_config_rss_ind_table(ha)) 2828f10a77bbSDavid C Somayajulu return (-1); 2829f10a77bbSDavid C Somayajulu 283035291c22SDavid C Somayajulu if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1)) 2831f10a77bbSDavid C Somayajulu return (-1); 2832f10a77bbSDavid C Somayajulu 2833f10a77bbSDavid C Somayajulu if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id)) 2834f10a77bbSDavid C Somayajulu return (-1); 2835f10a77bbSDavid C Somayajulu 2836a7c62c11SDavid C Somayajulu if (ha->ifp->if_capenable & IFCAP_LRO) { 2837a7c62c11SDavid C Somayajulu if (ha->hw.enable_hw_lro) { 2838a7c62c11SDavid C Somayajulu ha->hw.enable_soft_lro = 0; 2839a7c62c11SDavid C Somayajulu 2840f10a77bbSDavid C Somayajulu if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id)) 2841f10a77bbSDavid C Somayajulu return (-1); 2842a7c62c11SDavid C Somayajulu } else { 2843a7c62c11SDavid C Somayajulu ha->hw.enable_soft_lro = 1; 2844a7c62c11SDavid C Somayajulu 2845a7c62c11SDavid C Somayajulu if (qla_config_soft_lro(ha)) 2846a7c62c11SDavid C Somayajulu return (-1); 2847a7c62c11SDavid C Somayajulu } 2848a7c62c11SDavid C Somayajulu } 2849f10a77bbSDavid C Somayajulu 285035291c22SDavid C Somayajulu if (qla_init_nic_func(ha)) 285135291c22SDavid C Somayajulu return (-1); 285235291c22SDavid C Somayajulu 285335291c22SDavid C Somayajulu if (qla_query_fw_dcbx_caps(ha)) 285435291c22SDavid C Somayajulu return (-1); 285535291c22SDavid C Somayajulu 2856f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) 2857f10a77bbSDavid C Somayajulu QL_ENABLE_INTERRUPTS(ha, i); 2858f10a77bbSDavid C Somayajulu 2859f10a77bbSDavid C Somayajulu return (0); 2860f10a77bbSDavid C Somayajulu } 2861f10a77bbSDavid C Somayajulu 2862f10a77bbSDavid C Somayajulu static int 286335291c22SDavid C Somayajulu qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx) 2864f10a77bbSDavid C Somayajulu { 2865f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 2866f10a77bbSDavid C Somayajulu q80_rq_map_sds_to_rds_t *map_rings; 286735291c22SDavid C Somayajulu q80_rsp_map_sds_to_rds_t *map_rings_rsp; 2868f10a77bbSDavid C Somayajulu uint32_t i, err; 2869f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 2870f10a77bbSDavid C Somayajulu 2871f10a77bbSDavid C Somayajulu map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox; 2872f10a77bbSDavid C Somayajulu bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t)); 2873f10a77bbSDavid C Somayajulu 2874f10a77bbSDavid C Somayajulu map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS; 2875f10a77bbSDavid C Somayajulu map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2); 2876f10a77bbSDavid C Somayajulu map_rings->count_version |= Q8_MBX_CMD_VERSION; 2877f10a77bbSDavid C Somayajulu 2878f10a77bbSDavid C Somayajulu map_rings->cntxt_id = hw->rcv_cntxt_id; 287935291c22SDavid C Somayajulu map_rings->num_rings = num_idx; 2880f10a77bbSDavid C Somayajulu 288135291c22SDavid C Somayajulu for (i = 0; i < num_idx; i++) { 288235291c22SDavid C Somayajulu map_rings->sds_rds[i].sds_ring = i + start_idx; 288335291c22SDavid C Somayajulu map_rings->sds_rds[i].rds_ring = i + start_idx; 2884f10a77bbSDavid C Somayajulu } 2885f10a77bbSDavid C Somayajulu 2886f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)map_rings, 2887f10a77bbSDavid C Somayajulu (sizeof (q80_rq_map_sds_to_rds_t) >> 2), 2888f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) { 2889f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 2890f10a77bbSDavid C Somayajulu return (-1); 2891f10a77bbSDavid C Somayajulu } 2892f10a77bbSDavid C Somayajulu 289335291c22SDavid C Somayajulu map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox; 2894f10a77bbSDavid C Somayajulu 2895f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status); 2896f10a77bbSDavid C Somayajulu 2897f10a77bbSDavid C Somayajulu if (err) { 2898f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2899f10a77bbSDavid C Somayajulu return (-1); 2900f10a77bbSDavid C Somayajulu } 2901f10a77bbSDavid C Somayajulu 2902f10a77bbSDavid C Somayajulu return (0); 2903f10a77bbSDavid C Somayajulu } 2904f10a77bbSDavid C Somayajulu 2905f10a77bbSDavid C Somayajulu /* 2906f10a77bbSDavid C Somayajulu * Name: qla_init_rcv_cntxt 2907f10a77bbSDavid C Somayajulu * Function: Creates the Receive Context. 2908f10a77bbSDavid C Somayajulu */ 2909f10a77bbSDavid C Somayajulu static int 2910f10a77bbSDavid C Somayajulu qla_init_rcv_cntxt(qla_host_t *ha) 2911f10a77bbSDavid C Somayajulu { 2912f10a77bbSDavid C Somayajulu q80_rq_rcv_cntxt_t *rcntxt; 2913f10a77bbSDavid C Somayajulu q80_rsp_rcv_cntxt_t *rcntxt_rsp; 2914f10a77bbSDavid C Somayajulu q80_stat_desc_t *sdesc; 2915f10a77bbSDavid C Somayajulu int i, j; 2916f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 2917f10a77bbSDavid C Somayajulu device_t dev; 2918f10a77bbSDavid C Somayajulu uint32_t err; 2919f10a77bbSDavid C Somayajulu uint32_t rcntxt_sds_rings; 2920f10a77bbSDavid C Somayajulu uint32_t rcntxt_rds_rings; 292135291c22SDavid C Somayajulu uint32_t max_idx; 2922f10a77bbSDavid C Somayajulu 2923f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 2924f10a77bbSDavid C Somayajulu 2925f10a77bbSDavid C Somayajulu /* 2926f10a77bbSDavid C Somayajulu * Create Receive Context 2927f10a77bbSDavid C Somayajulu */ 2928f10a77bbSDavid C Somayajulu 2929f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) { 2930f10a77bbSDavid C Somayajulu sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0]; 2931f10a77bbSDavid C Somayajulu 2932f10a77bbSDavid C Somayajulu for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) { 2933f10a77bbSDavid C Somayajulu sdesc->data[0] = 1ULL; 2934f10a77bbSDavid C Somayajulu sdesc->data[1] = 1ULL; 2935f10a77bbSDavid C Somayajulu } 2936f10a77bbSDavid C Somayajulu } 2937f10a77bbSDavid C Somayajulu 2938f10a77bbSDavid C Somayajulu rcntxt_sds_rings = hw->num_sds_rings; 2939f10a77bbSDavid C Somayajulu if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) 2940f10a77bbSDavid C Somayajulu rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS; 2941f10a77bbSDavid C Somayajulu 2942f10a77bbSDavid C Somayajulu rcntxt_rds_rings = hw->num_rds_rings; 2943f10a77bbSDavid C Somayajulu 2944f10a77bbSDavid C Somayajulu if (hw->num_rds_rings > MAX_RDS_RING_SETS) 2945f10a77bbSDavid C Somayajulu rcntxt_rds_rings = MAX_RDS_RING_SETS; 2946f10a77bbSDavid C Somayajulu 2947f10a77bbSDavid C Somayajulu rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox; 2948f10a77bbSDavid C Somayajulu bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t))); 2949f10a77bbSDavid C Somayajulu 2950f10a77bbSDavid C Somayajulu rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT; 2951f10a77bbSDavid C Somayajulu rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2); 2952f10a77bbSDavid C Somayajulu rcntxt->count_version |= Q8_MBX_CMD_VERSION; 2953f10a77bbSDavid C Somayajulu 2954f10a77bbSDavid C Somayajulu rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW | 2955f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_LRO | 2956f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_HW_LRO | 2957f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_RSS | 2958f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_SGL_LRO; 2959f10a77bbSDavid C Somayajulu 296035291c22SDavid C Somayajulu if (ha->hw.enable_9kb) 296135291c22SDavid C Somayajulu rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO; 296235291c22SDavid C Somayajulu else 296335291c22SDavid C Somayajulu rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO; 296435291c22SDavid C Somayajulu 2965f10a77bbSDavid C Somayajulu if (ha->hw.num_rds_rings > 1) { 2966f10a77bbSDavid C Somayajulu rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5); 2967f10a77bbSDavid C Somayajulu rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS; 2968f10a77bbSDavid C Somayajulu } else 2969f10a77bbSDavid C Somayajulu rcntxt->nrds_sets_rings = 0x1 | (1 << 5); 2970f10a77bbSDavid C Somayajulu 2971f10a77bbSDavid C Somayajulu rcntxt->nsds_rings = rcntxt_sds_rings; 2972f10a77bbSDavid C Somayajulu 2973f10a77bbSDavid C Somayajulu rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE; 2974f10a77bbSDavid C Somayajulu 2975f10a77bbSDavid C Somayajulu rcntxt->rcv_vpid = 0; 2976f10a77bbSDavid C Somayajulu 2977f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_sds_rings; i++) { 2978f10a77bbSDavid C Somayajulu rcntxt->sds[i].paddr = 2979f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr); 2980f10a77bbSDavid C Somayajulu rcntxt->sds[i].size = 2981f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_STATUS_DESCRIPTORS); 2982b89f2279SDavid C Somayajulu rcntxt->sds[i].intr_id = qla_host_to_le16(hw->intr_id[i]); 2983f10a77bbSDavid C Somayajulu rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0); 2984f10a77bbSDavid C Somayajulu } 2985f10a77bbSDavid C Somayajulu 2986f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_rds_rings; i++) { 2987f10a77bbSDavid C Somayajulu rcntxt->rds[i].paddr_std = 2988f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr); 298935291c22SDavid C Somayajulu 299035291c22SDavid C Somayajulu if (ha->hw.enable_9kb) 299135291c22SDavid C Somayajulu rcntxt->rds[i].std_bsize = 299235291c22SDavid C Somayajulu qla_host_to_le64(MJUM9BYTES); 299335291c22SDavid C Somayajulu else 2994f10a77bbSDavid C Somayajulu rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES); 299535291c22SDavid C Somayajulu 2996f10a77bbSDavid C Somayajulu rcntxt->rds[i].std_nentries = 2997f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_RX_DESCRIPTORS); 2998f10a77bbSDavid C Somayajulu } 2999f10a77bbSDavid C Somayajulu 3000f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)rcntxt, 3001f10a77bbSDavid C Somayajulu (sizeof (q80_rq_rcv_cntxt_t) >> 2), 3002f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) { 3003f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 3004f10a77bbSDavid C Somayajulu return (-1); 3005f10a77bbSDavid C Somayajulu } 3006f10a77bbSDavid C Somayajulu 3007f10a77bbSDavid C Somayajulu rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox; 3008f10a77bbSDavid C Somayajulu 3009f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status); 3010f10a77bbSDavid C Somayajulu 3011f10a77bbSDavid C Somayajulu if (err) { 3012f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 3013f10a77bbSDavid C Somayajulu return (-1); 3014f10a77bbSDavid C Somayajulu } 3015f10a77bbSDavid C Somayajulu 3016f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_sds_rings; i++) { 3017f10a77bbSDavid C Somayajulu hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i]; 3018f10a77bbSDavid C Somayajulu } 3019f10a77bbSDavid C Somayajulu 3020f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_rds_rings; i++) { 3021f10a77bbSDavid C Somayajulu hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std; 3022f10a77bbSDavid C Somayajulu } 3023f10a77bbSDavid C Somayajulu 3024f10a77bbSDavid C Somayajulu hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id; 3025f10a77bbSDavid C Somayajulu 3026f10a77bbSDavid C Somayajulu ha->hw.flags.init_rx_cnxt = 1; 3027f10a77bbSDavid C Somayajulu 3028f10a77bbSDavid C Somayajulu if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) { 302935291c22SDavid C Somayajulu 303035291c22SDavid C Somayajulu for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) { 303135291c22SDavid C Somayajulu 303235291c22SDavid C Somayajulu if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings) 303335291c22SDavid C Somayajulu max_idx = MAX_RCNTXT_SDS_RINGS; 303435291c22SDavid C Somayajulu else 303535291c22SDavid C Somayajulu max_idx = hw->num_sds_rings - i; 303635291c22SDavid C Somayajulu 303735291c22SDavid C Somayajulu err = qla_add_rcv_rings(ha, i, max_idx); 3038f10a77bbSDavid C Somayajulu if (err) 3039f10a77bbSDavid C Somayajulu return -1; 304035291c22SDavid C Somayajulu 304135291c22SDavid C Somayajulu i += max_idx; 304235291c22SDavid C Somayajulu } 3043f10a77bbSDavid C Somayajulu } 3044f10a77bbSDavid C Somayajulu 3045f10a77bbSDavid C Somayajulu if (hw->num_rds_rings > 1) { 304635291c22SDavid C Somayajulu 304735291c22SDavid C Somayajulu for (i = 0; i < hw->num_rds_rings; ) { 304835291c22SDavid C Somayajulu 304935291c22SDavid C Somayajulu if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings) 305035291c22SDavid C Somayajulu max_idx = MAX_SDS_TO_RDS_MAP; 305135291c22SDavid C Somayajulu else 305235291c22SDavid C Somayajulu max_idx = hw->num_rds_rings - i; 305335291c22SDavid C Somayajulu 305435291c22SDavid C Somayajulu err = qla_map_sds_to_rds(ha, i, max_idx); 3055f10a77bbSDavid C Somayajulu if (err) 3056f10a77bbSDavid C Somayajulu return -1; 305735291c22SDavid C Somayajulu 305835291c22SDavid C Somayajulu i += max_idx; 305935291c22SDavid C Somayajulu } 3060f10a77bbSDavid C Somayajulu } 3061f10a77bbSDavid C Somayajulu 3062f10a77bbSDavid C Somayajulu return (0); 3063f10a77bbSDavid C Somayajulu } 3064f10a77bbSDavid C Somayajulu 3065f10a77bbSDavid C Somayajulu static int 306635291c22SDavid C Somayajulu qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds) 3067f10a77bbSDavid C Somayajulu { 3068f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 3069f10a77bbSDavid C Somayajulu q80_rq_add_rcv_rings_t *add_rcv; 3070f10a77bbSDavid C Somayajulu q80_rsp_add_rcv_rings_t *add_rcv_rsp; 3071f10a77bbSDavid C Somayajulu uint32_t i,j, err; 3072f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 3073f10a77bbSDavid C Somayajulu 3074f10a77bbSDavid C Somayajulu add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox; 3075f10a77bbSDavid C Somayajulu bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t)); 3076f10a77bbSDavid C Somayajulu 3077f10a77bbSDavid C Somayajulu add_rcv->opcode = Q8_MBX_ADD_RX_RINGS; 3078f10a77bbSDavid C Somayajulu add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2); 3079f10a77bbSDavid C Somayajulu add_rcv->count_version |= Q8_MBX_CMD_VERSION; 3080f10a77bbSDavid C Somayajulu 3081f10a77bbSDavid C Somayajulu add_rcv->nrds_sets_rings = nsds | (1 << 5); 3082f10a77bbSDavid C Somayajulu add_rcv->nsds_rings = nsds; 3083f10a77bbSDavid C Somayajulu add_rcv->cntxt_id = hw->rcv_cntxt_id; 3084f10a77bbSDavid C Somayajulu 3085f10a77bbSDavid C Somayajulu for (i = 0; i < nsds; i++) { 3086f10a77bbSDavid C Somayajulu 3087f10a77bbSDavid C Somayajulu j = i + sds_idx; 3088f10a77bbSDavid C Somayajulu 3089f10a77bbSDavid C Somayajulu add_rcv->sds[i].paddr = 3090f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr); 3091f10a77bbSDavid C Somayajulu 3092f10a77bbSDavid C Somayajulu add_rcv->sds[i].size = 3093f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_STATUS_DESCRIPTORS); 3094f10a77bbSDavid C Somayajulu 3095b89f2279SDavid C Somayajulu add_rcv->sds[i].intr_id = qla_host_to_le16(hw->intr_id[j]); 3096f10a77bbSDavid C Somayajulu add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0); 3097f10a77bbSDavid C Somayajulu 3098f10a77bbSDavid C Somayajulu } 3099b89f2279SDavid C Somayajulu 310035291c22SDavid C Somayajulu for (i = 0; (i < nsds); i++) { 3101f10a77bbSDavid C Somayajulu j = i + sds_idx; 310235291c22SDavid C Somayajulu 3103f10a77bbSDavid C Somayajulu add_rcv->rds[i].paddr_std = 3104f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr); 310535291c22SDavid C Somayajulu 310635291c22SDavid C Somayajulu if (ha->hw.enable_9kb) 310735291c22SDavid C Somayajulu add_rcv->rds[i].std_bsize = 310835291c22SDavid C Somayajulu qla_host_to_le64(MJUM9BYTES); 310935291c22SDavid C Somayajulu else 3110f10a77bbSDavid C Somayajulu add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES); 311135291c22SDavid C Somayajulu 3112f10a77bbSDavid C Somayajulu add_rcv->rds[i].std_nentries = 3113f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_RX_DESCRIPTORS); 3114f10a77bbSDavid C Somayajulu } 3115f10a77bbSDavid C Somayajulu 3116f10a77bbSDavid C Somayajulu 3117f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)add_rcv, 3118f10a77bbSDavid C Somayajulu (sizeof (q80_rq_add_rcv_rings_t) >> 2), 3119f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) { 3120f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 3121f10a77bbSDavid C Somayajulu return (-1); 3122f10a77bbSDavid C Somayajulu } 3123f10a77bbSDavid C Somayajulu 3124f10a77bbSDavid C Somayajulu add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox; 3125f10a77bbSDavid C Somayajulu 3126f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status); 3127f10a77bbSDavid C Somayajulu 3128f10a77bbSDavid C Somayajulu if (err) { 3129f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 3130f10a77bbSDavid C Somayajulu return (-1); 3131f10a77bbSDavid C Somayajulu } 3132f10a77bbSDavid C Somayajulu 313335291c22SDavid C Somayajulu for (i = 0; i < nsds; i++) { 313435291c22SDavid C Somayajulu hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i]; 3135f10a77bbSDavid C Somayajulu } 313635291c22SDavid C Somayajulu 313735291c22SDavid C Somayajulu for (i = 0; i < nsds; i++) { 313835291c22SDavid C Somayajulu hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std; 3139f10a77bbSDavid C Somayajulu } 314035291c22SDavid C Somayajulu 3141f10a77bbSDavid C Somayajulu return (0); 3142f10a77bbSDavid C Somayajulu } 3143f10a77bbSDavid C Somayajulu 3144f10a77bbSDavid C Somayajulu /* 3145f10a77bbSDavid C Somayajulu * Name: qla_del_rcv_cntxt 3146f10a77bbSDavid C Somayajulu * Function: Destroys the Receive Context. 3147f10a77bbSDavid C Somayajulu */ 3148f10a77bbSDavid C Somayajulu static void 3149f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(qla_host_t *ha) 3150f10a77bbSDavid C Somayajulu { 3151f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 3152f10a77bbSDavid C Somayajulu q80_rcv_cntxt_destroy_t *rcntxt; 3153f10a77bbSDavid C Somayajulu q80_rcv_cntxt_destroy_rsp_t *rcntxt_rsp; 3154f10a77bbSDavid C Somayajulu uint32_t err; 3155f10a77bbSDavid C Somayajulu uint8_t bcast_mac[6]; 3156f10a77bbSDavid C Somayajulu 3157f10a77bbSDavid C Somayajulu if (!ha->hw.flags.init_rx_cnxt) 3158f10a77bbSDavid C Somayajulu return; 3159f10a77bbSDavid C Somayajulu 3160f10a77bbSDavid C Somayajulu if (qla_hw_del_all_mcast(ha)) 3161f10a77bbSDavid C Somayajulu return; 3162f10a77bbSDavid C Somayajulu 3163f10a77bbSDavid C Somayajulu if (ha->hw.flags.bcast_mac) { 3164f10a77bbSDavid C Somayajulu 3165f10a77bbSDavid C Somayajulu bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF; 3166f10a77bbSDavid C Somayajulu bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF; 3167f10a77bbSDavid C Somayajulu 3168da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, bcast_mac, 0, 1)) 3169f10a77bbSDavid C Somayajulu return; 3170f10a77bbSDavid C Somayajulu ha->hw.flags.bcast_mac = 0; 3171f10a77bbSDavid C Somayajulu 3172f10a77bbSDavid C Somayajulu } 3173f10a77bbSDavid C Somayajulu 3174f10a77bbSDavid C Somayajulu if (ha->hw.flags.unicast_mac) { 3175da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0, 1)) 3176f10a77bbSDavid C Somayajulu return; 3177f10a77bbSDavid C Somayajulu ha->hw.flags.unicast_mac = 0; 3178f10a77bbSDavid C Somayajulu } 3179f10a77bbSDavid C Somayajulu 3180f10a77bbSDavid C Somayajulu rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox; 3181f10a77bbSDavid C Somayajulu bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t))); 3182f10a77bbSDavid C Somayajulu 3183f10a77bbSDavid C Somayajulu rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT; 3184f10a77bbSDavid C Somayajulu rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2); 3185f10a77bbSDavid C Somayajulu rcntxt->count_version |= Q8_MBX_CMD_VERSION; 3186f10a77bbSDavid C Somayajulu 3187f10a77bbSDavid C Somayajulu rcntxt->cntxt_id = ha->hw.rcv_cntxt_id; 3188f10a77bbSDavid C Somayajulu 3189f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)rcntxt, 3190f10a77bbSDavid C Somayajulu (sizeof (q80_rcv_cntxt_destroy_t) >> 2), 3191f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) { 3192f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 3193f10a77bbSDavid C Somayajulu return; 3194f10a77bbSDavid C Somayajulu } 3195f10a77bbSDavid C Somayajulu rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox; 3196f10a77bbSDavid C Somayajulu 3197f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status); 3198f10a77bbSDavid C Somayajulu 3199f10a77bbSDavid C Somayajulu if (err) { 3200f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 3201f10a77bbSDavid C Somayajulu } 3202f10a77bbSDavid C Somayajulu 3203f10a77bbSDavid C Somayajulu ha->hw.flags.init_rx_cnxt = 0; 3204f10a77bbSDavid C Somayajulu return; 3205f10a77bbSDavid C Somayajulu } 3206f10a77bbSDavid C Somayajulu 3207f10a77bbSDavid C Somayajulu /* 3208f10a77bbSDavid C Somayajulu * Name: qla_init_xmt_cntxt 3209f10a77bbSDavid C Somayajulu * Function: Creates the Transmit Context. 3210f10a77bbSDavid C Somayajulu */ 3211f10a77bbSDavid C Somayajulu static int 3212f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx) 3213f10a77bbSDavid C Somayajulu { 3214f10a77bbSDavid C Somayajulu device_t dev; 3215f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 3216f10a77bbSDavid C Somayajulu q80_rq_tx_cntxt_t *tcntxt; 3217f10a77bbSDavid C Somayajulu q80_rsp_tx_cntxt_t *tcntxt_rsp; 3218f10a77bbSDavid C Somayajulu uint32_t err; 3219f10a77bbSDavid C Somayajulu qla_hw_tx_cntxt_t *hw_tx_cntxt; 3220b89f2279SDavid C Somayajulu uint32_t intr_idx; 3221f10a77bbSDavid C Somayajulu 3222f10a77bbSDavid C Somayajulu hw_tx_cntxt = &hw->tx_cntxt[txr_idx]; 3223f10a77bbSDavid C Somayajulu 3224f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 3225f10a77bbSDavid C Somayajulu 3226f10a77bbSDavid C Somayajulu /* 3227f10a77bbSDavid C Somayajulu * Create Transmit Context 3228f10a77bbSDavid C Somayajulu */ 3229f10a77bbSDavid C Somayajulu tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox; 3230f10a77bbSDavid C Somayajulu bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t))); 3231f10a77bbSDavid C Somayajulu 3232f10a77bbSDavid C Somayajulu tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT; 3233f10a77bbSDavid C Somayajulu tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2); 3234f10a77bbSDavid C Somayajulu tcntxt->count_version |= Q8_MBX_CMD_VERSION; 3235f10a77bbSDavid C Somayajulu 3236b89f2279SDavid C Somayajulu intr_idx = txr_idx; 3237b89f2279SDavid C Somayajulu 323835291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV 323935291c22SDavid C Somayajulu 324035291c22SDavid C Somayajulu tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO | 324135291c22SDavid C Somayajulu Q8_TX_CNTXT_CAP0_TC; 324235291c22SDavid C Somayajulu 324335291c22SDavid C Somayajulu if (txr_idx >= (ha->hw.num_tx_rings >> 1)) { 324435291c22SDavid C Somayajulu tcntxt->traffic_class = 1; 324535291c22SDavid C Somayajulu } 324635291c22SDavid C Somayajulu 3247b89f2279SDavid C Somayajulu intr_idx = txr_idx % (ha->hw.num_tx_rings >> 1); 324835291c22SDavid C Somayajulu 3249b89f2279SDavid C Somayajulu #else 3250f10a77bbSDavid C Somayajulu tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO; 3251f10a77bbSDavid C Somayajulu 325235291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */ 325335291c22SDavid C Somayajulu 3254f10a77bbSDavid C Somayajulu tcntxt->ntx_rings = 1; 3255f10a77bbSDavid C Somayajulu 3256f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].paddr = 3257f10a77bbSDavid C Somayajulu qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr); 3258f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].tx_consumer = 3259f10a77bbSDavid C Somayajulu qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr); 3260f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS); 3261f10a77bbSDavid C Somayajulu 3262b89f2279SDavid C Somayajulu tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[intr_idx]); 3263f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0); 3264f10a77bbSDavid C Somayajulu 3265f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS; 3266f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0; 3267c06073f5SDavid C Somayajulu *(hw_tx_cntxt->tx_cons) = 0; 3268f10a77bbSDavid C Somayajulu 3269f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)tcntxt, 3270f10a77bbSDavid C Somayajulu (sizeof (q80_rq_tx_cntxt_t) >> 2), 3271f10a77bbSDavid C Somayajulu ha->hw.mbox, 3272f10a77bbSDavid C Somayajulu (sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) { 3273f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 3274f10a77bbSDavid C Somayajulu return (-1); 3275f10a77bbSDavid C Somayajulu } 3276f10a77bbSDavid C Somayajulu tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox; 3277f10a77bbSDavid C Somayajulu 3278f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status); 3279f10a77bbSDavid C Somayajulu 3280f10a77bbSDavid C Somayajulu if (err) { 3281f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 3282f10a77bbSDavid C Somayajulu return -1; 3283f10a77bbSDavid C Somayajulu } 3284f10a77bbSDavid C Somayajulu 3285f10a77bbSDavid C Somayajulu hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index; 3286f10a77bbSDavid C Somayajulu hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id; 3287f10a77bbSDavid C Somayajulu 328835291c22SDavid C Somayajulu if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0)) 328935291c22SDavid C Somayajulu return (-1); 329035291c22SDavid C Somayajulu 3291f10a77bbSDavid C Somayajulu return (0); 3292f10a77bbSDavid C Somayajulu } 3293f10a77bbSDavid C Somayajulu 3294f10a77bbSDavid C Somayajulu 3295f10a77bbSDavid C Somayajulu /* 3296f10a77bbSDavid C Somayajulu * Name: qla_del_xmt_cntxt 3297f10a77bbSDavid C Somayajulu * Function: Destroys the Transmit Context. 3298f10a77bbSDavid C Somayajulu */ 3299f10a77bbSDavid C Somayajulu static int 3300f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx) 3301f10a77bbSDavid C Somayajulu { 3302f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 3303f10a77bbSDavid C Somayajulu q80_tx_cntxt_destroy_t *tcntxt; 3304f10a77bbSDavid C Somayajulu q80_tx_cntxt_destroy_rsp_t *tcntxt_rsp; 3305f10a77bbSDavid C Somayajulu uint32_t err; 3306f10a77bbSDavid C Somayajulu 3307f10a77bbSDavid C Somayajulu tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox; 3308f10a77bbSDavid C Somayajulu bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t))); 3309f10a77bbSDavid C Somayajulu 3310f10a77bbSDavid C Somayajulu tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT; 3311f10a77bbSDavid C Somayajulu tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2); 3312f10a77bbSDavid C Somayajulu tcntxt->count_version |= Q8_MBX_CMD_VERSION; 3313f10a77bbSDavid C Somayajulu 3314f10a77bbSDavid C Somayajulu tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id; 3315f10a77bbSDavid C Somayajulu 3316f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)tcntxt, 3317f10a77bbSDavid C Somayajulu (sizeof (q80_tx_cntxt_destroy_t) >> 2), 3318f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) { 3319f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 3320f10a77bbSDavid C Somayajulu return (-1); 3321f10a77bbSDavid C Somayajulu } 3322f10a77bbSDavid C Somayajulu tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox; 3323f10a77bbSDavid C Somayajulu 3324f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status); 3325f10a77bbSDavid C Somayajulu 3326f10a77bbSDavid C Somayajulu if (err) { 3327f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 3328f10a77bbSDavid C Somayajulu return (-1); 3329f10a77bbSDavid C Somayajulu } 3330f10a77bbSDavid C Somayajulu 3331f10a77bbSDavid C Somayajulu return (0); 3332f10a77bbSDavid C Somayajulu } 3333f10a77bbSDavid C Somayajulu static void 3334f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt(qla_host_t *ha) 3335f10a77bbSDavid C Somayajulu { 3336f10a77bbSDavid C Somayajulu uint32_t i; 3337f10a77bbSDavid C Somayajulu 3338f10a77bbSDavid C Somayajulu if (!ha->hw.flags.init_tx_cnxt) 3339f10a77bbSDavid C Somayajulu return; 3340f10a77bbSDavid C Somayajulu 3341f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 3342f10a77bbSDavid C Somayajulu if (qla_del_xmt_cntxt_i(ha, i)) 3343f10a77bbSDavid C Somayajulu break; 3344f10a77bbSDavid C Somayajulu } 3345f10a77bbSDavid C Somayajulu ha->hw.flags.init_tx_cnxt = 0; 3346f10a77bbSDavid C Somayajulu } 3347f10a77bbSDavid C Somayajulu 3348f10a77bbSDavid C Somayajulu static int 3349f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt(qla_host_t *ha) 3350f10a77bbSDavid C Somayajulu { 3351f10a77bbSDavid C Somayajulu uint32_t i, j; 3352f10a77bbSDavid C Somayajulu 3353f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 3354f10a77bbSDavid C Somayajulu if (qla_init_xmt_cntxt_i(ha, i) != 0) { 3355f10a77bbSDavid C Somayajulu for (j = 0; j < i; j++) 3356f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt_i(ha, j); 3357f10a77bbSDavid C Somayajulu return (-1); 3358f10a77bbSDavid C Somayajulu } 3359f10a77bbSDavid C Somayajulu } 3360f10a77bbSDavid C Somayajulu ha->hw.flags.init_tx_cnxt = 1; 3361f10a77bbSDavid C Somayajulu return (0); 3362f10a77bbSDavid C Somayajulu } 3363f10a77bbSDavid C Somayajulu 3364f10a77bbSDavid C Somayajulu static int 3365da834d52SDavid C Somayajulu qla_hw_all_mcast(qla_host_t *ha, uint32_t add_mcast) 3366f10a77bbSDavid C Somayajulu { 3367f10a77bbSDavid C Somayajulu int i, nmcast; 3368da834d52SDavid C Somayajulu uint32_t count = 0; 3369da834d52SDavid C Somayajulu uint8_t *mcast; 3370f10a77bbSDavid C Somayajulu 3371f10a77bbSDavid C Somayajulu nmcast = ha->hw.nmcast; 3372f10a77bbSDavid C Somayajulu 3373da834d52SDavid C Somayajulu QL_DPRINT2(ha, (ha->pci_dev, 3374da834d52SDavid C Somayajulu "%s:[0x%x] enter nmcast = %d \n", __func__, add_mcast, nmcast)); 3375da834d52SDavid C Somayajulu 3376da834d52SDavid C Somayajulu mcast = ha->hw.mac_addr_arr; 3377da834d52SDavid C Somayajulu memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN)); 3378da834d52SDavid C Somayajulu 3379f10a77bbSDavid C Somayajulu for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) { 3380f10a77bbSDavid C Somayajulu if ((ha->hw.mcast[i].addr[0] != 0) || 3381f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[1] != 0) || 3382f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[2] != 0) || 3383f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[3] != 0) || 3384f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[4] != 0) || 3385f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[5] != 0)) { 3386f10a77bbSDavid C Somayajulu 3387da834d52SDavid C Somayajulu bcopy(ha->hw.mcast[i].addr, mcast, ETHER_ADDR_LEN); 3388da834d52SDavid C Somayajulu mcast = mcast + ETHER_ADDR_LEN; 3389da834d52SDavid C Somayajulu count++; 3390da834d52SDavid C Somayajulu 3391da834d52SDavid C Somayajulu if (count == Q8_MAX_MAC_ADDRS) { 3392da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, 3393da834d52SDavid C Somayajulu add_mcast, count)) { 3394da834d52SDavid C Somayajulu device_printf(ha->pci_dev, 3395da834d52SDavid C Somayajulu "%s: failed\n", __func__); 3396f10a77bbSDavid C Somayajulu return (-1); 3397f10a77bbSDavid C Somayajulu } 3398f10a77bbSDavid C Somayajulu 3399da834d52SDavid C Somayajulu count = 0; 3400da834d52SDavid C Somayajulu mcast = ha->hw.mac_addr_arr; 3401da834d52SDavid C Somayajulu memset(mcast, 0, 3402da834d52SDavid C Somayajulu (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN)); 3403da834d52SDavid C Somayajulu } 3404da834d52SDavid C Somayajulu 3405f10a77bbSDavid C Somayajulu nmcast--; 3406f10a77bbSDavid C Somayajulu } 3407f10a77bbSDavid C Somayajulu } 3408da834d52SDavid C Somayajulu 3409da834d52SDavid C Somayajulu if (count) { 3410da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mcast, 3411da834d52SDavid C Somayajulu count)) { 3412da834d52SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", __func__); 3413da834d52SDavid C Somayajulu return (-1); 3414da834d52SDavid C Somayajulu } 3415da834d52SDavid C Somayajulu } 3416da834d52SDavid C Somayajulu QL_DPRINT2(ha, (ha->pci_dev, 3417da834d52SDavid C Somayajulu "%s:[0x%x] exit nmcast = %d \n", __func__, add_mcast, nmcast)); 3418da834d52SDavid C Somayajulu 3419f10a77bbSDavid C Somayajulu return 0; 3420f10a77bbSDavid C Somayajulu } 3421f10a77bbSDavid C Somayajulu 3422f10a77bbSDavid C Somayajulu static int 3423da834d52SDavid C Somayajulu qla_hw_add_all_mcast(qla_host_t *ha) 3424da834d52SDavid C Somayajulu { 3425da834d52SDavid C Somayajulu int ret; 3426da834d52SDavid C Somayajulu 3427da834d52SDavid C Somayajulu ret = qla_hw_all_mcast(ha, 1); 3428da834d52SDavid C Somayajulu 3429da834d52SDavid C Somayajulu return (ret); 3430da834d52SDavid C Somayajulu } 3431da834d52SDavid C Somayajulu 343261fb8de9SDavid C Somayajulu int 3433f10a77bbSDavid C Somayajulu qla_hw_del_all_mcast(qla_host_t *ha) 3434f10a77bbSDavid C Somayajulu { 3435da834d52SDavid C Somayajulu int ret; 3436f10a77bbSDavid C Somayajulu 3437da834d52SDavid C Somayajulu ret = qla_hw_all_mcast(ha, 0); 3438f10a77bbSDavid C Somayajulu 3439da834d52SDavid C Somayajulu bzero(ha->hw.mcast, (sizeof (qla_mcast_t) * Q8_MAX_NUM_MULTICAST_ADDRS)); 3440da834d52SDavid C Somayajulu ha->hw.nmcast = 0; 3441f10a77bbSDavid C Somayajulu 3442da834d52SDavid C Somayajulu return (ret); 3443f10a77bbSDavid C Somayajulu } 3444f10a77bbSDavid C Somayajulu 3445f10a77bbSDavid C Somayajulu static int 3446da834d52SDavid C Somayajulu qla_hw_mac_addr_present(qla_host_t *ha, uint8_t *mta) 3447f10a77bbSDavid C Somayajulu { 3448f10a77bbSDavid C Somayajulu int i; 3449f10a77bbSDavid C Somayajulu 3450f10a77bbSDavid C Somayajulu for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) { 3451f10a77bbSDavid C Somayajulu if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) 3452da834d52SDavid C Somayajulu return (0); /* its been already added */ 3453f10a77bbSDavid C Somayajulu } 3454da834d52SDavid C Somayajulu return (-1); 3455da834d52SDavid C Somayajulu } 3456da834d52SDavid C Somayajulu 3457da834d52SDavid C Somayajulu static int 3458da834d52SDavid C Somayajulu qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast) 3459da834d52SDavid C Somayajulu { 3460da834d52SDavid C Somayajulu int i; 3461f10a77bbSDavid C Somayajulu 3462f10a77bbSDavid C Somayajulu for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) { 3463f10a77bbSDavid C Somayajulu 3464f10a77bbSDavid C Somayajulu if ((ha->hw.mcast[i].addr[0] == 0) && 3465f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[1] == 0) && 3466f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[2] == 0) && 3467f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[3] == 0) && 3468f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[4] == 0) && 3469f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[5] == 0)) { 3470f10a77bbSDavid C Somayajulu 3471f10a77bbSDavid C Somayajulu bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN); 3472f10a77bbSDavid C Somayajulu ha->hw.nmcast++; 3473f10a77bbSDavid C Somayajulu 3474da834d52SDavid C Somayajulu mta = mta + ETHER_ADDR_LEN; 3475da834d52SDavid C Somayajulu nmcast--; 3476da834d52SDavid C Somayajulu 3477da834d52SDavid C Somayajulu if (nmcast == 0) 3478da834d52SDavid C Somayajulu break; 3479f10a77bbSDavid C Somayajulu } 3480da834d52SDavid C Somayajulu 3481f10a77bbSDavid C Somayajulu } 3482f10a77bbSDavid C Somayajulu return 0; 3483f10a77bbSDavid C Somayajulu } 3484f10a77bbSDavid C Somayajulu 3485f10a77bbSDavid C Somayajulu static int 3486da834d52SDavid C Somayajulu qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta, uint32_t nmcast) 3487f10a77bbSDavid C Somayajulu { 3488f10a77bbSDavid C Somayajulu int i; 3489f10a77bbSDavid C Somayajulu 3490f10a77bbSDavid C Somayajulu for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) { 3491f10a77bbSDavid C Somayajulu if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) { 3492f10a77bbSDavid C Somayajulu 3493f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[0] = 0; 3494f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[1] = 0; 3495f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[2] = 0; 3496f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[3] = 0; 3497f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[4] = 0; 3498f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[5] = 0; 3499f10a77bbSDavid C Somayajulu 3500f10a77bbSDavid C Somayajulu ha->hw.nmcast--; 3501f10a77bbSDavid C Somayajulu 3502da834d52SDavid C Somayajulu mta = mta + ETHER_ADDR_LEN; 3503da834d52SDavid C Somayajulu nmcast--; 3504da834d52SDavid C Somayajulu 3505da834d52SDavid C Somayajulu if (nmcast == 0) 3506da834d52SDavid C Somayajulu break; 3507f10a77bbSDavid C Somayajulu } 3508f10a77bbSDavid C Somayajulu } 3509f10a77bbSDavid C Somayajulu return 0; 3510f10a77bbSDavid C Somayajulu } 3511f10a77bbSDavid C Somayajulu 3512f10a77bbSDavid C Somayajulu /* 3513f10a77bbSDavid C Somayajulu * Name: ql_hw_set_multi 3514da834d52SDavid C Somayajulu * Function: Sets the Multicast Addresses provided by the host O.S into the 3515f10a77bbSDavid C Somayajulu * hardware (for the given interface) 3516f10a77bbSDavid C Somayajulu */ 3517f10a77bbSDavid C Somayajulu int 3518da834d52SDavid C Somayajulu ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast_addr, uint32_t mcnt, 3519f10a77bbSDavid C Somayajulu uint32_t add_mac) 3520f10a77bbSDavid C Somayajulu { 3521da834d52SDavid C Somayajulu uint8_t *mta = mcast_addr; 3522f10a77bbSDavid C Somayajulu int i; 3523f10a77bbSDavid C Somayajulu int ret = 0; 3524da834d52SDavid C Somayajulu uint32_t count = 0; 3525da834d52SDavid C Somayajulu uint8_t *mcast; 3526da834d52SDavid C Somayajulu 3527da834d52SDavid C Somayajulu mcast = ha->hw.mac_addr_arr; 3528da834d52SDavid C Somayajulu memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN)); 3529f10a77bbSDavid C Somayajulu 3530f10a77bbSDavid C Somayajulu for (i = 0; i < mcnt; i++) { 3531da834d52SDavid C Somayajulu if (mta[0] || mta[1] || mta[2] || mta[3] || mta[4] || mta[5]) { 3532f10a77bbSDavid C Somayajulu if (add_mac) { 3533da834d52SDavid C Somayajulu if (qla_hw_mac_addr_present(ha, mta) != 0) { 3534da834d52SDavid C Somayajulu bcopy(mta, mcast, ETHER_ADDR_LEN); 3535da834d52SDavid C Somayajulu mcast = mcast + ETHER_ADDR_LEN; 3536da834d52SDavid C Somayajulu count++; 3537da834d52SDavid C Somayajulu } 3538f10a77bbSDavid C Somayajulu } else { 3539da834d52SDavid C Somayajulu if (qla_hw_mac_addr_present(ha, mta) == 0) { 3540da834d52SDavid C Somayajulu bcopy(mta, mcast, ETHER_ADDR_LEN); 3541da834d52SDavid C Somayajulu mcast = mcast + ETHER_ADDR_LEN; 3542da834d52SDavid C Somayajulu count++; 3543da834d52SDavid C Somayajulu } 3544da834d52SDavid C Somayajulu } 3545da834d52SDavid C Somayajulu } 3546da834d52SDavid C Somayajulu if (count == Q8_MAX_MAC_ADDRS) { 3547da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, 3548da834d52SDavid C Somayajulu add_mac, count)) { 3549da834d52SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", 3550da834d52SDavid C Somayajulu __func__); 3551da834d52SDavid C Somayajulu return (-1); 3552da834d52SDavid C Somayajulu } 3553da834d52SDavid C Somayajulu 3554da834d52SDavid C Somayajulu if (add_mac) { 3555da834d52SDavid C Somayajulu qla_hw_add_mcast(ha, ha->hw.mac_addr_arr, 3556da834d52SDavid C Somayajulu count); 3557da834d52SDavid C Somayajulu } else { 3558da834d52SDavid C Somayajulu qla_hw_del_mcast(ha, ha->hw.mac_addr_arr, 3559da834d52SDavid C Somayajulu count); 3560da834d52SDavid C Somayajulu } 3561da834d52SDavid C Somayajulu 3562da834d52SDavid C Somayajulu count = 0; 3563da834d52SDavid C Somayajulu mcast = ha->hw.mac_addr_arr; 3564da834d52SDavid C Somayajulu memset(mcast, 0, (Q8_MAX_MAC_ADDRS * ETHER_ADDR_LEN)); 3565f10a77bbSDavid C Somayajulu } 3566f10a77bbSDavid C Somayajulu 3567f10a77bbSDavid C Somayajulu mta += Q8_MAC_ADDR_LEN; 3568f10a77bbSDavid C Somayajulu } 3569da834d52SDavid C Somayajulu 3570da834d52SDavid C Somayajulu if (count) { 3571da834d52SDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr_arr, add_mac, 3572da834d52SDavid C Somayajulu count)) { 3573da834d52SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", __func__); 3574da834d52SDavid C Somayajulu return (-1); 3575da834d52SDavid C Somayajulu } 3576da834d52SDavid C Somayajulu if (add_mac) { 3577da834d52SDavid C Somayajulu qla_hw_add_mcast(ha, ha->hw.mac_addr_arr, count); 3578da834d52SDavid C Somayajulu } else { 3579da834d52SDavid C Somayajulu qla_hw_del_mcast(ha, ha->hw.mac_addr_arr, count); 3580da834d52SDavid C Somayajulu } 3581da834d52SDavid C Somayajulu } 3582da834d52SDavid C Somayajulu 3583f10a77bbSDavid C Somayajulu return (ret); 3584f10a77bbSDavid C Somayajulu } 3585f10a77bbSDavid C Somayajulu 3586f10a77bbSDavid C Somayajulu /* 3587b89f2279SDavid C Somayajulu * Name: ql_hw_tx_done_locked 3588f10a77bbSDavid C Somayajulu * Function: Handle Transmit Completions 3589f10a77bbSDavid C Somayajulu */ 3590b89f2279SDavid C Somayajulu void 3591b89f2279SDavid C Somayajulu ql_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx) 3592f10a77bbSDavid C Somayajulu { 3593f10a77bbSDavid C Somayajulu qla_tx_buf_t *txb; 3594f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 3595f10a77bbSDavid C Somayajulu uint32_t comp_idx, comp_count = 0; 3596f10a77bbSDavid C Somayajulu qla_hw_tx_cntxt_t *hw_tx_cntxt; 3597f10a77bbSDavid C Somayajulu 3598f10a77bbSDavid C Somayajulu hw_tx_cntxt = &hw->tx_cntxt[txr_idx]; 3599f10a77bbSDavid C Somayajulu 3600f10a77bbSDavid C Somayajulu /* retrieve index of last entry in tx ring completed */ 3601f10a77bbSDavid C Somayajulu comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons)); 3602f10a77bbSDavid C Somayajulu 3603f10a77bbSDavid C Somayajulu while (comp_idx != hw_tx_cntxt->txr_comp) { 3604f10a77bbSDavid C Somayajulu 3605f10a77bbSDavid C Somayajulu txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp]; 3606f10a77bbSDavid C Somayajulu 3607f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_comp++; 3608f10a77bbSDavid C Somayajulu if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS) 3609f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_comp = 0; 3610f10a77bbSDavid C Somayajulu 3611f10a77bbSDavid C Somayajulu comp_count++; 3612f10a77bbSDavid C Somayajulu 3613f10a77bbSDavid C Somayajulu if (txb->m_head) { 3614c8dfaf38SGleb Smirnoff if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1); 3615f10a77bbSDavid C Somayajulu 3616f10a77bbSDavid C Somayajulu bus_dmamap_sync(ha->tx_tag, txb->map, 3617f10a77bbSDavid C Somayajulu BUS_DMASYNC_POSTWRITE); 3618f10a77bbSDavid C Somayajulu bus_dmamap_unload(ha->tx_tag, txb->map); 3619f10a77bbSDavid C Somayajulu m_freem(txb->m_head); 3620f10a77bbSDavid C Somayajulu 3621f10a77bbSDavid C Somayajulu txb->m_head = NULL; 3622f10a77bbSDavid C Somayajulu } 3623f10a77bbSDavid C Somayajulu } 3624f10a77bbSDavid C Somayajulu 3625f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_free += comp_count; 3626f10a77bbSDavid C Somayajulu return; 3627f10a77bbSDavid C Somayajulu } 3628f10a77bbSDavid C Somayajulu 3629f10a77bbSDavid C Somayajulu void 3630f10a77bbSDavid C Somayajulu ql_update_link_state(qla_host_t *ha) 3631f10a77bbSDavid C Somayajulu { 3632f10a77bbSDavid C Somayajulu uint32_t link_state; 3633f10a77bbSDavid C Somayajulu uint32_t prev_link_state; 3634f10a77bbSDavid C Somayajulu 3635f10a77bbSDavid C Somayajulu if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) { 3636f10a77bbSDavid C Somayajulu ha->hw.link_up = 0; 3637f10a77bbSDavid C Somayajulu return; 3638f10a77bbSDavid C Somayajulu } 3639f10a77bbSDavid C Somayajulu link_state = READ_REG32(ha, Q8_LINK_STATE); 3640f10a77bbSDavid C Somayajulu 3641f10a77bbSDavid C Somayajulu prev_link_state = ha->hw.link_up; 3642f10a77bbSDavid C Somayajulu 3643f10a77bbSDavid C Somayajulu if (ha->pci_func == 0) 3644f10a77bbSDavid C Somayajulu ha->hw.link_up = (((link_state & 0xF) == 1)? 1 : 0); 3645f10a77bbSDavid C Somayajulu else 3646f10a77bbSDavid C Somayajulu ha->hw.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0); 3647f10a77bbSDavid C Somayajulu 3648f10a77bbSDavid C Somayajulu if (prev_link_state != ha->hw.link_up) { 3649f10a77bbSDavid C Somayajulu if (ha->hw.link_up) { 3650f10a77bbSDavid C Somayajulu if_link_state_change(ha->ifp, LINK_STATE_UP); 3651f10a77bbSDavid C Somayajulu } else { 3652f10a77bbSDavid C Somayajulu if_link_state_change(ha->ifp, LINK_STATE_DOWN); 3653f10a77bbSDavid C Somayajulu } 3654f10a77bbSDavid C Somayajulu } 3655f10a77bbSDavid C Somayajulu return; 3656f10a77bbSDavid C Somayajulu } 3657f10a77bbSDavid C Somayajulu 3658f10a77bbSDavid C Somayajulu int 3659f10a77bbSDavid C Somayajulu ql_hw_check_health(qla_host_t *ha) 3660f10a77bbSDavid C Somayajulu { 3661f10a77bbSDavid C Somayajulu uint32_t val; 3662f10a77bbSDavid C Somayajulu 3663f10a77bbSDavid C Somayajulu ha->hw.health_count++; 3664f10a77bbSDavid C Somayajulu 366512e46badSDavid C Somayajulu if (ha->hw.health_count < 500) 3666f10a77bbSDavid C Somayajulu return 0; 3667f10a77bbSDavid C Somayajulu 3668f10a77bbSDavid C Somayajulu ha->hw.health_count = 0; 3669f10a77bbSDavid C Somayajulu 3670f10a77bbSDavid C Somayajulu val = READ_REG32(ha, Q8_ASIC_TEMPERATURE); 3671f10a77bbSDavid C Somayajulu 3672f10a77bbSDavid C Somayajulu if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) || 3673f10a77bbSDavid C Somayajulu (QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) { 3674f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: Temperature Alert [0x%08x]\n", 3675f10a77bbSDavid C Somayajulu __func__, val); 3676f10a77bbSDavid C Somayajulu return -1; 3677f10a77bbSDavid C Somayajulu } 3678f10a77bbSDavid C Somayajulu 3679f10a77bbSDavid C Somayajulu val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT); 3680f10a77bbSDavid C Somayajulu 3681f10a77bbSDavid C Somayajulu if ((val != ha->hw.hbeat_value) && 3682467dcb5aSDavid C Somayajulu (!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) { 3683f10a77bbSDavid C Somayajulu ha->hw.hbeat_value = val; 368412e46badSDavid C Somayajulu ha->hw.hbeat_failure = 0; 3685f10a77bbSDavid C Somayajulu return 0; 3686f10a77bbSDavid C Somayajulu } 368712e46badSDavid C Somayajulu 368812e46badSDavid C Somayajulu ha->hw.hbeat_failure++; 368912e46badSDavid C Somayajulu 36907fb51846SDavid C Somayajulu 36917fb51846SDavid C Somayajulu if ((ha->dbg_level & 0x8000) && (ha->hw.hbeat_failure == 1)) 36927fb51846SDavid C Somayajulu device_printf(ha->pci_dev, "%s: Heartbeat Failue 1[0x%08x]\n", 36937fb51846SDavid C Somayajulu __func__, val); 369412e46badSDavid C Somayajulu if (ha->hw.hbeat_failure < 2) /* we ignore the first failure */ 369512e46badSDavid C Somayajulu return 0; 369612e46badSDavid C Somayajulu else 3697f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: Heartbeat Failue [0x%08x]\n", 3698f10a77bbSDavid C Somayajulu __func__, val); 3699f10a77bbSDavid C Somayajulu 3700f10a77bbSDavid C Somayajulu return -1; 3701f10a77bbSDavid C Somayajulu } 3702f10a77bbSDavid C Somayajulu 3703f10a77bbSDavid C Somayajulu static int 370435291c22SDavid C Somayajulu qla_init_nic_func(qla_host_t *ha) 370535291c22SDavid C Somayajulu { 370635291c22SDavid C Somayajulu device_t dev; 370735291c22SDavid C Somayajulu q80_init_nic_func_t *init_nic; 370835291c22SDavid C Somayajulu q80_init_nic_func_rsp_t *init_nic_rsp; 370935291c22SDavid C Somayajulu uint32_t err; 371035291c22SDavid C Somayajulu 371135291c22SDavid C Somayajulu dev = ha->pci_dev; 371235291c22SDavid C Somayajulu 371335291c22SDavid C Somayajulu init_nic = (q80_init_nic_func_t *)ha->hw.mbox; 371435291c22SDavid C Somayajulu bzero(init_nic, sizeof(q80_init_nic_func_t)); 371535291c22SDavid C Somayajulu 371635291c22SDavid C Somayajulu init_nic->opcode = Q8_MBX_INIT_NIC_FUNC; 371735291c22SDavid C Somayajulu init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2); 371835291c22SDavid C Somayajulu init_nic->count_version |= Q8_MBX_CMD_VERSION; 371935291c22SDavid C Somayajulu 372035291c22SDavid C Somayajulu init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN; 372135291c22SDavid C Somayajulu init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN; 372235291c22SDavid C Somayajulu init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN; 372335291c22SDavid C Somayajulu 372435291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t)); 372535291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)init_nic, 372635291c22SDavid C Somayajulu (sizeof (q80_init_nic_func_t) >> 2), 372735291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) { 372835291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 372935291c22SDavid C Somayajulu return -1; 373035291c22SDavid C Somayajulu } 373135291c22SDavid C Somayajulu 373235291c22SDavid C Somayajulu init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox; 373335291c22SDavid C Somayajulu // qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t)); 373435291c22SDavid C Somayajulu 373535291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status); 373635291c22SDavid C Somayajulu 373735291c22SDavid C Somayajulu if (err) { 373835291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 373935291c22SDavid C Somayajulu } 374035291c22SDavid C Somayajulu 374135291c22SDavid C Somayajulu return 0; 374235291c22SDavid C Somayajulu } 374335291c22SDavid C Somayajulu 374435291c22SDavid C Somayajulu static int 374535291c22SDavid C Somayajulu qla_stop_nic_func(qla_host_t *ha) 374635291c22SDavid C Somayajulu { 374735291c22SDavid C Somayajulu device_t dev; 374835291c22SDavid C Somayajulu q80_stop_nic_func_t *stop_nic; 374935291c22SDavid C Somayajulu q80_stop_nic_func_rsp_t *stop_nic_rsp; 375035291c22SDavid C Somayajulu uint32_t err; 375135291c22SDavid C Somayajulu 375235291c22SDavid C Somayajulu dev = ha->pci_dev; 375335291c22SDavid C Somayajulu 375435291c22SDavid C Somayajulu stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox; 375535291c22SDavid C Somayajulu bzero(stop_nic, sizeof(q80_stop_nic_func_t)); 375635291c22SDavid C Somayajulu 375735291c22SDavid C Somayajulu stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC; 375835291c22SDavid C Somayajulu stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2); 375935291c22SDavid C Somayajulu stop_nic->count_version |= Q8_MBX_CMD_VERSION; 376035291c22SDavid C Somayajulu 376135291c22SDavid C Somayajulu stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN; 376235291c22SDavid C Somayajulu stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN; 376335291c22SDavid C Somayajulu 376435291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t)); 376535291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)stop_nic, 376635291c22SDavid C Somayajulu (sizeof (q80_stop_nic_func_t) >> 2), 376735291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) { 376835291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 376935291c22SDavid C Somayajulu return -1; 377035291c22SDavid C Somayajulu } 377135291c22SDavid C Somayajulu 377235291c22SDavid C Somayajulu stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox; 377335291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t)); 377435291c22SDavid C Somayajulu 377535291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status); 377635291c22SDavid C Somayajulu 377735291c22SDavid C Somayajulu if (err) { 377835291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 377935291c22SDavid C Somayajulu } 378035291c22SDavid C Somayajulu 378135291c22SDavid C Somayajulu return 0; 378235291c22SDavid C Somayajulu } 378335291c22SDavid C Somayajulu 378435291c22SDavid C Somayajulu static int 378535291c22SDavid C Somayajulu qla_query_fw_dcbx_caps(qla_host_t *ha) 378635291c22SDavid C Somayajulu { 378735291c22SDavid C Somayajulu device_t dev; 378835291c22SDavid C Somayajulu q80_query_fw_dcbx_caps_t *fw_dcbx; 378935291c22SDavid C Somayajulu q80_query_fw_dcbx_caps_rsp_t *fw_dcbx_rsp; 379035291c22SDavid C Somayajulu uint32_t err; 379135291c22SDavid C Somayajulu 379235291c22SDavid C Somayajulu dev = ha->pci_dev; 379335291c22SDavid C Somayajulu 379435291c22SDavid C Somayajulu fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox; 379535291c22SDavid C Somayajulu bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t)); 379635291c22SDavid C Somayajulu 379735291c22SDavid C Somayajulu fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS; 379835291c22SDavid C Somayajulu fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2); 379935291c22SDavid C Somayajulu fw_dcbx->count_version |= Q8_MBX_CMD_VERSION; 380035291c22SDavid C Somayajulu 380135291c22SDavid C Somayajulu ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t)); 380235291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx, 380335291c22SDavid C Somayajulu (sizeof (q80_query_fw_dcbx_caps_t) >> 2), 380435291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) { 380535291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 380635291c22SDavid C Somayajulu return -1; 380735291c22SDavid C Somayajulu } 380835291c22SDavid C Somayajulu 380935291c22SDavid C Somayajulu fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox; 381035291c22SDavid C Somayajulu ql_dump_buf8(ha, __func__, fw_dcbx_rsp, 381135291c22SDavid C Somayajulu sizeof (q80_query_fw_dcbx_caps_rsp_t)); 381235291c22SDavid C Somayajulu 381335291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status); 381435291c22SDavid C Somayajulu 381535291c22SDavid C Somayajulu if (err) { 381635291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 381735291c22SDavid C Somayajulu } 381835291c22SDavid C Somayajulu 381935291c22SDavid C Somayajulu return 0; 382035291c22SDavid C Somayajulu } 382135291c22SDavid C Somayajulu 382235291c22SDavid C Somayajulu static int 382335291c22SDavid C Somayajulu qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2, 382435291c22SDavid C Somayajulu uint32_t aen_mb3, uint32_t aen_mb4) 382535291c22SDavid C Somayajulu { 382635291c22SDavid C Somayajulu device_t dev; 382735291c22SDavid C Somayajulu q80_idc_ack_t *idc_ack; 382835291c22SDavid C Somayajulu q80_idc_ack_rsp_t *idc_ack_rsp; 382935291c22SDavid C Somayajulu uint32_t err; 383035291c22SDavid C Somayajulu int count = 300; 383135291c22SDavid C Somayajulu 383235291c22SDavid C Somayajulu dev = ha->pci_dev; 383335291c22SDavid C Somayajulu 383435291c22SDavid C Somayajulu idc_ack = (q80_idc_ack_t *)ha->hw.mbox; 383535291c22SDavid C Somayajulu bzero(idc_ack, sizeof(q80_idc_ack_t)); 383635291c22SDavid C Somayajulu 383735291c22SDavid C Somayajulu idc_ack->opcode = Q8_MBX_IDC_ACK; 383835291c22SDavid C Somayajulu idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2); 383935291c22SDavid C Somayajulu idc_ack->count_version |= Q8_MBX_CMD_VERSION; 384035291c22SDavid C Somayajulu 384135291c22SDavid C Somayajulu idc_ack->aen_mb1 = aen_mb1; 384235291c22SDavid C Somayajulu idc_ack->aen_mb2 = aen_mb2; 384335291c22SDavid C Somayajulu idc_ack->aen_mb3 = aen_mb3; 384435291c22SDavid C Somayajulu idc_ack->aen_mb4 = aen_mb4; 384535291c22SDavid C Somayajulu 384635291c22SDavid C Somayajulu ha->hw.imd_compl= 0; 384735291c22SDavid C Somayajulu 384835291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)idc_ack, 384935291c22SDavid C Somayajulu (sizeof (q80_idc_ack_t) >> 2), 385035291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) { 385135291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 385235291c22SDavid C Somayajulu return -1; 385335291c22SDavid C Somayajulu } 385435291c22SDavid C Somayajulu 385535291c22SDavid C Somayajulu idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox; 385635291c22SDavid C Somayajulu 385735291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status); 385835291c22SDavid C Somayajulu 385935291c22SDavid C Somayajulu if (err) { 386035291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 386135291c22SDavid C Somayajulu return(-1); 386235291c22SDavid C Somayajulu } 386335291c22SDavid C Somayajulu 386435291c22SDavid C Somayajulu while (count && !ha->hw.imd_compl) { 386535291c22SDavid C Somayajulu qla_mdelay(__func__, 100); 386635291c22SDavid C Somayajulu count--; 386735291c22SDavid C Somayajulu } 386835291c22SDavid C Somayajulu 386935291c22SDavid C Somayajulu if (!count) 387035291c22SDavid C Somayajulu return -1; 387135291c22SDavid C Somayajulu else 387235291c22SDavid C Somayajulu device_printf(dev, "%s: count %d\n", __func__, count); 387335291c22SDavid C Somayajulu 387435291c22SDavid C Somayajulu return (0); 387535291c22SDavid C Somayajulu } 387635291c22SDavid C Somayajulu 387735291c22SDavid C Somayajulu static int 387835291c22SDavid C Somayajulu qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits) 387935291c22SDavid C Somayajulu { 388035291c22SDavid C Somayajulu device_t dev; 388135291c22SDavid C Somayajulu q80_set_port_cfg_t *pcfg; 388235291c22SDavid C Somayajulu q80_set_port_cfg_rsp_t *pfg_rsp; 388335291c22SDavid C Somayajulu uint32_t err; 388435291c22SDavid C Somayajulu int count = 300; 388535291c22SDavid C Somayajulu 388635291c22SDavid C Somayajulu dev = ha->pci_dev; 388735291c22SDavid C Somayajulu 388835291c22SDavid C Somayajulu pcfg = (q80_set_port_cfg_t *)ha->hw.mbox; 388935291c22SDavid C Somayajulu bzero(pcfg, sizeof(q80_set_port_cfg_t)); 389035291c22SDavid C Somayajulu 389135291c22SDavid C Somayajulu pcfg->opcode = Q8_MBX_SET_PORT_CONFIG; 389235291c22SDavid C Somayajulu pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2); 389335291c22SDavid C Somayajulu pcfg->count_version |= Q8_MBX_CMD_VERSION; 389435291c22SDavid C Somayajulu 389535291c22SDavid C Somayajulu pcfg->cfg_bits = cfg_bits; 389635291c22SDavid C Somayajulu 389735291c22SDavid C Somayajulu device_printf(dev, "%s: cfg_bits" 389835291c22SDavid C Somayajulu " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]" 389935291c22SDavid C Somayajulu " [0x%x, 0x%x, 0x%x]\n", __func__, 390035291c22SDavid C Somayajulu ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20), 390135291c22SDavid C Somayajulu ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5), 390235291c22SDavid C Somayajulu ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)); 390335291c22SDavid C Somayajulu 390435291c22SDavid C Somayajulu ha->hw.imd_compl= 0; 390535291c22SDavid C Somayajulu 390635291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)pcfg, 390735291c22SDavid C Somayajulu (sizeof (q80_set_port_cfg_t) >> 2), 390835291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) { 390935291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 391035291c22SDavid C Somayajulu return -1; 391135291c22SDavid C Somayajulu } 391235291c22SDavid C Somayajulu 391335291c22SDavid C Somayajulu pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox; 391435291c22SDavid C Somayajulu 391535291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status); 391635291c22SDavid C Somayajulu 391735291c22SDavid C Somayajulu if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) { 391835291c22SDavid C Somayajulu while (count && !ha->hw.imd_compl) { 391935291c22SDavid C Somayajulu qla_mdelay(__func__, 100); 392035291c22SDavid C Somayajulu count--; 392135291c22SDavid C Somayajulu } 392235291c22SDavid C Somayajulu if (count) { 392335291c22SDavid C Somayajulu device_printf(dev, "%s: count %d\n", __func__, count); 392435291c22SDavid C Somayajulu 392535291c22SDavid C Somayajulu err = 0; 392635291c22SDavid C Somayajulu } 392735291c22SDavid C Somayajulu } 392835291c22SDavid C Somayajulu 392935291c22SDavid C Somayajulu if (err) { 393035291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 393135291c22SDavid C Somayajulu return(-1); 393235291c22SDavid C Somayajulu } 393335291c22SDavid C Somayajulu 393435291c22SDavid C Somayajulu return (0); 393535291c22SDavid C Somayajulu } 393635291c22SDavid C Somayajulu 393735291c22SDavid C Somayajulu 393835291c22SDavid C Somayajulu static int 3939f10a77bbSDavid C Somayajulu qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size) 3940f10a77bbSDavid C Somayajulu { 3941f10a77bbSDavid C Somayajulu uint32_t err; 3942f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 3943f10a77bbSDavid C Somayajulu q80_config_md_templ_size_t *md_size; 3944f10a77bbSDavid C Somayajulu q80_config_md_templ_size_rsp_t *md_size_rsp; 3945f10a77bbSDavid C Somayajulu 39466a62bec0SDavid C Somayajulu #ifndef QL_LDFLASH_FW 394735291c22SDavid C Somayajulu 39486a62bec0SDavid C Somayajulu ql_minidump_template_hdr_t *hdr; 39496a62bec0SDavid C Somayajulu 39506a62bec0SDavid C Somayajulu hdr = (ql_minidump_template_hdr_t *)ql83xx_minidump; 39516a62bec0SDavid C Somayajulu *size = hdr->size_of_template; 395235291c22SDavid C Somayajulu return (0); 395335291c22SDavid C Somayajulu 395435291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */ 395535291c22SDavid C Somayajulu 3956f10a77bbSDavid C Somayajulu md_size = (q80_config_md_templ_size_t *) ha->hw.mbox; 3957f10a77bbSDavid C Somayajulu bzero(md_size, sizeof(q80_config_md_templ_size_t)); 3958f10a77bbSDavid C Somayajulu 3959f10a77bbSDavid C Somayajulu md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE; 3960f10a77bbSDavid C Somayajulu md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2); 3961f10a77bbSDavid C Somayajulu md_size->count_version |= Q8_MBX_CMD_VERSION; 3962f10a77bbSDavid C Somayajulu 3963f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *) md_size, 3964f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox, 3965f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) { 3966f10a77bbSDavid C Somayajulu 3967f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 3968f10a77bbSDavid C Somayajulu 3969f10a77bbSDavid C Somayajulu return (-1); 3970f10a77bbSDavid C Somayajulu } 3971f10a77bbSDavid C Somayajulu 3972f10a77bbSDavid C Somayajulu md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox; 3973f10a77bbSDavid C Somayajulu 3974f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status); 3975f10a77bbSDavid C Somayajulu 3976f10a77bbSDavid C Somayajulu if (err) { 3977f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 3978f10a77bbSDavid C Somayajulu return(-1); 3979f10a77bbSDavid C Somayajulu } 3980f10a77bbSDavid C Somayajulu 3981f10a77bbSDavid C Somayajulu *size = md_size_rsp->templ_size; 3982f10a77bbSDavid C Somayajulu 3983f10a77bbSDavid C Somayajulu return (0); 3984f10a77bbSDavid C Somayajulu } 3985f10a77bbSDavid C Somayajulu 3986f10a77bbSDavid C Somayajulu static int 398735291c22SDavid C Somayajulu qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits) 398835291c22SDavid C Somayajulu { 398935291c22SDavid C Somayajulu device_t dev; 399035291c22SDavid C Somayajulu q80_get_port_cfg_t *pcfg; 399135291c22SDavid C Somayajulu q80_get_port_cfg_rsp_t *pcfg_rsp; 399235291c22SDavid C Somayajulu uint32_t err; 399335291c22SDavid C Somayajulu 399435291c22SDavid C Somayajulu dev = ha->pci_dev; 399535291c22SDavid C Somayajulu 399635291c22SDavid C Somayajulu pcfg = (q80_get_port_cfg_t *)ha->hw.mbox; 399735291c22SDavid C Somayajulu bzero(pcfg, sizeof(q80_get_port_cfg_t)); 399835291c22SDavid C Somayajulu 399935291c22SDavid C Somayajulu pcfg->opcode = Q8_MBX_GET_PORT_CONFIG; 400035291c22SDavid C Somayajulu pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2); 400135291c22SDavid C Somayajulu pcfg->count_version |= Q8_MBX_CMD_VERSION; 400235291c22SDavid C Somayajulu 400335291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)pcfg, 400435291c22SDavid C Somayajulu (sizeof (q80_get_port_cfg_t) >> 2), 400535291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) { 400635291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 400735291c22SDavid C Somayajulu return -1; 400835291c22SDavid C Somayajulu } 400935291c22SDavid C Somayajulu 401035291c22SDavid C Somayajulu pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox; 401135291c22SDavid C Somayajulu 401235291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status); 401335291c22SDavid C Somayajulu 401435291c22SDavid C Somayajulu if (err) { 401535291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 401635291c22SDavid C Somayajulu return(-1); 401735291c22SDavid C Somayajulu } 401835291c22SDavid C Somayajulu 401935291c22SDavid C Somayajulu device_printf(dev, "%s: [cfg_bits, port type]" 402035291c22SDavid C Somayajulu " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]" 402135291c22SDavid C Somayajulu " [0x%x, 0x%x, 0x%x]\n", __func__, 402235291c22SDavid C Somayajulu pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type, 402335291c22SDavid C Somayajulu ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20), 402435291c22SDavid C Somayajulu ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5), 402535291c22SDavid C Somayajulu ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0) 402635291c22SDavid C Somayajulu ); 402735291c22SDavid C Somayajulu 402835291c22SDavid C Somayajulu *cfg_bits = pcfg_rsp->cfg_bits; 402935291c22SDavid C Somayajulu 403035291c22SDavid C Somayajulu return (0); 403135291c22SDavid C Somayajulu } 403235291c22SDavid C Somayajulu 403335291c22SDavid C Somayajulu int 4034b89f2279SDavid C Somayajulu ql_iscsi_pdu(qla_host_t *ha, struct mbuf *mp) 403535291c22SDavid C Somayajulu { 403635291c22SDavid C Somayajulu struct ether_vlan_header *eh; 403735291c22SDavid C Somayajulu uint16_t etype; 403835291c22SDavid C Somayajulu struct ip *ip = NULL; 403935291c22SDavid C Somayajulu struct ip6_hdr *ip6 = NULL; 404035291c22SDavid C Somayajulu struct tcphdr *th = NULL; 404135291c22SDavid C Somayajulu uint32_t hdrlen; 404235291c22SDavid C Somayajulu uint32_t offset; 404335291c22SDavid C Somayajulu uint8_t buf[sizeof(struct ip6_hdr)]; 404435291c22SDavid C Somayajulu 404535291c22SDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *); 404635291c22SDavid C Somayajulu 404735291c22SDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 404835291c22SDavid C Somayajulu hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 404935291c22SDavid C Somayajulu etype = ntohs(eh->evl_proto); 405035291c22SDavid C Somayajulu } else { 405135291c22SDavid C Somayajulu hdrlen = ETHER_HDR_LEN; 405235291c22SDavid C Somayajulu etype = ntohs(eh->evl_encap_proto); 405335291c22SDavid C Somayajulu } 405435291c22SDavid C Somayajulu 405535291c22SDavid C Somayajulu if (etype == ETHERTYPE_IP) { 405635291c22SDavid C Somayajulu 405735291c22SDavid C Somayajulu offset = (hdrlen + sizeof (struct ip)); 405835291c22SDavid C Somayajulu 405935291c22SDavid C Somayajulu if (mp->m_len >= offset) { 406035291c22SDavid C Somayajulu ip = (struct ip *)(mp->m_data + hdrlen); 406135291c22SDavid C Somayajulu } else { 406235291c22SDavid C Somayajulu m_copydata(mp, hdrlen, sizeof (struct ip), buf); 406335291c22SDavid C Somayajulu ip = (struct ip *)buf; 406435291c22SDavid C Somayajulu } 406535291c22SDavid C Somayajulu 406635291c22SDavid C Somayajulu if (ip->ip_p == IPPROTO_TCP) { 406735291c22SDavid C Somayajulu 406835291c22SDavid C Somayajulu hdrlen += ip->ip_hl << 2; 406935291c22SDavid C Somayajulu offset = hdrlen + 4; 407035291c22SDavid C Somayajulu 407135291c22SDavid C Somayajulu if (mp->m_len >= offset) { 40726a62bec0SDavid C Somayajulu th = (struct tcphdr *)(mp->m_data + hdrlen);; 407335291c22SDavid C Somayajulu } else { 407435291c22SDavid C Somayajulu m_copydata(mp, hdrlen, 4, buf); 407535291c22SDavid C Somayajulu th = (struct tcphdr *)buf; 407635291c22SDavid C Somayajulu } 407735291c22SDavid C Somayajulu } 407835291c22SDavid C Somayajulu 407935291c22SDavid C Somayajulu } else if (etype == ETHERTYPE_IPV6) { 408035291c22SDavid C Somayajulu 408135291c22SDavid C Somayajulu offset = (hdrlen + sizeof (struct ip6_hdr)); 408235291c22SDavid C Somayajulu 408335291c22SDavid C Somayajulu if (mp->m_len >= offset) { 408435291c22SDavid C Somayajulu ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen); 408535291c22SDavid C Somayajulu } else { 408635291c22SDavid C Somayajulu m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf); 408735291c22SDavid C Somayajulu ip6 = (struct ip6_hdr *)buf; 408835291c22SDavid C Somayajulu } 408935291c22SDavid C Somayajulu 409035291c22SDavid C Somayajulu if (ip6->ip6_nxt == IPPROTO_TCP) { 409135291c22SDavid C Somayajulu 409235291c22SDavid C Somayajulu hdrlen += sizeof(struct ip6_hdr); 409335291c22SDavid C Somayajulu offset = hdrlen + 4; 409435291c22SDavid C Somayajulu 409535291c22SDavid C Somayajulu if (mp->m_len >= offset) { 40966a62bec0SDavid C Somayajulu th = (struct tcphdr *)(mp->m_data + hdrlen);; 409735291c22SDavid C Somayajulu } else { 409835291c22SDavid C Somayajulu m_copydata(mp, hdrlen, 4, buf); 409935291c22SDavid C Somayajulu th = (struct tcphdr *)buf; 410035291c22SDavid C Somayajulu } 410135291c22SDavid C Somayajulu } 410235291c22SDavid C Somayajulu } 410335291c22SDavid C Somayajulu 410435291c22SDavid C Somayajulu if (th != NULL) { 410535291c22SDavid C Somayajulu if ((th->th_sport == htons(3260)) || 410635291c22SDavid C Somayajulu (th->th_dport == htons(3260))) 410735291c22SDavid C Somayajulu return 0; 410835291c22SDavid C Somayajulu } 410935291c22SDavid C Somayajulu return (-1); 411035291c22SDavid C Somayajulu } 411135291c22SDavid C Somayajulu 411235291c22SDavid C Somayajulu void 411335291c22SDavid C Somayajulu qla_hw_async_event(qla_host_t *ha) 411435291c22SDavid C Somayajulu { 411535291c22SDavid C Somayajulu switch (ha->hw.aen_mb0) { 411635291c22SDavid C Somayajulu case 0x8101: 411735291c22SDavid C Somayajulu (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2, 411835291c22SDavid C Somayajulu ha->hw.aen_mb3, ha->hw.aen_mb4); 411935291c22SDavid C Somayajulu 412035291c22SDavid C Somayajulu break; 412135291c22SDavid C Somayajulu 412235291c22SDavid C Somayajulu default: 412335291c22SDavid C Somayajulu break; 412435291c22SDavid C Somayajulu } 412535291c22SDavid C Somayajulu 412635291c22SDavid C Somayajulu return; 412735291c22SDavid C Somayajulu } 412835291c22SDavid C Somayajulu 412935291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW 413035291c22SDavid C Somayajulu static int 41316a62bec0SDavid C Somayajulu ql_get_minidump_template(qla_host_t *ha) 4132f10a77bbSDavid C Somayajulu { 4133f10a77bbSDavid C Somayajulu uint32_t err; 4134f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 4135f10a77bbSDavid C Somayajulu q80_config_md_templ_cmd_t *md_templ; 4136f10a77bbSDavid C Somayajulu q80_config_md_templ_cmd_rsp_t *md_templ_rsp; 4137f10a77bbSDavid C Somayajulu 4138f10a77bbSDavid C Somayajulu md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox; 4139f10a77bbSDavid C Somayajulu bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t))); 4140f10a77bbSDavid C Somayajulu 4141f10a77bbSDavid C Somayajulu md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT; 4142f10a77bbSDavid C Somayajulu md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2); 4143f10a77bbSDavid C Somayajulu md_templ->count_version |= Q8_MBX_CMD_VERSION; 4144f10a77bbSDavid C Somayajulu 4145f10a77bbSDavid C Somayajulu md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr; 4146f10a77bbSDavid C Somayajulu md_templ->buff_size = ha->hw.dma_buf.minidump.size; 4147f10a77bbSDavid C Somayajulu 4148f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *) md_templ, 4149f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_cmd_t) >> 2), 4150f10a77bbSDavid C Somayajulu ha->hw.mbox, 4151f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) { 4152f10a77bbSDavid C Somayajulu 4153f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 4154f10a77bbSDavid C Somayajulu 4155f10a77bbSDavid C Somayajulu return (-1); 4156f10a77bbSDavid C Somayajulu } 4157f10a77bbSDavid C Somayajulu 4158f10a77bbSDavid C Somayajulu md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox; 4159f10a77bbSDavid C Somayajulu 4160f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status); 4161f10a77bbSDavid C Somayajulu 4162f10a77bbSDavid C Somayajulu if (err) { 4163f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 4164f10a77bbSDavid C Somayajulu return (-1); 4165f10a77bbSDavid C Somayajulu } 4166f10a77bbSDavid C Somayajulu 4167f10a77bbSDavid C Somayajulu return (0); 4168f10a77bbSDavid C Somayajulu 4169f10a77bbSDavid C Somayajulu } 417035291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */ 4171f10a77bbSDavid C Somayajulu 41726a62bec0SDavid C Somayajulu /* 41736a62bec0SDavid C Somayajulu * Minidump related functionality 41746a62bec0SDavid C Somayajulu */ 41756a62bec0SDavid C Somayajulu 41766a62bec0SDavid C Somayajulu static int ql_parse_template(qla_host_t *ha); 41776a62bec0SDavid C Somayajulu 41786a62bec0SDavid C Somayajulu static uint32_t ql_rdcrb(qla_host_t *ha, 41796a62bec0SDavid C Somayajulu ql_minidump_entry_rdcrb_t *crb_entry, 41806a62bec0SDavid C Somayajulu uint32_t * data_buff); 41816a62bec0SDavid C Somayajulu 41826a62bec0SDavid C Somayajulu static uint32_t ql_pollrd(qla_host_t *ha, 41836a62bec0SDavid C Somayajulu ql_minidump_entry_pollrd_t *entry, 41846a62bec0SDavid C Somayajulu uint32_t * data_buff); 41856a62bec0SDavid C Somayajulu 41866a62bec0SDavid C Somayajulu static uint32_t ql_pollrd_modify_write(qla_host_t *ha, 41876a62bec0SDavid C Somayajulu ql_minidump_entry_rd_modify_wr_with_poll_t *entry, 41886a62bec0SDavid C Somayajulu uint32_t *data_buff); 41896a62bec0SDavid C Somayajulu 41906a62bec0SDavid C Somayajulu static uint32_t ql_L2Cache(qla_host_t *ha, 41916a62bec0SDavid C Somayajulu ql_minidump_entry_cache_t *cacheEntry, 41926a62bec0SDavid C Somayajulu uint32_t * data_buff); 41936a62bec0SDavid C Somayajulu 41946a62bec0SDavid C Somayajulu static uint32_t ql_L1Cache(qla_host_t *ha, 41956a62bec0SDavid C Somayajulu ql_minidump_entry_cache_t *cacheEntry, 41966a62bec0SDavid C Somayajulu uint32_t *data_buff); 41976a62bec0SDavid C Somayajulu 41986a62bec0SDavid C Somayajulu static uint32_t ql_rdocm(qla_host_t *ha, 41996a62bec0SDavid C Somayajulu ql_minidump_entry_rdocm_t *ocmEntry, 42006a62bec0SDavid C Somayajulu uint32_t *data_buff); 42016a62bec0SDavid C Somayajulu 42026a62bec0SDavid C Somayajulu static uint32_t ql_rdmem(qla_host_t *ha, 42036a62bec0SDavid C Somayajulu ql_minidump_entry_rdmem_t *mem_entry, 42046a62bec0SDavid C Somayajulu uint32_t *data_buff); 42056a62bec0SDavid C Somayajulu 42066a62bec0SDavid C Somayajulu static uint32_t ql_rdrom(qla_host_t *ha, 42076a62bec0SDavid C Somayajulu ql_minidump_entry_rdrom_t *romEntry, 42086a62bec0SDavid C Somayajulu uint32_t *data_buff); 42096a62bec0SDavid C Somayajulu 42106a62bec0SDavid C Somayajulu static uint32_t ql_rdmux(qla_host_t *ha, 42116a62bec0SDavid C Somayajulu ql_minidump_entry_mux_t *muxEntry, 42126a62bec0SDavid C Somayajulu uint32_t *data_buff); 42136a62bec0SDavid C Somayajulu 42146a62bec0SDavid C Somayajulu static uint32_t ql_rdmux2(qla_host_t *ha, 42156a62bec0SDavid C Somayajulu ql_minidump_entry_mux2_t *muxEntry, 42166a62bec0SDavid C Somayajulu uint32_t *data_buff); 42176a62bec0SDavid C Somayajulu 42186a62bec0SDavid C Somayajulu static uint32_t ql_rdqueue(qla_host_t *ha, 42196a62bec0SDavid C Somayajulu ql_minidump_entry_queue_t *queueEntry, 42206a62bec0SDavid C Somayajulu uint32_t *data_buff); 42216a62bec0SDavid C Somayajulu 42226a62bec0SDavid C Somayajulu static uint32_t ql_cntrl(qla_host_t *ha, 42236a62bec0SDavid C Somayajulu ql_minidump_template_hdr_t *template_hdr, 42246a62bec0SDavid C Somayajulu ql_minidump_entry_cntrl_t *crbEntry); 42256a62bec0SDavid C Somayajulu 42266a62bec0SDavid C Somayajulu 42276a62bec0SDavid C Somayajulu static uint32_t 42286a62bec0SDavid C Somayajulu ql_minidump_size(qla_host_t *ha) 42296a62bec0SDavid C Somayajulu { 42306a62bec0SDavid C Somayajulu uint32_t i, k; 42316a62bec0SDavid C Somayajulu uint32_t size = 0; 42326a62bec0SDavid C Somayajulu ql_minidump_template_hdr_t *hdr; 42336a62bec0SDavid C Somayajulu 42346a62bec0SDavid C Somayajulu hdr = (ql_minidump_template_hdr_t *)ha->hw.dma_buf.minidump.dma_b; 42356a62bec0SDavid C Somayajulu 42366a62bec0SDavid C Somayajulu i = 0x2; 42376a62bec0SDavid C Somayajulu 42386a62bec0SDavid C Somayajulu for (k = 1; k < QL_DBG_CAP_SIZE_ARRAY_LEN; k++) { 42396a62bec0SDavid C Somayajulu if (i & ha->hw.mdump_capture_mask) 42406a62bec0SDavid C Somayajulu size += hdr->capture_size_array[k]; 42416a62bec0SDavid C Somayajulu i = i << 1; 42426a62bec0SDavid C Somayajulu } 42436a62bec0SDavid C Somayajulu return (size); 42446a62bec0SDavid C Somayajulu } 42456a62bec0SDavid C Somayajulu 42466a62bec0SDavid C Somayajulu static void 42476a62bec0SDavid C Somayajulu ql_free_minidump_buffer(qla_host_t *ha) 42486a62bec0SDavid C Somayajulu { 42496a62bec0SDavid C Somayajulu if (ha->hw.mdump_buffer != NULL) { 42506a62bec0SDavid C Somayajulu free(ha->hw.mdump_buffer, M_QLA83XXBUF); 42516a62bec0SDavid C Somayajulu ha->hw.mdump_buffer = NULL; 42526a62bec0SDavid C Somayajulu ha->hw.mdump_buffer_size = 0; 42536a62bec0SDavid C Somayajulu } 42546a62bec0SDavid C Somayajulu return; 42556a62bec0SDavid C Somayajulu } 42566a62bec0SDavid C Somayajulu 4257f10a77bbSDavid C Somayajulu static int 42586a62bec0SDavid C Somayajulu ql_alloc_minidump_buffer(qla_host_t *ha) 42596a62bec0SDavid C Somayajulu { 42606a62bec0SDavid C Somayajulu ha->hw.mdump_buffer_size = ql_minidump_size(ha); 42616a62bec0SDavid C Somayajulu 42626a62bec0SDavid C Somayajulu if (!ha->hw.mdump_buffer_size) 42636a62bec0SDavid C Somayajulu return (-1); 42646a62bec0SDavid C Somayajulu 42656a62bec0SDavid C Somayajulu ha->hw.mdump_buffer = malloc(ha->hw.mdump_buffer_size, M_QLA83XXBUF, 42666a62bec0SDavid C Somayajulu M_NOWAIT); 42676a62bec0SDavid C Somayajulu 42686a62bec0SDavid C Somayajulu if (ha->hw.mdump_buffer == NULL) 42696a62bec0SDavid C Somayajulu return (-1); 42706a62bec0SDavid C Somayajulu 42716a62bec0SDavid C Somayajulu return (0); 42726a62bec0SDavid C Somayajulu } 42736a62bec0SDavid C Somayajulu 42746a62bec0SDavid C Somayajulu static void 42756a62bec0SDavid C Somayajulu ql_free_minidump_template_buffer(qla_host_t *ha) 42766a62bec0SDavid C Somayajulu { 42776a62bec0SDavid C Somayajulu if (ha->hw.mdump_template != NULL) { 42786a62bec0SDavid C Somayajulu free(ha->hw.mdump_template, M_QLA83XXBUF); 42796a62bec0SDavid C Somayajulu ha->hw.mdump_template = NULL; 42806a62bec0SDavid C Somayajulu ha->hw.mdump_template_size = 0; 42816a62bec0SDavid C Somayajulu } 42826a62bec0SDavid C Somayajulu return; 42836a62bec0SDavid C Somayajulu } 42846a62bec0SDavid C Somayajulu 42856a62bec0SDavid C Somayajulu static int 42866a62bec0SDavid C Somayajulu ql_alloc_minidump_template_buffer(qla_host_t *ha) 42876a62bec0SDavid C Somayajulu { 42886a62bec0SDavid C Somayajulu ha->hw.mdump_template_size = ha->hw.dma_buf.minidump.size; 42896a62bec0SDavid C Somayajulu 42906a62bec0SDavid C Somayajulu ha->hw.mdump_template = malloc(ha->hw.mdump_template_size, 42916a62bec0SDavid C Somayajulu M_QLA83XXBUF, M_NOWAIT); 42926a62bec0SDavid C Somayajulu 42936a62bec0SDavid C Somayajulu if (ha->hw.mdump_template == NULL) 42946a62bec0SDavid C Somayajulu return (-1); 42956a62bec0SDavid C Somayajulu 42966a62bec0SDavid C Somayajulu return (0); 42976a62bec0SDavid C Somayajulu } 42986a62bec0SDavid C Somayajulu 42996a62bec0SDavid C Somayajulu static int 43006a62bec0SDavid C Somayajulu ql_alloc_minidump_buffers(qla_host_t *ha) 43016a62bec0SDavid C Somayajulu { 43026a62bec0SDavid C Somayajulu int ret; 43036a62bec0SDavid C Somayajulu 43046a62bec0SDavid C Somayajulu ret = ql_alloc_minidump_template_buffer(ha); 43056a62bec0SDavid C Somayajulu 43066a62bec0SDavid C Somayajulu if (ret) 43076a62bec0SDavid C Somayajulu return (ret); 43086a62bec0SDavid C Somayajulu 43096a62bec0SDavid C Somayajulu ret = ql_alloc_minidump_buffer(ha); 43106a62bec0SDavid C Somayajulu 43116a62bec0SDavid C Somayajulu if (ret) 43126a62bec0SDavid C Somayajulu ql_free_minidump_template_buffer(ha); 43136a62bec0SDavid C Somayajulu 43146a62bec0SDavid C Somayajulu return (ret); 43156a62bec0SDavid C Somayajulu } 43166a62bec0SDavid C Somayajulu 43176a62bec0SDavid C Somayajulu 43186a62bec0SDavid C Somayajulu static uint32_t 43196a62bec0SDavid C Somayajulu ql_validate_minidump_checksum(qla_host_t *ha) 43206a62bec0SDavid C Somayajulu { 43216a62bec0SDavid C Somayajulu uint64_t sum = 0; 43226a62bec0SDavid C Somayajulu int count; 43236a62bec0SDavid C Somayajulu uint32_t *template_buff; 43246a62bec0SDavid C Somayajulu 43256a62bec0SDavid C Somayajulu count = ha->hw.dma_buf.minidump.size / sizeof (uint32_t); 43266a62bec0SDavid C Somayajulu template_buff = ha->hw.dma_buf.minidump.dma_b; 43276a62bec0SDavid C Somayajulu 43286a62bec0SDavid C Somayajulu while (count-- > 0) { 43296a62bec0SDavid C Somayajulu sum += *template_buff++; 43306a62bec0SDavid C Somayajulu } 43316a62bec0SDavid C Somayajulu 43326a62bec0SDavid C Somayajulu while (sum >> 32) { 43336a62bec0SDavid C Somayajulu sum = (sum & 0xFFFFFFFF) + (sum >> 32); 43346a62bec0SDavid C Somayajulu } 43356a62bec0SDavid C Somayajulu 43366a62bec0SDavid C Somayajulu return (~sum); 43376a62bec0SDavid C Somayajulu } 43386a62bec0SDavid C Somayajulu 43396a62bec0SDavid C Somayajulu int 43406a62bec0SDavid C Somayajulu ql_minidump_init(qla_host_t *ha) 4341f10a77bbSDavid C Somayajulu { 434235291c22SDavid C Somayajulu int ret = 0; 4343f10a77bbSDavid C Somayajulu uint32_t template_size = 0; 4344f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 4345f10a77bbSDavid C Somayajulu 4346f10a77bbSDavid C Somayajulu /* 4347f10a77bbSDavid C Somayajulu * Get Minidump Template Size 4348f10a77bbSDavid C Somayajulu */ 4349f10a77bbSDavid C Somayajulu ret = qla_get_minidump_tmplt_size(ha, &template_size); 4350f10a77bbSDavid C Somayajulu 4351f10a77bbSDavid C Somayajulu if (ret || (template_size == 0)) { 4352f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret, 4353f10a77bbSDavid C Somayajulu template_size); 4354f10a77bbSDavid C Somayajulu return (-1); 4355f10a77bbSDavid C Somayajulu } 4356f10a77bbSDavid C Somayajulu 4357f10a77bbSDavid C Somayajulu /* 4358f10a77bbSDavid C Somayajulu * Allocate Memory for Minidump Template 4359f10a77bbSDavid C Somayajulu */ 4360f10a77bbSDavid C Somayajulu 4361f10a77bbSDavid C Somayajulu ha->hw.dma_buf.minidump.alignment = 8; 4362f10a77bbSDavid C Somayajulu ha->hw.dma_buf.minidump.size = template_size; 4363f10a77bbSDavid C Somayajulu 436435291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW 4365f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) { 4366f10a77bbSDavid C Somayajulu 4367f10a77bbSDavid C Somayajulu device_printf(dev, "%s: minidump dma alloc failed\n", __func__); 4368f10a77bbSDavid C Somayajulu 4369f10a77bbSDavid C Somayajulu return (-1); 4370f10a77bbSDavid C Somayajulu } 4371f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.minidump = 1; 4372f10a77bbSDavid C Somayajulu 4373f10a77bbSDavid C Somayajulu /* 4374f10a77bbSDavid C Somayajulu * Retrieve Minidump Template 4375f10a77bbSDavid C Somayajulu */ 43766a62bec0SDavid C Somayajulu ret = ql_get_minidump_template(ha); 437735291c22SDavid C Somayajulu #else 437835291c22SDavid C Somayajulu ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump; 43796a62bec0SDavid C Somayajulu 438035291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */ 4381f10a77bbSDavid C Somayajulu 43826a62bec0SDavid C Somayajulu if (ret == 0) { 43836a62bec0SDavid C Somayajulu 43846a62bec0SDavid C Somayajulu ret = ql_validate_minidump_checksum(ha); 43856a62bec0SDavid C Somayajulu 43866a62bec0SDavid C Somayajulu if (ret == 0) { 43876a62bec0SDavid C Somayajulu 43886a62bec0SDavid C Somayajulu ret = ql_alloc_minidump_buffers(ha); 43896a62bec0SDavid C Somayajulu 43906a62bec0SDavid C Somayajulu if (ret == 0) 4391f10a77bbSDavid C Somayajulu ha->hw.mdump_init = 1; 43926a62bec0SDavid C Somayajulu else 43936a62bec0SDavid C Somayajulu device_printf(dev, 43946a62bec0SDavid C Somayajulu "%s: ql_alloc_minidump_buffers" 43956a62bec0SDavid C Somayajulu " failed\n", __func__); 43966a62bec0SDavid C Somayajulu } else { 43976a62bec0SDavid C Somayajulu device_printf(dev, "%s: ql_validate_minidump_checksum" 43986a62bec0SDavid C Somayajulu " failed\n", __func__); 4399f10a77bbSDavid C Somayajulu } 44006a62bec0SDavid C Somayajulu } else { 44016a62bec0SDavid C Somayajulu device_printf(dev, "%s: ql_get_minidump_template failed\n", 44026a62bec0SDavid C Somayajulu __func__); 44036a62bec0SDavid C Somayajulu } 44046a62bec0SDavid C Somayajulu 44056a62bec0SDavid C Somayajulu if (ret) 44066a62bec0SDavid C Somayajulu ql_minidump_free(ha); 4407f10a77bbSDavid C Somayajulu 4408f10a77bbSDavid C Somayajulu return (ret); 4409f10a77bbSDavid C Somayajulu } 4410f10a77bbSDavid C Somayajulu 4411f10a77bbSDavid C Somayajulu static void 44126a62bec0SDavid C Somayajulu ql_minidump_free(qla_host_t *ha) 4413f10a77bbSDavid C Somayajulu { 4414f10a77bbSDavid C Somayajulu ha->hw.mdump_init = 0; 4415f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.minidump) { 4416f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.minidump = 0; 4417f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump); 4418f10a77bbSDavid C Somayajulu } 44196a62bec0SDavid C Somayajulu 44206a62bec0SDavid C Somayajulu ql_free_minidump_template_buffer(ha); 44216a62bec0SDavid C Somayajulu ql_free_minidump_buffer(ha); 44226a62bec0SDavid C Somayajulu 4423f10a77bbSDavid C Somayajulu return; 4424f10a77bbSDavid C Somayajulu } 4425f10a77bbSDavid C Somayajulu 4426f10a77bbSDavid C Somayajulu void 4427f10a77bbSDavid C Somayajulu ql_minidump(qla_host_t *ha) 4428f10a77bbSDavid C Somayajulu { 4429f10a77bbSDavid C Somayajulu if (!ha->hw.mdump_init) 4430f10a77bbSDavid C Somayajulu return; 4431f10a77bbSDavid C Somayajulu 44326a62bec0SDavid C Somayajulu if (ha->hw.mdump_done) 4433f10a77bbSDavid C Somayajulu return; 4434f10a77bbSDavid C Somayajulu 4435f10a77bbSDavid C Somayajulu ha->hw.mdump_start_seq_index = ql_stop_sequence(ha); 4436f10a77bbSDavid C Somayajulu 44376a62bec0SDavid C Somayajulu bzero(ha->hw.mdump_buffer, ha->hw.mdump_buffer_size); 44386a62bec0SDavid C Somayajulu bzero(ha->hw.mdump_template, ha->hw.mdump_template_size); 44396a62bec0SDavid C Somayajulu 44406a62bec0SDavid C Somayajulu bcopy(ha->hw.dma_buf.minidump.dma_b, ha->hw.mdump_template, 44416a62bec0SDavid C Somayajulu ha->hw.mdump_template_size); 44426a62bec0SDavid C Somayajulu 44436a62bec0SDavid C Somayajulu ql_parse_template(ha); 44446a62bec0SDavid C Somayajulu 4445f10a77bbSDavid C Somayajulu ql_start_sequence(ha, ha->hw.mdump_start_seq_index); 4446f10a77bbSDavid C Somayajulu 44476a62bec0SDavid C Somayajulu ha->hw.mdump_done = 1; 44486a62bec0SDavid C Somayajulu 4449f10a77bbSDavid C Somayajulu return; 4450f10a77bbSDavid C Somayajulu } 44516a62bec0SDavid C Somayajulu 44526a62bec0SDavid C Somayajulu 44536a62bec0SDavid C Somayajulu /* 44546a62bec0SDavid C Somayajulu * helper routines 44556a62bec0SDavid C Somayajulu */ 44566a62bec0SDavid C Somayajulu static void 44576a62bec0SDavid C Somayajulu ql_entry_err_chk(ql_minidump_entry_t *entry, uint32_t esize) 44586a62bec0SDavid C Somayajulu { 44596a62bec0SDavid C Somayajulu if (esize != entry->hdr.entry_capture_size) { 44606a62bec0SDavid C Somayajulu entry->hdr.entry_capture_size = esize; 44616a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SIZE_ERR_FLAG; 44626a62bec0SDavid C Somayajulu } 44636a62bec0SDavid C Somayajulu return; 44646a62bec0SDavid C Somayajulu } 44656a62bec0SDavid C Somayajulu 44666a62bec0SDavid C Somayajulu 44676a62bec0SDavid C Somayajulu static int 44686a62bec0SDavid C Somayajulu ql_parse_template(qla_host_t *ha) 44696a62bec0SDavid C Somayajulu { 44706a62bec0SDavid C Somayajulu uint32_t num_of_entries, buff_level, e_cnt, esize; 44716a62bec0SDavid C Somayajulu uint32_t end_cnt, rv = 0; 44726a62bec0SDavid C Somayajulu char *dump_buff, *dbuff; 44736a62bec0SDavid C Somayajulu int sane_start = 0, sane_end = 0; 44746a62bec0SDavid C Somayajulu ql_minidump_template_hdr_t *template_hdr; 44756a62bec0SDavid C Somayajulu ql_minidump_entry_t *entry; 44766a62bec0SDavid C Somayajulu uint32_t capture_mask; 44776a62bec0SDavid C Somayajulu uint32_t dump_size; 44786a62bec0SDavid C Somayajulu 44796a62bec0SDavid C Somayajulu /* Setup parameters */ 44806a62bec0SDavid C Somayajulu template_hdr = (ql_minidump_template_hdr_t *)ha->hw.mdump_template; 44816a62bec0SDavid C Somayajulu 44826a62bec0SDavid C Somayajulu if (template_hdr->entry_type == TLHDR) 44836a62bec0SDavid C Somayajulu sane_start = 1; 44846a62bec0SDavid C Somayajulu 44856a62bec0SDavid C Somayajulu dump_buff = (char *) ha->hw.mdump_buffer; 44866a62bec0SDavid C Somayajulu 44876a62bec0SDavid C Somayajulu num_of_entries = template_hdr->num_of_entries; 44886a62bec0SDavid C Somayajulu 44896a62bec0SDavid C Somayajulu entry = (ql_minidump_entry_t *) ((char *)template_hdr 44906a62bec0SDavid C Somayajulu + template_hdr->first_entry_offset ); 44916a62bec0SDavid C Somayajulu 44926a62bec0SDavid C Somayajulu template_hdr->saved_state_array[QL_OCM0_ADDR_INDX] = 44936a62bec0SDavid C Somayajulu template_hdr->ocm_window_array[ha->pci_func]; 44946a62bec0SDavid C Somayajulu template_hdr->saved_state_array[QL_PCIE_FUNC_INDX] = ha->pci_func; 44956a62bec0SDavid C Somayajulu 44966a62bec0SDavid C Somayajulu capture_mask = ha->hw.mdump_capture_mask; 44976a62bec0SDavid C Somayajulu dump_size = ha->hw.mdump_buffer_size; 44986a62bec0SDavid C Somayajulu 44996a62bec0SDavid C Somayajulu template_hdr->driver_capture_mask = capture_mask; 45006a62bec0SDavid C Somayajulu 45016a62bec0SDavid C Somayajulu QL_DPRINT80(ha, (ha->pci_dev, 45026a62bec0SDavid C Somayajulu "%s: sane_start = %d num_of_entries = %d " 45036a62bec0SDavid C Somayajulu "capture_mask = 0x%x dump_size = %d \n", 45046a62bec0SDavid C Somayajulu __func__, sane_start, num_of_entries, capture_mask, dump_size)); 45056a62bec0SDavid C Somayajulu 45066a62bec0SDavid C Somayajulu for (buff_level = 0, e_cnt = 0; e_cnt < num_of_entries; e_cnt++) { 45076a62bec0SDavid C Somayajulu 45086a62bec0SDavid C Somayajulu /* 45096a62bec0SDavid C Somayajulu * If the capture_mask of the entry does not match capture mask 45106a62bec0SDavid C Somayajulu * skip the entry after marking the driver_flags indicator. 45116a62bec0SDavid C Somayajulu */ 45126a62bec0SDavid C Somayajulu 45136a62bec0SDavid C Somayajulu if (!(entry->hdr.entry_capture_mask & capture_mask)) { 45146a62bec0SDavid C Somayajulu 45156a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG; 45166a62bec0SDavid C Somayajulu entry = (ql_minidump_entry_t *) ((char *) entry 45176a62bec0SDavid C Somayajulu + entry->hdr.entry_size); 45186a62bec0SDavid C Somayajulu continue; 45196a62bec0SDavid C Somayajulu } 45206a62bec0SDavid C Somayajulu 45216a62bec0SDavid C Somayajulu /* 45226a62bec0SDavid C Somayajulu * This is ONLY needed in implementations where 45236a62bec0SDavid C Somayajulu * the capture buffer allocated is too small to capture 45246a62bec0SDavid C Somayajulu * all of the required entries for a given capture mask. 45256a62bec0SDavid C Somayajulu * We need to empty the buffer contents to a file 45266a62bec0SDavid C Somayajulu * if possible, before processing the next entry 45276a62bec0SDavid C Somayajulu * If the buff_full_flag is set, no further capture will happen 45286a62bec0SDavid C Somayajulu * and all remaining non-control entries will be skipped. 45296a62bec0SDavid C Somayajulu */ 45306a62bec0SDavid C Somayajulu if (entry->hdr.entry_capture_size != 0) { 45316a62bec0SDavid C Somayajulu if ((buff_level + entry->hdr.entry_capture_size) > 45326a62bec0SDavid C Somayajulu dump_size) { 45336a62bec0SDavid C Somayajulu /* Try to recover by emptying buffer to file */ 45346a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG; 45356a62bec0SDavid C Somayajulu entry = (ql_minidump_entry_t *) ((char *) entry 45366a62bec0SDavid C Somayajulu + entry->hdr.entry_size); 45376a62bec0SDavid C Somayajulu continue; 45386a62bec0SDavid C Somayajulu } 45396a62bec0SDavid C Somayajulu } 45406a62bec0SDavid C Somayajulu 45416a62bec0SDavid C Somayajulu /* 45426a62bec0SDavid C Somayajulu * Decode the entry type and process it accordingly 45436a62bec0SDavid C Somayajulu */ 45446a62bec0SDavid C Somayajulu 45456a62bec0SDavid C Somayajulu switch (entry->hdr.entry_type) { 45466a62bec0SDavid C Somayajulu case RDNOP: 45476a62bec0SDavid C Somayajulu break; 45486a62bec0SDavid C Somayajulu 45496a62bec0SDavid C Somayajulu case RDEND: 45506a62bec0SDavid C Somayajulu if (sane_end == 0) { 45516a62bec0SDavid C Somayajulu end_cnt = e_cnt; 45526a62bec0SDavid C Somayajulu } 45536a62bec0SDavid C Somayajulu sane_end++; 45546a62bec0SDavid C Somayajulu break; 45556a62bec0SDavid C Somayajulu 45566a62bec0SDavid C Somayajulu case RDCRB: 45576a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level; 45586a62bec0SDavid C Somayajulu esize = ql_rdcrb(ha, (void *)entry, (void *)dbuff); 45596a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize); 45606a62bec0SDavid C Somayajulu buff_level += esize; 45616a62bec0SDavid C Somayajulu break; 45626a62bec0SDavid C Somayajulu 45636a62bec0SDavid C Somayajulu case POLLRD: 45646a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level; 45656a62bec0SDavid C Somayajulu esize = ql_pollrd(ha, (void *)entry, (void *)dbuff); 45666a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize); 45676a62bec0SDavid C Somayajulu buff_level += esize; 45686a62bec0SDavid C Somayajulu break; 45696a62bec0SDavid C Somayajulu 45706a62bec0SDavid C Somayajulu case POLLRDMWR: 45716a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level; 45726a62bec0SDavid C Somayajulu esize = ql_pollrd_modify_write(ha, (void *)entry, 45736a62bec0SDavid C Somayajulu (void *)dbuff); 45746a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize); 45756a62bec0SDavid C Somayajulu buff_level += esize; 45766a62bec0SDavid C Somayajulu break; 45776a62bec0SDavid C Somayajulu 45786a62bec0SDavid C Somayajulu case L2ITG: 45796a62bec0SDavid C Somayajulu case L2DTG: 45806a62bec0SDavid C Somayajulu case L2DAT: 45816a62bec0SDavid C Somayajulu case L2INS: 45826a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level; 45836a62bec0SDavid C Somayajulu esize = ql_L2Cache(ha, (void *)entry, (void *)dbuff); 45846a62bec0SDavid C Somayajulu if (esize == -1) { 45856a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG; 45866a62bec0SDavid C Somayajulu } else { 45876a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize); 45886a62bec0SDavid C Somayajulu buff_level += esize; 45896a62bec0SDavid C Somayajulu } 45906a62bec0SDavid C Somayajulu break; 45916a62bec0SDavid C Somayajulu 45926a62bec0SDavid C Somayajulu case L1DAT: 45936a62bec0SDavid C Somayajulu case L1INS: 45946a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level; 45956a62bec0SDavid C Somayajulu esize = ql_L1Cache(ha, (void *)entry, (void *)dbuff); 45966a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize); 45976a62bec0SDavid C Somayajulu buff_level += esize; 45986a62bec0SDavid C Somayajulu break; 45996a62bec0SDavid C Somayajulu 46006a62bec0SDavid C Somayajulu case RDOCM: 46016a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level; 46026a62bec0SDavid C Somayajulu esize = ql_rdocm(ha, (void *)entry, (void *)dbuff); 46036a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize); 46046a62bec0SDavid C Somayajulu buff_level += esize; 46056a62bec0SDavid C Somayajulu break; 46066a62bec0SDavid C Somayajulu 46076a62bec0SDavid C Somayajulu case RDMEM: 46086a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level; 46096a62bec0SDavid C Somayajulu esize = ql_rdmem(ha, (void *)entry, (void *)dbuff); 46106a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize); 46116a62bec0SDavid C Somayajulu buff_level += esize; 46126a62bec0SDavid C Somayajulu break; 46136a62bec0SDavid C Somayajulu 46146a62bec0SDavid C Somayajulu case BOARD: 46156a62bec0SDavid C Somayajulu case RDROM: 46166a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level; 46176a62bec0SDavid C Somayajulu esize = ql_rdrom(ha, (void *)entry, (void *)dbuff); 46186a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize); 46196a62bec0SDavid C Somayajulu buff_level += esize; 46206a62bec0SDavid C Somayajulu break; 46216a62bec0SDavid C Somayajulu 46226a62bec0SDavid C Somayajulu case RDMUX: 46236a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level; 46246a62bec0SDavid C Somayajulu esize = ql_rdmux(ha, (void *)entry, (void *)dbuff); 46256a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize); 46266a62bec0SDavid C Somayajulu buff_level += esize; 46276a62bec0SDavid C Somayajulu break; 46286a62bec0SDavid C Somayajulu 46296a62bec0SDavid C Somayajulu case RDMUX2: 46306a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level; 46316a62bec0SDavid C Somayajulu esize = ql_rdmux2(ha, (void *)entry, (void *)dbuff); 46326a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize); 46336a62bec0SDavid C Somayajulu buff_level += esize; 46346a62bec0SDavid C Somayajulu break; 46356a62bec0SDavid C Somayajulu 46366a62bec0SDavid C Somayajulu case QUEUE: 46376a62bec0SDavid C Somayajulu dbuff = dump_buff + buff_level; 46386a62bec0SDavid C Somayajulu esize = ql_rdqueue(ha, (void *)entry, (void *)dbuff); 46396a62bec0SDavid C Somayajulu ql_entry_err_chk(entry, esize); 46406a62bec0SDavid C Somayajulu buff_level += esize; 46416a62bec0SDavid C Somayajulu break; 46426a62bec0SDavid C Somayajulu 46436a62bec0SDavid C Somayajulu case CNTRL: 46446a62bec0SDavid C Somayajulu if ((rv = ql_cntrl(ha, template_hdr, (void *)entry))) { 46456a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG; 46466a62bec0SDavid C Somayajulu } 46476a62bec0SDavid C Somayajulu break; 46486a62bec0SDavid C Somayajulu default: 46496a62bec0SDavid C Somayajulu entry->hdr.driver_flags |= QL_DBG_SKIPPED_FLAG; 46506a62bec0SDavid C Somayajulu break; 46516a62bec0SDavid C Somayajulu } 46526a62bec0SDavid C Somayajulu /* next entry in the template */ 46536a62bec0SDavid C Somayajulu entry = (ql_minidump_entry_t *) ((char *) entry 46546a62bec0SDavid C Somayajulu + entry->hdr.entry_size); 46556a62bec0SDavid C Somayajulu } 46566a62bec0SDavid C Somayajulu 46576a62bec0SDavid C Somayajulu if (!sane_start || (sane_end > 1)) { 46586a62bec0SDavid C Somayajulu device_printf(ha->pci_dev, 46596a62bec0SDavid C Somayajulu "\n%s: Template configuration error. Check Template\n", 46606a62bec0SDavid C Somayajulu __func__); 46616a62bec0SDavid C Somayajulu } 46626a62bec0SDavid C Somayajulu 46636a62bec0SDavid C Somayajulu QL_DPRINT80(ha, (ha->pci_dev, "%s: Minidump num of entries = %d\n", 46646a62bec0SDavid C Somayajulu __func__, template_hdr->num_of_entries)); 46656a62bec0SDavid C Somayajulu 46666a62bec0SDavid C Somayajulu return 0; 46676a62bec0SDavid C Somayajulu } 46686a62bec0SDavid C Somayajulu 46696a62bec0SDavid C Somayajulu /* 46706a62bec0SDavid C Somayajulu * Read CRB operation. 46716a62bec0SDavid C Somayajulu */ 46726a62bec0SDavid C Somayajulu static uint32_t 46736a62bec0SDavid C Somayajulu ql_rdcrb(qla_host_t *ha, ql_minidump_entry_rdcrb_t * crb_entry, 46746a62bec0SDavid C Somayajulu uint32_t * data_buff) 46756a62bec0SDavid C Somayajulu { 46766a62bec0SDavid C Somayajulu int loop_cnt; 46776a62bec0SDavid C Somayajulu int ret; 46786a62bec0SDavid C Somayajulu uint32_t op_count, addr, stride, value = 0; 46796a62bec0SDavid C Somayajulu 46806a62bec0SDavid C Somayajulu addr = crb_entry->addr; 46816a62bec0SDavid C Somayajulu op_count = crb_entry->op_count; 46826a62bec0SDavid C Somayajulu stride = crb_entry->addr_stride; 46836a62bec0SDavid C Somayajulu 46846a62bec0SDavid C Somayajulu for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) { 46856a62bec0SDavid C Somayajulu 46866a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &value, 1); 46876a62bec0SDavid C Somayajulu 46886a62bec0SDavid C Somayajulu if (ret) 46896a62bec0SDavid C Somayajulu return (0); 46906a62bec0SDavid C Somayajulu 46916a62bec0SDavid C Somayajulu *data_buff++ = addr; 46926a62bec0SDavid C Somayajulu *data_buff++ = value; 46936a62bec0SDavid C Somayajulu addr = addr + stride; 46946a62bec0SDavid C Somayajulu } 46956a62bec0SDavid C Somayajulu 46966a62bec0SDavid C Somayajulu /* 46976a62bec0SDavid C Somayajulu * for testing purpose we return amount of data written 46986a62bec0SDavid C Somayajulu */ 46996a62bec0SDavid C Somayajulu return (op_count * (2 * sizeof(uint32_t))); 47006a62bec0SDavid C Somayajulu } 47016a62bec0SDavid C Somayajulu 47026a62bec0SDavid C Somayajulu /* 47036a62bec0SDavid C Somayajulu * Handle L2 Cache. 47046a62bec0SDavid C Somayajulu */ 47056a62bec0SDavid C Somayajulu 47066a62bec0SDavid C Somayajulu static uint32_t 47076a62bec0SDavid C Somayajulu ql_L2Cache(qla_host_t *ha, ql_minidump_entry_cache_t *cacheEntry, 47086a62bec0SDavid C Somayajulu uint32_t * data_buff) 47096a62bec0SDavid C Somayajulu { 47106a62bec0SDavid C Somayajulu int i, k; 47116a62bec0SDavid C Somayajulu int loop_cnt; 47126a62bec0SDavid C Somayajulu int ret; 47136a62bec0SDavid C Somayajulu 47146a62bec0SDavid C Somayajulu uint32_t read_value; 47156a62bec0SDavid C Somayajulu uint32_t addr, read_addr, cntrl_addr, tag_reg_addr, cntl_value_w; 47166a62bec0SDavid C Somayajulu uint32_t tag_value, read_cnt; 47176a62bec0SDavid C Somayajulu volatile uint8_t cntl_value_r; 47186a62bec0SDavid C Somayajulu long timeout; 47196a62bec0SDavid C Somayajulu uint32_t data; 47206a62bec0SDavid C Somayajulu 47216a62bec0SDavid C Somayajulu loop_cnt = cacheEntry->op_count; 47226a62bec0SDavid C Somayajulu 47236a62bec0SDavid C Somayajulu read_addr = cacheEntry->read_addr; 47246a62bec0SDavid C Somayajulu cntrl_addr = cacheEntry->control_addr; 47256a62bec0SDavid C Somayajulu cntl_value_w = (uint32_t) cacheEntry->write_value; 47266a62bec0SDavid C Somayajulu 47276a62bec0SDavid C Somayajulu tag_reg_addr = cacheEntry->tag_reg_addr; 47286a62bec0SDavid C Somayajulu 47296a62bec0SDavid C Somayajulu tag_value = cacheEntry->init_tag_value; 47306a62bec0SDavid C Somayajulu read_cnt = cacheEntry->read_addr_cnt; 47316a62bec0SDavid C Somayajulu 47326a62bec0SDavid C Somayajulu for (i = 0; i < loop_cnt; i++) { 47336a62bec0SDavid C Somayajulu 47346a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0); 47356a62bec0SDavid C Somayajulu if (ret) 47366a62bec0SDavid C Somayajulu return (0); 47376a62bec0SDavid C Somayajulu 47386a62bec0SDavid C Somayajulu if (cacheEntry->write_value != 0) { 47396a62bec0SDavid C Somayajulu 47406a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, cntrl_addr, 47416a62bec0SDavid C Somayajulu &cntl_value_w, 0); 47426a62bec0SDavid C Somayajulu if (ret) 47436a62bec0SDavid C Somayajulu return (0); 47446a62bec0SDavid C Somayajulu } 47456a62bec0SDavid C Somayajulu 47466a62bec0SDavid C Somayajulu if (cacheEntry->poll_mask != 0) { 47476a62bec0SDavid C Somayajulu 47486a62bec0SDavid C Somayajulu timeout = cacheEntry->poll_wait; 47496a62bec0SDavid C Somayajulu 47506a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, cntrl_addr, &data, 1); 47516a62bec0SDavid C Somayajulu if (ret) 47526a62bec0SDavid C Somayajulu return (0); 47536a62bec0SDavid C Somayajulu 47546a62bec0SDavid C Somayajulu cntl_value_r = (uint8_t)data; 47556a62bec0SDavid C Somayajulu 47566a62bec0SDavid C Somayajulu while ((cntl_value_r & cacheEntry->poll_mask) != 0) { 47576a62bec0SDavid C Somayajulu 47586a62bec0SDavid C Somayajulu if (timeout) { 47596a62bec0SDavid C Somayajulu qla_mdelay(__func__, 1); 47606a62bec0SDavid C Somayajulu timeout--; 47616a62bec0SDavid C Somayajulu } else 47626a62bec0SDavid C Somayajulu break; 47636a62bec0SDavid C Somayajulu 47646a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, cntrl_addr, 47656a62bec0SDavid C Somayajulu &data, 1); 47666a62bec0SDavid C Somayajulu if (ret) 47676a62bec0SDavid C Somayajulu return (0); 47686a62bec0SDavid C Somayajulu 47696a62bec0SDavid C Somayajulu cntl_value_r = (uint8_t)data; 47706a62bec0SDavid C Somayajulu } 47716a62bec0SDavid C Somayajulu if (!timeout) { 47726a62bec0SDavid C Somayajulu /* Report timeout error. 47736a62bec0SDavid C Somayajulu * core dump capture failed 47746a62bec0SDavid C Somayajulu * Skip remaining entries. 47756a62bec0SDavid C Somayajulu * Write buffer out to file 47766a62bec0SDavid C Somayajulu * Use driver specific fields in template header 47776a62bec0SDavid C Somayajulu * to report this error. 47786a62bec0SDavid C Somayajulu */ 47796a62bec0SDavid C Somayajulu return (-1); 47806a62bec0SDavid C Somayajulu } 47816a62bec0SDavid C Somayajulu } 47826a62bec0SDavid C Somayajulu 47836a62bec0SDavid C Somayajulu addr = read_addr; 47846a62bec0SDavid C Somayajulu for (k = 0; k < read_cnt; k++) { 47856a62bec0SDavid C Somayajulu 47866a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &read_value, 1); 47876a62bec0SDavid C Somayajulu if (ret) 47886a62bec0SDavid C Somayajulu return (0); 47896a62bec0SDavid C Somayajulu 47906a62bec0SDavid C Somayajulu *data_buff++ = read_value; 47916a62bec0SDavid C Somayajulu addr += cacheEntry->read_addr_stride; 47926a62bec0SDavid C Somayajulu } 47936a62bec0SDavid C Somayajulu 47946a62bec0SDavid C Somayajulu tag_value += cacheEntry->tag_value_stride; 47956a62bec0SDavid C Somayajulu } 47966a62bec0SDavid C Somayajulu 47976a62bec0SDavid C Somayajulu return (read_cnt * loop_cnt * sizeof(uint32_t)); 47986a62bec0SDavid C Somayajulu } 47996a62bec0SDavid C Somayajulu 48006a62bec0SDavid C Somayajulu /* 48016a62bec0SDavid C Somayajulu * Handle L1 Cache. 48026a62bec0SDavid C Somayajulu */ 48036a62bec0SDavid C Somayajulu 48046a62bec0SDavid C Somayajulu static uint32_t 48056a62bec0SDavid C Somayajulu ql_L1Cache(qla_host_t *ha, 48066a62bec0SDavid C Somayajulu ql_minidump_entry_cache_t *cacheEntry, 48076a62bec0SDavid C Somayajulu uint32_t *data_buff) 48086a62bec0SDavid C Somayajulu { 48096a62bec0SDavid C Somayajulu int ret; 48106a62bec0SDavid C Somayajulu int i, k; 48116a62bec0SDavid C Somayajulu int loop_cnt; 48126a62bec0SDavid C Somayajulu 48136a62bec0SDavid C Somayajulu uint32_t read_value; 48146a62bec0SDavid C Somayajulu uint32_t addr, read_addr, cntrl_addr, tag_reg_addr; 48156a62bec0SDavid C Somayajulu uint32_t tag_value, read_cnt; 48166a62bec0SDavid C Somayajulu uint32_t cntl_value_w; 48176a62bec0SDavid C Somayajulu 48186a62bec0SDavid C Somayajulu loop_cnt = cacheEntry->op_count; 48196a62bec0SDavid C Somayajulu 48206a62bec0SDavid C Somayajulu read_addr = cacheEntry->read_addr; 48216a62bec0SDavid C Somayajulu cntrl_addr = cacheEntry->control_addr; 48226a62bec0SDavid C Somayajulu cntl_value_w = (uint32_t) cacheEntry->write_value; 48236a62bec0SDavid C Somayajulu 48246a62bec0SDavid C Somayajulu tag_reg_addr = cacheEntry->tag_reg_addr; 48256a62bec0SDavid C Somayajulu 48266a62bec0SDavid C Somayajulu tag_value = cacheEntry->init_tag_value; 48276a62bec0SDavid C Somayajulu read_cnt = cacheEntry->read_addr_cnt; 48286a62bec0SDavid C Somayajulu 48296a62bec0SDavid C Somayajulu for (i = 0; i < loop_cnt; i++) { 48306a62bec0SDavid C Somayajulu 48316a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, tag_reg_addr, &tag_value, 0); 48326a62bec0SDavid C Somayajulu if (ret) 48336a62bec0SDavid C Somayajulu return (0); 48346a62bec0SDavid C Somayajulu 48356a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, cntrl_addr, &cntl_value_w, 0); 48366a62bec0SDavid C Somayajulu if (ret) 48376a62bec0SDavid C Somayajulu return (0); 48386a62bec0SDavid C Somayajulu 48396a62bec0SDavid C Somayajulu addr = read_addr; 48406a62bec0SDavid C Somayajulu for (k = 0; k < read_cnt; k++) { 48416a62bec0SDavid C Somayajulu 48426a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &read_value, 1); 48436a62bec0SDavid C Somayajulu if (ret) 48446a62bec0SDavid C Somayajulu return (0); 48456a62bec0SDavid C Somayajulu 48466a62bec0SDavid C Somayajulu *data_buff++ = read_value; 48476a62bec0SDavid C Somayajulu addr += cacheEntry->read_addr_stride; 48486a62bec0SDavid C Somayajulu } 48496a62bec0SDavid C Somayajulu 48506a62bec0SDavid C Somayajulu tag_value += cacheEntry->tag_value_stride; 48516a62bec0SDavid C Somayajulu } 48526a62bec0SDavid C Somayajulu 48536a62bec0SDavid C Somayajulu return (read_cnt * loop_cnt * sizeof(uint32_t)); 48546a62bec0SDavid C Somayajulu } 48556a62bec0SDavid C Somayajulu 48566a62bec0SDavid C Somayajulu /* 48576a62bec0SDavid C Somayajulu * Reading OCM memory 48586a62bec0SDavid C Somayajulu */ 48596a62bec0SDavid C Somayajulu 48606a62bec0SDavid C Somayajulu static uint32_t 48616a62bec0SDavid C Somayajulu ql_rdocm(qla_host_t *ha, 48626a62bec0SDavid C Somayajulu ql_minidump_entry_rdocm_t *ocmEntry, 48636a62bec0SDavid C Somayajulu uint32_t *data_buff) 48646a62bec0SDavid C Somayajulu { 48656a62bec0SDavid C Somayajulu int i, loop_cnt; 48666a62bec0SDavid C Somayajulu volatile uint32_t addr; 48676a62bec0SDavid C Somayajulu volatile uint32_t value; 48686a62bec0SDavid C Somayajulu 48696a62bec0SDavid C Somayajulu addr = ocmEntry->read_addr; 48706a62bec0SDavid C Somayajulu loop_cnt = ocmEntry->op_count; 48716a62bec0SDavid C Somayajulu 48726a62bec0SDavid C Somayajulu for (i = 0; i < loop_cnt; i++) { 48736a62bec0SDavid C Somayajulu value = READ_REG32(ha, addr); 48746a62bec0SDavid C Somayajulu *data_buff++ = value; 48756a62bec0SDavid C Somayajulu addr += ocmEntry->read_addr_stride; 48766a62bec0SDavid C Somayajulu } 48776a62bec0SDavid C Somayajulu return (loop_cnt * sizeof(value)); 48786a62bec0SDavid C Somayajulu } 48796a62bec0SDavid C Somayajulu 48806a62bec0SDavid C Somayajulu /* 48816a62bec0SDavid C Somayajulu * Read memory 48826a62bec0SDavid C Somayajulu */ 48836a62bec0SDavid C Somayajulu 48846a62bec0SDavid C Somayajulu static uint32_t 48856a62bec0SDavid C Somayajulu ql_rdmem(qla_host_t *ha, 48866a62bec0SDavid C Somayajulu ql_minidump_entry_rdmem_t *mem_entry, 48876a62bec0SDavid C Somayajulu uint32_t *data_buff) 48886a62bec0SDavid C Somayajulu { 48896a62bec0SDavid C Somayajulu int ret; 48906a62bec0SDavid C Somayajulu int i, loop_cnt; 48916a62bec0SDavid C Somayajulu volatile uint32_t addr; 48926a62bec0SDavid C Somayajulu q80_offchip_mem_val_t val; 48936a62bec0SDavid C Somayajulu 48946a62bec0SDavid C Somayajulu addr = mem_entry->read_addr; 48956a62bec0SDavid C Somayajulu 48966a62bec0SDavid C Somayajulu /* size in bytes / 16 */ 48976a62bec0SDavid C Somayajulu loop_cnt = mem_entry->read_data_size / (sizeof(uint32_t) * 4); 48986a62bec0SDavid C Somayajulu 48996a62bec0SDavid C Somayajulu for (i = 0; i < loop_cnt; i++) { 49006a62bec0SDavid C Somayajulu 49016a62bec0SDavid C Somayajulu ret = ql_rdwr_offchip_mem(ha, (addr & 0x0ffffffff), &val, 1); 49026a62bec0SDavid C Somayajulu if (ret) 49036a62bec0SDavid C Somayajulu return (0); 49046a62bec0SDavid C Somayajulu 49056a62bec0SDavid C Somayajulu *data_buff++ = val.data_lo; 49066a62bec0SDavid C Somayajulu *data_buff++ = val.data_hi; 49076a62bec0SDavid C Somayajulu *data_buff++ = val.data_ulo; 49086a62bec0SDavid C Somayajulu *data_buff++ = val.data_uhi; 49096a62bec0SDavid C Somayajulu 49106a62bec0SDavid C Somayajulu addr += (sizeof(uint32_t) * 4); 49116a62bec0SDavid C Somayajulu } 49126a62bec0SDavid C Somayajulu 49136a62bec0SDavid C Somayajulu return (loop_cnt * (sizeof(uint32_t) * 4)); 49146a62bec0SDavid C Somayajulu } 49156a62bec0SDavid C Somayajulu 49166a62bec0SDavid C Somayajulu /* 49176a62bec0SDavid C Somayajulu * Read Rom 49186a62bec0SDavid C Somayajulu */ 49196a62bec0SDavid C Somayajulu 49206a62bec0SDavid C Somayajulu static uint32_t 49216a62bec0SDavid C Somayajulu ql_rdrom(qla_host_t *ha, 49226a62bec0SDavid C Somayajulu ql_minidump_entry_rdrom_t *romEntry, 49236a62bec0SDavid C Somayajulu uint32_t *data_buff) 49246a62bec0SDavid C Somayajulu { 49256a62bec0SDavid C Somayajulu int ret; 49266a62bec0SDavid C Somayajulu int i, loop_cnt; 49276a62bec0SDavid C Somayajulu uint32_t addr; 49286a62bec0SDavid C Somayajulu uint32_t value; 49296a62bec0SDavid C Somayajulu 49306a62bec0SDavid C Somayajulu addr = romEntry->read_addr; 49316a62bec0SDavid C Somayajulu loop_cnt = romEntry->read_data_size; /* This is size in bytes */ 49326a62bec0SDavid C Somayajulu loop_cnt /= sizeof(value); 49336a62bec0SDavid C Somayajulu 49346a62bec0SDavid C Somayajulu for (i = 0; i < loop_cnt; i++) { 49356a62bec0SDavid C Somayajulu 49366a62bec0SDavid C Somayajulu ret = ql_rd_flash32(ha, addr, &value); 49376a62bec0SDavid C Somayajulu if (ret) 49386a62bec0SDavid C Somayajulu return (0); 49396a62bec0SDavid C Somayajulu 49406a62bec0SDavid C Somayajulu *data_buff++ = value; 49416a62bec0SDavid C Somayajulu addr += sizeof(value); 49426a62bec0SDavid C Somayajulu } 49436a62bec0SDavid C Somayajulu 49446a62bec0SDavid C Somayajulu return (loop_cnt * sizeof(value)); 49456a62bec0SDavid C Somayajulu } 49466a62bec0SDavid C Somayajulu 49476a62bec0SDavid C Somayajulu /* 49486a62bec0SDavid C Somayajulu * Read MUX data 49496a62bec0SDavid C Somayajulu */ 49506a62bec0SDavid C Somayajulu 49516a62bec0SDavid C Somayajulu static uint32_t 49526a62bec0SDavid C Somayajulu ql_rdmux(qla_host_t *ha, 49536a62bec0SDavid C Somayajulu ql_minidump_entry_mux_t *muxEntry, 49546a62bec0SDavid C Somayajulu uint32_t *data_buff) 49556a62bec0SDavid C Somayajulu { 49566a62bec0SDavid C Somayajulu int ret; 49576a62bec0SDavid C Somayajulu int loop_cnt; 49586a62bec0SDavid C Somayajulu uint32_t read_value, sel_value; 49596a62bec0SDavid C Somayajulu uint32_t read_addr, select_addr; 49606a62bec0SDavid C Somayajulu 49616a62bec0SDavid C Somayajulu select_addr = muxEntry->select_addr; 49626a62bec0SDavid C Somayajulu sel_value = muxEntry->select_value; 49636a62bec0SDavid C Somayajulu read_addr = muxEntry->read_addr; 49646a62bec0SDavid C Somayajulu 49656a62bec0SDavid C Somayajulu for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) { 49666a62bec0SDavid C Somayajulu 49676a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr, &sel_value, 0); 49686a62bec0SDavid C Somayajulu if (ret) 49696a62bec0SDavid C Somayajulu return (0); 49706a62bec0SDavid C Somayajulu 49716a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1); 49726a62bec0SDavid C Somayajulu if (ret) 49736a62bec0SDavid C Somayajulu return (0); 49746a62bec0SDavid C Somayajulu 49756a62bec0SDavid C Somayajulu *data_buff++ = sel_value; 49766a62bec0SDavid C Somayajulu *data_buff++ = read_value; 49776a62bec0SDavid C Somayajulu 49786a62bec0SDavid C Somayajulu sel_value += muxEntry->select_value_stride; 49796a62bec0SDavid C Somayajulu } 49806a62bec0SDavid C Somayajulu 49816a62bec0SDavid C Somayajulu return (loop_cnt * (2 * sizeof(uint32_t))); 49826a62bec0SDavid C Somayajulu } 49836a62bec0SDavid C Somayajulu 49846a62bec0SDavid C Somayajulu static uint32_t 49856a62bec0SDavid C Somayajulu ql_rdmux2(qla_host_t *ha, 49866a62bec0SDavid C Somayajulu ql_minidump_entry_mux2_t *muxEntry, 49876a62bec0SDavid C Somayajulu uint32_t *data_buff) 49886a62bec0SDavid C Somayajulu { 49896a62bec0SDavid C Somayajulu int ret; 49906a62bec0SDavid C Somayajulu int loop_cnt; 49916a62bec0SDavid C Somayajulu 49926a62bec0SDavid C Somayajulu uint32_t select_addr_1, select_addr_2; 49936a62bec0SDavid C Somayajulu uint32_t select_value_1, select_value_2; 49946a62bec0SDavid C Somayajulu uint32_t select_value_count, select_value_mask; 49956a62bec0SDavid C Somayajulu uint32_t read_addr, read_value; 49966a62bec0SDavid C Somayajulu 49976a62bec0SDavid C Somayajulu select_addr_1 = muxEntry->select_addr_1; 49986a62bec0SDavid C Somayajulu select_addr_2 = muxEntry->select_addr_2; 49996a62bec0SDavid C Somayajulu select_value_1 = muxEntry->select_value_1; 50006a62bec0SDavid C Somayajulu select_value_2 = muxEntry->select_value_2; 50016a62bec0SDavid C Somayajulu select_value_count = muxEntry->select_value_count; 50026a62bec0SDavid C Somayajulu select_value_mask = muxEntry->select_value_mask; 50036a62bec0SDavid C Somayajulu 50046a62bec0SDavid C Somayajulu read_addr = muxEntry->read_addr; 50056a62bec0SDavid C Somayajulu 50066a62bec0SDavid C Somayajulu for (loop_cnt = 0; loop_cnt < muxEntry->select_value_count; 50076a62bec0SDavid C Somayajulu loop_cnt++) { 50086a62bec0SDavid C Somayajulu 50096a62bec0SDavid C Somayajulu uint32_t temp_sel_val; 50106a62bec0SDavid C Somayajulu 50116a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_1, 0); 50126a62bec0SDavid C Somayajulu if (ret) 50136a62bec0SDavid C Somayajulu return (0); 50146a62bec0SDavid C Somayajulu 50156a62bec0SDavid C Somayajulu temp_sel_val = select_value_1 & select_value_mask; 50166a62bec0SDavid C Somayajulu 50176a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0); 50186a62bec0SDavid C Somayajulu if (ret) 50196a62bec0SDavid C Somayajulu return (0); 50206a62bec0SDavid C Somayajulu 50216a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1); 50226a62bec0SDavid C Somayajulu if (ret) 50236a62bec0SDavid C Somayajulu return (0); 50246a62bec0SDavid C Somayajulu 50256a62bec0SDavid C Somayajulu *data_buff++ = temp_sel_val; 50266a62bec0SDavid C Somayajulu *data_buff++ = read_value; 50276a62bec0SDavid C Somayajulu 50286a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr_1, &select_value_2, 0); 50296a62bec0SDavid C Somayajulu if (ret) 50306a62bec0SDavid C Somayajulu return (0); 50316a62bec0SDavid C Somayajulu 50326a62bec0SDavid C Somayajulu temp_sel_val = select_value_2 & select_value_mask; 50336a62bec0SDavid C Somayajulu 50346a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr_2, &temp_sel_val, 0); 50356a62bec0SDavid C Somayajulu if (ret) 50366a62bec0SDavid C Somayajulu return (0); 50376a62bec0SDavid C Somayajulu 50386a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1); 50396a62bec0SDavid C Somayajulu if (ret) 50406a62bec0SDavid C Somayajulu return (0); 50416a62bec0SDavid C Somayajulu 50426a62bec0SDavid C Somayajulu *data_buff++ = temp_sel_val; 50436a62bec0SDavid C Somayajulu *data_buff++ = read_value; 50446a62bec0SDavid C Somayajulu 50456a62bec0SDavid C Somayajulu select_value_1 += muxEntry->select_value_stride; 50466a62bec0SDavid C Somayajulu select_value_2 += muxEntry->select_value_stride; 50476a62bec0SDavid C Somayajulu } 50486a62bec0SDavid C Somayajulu 50496a62bec0SDavid C Somayajulu return (loop_cnt * (4 * sizeof(uint32_t))); 50506a62bec0SDavid C Somayajulu } 50516a62bec0SDavid C Somayajulu 50526a62bec0SDavid C Somayajulu /* 50536a62bec0SDavid C Somayajulu * Handling Queue State Reads. 50546a62bec0SDavid C Somayajulu */ 50556a62bec0SDavid C Somayajulu 50566a62bec0SDavid C Somayajulu static uint32_t 50576a62bec0SDavid C Somayajulu ql_rdqueue(qla_host_t *ha, 50586a62bec0SDavid C Somayajulu ql_minidump_entry_queue_t *queueEntry, 50596a62bec0SDavid C Somayajulu uint32_t *data_buff) 50606a62bec0SDavid C Somayajulu { 50616a62bec0SDavid C Somayajulu int ret; 50626a62bec0SDavid C Somayajulu int loop_cnt, k; 50636a62bec0SDavid C Somayajulu uint32_t read_value; 50646a62bec0SDavid C Somayajulu uint32_t read_addr, read_stride, select_addr; 50656a62bec0SDavid C Somayajulu uint32_t queue_id, read_cnt; 50666a62bec0SDavid C Somayajulu 50676a62bec0SDavid C Somayajulu read_cnt = queueEntry->read_addr_cnt; 50686a62bec0SDavid C Somayajulu read_stride = queueEntry->read_addr_stride; 50696a62bec0SDavid C Somayajulu select_addr = queueEntry->select_addr; 50706a62bec0SDavid C Somayajulu 50716a62bec0SDavid C Somayajulu for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count; 50726a62bec0SDavid C Somayajulu loop_cnt++) { 50736a62bec0SDavid C Somayajulu 50746a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr, &queue_id, 0); 50756a62bec0SDavid C Somayajulu if (ret) 50766a62bec0SDavid C Somayajulu return (0); 50776a62bec0SDavid C Somayajulu 50786a62bec0SDavid C Somayajulu read_addr = queueEntry->read_addr; 50796a62bec0SDavid C Somayajulu 50806a62bec0SDavid C Somayajulu for (k = 0; k < read_cnt; k++) { 50816a62bec0SDavid C Somayajulu 50826a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, read_addr, &read_value, 1); 50836a62bec0SDavid C Somayajulu if (ret) 50846a62bec0SDavid C Somayajulu return (0); 50856a62bec0SDavid C Somayajulu 50866a62bec0SDavid C Somayajulu *data_buff++ = read_value; 50876a62bec0SDavid C Somayajulu read_addr += read_stride; 50886a62bec0SDavid C Somayajulu } 50896a62bec0SDavid C Somayajulu 50906a62bec0SDavid C Somayajulu queue_id += queueEntry->queue_id_stride; 50916a62bec0SDavid C Somayajulu } 50926a62bec0SDavid C Somayajulu 50936a62bec0SDavid C Somayajulu return (loop_cnt * (read_cnt * sizeof(uint32_t))); 50946a62bec0SDavid C Somayajulu } 50956a62bec0SDavid C Somayajulu 50966a62bec0SDavid C Somayajulu /* 50976a62bec0SDavid C Somayajulu * Handling control entries. 50986a62bec0SDavid C Somayajulu */ 50996a62bec0SDavid C Somayajulu 51006a62bec0SDavid C Somayajulu static uint32_t 51016a62bec0SDavid C Somayajulu ql_cntrl(qla_host_t *ha, 51026a62bec0SDavid C Somayajulu ql_minidump_template_hdr_t *template_hdr, 51036a62bec0SDavid C Somayajulu ql_minidump_entry_cntrl_t *crbEntry) 51046a62bec0SDavid C Somayajulu { 51056a62bec0SDavid C Somayajulu int ret; 51066a62bec0SDavid C Somayajulu int count; 51076a62bec0SDavid C Somayajulu uint32_t opcode, read_value, addr, entry_addr; 51086a62bec0SDavid C Somayajulu long timeout; 51096a62bec0SDavid C Somayajulu 51106a62bec0SDavid C Somayajulu entry_addr = crbEntry->addr; 51116a62bec0SDavid C Somayajulu 51126a62bec0SDavid C Somayajulu for (count = 0; count < crbEntry->op_count; count++) { 51136a62bec0SDavid C Somayajulu opcode = crbEntry->opcode; 51146a62bec0SDavid C Somayajulu 51156a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_WR) { 51166a62bec0SDavid C Somayajulu 51176a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, 51186a62bec0SDavid C Somayajulu &crbEntry->value_1, 0); 51196a62bec0SDavid C Somayajulu if (ret) 51206a62bec0SDavid C Somayajulu return (0); 51216a62bec0SDavid C Somayajulu 51226a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_WR; 51236a62bec0SDavid C Somayajulu } 51246a62bec0SDavid C Somayajulu 51256a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_RW) { 51266a62bec0SDavid C Somayajulu 51276a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1); 51286a62bec0SDavid C Somayajulu if (ret) 51296a62bec0SDavid C Somayajulu return (0); 51306a62bec0SDavid C Somayajulu 51316a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0); 51326a62bec0SDavid C Somayajulu if (ret) 51336a62bec0SDavid C Somayajulu return (0); 51346a62bec0SDavid C Somayajulu 51356a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_RW; 51366a62bec0SDavid C Somayajulu } 51376a62bec0SDavid C Somayajulu 51386a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_AND) { 51396a62bec0SDavid C Somayajulu 51406a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1); 51416a62bec0SDavid C Somayajulu if (ret) 51426a62bec0SDavid C Somayajulu return (0); 51436a62bec0SDavid C Somayajulu 51446a62bec0SDavid C Somayajulu read_value &= crbEntry->value_2; 51456a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_AND; 51466a62bec0SDavid C Somayajulu 51476a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_OR) { 51486a62bec0SDavid C Somayajulu read_value |= crbEntry->value_3; 51496a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_OR; 51506a62bec0SDavid C Somayajulu } 51516a62bec0SDavid C Somayajulu 51526a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0); 51536a62bec0SDavid C Somayajulu if (ret) 51546a62bec0SDavid C Somayajulu return (0); 51556a62bec0SDavid C Somayajulu } 51566a62bec0SDavid C Somayajulu 51576a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_OR) { 51586a62bec0SDavid C Somayajulu 51596a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 1); 51606a62bec0SDavid C Somayajulu if (ret) 51616a62bec0SDavid C Somayajulu return (0); 51626a62bec0SDavid C Somayajulu 51636a62bec0SDavid C Somayajulu read_value |= crbEntry->value_3; 51646a62bec0SDavid C Somayajulu 51656a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, entry_addr, &read_value, 0); 51666a62bec0SDavid C Somayajulu if (ret) 51676a62bec0SDavid C Somayajulu return (0); 51686a62bec0SDavid C Somayajulu 51696a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_OR; 51706a62bec0SDavid C Somayajulu } 51716a62bec0SDavid C Somayajulu 51726a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_POLL) { 51736a62bec0SDavid C Somayajulu 51746a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_POLL; 51756a62bec0SDavid C Somayajulu timeout = crbEntry->poll_timeout; 51766a62bec0SDavid C Somayajulu addr = entry_addr; 51776a62bec0SDavid C Somayajulu 51786a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &read_value, 1); 51796a62bec0SDavid C Somayajulu if (ret) 51806a62bec0SDavid C Somayajulu return (0); 51816a62bec0SDavid C Somayajulu 51826a62bec0SDavid C Somayajulu while ((read_value & crbEntry->value_2) 51836a62bec0SDavid C Somayajulu != crbEntry->value_1) { 51846a62bec0SDavid C Somayajulu 51856a62bec0SDavid C Somayajulu if (timeout) { 51866a62bec0SDavid C Somayajulu qla_mdelay(__func__, 1); 51876a62bec0SDavid C Somayajulu timeout--; 51886a62bec0SDavid C Somayajulu } else 51896a62bec0SDavid C Somayajulu break; 51906a62bec0SDavid C Somayajulu 51916a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, 51926a62bec0SDavid C Somayajulu &read_value, 1); 51936a62bec0SDavid C Somayajulu if (ret) 51946a62bec0SDavid C Somayajulu return (0); 51956a62bec0SDavid C Somayajulu } 51966a62bec0SDavid C Somayajulu 51976a62bec0SDavid C Somayajulu if (!timeout) { 51986a62bec0SDavid C Somayajulu /* 51996a62bec0SDavid C Somayajulu * Report timeout error. 52006a62bec0SDavid C Somayajulu * core dump capture failed 52016a62bec0SDavid C Somayajulu * Skip remaining entries. 52026a62bec0SDavid C Somayajulu * Write buffer out to file 52036a62bec0SDavid C Somayajulu * Use driver specific fields in template header 52046a62bec0SDavid C Somayajulu * to report this error. 52056a62bec0SDavid C Somayajulu */ 52066a62bec0SDavid C Somayajulu return (-1); 52076a62bec0SDavid C Somayajulu } 52086a62bec0SDavid C Somayajulu } 52096a62bec0SDavid C Somayajulu 52106a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_RDSTATE) { 52116a62bec0SDavid C Somayajulu /* 52126a62bec0SDavid C Somayajulu * decide which address to use. 52136a62bec0SDavid C Somayajulu */ 52146a62bec0SDavid C Somayajulu if (crbEntry->state_index_a) { 52156a62bec0SDavid C Somayajulu addr = template_hdr->saved_state_array[ 52166a62bec0SDavid C Somayajulu crbEntry-> state_index_a]; 52176a62bec0SDavid C Somayajulu } else { 52186a62bec0SDavid C Somayajulu addr = entry_addr; 52196a62bec0SDavid C Somayajulu } 52206a62bec0SDavid C Somayajulu 52216a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &read_value, 1); 52226a62bec0SDavid C Somayajulu if (ret) 52236a62bec0SDavid C Somayajulu return (0); 52246a62bec0SDavid C Somayajulu 52256a62bec0SDavid C Somayajulu template_hdr->saved_state_array[crbEntry->state_index_v] 52266a62bec0SDavid C Somayajulu = read_value; 52276a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_RDSTATE; 52286a62bec0SDavid C Somayajulu } 52296a62bec0SDavid C Somayajulu 52306a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_WRSTATE) { 52316a62bec0SDavid C Somayajulu /* 52326a62bec0SDavid C Somayajulu * decide which value to use. 52336a62bec0SDavid C Somayajulu */ 52346a62bec0SDavid C Somayajulu if (crbEntry->state_index_v) { 52356a62bec0SDavid C Somayajulu read_value = template_hdr->saved_state_array[ 52366a62bec0SDavid C Somayajulu crbEntry->state_index_v]; 52376a62bec0SDavid C Somayajulu } else { 52386a62bec0SDavid C Somayajulu read_value = crbEntry->value_1; 52396a62bec0SDavid C Somayajulu } 52406a62bec0SDavid C Somayajulu /* 52416a62bec0SDavid C Somayajulu * decide which address to use. 52426a62bec0SDavid C Somayajulu */ 52436a62bec0SDavid C Somayajulu if (crbEntry->state_index_a) { 52446a62bec0SDavid C Somayajulu addr = template_hdr->saved_state_array[ 52456a62bec0SDavid C Somayajulu crbEntry-> state_index_a]; 52466a62bec0SDavid C Somayajulu } else { 52476a62bec0SDavid C Somayajulu addr = entry_addr; 52486a62bec0SDavid C Somayajulu } 52496a62bec0SDavid C Somayajulu 52506a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr, &read_value, 0); 52516a62bec0SDavid C Somayajulu if (ret) 52526a62bec0SDavid C Somayajulu return (0); 52536a62bec0SDavid C Somayajulu 52546a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_WRSTATE; 52556a62bec0SDavid C Somayajulu } 52566a62bec0SDavid C Somayajulu 52576a62bec0SDavid C Somayajulu if (opcode & QL_DBG_OPCODE_MDSTATE) { 52586a62bec0SDavid C Somayajulu /* Read value from saved state using index */ 52596a62bec0SDavid C Somayajulu read_value = template_hdr->saved_state_array[ 52606a62bec0SDavid C Somayajulu crbEntry->state_index_v]; 52616a62bec0SDavid C Somayajulu 52626a62bec0SDavid C Somayajulu read_value <<= crbEntry->shl; /*Shift left operation */ 52636a62bec0SDavid C Somayajulu read_value >>= crbEntry->shr; /*Shift right operation */ 52646a62bec0SDavid C Somayajulu 52656a62bec0SDavid C Somayajulu if (crbEntry->value_2) { 52666a62bec0SDavid C Somayajulu /* check if AND mask is provided */ 52676a62bec0SDavid C Somayajulu read_value &= crbEntry->value_2; 52686a62bec0SDavid C Somayajulu } 52696a62bec0SDavid C Somayajulu 52706a62bec0SDavid C Somayajulu read_value |= crbEntry->value_3; /* OR operation */ 52716a62bec0SDavid C Somayajulu read_value += crbEntry->value_1; /* increment op */ 52726a62bec0SDavid C Somayajulu 52736a62bec0SDavid C Somayajulu /* Write value back to state area. */ 52746a62bec0SDavid C Somayajulu 52756a62bec0SDavid C Somayajulu template_hdr->saved_state_array[crbEntry->state_index_v] 52766a62bec0SDavid C Somayajulu = read_value; 52776a62bec0SDavid C Somayajulu opcode &= ~QL_DBG_OPCODE_MDSTATE; 52786a62bec0SDavid C Somayajulu } 52796a62bec0SDavid C Somayajulu 52806a62bec0SDavid C Somayajulu entry_addr += crbEntry->addr_stride; 52816a62bec0SDavid C Somayajulu } 52826a62bec0SDavid C Somayajulu 52836a62bec0SDavid C Somayajulu return (0); 52846a62bec0SDavid C Somayajulu } 52856a62bec0SDavid C Somayajulu 52866a62bec0SDavid C Somayajulu /* 52876a62bec0SDavid C Somayajulu * Handling rd poll entry. 52886a62bec0SDavid C Somayajulu */ 52896a62bec0SDavid C Somayajulu 52906a62bec0SDavid C Somayajulu static uint32_t 52916a62bec0SDavid C Somayajulu ql_pollrd(qla_host_t *ha, ql_minidump_entry_pollrd_t *entry, 52926a62bec0SDavid C Somayajulu uint32_t *data_buff) 52936a62bec0SDavid C Somayajulu { 52946a62bec0SDavid C Somayajulu int ret; 52956a62bec0SDavid C Somayajulu int loop_cnt; 52966a62bec0SDavid C Somayajulu uint32_t op_count, select_addr, select_value_stride, select_value; 52976a62bec0SDavid C Somayajulu uint32_t read_addr, poll, mask, data_size, data; 52986a62bec0SDavid C Somayajulu uint32_t wait_count = 0; 52996a62bec0SDavid C Somayajulu 53006a62bec0SDavid C Somayajulu select_addr = entry->select_addr; 53016a62bec0SDavid C Somayajulu read_addr = entry->read_addr; 53026a62bec0SDavid C Somayajulu select_value = entry->select_value; 53036a62bec0SDavid C Somayajulu select_value_stride = entry->select_value_stride; 53046a62bec0SDavid C Somayajulu op_count = entry->op_count; 53056a62bec0SDavid C Somayajulu poll = entry->poll; 53066a62bec0SDavid C Somayajulu mask = entry->mask; 53076a62bec0SDavid C Somayajulu data_size = entry->data_size; 53086a62bec0SDavid C Somayajulu 53096a62bec0SDavid C Somayajulu for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) { 53106a62bec0SDavid C Somayajulu 53116a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr, &select_value, 0); 53126a62bec0SDavid C Somayajulu if (ret) 53136a62bec0SDavid C Somayajulu return (0); 53146a62bec0SDavid C Somayajulu 53156a62bec0SDavid C Somayajulu wait_count = 0; 53166a62bec0SDavid C Somayajulu 53176a62bec0SDavid C Somayajulu while (wait_count < poll) { 53186a62bec0SDavid C Somayajulu 53196a62bec0SDavid C Somayajulu uint32_t temp; 53206a62bec0SDavid C Somayajulu 53216a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, select_addr, &temp, 1); 53226a62bec0SDavid C Somayajulu if (ret) 53236a62bec0SDavid C Somayajulu return (0); 53246a62bec0SDavid C Somayajulu 53256a62bec0SDavid C Somayajulu if ( (temp & mask) != 0 ) { 53266a62bec0SDavid C Somayajulu break; 53276a62bec0SDavid C Somayajulu } 53286a62bec0SDavid C Somayajulu wait_count++; 53296a62bec0SDavid C Somayajulu } 53306a62bec0SDavid C Somayajulu 53316a62bec0SDavid C Somayajulu if (wait_count == poll) { 53326a62bec0SDavid C Somayajulu device_printf(ha->pci_dev, 53336a62bec0SDavid C Somayajulu "%s: Error in processing entry\n", __func__); 53346a62bec0SDavid C Somayajulu device_printf(ha->pci_dev, 53356a62bec0SDavid C Somayajulu "%s: wait_count <0x%x> poll <0x%x>\n", 53366a62bec0SDavid C Somayajulu __func__, wait_count, poll); 53376a62bec0SDavid C Somayajulu return 0; 53386a62bec0SDavid C Somayajulu } 53396a62bec0SDavid C Somayajulu 53406a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, read_addr, &data, 1); 53416a62bec0SDavid C Somayajulu if (ret) 53426a62bec0SDavid C Somayajulu return (0); 53436a62bec0SDavid C Somayajulu 53446a62bec0SDavid C Somayajulu *data_buff++ = select_value; 53456a62bec0SDavid C Somayajulu *data_buff++ = data; 53466a62bec0SDavid C Somayajulu select_value = select_value + select_value_stride; 53476a62bec0SDavid C Somayajulu } 53486a62bec0SDavid C Somayajulu 53496a62bec0SDavid C Somayajulu /* 53506a62bec0SDavid C Somayajulu * for testing purpose we return amount of data written 53516a62bec0SDavid C Somayajulu */ 53526a62bec0SDavid C Somayajulu return (loop_cnt * (2 * sizeof(uint32_t))); 53536a62bec0SDavid C Somayajulu } 53546a62bec0SDavid C Somayajulu 53556a62bec0SDavid C Somayajulu 53566a62bec0SDavid C Somayajulu /* 53576a62bec0SDavid C Somayajulu * Handling rd modify write poll entry. 53586a62bec0SDavid C Somayajulu */ 53596a62bec0SDavid C Somayajulu 53606a62bec0SDavid C Somayajulu static uint32_t 53616a62bec0SDavid C Somayajulu ql_pollrd_modify_write(qla_host_t *ha, 53626a62bec0SDavid C Somayajulu ql_minidump_entry_rd_modify_wr_with_poll_t *entry, 53636a62bec0SDavid C Somayajulu uint32_t *data_buff) 53646a62bec0SDavid C Somayajulu { 53656a62bec0SDavid C Somayajulu int ret; 53666a62bec0SDavid C Somayajulu uint32_t addr_1, addr_2, value_1, value_2, data; 53676a62bec0SDavid C Somayajulu uint32_t poll, mask, data_size, modify_mask; 53686a62bec0SDavid C Somayajulu uint32_t wait_count = 0; 53696a62bec0SDavid C Somayajulu 53706a62bec0SDavid C Somayajulu addr_1 = entry->addr_1; 53716a62bec0SDavid C Somayajulu addr_2 = entry->addr_2; 53726a62bec0SDavid C Somayajulu value_1 = entry->value_1; 53736a62bec0SDavid C Somayajulu value_2 = entry->value_2; 53746a62bec0SDavid C Somayajulu 53756a62bec0SDavid C Somayajulu poll = entry->poll; 53766a62bec0SDavid C Somayajulu mask = entry->mask; 53776a62bec0SDavid C Somayajulu modify_mask = entry->modify_mask; 53786a62bec0SDavid C Somayajulu data_size = entry->data_size; 53796a62bec0SDavid C Somayajulu 53806a62bec0SDavid C Somayajulu 53816a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_1, &value_1, 0); 53826a62bec0SDavid C Somayajulu if (ret) 53836a62bec0SDavid C Somayajulu return (0); 53846a62bec0SDavid C Somayajulu 53856a62bec0SDavid C Somayajulu wait_count = 0; 53866a62bec0SDavid C Somayajulu while (wait_count < poll) { 53876a62bec0SDavid C Somayajulu 53886a62bec0SDavid C Somayajulu uint32_t temp; 53896a62bec0SDavid C Somayajulu 53906a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1); 53916a62bec0SDavid C Somayajulu if (ret) 53926a62bec0SDavid C Somayajulu return (0); 53936a62bec0SDavid C Somayajulu 53946a62bec0SDavid C Somayajulu if ( (temp & mask) != 0 ) { 53956a62bec0SDavid C Somayajulu break; 53966a62bec0SDavid C Somayajulu } 53976a62bec0SDavid C Somayajulu wait_count++; 53986a62bec0SDavid C Somayajulu } 53996a62bec0SDavid C Somayajulu 54006a62bec0SDavid C Somayajulu if (wait_count == poll) { 54016a62bec0SDavid C Somayajulu device_printf(ha->pci_dev, "%s Error in processing entry\n", 54026a62bec0SDavid C Somayajulu __func__); 54036a62bec0SDavid C Somayajulu } else { 54046a62bec0SDavid C Somayajulu 54056a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_2, &data, 1); 54066a62bec0SDavid C Somayajulu if (ret) 54076a62bec0SDavid C Somayajulu return (0); 54086a62bec0SDavid C Somayajulu 54096a62bec0SDavid C Somayajulu data = (data & modify_mask); 54106a62bec0SDavid C Somayajulu 54116a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_2, &data, 0); 54126a62bec0SDavid C Somayajulu if (ret) 54136a62bec0SDavid C Somayajulu return (0); 54146a62bec0SDavid C Somayajulu 54156a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_1, &value_2, 0); 54166a62bec0SDavid C Somayajulu if (ret) 54176a62bec0SDavid C Somayajulu return (0); 54186a62bec0SDavid C Somayajulu 54196a62bec0SDavid C Somayajulu /* Poll again */ 54206a62bec0SDavid C Somayajulu wait_count = 0; 54216a62bec0SDavid C Somayajulu while (wait_count < poll) { 54226a62bec0SDavid C Somayajulu 54236a62bec0SDavid C Somayajulu uint32_t temp; 54246a62bec0SDavid C Somayajulu 54256a62bec0SDavid C Somayajulu ret = ql_rdwr_indreg32(ha, addr_1, &temp, 1); 54266a62bec0SDavid C Somayajulu if (ret) 54276a62bec0SDavid C Somayajulu return (0); 54286a62bec0SDavid C Somayajulu 54296a62bec0SDavid C Somayajulu if ( (temp & mask) != 0 ) { 54306a62bec0SDavid C Somayajulu break; 54316a62bec0SDavid C Somayajulu } 54326a62bec0SDavid C Somayajulu wait_count++; 54336a62bec0SDavid C Somayajulu } 54346a62bec0SDavid C Somayajulu *data_buff++ = addr_2; 54356a62bec0SDavid C Somayajulu *data_buff++ = data; 54366a62bec0SDavid C Somayajulu } 54376a62bec0SDavid C Somayajulu 54386a62bec0SDavid C Somayajulu /* 54396a62bec0SDavid C Somayajulu * for testing purpose we return amount of data written 54406a62bec0SDavid C Somayajulu */ 54416a62bec0SDavid C Somayajulu return (2 * sizeof(uint32_t)); 54426a62bec0SDavid C Somayajulu } 54436a62bec0SDavid C Somayajulu 54446a62bec0SDavid C Somayajulu 5445