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" 44f10a77bbSDavid C Somayajulu 45f10a77bbSDavid C Somayajulu /* 46f10a77bbSDavid C Somayajulu * Static Functions 47f10a77bbSDavid C Somayajulu */ 48f10a77bbSDavid C Somayajulu 49f10a77bbSDavid C Somayajulu static void qla_del_rcv_cntxt(qla_host_t *ha); 50f10a77bbSDavid C Somayajulu static int qla_init_rcv_cntxt(qla_host_t *ha); 51f10a77bbSDavid C Somayajulu static void qla_del_xmt_cntxt(qla_host_t *ha); 52f10a77bbSDavid C Somayajulu static int qla_init_xmt_cntxt(qla_host_t *ha); 53f10a77bbSDavid C Somayajulu static void qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx); 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); 76f10a77bbSDavid C Somayajulu 77f10a77bbSDavid C Somayajulu static int qla_minidump_init(qla_host_t *ha); 78f10a77bbSDavid C Somayajulu static void qla_minidump_free(qla_host_t *ha); 79f10a77bbSDavid C Somayajulu 80f10a77bbSDavid C Somayajulu 81f10a77bbSDavid C Somayajulu static int 82f10a77bbSDavid C Somayajulu qla_sysctl_get_drvr_stats(SYSCTL_HANDLER_ARGS) 83f10a77bbSDavid C Somayajulu { 84f10a77bbSDavid C Somayajulu int err = 0, ret; 85f10a77bbSDavid C Somayajulu qla_host_t *ha; 86f10a77bbSDavid C Somayajulu uint32_t i; 87f10a77bbSDavid C Somayajulu 88f10a77bbSDavid C Somayajulu err = sysctl_handle_int(oidp, &ret, 0, req); 89f10a77bbSDavid C Somayajulu 90f10a77bbSDavid C Somayajulu if (err || !req->newptr) 91f10a77bbSDavid C Somayajulu return (err); 92f10a77bbSDavid C Somayajulu 93f10a77bbSDavid C Somayajulu if (ret == 1) { 94f10a77bbSDavid C Somayajulu 95f10a77bbSDavid C Somayajulu ha = (qla_host_t *)arg1; 96f10a77bbSDavid C Somayajulu 97f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) 98f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, 99f10a77bbSDavid C Somayajulu "%s: sds_ring[%d] = %p\n", __func__,i, 100f10a77bbSDavid C Somayajulu (void *)ha->hw.sds[i].intr_count); 101f10a77bbSDavid C Somayajulu 102f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) 103f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, 104f10a77bbSDavid C Somayajulu "%s: tx[%d] = %p\n", __func__,i, 105f10a77bbSDavid C Somayajulu (void *)ha->tx_ring[i].count); 106f10a77bbSDavid C Somayajulu 107f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) 108f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, 109f10a77bbSDavid C Somayajulu "%s: rds_ring[%d] = %p\n", __func__,i, 110f10a77bbSDavid C Somayajulu (void *)ha->hw.rds[i].count); 111f10a77bbSDavid C Somayajulu 112f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: lro_pkt_count = %p\n", __func__, 113f10a77bbSDavid C Somayajulu (void *)ha->lro_pkt_count); 114f10a77bbSDavid C Somayajulu 115f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: lro_bytes = %p\n", __func__, 116f10a77bbSDavid C Somayajulu (void *)ha->lro_bytes); 11735291c22SDavid C Somayajulu 11835291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV 11935291c22SDavid C Somayajulu device_printf(ha->pci_dev, "%s: iscsi_pkts = %p\n", __func__, 12035291c22SDavid C Somayajulu (void *)ha->hw.iscsi_pkt_count); 12135291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */ 12235291c22SDavid C Somayajulu 12335291c22SDavid C Somayajulu } 12435291c22SDavid C Somayajulu return (err); 12535291c22SDavid C Somayajulu } 12635291c22SDavid C Somayajulu 12735291c22SDavid C Somayajulu static int 12835291c22SDavid C Somayajulu qla_sysctl_get_quick_stats(SYSCTL_HANDLER_ARGS) 12935291c22SDavid C Somayajulu { 13035291c22SDavid C Somayajulu int err, ret = 0; 13135291c22SDavid C Somayajulu qla_host_t *ha; 13235291c22SDavid C Somayajulu 13335291c22SDavid C Somayajulu err = sysctl_handle_int(oidp, &ret, 0, req); 13435291c22SDavid C Somayajulu 13535291c22SDavid C Somayajulu if (err || !req->newptr) 13635291c22SDavid C Somayajulu return (err); 13735291c22SDavid C Somayajulu 13835291c22SDavid C Somayajulu if (ret == 1) { 13935291c22SDavid C Somayajulu ha = (qla_host_t *)arg1; 14035291c22SDavid C Somayajulu qla_get_quick_stats(ha); 141f10a77bbSDavid C Somayajulu } 142f10a77bbSDavid C Somayajulu return (err); 143f10a77bbSDavid C Somayajulu } 144f10a77bbSDavid C Somayajulu 145f10a77bbSDavid C Somayajulu #ifdef QL_DBG 146f10a77bbSDavid C Somayajulu 147f10a77bbSDavid C Somayajulu static void 148f10a77bbSDavid C Somayajulu qla_stop_pegs(qla_host_t *ha) 149f10a77bbSDavid C Somayajulu { 150f10a77bbSDavid C Somayajulu uint32_t val = 1; 151f10a77bbSDavid C Somayajulu 152f10a77bbSDavid C Somayajulu ql_rdwr_indreg32(ha, Q8_CRB_PEG_0, &val, 0); 153f10a77bbSDavid C Somayajulu ql_rdwr_indreg32(ha, Q8_CRB_PEG_1, &val, 0); 154f10a77bbSDavid C Somayajulu ql_rdwr_indreg32(ha, Q8_CRB_PEG_2, &val, 0); 155f10a77bbSDavid C Somayajulu ql_rdwr_indreg32(ha, Q8_CRB_PEG_3, &val, 0); 156f10a77bbSDavid C Somayajulu ql_rdwr_indreg32(ha, Q8_CRB_PEG_4, &val, 0); 157f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s PEGS HALTED!!!!!\n", __func__); 158f10a77bbSDavid C Somayajulu } 159f10a77bbSDavid C Somayajulu 160f10a77bbSDavid C Somayajulu static int 161f10a77bbSDavid C Somayajulu qla_sysctl_stop_pegs(SYSCTL_HANDLER_ARGS) 162f10a77bbSDavid C Somayajulu { 163f10a77bbSDavid C Somayajulu int err, ret = 0; 164f10a77bbSDavid C Somayajulu qla_host_t *ha; 165f10a77bbSDavid C Somayajulu 166f10a77bbSDavid C Somayajulu err = sysctl_handle_int(oidp, &ret, 0, req); 167f10a77bbSDavid C Somayajulu 168f10a77bbSDavid C Somayajulu 169f10a77bbSDavid C Somayajulu if (err || !req->newptr) 170f10a77bbSDavid C Somayajulu return (err); 171f10a77bbSDavid C Somayajulu 172f10a77bbSDavid C Somayajulu if (ret == 1) { 173f10a77bbSDavid C Somayajulu ha = (qla_host_t *)arg1; 174f10a77bbSDavid C Somayajulu (void)QLA_LOCK(ha, __func__, 0); 175f10a77bbSDavid C Somayajulu qla_stop_pegs(ha); 176f10a77bbSDavid C Somayajulu QLA_UNLOCK(ha, __func__); 177f10a77bbSDavid C Somayajulu } 178f10a77bbSDavid C Somayajulu 179f10a77bbSDavid C Somayajulu return err; 180f10a77bbSDavid C Somayajulu } 181f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */ 182f10a77bbSDavid C Somayajulu 18335291c22SDavid C Somayajulu static int 18435291c22SDavid C Somayajulu qla_validate_set_port_cfg_bit(uint32_t bits) 18535291c22SDavid C Somayajulu { 18635291c22SDavid C Somayajulu if ((bits & 0xF) > 1) 18735291c22SDavid C Somayajulu return (-1); 18835291c22SDavid C Somayajulu 18935291c22SDavid C Somayajulu if (((bits >> 4) & 0xF) > 2) 19035291c22SDavid C Somayajulu return (-1); 19135291c22SDavid C Somayajulu 19235291c22SDavid C Somayajulu if (((bits >> 8) & 0xF) > 2) 19335291c22SDavid C Somayajulu return (-1); 19435291c22SDavid C Somayajulu 19535291c22SDavid C Somayajulu return (0); 19635291c22SDavid C Somayajulu } 19735291c22SDavid C Somayajulu 19835291c22SDavid C Somayajulu static int 19935291c22SDavid C Somayajulu qla_sysctl_port_cfg(SYSCTL_HANDLER_ARGS) 20035291c22SDavid C Somayajulu { 20135291c22SDavid C Somayajulu int err, ret = 0; 20235291c22SDavid C Somayajulu qla_host_t *ha; 20335291c22SDavid C Somayajulu uint32_t cfg_bits; 20435291c22SDavid C Somayajulu 20535291c22SDavid C Somayajulu err = sysctl_handle_int(oidp, &ret, 0, req); 20635291c22SDavid C Somayajulu 20735291c22SDavid C Somayajulu if (err || !req->newptr) 20835291c22SDavid C Somayajulu return (err); 20935291c22SDavid C Somayajulu 21035291c22SDavid C Somayajulu if ((qla_validate_set_port_cfg_bit((uint32_t)ret) == 0)) { 21135291c22SDavid C Somayajulu 21235291c22SDavid C Somayajulu ha = (qla_host_t *)arg1; 21335291c22SDavid C Somayajulu 21435291c22SDavid C Somayajulu err = qla_get_port_config(ha, &cfg_bits); 21535291c22SDavid C Somayajulu 21635291c22SDavid C Somayajulu if (err) 21735291c22SDavid C Somayajulu goto qla_sysctl_set_port_cfg_exit; 21835291c22SDavid C Somayajulu 21935291c22SDavid C Somayajulu if (ret & 0x1) { 22035291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_DCBX_ENABLE; 22135291c22SDavid C Somayajulu } else { 22235291c22SDavid C Somayajulu cfg_bits &= ~Q8_PORT_CFG_BITS_DCBX_ENABLE; 22335291c22SDavid C Somayajulu } 22435291c22SDavid C Somayajulu 22535291c22SDavid C Somayajulu ret = ret >> 4; 22635291c22SDavid C Somayajulu cfg_bits &= ~Q8_PORT_CFG_BITS_PAUSE_CFG_MASK; 22735291c22SDavid C Somayajulu 22835291c22SDavid C Somayajulu if ((ret & 0xF) == 0) { 22935291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_DISABLED; 23035291c22SDavid C Somayajulu } else if ((ret & 0xF) == 1){ 23135291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_STD; 23235291c22SDavid C Somayajulu } else { 23335291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_PAUSE_PPM; 23435291c22SDavid C Somayajulu } 23535291c22SDavid C Somayajulu 23635291c22SDavid C Somayajulu ret = ret >> 4; 23735291c22SDavid C Somayajulu cfg_bits &= ~Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK; 23835291c22SDavid C Somayajulu 23935291c22SDavid C Somayajulu if (ret == 0) { 24035291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT_RCV; 24135291c22SDavid C Somayajulu } else if (ret == 1){ 24235291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_XMT; 24335291c22SDavid C Somayajulu } else { 24435291c22SDavid C Somayajulu cfg_bits |= Q8_PORT_CFG_BITS_STDPAUSE_RCV; 24535291c22SDavid C Somayajulu } 24635291c22SDavid C Somayajulu 24735291c22SDavid C Somayajulu err = qla_set_port_config(ha, cfg_bits); 24835291c22SDavid C Somayajulu } else { 24935291c22SDavid C Somayajulu ha = (qla_host_t *)arg1; 25035291c22SDavid C Somayajulu 25135291c22SDavid C Somayajulu err = qla_get_port_config(ha, &cfg_bits); 25235291c22SDavid C Somayajulu } 25335291c22SDavid C Somayajulu 25435291c22SDavid C Somayajulu qla_sysctl_set_port_cfg_exit: 25535291c22SDavid C Somayajulu return err; 25635291c22SDavid C Somayajulu } 25735291c22SDavid C Somayajulu 258f10a77bbSDavid C Somayajulu /* 259f10a77bbSDavid C Somayajulu * Name: ql_hw_add_sysctls 260f10a77bbSDavid C Somayajulu * Function: Add P3Plus specific sysctls 261f10a77bbSDavid C Somayajulu */ 262f10a77bbSDavid C Somayajulu void 263f10a77bbSDavid C Somayajulu ql_hw_add_sysctls(qla_host_t *ha) 264f10a77bbSDavid C Somayajulu { 265f10a77bbSDavid C Somayajulu device_t dev; 266f10a77bbSDavid C Somayajulu 267f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 268f10a77bbSDavid C Somayajulu 269f10a77bbSDavid C Somayajulu ha->hw.num_sds_rings = MAX_SDS_RINGS; 270f10a77bbSDavid C Somayajulu ha->hw.num_rds_rings = MAX_RDS_RINGS; 271f10a77bbSDavid C Somayajulu ha->hw.num_tx_rings = NUM_TX_RINGS; 272f10a77bbSDavid C Somayajulu 273f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 274f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 275f10a77bbSDavid C Somayajulu OID_AUTO, "num_rds_rings", CTLFLAG_RD, &ha->hw.num_rds_rings, 276f10a77bbSDavid C Somayajulu ha->hw.num_rds_rings, "Number of Rcv Descriptor Rings"); 277f10a77bbSDavid C Somayajulu 278f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 279f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 280f10a77bbSDavid C Somayajulu OID_AUTO, "num_sds_rings", CTLFLAG_RD, &ha->hw.num_sds_rings, 281f10a77bbSDavid C Somayajulu ha->hw.num_sds_rings, "Number of Status Descriptor Rings"); 282f10a77bbSDavid C Somayajulu 283f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 284f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 285f10a77bbSDavid C Somayajulu OID_AUTO, "num_tx_rings", CTLFLAG_RD, &ha->hw.num_tx_rings, 286f10a77bbSDavid C Somayajulu ha->hw.num_tx_rings, "Number of Transmit Rings"); 287f10a77bbSDavid C Somayajulu 288f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 289f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 290f10a77bbSDavid C Somayajulu OID_AUTO, "tx_ring_index", CTLFLAG_RW, &ha->txr_idx, 291f10a77bbSDavid C Somayajulu ha->txr_idx, "Tx Ring Used"); 292f10a77bbSDavid C Somayajulu 293f10a77bbSDavid C Somayajulu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 294f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 295f10a77bbSDavid C Somayajulu OID_AUTO, "drvr_stats", CTLTYPE_INT | CTLFLAG_RW, 296f10a77bbSDavid C Somayajulu (void *)ha, 0, 297f10a77bbSDavid C Somayajulu qla_sysctl_get_drvr_stats, "I", "Driver Maintained Statistics"); 298f10a77bbSDavid C Somayajulu 29935291c22SDavid C Somayajulu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 30035291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 30135291c22SDavid C Somayajulu OID_AUTO, "quick_stats", CTLTYPE_INT | CTLFLAG_RW, 30235291c22SDavid C Somayajulu (void *)ha, 0, 30335291c22SDavid C Somayajulu qla_sysctl_get_quick_stats, "I", "Quick Statistics"); 30435291c22SDavid C Somayajulu 305f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 306f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 307f10a77bbSDavid C Somayajulu OID_AUTO, "max_tx_segs", CTLFLAG_RD, &ha->hw.max_tx_segs, 308f10a77bbSDavid C Somayajulu ha->hw.max_tx_segs, "Max # of Segments in a non-TSO pkt"); 309f10a77bbSDavid C Somayajulu 310f10a77bbSDavid C Somayajulu ha->hw.sds_cidx_thres = 32; 311f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 312f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 313f10a77bbSDavid C Somayajulu OID_AUTO, "sds_cidx_thres", CTLFLAG_RW, &ha->hw.sds_cidx_thres, 314f10a77bbSDavid C Somayajulu ha->hw.sds_cidx_thres, 315f10a77bbSDavid C Somayajulu "Number of SDS entries to process before updating" 316f10a77bbSDavid C Somayajulu " SDS Ring Consumer Index"); 317f10a77bbSDavid C Somayajulu 318f10a77bbSDavid C Somayajulu ha->hw.rds_pidx_thres = 32; 319f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 320f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 321f10a77bbSDavid C Somayajulu OID_AUTO, "rds_pidx_thres", CTLFLAG_RW, &ha->hw.rds_pidx_thres, 322f10a77bbSDavid C Somayajulu ha->hw.rds_pidx_thres, 323f10a77bbSDavid C Somayajulu "Number of Rcv Rings Entries to post before updating" 324f10a77bbSDavid C Somayajulu " RDS Ring Producer Index"); 325f10a77bbSDavid C Somayajulu 32635291c22SDavid C Somayajulu ha->hw.rcv_intr_coalesce = (3 << 16) | 256; 327c12c5bfbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 328c12c5bfbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 32935291c22SDavid C Somayajulu OID_AUTO, "rcv_intr_coalesce", CTLFLAG_RW, 33035291c22SDavid C Somayajulu &ha->hw.rcv_intr_coalesce, 33135291c22SDavid C Somayajulu ha->hw.rcv_intr_coalesce, 33235291c22SDavid C Somayajulu "Rcv Intr Coalescing Parameters\n" 33335291c22SDavid C Somayajulu "\tbits 15:0 max packets\n" 33435291c22SDavid C Somayajulu "\tbits 31:16 max micro-seconds to wait\n" 33535291c22SDavid C Somayajulu "\tplease run\n" 33635291c22SDavid C Somayajulu "\tifconfig <if> down && ifconfig <if> up\n" 33735291c22SDavid C Somayajulu "\tto take effect \n"); 33835291c22SDavid C Somayajulu 33935291c22SDavid C Somayajulu ha->hw.xmt_intr_coalesce = (64 << 16) | 64; 34035291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 34135291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 34235291c22SDavid C Somayajulu OID_AUTO, "xmt_intr_coalesce", CTLFLAG_RW, 34335291c22SDavid C Somayajulu &ha->hw.xmt_intr_coalesce, 34435291c22SDavid C Somayajulu ha->hw.xmt_intr_coalesce, 34535291c22SDavid C Somayajulu "Xmt Intr Coalescing Parameters\n" 34635291c22SDavid C Somayajulu "\tbits 15:0 max packets\n" 34735291c22SDavid C Somayajulu "\tbits 31:16 max micro-seconds to wait\n" 34835291c22SDavid C Somayajulu "\tplease run\n" 34935291c22SDavid C Somayajulu "\tifconfig <if> down && ifconfig <if> up\n" 35035291c22SDavid C Somayajulu "\tto take effect \n"); 35135291c22SDavid 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, "port_cfg", CTLTYPE_INT | CTLFLAG_RW, 35535291c22SDavid C Somayajulu (void *)ha, 0, 35635291c22SDavid C Somayajulu qla_sysctl_port_cfg, "I", 35735291c22SDavid C Somayajulu "Set Port Configuration if values below " 35835291c22SDavid C Somayajulu "otherwise Get Port Configuration\n" 35935291c22SDavid C Somayajulu "\tBits 0-3 ; 1 = DCBX Enable; 0 = DCBX Disable\n" 36035291c22SDavid C Somayajulu "\tBits 4-7 : 0 = no pause; 1 = std ; 2 = ppm \n" 36135291c22SDavid C Somayajulu "\tBits 8-11: std pause cfg; 0 = xmt and rcv;" 36235291c22SDavid C Somayajulu " 1 = xmt only; 2 = rcv only;\n" 36335291c22SDavid C Somayajulu ); 36435291c22SDavid C Somayajulu 36535291c22SDavid C Somayajulu ha->hw.enable_9kb = 1; 36635291c22SDavid C Somayajulu 36735291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 36835291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 36935291c22SDavid C Somayajulu OID_AUTO, "enable_9kb", CTLFLAG_RW, &ha->hw.enable_9kb, 37035291c22SDavid C Somayajulu ha->hw.enable_9kb, "Enable 9Kbyte Buffers when MTU = 9000"); 371c12c5bfbSDavid C Somayajulu 372f10a77bbSDavid C Somayajulu ha->hw.mdump_active = 0; 373f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 374f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 375f10a77bbSDavid C Somayajulu OID_AUTO, "minidump_active", CTLFLAG_RW, &ha->hw.mdump_active, 376f10a77bbSDavid C Somayajulu ha->hw.mdump_active, 377f10a77bbSDavid C Somayajulu "Minidump Utility is Active \n" 378f10a77bbSDavid C Somayajulu "\t 0 = Minidump Utility is not active\n" 379f10a77bbSDavid C Somayajulu "\t 1 = Minidump Utility is retrieved on this port\n" 380f10a77bbSDavid C Somayajulu "\t 2 = Minidump Utility is retrieved on the other port\n"); 381f10a77bbSDavid C Somayajulu 382f10a77bbSDavid C Somayajulu ha->hw.mdump_start = 0; 383f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 384f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 385f10a77bbSDavid C Somayajulu OID_AUTO, "minidump_start", CTLFLAG_RW, 386f10a77bbSDavid C Somayajulu &ha->hw.mdump_start, ha->hw.mdump_start, 387f10a77bbSDavid C Somayajulu "Minidump Utility can start minidump process"); 388f10a77bbSDavid C Somayajulu #ifdef QL_DBG 389f10a77bbSDavid C Somayajulu 390467dcb5aSDavid C Somayajulu ha->err_inject = 0; 391f10a77bbSDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 392f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 393f10a77bbSDavid C Somayajulu OID_AUTO, "err_inject", 394f10a77bbSDavid C Somayajulu CTLFLAG_RW, &ha->err_inject, ha->err_inject, 395f10a77bbSDavid C Somayajulu "Error to be injected\n" 396f10a77bbSDavid C Somayajulu "\t\t\t 0: No Errors\n" 397f10a77bbSDavid C Somayajulu "\t\t\t 1: rcv: rxb struct invalid\n" 398f10a77bbSDavid C Somayajulu "\t\t\t 2: rcv: mp == NULL\n" 399f10a77bbSDavid C Somayajulu "\t\t\t 3: lro: rxb struct invalid\n" 400f10a77bbSDavid C Somayajulu "\t\t\t 4: lro: mp == NULL\n" 401f10a77bbSDavid C Somayajulu "\t\t\t 5: rcv: num handles invalid\n" 402f10a77bbSDavid C Somayajulu "\t\t\t 6: reg: indirect reg rd_wr failure\n" 403f10a77bbSDavid C Somayajulu "\t\t\t 7: ocm: offchip memory rd_wr failure\n" 404f10a77bbSDavid C Somayajulu "\t\t\t 8: mbx: mailbox command failure\n" 405f10a77bbSDavid C Somayajulu "\t\t\t 9: heartbeat failure\n" 406f10a77bbSDavid C Somayajulu "\t\t\t A: temperature failure\n" ); 407f10a77bbSDavid C Somayajulu 408f10a77bbSDavid C Somayajulu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 409f10a77bbSDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 410f10a77bbSDavid C Somayajulu OID_AUTO, "peg_stop", CTLTYPE_INT | CTLFLAG_RW, 411f10a77bbSDavid C Somayajulu (void *)ha, 0, 412f10a77bbSDavid C Somayajulu qla_sysctl_stop_pegs, "I", "Peg Stop"); 413f10a77bbSDavid C Somayajulu 414f10a77bbSDavid C Somayajulu #endif /* #ifdef QL_DBG */ 415f10a77bbSDavid C Somayajulu 41635291c22SDavid C Somayajulu ha->hw.user_pri_nic = 0; 41735291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 41835291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 41935291c22SDavid C Somayajulu OID_AUTO, "user_pri_nic", CTLFLAG_RW, &ha->hw.user_pri_nic, 42035291c22SDavid C Somayajulu ha->hw.user_pri_nic, 42135291c22SDavid C Somayajulu "VLAN Tag User Priority for Normal Ethernet Packets"); 42235291c22SDavid C Somayajulu 42335291c22SDavid C Somayajulu ha->hw.user_pri_iscsi = 4; 42435291c22SDavid C Somayajulu SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 42535291c22SDavid C Somayajulu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 42635291c22SDavid C Somayajulu OID_AUTO, "user_pri_iscsi", CTLFLAG_RW, &ha->hw.user_pri_iscsi, 42735291c22SDavid C Somayajulu ha->hw.user_pri_iscsi, 42835291c22SDavid C Somayajulu "VLAN Tag User Priority for iSCSI Packets"); 42935291c22SDavid C Somayajulu 430f10a77bbSDavid C Somayajulu } 431f10a77bbSDavid C Somayajulu 432f10a77bbSDavid C Somayajulu void 433f10a77bbSDavid C Somayajulu ql_hw_link_status(qla_host_t *ha) 434f10a77bbSDavid C Somayajulu { 435f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "cable_oui\t\t 0x%08x\n", ha->hw.cable_oui); 436f10a77bbSDavid C Somayajulu 437f10a77bbSDavid C Somayajulu if (ha->hw.link_up) { 438f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link Up\n"); 439f10a77bbSDavid C Somayajulu } else { 440f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link Down\n"); 441f10a77bbSDavid C Somayajulu } 442f10a77bbSDavid C Somayajulu 443f10a77bbSDavid C Somayajulu if (ha->hw.flags.fduplex) { 444f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Full Duplex\n"); 445f10a77bbSDavid C Somayajulu } else { 446f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Half Duplex\n"); 447f10a77bbSDavid C Somayajulu } 448f10a77bbSDavid C Somayajulu 449f10a77bbSDavid C Somayajulu if (ha->hw.flags.autoneg) { 450f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Auto Negotiation Enabled\n"); 451f10a77bbSDavid C Somayajulu } else { 452f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Auto Negotiation Disabled\n"); 453f10a77bbSDavid C Somayajulu } 454f10a77bbSDavid C Somayajulu 455f10a77bbSDavid C Somayajulu switch (ha->hw.link_speed) { 456f10a77bbSDavid C Somayajulu case 0x710: 457f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t 10Gps\n"); 458f10a77bbSDavid C Somayajulu break; 459f10a77bbSDavid C Somayajulu 460f10a77bbSDavid C Somayajulu case 0x3E8: 461f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t 1Gps\n"); 462f10a77bbSDavid C Somayajulu break; 463f10a77bbSDavid C Somayajulu 464f10a77bbSDavid C Somayajulu case 0x64: 465f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t 100Mbps\n"); 466f10a77bbSDavid C Somayajulu break; 467f10a77bbSDavid C Somayajulu 468f10a77bbSDavid C Somayajulu default: 469f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "link speed\t\t Unknown\n"); 470f10a77bbSDavid C Somayajulu break; 471f10a77bbSDavid C Somayajulu } 472f10a77bbSDavid C Somayajulu 473f10a77bbSDavid C Somayajulu switch (ha->hw.module_type) { 474f10a77bbSDavid C Somayajulu 475f10a77bbSDavid C Somayajulu case 0x01: 476f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GBase-LRM\n"); 477f10a77bbSDavid C Somayajulu break; 478f10a77bbSDavid C Somayajulu 479f10a77bbSDavid C Somayajulu case 0x02: 480f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GBase-LR\n"); 481f10a77bbSDavid C Somayajulu break; 482f10a77bbSDavid C Somayajulu 483f10a77bbSDavid C Somayajulu case 0x03: 484f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GBase-SR\n"); 485f10a77bbSDavid C Somayajulu break; 486f10a77bbSDavid C Somayajulu 487f10a77bbSDavid C Somayajulu case 0x04: 488f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, 489f10a77bbSDavid C Somayajulu "Module Type 10GE Passive Copper(Compliant)[%d m]\n", 490f10a77bbSDavid C Somayajulu ha->hw.cable_length); 491f10a77bbSDavid C Somayajulu break; 492f10a77bbSDavid C Somayajulu 493f10a77bbSDavid C Somayajulu case 0x05: 494f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 10GE Active" 495f10a77bbSDavid C Somayajulu " Limiting Copper(Compliant)[%d m]\n", 496f10a77bbSDavid C Somayajulu ha->hw.cable_length); 497f10a77bbSDavid C Somayajulu break; 498f10a77bbSDavid C Somayajulu 499f10a77bbSDavid C Somayajulu case 0x06: 500f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, 501f10a77bbSDavid C Somayajulu "Module Type 10GE Passive Copper" 502f10a77bbSDavid C Somayajulu " (Legacy, Best Effort)[%d m]\n", 503f10a77bbSDavid C Somayajulu ha->hw.cable_length); 504f10a77bbSDavid C Somayajulu break; 505f10a77bbSDavid C Somayajulu 506f10a77bbSDavid C Somayajulu case 0x07: 507f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-SX\n"); 508f10a77bbSDavid C Somayajulu break; 509f10a77bbSDavid C Somayajulu 510f10a77bbSDavid C Somayajulu case 0x08: 511f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-LX\n"); 512f10a77bbSDavid C Somayajulu break; 513f10a77bbSDavid C Somayajulu 514f10a77bbSDavid C Somayajulu case 0x09: 515f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-CX\n"); 516f10a77bbSDavid C Somayajulu break; 517f10a77bbSDavid C Somayajulu 518f10a77bbSDavid C Somayajulu case 0x0A: 519f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1000Base-T\n"); 520f10a77bbSDavid C Somayajulu break; 521f10a77bbSDavid C Somayajulu 522f10a77bbSDavid C Somayajulu case 0x0B: 523f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Module Type 1GE Passive Copper" 524f10a77bbSDavid C Somayajulu "(Legacy, Best Effort)\n"); 525f10a77bbSDavid C Somayajulu break; 526f10a77bbSDavid C Somayajulu 527f10a77bbSDavid C Somayajulu default: 528f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "Unknown Module Type 0x%x\n", 529f10a77bbSDavid C Somayajulu ha->hw.module_type); 530f10a77bbSDavid C Somayajulu break; 531f10a77bbSDavid C Somayajulu } 532f10a77bbSDavid C Somayajulu 533f10a77bbSDavid C Somayajulu if (ha->hw.link_faults == 1) 534f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "SFP Power Fault\n"); 535f10a77bbSDavid C Somayajulu } 536f10a77bbSDavid C Somayajulu 537f10a77bbSDavid C Somayajulu /* 538f10a77bbSDavid C Somayajulu * Name: ql_free_dma 539f10a77bbSDavid C Somayajulu * Function: Frees the DMA'able memory allocated in ql_alloc_dma() 540f10a77bbSDavid C Somayajulu */ 541f10a77bbSDavid C Somayajulu void 542f10a77bbSDavid C Somayajulu ql_free_dma(qla_host_t *ha) 543f10a77bbSDavid C Somayajulu { 544f10a77bbSDavid C Somayajulu uint32_t i; 545f10a77bbSDavid C Somayajulu 546f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.sds_ring) { 547f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 548f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.sds_ring[i]); 549f10a77bbSDavid C Somayajulu } 550f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.sds_ring = 0; 551f10a77bbSDavid C Somayajulu } 552f10a77bbSDavid C Somayajulu 553f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.rds_ring) { 554f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) { 555f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.rds_ring[i]); 556f10a77bbSDavid C Somayajulu } 557f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.rds_ring = 0; 558f10a77bbSDavid C Somayajulu } 559f10a77bbSDavid C Somayajulu 560f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.tx_ring) { 561f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.tx_ring); 562f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.tx_ring = 0; 563f10a77bbSDavid C Somayajulu } 564f10a77bbSDavid C Somayajulu qla_minidump_free(ha); 565f10a77bbSDavid C Somayajulu } 566f10a77bbSDavid C Somayajulu 567f10a77bbSDavid C Somayajulu /* 568f10a77bbSDavid C Somayajulu * Name: ql_alloc_dma 569f10a77bbSDavid C Somayajulu * Function: Allocates DMA'able memory for Tx/Rx Rings, Tx/Rx Contexts. 570f10a77bbSDavid C Somayajulu */ 571f10a77bbSDavid C Somayajulu int 572f10a77bbSDavid C Somayajulu ql_alloc_dma(qla_host_t *ha) 573f10a77bbSDavid C Somayajulu { 574f10a77bbSDavid C Somayajulu device_t dev; 575f10a77bbSDavid C Somayajulu uint32_t i, j, size, tx_ring_size; 576f10a77bbSDavid C Somayajulu qla_hw_t *hw; 577f10a77bbSDavid C Somayajulu qla_hw_tx_cntxt_t *tx_cntxt; 578f10a77bbSDavid C Somayajulu uint8_t *vaddr; 579f10a77bbSDavid C Somayajulu bus_addr_t paddr; 580f10a77bbSDavid C Somayajulu 581f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 582f10a77bbSDavid C Somayajulu 583f10a77bbSDavid C Somayajulu QL_DPRINT2(ha, (dev, "%s: enter\n", __func__)); 584f10a77bbSDavid C Somayajulu 585f10a77bbSDavid C Somayajulu hw = &ha->hw; 586f10a77bbSDavid C Somayajulu /* 587f10a77bbSDavid C Somayajulu * Allocate Transmit Ring 588f10a77bbSDavid C Somayajulu */ 589f10a77bbSDavid C Somayajulu tx_ring_size = (sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS); 590f10a77bbSDavid C Somayajulu size = (tx_ring_size * ha->hw.num_tx_rings); 591f10a77bbSDavid C Somayajulu 592f10a77bbSDavid C Somayajulu hw->dma_buf.tx_ring.alignment = 8; 593f10a77bbSDavid C Somayajulu hw->dma_buf.tx_ring.size = size + PAGE_SIZE; 594f10a77bbSDavid C Somayajulu 595f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &hw->dma_buf.tx_ring)) { 596f10a77bbSDavid C Somayajulu device_printf(dev, "%s: tx ring alloc failed\n", __func__); 597f10a77bbSDavid C Somayajulu goto ql_alloc_dma_exit; 598f10a77bbSDavid C Somayajulu } 599f10a77bbSDavid C Somayajulu 600f10a77bbSDavid C Somayajulu vaddr = (uint8_t *)hw->dma_buf.tx_ring.dma_b; 601f10a77bbSDavid C Somayajulu paddr = hw->dma_buf.tx_ring.dma_addr; 602f10a77bbSDavid C Somayajulu 603f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 604f10a77bbSDavid C Somayajulu tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i]; 605f10a77bbSDavid C Somayajulu 606f10a77bbSDavid C Somayajulu tx_cntxt->tx_ring_base = (q80_tx_cmd_t *)vaddr; 607f10a77bbSDavid C Somayajulu tx_cntxt->tx_ring_paddr = paddr; 608f10a77bbSDavid C Somayajulu 609f10a77bbSDavid C Somayajulu vaddr += tx_ring_size; 610f10a77bbSDavid C Somayajulu paddr += tx_ring_size; 611f10a77bbSDavid C Somayajulu } 612f10a77bbSDavid C Somayajulu 613f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 614f10a77bbSDavid C Somayajulu tx_cntxt = (qla_hw_tx_cntxt_t *)&hw->tx_cntxt[i]; 615f10a77bbSDavid C Somayajulu 616f10a77bbSDavid C Somayajulu tx_cntxt->tx_cons = (uint32_t *)vaddr; 617f10a77bbSDavid C Somayajulu tx_cntxt->tx_cons_paddr = paddr; 618f10a77bbSDavid C Somayajulu 619f10a77bbSDavid C Somayajulu vaddr += sizeof (uint32_t); 620f10a77bbSDavid C Somayajulu paddr += sizeof (uint32_t); 621f10a77bbSDavid C Somayajulu } 622f10a77bbSDavid C Somayajulu 623f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.tx_ring = 1; 624f10a77bbSDavid C Somayajulu 625f10a77bbSDavid C Somayajulu QL_DPRINT2(ha, (dev, "%s: tx_ring phys %p virt %p\n", 626f10a77bbSDavid C Somayajulu __func__, (void *)(hw->dma_buf.tx_ring.dma_addr), 627f10a77bbSDavid C Somayajulu hw->dma_buf.tx_ring.dma_b)); 628f10a77bbSDavid C Somayajulu /* 629f10a77bbSDavid C Somayajulu * Allocate Receive Descriptor Rings 630f10a77bbSDavid C Somayajulu */ 631f10a77bbSDavid C Somayajulu 632f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_rds_rings; i++) { 633f10a77bbSDavid C Somayajulu 634f10a77bbSDavid C Somayajulu hw->dma_buf.rds_ring[i].alignment = 8; 635f10a77bbSDavid C Somayajulu hw->dma_buf.rds_ring[i].size = 636f10a77bbSDavid C Somayajulu (sizeof(q80_recv_desc_t)) * NUM_RX_DESCRIPTORS; 637f10a77bbSDavid C Somayajulu 638f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &hw->dma_buf.rds_ring[i])) { 639f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rds ring[%d] alloc failed\n", 640f10a77bbSDavid C Somayajulu __func__, i); 641f10a77bbSDavid C Somayajulu 642f10a77bbSDavid C Somayajulu for (j = 0; j < i; j++) 643f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &hw->dma_buf.rds_ring[j]); 644f10a77bbSDavid C Somayajulu 645f10a77bbSDavid C Somayajulu goto ql_alloc_dma_exit; 646f10a77bbSDavid C Somayajulu } 647f10a77bbSDavid C Somayajulu QL_DPRINT4(ha, (dev, "%s: rx_ring[%d] phys %p virt %p\n", 648f10a77bbSDavid C Somayajulu __func__, i, (void *)(hw->dma_buf.rds_ring[i].dma_addr), 649f10a77bbSDavid C Somayajulu hw->dma_buf.rds_ring[i].dma_b)); 650f10a77bbSDavid C Somayajulu } 651f10a77bbSDavid C Somayajulu 652f10a77bbSDavid C Somayajulu hw->dma_buf.flags.rds_ring = 1; 653f10a77bbSDavid C Somayajulu 654f10a77bbSDavid C Somayajulu /* 655f10a77bbSDavid C Somayajulu * Allocate Status Descriptor Rings 656f10a77bbSDavid C Somayajulu */ 657f10a77bbSDavid C Somayajulu 658f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) { 659f10a77bbSDavid C Somayajulu hw->dma_buf.sds_ring[i].alignment = 8; 660f10a77bbSDavid C Somayajulu hw->dma_buf.sds_ring[i].size = 661f10a77bbSDavid C Somayajulu (sizeof(q80_stat_desc_t)) * NUM_STATUS_DESCRIPTORS; 662f10a77bbSDavid C Somayajulu 663f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &hw->dma_buf.sds_ring[i])) { 664f10a77bbSDavid C Somayajulu device_printf(dev, "%s: sds ring alloc failed\n", 665f10a77bbSDavid C Somayajulu __func__); 666f10a77bbSDavid C Somayajulu 667f10a77bbSDavid C Somayajulu for (j = 0; j < i; j++) 668f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &hw->dma_buf.sds_ring[j]); 669f10a77bbSDavid C Somayajulu 670f10a77bbSDavid C Somayajulu goto ql_alloc_dma_exit; 671f10a77bbSDavid C Somayajulu } 672f10a77bbSDavid C Somayajulu QL_DPRINT4(ha, (dev, "%s: sds_ring[%d] phys %p virt %p\n", 673f10a77bbSDavid C Somayajulu __func__, i, 674f10a77bbSDavid C Somayajulu (void *)(hw->dma_buf.sds_ring[i].dma_addr), 675f10a77bbSDavid C Somayajulu hw->dma_buf.sds_ring[i].dma_b)); 676f10a77bbSDavid C Somayajulu } 677f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) { 678f10a77bbSDavid C Somayajulu hw->sds[i].sds_ring_base = 679f10a77bbSDavid C Somayajulu (q80_stat_desc_t *)hw->dma_buf.sds_ring[i].dma_b; 680f10a77bbSDavid C Somayajulu } 681f10a77bbSDavid C Somayajulu 682f10a77bbSDavid C Somayajulu hw->dma_buf.flags.sds_ring = 1; 683f10a77bbSDavid C Somayajulu 684f10a77bbSDavid C Somayajulu return 0; 685f10a77bbSDavid C Somayajulu 686f10a77bbSDavid C Somayajulu ql_alloc_dma_exit: 687f10a77bbSDavid C Somayajulu ql_free_dma(ha); 688f10a77bbSDavid C Somayajulu return -1; 689f10a77bbSDavid C Somayajulu } 690f10a77bbSDavid C Somayajulu 691f10a77bbSDavid C Somayajulu #define Q8_MBX_MSEC_DELAY 5000 692f10a77bbSDavid C Somayajulu 693f10a77bbSDavid C Somayajulu static int 694f10a77bbSDavid C Somayajulu qla_mbx_cmd(qla_host_t *ha, uint32_t *h_mbox, uint32_t n_hmbox, 695f10a77bbSDavid C Somayajulu uint32_t *fw_mbox, uint32_t n_fwmbox, uint32_t no_pause) 696f10a77bbSDavid C Somayajulu { 697f10a77bbSDavid C Somayajulu uint32_t i; 698f10a77bbSDavid C Somayajulu uint32_t data; 699f10a77bbSDavid C Somayajulu int ret = 0; 700f10a77bbSDavid C Somayajulu 701f10a77bbSDavid C Somayajulu if (QL_ERR_INJECT(ha, INJCT_MBX_CMD_FAILURE)) { 702f10a77bbSDavid C Somayajulu ret = -3; 703f10a77bbSDavid C Somayajulu ha->qla_initiate_recovery = 1; 704f10a77bbSDavid C Somayajulu goto exit_qla_mbx_cmd; 705f10a77bbSDavid C Somayajulu } 706f10a77bbSDavid C Somayajulu 707f10a77bbSDavid C Somayajulu if (no_pause) 708f10a77bbSDavid C Somayajulu i = 1000; 709f10a77bbSDavid C Somayajulu else 710f10a77bbSDavid C Somayajulu i = Q8_MBX_MSEC_DELAY; 711f10a77bbSDavid C Somayajulu 712f10a77bbSDavid C Somayajulu while (i) { 713f10a77bbSDavid C Somayajulu data = READ_REG32(ha, Q8_HOST_MBOX_CNTRL); 714f10a77bbSDavid C Somayajulu if (data == 0) 715f10a77bbSDavid C Somayajulu break; 716f10a77bbSDavid C Somayajulu if (no_pause) { 717f10a77bbSDavid C Somayajulu DELAY(1000); 718f10a77bbSDavid C Somayajulu } else { 719f10a77bbSDavid C Somayajulu qla_mdelay(__func__, 1); 720f10a77bbSDavid C Somayajulu } 721f10a77bbSDavid C Somayajulu i--; 722f10a77bbSDavid C Somayajulu } 723f10a77bbSDavid C Somayajulu 724f10a77bbSDavid C Somayajulu if (i == 0) { 725f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: host_mbx_cntrl 0x%08x\n", 726f10a77bbSDavid C Somayajulu __func__, data); 727f10a77bbSDavid C Somayajulu ret = -1; 728f10a77bbSDavid C Somayajulu ha->qla_initiate_recovery = 1; 729f10a77bbSDavid C Somayajulu goto exit_qla_mbx_cmd; 730f10a77bbSDavid C Somayajulu } 731f10a77bbSDavid C Somayajulu 732f10a77bbSDavid C Somayajulu for (i = 0; i < n_hmbox; i++) { 733f10a77bbSDavid C Somayajulu WRITE_REG32(ha, (Q8_HOST_MBOX0 + (i << 2)), *h_mbox); 734f10a77bbSDavid C Somayajulu h_mbox++; 735f10a77bbSDavid C Somayajulu } 736f10a77bbSDavid C Somayajulu 737f10a77bbSDavid C Somayajulu WRITE_REG32(ha, Q8_HOST_MBOX_CNTRL, 0x1); 738f10a77bbSDavid C Somayajulu 739f10a77bbSDavid C Somayajulu 740f10a77bbSDavid C Somayajulu i = Q8_MBX_MSEC_DELAY; 741f10a77bbSDavid C Somayajulu while (i) { 742f10a77bbSDavid C Somayajulu data = READ_REG32(ha, Q8_FW_MBOX_CNTRL); 743f10a77bbSDavid C Somayajulu 744f10a77bbSDavid C Somayajulu if ((data & 0x3) == 1) { 745f10a77bbSDavid C Somayajulu data = READ_REG32(ha, Q8_FW_MBOX0); 746f10a77bbSDavid C Somayajulu if ((data & 0xF000) != 0x8000) 747f10a77bbSDavid C Somayajulu break; 748f10a77bbSDavid C Somayajulu } 749f10a77bbSDavid C Somayajulu if (no_pause) { 750f10a77bbSDavid C Somayajulu DELAY(1000); 751f10a77bbSDavid C Somayajulu } else { 752f10a77bbSDavid C Somayajulu qla_mdelay(__func__, 1); 753f10a77bbSDavid C Somayajulu } 754f10a77bbSDavid C Somayajulu i--; 755f10a77bbSDavid C Somayajulu } 756f10a77bbSDavid C Somayajulu if (i == 0) { 757f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: fw_mbx_cntrl 0x%08x\n", 758f10a77bbSDavid C Somayajulu __func__, data); 759f10a77bbSDavid C Somayajulu ret = -2; 760f10a77bbSDavid C Somayajulu ha->qla_initiate_recovery = 1; 761f10a77bbSDavid C Somayajulu goto exit_qla_mbx_cmd; 762f10a77bbSDavid C Somayajulu } 763f10a77bbSDavid C Somayajulu 764f10a77bbSDavid C Somayajulu for (i = 0; i < n_fwmbox; i++) { 765f10a77bbSDavid C Somayajulu *fw_mbox++ = READ_REG32(ha, (Q8_FW_MBOX0 + (i << 2))); 766f10a77bbSDavid C Somayajulu } 767f10a77bbSDavid C Somayajulu 768f10a77bbSDavid C Somayajulu WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0); 769f10a77bbSDavid C Somayajulu WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0); 770f10a77bbSDavid C Somayajulu 771f10a77bbSDavid C Somayajulu exit_qla_mbx_cmd: 772f10a77bbSDavid C Somayajulu return (ret); 773f10a77bbSDavid C Somayajulu } 774f10a77bbSDavid C Somayajulu 77535291c22SDavid C Somayajulu int 77635291c22SDavid C Somayajulu qla_get_nic_partition(qla_host_t *ha, uint32_t *supports_9kb, 77735291c22SDavid C Somayajulu uint32_t *num_rcvq) 778f10a77bbSDavid C Somayajulu { 779f10a77bbSDavid C Somayajulu uint32_t *mbox, err; 780f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 781f10a77bbSDavid C Somayajulu 782f10a77bbSDavid C Somayajulu bzero(ha->hw.mbox, (sizeof (uint32_t) * Q8_NUM_MBOX)); 783f10a77bbSDavid C Somayajulu 784f10a77bbSDavid C Somayajulu mbox = ha->hw.mbox; 785f10a77bbSDavid C Somayajulu 786f10a77bbSDavid C Somayajulu mbox[0] = Q8_MBX_GET_NIC_PARTITION | (0x2 << 16) | (0x2 << 29); 787f10a77bbSDavid C Somayajulu 788f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, mbox, 2, mbox, 19, 0)) { 789f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 790f10a77bbSDavid C Somayajulu return (-1); 791f10a77bbSDavid C Somayajulu } 792f10a77bbSDavid C Somayajulu err = mbox[0] >> 25; 793f10a77bbSDavid C Somayajulu 79435291c22SDavid C Somayajulu if (supports_9kb != NULL) { 79535291c22SDavid C Somayajulu if (mbox[16] & 0x80) /* bit 7 of mbox 16 */ 79635291c22SDavid C Somayajulu *supports_9kb = 1; 79735291c22SDavid C Somayajulu else 79835291c22SDavid C Somayajulu *supports_9kb = 0; 79935291c22SDavid C Somayajulu } 80035291c22SDavid C Somayajulu 80135291c22SDavid C Somayajulu if (num_rcvq != NULL) 80235291c22SDavid C Somayajulu *num_rcvq = ((mbox[6] >> 16) & 0xFFFF); 80335291c22SDavid C Somayajulu 804f10a77bbSDavid C Somayajulu if ((err != 1) && (err != 0)) { 805f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 806f10a77bbSDavid C Somayajulu return (-1); 807f10a77bbSDavid C Somayajulu } 808f10a77bbSDavid C Somayajulu return 0; 809f10a77bbSDavid C Somayajulu } 810f10a77bbSDavid C Somayajulu 811f10a77bbSDavid C Somayajulu static int 81235291c22SDavid C Somayajulu qla_config_intr_cntxt(qla_host_t *ha, uint32_t start_idx, uint32_t num_intrs, 81335291c22SDavid C Somayajulu uint32_t create) 814f10a77bbSDavid C Somayajulu { 815f10a77bbSDavid C Somayajulu uint32_t i, err; 816f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 817f10a77bbSDavid C Somayajulu q80_config_intr_t *c_intr; 818f10a77bbSDavid C Somayajulu q80_config_intr_rsp_t *c_intr_rsp; 819f10a77bbSDavid C Somayajulu 820f10a77bbSDavid C Somayajulu c_intr = (q80_config_intr_t *)ha->hw.mbox; 821f10a77bbSDavid C Somayajulu bzero(c_intr, (sizeof (q80_config_intr_t))); 822f10a77bbSDavid C Somayajulu 823f10a77bbSDavid C Somayajulu c_intr->opcode = Q8_MBX_CONFIG_INTR; 824f10a77bbSDavid C Somayajulu 825f10a77bbSDavid C Somayajulu c_intr->count_version = (sizeof (q80_config_intr_t) >> 2); 826f10a77bbSDavid C Somayajulu c_intr->count_version |= Q8_MBX_CMD_VERSION; 827f10a77bbSDavid C Somayajulu 828f10a77bbSDavid C Somayajulu c_intr->nentries = num_intrs; 829f10a77bbSDavid C Somayajulu 830f10a77bbSDavid C Somayajulu for (i = 0; i < num_intrs; i++) { 831f10a77bbSDavid C Somayajulu if (create) { 832f10a77bbSDavid C Somayajulu c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_CREATE; 83335291c22SDavid C Somayajulu c_intr->intr[i].msix_index = start_idx + 1 + i; 834f10a77bbSDavid C Somayajulu } else { 835f10a77bbSDavid C Somayajulu c_intr->intr[i].cmd_type = Q8_MBX_CONFIG_INTR_DELETE; 83635291c22SDavid C Somayajulu c_intr->intr[i].msix_index = 83735291c22SDavid C Somayajulu ha->hw.intr_id[(start_idx + i)]; 838f10a77bbSDavid C Somayajulu } 839f10a77bbSDavid C Somayajulu 840f10a77bbSDavid C Somayajulu c_intr->intr[i].cmd_type |= Q8_MBX_CONFIG_INTR_TYPE_MSI_X; 841f10a77bbSDavid C Somayajulu } 842f10a77bbSDavid C Somayajulu 843f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)c_intr, 844f10a77bbSDavid C Somayajulu (sizeof (q80_config_intr_t) >> 2), 845f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_config_intr_rsp_t) >> 2), 0)) { 846f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 847f10a77bbSDavid C Somayajulu return (-1); 848f10a77bbSDavid C Somayajulu } 849f10a77bbSDavid C Somayajulu 850f10a77bbSDavid C Somayajulu c_intr_rsp = (q80_config_intr_rsp_t *)ha->hw.mbox; 851f10a77bbSDavid C Somayajulu 852f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(c_intr_rsp->regcnt_status); 853f10a77bbSDavid C Somayajulu 854f10a77bbSDavid C Somayajulu if (err) { 855f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x, %d]\n", __func__, err, 856f10a77bbSDavid C Somayajulu c_intr_rsp->nentries); 857f10a77bbSDavid C Somayajulu 858f10a77bbSDavid C Somayajulu for (i = 0; i < c_intr_rsp->nentries; i++) { 859f10a77bbSDavid C Somayajulu device_printf(dev, "%s: [%d]:[0x%x 0x%x 0x%x]\n", 860f10a77bbSDavid C Somayajulu __func__, i, 861f10a77bbSDavid C Somayajulu c_intr_rsp->intr[i].status, 862f10a77bbSDavid C Somayajulu c_intr_rsp->intr[i].intr_id, 863f10a77bbSDavid C Somayajulu c_intr_rsp->intr[i].intr_src); 864f10a77bbSDavid C Somayajulu } 865f10a77bbSDavid C Somayajulu 866f10a77bbSDavid C Somayajulu return (-1); 867f10a77bbSDavid C Somayajulu } 868f10a77bbSDavid C Somayajulu 869f10a77bbSDavid C Somayajulu for (i = 0; ((i < num_intrs) && create); i++) { 870f10a77bbSDavid C Somayajulu if (!c_intr_rsp->intr[i].status) { 87135291c22SDavid C Somayajulu ha->hw.intr_id[(start_idx + i)] = 87235291c22SDavid C Somayajulu c_intr_rsp->intr[i].intr_id; 87335291c22SDavid C Somayajulu ha->hw.intr_src[(start_idx + i)] = 87435291c22SDavid C Somayajulu c_intr_rsp->intr[i].intr_src; 875f10a77bbSDavid C Somayajulu } 876f10a77bbSDavid C Somayajulu } 877f10a77bbSDavid C Somayajulu 878f10a77bbSDavid C Somayajulu return (0); 879f10a77bbSDavid C Somayajulu } 880f10a77bbSDavid C Somayajulu 881f10a77bbSDavid C Somayajulu /* 882f10a77bbSDavid C Somayajulu * Name: qla_config_rss 883f10a77bbSDavid C Somayajulu * Function: Configure RSS for the context/interface. 884f10a77bbSDavid C Somayajulu */ 885f10a77bbSDavid C Somayajulu static const uint64_t rss_key[] = { 0xbeac01fa6a42b73bULL, 886f10a77bbSDavid C Somayajulu 0x8030f20c77cb2da3ULL, 887f10a77bbSDavid C Somayajulu 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL, 888f10a77bbSDavid C Somayajulu 0x255b0ec26d5a56daULL }; 889f10a77bbSDavid C Somayajulu 890f10a77bbSDavid C Somayajulu static int 891f10a77bbSDavid C Somayajulu qla_config_rss(qla_host_t *ha, uint16_t cntxt_id) 892f10a77bbSDavid C Somayajulu { 893f10a77bbSDavid C Somayajulu q80_config_rss_t *c_rss; 894f10a77bbSDavid C Somayajulu q80_config_rss_rsp_t *c_rss_rsp; 895f10a77bbSDavid C Somayajulu uint32_t err, i; 896f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 897f10a77bbSDavid C Somayajulu 898f10a77bbSDavid C Somayajulu c_rss = (q80_config_rss_t *)ha->hw.mbox; 899f10a77bbSDavid C Somayajulu bzero(c_rss, (sizeof (q80_config_rss_t))); 900f10a77bbSDavid C Somayajulu 901f10a77bbSDavid C Somayajulu c_rss->opcode = Q8_MBX_CONFIG_RSS; 902f10a77bbSDavid C Somayajulu 903f10a77bbSDavid C Somayajulu c_rss->count_version = (sizeof (q80_config_rss_t) >> 2); 904f10a77bbSDavid C Somayajulu c_rss->count_version |= Q8_MBX_CMD_VERSION; 905f10a77bbSDavid C Somayajulu 906f10a77bbSDavid C Somayajulu c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP_IP | 907f10a77bbSDavid C Somayajulu Q8_MBX_RSS_HASH_TYPE_IPV6_TCP_IP); 90835291c22SDavid C Somayajulu //c_rss->hash_type = (Q8_MBX_RSS_HASH_TYPE_IPV4_TCP | 90935291c22SDavid C Somayajulu // Q8_MBX_RSS_HASH_TYPE_IPV6_TCP); 910f10a77bbSDavid C Somayajulu 911f10a77bbSDavid C Somayajulu c_rss->flags = Q8_MBX_RSS_FLAGS_ENABLE_RSS; 912f10a77bbSDavid C Somayajulu c_rss->flags |= Q8_MBX_RSS_FLAGS_USE_IND_TABLE; 913f10a77bbSDavid C Somayajulu 914f10a77bbSDavid C Somayajulu c_rss->indtbl_mask = Q8_MBX_RSS_INDTBL_MASK; 915f10a77bbSDavid C Somayajulu 916f10a77bbSDavid C Somayajulu c_rss->indtbl_mask |= Q8_MBX_RSS_FLAGS_MULTI_RSS_VALID; 917f10a77bbSDavid C Somayajulu c_rss->flags |= Q8_MBX_RSS_FLAGS_TYPE_CRSS; 918f10a77bbSDavid C Somayajulu 919f10a77bbSDavid C Somayajulu c_rss->cntxt_id = cntxt_id; 920f10a77bbSDavid C Somayajulu 921f10a77bbSDavid C Somayajulu for (i = 0; i < 5; i++) { 922f10a77bbSDavid C Somayajulu c_rss->rss_key[i] = rss_key[i]; 923f10a77bbSDavid C Somayajulu } 924f10a77bbSDavid C Somayajulu 925f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)c_rss, 926f10a77bbSDavid C Somayajulu (sizeof (q80_config_rss_t) >> 2), 927f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_rss_rsp_t) >> 2), 0)) { 928f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 929f10a77bbSDavid C Somayajulu return (-1); 930f10a77bbSDavid C Somayajulu } 931f10a77bbSDavid C Somayajulu c_rss_rsp = (q80_config_rss_rsp_t *)ha->hw.mbox; 932f10a77bbSDavid C Somayajulu 933f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(c_rss_rsp->regcnt_status); 934f10a77bbSDavid C Somayajulu 935f10a77bbSDavid C Somayajulu if (err) { 936f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 937f10a77bbSDavid C Somayajulu return (-1); 938f10a77bbSDavid C Somayajulu } 939f10a77bbSDavid C Somayajulu return 0; 940f10a77bbSDavid C Somayajulu } 941f10a77bbSDavid C Somayajulu 942f10a77bbSDavid C Somayajulu static int 943f10a77bbSDavid C Somayajulu qla_set_rss_ind_table(qla_host_t *ha, uint32_t start_idx, uint32_t count, 944f10a77bbSDavid C Somayajulu uint16_t cntxt_id, uint8_t *ind_table) 945f10a77bbSDavid C Somayajulu { 946f10a77bbSDavid C Somayajulu q80_config_rss_ind_table_t *c_rss_ind; 947f10a77bbSDavid C Somayajulu q80_config_rss_ind_table_rsp_t *c_rss_ind_rsp; 948f10a77bbSDavid C Somayajulu uint32_t err; 949f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 950f10a77bbSDavid C Somayajulu 951f10a77bbSDavid C Somayajulu if ((count > Q8_RSS_IND_TBL_SIZE) || 952f10a77bbSDavid C Somayajulu ((start_idx + count - 1) > Q8_RSS_IND_TBL_MAX_IDX)) { 953f10a77bbSDavid C Somayajulu device_printf(dev, "%s: illegal count [%d, %d]\n", __func__, 954f10a77bbSDavid C Somayajulu start_idx, count); 955f10a77bbSDavid C Somayajulu return (-1); 956f10a77bbSDavid C Somayajulu } 957f10a77bbSDavid C Somayajulu 958f10a77bbSDavid C Somayajulu c_rss_ind = (q80_config_rss_ind_table_t *)ha->hw.mbox; 959f10a77bbSDavid C Somayajulu bzero(c_rss_ind, sizeof (q80_config_rss_ind_table_t)); 960f10a77bbSDavid C Somayajulu 961f10a77bbSDavid C Somayajulu c_rss_ind->opcode = Q8_MBX_CONFIG_RSS_TABLE; 962f10a77bbSDavid C Somayajulu c_rss_ind->count_version = (sizeof (q80_config_rss_ind_table_t) >> 2); 963f10a77bbSDavid C Somayajulu c_rss_ind->count_version |= Q8_MBX_CMD_VERSION; 964f10a77bbSDavid C Somayajulu 965f10a77bbSDavid C Somayajulu c_rss_ind->start_idx = start_idx; 966f10a77bbSDavid C Somayajulu c_rss_ind->end_idx = start_idx + count - 1; 967f10a77bbSDavid C Somayajulu c_rss_ind->cntxt_id = cntxt_id; 968f10a77bbSDavid C Somayajulu bcopy(ind_table, c_rss_ind->ind_table, count); 969f10a77bbSDavid C Somayajulu 970f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)c_rss_ind, 971f10a77bbSDavid C Somayajulu (sizeof (q80_config_rss_ind_table_t) >> 2), ha->hw.mbox, 972f10a77bbSDavid C Somayajulu (sizeof(q80_config_rss_ind_table_rsp_t) >> 2), 0)) { 973f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 974f10a77bbSDavid C Somayajulu return (-1); 975f10a77bbSDavid C Somayajulu } 976f10a77bbSDavid C Somayajulu 977f10a77bbSDavid C Somayajulu c_rss_ind_rsp = (q80_config_rss_ind_table_rsp_t *)ha->hw.mbox; 978f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(c_rss_ind_rsp->regcnt_status); 979f10a77bbSDavid C Somayajulu 980f10a77bbSDavid C Somayajulu if (err) { 981f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 982f10a77bbSDavid C Somayajulu return (-1); 983f10a77bbSDavid C Somayajulu } 984f10a77bbSDavid C Somayajulu return 0; 985f10a77bbSDavid C Somayajulu } 986f10a77bbSDavid C Somayajulu 987f10a77bbSDavid C Somayajulu /* 988f10a77bbSDavid C Somayajulu * Name: qla_config_intr_coalesce 989f10a77bbSDavid C Somayajulu * Function: Configure Interrupt Coalescing. 990f10a77bbSDavid C Somayajulu */ 991f10a77bbSDavid C Somayajulu static int 99235291c22SDavid C Somayajulu qla_config_intr_coalesce(qla_host_t *ha, uint16_t cntxt_id, int tenable, 99335291c22SDavid C Somayajulu int rcv) 994f10a77bbSDavid C Somayajulu { 995f10a77bbSDavid C Somayajulu q80_config_intr_coalesc_t *intrc; 996f10a77bbSDavid C Somayajulu q80_config_intr_coalesc_rsp_t *intrc_rsp; 997f10a77bbSDavid C Somayajulu uint32_t err, i; 998f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 999f10a77bbSDavid C Somayajulu 1000f10a77bbSDavid C Somayajulu intrc = (q80_config_intr_coalesc_t *)ha->hw.mbox; 1001f10a77bbSDavid C Somayajulu bzero(intrc, (sizeof (q80_config_intr_coalesc_t))); 1002f10a77bbSDavid C Somayajulu 1003f10a77bbSDavid C Somayajulu intrc->opcode = Q8_MBX_CONFIG_INTR_COALESCE; 1004f10a77bbSDavid C Somayajulu intrc->count_version = (sizeof (q80_config_intr_coalesc_t) >> 2); 1005f10a77bbSDavid C Somayajulu intrc->count_version |= Q8_MBX_CMD_VERSION; 1006f10a77bbSDavid C Somayajulu 100735291c22SDavid C Somayajulu if (rcv) { 1008f10a77bbSDavid C Somayajulu intrc->flags = Q8_MBX_INTRC_FLAGS_RCV; 100935291c22SDavid C Somayajulu intrc->max_pkts = ha->hw.rcv_intr_coalesce & 0xFFFF; 101035291c22SDavid C Somayajulu intrc->max_mswait = (ha->hw.rcv_intr_coalesce >> 16) & 0xFFFF; 101135291c22SDavid C Somayajulu } else { 101235291c22SDavid C Somayajulu intrc->flags = Q8_MBX_INTRC_FLAGS_XMT; 101335291c22SDavid C Somayajulu intrc->max_pkts = ha->hw.xmt_intr_coalesce & 0xFFFF; 101435291c22SDavid C Somayajulu intrc->max_mswait = (ha->hw.xmt_intr_coalesce >> 16) & 0xFFFF; 101535291c22SDavid C Somayajulu } 1016f10a77bbSDavid C Somayajulu 101735291c22SDavid C Somayajulu intrc->cntxt_id = cntxt_id; 1018f10a77bbSDavid C Somayajulu 1019f10a77bbSDavid C Somayajulu if (tenable) { 1020f10a77bbSDavid C Somayajulu intrc->flags |= Q8_MBX_INTRC_FLAGS_PERIODIC; 1021f10a77bbSDavid C Somayajulu intrc->timer_type = Q8_MBX_INTRC_TIMER_PERIODIC; 1022f10a77bbSDavid C Somayajulu 1023f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 1024f10a77bbSDavid C Somayajulu intrc->sds_ring_mask |= (1 << i); 1025f10a77bbSDavid C Somayajulu } 1026f10a77bbSDavid C Somayajulu intrc->ms_timeout = 1000; 1027f10a77bbSDavid C Somayajulu } 1028f10a77bbSDavid C Somayajulu 1029f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)intrc, 1030f10a77bbSDavid C Somayajulu (sizeof (q80_config_intr_coalesc_t) >> 2), 1031f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_intr_coalesc_rsp_t) >> 2), 0)) { 1032f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 1033f10a77bbSDavid C Somayajulu return (-1); 1034f10a77bbSDavid C Somayajulu } 1035f10a77bbSDavid C Somayajulu intrc_rsp = (q80_config_intr_coalesc_rsp_t *)ha->hw.mbox; 1036f10a77bbSDavid C Somayajulu 1037f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(intrc_rsp->regcnt_status); 1038f10a77bbSDavid C Somayajulu 1039f10a77bbSDavid C Somayajulu if (err) { 1040f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 1041f10a77bbSDavid C Somayajulu return (-1); 1042f10a77bbSDavid C Somayajulu } 1043f10a77bbSDavid C Somayajulu 1044f10a77bbSDavid C Somayajulu return 0; 1045f10a77bbSDavid C Somayajulu } 1046f10a77bbSDavid C Somayajulu 1047f10a77bbSDavid C Somayajulu 1048f10a77bbSDavid C Somayajulu /* 1049f10a77bbSDavid C Somayajulu * Name: qla_config_mac_addr 1050f10a77bbSDavid C Somayajulu * Function: binds a MAC address to the context/interface. 1051f10a77bbSDavid C Somayajulu * Can be unicast, multicast or broadcast. 1052f10a77bbSDavid C Somayajulu */ 1053f10a77bbSDavid C Somayajulu static int 1054f10a77bbSDavid C Somayajulu qla_config_mac_addr(qla_host_t *ha, uint8_t *mac_addr, uint32_t add_mac) 1055f10a77bbSDavid C Somayajulu { 1056f10a77bbSDavid C Somayajulu q80_config_mac_addr_t *cmac; 1057f10a77bbSDavid C Somayajulu q80_config_mac_addr_rsp_t *cmac_rsp; 1058f10a77bbSDavid C Somayajulu uint32_t err; 1059f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1060f10a77bbSDavid C Somayajulu 1061f10a77bbSDavid C Somayajulu cmac = (q80_config_mac_addr_t *)ha->hw.mbox; 1062f10a77bbSDavid C Somayajulu bzero(cmac, (sizeof (q80_config_mac_addr_t))); 1063f10a77bbSDavid C Somayajulu 1064f10a77bbSDavid C Somayajulu cmac->opcode = Q8_MBX_CONFIG_MAC_ADDR; 1065f10a77bbSDavid C Somayajulu cmac->count_version = sizeof (q80_config_mac_addr_t) >> 2; 1066f10a77bbSDavid C Somayajulu cmac->count_version |= Q8_MBX_CMD_VERSION; 1067f10a77bbSDavid C Somayajulu 1068f10a77bbSDavid C Somayajulu if (add_mac) 1069f10a77bbSDavid C Somayajulu cmac->cmd = Q8_MBX_CMAC_CMD_ADD_MAC_ADDR; 1070f10a77bbSDavid C Somayajulu else 1071f10a77bbSDavid C Somayajulu cmac->cmd = Q8_MBX_CMAC_CMD_DEL_MAC_ADDR; 1072f10a77bbSDavid C Somayajulu 1073f10a77bbSDavid C Somayajulu cmac->cmd |= Q8_MBX_CMAC_CMD_CAM_INGRESS; 1074f10a77bbSDavid C Somayajulu 1075f10a77bbSDavid C Somayajulu cmac->nmac_entries = 1; 1076f10a77bbSDavid C Somayajulu cmac->cntxt_id = ha->hw.rcv_cntxt_id; 1077f10a77bbSDavid C Somayajulu bcopy(mac_addr, cmac->mac_addr[0].addr, 6); 1078f10a77bbSDavid C Somayajulu 1079f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)cmac, 1080f10a77bbSDavid C Somayajulu (sizeof (q80_config_mac_addr_t) >> 2), 1081f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_mac_addr_rsp_t) >> 2), 1)) { 1082f10a77bbSDavid C Somayajulu device_printf(dev, "%s: %s failed0\n", __func__, 1083f10a77bbSDavid C Somayajulu (add_mac ? "Add" : "Del")); 1084f10a77bbSDavid C Somayajulu return (-1); 1085f10a77bbSDavid C Somayajulu } 1086f10a77bbSDavid C Somayajulu cmac_rsp = (q80_config_mac_addr_rsp_t *)ha->hw.mbox; 1087f10a77bbSDavid C Somayajulu 1088f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(cmac_rsp->regcnt_status); 1089f10a77bbSDavid C Somayajulu 1090f10a77bbSDavid C Somayajulu if (err) { 1091f10a77bbSDavid C Somayajulu device_printf(dev, "%s: %s " 1092f10a77bbSDavid C Somayajulu "%02x:%02x:%02x:%02x:%02x:%02x failed1 [0x%08x]\n", 1093f10a77bbSDavid C Somayajulu __func__, (add_mac ? "Add" : "Del"), 1094f10a77bbSDavid C Somayajulu mac_addr[0], mac_addr[1], mac_addr[2], 1095f10a77bbSDavid C Somayajulu mac_addr[3], mac_addr[4], mac_addr[5], err); 1096f10a77bbSDavid C Somayajulu return (-1); 1097f10a77bbSDavid C Somayajulu } 1098f10a77bbSDavid C Somayajulu 1099f10a77bbSDavid C Somayajulu return 0; 1100f10a77bbSDavid C Somayajulu } 1101f10a77bbSDavid C Somayajulu 1102f10a77bbSDavid C Somayajulu 1103f10a77bbSDavid C Somayajulu /* 1104f10a77bbSDavid C Somayajulu * Name: qla_set_mac_rcv_mode 1105453130d9SPedro F. Giffuni * Function: Enable/Disable AllMulticast and Promiscuous Modes. 1106f10a77bbSDavid C Somayajulu */ 1107f10a77bbSDavid C Somayajulu static int 1108f10a77bbSDavid C Somayajulu qla_set_mac_rcv_mode(qla_host_t *ha, uint32_t mode) 1109f10a77bbSDavid C Somayajulu { 1110f10a77bbSDavid C Somayajulu q80_config_mac_rcv_mode_t *rcv_mode; 1111f10a77bbSDavid C Somayajulu uint32_t err; 1112f10a77bbSDavid C Somayajulu q80_config_mac_rcv_mode_rsp_t *rcv_mode_rsp; 1113f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1114f10a77bbSDavid C Somayajulu 1115f10a77bbSDavid C Somayajulu rcv_mode = (q80_config_mac_rcv_mode_t *)ha->hw.mbox; 1116f10a77bbSDavid C Somayajulu bzero(rcv_mode, (sizeof (q80_config_mac_rcv_mode_t))); 1117f10a77bbSDavid C Somayajulu 1118f10a77bbSDavid C Somayajulu rcv_mode->opcode = Q8_MBX_CONFIG_MAC_RX_MODE; 1119f10a77bbSDavid C Somayajulu rcv_mode->count_version = sizeof (q80_config_mac_rcv_mode_t) >> 2; 1120f10a77bbSDavid C Somayajulu rcv_mode->count_version |= Q8_MBX_CMD_VERSION; 1121f10a77bbSDavid C Somayajulu 1122f10a77bbSDavid C Somayajulu rcv_mode->mode = mode; 1123f10a77bbSDavid C Somayajulu 1124f10a77bbSDavid C Somayajulu rcv_mode->cntxt_id = ha->hw.rcv_cntxt_id; 1125f10a77bbSDavid C Somayajulu 1126f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)rcv_mode, 1127f10a77bbSDavid C Somayajulu (sizeof (q80_config_mac_rcv_mode_t) >> 2), 1128f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_config_mac_rcv_mode_rsp_t) >> 2), 1)) { 1129f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 1130f10a77bbSDavid C Somayajulu return (-1); 1131f10a77bbSDavid C Somayajulu } 1132f10a77bbSDavid C Somayajulu rcv_mode_rsp = (q80_config_mac_rcv_mode_rsp_t *)ha->hw.mbox; 1133f10a77bbSDavid C Somayajulu 1134f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(rcv_mode_rsp->regcnt_status); 1135f10a77bbSDavid C Somayajulu 1136f10a77bbSDavid C Somayajulu if (err) { 1137f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 1138f10a77bbSDavid C Somayajulu return (-1); 1139f10a77bbSDavid C Somayajulu } 1140f10a77bbSDavid C Somayajulu 1141f10a77bbSDavid C Somayajulu return 0; 1142f10a77bbSDavid C Somayajulu } 1143f10a77bbSDavid C Somayajulu 1144f10a77bbSDavid C Somayajulu int 1145f10a77bbSDavid C Somayajulu ql_set_promisc(qla_host_t *ha) 1146f10a77bbSDavid C Somayajulu { 1147f10a77bbSDavid C Somayajulu int ret; 1148f10a77bbSDavid C Somayajulu 1149f10a77bbSDavid C Somayajulu ha->hw.mac_rcv_mode |= Q8_MBX_MAC_RCV_PROMISC_ENABLE; 1150f10a77bbSDavid C Somayajulu ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 1151f10a77bbSDavid C Somayajulu return (ret); 1152f10a77bbSDavid C Somayajulu } 1153f10a77bbSDavid C Somayajulu 115435291c22SDavid C Somayajulu void 115535291c22SDavid C Somayajulu qla_reset_promisc(qla_host_t *ha) 115635291c22SDavid C Somayajulu { 115735291c22SDavid C Somayajulu ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_RCV_PROMISC_ENABLE; 115835291c22SDavid C Somayajulu (void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 115935291c22SDavid C Somayajulu } 116035291c22SDavid C Somayajulu 1161f10a77bbSDavid C Somayajulu int 1162f10a77bbSDavid C Somayajulu ql_set_allmulti(qla_host_t *ha) 1163f10a77bbSDavid C Somayajulu { 1164f10a77bbSDavid C Somayajulu int ret; 1165f10a77bbSDavid C Somayajulu 1166f10a77bbSDavid C Somayajulu ha->hw.mac_rcv_mode |= Q8_MBX_MAC_ALL_MULTI_ENABLE; 1167f10a77bbSDavid C Somayajulu ret = qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 1168f10a77bbSDavid C Somayajulu return (ret); 1169f10a77bbSDavid C Somayajulu } 1170f10a77bbSDavid C Somayajulu 117135291c22SDavid C Somayajulu void 117235291c22SDavid C Somayajulu qla_reset_allmulti(qla_host_t *ha) 117335291c22SDavid C Somayajulu { 117435291c22SDavid C Somayajulu ha->hw.mac_rcv_mode &= ~Q8_MBX_MAC_ALL_MULTI_ENABLE; 117535291c22SDavid C Somayajulu (void)qla_set_mac_rcv_mode(ha, ha->hw.mac_rcv_mode); 117635291c22SDavid C Somayajulu } 1177f10a77bbSDavid C Somayajulu 1178f10a77bbSDavid C Somayajulu /* 1179f10a77bbSDavid C Somayajulu * Name: ql_set_max_mtu 1180f10a77bbSDavid C Somayajulu * Function: 1181f10a77bbSDavid C Somayajulu * Sets the maximum transfer unit size for the specified rcv context. 1182f10a77bbSDavid C Somayajulu */ 1183f10a77bbSDavid C Somayajulu int 1184f10a77bbSDavid C Somayajulu ql_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id) 1185f10a77bbSDavid C Somayajulu { 1186f10a77bbSDavid C Somayajulu device_t dev; 1187f10a77bbSDavid C Somayajulu q80_set_max_mtu_t *max_mtu; 1188f10a77bbSDavid C Somayajulu q80_set_max_mtu_rsp_t *max_mtu_rsp; 1189f10a77bbSDavid C Somayajulu uint32_t err; 1190f10a77bbSDavid C Somayajulu 1191f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1192f10a77bbSDavid C Somayajulu 1193f10a77bbSDavid C Somayajulu max_mtu = (q80_set_max_mtu_t *)ha->hw.mbox; 1194f10a77bbSDavid C Somayajulu bzero(max_mtu, (sizeof (q80_set_max_mtu_t))); 1195f10a77bbSDavid C Somayajulu 1196f10a77bbSDavid C Somayajulu max_mtu->opcode = Q8_MBX_SET_MAX_MTU; 1197f10a77bbSDavid C Somayajulu max_mtu->count_version = (sizeof (q80_set_max_mtu_t) >> 2); 1198f10a77bbSDavid C Somayajulu max_mtu->count_version |= Q8_MBX_CMD_VERSION; 1199f10a77bbSDavid C Somayajulu 1200f10a77bbSDavid C Somayajulu max_mtu->cntxt_id = cntxt_id; 1201f10a77bbSDavid C Somayajulu max_mtu->mtu = mtu; 1202f10a77bbSDavid C Somayajulu 1203f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)max_mtu, 1204f10a77bbSDavid C Somayajulu (sizeof (q80_set_max_mtu_t) >> 2), 1205f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_set_max_mtu_rsp_t) >> 2), 1)) { 1206f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 1207f10a77bbSDavid C Somayajulu return -1; 1208f10a77bbSDavid C Somayajulu } 1209f10a77bbSDavid C Somayajulu 1210f10a77bbSDavid C Somayajulu max_mtu_rsp = (q80_set_max_mtu_rsp_t *)ha->hw.mbox; 1211f10a77bbSDavid C Somayajulu 1212f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(max_mtu_rsp->regcnt_status); 1213f10a77bbSDavid C Somayajulu 1214f10a77bbSDavid C Somayajulu if (err) { 1215f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 1216f10a77bbSDavid C Somayajulu } 1217f10a77bbSDavid C Somayajulu 1218f10a77bbSDavid C Somayajulu return 0; 1219f10a77bbSDavid C Somayajulu } 1220f10a77bbSDavid C Somayajulu 1221f10a77bbSDavid C Somayajulu static int 1222f10a77bbSDavid C Somayajulu qla_link_event_req(qla_host_t *ha, uint16_t cntxt_id) 1223f10a77bbSDavid C Somayajulu { 1224f10a77bbSDavid C Somayajulu device_t dev; 1225f10a77bbSDavid C Somayajulu q80_link_event_t *lnk; 1226f10a77bbSDavid C Somayajulu q80_link_event_rsp_t *lnk_rsp; 1227f10a77bbSDavid C Somayajulu uint32_t err; 1228f10a77bbSDavid C Somayajulu 1229f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1230f10a77bbSDavid C Somayajulu 1231f10a77bbSDavid C Somayajulu lnk = (q80_link_event_t *)ha->hw.mbox; 1232f10a77bbSDavid C Somayajulu bzero(lnk, (sizeof (q80_link_event_t))); 1233f10a77bbSDavid C Somayajulu 1234f10a77bbSDavid C Somayajulu lnk->opcode = Q8_MBX_LINK_EVENT_REQ; 1235f10a77bbSDavid C Somayajulu lnk->count_version = (sizeof (q80_link_event_t) >> 2); 1236f10a77bbSDavid C Somayajulu lnk->count_version |= Q8_MBX_CMD_VERSION; 1237f10a77bbSDavid C Somayajulu 1238f10a77bbSDavid C Somayajulu lnk->cntxt_id = cntxt_id; 1239f10a77bbSDavid C Somayajulu lnk->cmd = Q8_LINK_EVENT_CMD_ENABLE_ASYNC; 1240f10a77bbSDavid C Somayajulu 1241f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)lnk, (sizeof (q80_link_event_t) >> 2), 1242f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_link_event_rsp_t) >> 2), 0)) { 1243f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 1244f10a77bbSDavid C Somayajulu return -1; 1245f10a77bbSDavid C Somayajulu } 1246f10a77bbSDavid C Somayajulu 1247f10a77bbSDavid C Somayajulu lnk_rsp = (q80_link_event_rsp_t *)ha->hw.mbox; 1248f10a77bbSDavid C Somayajulu 1249f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(lnk_rsp->regcnt_status); 1250f10a77bbSDavid C Somayajulu 1251f10a77bbSDavid C Somayajulu if (err) { 1252f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 1253f10a77bbSDavid C Somayajulu } 1254f10a77bbSDavid C Somayajulu 1255f10a77bbSDavid C Somayajulu return 0; 1256f10a77bbSDavid C Somayajulu } 1257f10a77bbSDavid C Somayajulu 1258f10a77bbSDavid C Somayajulu static int 1259f10a77bbSDavid C Somayajulu qla_config_fw_lro(qla_host_t *ha, uint16_t cntxt_id) 1260f10a77bbSDavid C Somayajulu { 1261f10a77bbSDavid C Somayajulu device_t dev; 1262f10a77bbSDavid C Somayajulu q80_config_fw_lro_t *fw_lro; 1263f10a77bbSDavid C Somayajulu q80_config_fw_lro_rsp_t *fw_lro_rsp; 1264f10a77bbSDavid C Somayajulu uint32_t err; 1265f10a77bbSDavid C Somayajulu 1266f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1267f10a77bbSDavid C Somayajulu 1268f10a77bbSDavid C Somayajulu fw_lro = (q80_config_fw_lro_t *)ha->hw.mbox; 1269f10a77bbSDavid C Somayajulu bzero(fw_lro, sizeof(q80_config_fw_lro_t)); 1270f10a77bbSDavid C Somayajulu 1271f10a77bbSDavid C Somayajulu fw_lro->opcode = Q8_MBX_CONFIG_FW_LRO; 1272f10a77bbSDavid C Somayajulu fw_lro->count_version = (sizeof (q80_config_fw_lro_t) >> 2); 1273f10a77bbSDavid C Somayajulu fw_lro->count_version |= Q8_MBX_CMD_VERSION; 1274f10a77bbSDavid C Somayajulu 1275f10a77bbSDavid C Somayajulu fw_lro->flags |= Q8_MBX_FW_LRO_IPV4 | Q8_MBX_FW_LRO_IPV4_WO_DST_IP_CHK; 127635291c22SDavid C Somayajulu fw_lro->flags |= Q8_MBX_FW_LRO_IPV6 | Q8_MBX_FW_LRO_IPV6_WO_DST_IP_CHK; 1277f10a77bbSDavid C Somayajulu 1278f10a77bbSDavid C Somayajulu fw_lro->cntxt_id = cntxt_id; 1279f10a77bbSDavid C Somayajulu 1280f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)fw_lro, 1281f10a77bbSDavid C Somayajulu (sizeof (q80_config_fw_lro_t) >> 2), 1282f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_config_fw_lro_rsp_t) >> 2), 0)) { 1283f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 1284f10a77bbSDavid C Somayajulu return -1; 1285f10a77bbSDavid C Somayajulu } 1286f10a77bbSDavid C Somayajulu 1287f10a77bbSDavid C Somayajulu fw_lro_rsp = (q80_config_fw_lro_rsp_t *)ha->hw.mbox; 1288f10a77bbSDavid C Somayajulu 1289f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(fw_lro_rsp->regcnt_status); 1290f10a77bbSDavid C Somayajulu 1291f10a77bbSDavid C Somayajulu if (err) { 1292f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 1293f10a77bbSDavid C Somayajulu } 1294f10a77bbSDavid C Somayajulu 1295f10a77bbSDavid C Somayajulu return 0; 1296f10a77bbSDavid C Somayajulu } 1297f10a77bbSDavid C Somayajulu 1298f10a77bbSDavid C Somayajulu static void 129935291c22SDavid C Somayajulu qla_xmt_stats(qla_host_t *ha, q80_xmt_stats_t *xstat, int i) 1300f10a77bbSDavid C Somayajulu { 1301f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1302f10a77bbSDavid C Somayajulu 130335291c22SDavid C Somayajulu if (i < ha->hw.num_tx_rings) { 130435291c22SDavid C Somayajulu device_printf(dev, "%s[%d]: total_bytes\t\t%" PRIu64 "\n", 130535291c22SDavid C Somayajulu __func__, i, xstat->total_bytes); 130635291c22SDavid C Somayajulu device_printf(dev, "%s[%d]: total_pkts\t\t%" PRIu64 "\n", 130735291c22SDavid C Somayajulu __func__, i, xstat->total_pkts); 130835291c22SDavid C Somayajulu device_printf(dev, "%s[%d]: errors\t\t%" PRIu64 "\n", 130935291c22SDavid C Somayajulu __func__, i, xstat->errors); 131035291c22SDavid C Somayajulu device_printf(dev, "%s[%d]: pkts_dropped\t%" PRIu64 "\n", 131135291c22SDavid C Somayajulu __func__, i, xstat->pkts_dropped); 131235291c22SDavid C Somayajulu device_printf(dev, "%s[%d]: switch_pkts\t\t%" PRIu64 "\n", 131335291c22SDavid C Somayajulu __func__, i, xstat->switch_pkts); 131435291c22SDavid C Somayajulu device_printf(dev, "%s[%d]: num_buffers\t\t%" PRIu64 "\n", 131535291c22SDavid C Somayajulu __func__, i, xstat->num_buffers); 131635291c22SDavid C Somayajulu } else { 131735291c22SDavid C Somayajulu device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n", 131835291c22SDavid C Somayajulu __func__, xstat->total_bytes); 131935291c22SDavid C Somayajulu device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n", 132035291c22SDavid C Somayajulu __func__, xstat->total_pkts); 132135291c22SDavid C Somayajulu device_printf(dev, "%s: errors\t\t\t%" PRIu64 "\n", 132235291c22SDavid C Somayajulu __func__, xstat->errors); 132335291c22SDavid C Somayajulu device_printf(dev, "%s: pkts_dropped\t\t\t%" PRIu64 "\n", 132435291c22SDavid C Somayajulu __func__, xstat->pkts_dropped); 132535291c22SDavid C Somayajulu device_printf(dev, "%s: switch_pkts\t\t\t%" PRIu64 "\n", 132635291c22SDavid C Somayajulu __func__, xstat->switch_pkts); 132735291c22SDavid C Somayajulu device_printf(dev, "%s: num_buffers\t\t\t%" PRIu64 "\n", 132835291c22SDavid C Somayajulu __func__, xstat->num_buffers); 132935291c22SDavid C Somayajulu } 1330f10a77bbSDavid C Somayajulu } 1331f10a77bbSDavid C Somayajulu 1332f10a77bbSDavid C Somayajulu static void 1333f10a77bbSDavid C Somayajulu qla_rcv_stats(qla_host_t *ha, q80_rcv_stats_t *rstat) 1334f10a77bbSDavid C Somayajulu { 1335f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1336f10a77bbSDavid C Somayajulu 1337f10a77bbSDavid C Somayajulu device_printf(dev, "%s: total_bytes\t\t\t%" PRIu64 "\n", __func__, 1338f10a77bbSDavid C Somayajulu rstat->total_bytes); 1339f10a77bbSDavid C Somayajulu device_printf(dev, "%s: total_pkts\t\t\t%" PRIu64 "\n", __func__, 1340f10a77bbSDavid C Somayajulu rstat->total_pkts); 1341f10a77bbSDavid C Somayajulu device_printf(dev, "%s: lro_pkt_count\t\t%" PRIu64 "\n", __func__, 1342f10a77bbSDavid C Somayajulu rstat->lro_pkt_count); 134335291c22SDavid C Somayajulu device_printf(dev, "%s: sw_pkt_count\t\t\t%" PRIu64 "\n", __func__, 1344f10a77bbSDavid C Somayajulu rstat->sw_pkt_count); 1345f10a77bbSDavid C Somayajulu device_printf(dev, "%s: ip_chksum_err\t\t%" PRIu64 "\n", __func__, 1346f10a77bbSDavid C Somayajulu rstat->ip_chksum_err); 1347f10a77bbSDavid C Somayajulu device_printf(dev, "%s: pkts_wo_acntxts\t\t%" PRIu64 "\n", __func__, 1348f10a77bbSDavid C Somayajulu rstat->pkts_wo_acntxts); 1349f10a77bbSDavid C Somayajulu device_printf(dev, "%s: pkts_dropped_no_sds_card\t%" PRIu64 "\n", 1350f10a77bbSDavid C Somayajulu __func__, rstat->pkts_dropped_no_sds_card); 1351f10a77bbSDavid C Somayajulu device_printf(dev, "%s: pkts_dropped_no_sds_host\t%" PRIu64 "\n", 1352f10a77bbSDavid C Somayajulu __func__, rstat->pkts_dropped_no_sds_host); 1353f10a77bbSDavid C Somayajulu device_printf(dev, "%s: oversized_pkts\t\t%" PRIu64 "\n", __func__, 1354f10a77bbSDavid C Somayajulu rstat->oversized_pkts); 1355f10a77bbSDavid C Somayajulu device_printf(dev, "%s: pkts_dropped_no_rds\t\t%" PRIu64 "\n", 1356f10a77bbSDavid C Somayajulu __func__, rstat->pkts_dropped_no_rds); 1357f10a77bbSDavid C Somayajulu device_printf(dev, "%s: unxpctd_mcast_pkts\t\t%" PRIu64 "\n", 1358f10a77bbSDavid C Somayajulu __func__, rstat->unxpctd_mcast_pkts); 1359f10a77bbSDavid C Somayajulu device_printf(dev, "%s: re1_fbq_error\t\t%" PRIu64 "\n", __func__, 1360f10a77bbSDavid C Somayajulu rstat->re1_fbq_error); 1361f10a77bbSDavid C Somayajulu device_printf(dev, "%s: invalid_mac_addr\t\t%" PRIu64 "\n", __func__, 1362f10a77bbSDavid C Somayajulu rstat->invalid_mac_addr); 1363f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rds_prime_trys\t\t%" PRIu64 "\n", __func__, 1364f10a77bbSDavid C Somayajulu rstat->rds_prime_trys); 1365f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rds_prime_success\t\t%" PRIu64 "\n", __func__, 1366f10a77bbSDavid C Somayajulu rstat->rds_prime_success); 1367f10a77bbSDavid C Somayajulu device_printf(dev, "%s: lro_flows_added\t\t%" PRIu64 "\n", __func__, 1368f10a77bbSDavid C Somayajulu rstat->lro_flows_added); 1369f10a77bbSDavid C Somayajulu device_printf(dev, "%s: lro_flows_deleted\t\t%" PRIu64 "\n", __func__, 1370f10a77bbSDavid C Somayajulu rstat->lro_flows_deleted); 1371f10a77bbSDavid C Somayajulu device_printf(dev, "%s: lro_flows_active\t\t%" PRIu64 "\n", __func__, 1372f10a77bbSDavid C Somayajulu rstat->lro_flows_active); 1373f10a77bbSDavid C Somayajulu device_printf(dev, "%s: pkts_droped_unknown\t\t%" PRIu64 "\n", 1374f10a77bbSDavid C Somayajulu __func__, rstat->pkts_droped_unknown); 1375f10a77bbSDavid C Somayajulu } 1376f10a77bbSDavid C Somayajulu 1377f10a77bbSDavid C Somayajulu static void 1378f10a77bbSDavid C Somayajulu qla_mac_stats(qla_host_t *ha, q80_mac_stats_t *mstat) 1379f10a77bbSDavid C Somayajulu { 1380f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 1381f10a77bbSDavid C Somayajulu 1382f10a77bbSDavid C Somayajulu device_printf(dev, "%s: xmt_frames\t\t\t%" PRIu64 "\n", __func__, 1383f10a77bbSDavid C Somayajulu mstat->xmt_frames); 1384f10a77bbSDavid C Somayajulu device_printf(dev, "%s: xmt_bytes\t\t\t%" PRIu64 "\n", __func__, 1385f10a77bbSDavid C Somayajulu mstat->xmt_bytes); 1386f10a77bbSDavid C Somayajulu device_printf(dev, "%s: xmt_mcast_pkts\t\t%" PRIu64 "\n", __func__, 1387f10a77bbSDavid C Somayajulu mstat->xmt_mcast_pkts); 1388f10a77bbSDavid C Somayajulu device_printf(dev, "%s: xmt_bcast_pkts\t\t%" PRIu64 "\n", __func__, 1389f10a77bbSDavid C Somayajulu mstat->xmt_bcast_pkts); 1390f10a77bbSDavid C Somayajulu device_printf(dev, "%s: xmt_pause_frames\t\t%" PRIu64 "\n", __func__, 1391f10a77bbSDavid C Somayajulu mstat->xmt_pause_frames); 1392f10a77bbSDavid C Somayajulu device_printf(dev, "%s: xmt_cntrl_pkts\t\t%" PRIu64 "\n", __func__, 1393f10a77bbSDavid C Somayajulu mstat->xmt_cntrl_pkts); 1394f10a77bbSDavid C Somayajulu device_printf(dev, "%s: xmt_pkt_lt_64bytes\t\t%" PRIu64 "\n", 1395f10a77bbSDavid C Somayajulu __func__, mstat->xmt_pkt_lt_64bytes); 1396f10a77bbSDavid C Somayajulu device_printf(dev, "%s: xmt_pkt_lt_127bytes\t\t%" PRIu64 "\n", 1397f10a77bbSDavid C Somayajulu __func__, mstat->xmt_pkt_lt_127bytes); 1398f10a77bbSDavid C Somayajulu device_printf(dev, "%s: xmt_pkt_lt_255bytes\t\t%" PRIu64 "\n", 1399f10a77bbSDavid C Somayajulu __func__, mstat->xmt_pkt_lt_255bytes); 1400f10a77bbSDavid C Somayajulu device_printf(dev, "%s: xmt_pkt_lt_511bytes\t\t%" PRIu64 "\n", 1401f10a77bbSDavid C Somayajulu __func__, mstat->xmt_pkt_lt_511bytes); 140235291c22SDavid C Somayajulu device_printf(dev, "%s: xmt_pkt_lt_1023bytes\t\t%" PRIu64 "\n", 1403f10a77bbSDavid C Somayajulu __func__, mstat->xmt_pkt_lt_1023bytes); 140435291c22SDavid C Somayajulu device_printf(dev, "%s: xmt_pkt_lt_1518bytes\t\t%" PRIu64 "\n", 1405f10a77bbSDavid C Somayajulu __func__, mstat->xmt_pkt_lt_1518bytes); 140635291c22SDavid C Somayajulu device_printf(dev, "%s: xmt_pkt_gt_1518bytes\t\t%" PRIu64 "\n", 1407f10a77bbSDavid C Somayajulu __func__, mstat->xmt_pkt_gt_1518bytes); 1408f10a77bbSDavid C Somayajulu 1409f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_frames\t\t\t%" PRIu64 "\n", __func__, 1410f10a77bbSDavid C Somayajulu mstat->rcv_frames); 1411f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_bytes\t\t\t%" PRIu64 "\n", __func__, 1412f10a77bbSDavid C Somayajulu mstat->rcv_bytes); 1413f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_mcast_pkts\t\t%" PRIu64 "\n", __func__, 1414f10a77bbSDavid C Somayajulu mstat->rcv_mcast_pkts); 1415f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_bcast_pkts\t\t%" PRIu64 "\n", __func__, 1416f10a77bbSDavid C Somayajulu mstat->rcv_bcast_pkts); 1417f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_pause_frames\t\t%" PRIu64 "\n", __func__, 1418f10a77bbSDavid C Somayajulu mstat->rcv_pause_frames); 1419f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_cntrl_pkts\t\t%" PRIu64 "\n", __func__, 1420f10a77bbSDavid C Somayajulu mstat->rcv_cntrl_pkts); 1421f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_pkt_lt_64bytes\t\t%" PRIu64 "\n", 1422f10a77bbSDavid C Somayajulu __func__, mstat->rcv_pkt_lt_64bytes); 1423f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_pkt_lt_127bytes\t\t%" PRIu64 "\n", 1424f10a77bbSDavid C Somayajulu __func__, mstat->rcv_pkt_lt_127bytes); 1425f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_pkt_lt_255bytes\t\t%" PRIu64 "\n", 1426f10a77bbSDavid C Somayajulu __func__, mstat->rcv_pkt_lt_255bytes); 1427f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_pkt_lt_511bytes\t\t%" PRIu64 "\n", 1428f10a77bbSDavid C Somayajulu __func__, mstat->rcv_pkt_lt_511bytes); 142935291c22SDavid C Somayajulu device_printf(dev, "%s: rcv_pkt_lt_1023bytes\t\t%" PRIu64 "\n", 1430f10a77bbSDavid C Somayajulu __func__, mstat->rcv_pkt_lt_1023bytes); 143135291c22SDavid C Somayajulu device_printf(dev, "%s: rcv_pkt_lt_1518bytes\t\t%" PRIu64 "\n", 1432f10a77bbSDavid C Somayajulu __func__, mstat->rcv_pkt_lt_1518bytes); 143335291c22SDavid C Somayajulu device_printf(dev, "%s: rcv_pkt_gt_1518bytes\t\t%" PRIu64 "\n", 1434f10a77bbSDavid C Somayajulu __func__, mstat->rcv_pkt_gt_1518bytes); 1435f10a77bbSDavid C Somayajulu 1436f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_len_error\t\t%" PRIu64 "\n", __func__, 1437f10a77bbSDavid C Somayajulu mstat->rcv_len_error); 1438f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_len_small\t\t%" PRIu64 "\n", __func__, 1439f10a77bbSDavid C Somayajulu mstat->rcv_len_small); 1440f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_len_large\t\t%" PRIu64 "\n", __func__, 1441f10a77bbSDavid C Somayajulu mstat->rcv_len_large); 1442f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_jabber\t\t\t%" PRIu64 "\n", __func__, 1443f10a77bbSDavid C Somayajulu mstat->rcv_jabber); 1444f10a77bbSDavid C Somayajulu device_printf(dev, "%s: rcv_dropped\t\t\t%" PRIu64 "\n", __func__, 1445f10a77bbSDavid C Somayajulu mstat->rcv_dropped); 1446f10a77bbSDavid C Somayajulu device_printf(dev, "%s: fcs_error\t\t\t%" PRIu64 "\n", __func__, 1447f10a77bbSDavid C Somayajulu mstat->fcs_error); 1448f10a77bbSDavid C Somayajulu device_printf(dev, "%s: align_error\t\t\t%" PRIu64 "\n", __func__, 1449f10a77bbSDavid C Somayajulu mstat->align_error); 1450f10a77bbSDavid C Somayajulu } 1451f10a77bbSDavid C Somayajulu 1452f10a77bbSDavid C Somayajulu 1453f10a77bbSDavid C Somayajulu static int 145435291c22SDavid C Somayajulu qla_get_hw_stats(qla_host_t *ha, uint32_t cmd, uint32_t rsp_size) 1455f10a77bbSDavid C Somayajulu { 1456f10a77bbSDavid C Somayajulu device_t dev; 1457f10a77bbSDavid C Somayajulu q80_get_stats_t *stat; 1458f10a77bbSDavid C Somayajulu q80_get_stats_rsp_t *stat_rsp; 1459f10a77bbSDavid C Somayajulu uint32_t err; 1460f10a77bbSDavid C Somayajulu 1461f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1462f10a77bbSDavid C Somayajulu 1463f10a77bbSDavid C Somayajulu stat = (q80_get_stats_t *)ha->hw.mbox; 1464f10a77bbSDavid C Somayajulu bzero(stat, (sizeof (q80_get_stats_t))); 1465f10a77bbSDavid C Somayajulu 1466f10a77bbSDavid C Somayajulu stat->opcode = Q8_MBX_GET_STATS; 1467f10a77bbSDavid C Somayajulu stat->count_version = 2; 1468f10a77bbSDavid C Somayajulu stat->count_version |= Q8_MBX_CMD_VERSION; 1469f10a77bbSDavid C Somayajulu 1470f10a77bbSDavid C Somayajulu stat->cmd = cmd; 1471f10a77bbSDavid C Somayajulu 1472f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)stat, 2, 147335291c22SDavid C Somayajulu ha->hw.mbox, (rsp_size >> 2), 0)) { 1474f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 1475f10a77bbSDavid C Somayajulu return -1; 1476f10a77bbSDavid C Somayajulu } 1477f10a77bbSDavid C Somayajulu 1478f10a77bbSDavid C Somayajulu stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox; 1479f10a77bbSDavid C Somayajulu 1480f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(stat_rsp->regcnt_status); 1481f10a77bbSDavid C Somayajulu 1482f10a77bbSDavid C Somayajulu if (err) { 1483f10a77bbSDavid C Somayajulu return -1; 1484f10a77bbSDavid C Somayajulu } 1485f10a77bbSDavid C Somayajulu 1486f10a77bbSDavid C Somayajulu return 0; 1487f10a77bbSDavid C Somayajulu } 1488f10a77bbSDavid C Somayajulu 1489f10a77bbSDavid C Somayajulu void 1490f10a77bbSDavid C Somayajulu ql_get_stats(qla_host_t *ha) 1491f10a77bbSDavid C Somayajulu { 1492f10a77bbSDavid C Somayajulu q80_get_stats_rsp_t *stat_rsp; 1493f10a77bbSDavid C Somayajulu q80_mac_stats_t *mstat; 1494f10a77bbSDavid C Somayajulu q80_xmt_stats_t *xstat; 1495f10a77bbSDavid C Somayajulu q80_rcv_stats_t *rstat; 1496f10a77bbSDavid C Somayajulu uint32_t cmd; 149735291c22SDavid C Somayajulu int i; 1498f10a77bbSDavid C Somayajulu 1499f10a77bbSDavid C Somayajulu stat_rsp = (q80_get_stats_rsp_t *)ha->hw.mbox; 1500f10a77bbSDavid C Somayajulu /* 1501f10a77bbSDavid C Somayajulu * Get MAC Statistics 1502f10a77bbSDavid C Somayajulu */ 1503f10a77bbSDavid C Somayajulu cmd = Q8_GET_STATS_CMD_TYPE_MAC; 150435291c22SDavid C Somayajulu // cmd |= Q8_GET_STATS_CMD_CLEAR; 1505f10a77bbSDavid C Somayajulu 1506f10a77bbSDavid C Somayajulu cmd |= ((ha->pci_func & 0x1) << 16); 1507f10a77bbSDavid C Somayajulu 150835291c22SDavid C Somayajulu if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) { 1509f10a77bbSDavid C Somayajulu mstat = (q80_mac_stats_t *)&stat_rsp->u.mac; 1510f10a77bbSDavid C Somayajulu qla_mac_stats(ha, mstat); 1511f10a77bbSDavid C Somayajulu } else { 1512f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: mac failed [0x%08x]\n", 1513f10a77bbSDavid C Somayajulu __func__, ha->hw.mbox[0]); 1514f10a77bbSDavid C Somayajulu } 1515f10a77bbSDavid C Somayajulu /* 1516f10a77bbSDavid C Somayajulu * Get RCV Statistics 1517f10a77bbSDavid C Somayajulu */ 1518f10a77bbSDavid C Somayajulu cmd = Q8_GET_STATS_CMD_RCV | Q8_GET_STATS_CMD_TYPE_CNTXT; 151935291c22SDavid C Somayajulu // cmd |= Q8_GET_STATS_CMD_CLEAR; 1520f10a77bbSDavid C Somayajulu cmd |= (ha->hw.rcv_cntxt_id << 16); 1521f10a77bbSDavid C Somayajulu 152235291c22SDavid C Somayajulu if (qla_get_hw_stats(ha, cmd, sizeof (q80_get_stats_rsp_t)) == 0) { 1523f10a77bbSDavid C Somayajulu rstat = (q80_rcv_stats_t *)&stat_rsp->u.rcv; 1524f10a77bbSDavid C Somayajulu qla_rcv_stats(ha, rstat); 1525f10a77bbSDavid C Somayajulu } else { 1526f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: rcv failed [0x%08x]\n", 1527f10a77bbSDavid C Somayajulu __func__, ha->hw.mbox[0]); 1528f10a77bbSDavid C Somayajulu } 1529f10a77bbSDavid C Somayajulu /* 1530f10a77bbSDavid C Somayajulu * Get XMT Statistics 1531f10a77bbSDavid C Somayajulu */ 153235291c22SDavid C Somayajulu for (i = 0 ; i < ha->hw.num_tx_rings; i++) { 1533f10a77bbSDavid C Somayajulu cmd = Q8_GET_STATS_CMD_XMT | Q8_GET_STATS_CMD_TYPE_CNTXT; 153435291c22SDavid C Somayajulu // cmd |= Q8_GET_STATS_CMD_CLEAR; 153535291c22SDavid C Somayajulu cmd |= (ha->hw.tx_cntxt[i].tx_cntxt_id << 16); 1536f10a77bbSDavid C Somayajulu 153735291c22SDavid C Somayajulu if (qla_get_hw_stats(ha, cmd, sizeof(q80_get_stats_rsp_t)) 153835291c22SDavid C Somayajulu == 0) { 1539f10a77bbSDavid C Somayajulu xstat = (q80_xmt_stats_t *)&stat_rsp->u.xmt; 154035291c22SDavid C Somayajulu qla_xmt_stats(ha, xstat, i); 1541f10a77bbSDavid C Somayajulu } else { 1542f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: xmt failed [0x%08x]\n", 1543f10a77bbSDavid C Somayajulu __func__, ha->hw.mbox[0]); 1544f10a77bbSDavid C Somayajulu } 1545f10a77bbSDavid C Somayajulu } 154635291c22SDavid C Somayajulu return; 154735291c22SDavid C Somayajulu } 154835291c22SDavid C Somayajulu 154935291c22SDavid C Somayajulu static void 155035291c22SDavid C Somayajulu qla_get_quick_stats(qla_host_t *ha) 155135291c22SDavid C Somayajulu { 155235291c22SDavid C Somayajulu q80_get_mac_rcv_xmt_stats_rsp_t *stat_rsp; 155335291c22SDavid C Somayajulu q80_mac_stats_t *mstat; 155435291c22SDavid C Somayajulu q80_xmt_stats_t *xstat; 155535291c22SDavid C Somayajulu q80_rcv_stats_t *rstat; 155635291c22SDavid C Somayajulu uint32_t cmd; 155735291c22SDavid C Somayajulu 155835291c22SDavid C Somayajulu stat_rsp = (q80_get_mac_rcv_xmt_stats_rsp_t *)ha->hw.mbox; 155935291c22SDavid C Somayajulu 156035291c22SDavid C Somayajulu cmd = Q8_GET_STATS_CMD_TYPE_ALL; 156135291c22SDavid C Somayajulu // cmd |= Q8_GET_STATS_CMD_CLEAR; 156235291c22SDavid C Somayajulu 156335291c22SDavid C Somayajulu // cmd |= ((ha->pci_func & 0x3) << 16); 156435291c22SDavid C Somayajulu cmd |= (0xFFFF << 16); 156535291c22SDavid C Somayajulu 156635291c22SDavid C Somayajulu if (qla_get_hw_stats(ha, cmd, 156735291c22SDavid C Somayajulu sizeof (q80_get_mac_rcv_xmt_stats_rsp_t)) == 0) { 156835291c22SDavid C Somayajulu 156935291c22SDavid C Somayajulu mstat = (q80_mac_stats_t *)&stat_rsp->mac; 157035291c22SDavid C Somayajulu rstat = (q80_rcv_stats_t *)&stat_rsp->rcv; 157135291c22SDavid C Somayajulu xstat = (q80_xmt_stats_t *)&stat_rsp->xmt; 157235291c22SDavid C Somayajulu qla_mac_stats(ha, mstat); 157335291c22SDavid C Somayajulu qla_rcv_stats(ha, rstat); 157435291c22SDavid C Somayajulu qla_xmt_stats(ha, xstat, ha->hw.num_tx_rings); 157535291c22SDavid C Somayajulu } else { 157635291c22SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed [0x%08x]\n", 157735291c22SDavid C Somayajulu __func__, ha->hw.mbox[0]); 157835291c22SDavid C Somayajulu } 157935291c22SDavid C Somayajulu return; 158035291c22SDavid C Somayajulu } 1581f10a77bbSDavid C Somayajulu 1582f10a77bbSDavid C Somayajulu /* 1583f10a77bbSDavid C Somayajulu * Name: qla_tx_tso 1584f10a77bbSDavid C Somayajulu * Function: Checks if the packet to be transmitted is a candidate for 1585f10a77bbSDavid C Somayajulu * Large TCP Segment Offload. If yes, the appropriate fields in the Tx 1586f10a77bbSDavid C Somayajulu * Ring Structure are plugged in. 1587f10a77bbSDavid C Somayajulu */ 1588f10a77bbSDavid C Somayajulu static int 1589f10a77bbSDavid C Somayajulu qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr) 1590f10a77bbSDavid C Somayajulu { 1591f10a77bbSDavid C Somayajulu struct ether_vlan_header *eh; 1592f10a77bbSDavid C Somayajulu struct ip *ip = NULL; 1593f10a77bbSDavid C Somayajulu struct ip6_hdr *ip6 = NULL; 1594f10a77bbSDavid C Somayajulu struct tcphdr *th = NULL; 1595f10a77bbSDavid C Somayajulu uint32_t ehdrlen, hdrlen, ip_hlen, tcp_hlen, tcp_opt_off; 1596f10a77bbSDavid C Somayajulu uint16_t etype, opcode, offload = 1; 1597f10a77bbSDavid C Somayajulu device_t dev; 1598f10a77bbSDavid C Somayajulu 1599f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1600f10a77bbSDavid C Somayajulu 1601f10a77bbSDavid C Somayajulu 1602f10a77bbSDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *); 1603f10a77bbSDavid C Somayajulu 1604f10a77bbSDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 1605f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 1606f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_proto); 1607f10a77bbSDavid C Somayajulu } else { 1608f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN; 1609f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_encap_proto); 1610f10a77bbSDavid C Somayajulu } 1611f10a77bbSDavid C Somayajulu 1612f10a77bbSDavid C Somayajulu hdrlen = 0; 1613f10a77bbSDavid C Somayajulu 1614f10a77bbSDavid C Somayajulu switch (etype) { 1615f10a77bbSDavid C Somayajulu case ETHERTYPE_IP: 1616f10a77bbSDavid C Somayajulu 1617f10a77bbSDavid C Somayajulu tcp_opt_off = ehdrlen + sizeof(struct ip) + 1618f10a77bbSDavid C Somayajulu sizeof(struct tcphdr); 1619f10a77bbSDavid C Somayajulu 1620f10a77bbSDavid C Somayajulu if (mp->m_len < tcp_opt_off) { 1621f10a77bbSDavid C Somayajulu m_copydata(mp, 0, tcp_opt_off, hdr); 1622f10a77bbSDavid C Somayajulu ip = (struct ip *)(hdr + ehdrlen); 1623f10a77bbSDavid C Somayajulu } else { 1624f10a77bbSDavid C Somayajulu ip = (struct ip *)(mp->m_data + ehdrlen); 1625f10a77bbSDavid C Somayajulu } 1626f10a77bbSDavid C Somayajulu 1627f10a77bbSDavid C Somayajulu ip_hlen = ip->ip_hl << 2; 1628f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_LSO; 1629f10a77bbSDavid C Somayajulu 1630f10a77bbSDavid C Somayajulu 1631f10a77bbSDavid C Somayajulu if ((ip->ip_p != IPPROTO_TCP) || 1632f10a77bbSDavid C Somayajulu (ip_hlen != sizeof (struct ip))){ 1633f10a77bbSDavid C Somayajulu /* IP Options are not supported */ 1634f10a77bbSDavid C Somayajulu 1635f10a77bbSDavid C Somayajulu offload = 0; 1636f10a77bbSDavid C Somayajulu } else 1637f10a77bbSDavid C Somayajulu th = (struct tcphdr *)((caddr_t)ip + ip_hlen); 1638f10a77bbSDavid C Somayajulu 1639f10a77bbSDavid C Somayajulu break; 1640f10a77bbSDavid C Somayajulu 1641f10a77bbSDavid C Somayajulu case ETHERTYPE_IPV6: 1642f10a77bbSDavid C Somayajulu 1643f10a77bbSDavid C Somayajulu tcp_opt_off = ehdrlen + sizeof(struct ip6_hdr) + 1644f10a77bbSDavid C Somayajulu sizeof (struct tcphdr); 1645f10a77bbSDavid C Somayajulu 1646f10a77bbSDavid C Somayajulu if (mp->m_len < tcp_opt_off) { 1647f10a77bbSDavid C Somayajulu m_copydata(mp, 0, tcp_opt_off, hdr); 1648f10a77bbSDavid C Somayajulu ip6 = (struct ip6_hdr *)(hdr + ehdrlen); 1649f10a77bbSDavid C Somayajulu } else { 1650f10a77bbSDavid C Somayajulu ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); 1651f10a77bbSDavid C Somayajulu } 1652f10a77bbSDavid C Somayajulu 1653f10a77bbSDavid C Somayajulu ip_hlen = sizeof(struct ip6_hdr); 1654f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6; 1655f10a77bbSDavid C Somayajulu 1656f10a77bbSDavid C Somayajulu if (ip6->ip6_nxt != IPPROTO_TCP) { 1657f10a77bbSDavid C Somayajulu //device_printf(dev, "%s: ipv6\n", __func__); 1658f10a77bbSDavid C Somayajulu offload = 0; 1659f10a77bbSDavid C Somayajulu } else 1660f10a77bbSDavid C Somayajulu th = (struct tcphdr *)((caddr_t)ip6 + ip_hlen); 1661f10a77bbSDavid C Somayajulu break; 1662f10a77bbSDavid C Somayajulu 1663f10a77bbSDavid C Somayajulu default: 1664f10a77bbSDavid C Somayajulu QL_DPRINT8(ha, (dev, "%s: type!=ip\n", __func__)); 1665f10a77bbSDavid C Somayajulu offload = 0; 1666f10a77bbSDavid C Somayajulu break; 1667f10a77bbSDavid C Somayajulu } 1668f10a77bbSDavid C Somayajulu 1669f10a77bbSDavid C Somayajulu if (!offload) 1670f10a77bbSDavid C Somayajulu return (-1); 1671f10a77bbSDavid C Somayajulu 1672f10a77bbSDavid C Somayajulu tcp_hlen = th->th_off << 2; 1673f10a77bbSDavid C Somayajulu hdrlen = ehdrlen + ip_hlen + tcp_hlen; 1674f10a77bbSDavid C Somayajulu 1675f10a77bbSDavid C Somayajulu if (mp->m_len < hdrlen) { 1676f10a77bbSDavid C Somayajulu if (mp->m_len < tcp_opt_off) { 1677f10a77bbSDavid C Somayajulu if (tcp_hlen > sizeof(struct tcphdr)) { 1678f10a77bbSDavid C Somayajulu m_copydata(mp, tcp_opt_off, 1679f10a77bbSDavid C Somayajulu (tcp_hlen - sizeof(struct tcphdr)), 1680f10a77bbSDavid C Somayajulu &hdr[tcp_opt_off]); 1681f10a77bbSDavid C Somayajulu } 1682f10a77bbSDavid C Somayajulu } else { 1683f10a77bbSDavid C Somayajulu m_copydata(mp, 0, hdrlen, hdr); 1684f10a77bbSDavid C Somayajulu } 1685f10a77bbSDavid C Somayajulu } 1686f10a77bbSDavid C Somayajulu 1687f10a77bbSDavid C Somayajulu tx_cmd->mss = mp->m_pkthdr.tso_segsz; 1688f10a77bbSDavid C Somayajulu 1689f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode = opcode ; 1690f10a77bbSDavid C Somayajulu tx_cmd->tcp_hdr_off = ip_hlen + ehdrlen; 1691f10a77bbSDavid C Somayajulu tx_cmd->total_hdr_len = hdrlen; 1692f10a77bbSDavid C Somayajulu 1693f10a77bbSDavid C Somayajulu /* Check for Multicast least significant bit of MSB == 1 */ 1694f10a77bbSDavid C Somayajulu if (eh->evl_dhost[0] & 0x01) { 1695f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_MULTICAST; 1696f10a77bbSDavid C Somayajulu } 1697f10a77bbSDavid C Somayajulu 1698f10a77bbSDavid C Somayajulu if (mp->m_len < hdrlen) { 1699f10a77bbSDavid C Somayajulu printf("%d\n", hdrlen); 1700f10a77bbSDavid C Somayajulu return (1); 1701f10a77bbSDavid C Somayajulu } 1702f10a77bbSDavid C Somayajulu 1703f10a77bbSDavid C Somayajulu return (0); 1704f10a77bbSDavid C Somayajulu } 1705f10a77bbSDavid C Somayajulu 1706f10a77bbSDavid C Somayajulu /* 1707f10a77bbSDavid C Somayajulu * Name: qla_tx_chksum 1708f10a77bbSDavid C Somayajulu * Function: Checks if the packet to be transmitted is a candidate for 1709f10a77bbSDavid C Somayajulu * TCP/UDP Checksum offload. If yes, the appropriate fields in the Tx 1710f10a77bbSDavid C Somayajulu * Ring Structure are plugged in. 1711f10a77bbSDavid C Somayajulu */ 1712f10a77bbSDavid C Somayajulu static int 1713f10a77bbSDavid C Somayajulu qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, uint32_t *op_code, 1714f10a77bbSDavid C Somayajulu uint32_t *tcp_hdr_off) 1715f10a77bbSDavid C Somayajulu { 1716f10a77bbSDavid C Somayajulu struct ether_vlan_header *eh; 1717f10a77bbSDavid C Somayajulu struct ip *ip; 1718f10a77bbSDavid C Somayajulu struct ip6_hdr *ip6; 1719f10a77bbSDavid C Somayajulu uint32_t ehdrlen, ip_hlen; 1720f10a77bbSDavid C Somayajulu uint16_t etype, opcode, offload = 1; 1721f10a77bbSDavid C Somayajulu device_t dev; 1722f10a77bbSDavid C Somayajulu uint8_t buf[sizeof(struct ip6_hdr)]; 1723f10a77bbSDavid C Somayajulu 1724f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1725f10a77bbSDavid C Somayajulu 1726f10a77bbSDavid C Somayajulu *op_code = 0; 1727f10a77bbSDavid C Somayajulu 1728f10a77bbSDavid C Somayajulu if ((mp->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) == 0) 1729f10a77bbSDavid C Somayajulu return (-1); 1730f10a77bbSDavid C Somayajulu 1731f10a77bbSDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *); 1732f10a77bbSDavid C Somayajulu 1733f10a77bbSDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 1734f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 1735f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_proto); 1736f10a77bbSDavid C Somayajulu } else { 1737f10a77bbSDavid C Somayajulu ehdrlen = ETHER_HDR_LEN; 1738f10a77bbSDavid C Somayajulu etype = ntohs(eh->evl_encap_proto); 1739f10a77bbSDavid C Somayajulu } 1740f10a77bbSDavid C Somayajulu 1741f10a77bbSDavid C Somayajulu 1742f10a77bbSDavid C Somayajulu switch (etype) { 1743f10a77bbSDavid C Somayajulu case ETHERTYPE_IP: 1744f10a77bbSDavid C Somayajulu ip = (struct ip *)(mp->m_data + ehdrlen); 1745f10a77bbSDavid C Somayajulu 1746f10a77bbSDavid C Somayajulu ip_hlen = sizeof (struct ip); 1747f10a77bbSDavid C Somayajulu 1748f10a77bbSDavid C Somayajulu if (mp->m_len < (ehdrlen + ip_hlen)) { 1749f10a77bbSDavid C Somayajulu m_copydata(mp, ehdrlen, sizeof(struct ip), buf); 1750f10a77bbSDavid C Somayajulu ip = (struct ip *)buf; 1751f10a77bbSDavid C Somayajulu } 1752f10a77bbSDavid C Somayajulu 1753f10a77bbSDavid C Somayajulu if (ip->ip_p == IPPROTO_TCP) 1754f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM; 1755f10a77bbSDavid C Somayajulu else if (ip->ip_p == IPPROTO_UDP) 1756f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM; 1757f10a77bbSDavid C Somayajulu else { 1758f10a77bbSDavid C Somayajulu //device_printf(dev, "%s: ipv4\n", __func__); 1759f10a77bbSDavid C Somayajulu offload = 0; 1760f10a77bbSDavid C Somayajulu } 1761f10a77bbSDavid C Somayajulu break; 1762f10a77bbSDavid C Somayajulu 1763f10a77bbSDavid C Somayajulu case ETHERTYPE_IPV6: 1764f10a77bbSDavid C Somayajulu ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); 1765f10a77bbSDavid C Somayajulu 1766f10a77bbSDavid C Somayajulu ip_hlen = sizeof(struct ip6_hdr); 1767f10a77bbSDavid C Somayajulu 1768f10a77bbSDavid C Somayajulu if (mp->m_len < (ehdrlen + ip_hlen)) { 1769f10a77bbSDavid C Somayajulu m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr), 1770f10a77bbSDavid C Somayajulu buf); 1771f10a77bbSDavid C Somayajulu ip6 = (struct ip6_hdr *)buf; 1772f10a77bbSDavid C Somayajulu } 1773f10a77bbSDavid C Somayajulu 1774f10a77bbSDavid C Somayajulu if (ip6->ip6_nxt == IPPROTO_TCP) 1775f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6; 1776f10a77bbSDavid C Somayajulu else if (ip6->ip6_nxt == IPPROTO_UDP) 1777f10a77bbSDavid C Somayajulu opcode = Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6; 1778f10a77bbSDavid C Somayajulu else { 1779f10a77bbSDavid C Somayajulu //device_printf(dev, "%s: ipv6\n", __func__); 1780f10a77bbSDavid C Somayajulu offload = 0; 1781f10a77bbSDavid C Somayajulu } 1782f10a77bbSDavid C Somayajulu break; 1783f10a77bbSDavid C Somayajulu 1784f10a77bbSDavid C Somayajulu default: 1785f10a77bbSDavid C Somayajulu offload = 0; 1786f10a77bbSDavid C Somayajulu break; 1787f10a77bbSDavid C Somayajulu } 1788f10a77bbSDavid C Somayajulu if (!offload) 1789f10a77bbSDavid C Somayajulu return (-1); 1790f10a77bbSDavid C Somayajulu 1791f10a77bbSDavid C Somayajulu *op_code = opcode; 1792f10a77bbSDavid C Somayajulu *tcp_hdr_off = (ip_hlen + ehdrlen); 1793f10a77bbSDavid C Somayajulu 1794f10a77bbSDavid C Somayajulu return (0); 1795f10a77bbSDavid C Somayajulu } 1796f10a77bbSDavid C Somayajulu 1797f10a77bbSDavid C Somayajulu #define QLA_TX_MIN_FREE 2 1798f10a77bbSDavid C Somayajulu /* 1799f10a77bbSDavid C Somayajulu * Name: ql_hw_send 1800f10a77bbSDavid C Somayajulu * Function: Transmits a packet. It first checks if the packet is a 1801f10a77bbSDavid C Somayajulu * candidate for Large TCP Segment Offload and then for UDP/TCP checksum 1802f10a77bbSDavid C Somayajulu * offload. If either of these creteria are not met, it is transmitted 1803f10a77bbSDavid C Somayajulu * as a regular ethernet frame. 1804f10a77bbSDavid C Somayajulu */ 1805f10a77bbSDavid C Somayajulu int 1806f10a77bbSDavid C Somayajulu ql_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs, 180735291c22SDavid C Somayajulu uint32_t tx_idx, struct mbuf *mp, uint32_t txr_idx, uint32_t iscsi_pdu) 1808f10a77bbSDavid C Somayajulu { 1809f10a77bbSDavid C Somayajulu struct ether_vlan_header *eh; 1810f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 1811f10a77bbSDavid C Somayajulu q80_tx_cmd_t *tx_cmd, tso_cmd; 1812f10a77bbSDavid C Somayajulu bus_dma_segment_t *c_seg; 1813f10a77bbSDavid C Somayajulu uint32_t num_tx_cmds, hdr_len = 0; 1814f10a77bbSDavid C Somayajulu uint32_t total_length = 0, bytes, tx_cmd_count = 0, txr_next; 1815f10a77bbSDavid C Somayajulu device_t dev; 1816f10a77bbSDavid C Somayajulu int i, ret; 1817f10a77bbSDavid C Somayajulu uint8_t *src = NULL, *dst = NULL; 1818f10a77bbSDavid C Somayajulu uint8_t frame_hdr[QL_FRAME_HDR_SIZE]; 1819f10a77bbSDavid C Somayajulu uint32_t op_code = 0; 1820f10a77bbSDavid C Somayajulu uint32_t tcp_hdr_off = 0; 1821f10a77bbSDavid C Somayajulu 1822f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 1823f10a77bbSDavid C Somayajulu 1824f10a77bbSDavid C Somayajulu /* 1825f10a77bbSDavid C Somayajulu * Always make sure there is atleast one empty slot in the tx_ring 1826f10a77bbSDavid C Somayajulu * tx_ring is considered full when there only one entry available 1827f10a77bbSDavid C Somayajulu */ 1828f10a77bbSDavid C Somayajulu num_tx_cmds = (nsegs + (Q8_TX_CMD_MAX_SEGMENTS - 1)) >> 2; 1829f10a77bbSDavid C Somayajulu 1830f10a77bbSDavid C Somayajulu total_length = mp->m_pkthdr.len; 1831f10a77bbSDavid C Somayajulu if (total_length > QLA_MAX_TSO_FRAME_SIZE) { 1832f10a77bbSDavid C Somayajulu device_printf(dev, "%s: total length exceeds maxlen(%d)\n", 1833f10a77bbSDavid C Somayajulu __func__, total_length); 1834f10a77bbSDavid C Somayajulu return (-1); 1835f10a77bbSDavid C Somayajulu } 1836f10a77bbSDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *); 1837f10a77bbSDavid C Somayajulu 1838f10a77bbSDavid C Somayajulu if (mp->m_pkthdr.csum_flags & CSUM_TSO) { 1839f10a77bbSDavid C Somayajulu 1840f10a77bbSDavid C Somayajulu bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t)); 1841f10a77bbSDavid C Somayajulu 1842f10a77bbSDavid C Somayajulu src = frame_hdr; 1843f10a77bbSDavid C Somayajulu ret = qla_tx_tso(ha, mp, &tso_cmd, src); 1844f10a77bbSDavid C Somayajulu 1845f10a77bbSDavid C Somayajulu if (!(ret & ~1)) { 1846f10a77bbSDavid C Somayajulu /* find the additional tx_cmd descriptors required */ 1847f10a77bbSDavid C Somayajulu 1848f10a77bbSDavid C Somayajulu if (mp->m_flags & M_VLANTAG) 1849f10a77bbSDavid C Somayajulu tso_cmd.total_hdr_len += ETHER_VLAN_ENCAP_LEN; 1850f10a77bbSDavid C Somayajulu 1851f10a77bbSDavid C Somayajulu hdr_len = tso_cmd.total_hdr_len; 1852f10a77bbSDavid C Somayajulu 1853f10a77bbSDavid C Somayajulu bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN; 1854f10a77bbSDavid C Somayajulu bytes = QL_MIN(bytes, hdr_len); 1855f10a77bbSDavid C Somayajulu 1856f10a77bbSDavid C Somayajulu num_tx_cmds++; 1857f10a77bbSDavid C Somayajulu hdr_len -= bytes; 1858f10a77bbSDavid C Somayajulu 1859f10a77bbSDavid C Somayajulu while (hdr_len) { 1860f10a77bbSDavid C Somayajulu bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len); 1861f10a77bbSDavid C Somayajulu hdr_len -= bytes; 1862f10a77bbSDavid C Somayajulu num_tx_cmds++; 1863f10a77bbSDavid C Somayajulu } 1864f10a77bbSDavid C Somayajulu hdr_len = tso_cmd.total_hdr_len; 1865f10a77bbSDavid C Somayajulu 1866f10a77bbSDavid C Somayajulu if (ret == 0) 1867f10a77bbSDavid C Somayajulu src = (uint8_t *)eh; 1868f10a77bbSDavid C Somayajulu } else 1869f10a77bbSDavid C Somayajulu return (EINVAL); 1870f10a77bbSDavid C Somayajulu } else { 1871f10a77bbSDavid C Somayajulu (void)qla_tx_chksum(ha, mp, &op_code, &tcp_hdr_off); 1872f10a77bbSDavid C Somayajulu } 1873f10a77bbSDavid C Somayajulu 187435291c22SDavid C Somayajulu if (iscsi_pdu) 187535291c22SDavid C Somayajulu ha->hw.iscsi_pkt_count++; 187635291c22SDavid C Somayajulu 1877f10a77bbSDavid C Somayajulu if (hw->tx_cntxt[txr_idx].txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) { 1878f10a77bbSDavid C Somayajulu qla_hw_tx_done_locked(ha, txr_idx); 1879f10a77bbSDavid C Somayajulu if (hw->tx_cntxt[txr_idx].txr_free <= 1880f10a77bbSDavid C Somayajulu (num_tx_cmds + QLA_TX_MIN_FREE)) { 1881f10a77bbSDavid C Somayajulu QL_DPRINT8(ha, (dev, "%s: (hw->txr_free <= " 1882f10a77bbSDavid C Somayajulu "(num_tx_cmds + QLA_TX_MIN_FREE))\n", 1883f10a77bbSDavid C Somayajulu __func__)); 1884f10a77bbSDavid C Somayajulu return (-1); 1885f10a77bbSDavid C Somayajulu } 1886f10a77bbSDavid C Somayajulu } 1887f10a77bbSDavid C Somayajulu 1888f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[tx_idx]; 1889f10a77bbSDavid C Somayajulu 1890f10a77bbSDavid C Somayajulu if (!(mp->m_pkthdr.csum_flags & CSUM_TSO)) { 1891f10a77bbSDavid C Somayajulu 1892f10a77bbSDavid C Somayajulu if (nsegs > ha->hw.max_tx_segs) 1893f10a77bbSDavid C Somayajulu ha->hw.max_tx_segs = nsegs; 1894f10a77bbSDavid C Somayajulu 1895f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 1896f10a77bbSDavid C Somayajulu 1897f10a77bbSDavid C Somayajulu if (op_code) { 1898f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode = op_code; 1899f10a77bbSDavid C Somayajulu tx_cmd->tcp_hdr_off = tcp_hdr_off; 1900f10a77bbSDavid C Somayajulu 1901f10a77bbSDavid C Somayajulu } else { 1902f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode = Q8_TX_CMD_OP_XMT_ETHER; 1903f10a77bbSDavid C Somayajulu } 1904f10a77bbSDavid C Somayajulu } else { 1905f10a77bbSDavid C Somayajulu bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t)); 1906f10a77bbSDavid C Somayajulu ha->tx_tso_frames++; 1907f10a77bbSDavid C Somayajulu } 1908f10a77bbSDavid C Somayajulu 1909f10a77bbSDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 1910f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED; 191135291c22SDavid C Somayajulu 191235291c22SDavid C Somayajulu if (iscsi_pdu) 191335291c22SDavid C Somayajulu eh->evl_tag |= ha->hw.user_pri_iscsi << 13; 191435291c22SDavid C Somayajulu 1915f10a77bbSDavid C Somayajulu } else if (mp->m_flags & M_VLANTAG) { 1916f10a77bbSDavid C Somayajulu 1917f10a77bbSDavid C Somayajulu if (hdr_len) { /* TSO */ 1918f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= (Q8_TX_CMD_FLAGS_VLAN_TAGGED | 1919f10a77bbSDavid C Somayajulu Q8_TX_CMD_FLAGS_HW_VLAN_ID); 1920f10a77bbSDavid C Somayajulu tx_cmd->tcp_hdr_off += ETHER_VLAN_ENCAP_LEN; 1921f10a77bbSDavid C Somayajulu } else 1922f10a77bbSDavid C Somayajulu tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_HW_VLAN_ID; 1923f10a77bbSDavid C Somayajulu 1924f10a77bbSDavid C Somayajulu ha->hw_vlan_tx_frames++; 1925f10a77bbSDavid C Somayajulu tx_cmd->vlan_tci = mp->m_pkthdr.ether_vtag; 192635291c22SDavid C Somayajulu 192735291c22SDavid C Somayajulu if (iscsi_pdu) { 192835291c22SDavid C Somayajulu tx_cmd->vlan_tci |= ha->hw.user_pri_iscsi << 13; 192935291c22SDavid C Somayajulu mp->m_pkthdr.ether_vtag = tx_cmd->vlan_tci; 193035291c22SDavid C Somayajulu } 1931f10a77bbSDavid C Somayajulu } 1932f10a77bbSDavid C Somayajulu 1933f10a77bbSDavid C Somayajulu 1934f10a77bbSDavid C Somayajulu tx_cmd->n_bufs = (uint8_t)nsegs; 1935f10a77bbSDavid C Somayajulu tx_cmd->data_len_lo = (uint8_t)(total_length & 0xFF); 1936f10a77bbSDavid C Somayajulu tx_cmd->data_len_hi = qla_host_to_le16(((uint16_t)(total_length >> 8))); 1937f10a77bbSDavid C Somayajulu tx_cmd->cntxtid = Q8_TX_CMD_PORT_CNXTID(ha->pci_func); 1938f10a77bbSDavid C Somayajulu 1939f10a77bbSDavid C Somayajulu c_seg = segs; 1940f10a77bbSDavid C Somayajulu 1941f10a77bbSDavid C Somayajulu while (1) { 1942f10a77bbSDavid C Somayajulu for (i = 0; ((i < Q8_TX_CMD_MAX_SEGMENTS) && nsegs); i++) { 1943f10a77bbSDavid C Somayajulu 1944f10a77bbSDavid C Somayajulu switch (i) { 1945f10a77bbSDavid C Somayajulu case 0: 1946f10a77bbSDavid C Somayajulu tx_cmd->buf1_addr = c_seg->ds_addr; 1947f10a77bbSDavid C Somayajulu tx_cmd->buf1_len = c_seg->ds_len; 1948f10a77bbSDavid C Somayajulu break; 1949f10a77bbSDavid C Somayajulu 1950f10a77bbSDavid C Somayajulu case 1: 1951f10a77bbSDavid C Somayajulu tx_cmd->buf2_addr = c_seg->ds_addr; 1952f10a77bbSDavid C Somayajulu tx_cmd->buf2_len = c_seg->ds_len; 1953f10a77bbSDavid C Somayajulu break; 1954f10a77bbSDavid C Somayajulu 1955f10a77bbSDavid C Somayajulu case 2: 1956f10a77bbSDavid C Somayajulu tx_cmd->buf3_addr = c_seg->ds_addr; 1957f10a77bbSDavid C Somayajulu tx_cmd->buf3_len = c_seg->ds_len; 1958f10a77bbSDavid C Somayajulu break; 1959f10a77bbSDavid C Somayajulu 1960f10a77bbSDavid C Somayajulu case 3: 1961f10a77bbSDavid C Somayajulu tx_cmd->buf4_addr = c_seg->ds_addr; 1962f10a77bbSDavid C Somayajulu tx_cmd->buf4_len = c_seg->ds_len; 1963f10a77bbSDavid C Somayajulu break; 1964f10a77bbSDavid C Somayajulu } 1965f10a77bbSDavid C Somayajulu 1966f10a77bbSDavid C Somayajulu c_seg++; 1967f10a77bbSDavid C Somayajulu nsegs--; 1968f10a77bbSDavid C Somayajulu } 1969f10a77bbSDavid C Somayajulu 1970f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next = 1971f10a77bbSDavid C Somayajulu (hw->tx_cntxt[txr_idx].txr_next + 1) & 1972f10a77bbSDavid C Somayajulu (NUM_TX_DESCRIPTORS - 1); 1973f10a77bbSDavid C Somayajulu tx_cmd_count++; 1974f10a77bbSDavid C Somayajulu 1975f10a77bbSDavid C Somayajulu if (!nsegs) 1976f10a77bbSDavid C Somayajulu break; 1977f10a77bbSDavid C Somayajulu 1978f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next]; 1979f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 1980f10a77bbSDavid C Somayajulu } 1981f10a77bbSDavid C Somayajulu 1982f10a77bbSDavid C Somayajulu if (mp->m_pkthdr.csum_flags & CSUM_TSO) { 1983f10a77bbSDavid C Somayajulu 1984f10a77bbSDavid C Somayajulu /* TSO : Copy the header in the following tx cmd descriptors */ 1985f10a77bbSDavid C Somayajulu 1986f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next; 1987f10a77bbSDavid C Somayajulu 1988f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next]; 1989f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 1990f10a77bbSDavid C Somayajulu 1991f10a77bbSDavid C Somayajulu bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN; 1992f10a77bbSDavid C Somayajulu bytes = QL_MIN(bytes, hdr_len); 1993f10a77bbSDavid C Somayajulu 1994f10a77bbSDavid C Somayajulu dst = (uint8_t *)tx_cmd + Q8_TX_CMD_TSO_ALIGN; 1995f10a77bbSDavid C Somayajulu 1996f10a77bbSDavid C Somayajulu if (mp->m_flags & M_VLANTAG) { 1997f10a77bbSDavid C Somayajulu /* first copy the src/dst MAC addresses */ 1998f10a77bbSDavid C Somayajulu bcopy(src, dst, (ETHER_ADDR_LEN * 2)); 1999f10a77bbSDavid C Somayajulu dst += (ETHER_ADDR_LEN * 2); 2000f10a77bbSDavid C Somayajulu src += (ETHER_ADDR_LEN * 2); 2001f10a77bbSDavid C Somayajulu 2002f10a77bbSDavid C Somayajulu *((uint16_t *)dst) = htons(ETHERTYPE_VLAN); 2003f10a77bbSDavid C Somayajulu dst += 2; 2004f10a77bbSDavid C Somayajulu *((uint16_t *)dst) = htons(mp->m_pkthdr.ether_vtag); 2005f10a77bbSDavid C Somayajulu dst += 2; 2006f10a77bbSDavid C Somayajulu 2007f10a77bbSDavid C Somayajulu /* bytes left in src header */ 2008f10a77bbSDavid C Somayajulu hdr_len -= ((ETHER_ADDR_LEN * 2) + 2009f10a77bbSDavid C Somayajulu ETHER_VLAN_ENCAP_LEN); 2010f10a77bbSDavid C Somayajulu 2011f10a77bbSDavid C Somayajulu /* bytes left in TxCmd Entry */ 2012f10a77bbSDavid C Somayajulu bytes -= ((ETHER_ADDR_LEN * 2) + ETHER_VLAN_ENCAP_LEN); 2013f10a77bbSDavid C Somayajulu 2014f10a77bbSDavid C Somayajulu 2015f10a77bbSDavid C Somayajulu bcopy(src, dst, bytes); 2016f10a77bbSDavid C Somayajulu src += bytes; 2017f10a77bbSDavid C Somayajulu hdr_len -= bytes; 2018f10a77bbSDavid C Somayajulu } else { 2019f10a77bbSDavid C Somayajulu bcopy(src, dst, bytes); 2020f10a77bbSDavid C Somayajulu src += bytes; 2021f10a77bbSDavid C Somayajulu hdr_len -= bytes; 2022f10a77bbSDavid C Somayajulu } 2023f10a77bbSDavid C Somayajulu 2024f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next = 2025f10a77bbSDavid C Somayajulu (hw->tx_cntxt[txr_idx].txr_next + 1) & 2026f10a77bbSDavid C Somayajulu (NUM_TX_DESCRIPTORS - 1); 2027f10a77bbSDavid C Somayajulu tx_cmd_count++; 2028f10a77bbSDavid C Somayajulu 2029f10a77bbSDavid C Somayajulu while (hdr_len) { 2030f10a77bbSDavid C Somayajulu tx_cmd = &hw->tx_cntxt[txr_idx].tx_ring_base[txr_next]; 2031f10a77bbSDavid C Somayajulu bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t)); 2032f10a77bbSDavid C Somayajulu 2033f10a77bbSDavid C Somayajulu bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len); 2034f10a77bbSDavid C Somayajulu 2035f10a77bbSDavid C Somayajulu bcopy(src, tx_cmd, bytes); 2036f10a77bbSDavid C Somayajulu src += bytes; 2037f10a77bbSDavid C Somayajulu hdr_len -= bytes; 2038f10a77bbSDavid C Somayajulu 2039f10a77bbSDavid C Somayajulu txr_next = hw->tx_cntxt[txr_idx].txr_next = 2040f10a77bbSDavid C Somayajulu (hw->tx_cntxt[txr_idx].txr_next + 1) & 2041f10a77bbSDavid C Somayajulu (NUM_TX_DESCRIPTORS - 1); 2042f10a77bbSDavid C Somayajulu tx_cmd_count++; 2043f10a77bbSDavid C Somayajulu } 2044f10a77bbSDavid C Somayajulu } 2045f10a77bbSDavid C Somayajulu 2046f10a77bbSDavid C Somayajulu hw->tx_cntxt[txr_idx].txr_free = 2047f10a77bbSDavid C Somayajulu hw->tx_cntxt[txr_idx].txr_free - tx_cmd_count; 2048f10a77bbSDavid C Somayajulu 2049f10a77bbSDavid C Somayajulu QL_UPDATE_TX_PRODUCER_INDEX(ha, hw->tx_cntxt[txr_idx].txr_next,\ 2050f10a77bbSDavid C Somayajulu txr_idx); 2051f10a77bbSDavid C Somayajulu QL_DPRINT8(ha, (dev, "%s: return\n", __func__)); 2052f10a77bbSDavid C Somayajulu 2053f10a77bbSDavid C Somayajulu return (0); 2054f10a77bbSDavid C Somayajulu } 2055f10a77bbSDavid C Somayajulu 2056f10a77bbSDavid C Somayajulu 205735291c22SDavid C Somayajulu 205835291c22SDavid C Somayajulu #define Q8_CONFIG_IND_TBL_SIZE 32 /* < Q8_RSS_IND_TBL_SIZE and power of 2 */ 2059f10a77bbSDavid C Somayajulu static int 2060f10a77bbSDavid C Somayajulu qla_config_rss_ind_table(qla_host_t *ha) 2061f10a77bbSDavid C Somayajulu { 2062f10a77bbSDavid C Somayajulu uint32_t i, count; 206335291c22SDavid C Somayajulu uint8_t rss_ind_tbl[Q8_CONFIG_IND_TBL_SIZE]; 2064f10a77bbSDavid C Somayajulu 2065f10a77bbSDavid C Somayajulu 206635291c22SDavid C Somayajulu for (i = 0; i < Q8_CONFIG_IND_TBL_SIZE; i++) { 2067f10a77bbSDavid C Somayajulu rss_ind_tbl[i] = i % ha->hw.num_sds_rings; 2068f10a77bbSDavid C Somayajulu } 2069f10a77bbSDavid C Somayajulu 207035291c22SDavid C Somayajulu for (i = 0; i <= Q8_RSS_IND_TBL_MAX_IDX ; 207135291c22SDavid C Somayajulu i = i + Q8_CONFIG_IND_TBL_SIZE) { 2072f10a77bbSDavid C Somayajulu 207335291c22SDavid C Somayajulu if ((i + Q8_CONFIG_IND_TBL_SIZE) > Q8_RSS_IND_TBL_MAX_IDX) { 2074f10a77bbSDavid C Somayajulu count = Q8_RSS_IND_TBL_MAX_IDX - i + 1; 2075f10a77bbSDavid C Somayajulu } else { 207635291c22SDavid C Somayajulu count = Q8_CONFIG_IND_TBL_SIZE; 2077f10a77bbSDavid C Somayajulu } 2078f10a77bbSDavid C Somayajulu 2079f10a77bbSDavid C Somayajulu if (qla_set_rss_ind_table(ha, i, count, ha->hw.rcv_cntxt_id, 2080f10a77bbSDavid C Somayajulu rss_ind_tbl)) 2081f10a77bbSDavid C Somayajulu return (-1); 2082f10a77bbSDavid C Somayajulu } 2083f10a77bbSDavid C Somayajulu 2084f10a77bbSDavid C Somayajulu return (0); 2085f10a77bbSDavid C Somayajulu } 2086f10a77bbSDavid C Somayajulu 2087f10a77bbSDavid C Somayajulu /* 2088f10a77bbSDavid C Somayajulu * Name: ql_del_hw_if 2089f10a77bbSDavid C Somayajulu * Function: Destroys the hardware specific entities corresponding to an 2090f10a77bbSDavid C Somayajulu * Ethernet Interface 2091f10a77bbSDavid C Somayajulu */ 2092f10a77bbSDavid C Somayajulu void 2093f10a77bbSDavid C Somayajulu ql_del_hw_if(qla_host_t *ha) 2094f10a77bbSDavid C Somayajulu { 209535291c22SDavid C Somayajulu uint32_t i; 209635291c22SDavid C Somayajulu uint32_t num_msix; 209735291c22SDavid C Somayajulu 209835291c22SDavid C Somayajulu (void)qla_stop_nic_func(ha); 2099f10a77bbSDavid C Somayajulu 2100f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(ha); 2101f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt(ha); 2102f10a77bbSDavid C Somayajulu 2103f10a77bbSDavid C Somayajulu if (ha->hw.flags.init_intr_cnxt) { 210435291c22SDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; ) { 210535291c22SDavid C Somayajulu 210635291c22SDavid C Somayajulu if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings) 210735291c22SDavid C Somayajulu num_msix = Q8_MAX_INTR_VECTORS; 210835291c22SDavid C Somayajulu else 210935291c22SDavid C Somayajulu num_msix = ha->hw.num_sds_rings - i; 211035291c22SDavid C Somayajulu qla_config_intr_cntxt(ha, i, num_msix, 0); 211135291c22SDavid C Somayajulu 211235291c22SDavid C Somayajulu i += num_msix; 211335291c22SDavid C Somayajulu } 211435291c22SDavid C Somayajulu 2115f10a77bbSDavid C Somayajulu ha->hw.flags.init_intr_cnxt = 0; 2116f10a77bbSDavid C Somayajulu } 211735291c22SDavid C Somayajulu return; 2118f10a77bbSDavid C Somayajulu } 2119f10a77bbSDavid C Somayajulu 212035291c22SDavid C Somayajulu void 212135291c22SDavid C Somayajulu qla_confirm_9kb_enable(qla_host_t *ha) 212235291c22SDavid C Somayajulu { 212335291c22SDavid C Somayajulu uint32_t supports_9kb = 0; 212435291c22SDavid C Somayajulu 212535291c22SDavid C Somayajulu ha->hw.mbx_intr_mask_offset = READ_REG32(ha, Q8_MBOX_INT_MASK_MSIX); 212635291c22SDavid C Somayajulu 212735291c22SDavid C Somayajulu /* Use MSI-X vector 0; Enable Firmware Mailbox Interrupt */ 212835291c22SDavid C Somayajulu WRITE_REG32(ha, Q8_MBOX_INT_ENABLE, BIT_2); 212935291c22SDavid C Somayajulu WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0); 213035291c22SDavid C Somayajulu 213135291c22SDavid C Somayajulu qla_get_nic_partition(ha, &supports_9kb, NULL); 213235291c22SDavid C Somayajulu 213335291c22SDavid C Somayajulu if (!supports_9kb) 213435291c22SDavid C Somayajulu ha->hw.enable_9kb = 0; 213535291c22SDavid C Somayajulu 213635291c22SDavid C Somayajulu return; 213735291c22SDavid C Somayajulu } 213835291c22SDavid C Somayajulu 213935291c22SDavid C Somayajulu 2140f10a77bbSDavid C Somayajulu /* 2141f10a77bbSDavid C Somayajulu * Name: ql_init_hw_if 2142f10a77bbSDavid C Somayajulu * Function: Creates the hardware specific entities corresponding to an 2143f10a77bbSDavid C Somayajulu * Ethernet Interface - Transmit and Receive Contexts. Sets the MAC Address 2144f10a77bbSDavid C Somayajulu * corresponding to the interface. Enables LRO if allowed. 2145f10a77bbSDavid C Somayajulu */ 2146f10a77bbSDavid C Somayajulu int 2147f10a77bbSDavid C Somayajulu ql_init_hw_if(qla_host_t *ha) 2148f10a77bbSDavid C Somayajulu { 2149f10a77bbSDavid C Somayajulu device_t dev; 2150f10a77bbSDavid C Somayajulu uint32_t i; 2151f10a77bbSDavid C Somayajulu uint8_t bcast_mac[6]; 2152f10a77bbSDavid C Somayajulu qla_rdesc_t *rdesc; 215335291c22SDavid C Somayajulu uint32_t num_msix; 2154f10a77bbSDavid C Somayajulu 2155f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 2156f10a77bbSDavid C Somayajulu 2157f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 2158f10a77bbSDavid C Somayajulu bzero(ha->hw.dma_buf.sds_ring[i].dma_b, 2159f10a77bbSDavid C Somayajulu ha->hw.dma_buf.sds_ring[i].size); 2160f10a77bbSDavid C Somayajulu } 2161f10a77bbSDavid C Somayajulu 216235291c22SDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; ) { 2163f10a77bbSDavid C Somayajulu 216435291c22SDavid C Somayajulu if ((i + Q8_MAX_INTR_VECTORS) < ha->hw.num_sds_rings) 216535291c22SDavid C Somayajulu num_msix = Q8_MAX_INTR_VECTORS; 216635291c22SDavid C Somayajulu else 216735291c22SDavid C Somayajulu num_msix = ha->hw.num_sds_rings - i; 2168f10a77bbSDavid C Somayajulu 216935291c22SDavid C Somayajulu if (qla_config_intr_cntxt(ha, i, num_msix, 1)) { 217035291c22SDavid C Somayajulu 217135291c22SDavid C Somayajulu if (i > 0) { 217235291c22SDavid C Somayajulu 217335291c22SDavid C Somayajulu num_msix = i; 217435291c22SDavid C Somayajulu 217535291c22SDavid C Somayajulu for (i = 0; i < num_msix; ) { 217635291c22SDavid C Somayajulu qla_config_intr_cntxt(ha, i, 217735291c22SDavid C Somayajulu Q8_MAX_INTR_VECTORS, 0); 217835291c22SDavid C Somayajulu i += Q8_MAX_INTR_VECTORS; 217935291c22SDavid C Somayajulu } 218035291c22SDavid C Somayajulu } 2181f10a77bbSDavid C Somayajulu return (-1); 218235291c22SDavid C Somayajulu } 218335291c22SDavid C Somayajulu 218435291c22SDavid C Somayajulu i = i + num_msix; 218535291c22SDavid C Somayajulu } 218635291c22SDavid C Somayajulu 218735291c22SDavid C Somayajulu ha->hw.flags.init_intr_cnxt = 1; 2188f10a77bbSDavid C Somayajulu 2189f10a77bbSDavid C Somayajulu if (ha->hw.mdump_init == 0) { 2190f10a77bbSDavid C Somayajulu qla_minidump_init(ha); 2191f10a77bbSDavid C Somayajulu } 2192f10a77bbSDavid C Somayajulu 2193f10a77bbSDavid C Somayajulu /* 2194f10a77bbSDavid C Somayajulu * Create Receive Context 2195f10a77bbSDavid C Somayajulu */ 2196f10a77bbSDavid C Somayajulu if (qla_init_rcv_cntxt(ha)) { 2197f10a77bbSDavid C Somayajulu return (-1); 2198f10a77bbSDavid C Somayajulu } 2199f10a77bbSDavid C Somayajulu 2200f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) { 2201f10a77bbSDavid C Somayajulu rdesc = &ha->hw.rds[i]; 2202f10a77bbSDavid C Somayajulu rdesc->rx_next = NUM_RX_DESCRIPTORS - 2; 2203f10a77bbSDavid C Somayajulu rdesc->rx_in = 0; 2204f10a77bbSDavid C Somayajulu /* Update the RDS Producer Indices */ 2205f10a77bbSDavid C Somayajulu QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,\ 2206f10a77bbSDavid C Somayajulu rdesc->rx_next); 2207f10a77bbSDavid C Somayajulu } 2208f10a77bbSDavid C Somayajulu 2209f10a77bbSDavid C Somayajulu 2210f10a77bbSDavid C Somayajulu /* 2211f10a77bbSDavid C Somayajulu * Create Transmit Context 2212f10a77bbSDavid C Somayajulu */ 2213f10a77bbSDavid C Somayajulu if (qla_init_xmt_cntxt(ha)) { 2214f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(ha); 2215f10a77bbSDavid C Somayajulu return (-1); 2216f10a77bbSDavid C Somayajulu } 2217f10a77bbSDavid C Somayajulu ha->hw.max_tx_segs = 0; 2218f10a77bbSDavid C Somayajulu 2219f10a77bbSDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr, 1)) 2220f10a77bbSDavid C Somayajulu return(-1); 2221f10a77bbSDavid C Somayajulu 2222f10a77bbSDavid C Somayajulu ha->hw.flags.unicast_mac = 1; 2223f10a77bbSDavid C Somayajulu 2224f10a77bbSDavid C Somayajulu bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF; 2225f10a77bbSDavid C Somayajulu bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF; 2226f10a77bbSDavid C Somayajulu 2227f10a77bbSDavid C Somayajulu if (qla_config_mac_addr(ha, bcast_mac, 1)) 2228f10a77bbSDavid C Somayajulu return (-1); 2229f10a77bbSDavid C Somayajulu 2230f10a77bbSDavid C Somayajulu ha->hw.flags.bcast_mac = 1; 2231f10a77bbSDavid C Somayajulu 2232f10a77bbSDavid C Somayajulu /* 2233f10a77bbSDavid C Somayajulu * program any cached multicast addresses 2234f10a77bbSDavid C Somayajulu */ 2235f10a77bbSDavid C Somayajulu if (qla_hw_add_all_mcast(ha)) 2236f10a77bbSDavid C Somayajulu return (-1); 2237f10a77bbSDavid C Somayajulu 2238f10a77bbSDavid C Somayajulu if (qla_config_rss(ha, ha->hw.rcv_cntxt_id)) 2239f10a77bbSDavid C Somayajulu return (-1); 2240f10a77bbSDavid C Somayajulu 2241f10a77bbSDavid C Somayajulu if (qla_config_rss_ind_table(ha)) 2242f10a77bbSDavid C Somayajulu return (-1); 2243f10a77bbSDavid C Somayajulu 224435291c22SDavid C Somayajulu if (qla_config_intr_coalesce(ha, ha->hw.rcv_cntxt_id, 0, 1)) 2245f10a77bbSDavid C Somayajulu return (-1); 2246f10a77bbSDavid C Somayajulu 2247f10a77bbSDavid C Somayajulu if (qla_link_event_req(ha, ha->hw.rcv_cntxt_id)) 2248f10a77bbSDavid C Somayajulu return (-1); 2249f10a77bbSDavid C Somayajulu 2250f10a77bbSDavid C Somayajulu if (qla_config_fw_lro(ha, ha->hw.rcv_cntxt_id)) 2251f10a77bbSDavid C Somayajulu return (-1); 2252f10a77bbSDavid C Somayajulu 225335291c22SDavid C Somayajulu if (qla_init_nic_func(ha)) 225435291c22SDavid C Somayajulu return (-1); 225535291c22SDavid C Somayajulu 225635291c22SDavid C Somayajulu if (qla_query_fw_dcbx_caps(ha)) 225735291c22SDavid C Somayajulu return (-1); 225835291c22SDavid C Somayajulu 2259f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) 2260f10a77bbSDavid C Somayajulu QL_ENABLE_INTERRUPTS(ha, i); 2261f10a77bbSDavid C Somayajulu 2262f10a77bbSDavid C Somayajulu return (0); 2263f10a77bbSDavid C Somayajulu } 2264f10a77bbSDavid C Somayajulu 2265f10a77bbSDavid C Somayajulu static int 226635291c22SDavid C Somayajulu qla_map_sds_to_rds(qla_host_t *ha, uint32_t start_idx, uint32_t num_idx) 2267f10a77bbSDavid C Somayajulu { 2268f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 2269f10a77bbSDavid C Somayajulu q80_rq_map_sds_to_rds_t *map_rings; 227035291c22SDavid C Somayajulu q80_rsp_map_sds_to_rds_t *map_rings_rsp; 2271f10a77bbSDavid C Somayajulu uint32_t i, err; 2272f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 2273f10a77bbSDavid C Somayajulu 2274f10a77bbSDavid C Somayajulu map_rings = (q80_rq_map_sds_to_rds_t *)ha->hw.mbox; 2275f10a77bbSDavid C Somayajulu bzero(map_rings, sizeof(q80_rq_map_sds_to_rds_t)); 2276f10a77bbSDavid C Somayajulu 2277f10a77bbSDavid C Somayajulu map_rings->opcode = Q8_MBX_MAP_SDS_TO_RDS; 2278f10a77bbSDavid C Somayajulu map_rings->count_version = (sizeof (q80_rq_map_sds_to_rds_t) >> 2); 2279f10a77bbSDavid C Somayajulu map_rings->count_version |= Q8_MBX_CMD_VERSION; 2280f10a77bbSDavid C Somayajulu 2281f10a77bbSDavid C Somayajulu map_rings->cntxt_id = hw->rcv_cntxt_id; 228235291c22SDavid C Somayajulu map_rings->num_rings = num_idx; 2283f10a77bbSDavid C Somayajulu 228435291c22SDavid C Somayajulu for (i = 0; i < num_idx; i++) { 228535291c22SDavid C Somayajulu map_rings->sds_rds[i].sds_ring = i + start_idx; 228635291c22SDavid C Somayajulu map_rings->sds_rds[i].rds_ring = i + start_idx; 2287f10a77bbSDavid C Somayajulu } 2288f10a77bbSDavid C Somayajulu 2289f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)map_rings, 2290f10a77bbSDavid C Somayajulu (sizeof (q80_rq_map_sds_to_rds_t) >> 2), 2291f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) { 2292f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 2293f10a77bbSDavid C Somayajulu return (-1); 2294f10a77bbSDavid C Somayajulu } 2295f10a77bbSDavid C Somayajulu 229635291c22SDavid C Somayajulu map_rings_rsp = (q80_rsp_map_sds_to_rds_t *)ha->hw.mbox; 2297f10a77bbSDavid C Somayajulu 2298f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(map_rings_rsp->regcnt_status); 2299f10a77bbSDavid C Somayajulu 2300f10a77bbSDavid C Somayajulu if (err) { 2301f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2302f10a77bbSDavid C Somayajulu return (-1); 2303f10a77bbSDavid C Somayajulu } 2304f10a77bbSDavid C Somayajulu 2305f10a77bbSDavid C Somayajulu return (0); 2306f10a77bbSDavid C Somayajulu } 2307f10a77bbSDavid C Somayajulu 2308f10a77bbSDavid C Somayajulu /* 2309f10a77bbSDavid C Somayajulu * Name: qla_init_rcv_cntxt 2310f10a77bbSDavid C Somayajulu * Function: Creates the Receive Context. 2311f10a77bbSDavid C Somayajulu */ 2312f10a77bbSDavid C Somayajulu static int 2313f10a77bbSDavid C Somayajulu qla_init_rcv_cntxt(qla_host_t *ha) 2314f10a77bbSDavid C Somayajulu { 2315f10a77bbSDavid C Somayajulu q80_rq_rcv_cntxt_t *rcntxt; 2316f10a77bbSDavid C Somayajulu q80_rsp_rcv_cntxt_t *rcntxt_rsp; 2317f10a77bbSDavid C Somayajulu q80_stat_desc_t *sdesc; 2318f10a77bbSDavid C Somayajulu int i, j; 2319f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 2320f10a77bbSDavid C Somayajulu device_t dev; 2321f10a77bbSDavid C Somayajulu uint32_t err; 2322f10a77bbSDavid C Somayajulu uint32_t rcntxt_sds_rings; 2323f10a77bbSDavid C Somayajulu uint32_t rcntxt_rds_rings; 232435291c22SDavid C Somayajulu uint32_t max_idx; 2325f10a77bbSDavid C Somayajulu 2326f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 2327f10a77bbSDavid C Somayajulu 2328f10a77bbSDavid C Somayajulu /* 2329f10a77bbSDavid C Somayajulu * Create Receive Context 2330f10a77bbSDavid C Somayajulu */ 2331f10a77bbSDavid C Somayajulu 2332f10a77bbSDavid C Somayajulu for (i = 0; i < hw->num_sds_rings; i++) { 2333f10a77bbSDavid C Somayajulu sdesc = (q80_stat_desc_t *)&hw->sds[i].sds_ring_base[0]; 2334f10a77bbSDavid C Somayajulu 2335f10a77bbSDavid C Somayajulu for (j = 0; j < NUM_STATUS_DESCRIPTORS; j++) { 2336f10a77bbSDavid C Somayajulu sdesc->data[0] = 1ULL; 2337f10a77bbSDavid C Somayajulu sdesc->data[1] = 1ULL; 2338f10a77bbSDavid C Somayajulu } 2339f10a77bbSDavid C Somayajulu } 2340f10a77bbSDavid C Somayajulu 2341f10a77bbSDavid C Somayajulu rcntxt_sds_rings = hw->num_sds_rings; 2342f10a77bbSDavid C Somayajulu if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) 2343f10a77bbSDavid C Somayajulu rcntxt_sds_rings = MAX_RCNTXT_SDS_RINGS; 2344f10a77bbSDavid C Somayajulu 2345f10a77bbSDavid C Somayajulu rcntxt_rds_rings = hw->num_rds_rings; 2346f10a77bbSDavid C Somayajulu 2347f10a77bbSDavid C Somayajulu if (hw->num_rds_rings > MAX_RDS_RING_SETS) 2348f10a77bbSDavid C Somayajulu rcntxt_rds_rings = MAX_RDS_RING_SETS; 2349f10a77bbSDavid C Somayajulu 2350f10a77bbSDavid C Somayajulu rcntxt = (q80_rq_rcv_cntxt_t *)ha->hw.mbox; 2351f10a77bbSDavid C Somayajulu bzero(rcntxt, (sizeof (q80_rq_rcv_cntxt_t))); 2352f10a77bbSDavid C Somayajulu 2353f10a77bbSDavid C Somayajulu rcntxt->opcode = Q8_MBX_CREATE_RX_CNTXT; 2354f10a77bbSDavid C Somayajulu rcntxt->count_version = (sizeof (q80_rq_rcv_cntxt_t) >> 2); 2355f10a77bbSDavid C Somayajulu rcntxt->count_version |= Q8_MBX_CMD_VERSION; 2356f10a77bbSDavid C Somayajulu 2357f10a77bbSDavid C Somayajulu rcntxt->cap0 = Q8_RCV_CNTXT_CAP0_BASEFW | 2358f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_LRO | 2359f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_HW_LRO | 2360f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_RSS | 2361f10a77bbSDavid C Somayajulu Q8_RCV_CNTXT_CAP0_SGL_LRO; 2362f10a77bbSDavid C Somayajulu 236335291c22SDavid C Somayajulu if (ha->hw.enable_9kb) 236435291c22SDavid C Somayajulu rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SINGLE_JUMBO; 236535291c22SDavid C Somayajulu else 236635291c22SDavid C Somayajulu rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_SGL_JUMBO; 236735291c22SDavid C Somayajulu 2368f10a77bbSDavid C Somayajulu if (ha->hw.num_rds_rings > 1) { 2369f10a77bbSDavid C Somayajulu rcntxt->nrds_sets_rings = rcntxt_rds_rings | (1 << 5); 2370f10a77bbSDavid C Somayajulu rcntxt->cap0 |= Q8_RCV_CNTXT_CAP0_MULTI_RDS; 2371f10a77bbSDavid C Somayajulu } else 2372f10a77bbSDavid C Somayajulu rcntxt->nrds_sets_rings = 0x1 | (1 << 5); 2373f10a77bbSDavid C Somayajulu 2374f10a77bbSDavid C Somayajulu rcntxt->nsds_rings = rcntxt_sds_rings; 2375f10a77bbSDavid C Somayajulu 2376f10a77bbSDavid C Somayajulu rcntxt->rds_producer_mode = Q8_RCV_CNTXT_RDS_PROD_MODE_UNIQUE; 2377f10a77bbSDavid C Somayajulu 2378f10a77bbSDavid C Somayajulu rcntxt->rcv_vpid = 0; 2379f10a77bbSDavid C Somayajulu 2380f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_sds_rings; i++) { 2381f10a77bbSDavid C Somayajulu rcntxt->sds[i].paddr = 2382f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.sds_ring[i].dma_addr); 2383f10a77bbSDavid C Somayajulu rcntxt->sds[i].size = 2384f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_STATUS_DESCRIPTORS); 2385f10a77bbSDavid C Somayajulu if (ha->msix_count == 2) { 2386f10a77bbSDavid C Somayajulu rcntxt->sds[i].intr_id = 2387f10a77bbSDavid C Somayajulu qla_host_to_le16(hw->intr_id[0]); 2388f10a77bbSDavid C Somayajulu rcntxt->sds[i].intr_src_bit = qla_host_to_le16((i)); 2389f10a77bbSDavid C Somayajulu } else { 2390f10a77bbSDavid C Somayajulu rcntxt->sds[i].intr_id = 2391f10a77bbSDavid C Somayajulu qla_host_to_le16(hw->intr_id[i]); 2392f10a77bbSDavid C Somayajulu rcntxt->sds[i].intr_src_bit = qla_host_to_le16(0); 2393f10a77bbSDavid C Somayajulu } 2394f10a77bbSDavid C Somayajulu } 2395f10a77bbSDavid C Somayajulu 2396f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_rds_rings; i++) { 2397f10a77bbSDavid C Somayajulu rcntxt->rds[i].paddr_std = 2398f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.rds_ring[i].dma_addr); 239935291c22SDavid C Somayajulu 240035291c22SDavid C Somayajulu if (ha->hw.enable_9kb) 240135291c22SDavid C Somayajulu rcntxt->rds[i].std_bsize = 240235291c22SDavid C Somayajulu qla_host_to_le64(MJUM9BYTES); 240335291c22SDavid C Somayajulu else 2404f10a77bbSDavid C Somayajulu rcntxt->rds[i].std_bsize = qla_host_to_le64(MCLBYTES); 240535291c22SDavid C Somayajulu 2406f10a77bbSDavid C Somayajulu rcntxt->rds[i].std_nentries = 2407f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_RX_DESCRIPTORS); 2408f10a77bbSDavid C Somayajulu } 2409f10a77bbSDavid C Somayajulu 2410f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)rcntxt, 2411f10a77bbSDavid C Somayajulu (sizeof (q80_rq_rcv_cntxt_t) >> 2), 2412f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rsp_rcv_cntxt_t) >> 2), 0)) { 2413f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 2414f10a77bbSDavid C Somayajulu return (-1); 2415f10a77bbSDavid C Somayajulu } 2416f10a77bbSDavid C Somayajulu 2417f10a77bbSDavid C Somayajulu rcntxt_rsp = (q80_rsp_rcv_cntxt_t *)ha->hw.mbox; 2418f10a77bbSDavid C Somayajulu 2419f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status); 2420f10a77bbSDavid C Somayajulu 2421f10a77bbSDavid C Somayajulu if (err) { 2422f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2423f10a77bbSDavid C Somayajulu return (-1); 2424f10a77bbSDavid C Somayajulu } 2425f10a77bbSDavid C Somayajulu 2426f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_sds_rings; i++) { 2427f10a77bbSDavid C Somayajulu hw->sds[i].sds_consumer = rcntxt_rsp->sds_cons[i]; 2428f10a77bbSDavid C Somayajulu } 2429f10a77bbSDavid C Somayajulu 2430f10a77bbSDavid C Somayajulu for (i = 0; i < rcntxt_rds_rings; i++) { 2431f10a77bbSDavid C Somayajulu hw->rds[i].prod_std = rcntxt_rsp->rds[i].prod_std; 2432f10a77bbSDavid C Somayajulu } 2433f10a77bbSDavid C Somayajulu 2434f10a77bbSDavid C Somayajulu hw->rcv_cntxt_id = rcntxt_rsp->cntxt_id; 2435f10a77bbSDavid C Somayajulu 2436f10a77bbSDavid C Somayajulu ha->hw.flags.init_rx_cnxt = 1; 2437f10a77bbSDavid C Somayajulu 2438f10a77bbSDavid C Somayajulu if (hw->num_sds_rings > MAX_RCNTXT_SDS_RINGS) { 243935291c22SDavid C Somayajulu 244035291c22SDavid C Somayajulu for (i = MAX_RCNTXT_SDS_RINGS; i < hw->num_sds_rings;) { 244135291c22SDavid C Somayajulu 244235291c22SDavid C Somayajulu if ((i + MAX_RCNTXT_SDS_RINGS) < hw->num_sds_rings) 244335291c22SDavid C Somayajulu max_idx = MAX_RCNTXT_SDS_RINGS; 244435291c22SDavid C Somayajulu else 244535291c22SDavid C Somayajulu max_idx = hw->num_sds_rings - i; 244635291c22SDavid C Somayajulu 244735291c22SDavid C Somayajulu err = qla_add_rcv_rings(ha, i, max_idx); 2448f10a77bbSDavid C Somayajulu if (err) 2449f10a77bbSDavid C Somayajulu return -1; 245035291c22SDavid C Somayajulu 245135291c22SDavid C Somayajulu i += max_idx; 245235291c22SDavid C Somayajulu } 2453f10a77bbSDavid C Somayajulu } 2454f10a77bbSDavid C Somayajulu 2455f10a77bbSDavid C Somayajulu if (hw->num_rds_rings > 1) { 245635291c22SDavid C Somayajulu 245735291c22SDavid C Somayajulu for (i = 0; i < hw->num_rds_rings; ) { 245835291c22SDavid C Somayajulu 245935291c22SDavid C Somayajulu if ((i + MAX_SDS_TO_RDS_MAP) < hw->num_rds_rings) 246035291c22SDavid C Somayajulu max_idx = MAX_SDS_TO_RDS_MAP; 246135291c22SDavid C Somayajulu else 246235291c22SDavid C Somayajulu max_idx = hw->num_rds_rings - i; 246335291c22SDavid C Somayajulu 246435291c22SDavid C Somayajulu err = qla_map_sds_to_rds(ha, i, max_idx); 2465f10a77bbSDavid C Somayajulu if (err) 2466f10a77bbSDavid C Somayajulu return -1; 246735291c22SDavid C Somayajulu 246835291c22SDavid C Somayajulu i += max_idx; 246935291c22SDavid C Somayajulu } 2470f10a77bbSDavid C Somayajulu } 2471f10a77bbSDavid C Somayajulu 2472f10a77bbSDavid C Somayajulu return (0); 2473f10a77bbSDavid C Somayajulu } 2474f10a77bbSDavid C Somayajulu 2475f10a77bbSDavid C Somayajulu static int 247635291c22SDavid C Somayajulu qla_add_rcv_rings(qla_host_t *ha, uint32_t sds_idx, uint32_t nsds) 2477f10a77bbSDavid C Somayajulu { 2478f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 2479f10a77bbSDavid C Somayajulu q80_rq_add_rcv_rings_t *add_rcv; 2480f10a77bbSDavid C Somayajulu q80_rsp_add_rcv_rings_t *add_rcv_rsp; 2481f10a77bbSDavid C Somayajulu uint32_t i,j, err; 2482f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 2483f10a77bbSDavid C Somayajulu 2484f10a77bbSDavid C Somayajulu add_rcv = (q80_rq_add_rcv_rings_t *)ha->hw.mbox; 2485f10a77bbSDavid C Somayajulu bzero(add_rcv, sizeof (q80_rq_add_rcv_rings_t)); 2486f10a77bbSDavid C Somayajulu 2487f10a77bbSDavid C Somayajulu add_rcv->opcode = Q8_MBX_ADD_RX_RINGS; 2488f10a77bbSDavid C Somayajulu add_rcv->count_version = (sizeof (q80_rq_add_rcv_rings_t) >> 2); 2489f10a77bbSDavid C Somayajulu add_rcv->count_version |= Q8_MBX_CMD_VERSION; 2490f10a77bbSDavid C Somayajulu 2491f10a77bbSDavid C Somayajulu add_rcv->nrds_sets_rings = nsds | (1 << 5); 2492f10a77bbSDavid C Somayajulu add_rcv->nsds_rings = nsds; 2493f10a77bbSDavid C Somayajulu add_rcv->cntxt_id = hw->rcv_cntxt_id; 2494f10a77bbSDavid C Somayajulu 2495f10a77bbSDavid C Somayajulu for (i = 0; i < nsds; i++) { 2496f10a77bbSDavid C Somayajulu 2497f10a77bbSDavid C Somayajulu j = i + sds_idx; 2498f10a77bbSDavid C Somayajulu 2499f10a77bbSDavid C Somayajulu add_rcv->sds[i].paddr = 2500f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.sds_ring[j].dma_addr); 2501f10a77bbSDavid C Somayajulu 2502f10a77bbSDavid C Somayajulu add_rcv->sds[i].size = 2503f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_STATUS_DESCRIPTORS); 2504f10a77bbSDavid C Somayajulu 2505f10a77bbSDavid C Somayajulu if (ha->msix_count == 2) { 2506f10a77bbSDavid C Somayajulu add_rcv->sds[i].intr_id = 2507f10a77bbSDavid C Somayajulu qla_host_to_le16(hw->intr_id[0]); 2508f10a77bbSDavid C Somayajulu add_rcv->sds[i].intr_src_bit = qla_host_to_le16(j); 2509f10a77bbSDavid C Somayajulu } else { 2510f10a77bbSDavid C Somayajulu add_rcv->sds[i].intr_id = 2511f10a77bbSDavid C Somayajulu qla_host_to_le16(hw->intr_id[j]); 2512f10a77bbSDavid C Somayajulu add_rcv->sds[i].intr_src_bit = qla_host_to_le16(0); 2513f10a77bbSDavid C Somayajulu } 2514f10a77bbSDavid C Somayajulu 2515f10a77bbSDavid C Somayajulu } 251635291c22SDavid C Somayajulu for (i = 0; (i < nsds); i++) { 2517f10a77bbSDavid C Somayajulu j = i + sds_idx; 251835291c22SDavid C Somayajulu 2519f10a77bbSDavid C Somayajulu add_rcv->rds[i].paddr_std = 2520f10a77bbSDavid C Somayajulu qla_host_to_le64(hw->dma_buf.rds_ring[j].dma_addr); 252135291c22SDavid C Somayajulu 252235291c22SDavid C Somayajulu if (ha->hw.enable_9kb) 252335291c22SDavid C Somayajulu add_rcv->rds[i].std_bsize = 252435291c22SDavid C Somayajulu qla_host_to_le64(MJUM9BYTES); 252535291c22SDavid C Somayajulu else 2526f10a77bbSDavid C Somayajulu add_rcv->rds[i].std_bsize = qla_host_to_le64(MCLBYTES); 252735291c22SDavid C Somayajulu 2528f10a77bbSDavid C Somayajulu add_rcv->rds[i].std_nentries = 2529f10a77bbSDavid C Somayajulu qla_host_to_le32(NUM_RX_DESCRIPTORS); 2530f10a77bbSDavid C Somayajulu } 2531f10a77bbSDavid C Somayajulu 2532f10a77bbSDavid C Somayajulu 2533f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)add_rcv, 2534f10a77bbSDavid C Somayajulu (sizeof (q80_rq_add_rcv_rings_t) >> 2), 2535f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rsp_add_rcv_rings_t) >> 2), 0)) { 2536f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 2537f10a77bbSDavid C Somayajulu return (-1); 2538f10a77bbSDavid C Somayajulu } 2539f10a77bbSDavid C Somayajulu 2540f10a77bbSDavid C Somayajulu add_rcv_rsp = (q80_rsp_add_rcv_rings_t *)ha->hw.mbox; 2541f10a77bbSDavid C Somayajulu 2542f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(add_rcv_rsp->regcnt_status); 2543f10a77bbSDavid C Somayajulu 2544f10a77bbSDavid C Somayajulu if (err) { 2545f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2546f10a77bbSDavid C Somayajulu return (-1); 2547f10a77bbSDavid C Somayajulu } 2548f10a77bbSDavid C Somayajulu 254935291c22SDavid C Somayajulu for (i = 0; i < nsds; i++) { 255035291c22SDavid C Somayajulu hw->sds[(i + sds_idx)].sds_consumer = add_rcv_rsp->sds_cons[i]; 2551f10a77bbSDavid C Somayajulu } 255235291c22SDavid C Somayajulu 255335291c22SDavid C Somayajulu for (i = 0; i < nsds; i++) { 255435291c22SDavid C Somayajulu hw->rds[(i + sds_idx)].prod_std = add_rcv_rsp->rds[i].prod_std; 2555f10a77bbSDavid C Somayajulu } 255635291c22SDavid C Somayajulu 2557f10a77bbSDavid C Somayajulu return (0); 2558f10a77bbSDavid C Somayajulu } 2559f10a77bbSDavid C Somayajulu 2560f10a77bbSDavid C Somayajulu /* 2561f10a77bbSDavid C Somayajulu * Name: qla_del_rcv_cntxt 2562f10a77bbSDavid C Somayajulu * Function: Destroys the Receive Context. 2563f10a77bbSDavid C Somayajulu */ 2564f10a77bbSDavid C Somayajulu static void 2565f10a77bbSDavid C Somayajulu qla_del_rcv_cntxt(qla_host_t *ha) 2566f10a77bbSDavid C Somayajulu { 2567f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 2568f10a77bbSDavid C Somayajulu q80_rcv_cntxt_destroy_t *rcntxt; 2569f10a77bbSDavid C Somayajulu q80_rcv_cntxt_destroy_rsp_t *rcntxt_rsp; 2570f10a77bbSDavid C Somayajulu uint32_t err; 2571f10a77bbSDavid C Somayajulu uint8_t bcast_mac[6]; 2572f10a77bbSDavid C Somayajulu 2573f10a77bbSDavid C Somayajulu if (!ha->hw.flags.init_rx_cnxt) 2574f10a77bbSDavid C Somayajulu return; 2575f10a77bbSDavid C Somayajulu 2576f10a77bbSDavid C Somayajulu if (qla_hw_del_all_mcast(ha)) 2577f10a77bbSDavid C Somayajulu return; 2578f10a77bbSDavid C Somayajulu 2579f10a77bbSDavid C Somayajulu if (ha->hw.flags.bcast_mac) { 2580f10a77bbSDavid C Somayajulu 2581f10a77bbSDavid C Somayajulu bcast_mac[0] = 0xFF; bcast_mac[1] = 0xFF; bcast_mac[2] = 0xFF; 2582f10a77bbSDavid C Somayajulu bcast_mac[3] = 0xFF; bcast_mac[4] = 0xFF; bcast_mac[5] = 0xFF; 2583f10a77bbSDavid C Somayajulu 2584f10a77bbSDavid C Somayajulu if (qla_config_mac_addr(ha, bcast_mac, 0)) 2585f10a77bbSDavid C Somayajulu return; 2586f10a77bbSDavid C Somayajulu ha->hw.flags.bcast_mac = 0; 2587f10a77bbSDavid C Somayajulu 2588f10a77bbSDavid C Somayajulu } 2589f10a77bbSDavid C Somayajulu 2590f10a77bbSDavid C Somayajulu if (ha->hw.flags.unicast_mac) { 2591f10a77bbSDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mac_addr, 0)) 2592f10a77bbSDavid C Somayajulu return; 2593f10a77bbSDavid C Somayajulu ha->hw.flags.unicast_mac = 0; 2594f10a77bbSDavid C Somayajulu } 2595f10a77bbSDavid C Somayajulu 2596f10a77bbSDavid C Somayajulu rcntxt = (q80_rcv_cntxt_destroy_t *)ha->hw.mbox; 2597f10a77bbSDavid C Somayajulu bzero(rcntxt, (sizeof (q80_rcv_cntxt_destroy_t))); 2598f10a77bbSDavid C Somayajulu 2599f10a77bbSDavid C Somayajulu rcntxt->opcode = Q8_MBX_DESTROY_RX_CNTXT; 2600f10a77bbSDavid C Somayajulu rcntxt->count_version = (sizeof (q80_rcv_cntxt_destroy_t) >> 2); 2601f10a77bbSDavid C Somayajulu rcntxt->count_version |= Q8_MBX_CMD_VERSION; 2602f10a77bbSDavid C Somayajulu 2603f10a77bbSDavid C Somayajulu rcntxt->cntxt_id = ha->hw.rcv_cntxt_id; 2604f10a77bbSDavid C Somayajulu 2605f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)rcntxt, 2606f10a77bbSDavid C Somayajulu (sizeof (q80_rcv_cntxt_destroy_t) >> 2), 2607f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof(q80_rcv_cntxt_destroy_rsp_t) >> 2), 0)) { 2608f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 2609f10a77bbSDavid C Somayajulu return; 2610f10a77bbSDavid C Somayajulu } 2611f10a77bbSDavid C Somayajulu rcntxt_rsp = (q80_rcv_cntxt_destroy_rsp_t *)ha->hw.mbox; 2612f10a77bbSDavid C Somayajulu 2613f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(rcntxt_rsp->regcnt_status); 2614f10a77bbSDavid C Somayajulu 2615f10a77bbSDavid C Somayajulu if (err) { 2616f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2617f10a77bbSDavid C Somayajulu } 2618f10a77bbSDavid C Somayajulu 2619f10a77bbSDavid C Somayajulu ha->hw.flags.init_rx_cnxt = 0; 2620f10a77bbSDavid C Somayajulu return; 2621f10a77bbSDavid C Somayajulu } 2622f10a77bbSDavid C Somayajulu 2623f10a77bbSDavid C Somayajulu /* 2624f10a77bbSDavid C Somayajulu * Name: qla_init_xmt_cntxt 2625f10a77bbSDavid C Somayajulu * Function: Creates the Transmit Context. 2626f10a77bbSDavid C Somayajulu */ 2627f10a77bbSDavid C Somayajulu static int 2628f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx) 2629f10a77bbSDavid C Somayajulu { 2630f10a77bbSDavid C Somayajulu device_t dev; 2631f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 2632f10a77bbSDavid C Somayajulu q80_rq_tx_cntxt_t *tcntxt; 2633f10a77bbSDavid C Somayajulu q80_rsp_tx_cntxt_t *tcntxt_rsp; 2634f10a77bbSDavid C Somayajulu uint32_t err; 2635f10a77bbSDavid C Somayajulu qla_hw_tx_cntxt_t *hw_tx_cntxt; 2636f10a77bbSDavid C Somayajulu 2637f10a77bbSDavid C Somayajulu hw_tx_cntxt = &hw->tx_cntxt[txr_idx]; 2638f10a77bbSDavid C Somayajulu 2639f10a77bbSDavid C Somayajulu dev = ha->pci_dev; 2640f10a77bbSDavid C Somayajulu 2641f10a77bbSDavid C Somayajulu /* 2642f10a77bbSDavid C Somayajulu * Create Transmit Context 2643f10a77bbSDavid C Somayajulu */ 2644f10a77bbSDavid C Somayajulu tcntxt = (q80_rq_tx_cntxt_t *)ha->hw.mbox; 2645f10a77bbSDavid C Somayajulu bzero(tcntxt, (sizeof (q80_rq_tx_cntxt_t))); 2646f10a77bbSDavid C Somayajulu 2647f10a77bbSDavid C Somayajulu tcntxt->opcode = Q8_MBX_CREATE_TX_CNTXT; 2648f10a77bbSDavid C Somayajulu tcntxt->count_version = (sizeof (q80_rq_tx_cntxt_t) >> 2); 2649f10a77bbSDavid C Somayajulu tcntxt->count_version |= Q8_MBX_CMD_VERSION; 2650f10a77bbSDavid C Somayajulu 265135291c22SDavid C Somayajulu #ifdef QL_ENABLE_ISCSI_TLV 265235291c22SDavid C Somayajulu 265335291c22SDavid C Somayajulu tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO | 265435291c22SDavid C Somayajulu Q8_TX_CNTXT_CAP0_TC; 265535291c22SDavid C Somayajulu 265635291c22SDavid C Somayajulu if (txr_idx >= (ha->hw.num_tx_rings >> 1)) { 265735291c22SDavid C Somayajulu tcntxt->traffic_class = 1; 265835291c22SDavid C Somayajulu } 265935291c22SDavid C Somayajulu 266035291c22SDavid C Somayajulu #else 266135291c22SDavid C Somayajulu 2662f10a77bbSDavid C Somayajulu tcntxt->cap0 = Q8_TX_CNTXT_CAP0_BASEFW | Q8_TX_CNTXT_CAP0_LSO; 2663f10a77bbSDavid C Somayajulu 266435291c22SDavid C Somayajulu #endif /* #ifdef QL_ENABLE_ISCSI_TLV */ 266535291c22SDavid C Somayajulu 2666f10a77bbSDavid C Somayajulu tcntxt->ntx_rings = 1; 2667f10a77bbSDavid C Somayajulu 2668f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].paddr = 2669f10a77bbSDavid C Somayajulu qla_host_to_le64(hw_tx_cntxt->tx_ring_paddr); 2670f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].tx_consumer = 2671f10a77bbSDavid C Somayajulu qla_host_to_le64(hw_tx_cntxt->tx_cons_paddr); 2672f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].nentries = qla_host_to_le16(NUM_TX_DESCRIPTORS); 2673f10a77bbSDavid C Somayajulu 2674f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].intr_id = qla_host_to_le16(hw->intr_id[0]); 2675f10a77bbSDavid C Somayajulu tcntxt->tx_ring[0].intr_src_bit = qla_host_to_le16(0); 2676f10a77bbSDavid C Somayajulu 2677f10a77bbSDavid C Somayajulu 2678f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_free = NUM_TX_DESCRIPTORS; 2679f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_next = hw_tx_cntxt->txr_comp = 0; 2680f10a77bbSDavid C Somayajulu 2681f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)tcntxt, 2682f10a77bbSDavid C Somayajulu (sizeof (q80_rq_tx_cntxt_t) >> 2), 2683f10a77bbSDavid C Somayajulu ha->hw.mbox, 2684f10a77bbSDavid C Somayajulu (sizeof(q80_rsp_tx_cntxt_t) >> 2), 0)) { 2685f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 2686f10a77bbSDavid C Somayajulu return (-1); 2687f10a77bbSDavid C Somayajulu } 2688f10a77bbSDavid C Somayajulu tcntxt_rsp = (q80_rsp_tx_cntxt_t *)ha->hw.mbox; 2689f10a77bbSDavid C Somayajulu 2690f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status); 2691f10a77bbSDavid C Somayajulu 2692f10a77bbSDavid C Somayajulu if (err) { 2693f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2694f10a77bbSDavid C Somayajulu return -1; 2695f10a77bbSDavid C Somayajulu } 2696f10a77bbSDavid C Somayajulu 2697f10a77bbSDavid C Somayajulu hw_tx_cntxt->tx_prod_reg = tcntxt_rsp->tx_ring[0].prod_index; 2698f10a77bbSDavid C Somayajulu hw_tx_cntxt->tx_cntxt_id = tcntxt_rsp->tx_ring[0].cntxt_id; 2699f10a77bbSDavid C Somayajulu 270035291c22SDavid C Somayajulu if (qla_config_intr_coalesce(ha, hw_tx_cntxt->tx_cntxt_id, 0, 0)) 270135291c22SDavid C Somayajulu return (-1); 270235291c22SDavid C Somayajulu 2703f10a77bbSDavid C Somayajulu return (0); 2704f10a77bbSDavid C Somayajulu } 2705f10a77bbSDavid C Somayajulu 2706f10a77bbSDavid C Somayajulu 2707f10a77bbSDavid C Somayajulu /* 2708f10a77bbSDavid C Somayajulu * Name: qla_del_xmt_cntxt 2709f10a77bbSDavid C Somayajulu * Function: Destroys the Transmit Context. 2710f10a77bbSDavid C Somayajulu */ 2711f10a77bbSDavid C Somayajulu static int 2712f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt_i(qla_host_t *ha, uint32_t txr_idx) 2713f10a77bbSDavid C Somayajulu { 2714f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 2715f10a77bbSDavid C Somayajulu q80_tx_cntxt_destroy_t *tcntxt; 2716f10a77bbSDavid C Somayajulu q80_tx_cntxt_destroy_rsp_t *tcntxt_rsp; 2717f10a77bbSDavid C Somayajulu uint32_t err; 2718f10a77bbSDavid C Somayajulu 2719f10a77bbSDavid C Somayajulu tcntxt = (q80_tx_cntxt_destroy_t *)ha->hw.mbox; 2720f10a77bbSDavid C Somayajulu bzero(tcntxt, (sizeof (q80_tx_cntxt_destroy_t))); 2721f10a77bbSDavid C Somayajulu 2722f10a77bbSDavid C Somayajulu tcntxt->opcode = Q8_MBX_DESTROY_TX_CNTXT; 2723f10a77bbSDavid C Somayajulu tcntxt->count_version = (sizeof (q80_tx_cntxt_destroy_t) >> 2); 2724f10a77bbSDavid C Somayajulu tcntxt->count_version |= Q8_MBX_CMD_VERSION; 2725f10a77bbSDavid C Somayajulu 2726f10a77bbSDavid C Somayajulu tcntxt->cntxt_id = ha->hw.tx_cntxt[txr_idx].tx_cntxt_id; 2727f10a77bbSDavid C Somayajulu 2728f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)tcntxt, 2729f10a77bbSDavid C Somayajulu (sizeof (q80_tx_cntxt_destroy_t) >> 2), 2730f10a77bbSDavid C Somayajulu ha->hw.mbox, (sizeof (q80_tx_cntxt_destroy_rsp_t) >> 2), 0)) { 2731f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed0\n", __func__); 2732f10a77bbSDavid C Somayajulu return (-1); 2733f10a77bbSDavid C Somayajulu } 2734f10a77bbSDavid C Somayajulu tcntxt_rsp = (q80_tx_cntxt_destroy_rsp_t *)ha->hw.mbox; 2735f10a77bbSDavid C Somayajulu 2736f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(tcntxt_rsp->regcnt_status); 2737f10a77bbSDavid C Somayajulu 2738f10a77bbSDavid C Somayajulu if (err) { 2739f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed1 [0x%08x]\n", __func__, err); 2740f10a77bbSDavid C Somayajulu return (-1); 2741f10a77bbSDavid C Somayajulu } 2742f10a77bbSDavid C Somayajulu 2743f10a77bbSDavid C Somayajulu return (0); 2744f10a77bbSDavid C Somayajulu } 2745f10a77bbSDavid C Somayajulu static void 2746f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt(qla_host_t *ha) 2747f10a77bbSDavid C Somayajulu { 2748f10a77bbSDavid C Somayajulu uint32_t i; 2749f10a77bbSDavid C Somayajulu 2750f10a77bbSDavid C Somayajulu if (!ha->hw.flags.init_tx_cnxt) 2751f10a77bbSDavid C Somayajulu return; 2752f10a77bbSDavid C Somayajulu 2753f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 2754f10a77bbSDavid C Somayajulu if (qla_del_xmt_cntxt_i(ha, i)) 2755f10a77bbSDavid C Somayajulu break; 2756f10a77bbSDavid C Somayajulu } 2757f10a77bbSDavid C Somayajulu ha->hw.flags.init_tx_cnxt = 0; 2758f10a77bbSDavid C Somayajulu } 2759f10a77bbSDavid C Somayajulu 2760f10a77bbSDavid C Somayajulu static int 2761f10a77bbSDavid C Somayajulu qla_init_xmt_cntxt(qla_host_t *ha) 2762f10a77bbSDavid C Somayajulu { 2763f10a77bbSDavid C Somayajulu uint32_t i, j; 2764f10a77bbSDavid C Somayajulu 2765f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 2766f10a77bbSDavid C Somayajulu if (qla_init_xmt_cntxt_i(ha, i) != 0) { 2767f10a77bbSDavid C Somayajulu for (j = 0; j < i; j++) 2768f10a77bbSDavid C Somayajulu qla_del_xmt_cntxt_i(ha, j); 2769f10a77bbSDavid C Somayajulu return (-1); 2770f10a77bbSDavid C Somayajulu } 2771f10a77bbSDavid C Somayajulu } 2772f10a77bbSDavid C Somayajulu ha->hw.flags.init_tx_cnxt = 1; 2773f10a77bbSDavid C Somayajulu return (0); 2774f10a77bbSDavid C Somayajulu } 2775f10a77bbSDavid C Somayajulu 2776f10a77bbSDavid C Somayajulu static int 2777f10a77bbSDavid C Somayajulu qla_hw_add_all_mcast(qla_host_t *ha) 2778f10a77bbSDavid C Somayajulu { 2779f10a77bbSDavid C Somayajulu int i, nmcast; 2780f10a77bbSDavid C Somayajulu 2781f10a77bbSDavid C Somayajulu nmcast = ha->hw.nmcast; 2782f10a77bbSDavid C Somayajulu 2783f10a77bbSDavid C Somayajulu for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) { 2784f10a77bbSDavid C Somayajulu if ((ha->hw.mcast[i].addr[0] != 0) || 2785f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[1] != 0) || 2786f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[2] != 0) || 2787f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[3] != 0) || 2788f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[4] != 0) || 2789f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[5] != 0)) { 2790f10a77bbSDavid C Somayajulu 2791f10a77bbSDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 1)) { 2792f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed\n", 2793f10a77bbSDavid C Somayajulu __func__); 2794f10a77bbSDavid C Somayajulu return (-1); 2795f10a77bbSDavid C Somayajulu } 2796f10a77bbSDavid C Somayajulu 2797f10a77bbSDavid C Somayajulu nmcast--; 2798f10a77bbSDavid C Somayajulu } 2799f10a77bbSDavid C Somayajulu } 2800f10a77bbSDavid C Somayajulu return 0; 2801f10a77bbSDavid C Somayajulu } 2802f10a77bbSDavid C Somayajulu 2803f10a77bbSDavid C Somayajulu static int 2804f10a77bbSDavid C Somayajulu qla_hw_del_all_mcast(qla_host_t *ha) 2805f10a77bbSDavid C Somayajulu { 2806f10a77bbSDavid C Somayajulu int i, nmcast; 2807f10a77bbSDavid C Somayajulu 2808f10a77bbSDavid C Somayajulu nmcast = ha->hw.nmcast; 2809f10a77bbSDavid C Somayajulu 2810f10a77bbSDavid C Somayajulu for (i = 0 ; ((i < Q8_MAX_NUM_MULTICAST_ADDRS) && nmcast); i++) { 2811f10a77bbSDavid C Somayajulu if ((ha->hw.mcast[i].addr[0] != 0) || 2812f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[1] != 0) || 2813f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[2] != 0) || 2814f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[3] != 0) || 2815f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[4] != 0) || 2816f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[5] != 0)) { 2817f10a77bbSDavid C Somayajulu 2818f10a77bbSDavid C Somayajulu if (qla_config_mac_addr(ha, ha->hw.mcast[i].addr, 0)) 2819f10a77bbSDavid C Somayajulu return (-1); 2820f10a77bbSDavid C Somayajulu 2821f10a77bbSDavid C Somayajulu nmcast--; 2822f10a77bbSDavid C Somayajulu } 2823f10a77bbSDavid C Somayajulu } 2824f10a77bbSDavid C Somayajulu return 0; 2825f10a77bbSDavid C Somayajulu } 2826f10a77bbSDavid C Somayajulu 2827f10a77bbSDavid C Somayajulu static int 2828f10a77bbSDavid C Somayajulu qla_hw_add_mcast(qla_host_t *ha, uint8_t *mta) 2829f10a77bbSDavid C Somayajulu { 2830f10a77bbSDavid C Somayajulu int i; 2831f10a77bbSDavid C Somayajulu 2832f10a77bbSDavid C Somayajulu for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) { 2833f10a77bbSDavid C Somayajulu 2834f10a77bbSDavid C Somayajulu if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) 2835f10a77bbSDavid C Somayajulu return 0; /* its been already added */ 2836f10a77bbSDavid C Somayajulu } 2837f10a77bbSDavid C Somayajulu 2838f10a77bbSDavid C Somayajulu for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) { 2839f10a77bbSDavid C Somayajulu 2840f10a77bbSDavid C Somayajulu if ((ha->hw.mcast[i].addr[0] == 0) && 2841f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[1] == 0) && 2842f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[2] == 0) && 2843f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[3] == 0) && 2844f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[4] == 0) && 2845f10a77bbSDavid C Somayajulu (ha->hw.mcast[i].addr[5] == 0)) { 2846f10a77bbSDavid C Somayajulu 2847f10a77bbSDavid C Somayajulu if (qla_config_mac_addr(ha, mta, 1)) 2848f10a77bbSDavid C Somayajulu return (-1); 2849f10a77bbSDavid C Somayajulu 2850f10a77bbSDavid C Somayajulu bcopy(mta, ha->hw.mcast[i].addr, Q8_MAC_ADDR_LEN); 2851f10a77bbSDavid C Somayajulu ha->hw.nmcast++; 2852f10a77bbSDavid C Somayajulu 2853f10a77bbSDavid C Somayajulu return 0; 2854f10a77bbSDavid C Somayajulu } 2855f10a77bbSDavid C Somayajulu } 2856f10a77bbSDavid C Somayajulu return 0; 2857f10a77bbSDavid C Somayajulu } 2858f10a77bbSDavid C Somayajulu 2859f10a77bbSDavid C Somayajulu static int 2860f10a77bbSDavid C Somayajulu qla_hw_del_mcast(qla_host_t *ha, uint8_t *mta) 2861f10a77bbSDavid C Somayajulu { 2862f10a77bbSDavid C Somayajulu int i; 2863f10a77bbSDavid C Somayajulu 2864f10a77bbSDavid C Somayajulu for (i = 0; i < Q8_MAX_NUM_MULTICAST_ADDRS; i++) { 2865f10a77bbSDavid C Somayajulu if (QL_MAC_CMP(ha->hw.mcast[i].addr, mta) == 0) { 2866f10a77bbSDavid C Somayajulu 2867f10a77bbSDavid C Somayajulu if (qla_config_mac_addr(ha, mta, 0)) 2868f10a77bbSDavid C Somayajulu return (-1); 2869f10a77bbSDavid C Somayajulu 2870f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[0] = 0; 2871f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[1] = 0; 2872f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[2] = 0; 2873f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[3] = 0; 2874f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[4] = 0; 2875f10a77bbSDavid C Somayajulu ha->hw.mcast[i].addr[5] = 0; 2876f10a77bbSDavid C Somayajulu 2877f10a77bbSDavid C Somayajulu ha->hw.nmcast--; 2878f10a77bbSDavid C Somayajulu 2879f10a77bbSDavid C Somayajulu return 0; 2880f10a77bbSDavid C Somayajulu } 2881f10a77bbSDavid C Somayajulu } 2882f10a77bbSDavid C Somayajulu return 0; 2883f10a77bbSDavid C Somayajulu } 2884f10a77bbSDavid C Somayajulu 2885f10a77bbSDavid C Somayajulu /* 2886f10a77bbSDavid C Somayajulu * Name: ql_hw_set_multi 2887f10a77bbSDavid C Somayajulu * Function: Sets the Multicast Addresses provided the host O.S into the 2888f10a77bbSDavid C Somayajulu * hardware (for the given interface) 2889f10a77bbSDavid C Somayajulu */ 2890f10a77bbSDavid C Somayajulu int 2891f10a77bbSDavid C Somayajulu ql_hw_set_multi(qla_host_t *ha, uint8_t *mcast, uint32_t mcnt, 2892f10a77bbSDavid C Somayajulu uint32_t add_mac) 2893f10a77bbSDavid C Somayajulu { 2894f10a77bbSDavid C Somayajulu int i; 2895f10a77bbSDavid C Somayajulu uint8_t *mta = mcast; 2896f10a77bbSDavid C Somayajulu int ret = 0; 2897f10a77bbSDavid C Somayajulu 2898f10a77bbSDavid C Somayajulu for (i = 0; i < mcnt; i++) { 2899f10a77bbSDavid C Somayajulu if (add_mac) { 2900f10a77bbSDavid C Somayajulu ret = qla_hw_add_mcast(ha, mta); 2901f10a77bbSDavid C Somayajulu if (ret) 2902f10a77bbSDavid C Somayajulu break; 2903f10a77bbSDavid C Somayajulu } else { 2904f10a77bbSDavid C Somayajulu ret = qla_hw_del_mcast(ha, mta); 2905f10a77bbSDavid C Somayajulu if (ret) 2906f10a77bbSDavid C Somayajulu break; 2907f10a77bbSDavid C Somayajulu } 2908f10a77bbSDavid C Somayajulu 2909f10a77bbSDavid C Somayajulu mta += Q8_MAC_ADDR_LEN; 2910f10a77bbSDavid C Somayajulu } 2911f10a77bbSDavid C Somayajulu return (ret); 2912f10a77bbSDavid C Somayajulu } 2913f10a77bbSDavid C Somayajulu 2914f10a77bbSDavid C Somayajulu /* 2915f10a77bbSDavid C Somayajulu * Name: qla_hw_tx_done_locked 2916f10a77bbSDavid C Somayajulu * Function: Handle Transmit Completions 2917f10a77bbSDavid C Somayajulu */ 2918f10a77bbSDavid C Somayajulu static void 2919f10a77bbSDavid C Somayajulu qla_hw_tx_done_locked(qla_host_t *ha, uint32_t txr_idx) 2920f10a77bbSDavid C Somayajulu { 2921f10a77bbSDavid C Somayajulu qla_tx_buf_t *txb; 2922f10a77bbSDavid C Somayajulu qla_hw_t *hw = &ha->hw; 2923f10a77bbSDavid C Somayajulu uint32_t comp_idx, comp_count = 0; 2924f10a77bbSDavid C Somayajulu qla_hw_tx_cntxt_t *hw_tx_cntxt; 2925f10a77bbSDavid C Somayajulu 2926f10a77bbSDavid C Somayajulu hw_tx_cntxt = &hw->tx_cntxt[txr_idx]; 2927f10a77bbSDavid C Somayajulu 2928f10a77bbSDavid C Somayajulu /* retrieve index of last entry in tx ring completed */ 2929f10a77bbSDavid C Somayajulu comp_idx = qla_le32_to_host(*(hw_tx_cntxt->tx_cons)); 2930f10a77bbSDavid C Somayajulu 2931f10a77bbSDavid C Somayajulu while (comp_idx != hw_tx_cntxt->txr_comp) { 2932f10a77bbSDavid C Somayajulu 2933f10a77bbSDavid C Somayajulu txb = &ha->tx_ring[txr_idx].tx_buf[hw_tx_cntxt->txr_comp]; 2934f10a77bbSDavid C Somayajulu 2935f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_comp++; 2936f10a77bbSDavid C Somayajulu if (hw_tx_cntxt->txr_comp == NUM_TX_DESCRIPTORS) 2937f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_comp = 0; 2938f10a77bbSDavid C Somayajulu 2939f10a77bbSDavid C Somayajulu comp_count++; 2940f10a77bbSDavid C Somayajulu 2941f10a77bbSDavid C Somayajulu if (txb->m_head) { 2942c8dfaf38SGleb Smirnoff if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1); 2943f10a77bbSDavid C Somayajulu 2944f10a77bbSDavid C Somayajulu bus_dmamap_sync(ha->tx_tag, txb->map, 2945f10a77bbSDavid C Somayajulu BUS_DMASYNC_POSTWRITE); 2946f10a77bbSDavid C Somayajulu bus_dmamap_unload(ha->tx_tag, txb->map); 2947f10a77bbSDavid C Somayajulu m_freem(txb->m_head); 2948f10a77bbSDavid C Somayajulu 2949f10a77bbSDavid C Somayajulu txb->m_head = NULL; 2950f10a77bbSDavid C Somayajulu } 2951f10a77bbSDavid C Somayajulu } 2952f10a77bbSDavid C Somayajulu 2953f10a77bbSDavid C Somayajulu hw_tx_cntxt->txr_free += comp_count; 2954f10a77bbSDavid C Somayajulu return; 2955f10a77bbSDavid C Somayajulu } 2956f10a77bbSDavid C Somayajulu 2957f10a77bbSDavid C Somayajulu /* 2958f10a77bbSDavid C Somayajulu * Name: ql_hw_tx_done 2959f10a77bbSDavid C Somayajulu * Function: Handle Transmit Completions 2960f10a77bbSDavid C Somayajulu */ 2961f10a77bbSDavid C Somayajulu void 2962f10a77bbSDavid C Somayajulu ql_hw_tx_done(qla_host_t *ha) 2963f10a77bbSDavid C Somayajulu { 2964f10a77bbSDavid C Somayajulu int i; 2965f10a77bbSDavid C Somayajulu uint32_t flag = 0; 2966f10a77bbSDavid C Somayajulu 2967f10a77bbSDavid C Somayajulu if (!mtx_trylock(&ha->tx_lock)) { 2968f10a77bbSDavid C Somayajulu QL_DPRINT8(ha, (ha->pci_dev, 2969f10a77bbSDavid C Somayajulu "%s: !mtx_trylock(&ha->tx_lock)\n", __func__)); 2970f10a77bbSDavid C Somayajulu return; 2971f10a77bbSDavid C Somayajulu } 2972f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 2973f10a77bbSDavid C Somayajulu qla_hw_tx_done_locked(ha, i); 2974f10a77bbSDavid C Somayajulu if (ha->hw.tx_cntxt[i].txr_free <= (NUM_TX_DESCRIPTORS >> 1)) 2975f10a77bbSDavid C Somayajulu flag = 1; 2976f10a77bbSDavid C Somayajulu } 2977f10a77bbSDavid C Somayajulu 2978f10a77bbSDavid C Somayajulu if (!flag) 2979f10a77bbSDavid C Somayajulu ha->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2980f10a77bbSDavid C Somayajulu 2981f10a77bbSDavid C Somayajulu QLA_TX_UNLOCK(ha); 2982f10a77bbSDavid C Somayajulu return; 2983f10a77bbSDavid C Somayajulu } 2984f10a77bbSDavid C Somayajulu 2985f10a77bbSDavid C Somayajulu void 2986f10a77bbSDavid C Somayajulu ql_update_link_state(qla_host_t *ha) 2987f10a77bbSDavid C Somayajulu { 2988f10a77bbSDavid C Somayajulu uint32_t link_state; 2989f10a77bbSDavid C Somayajulu uint32_t prev_link_state; 2990f10a77bbSDavid C Somayajulu 2991f10a77bbSDavid C Somayajulu if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) { 2992f10a77bbSDavid C Somayajulu ha->hw.link_up = 0; 2993f10a77bbSDavid C Somayajulu return; 2994f10a77bbSDavid C Somayajulu } 2995f10a77bbSDavid C Somayajulu link_state = READ_REG32(ha, Q8_LINK_STATE); 2996f10a77bbSDavid C Somayajulu 2997f10a77bbSDavid C Somayajulu prev_link_state = ha->hw.link_up; 2998f10a77bbSDavid C Somayajulu 2999f10a77bbSDavid C Somayajulu if (ha->pci_func == 0) 3000f10a77bbSDavid C Somayajulu ha->hw.link_up = (((link_state & 0xF) == 1)? 1 : 0); 3001f10a77bbSDavid C Somayajulu else 3002f10a77bbSDavid C Somayajulu ha->hw.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0); 3003f10a77bbSDavid C Somayajulu 3004f10a77bbSDavid C Somayajulu if (prev_link_state != ha->hw.link_up) { 3005f10a77bbSDavid C Somayajulu if (ha->hw.link_up) { 3006f10a77bbSDavid C Somayajulu if_link_state_change(ha->ifp, LINK_STATE_UP); 3007f10a77bbSDavid C Somayajulu } else { 3008f10a77bbSDavid C Somayajulu if_link_state_change(ha->ifp, LINK_STATE_DOWN); 3009f10a77bbSDavid C Somayajulu } 3010f10a77bbSDavid C Somayajulu } 3011f10a77bbSDavid C Somayajulu return; 3012f10a77bbSDavid C Somayajulu } 3013f10a77bbSDavid C Somayajulu 3014f10a77bbSDavid C Somayajulu void 3015f10a77bbSDavid C Somayajulu ql_hw_stop_rcv(qla_host_t *ha) 3016f10a77bbSDavid C Somayajulu { 3017f10a77bbSDavid C Somayajulu int i, done, count = 100; 3018f10a77bbSDavid C Somayajulu 301935291c22SDavid C Somayajulu while (count) { 3020f10a77bbSDavid C Somayajulu done = 1; 3021f10a77bbSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 3022f10a77bbSDavid C Somayajulu if (ha->hw.sds[i].rcv_active) 3023f10a77bbSDavid C Somayajulu done = 0; 3024f10a77bbSDavid C Somayajulu } 3025f10a77bbSDavid C Somayajulu if (done) 3026f10a77bbSDavid C Somayajulu break; 3027f10a77bbSDavid C Somayajulu else 3028f10a77bbSDavid C Somayajulu qla_mdelay(__func__, 10); 302935291c22SDavid C Somayajulu count--; 3030f10a77bbSDavid C Somayajulu } 3031f10a77bbSDavid C Somayajulu if (!count) 3032f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: Counter expired.\n", __func__); 3033f10a77bbSDavid C Somayajulu 3034f10a77bbSDavid C Somayajulu return; 3035f10a77bbSDavid C Somayajulu } 3036f10a77bbSDavid C Somayajulu 3037f10a77bbSDavid C Somayajulu int 3038f10a77bbSDavid C Somayajulu ql_hw_check_health(qla_host_t *ha) 3039f10a77bbSDavid C Somayajulu { 3040f10a77bbSDavid C Somayajulu uint32_t val; 3041f10a77bbSDavid C Somayajulu 3042f10a77bbSDavid C Somayajulu ha->hw.health_count++; 3043f10a77bbSDavid C Somayajulu 3044f10a77bbSDavid C Somayajulu if (ha->hw.health_count < 1000) 3045f10a77bbSDavid C Somayajulu return 0; 3046f10a77bbSDavid C Somayajulu 3047f10a77bbSDavid C Somayajulu ha->hw.health_count = 0; 3048f10a77bbSDavid C Somayajulu 3049f10a77bbSDavid C Somayajulu val = READ_REG32(ha, Q8_ASIC_TEMPERATURE); 3050f10a77bbSDavid C Somayajulu 3051f10a77bbSDavid C Somayajulu if (((val & 0xFFFF) == 2) || ((val & 0xFFFF) == 3) || 3052f10a77bbSDavid C Somayajulu (QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE))) { 3053f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: Temperature Alert [0x%08x]\n", 3054f10a77bbSDavid C Somayajulu __func__, val); 3055f10a77bbSDavid C Somayajulu return -1; 3056f10a77bbSDavid C Somayajulu } 3057f10a77bbSDavid C Somayajulu 3058f10a77bbSDavid C Somayajulu val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT); 3059f10a77bbSDavid C Somayajulu 3060f10a77bbSDavid C Somayajulu if ((val != ha->hw.hbeat_value) && 3061467dcb5aSDavid C Somayajulu (!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) { 3062f10a77bbSDavid C Somayajulu ha->hw.hbeat_value = val; 3063f10a77bbSDavid C Somayajulu return 0; 3064f10a77bbSDavid C Somayajulu } 3065f10a77bbSDavid C Somayajulu device_printf(ha->pci_dev, "%s: Heartbeat Failue [0x%08x]\n", 3066f10a77bbSDavid C Somayajulu __func__, val); 3067f10a77bbSDavid C Somayajulu 3068f10a77bbSDavid C Somayajulu return -1; 3069f10a77bbSDavid C Somayajulu } 3070f10a77bbSDavid C Somayajulu 3071f10a77bbSDavid C Somayajulu static int 307235291c22SDavid C Somayajulu qla_init_nic_func(qla_host_t *ha) 307335291c22SDavid C Somayajulu { 307435291c22SDavid C Somayajulu device_t dev; 307535291c22SDavid C Somayajulu q80_init_nic_func_t *init_nic; 307635291c22SDavid C Somayajulu q80_init_nic_func_rsp_t *init_nic_rsp; 307735291c22SDavid C Somayajulu uint32_t err; 307835291c22SDavid C Somayajulu 307935291c22SDavid C Somayajulu dev = ha->pci_dev; 308035291c22SDavid C Somayajulu 308135291c22SDavid C Somayajulu init_nic = (q80_init_nic_func_t *)ha->hw.mbox; 308235291c22SDavid C Somayajulu bzero(init_nic, sizeof(q80_init_nic_func_t)); 308335291c22SDavid C Somayajulu 308435291c22SDavid C Somayajulu init_nic->opcode = Q8_MBX_INIT_NIC_FUNC; 308535291c22SDavid C Somayajulu init_nic->count_version = (sizeof (q80_init_nic_func_t) >> 2); 308635291c22SDavid C Somayajulu init_nic->count_version |= Q8_MBX_CMD_VERSION; 308735291c22SDavid C Somayajulu 308835291c22SDavid C Somayajulu init_nic->options = Q8_INIT_NIC_REG_DCBX_CHNG_AEN; 308935291c22SDavid C Somayajulu init_nic->options |= Q8_INIT_NIC_REG_SFP_CHNG_AEN; 309035291c22SDavid C Somayajulu init_nic->options |= Q8_INIT_NIC_REG_IDC_AEN; 309135291c22SDavid C Somayajulu 309235291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, init_nic, sizeof (q80_init_nic_func_t)); 309335291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)init_nic, 309435291c22SDavid C Somayajulu (sizeof (q80_init_nic_func_t) >> 2), 309535291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_init_nic_func_rsp_t) >> 2), 0)) { 309635291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 309735291c22SDavid C Somayajulu return -1; 309835291c22SDavid C Somayajulu } 309935291c22SDavid C Somayajulu 310035291c22SDavid C Somayajulu init_nic_rsp = (q80_init_nic_func_rsp_t *)ha->hw.mbox; 310135291c22SDavid C Somayajulu // qla_dump_buf8(ha, __func__, init_nic_rsp, sizeof (q80_init_nic_func_rsp_t)); 310235291c22SDavid C Somayajulu 310335291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(init_nic_rsp->regcnt_status); 310435291c22SDavid C Somayajulu 310535291c22SDavid C Somayajulu if (err) { 310635291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 310735291c22SDavid C Somayajulu } 310835291c22SDavid C Somayajulu 310935291c22SDavid C Somayajulu return 0; 311035291c22SDavid C Somayajulu } 311135291c22SDavid C Somayajulu 311235291c22SDavid C Somayajulu static int 311335291c22SDavid C Somayajulu qla_stop_nic_func(qla_host_t *ha) 311435291c22SDavid C Somayajulu { 311535291c22SDavid C Somayajulu device_t dev; 311635291c22SDavid C Somayajulu q80_stop_nic_func_t *stop_nic; 311735291c22SDavid C Somayajulu q80_stop_nic_func_rsp_t *stop_nic_rsp; 311835291c22SDavid C Somayajulu uint32_t err; 311935291c22SDavid C Somayajulu 312035291c22SDavid C Somayajulu dev = ha->pci_dev; 312135291c22SDavid C Somayajulu 312235291c22SDavid C Somayajulu stop_nic = (q80_stop_nic_func_t *)ha->hw.mbox; 312335291c22SDavid C Somayajulu bzero(stop_nic, sizeof(q80_stop_nic_func_t)); 312435291c22SDavid C Somayajulu 312535291c22SDavid C Somayajulu stop_nic->opcode = Q8_MBX_STOP_NIC_FUNC; 312635291c22SDavid C Somayajulu stop_nic->count_version = (sizeof (q80_stop_nic_func_t) >> 2); 312735291c22SDavid C Somayajulu stop_nic->count_version |= Q8_MBX_CMD_VERSION; 312835291c22SDavid C Somayajulu 312935291c22SDavid C Somayajulu stop_nic->options = Q8_STOP_NIC_DEREG_DCBX_CHNG_AEN; 313035291c22SDavid C Somayajulu stop_nic->options |= Q8_STOP_NIC_DEREG_SFP_CHNG_AEN; 313135291c22SDavid C Somayajulu 313235291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic, sizeof (q80_stop_nic_func_t)); 313335291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)stop_nic, 313435291c22SDavid C Somayajulu (sizeof (q80_stop_nic_func_t) >> 2), 313535291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_stop_nic_func_rsp_t) >> 2), 0)) { 313635291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 313735291c22SDavid C Somayajulu return -1; 313835291c22SDavid C Somayajulu } 313935291c22SDavid C Somayajulu 314035291c22SDavid C Somayajulu stop_nic_rsp = (q80_stop_nic_func_rsp_t *)ha->hw.mbox; 314135291c22SDavid C Somayajulu //qla_dump_buf8(ha, __func__, stop_nic_rsp, sizeof (q80_stop_nic_func_rsp_ t)); 314235291c22SDavid C Somayajulu 314335291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(stop_nic_rsp->regcnt_status); 314435291c22SDavid C Somayajulu 314535291c22SDavid C Somayajulu if (err) { 314635291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 314735291c22SDavid C Somayajulu } 314835291c22SDavid C Somayajulu 314935291c22SDavid C Somayajulu return 0; 315035291c22SDavid C Somayajulu } 315135291c22SDavid C Somayajulu 315235291c22SDavid C Somayajulu static int 315335291c22SDavid C Somayajulu qla_query_fw_dcbx_caps(qla_host_t *ha) 315435291c22SDavid C Somayajulu { 315535291c22SDavid C Somayajulu device_t dev; 315635291c22SDavid C Somayajulu q80_query_fw_dcbx_caps_t *fw_dcbx; 315735291c22SDavid C Somayajulu q80_query_fw_dcbx_caps_rsp_t *fw_dcbx_rsp; 315835291c22SDavid C Somayajulu uint32_t err; 315935291c22SDavid C Somayajulu 316035291c22SDavid C Somayajulu dev = ha->pci_dev; 316135291c22SDavid C Somayajulu 316235291c22SDavid C Somayajulu fw_dcbx = (q80_query_fw_dcbx_caps_t *)ha->hw.mbox; 316335291c22SDavid C Somayajulu bzero(fw_dcbx, sizeof(q80_query_fw_dcbx_caps_t)); 316435291c22SDavid C Somayajulu 316535291c22SDavid C Somayajulu fw_dcbx->opcode = Q8_MBX_GET_FW_DCBX_CAPS; 316635291c22SDavid C Somayajulu fw_dcbx->count_version = (sizeof (q80_query_fw_dcbx_caps_t) >> 2); 316735291c22SDavid C Somayajulu fw_dcbx->count_version |= Q8_MBX_CMD_VERSION; 316835291c22SDavid C Somayajulu 316935291c22SDavid C Somayajulu ql_dump_buf8(ha, __func__, fw_dcbx, sizeof (q80_query_fw_dcbx_caps_t)); 317035291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)fw_dcbx, 317135291c22SDavid C Somayajulu (sizeof (q80_query_fw_dcbx_caps_t) >> 2), 317235291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_query_fw_dcbx_caps_rsp_t) >> 2), 0)) { 317335291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 317435291c22SDavid C Somayajulu return -1; 317535291c22SDavid C Somayajulu } 317635291c22SDavid C Somayajulu 317735291c22SDavid C Somayajulu fw_dcbx_rsp = (q80_query_fw_dcbx_caps_rsp_t *)ha->hw.mbox; 317835291c22SDavid C Somayajulu ql_dump_buf8(ha, __func__, fw_dcbx_rsp, 317935291c22SDavid C Somayajulu sizeof (q80_query_fw_dcbx_caps_rsp_t)); 318035291c22SDavid C Somayajulu 318135291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(fw_dcbx_rsp->regcnt_status); 318235291c22SDavid C Somayajulu 318335291c22SDavid C Somayajulu if (err) { 318435291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 318535291c22SDavid C Somayajulu } 318635291c22SDavid C Somayajulu 318735291c22SDavid C Somayajulu return 0; 318835291c22SDavid C Somayajulu } 318935291c22SDavid C Somayajulu 319035291c22SDavid C Somayajulu static int 319135291c22SDavid C Somayajulu qla_idc_ack(qla_host_t *ha, uint32_t aen_mb1, uint32_t aen_mb2, 319235291c22SDavid C Somayajulu uint32_t aen_mb3, uint32_t aen_mb4) 319335291c22SDavid C Somayajulu { 319435291c22SDavid C Somayajulu device_t dev; 319535291c22SDavid C Somayajulu q80_idc_ack_t *idc_ack; 319635291c22SDavid C Somayajulu q80_idc_ack_rsp_t *idc_ack_rsp; 319735291c22SDavid C Somayajulu uint32_t err; 319835291c22SDavid C Somayajulu int count = 300; 319935291c22SDavid C Somayajulu 320035291c22SDavid C Somayajulu dev = ha->pci_dev; 320135291c22SDavid C Somayajulu 320235291c22SDavid C Somayajulu idc_ack = (q80_idc_ack_t *)ha->hw.mbox; 320335291c22SDavid C Somayajulu bzero(idc_ack, sizeof(q80_idc_ack_t)); 320435291c22SDavid C Somayajulu 320535291c22SDavid C Somayajulu idc_ack->opcode = Q8_MBX_IDC_ACK; 320635291c22SDavid C Somayajulu idc_ack->count_version = (sizeof (q80_idc_ack_t) >> 2); 320735291c22SDavid C Somayajulu idc_ack->count_version |= Q8_MBX_CMD_VERSION; 320835291c22SDavid C Somayajulu 320935291c22SDavid C Somayajulu idc_ack->aen_mb1 = aen_mb1; 321035291c22SDavid C Somayajulu idc_ack->aen_mb2 = aen_mb2; 321135291c22SDavid C Somayajulu idc_ack->aen_mb3 = aen_mb3; 321235291c22SDavid C Somayajulu idc_ack->aen_mb4 = aen_mb4; 321335291c22SDavid C Somayajulu 321435291c22SDavid C Somayajulu ha->hw.imd_compl= 0; 321535291c22SDavid C Somayajulu 321635291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)idc_ack, 321735291c22SDavid C Somayajulu (sizeof (q80_idc_ack_t) >> 2), 321835291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_idc_ack_rsp_t) >> 2), 0)) { 321935291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 322035291c22SDavid C Somayajulu return -1; 322135291c22SDavid C Somayajulu } 322235291c22SDavid C Somayajulu 322335291c22SDavid C Somayajulu idc_ack_rsp = (q80_idc_ack_rsp_t *)ha->hw.mbox; 322435291c22SDavid C Somayajulu 322535291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(idc_ack_rsp->regcnt_status); 322635291c22SDavid C Somayajulu 322735291c22SDavid C Somayajulu if (err) { 322835291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 322935291c22SDavid C Somayajulu return(-1); 323035291c22SDavid C Somayajulu } 323135291c22SDavid C Somayajulu 323235291c22SDavid C Somayajulu while (count && !ha->hw.imd_compl) { 323335291c22SDavid C Somayajulu qla_mdelay(__func__, 100); 323435291c22SDavid C Somayajulu count--; 323535291c22SDavid C Somayajulu } 323635291c22SDavid C Somayajulu 323735291c22SDavid C Somayajulu if (!count) 323835291c22SDavid C Somayajulu return -1; 323935291c22SDavid C Somayajulu else 324035291c22SDavid C Somayajulu device_printf(dev, "%s: count %d\n", __func__, count); 324135291c22SDavid C Somayajulu 324235291c22SDavid C Somayajulu return (0); 324335291c22SDavid C Somayajulu } 324435291c22SDavid C Somayajulu 324535291c22SDavid C Somayajulu static int 324635291c22SDavid C Somayajulu qla_set_port_config(qla_host_t *ha, uint32_t cfg_bits) 324735291c22SDavid C Somayajulu { 324835291c22SDavid C Somayajulu device_t dev; 324935291c22SDavid C Somayajulu q80_set_port_cfg_t *pcfg; 325035291c22SDavid C Somayajulu q80_set_port_cfg_rsp_t *pfg_rsp; 325135291c22SDavid C Somayajulu uint32_t err; 325235291c22SDavid C Somayajulu int count = 300; 325335291c22SDavid C Somayajulu 325435291c22SDavid C Somayajulu dev = ha->pci_dev; 325535291c22SDavid C Somayajulu 325635291c22SDavid C Somayajulu pcfg = (q80_set_port_cfg_t *)ha->hw.mbox; 325735291c22SDavid C Somayajulu bzero(pcfg, sizeof(q80_set_port_cfg_t)); 325835291c22SDavid C Somayajulu 325935291c22SDavid C Somayajulu pcfg->opcode = Q8_MBX_SET_PORT_CONFIG; 326035291c22SDavid C Somayajulu pcfg->count_version = (sizeof (q80_set_port_cfg_t) >> 2); 326135291c22SDavid C Somayajulu pcfg->count_version |= Q8_MBX_CMD_VERSION; 326235291c22SDavid C Somayajulu 326335291c22SDavid C Somayajulu pcfg->cfg_bits = cfg_bits; 326435291c22SDavid C Somayajulu 326535291c22SDavid C Somayajulu device_printf(dev, "%s: cfg_bits" 326635291c22SDavid C Somayajulu " [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]" 326735291c22SDavid C Somayajulu " [0x%x, 0x%x, 0x%x]\n", __func__, 326835291c22SDavid C Somayajulu ((cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20), 326935291c22SDavid C Somayajulu ((cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5), 327035291c22SDavid C Somayajulu ((cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0)); 327135291c22SDavid C Somayajulu 327235291c22SDavid C Somayajulu ha->hw.imd_compl= 0; 327335291c22SDavid C Somayajulu 327435291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)pcfg, 327535291c22SDavid C Somayajulu (sizeof (q80_set_port_cfg_t) >> 2), 327635291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_set_port_cfg_rsp_t) >> 2), 0)) { 327735291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 327835291c22SDavid C Somayajulu return -1; 327935291c22SDavid C Somayajulu } 328035291c22SDavid C Somayajulu 328135291c22SDavid C Somayajulu pfg_rsp = (q80_set_port_cfg_rsp_t *)ha->hw.mbox; 328235291c22SDavid C Somayajulu 328335291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(pfg_rsp->regcnt_status); 328435291c22SDavid C Somayajulu 328535291c22SDavid C Somayajulu if (err == Q8_MBX_RSP_IDC_INTRMD_RSP) { 328635291c22SDavid C Somayajulu while (count && !ha->hw.imd_compl) { 328735291c22SDavid C Somayajulu qla_mdelay(__func__, 100); 328835291c22SDavid C Somayajulu count--; 328935291c22SDavid C Somayajulu } 329035291c22SDavid C Somayajulu if (count) { 329135291c22SDavid C Somayajulu device_printf(dev, "%s: count %d\n", __func__, count); 329235291c22SDavid C Somayajulu 329335291c22SDavid C Somayajulu err = 0; 329435291c22SDavid C Somayajulu } 329535291c22SDavid C Somayajulu } 329635291c22SDavid C Somayajulu 329735291c22SDavid C Somayajulu if (err) { 329835291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 329935291c22SDavid C Somayajulu return(-1); 330035291c22SDavid C Somayajulu } 330135291c22SDavid C Somayajulu 330235291c22SDavid C Somayajulu return (0); 330335291c22SDavid C Somayajulu } 330435291c22SDavid C Somayajulu 330535291c22SDavid C Somayajulu 330635291c22SDavid C Somayajulu static int 3307f10a77bbSDavid C Somayajulu qla_get_minidump_tmplt_size(qla_host_t *ha, uint32_t *size) 3308f10a77bbSDavid C Somayajulu { 3309f10a77bbSDavid C Somayajulu uint32_t err; 3310f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 3311f10a77bbSDavid C Somayajulu q80_config_md_templ_size_t *md_size; 3312f10a77bbSDavid C Somayajulu q80_config_md_templ_size_rsp_t *md_size_rsp; 3313f10a77bbSDavid C Somayajulu 331435291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW 331535291c22SDavid C Somayajulu 331635291c22SDavid C Somayajulu *size = ql83xx_minidump_len; 331735291c22SDavid C Somayajulu return (0); 331835291c22SDavid C Somayajulu 331935291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */ 332035291c22SDavid C Somayajulu 3321f10a77bbSDavid C Somayajulu md_size = (q80_config_md_templ_size_t *) ha->hw.mbox; 3322f10a77bbSDavid C Somayajulu bzero(md_size, sizeof(q80_config_md_templ_size_t)); 3323f10a77bbSDavid C Somayajulu 3324f10a77bbSDavid C Somayajulu md_size->opcode = Q8_MBX_GET_MINIDUMP_TMPLT_SIZE; 3325f10a77bbSDavid C Somayajulu md_size->count_version = (sizeof (q80_config_md_templ_size_t) >> 2); 3326f10a77bbSDavid C Somayajulu md_size->count_version |= Q8_MBX_CMD_VERSION; 3327f10a77bbSDavid C Somayajulu 3328f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *) md_size, 3329f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_size_t) >> 2), ha->hw.mbox, 3330f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_size_rsp_t) >> 2), 0)) { 3331f10a77bbSDavid C Somayajulu 3332f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 3333f10a77bbSDavid C Somayajulu 3334f10a77bbSDavid C Somayajulu return (-1); 3335f10a77bbSDavid C Somayajulu } 3336f10a77bbSDavid C Somayajulu 3337f10a77bbSDavid C Somayajulu md_size_rsp = (q80_config_md_templ_size_rsp_t *) ha->hw.mbox; 3338f10a77bbSDavid C Somayajulu 3339f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(md_size_rsp->regcnt_status); 3340f10a77bbSDavid C Somayajulu 3341f10a77bbSDavid C Somayajulu if (err) { 3342f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 3343f10a77bbSDavid C Somayajulu return(-1); 3344f10a77bbSDavid C Somayajulu } 3345f10a77bbSDavid C Somayajulu 3346f10a77bbSDavid C Somayajulu *size = md_size_rsp->templ_size; 3347f10a77bbSDavid C Somayajulu 3348f10a77bbSDavid C Somayajulu return (0); 3349f10a77bbSDavid C Somayajulu } 3350f10a77bbSDavid C Somayajulu 3351f10a77bbSDavid C Somayajulu static int 335235291c22SDavid C Somayajulu qla_get_port_config(qla_host_t *ha, uint32_t *cfg_bits) 335335291c22SDavid C Somayajulu { 335435291c22SDavid C Somayajulu device_t dev; 335535291c22SDavid C Somayajulu q80_get_port_cfg_t *pcfg; 335635291c22SDavid C Somayajulu q80_get_port_cfg_rsp_t *pcfg_rsp; 335735291c22SDavid C Somayajulu uint32_t err; 335835291c22SDavid C Somayajulu 335935291c22SDavid C Somayajulu dev = ha->pci_dev; 336035291c22SDavid C Somayajulu 336135291c22SDavid C Somayajulu pcfg = (q80_get_port_cfg_t *)ha->hw.mbox; 336235291c22SDavid C Somayajulu bzero(pcfg, sizeof(q80_get_port_cfg_t)); 336335291c22SDavid C Somayajulu 336435291c22SDavid C Somayajulu pcfg->opcode = Q8_MBX_GET_PORT_CONFIG; 336535291c22SDavid C Somayajulu pcfg->count_version = (sizeof (q80_get_port_cfg_t) >> 2); 336635291c22SDavid C Somayajulu pcfg->count_version |= Q8_MBX_CMD_VERSION; 336735291c22SDavid C Somayajulu 336835291c22SDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *)pcfg, 336935291c22SDavid C Somayajulu (sizeof (q80_get_port_cfg_t) >> 2), 337035291c22SDavid C Somayajulu ha->hw.mbox, (sizeof (q80_get_port_cfg_rsp_t) >> 2), 0)) { 337135291c22SDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 337235291c22SDavid C Somayajulu return -1; 337335291c22SDavid C Somayajulu } 337435291c22SDavid C Somayajulu 337535291c22SDavid C Somayajulu pcfg_rsp = (q80_get_port_cfg_rsp_t *)ha->hw.mbox; 337635291c22SDavid C Somayajulu 337735291c22SDavid C Somayajulu err = Q8_MBX_RSP_STATUS(pcfg_rsp->regcnt_status); 337835291c22SDavid C Somayajulu 337935291c22SDavid C Somayajulu if (err) { 338035291c22SDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 338135291c22SDavid C Somayajulu return(-1); 338235291c22SDavid C Somayajulu } 338335291c22SDavid C Somayajulu 338435291c22SDavid C Somayajulu device_printf(dev, "%s: [cfg_bits, port type]" 338535291c22SDavid C Somayajulu " [0x%08x, 0x%02x] [STD_PAUSE_DIR, PAUSE_TYPE, DCBX]" 338635291c22SDavid C Somayajulu " [0x%x, 0x%x, 0x%x]\n", __func__, 338735291c22SDavid C Somayajulu pcfg_rsp->cfg_bits, pcfg_rsp->phys_port_type, 338835291c22SDavid C Somayajulu ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_STDPAUSE_DIR_MASK)>>20), 338935291c22SDavid C Somayajulu ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_PAUSE_CFG_MASK) >> 5), 339035291c22SDavid C Somayajulu ((pcfg_rsp->cfg_bits & Q8_PORT_CFG_BITS_DCBX_ENABLE) ? 1: 0) 339135291c22SDavid C Somayajulu ); 339235291c22SDavid C Somayajulu 339335291c22SDavid C Somayajulu *cfg_bits = pcfg_rsp->cfg_bits; 339435291c22SDavid C Somayajulu 339535291c22SDavid C Somayajulu return (0); 339635291c22SDavid C Somayajulu } 339735291c22SDavid C Somayajulu 339835291c22SDavid C Somayajulu int 339935291c22SDavid C Somayajulu qla_iscsi_pdu(qla_host_t *ha, struct mbuf *mp) 340035291c22SDavid C Somayajulu { 340135291c22SDavid C Somayajulu struct ether_vlan_header *eh; 340235291c22SDavid C Somayajulu uint16_t etype; 340335291c22SDavid C Somayajulu struct ip *ip = NULL; 340435291c22SDavid C Somayajulu struct ip6_hdr *ip6 = NULL; 340535291c22SDavid C Somayajulu struct tcphdr *th = NULL; 340635291c22SDavid C Somayajulu uint32_t hdrlen; 340735291c22SDavid C Somayajulu uint32_t offset; 340835291c22SDavid C Somayajulu uint8_t buf[sizeof(struct ip6_hdr)]; 340935291c22SDavid C Somayajulu 341035291c22SDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *); 341135291c22SDavid C Somayajulu 341235291c22SDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 341335291c22SDavid C Somayajulu hdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 341435291c22SDavid C Somayajulu etype = ntohs(eh->evl_proto); 341535291c22SDavid C Somayajulu } else { 341635291c22SDavid C Somayajulu hdrlen = ETHER_HDR_LEN; 341735291c22SDavid C Somayajulu etype = ntohs(eh->evl_encap_proto); 341835291c22SDavid C Somayajulu } 341935291c22SDavid C Somayajulu 342035291c22SDavid C Somayajulu if (etype == ETHERTYPE_IP) { 342135291c22SDavid C Somayajulu 342235291c22SDavid C Somayajulu offset = (hdrlen + sizeof (struct ip)); 342335291c22SDavid C Somayajulu 342435291c22SDavid C Somayajulu if (mp->m_len >= offset) { 342535291c22SDavid C Somayajulu ip = (struct ip *)(mp->m_data + hdrlen); 342635291c22SDavid C Somayajulu } else { 342735291c22SDavid C Somayajulu m_copydata(mp, hdrlen, sizeof (struct ip), buf); 342835291c22SDavid C Somayajulu ip = (struct ip *)buf; 342935291c22SDavid C Somayajulu } 343035291c22SDavid C Somayajulu 343135291c22SDavid C Somayajulu if (ip->ip_p == IPPROTO_TCP) { 343235291c22SDavid C Somayajulu 343335291c22SDavid C Somayajulu hdrlen += ip->ip_hl << 2; 343435291c22SDavid C Somayajulu offset = hdrlen + 4; 343535291c22SDavid C Somayajulu 343635291c22SDavid C Somayajulu if (mp->m_len >= offset) { 343774b8d63dSPedro F. Giffuni th = (struct tcphdr *)(mp->m_data + hdrlen); 343835291c22SDavid C Somayajulu } else { 343935291c22SDavid C Somayajulu m_copydata(mp, hdrlen, 4, buf); 344035291c22SDavid C Somayajulu th = (struct tcphdr *)buf; 344135291c22SDavid C Somayajulu } 344235291c22SDavid C Somayajulu } 344335291c22SDavid C Somayajulu 344435291c22SDavid C Somayajulu } else if (etype == ETHERTYPE_IPV6) { 344535291c22SDavid C Somayajulu 344635291c22SDavid C Somayajulu offset = (hdrlen + sizeof (struct ip6_hdr)); 344735291c22SDavid C Somayajulu 344835291c22SDavid C Somayajulu if (mp->m_len >= offset) { 344935291c22SDavid C Somayajulu ip6 = (struct ip6_hdr *)(mp->m_data + hdrlen); 345035291c22SDavid C Somayajulu } else { 345135291c22SDavid C Somayajulu m_copydata(mp, hdrlen, sizeof (struct ip6_hdr), buf); 345235291c22SDavid C Somayajulu ip6 = (struct ip6_hdr *)buf; 345335291c22SDavid C Somayajulu } 345435291c22SDavid C Somayajulu 345535291c22SDavid C Somayajulu if (ip6->ip6_nxt == IPPROTO_TCP) { 345635291c22SDavid C Somayajulu 345735291c22SDavid C Somayajulu hdrlen += sizeof(struct ip6_hdr); 345835291c22SDavid C Somayajulu offset = hdrlen + 4; 345935291c22SDavid C Somayajulu 346035291c22SDavid C Somayajulu if (mp->m_len >= offset) { 346174b8d63dSPedro F. Giffuni th = (struct tcphdr *)(mp->m_data + hdrlen); 346235291c22SDavid C Somayajulu } else { 346335291c22SDavid C Somayajulu m_copydata(mp, hdrlen, 4, buf); 346435291c22SDavid C Somayajulu th = (struct tcphdr *)buf; 346535291c22SDavid C Somayajulu } 346635291c22SDavid C Somayajulu } 346735291c22SDavid C Somayajulu } 346835291c22SDavid C Somayajulu 346935291c22SDavid C Somayajulu if (th != NULL) { 347035291c22SDavid C Somayajulu if ((th->th_sport == htons(3260)) || 347135291c22SDavid C Somayajulu (th->th_dport == htons(3260))) 347235291c22SDavid C Somayajulu return 0; 347335291c22SDavid C Somayajulu } 347435291c22SDavid C Somayajulu return (-1); 347535291c22SDavid C Somayajulu } 347635291c22SDavid C Somayajulu 347735291c22SDavid C Somayajulu void 347835291c22SDavid C Somayajulu qla_hw_async_event(qla_host_t *ha) 347935291c22SDavid C Somayajulu { 348035291c22SDavid C Somayajulu switch (ha->hw.aen_mb0) { 348135291c22SDavid C Somayajulu case 0x8101: 348235291c22SDavid C Somayajulu (void)qla_idc_ack(ha, ha->hw.aen_mb1, ha->hw.aen_mb2, 348335291c22SDavid C Somayajulu ha->hw.aen_mb3, ha->hw.aen_mb4); 348435291c22SDavid C Somayajulu 348535291c22SDavid C Somayajulu break; 348635291c22SDavid C Somayajulu 348735291c22SDavid C Somayajulu default: 348835291c22SDavid C Somayajulu break; 348935291c22SDavid C Somayajulu } 349035291c22SDavid C Somayajulu 349135291c22SDavid C Somayajulu return; 349235291c22SDavid C Somayajulu } 349335291c22SDavid C Somayajulu 349435291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW 349535291c22SDavid C Somayajulu static int 3496f10a77bbSDavid C Somayajulu qla_get_minidump_template(qla_host_t *ha) 3497f10a77bbSDavid C Somayajulu { 3498f10a77bbSDavid C Somayajulu uint32_t err; 3499f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 3500f10a77bbSDavid C Somayajulu q80_config_md_templ_cmd_t *md_templ; 3501f10a77bbSDavid C Somayajulu q80_config_md_templ_cmd_rsp_t *md_templ_rsp; 3502f10a77bbSDavid C Somayajulu 3503f10a77bbSDavid C Somayajulu md_templ = (q80_config_md_templ_cmd_t *) ha->hw.mbox; 3504f10a77bbSDavid C Somayajulu bzero(md_templ, (sizeof (q80_config_md_templ_cmd_t))); 3505f10a77bbSDavid C Somayajulu 3506f10a77bbSDavid C Somayajulu md_templ->opcode = Q8_MBX_GET_MINIDUMP_TMPLT; 3507f10a77bbSDavid C Somayajulu md_templ->count_version = ( sizeof(q80_config_md_templ_cmd_t) >> 2); 3508f10a77bbSDavid C Somayajulu md_templ->count_version |= Q8_MBX_CMD_VERSION; 3509f10a77bbSDavid C Somayajulu 3510f10a77bbSDavid C Somayajulu md_templ->buf_addr = ha->hw.dma_buf.minidump.dma_addr; 3511f10a77bbSDavid C Somayajulu md_templ->buff_size = ha->hw.dma_buf.minidump.size; 3512f10a77bbSDavid C Somayajulu 3513f10a77bbSDavid C Somayajulu if (qla_mbx_cmd(ha, (uint32_t *) md_templ, 3514f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_cmd_t) >> 2), 3515f10a77bbSDavid C Somayajulu ha->hw.mbox, 3516f10a77bbSDavid C Somayajulu (sizeof(q80_config_md_templ_cmd_rsp_t) >> 2), 0)) { 3517f10a77bbSDavid C Somayajulu 3518f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed\n", __func__); 3519f10a77bbSDavid C Somayajulu 3520f10a77bbSDavid C Somayajulu return (-1); 3521f10a77bbSDavid C Somayajulu } 3522f10a77bbSDavid C Somayajulu 3523f10a77bbSDavid C Somayajulu md_templ_rsp = (q80_config_md_templ_cmd_rsp_t *) ha->hw.mbox; 3524f10a77bbSDavid C Somayajulu 3525f10a77bbSDavid C Somayajulu err = Q8_MBX_RSP_STATUS(md_templ_rsp->regcnt_status); 3526f10a77bbSDavid C Somayajulu 3527f10a77bbSDavid C Somayajulu if (err) { 3528f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [0x%08x]\n", __func__, err); 3529f10a77bbSDavid C Somayajulu return (-1); 3530f10a77bbSDavid C Somayajulu } 3531f10a77bbSDavid C Somayajulu 3532f10a77bbSDavid C Somayajulu return (0); 3533f10a77bbSDavid C Somayajulu 3534f10a77bbSDavid C Somayajulu } 353535291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */ 3536f10a77bbSDavid C Somayajulu 3537f10a77bbSDavid C Somayajulu static int 3538f10a77bbSDavid C Somayajulu qla_minidump_init(qla_host_t *ha) 3539f10a77bbSDavid C Somayajulu { 354035291c22SDavid C Somayajulu int ret = 0; 3541f10a77bbSDavid C Somayajulu uint32_t template_size = 0; 3542f10a77bbSDavid C Somayajulu device_t dev = ha->pci_dev; 3543f10a77bbSDavid C Somayajulu 3544f10a77bbSDavid C Somayajulu /* 3545f10a77bbSDavid C Somayajulu * Get Minidump Template Size 3546f10a77bbSDavid C Somayajulu */ 3547f10a77bbSDavid C Somayajulu ret = qla_get_minidump_tmplt_size(ha, &template_size); 3548f10a77bbSDavid C Somayajulu 3549f10a77bbSDavid C Somayajulu if (ret || (template_size == 0)) { 3550f10a77bbSDavid C Somayajulu device_printf(dev, "%s: failed [%d, %d]\n", __func__, ret, 3551f10a77bbSDavid C Somayajulu template_size); 3552f10a77bbSDavid C Somayajulu return (-1); 3553f10a77bbSDavid C Somayajulu } 3554f10a77bbSDavid C Somayajulu 3555f10a77bbSDavid C Somayajulu /* 3556f10a77bbSDavid C Somayajulu * Allocate Memory for Minidump Template 3557f10a77bbSDavid C Somayajulu */ 3558f10a77bbSDavid C Somayajulu 3559f10a77bbSDavid C Somayajulu ha->hw.dma_buf.minidump.alignment = 8; 3560f10a77bbSDavid C Somayajulu ha->hw.dma_buf.minidump.size = template_size; 3561f10a77bbSDavid C Somayajulu 356235291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW 3563f10a77bbSDavid C Somayajulu if (ql_alloc_dmabuf(ha, &ha->hw.dma_buf.minidump)) { 3564f10a77bbSDavid C Somayajulu 3565f10a77bbSDavid C Somayajulu device_printf(dev, "%s: minidump dma alloc failed\n", __func__); 3566f10a77bbSDavid C Somayajulu 3567f10a77bbSDavid C Somayajulu return (-1); 3568f10a77bbSDavid C Somayajulu } 3569f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.minidump = 1; 3570f10a77bbSDavid C Somayajulu 3571f10a77bbSDavid C Somayajulu /* 3572f10a77bbSDavid C Somayajulu * Retrieve Minidump Template 3573f10a77bbSDavid C Somayajulu */ 3574f10a77bbSDavid C Somayajulu ret = qla_get_minidump_template(ha); 357535291c22SDavid C Somayajulu #else 357635291c22SDavid C Somayajulu ha->hw.dma_buf.minidump.dma_b = ql83xx_minidump; 357735291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */ 3578f10a77bbSDavid C Somayajulu 3579f10a77bbSDavid C Somayajulu if (ret) { 3580f10a77bbSDavid C Somayajulu qla_minidump_free(ha); 3581f10a77bbSDavid C Somayajulu } else { 3582f10a77bbSDavid C Somayajulu ha->hw.mdump_init = 1; 3583f10a77bbSDavid C Somayajulu } 3584f10a77bbSDavid C Somayajulu 3585f10a77bbSDavid C Somayajulu return (ret); 3586f10a77bbSDavid C Somayajulu } 3587f10a77bbSDavid C Somayajulu 3588f10a77bbSDavid C Somayajulu 3589f10a77bbSDavid C Somayajulu static void 3590f10a77bbSDavid C Somayajulu qla_minidump_free(qla_host_t *ha) 3591f10a77bbSDavid C Somayajulu { 3592f10a77bbSDavid C Somayajulu ha->hw.mdump_init = 0; 3593f10a77bbSDavid C Somayajulu if (ha->hw.dma_buf.flags.minidump) { 3594f10a77bbSDavid C Somayajulu ha->hw.dma_buf.flags.minidump = 0; 3595f10a77bbSDavid C Somayajulu ql_free_dmabuf(ha, &ha->hw.dma_buf.minidump); 3596f10a77bbSDavid C Somayajulu } 3597f10a77bbSDavid C Somayajulu return; 3598f10a77bbSDavid C Somayajulu } 3599f10a77bbSDavid C Somayajulu 3600f10a77bbSDavid C Somayajulu void 3601f10a77bbSDavid C Somayajulu ql_minidump(qla_host_t *ha) 3602f10a77bbSDavid C Somayajulu { 3603f10a77bbSDavid C Somayajulu uint32_t delay = 6000; 3604f10a77bbSDavid C Somayajulu 3605f10a77bbSDavid C Somayajulu if (!ha->hw.mdump_init) 3606f10a77bbSDavid C Somayajulu return; 3607f10a77bbSDavid C Somayajulu 3608f10a77bbSDavid C Somayajulu if (!ha->hw.mdump_active) 3609f10a77bbSDavid C Somayajulu return; 3610f10a77bbSDavid C Somayajulu 3611f10a77bbSDavid C Somayajulu if (ha->hw.mdump_active == 1) { 3612f10a77bbSDavid C Somayajulu ha->hw.mdump_start_seq_index = ql_stop_sequence(ha); 3613f10a77bbSDavid C Somayajulu ha->hw.mdump_start = 1; 3614f10a77bbSDavid C Somayajulu } 3615f10a77bbSDavid C Somayajulu 3616f10a77bbSDavid C Somayajulu while (delay-- && ha->hw.mdump_active) { 3617f10a77bbSDavid C Somayajulu qla_mdelay(__func__, 100); 3618f10a77bbSDavid C Somayajulu } 3619f10a77bbSDavid C Somayajulu ha->hw.mdump_start = 0; 3620f10a77bbSDavid C Somayajulu ql_start_sequence(ha, ha->hw.mdump_start_seq_index); 3621f10a77bbSDavid C Somayajulu 3622f10a77bbSDavid C Somayajulu return; 3623f10a77bbSDavid C Somayajulu } 3624