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