1711bcba0SDavid C Somayajulu /* 2711bcba0SDavid C Somayajulu * Copyright (c) 2013-2014 Qlogic Corporation 3711bcba0SDavid C Somayajulu * All rights reserved. 4711bcba0SDavid C Somayajulu * 5711bcba0SDavid C Somayajulu * Redistribution and use in source and binary forms, with or without 6711bcba0SDavid C Somayajulu * modification, are permitted provided that the following conditions 7711bcba0SDavid C Somayajulu * are met: 8711bcba0SDavid C Somayajulu * 9711bcba0SDavid C Somayajulu * 1. Redistributions of source code must retain the above copyright 10711bcba0SDavid C Somayajulu * notice, this list of conditions and the following disclaimer. 11711bcba0SDavid C Somayajulu * 2. Redistributions in binary form must reproduce the above copyright 12711bcba0SDavid C Somayajulu * notice, this list of conditions and the following disclaimer in the 13711bcba0SDavid C Somayajulu * documentation and/or other materials provided with the distribution. 14711bcba0SDavid C Somayajulu * 15711bcba0SDavid C Somayajulu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16711bcba0SDavid C Somayajulu * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17711bcba0SDavid C Somayajulu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18711bcba0SDavid C Somayajulu * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19711bcba0SDavid C Somayajulu * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20711bcba0SDavid C Somayajulu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21711bcba0SDavid C Somayajulu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22711bcba0SDavid C Somayajulu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23711bcba0SDavid C Somayajulu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24711bcba0SDavid C Somayajulu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25711bcba0SDavid C Somayajulu * POSSIBILITY OF SUCH DAMAGE. 26711bcba0SDavid C Somayajulu */ 27711bcba0SDavid C Somayajulu 28711bcba0SDavid C Somayajulu /* 29711bcba0SDavid C Somayajulu * File: qls_isr.c 30711bcba0SDavid C Somayajulu * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656. 31711bcba0SDavid C Somayajulu */ 32711bcba0SDavid C Somayajulu #include <sys/cdefs.h> 33711bcba0SDavid C Somayajulu __FBSDID("$FreeBSD$"); 34711bcba0SDavid C Somayajulu 35711bcba0SDavid C Somayajulu 36711bcba0SDavid C Somayajulu 37711bcba0SDavid C Somayajulu #include "qls_os.h" 38711bcba0SDavid C Somayajulu #include "qls_hw.h" 39711bcba0SDavid C Somayajulu #include "qls_def.h" 40711bcba0SDavid C Somayajulu #include "qls_inline.h" 41711bcba0SDavid C Somayajulu #include "qls_ver.h" 42711bcba0SDavid C Somayajulu #include "qls_glbl.h" 43711bcba0SDavid C Somayajulu #include "qls_dbg.h" 44711bcba0SDavid C Somayajulu 45711bcba0SDavid C Somayajulu 46711bcba0SDavid C Somayajulu static void 47711bcba0SDavid C Somayajulu qls_tx_comp(qla_host_t *ha, uint32_t txr_idx, q81_tx_mac_comp_t *tx_comp) 48711bcba0SDavid C Somayajulu { 49711bcba0SDavid C Somayajulu qla_tx_buf_t *txb; 50711bcba0SDavid C Somayajulu uint32_t tx_idx = tx_comp->tid_lo; 51711bcba0SDavid C Somayajulu 52711bcba0SDavid C Somayajulu if (tx_idx >= NUM_TX_DESCRIPTORS) { 53711bcba0SDavid C Somayajulu ha->qla_initiate_recovery = 1; 54711bcba0SDavid C Somayajulu return; 55711bcba0SDavid C Somayajulu } 56711bcba0SDavid C Somayajulu 57711bcba0SDavid C Somayajulu txb = &ha->tx_ring[txr_idx].tx_buf[tx_idx]; 58711bcba0SDavid C Somayajulu 59711bcba0SDavid C Somayajulu if (txb->m_head) { 60*c8dfaf38SGleb Smirnoff if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1); 61711bcba0SDavid C Somayajulu bus_dmamap_sync(ha->tx_tag, txb->map, 62711bcba0SDavid C Somayajulu BUS_DMASYNC_POSTWRITE); 63711bcba0SDavid C Somayajulu bus_dmamap_unload(ha->tx_tag, txb->map); 64711bcba0SDavid C Somayajulu m_freem(txb->m_head); 65711bcba0SDavid C Somayajulu 66711bcba0SDavid C Somayajulu txb->m_head = NULL; 67711bcba0SDavid C Somayajulu } 68711bcba0SDavid C Somayajulu 69711bcba0SDavid C Somayajulu ha->tx_ring[txr_idx].txr_done++; 70711bcba0SDavid C Somayajulu 71711bcba0SDavid C Somayajulu if (ha->tx_ring[txr_idx].txr_done == NUM_TX_DESCRIPTORS) 72711bcba0SDavid C Somayajulu ha->tx_ring[txr_idx].txr_done = 0; 73711bcba0SDavid C Somayajulu } 74711bcba0SDavid C Somayajulu 75711bcba0SDavid C Somayajulu static void 76711bcba0SDavid C Somayajulu qls_replenish_rx(qla_host_t *ha, uint32_t r_idx) 77711bcba0SDavid C Somayajulu { 78711bcba0SDavid C Somayajulu qla_rx_buf_t *rxb; 79711bcba0SDavid C Somayajulu qla_rx_ring_t *rxr; 80711bcba0SDavid C Somayajulu int count; 81711bcba0SDavid C Somayajulu volatile q81_bq_addr_e_t *sbq_e; 82711bcba0SDavid C Somayajulu 83711bcba0SDavid C Somayajulu rxr = &ha->rx_ring[r_idx]; 84711bcba0SDavid C Somayajulu 85711bcba0SDavid C Somayajulu count = rxr->rx_free; 86711bcba0SDavid C Somayajulu sbq_e = rxr->sbq_vaddr; 87711bcba0SDavid C Somayajulu 88711bcba0SDavid C Somayajulu while (count--) { 89711bcba0SDavid C Somayajulu 90711bcba0SDavid C Somayajulu rxb = &rxr->rx_buf[rxr->sbq_next]; 91711bcba0SDavid C Somayajulu 92711bcba0SDavid C Somayajulu if (rxb->m_head == NULL) { 93711bcba0SDavid C Somayajulu if (qls_get_mbuf(ha, rxb, NULL) != 0) { 94711bcba0SDavid C Somayajulu device_printf(ha->pci_dev, 95711bcba0SDavid C Somayajulu "%s: qls_get_mbuf [0,%d,%d] failed\n", 96711bcba0SDavid C Somayajulu __func__, rxr->sbq_next, r_idx); 97711bcba0SDavid C Somayajulu rxb->m_head = NULL; 98711bcba0SDavid C Somayajulu break; 99711bcba0SDavid C Somayajulu } 100711bcba0SDavid C Somayajulu } 101711bcba0SDavid C Somayajulu 102711bcba0SDavid C Somayajulu if (rxb->m_head != NULL) { 103711bcba0SDavid C Somayajulu sbq_e[rxr->sbq_next].addr_lo = (uint32_t)rxb->paddr; 104711bcba0SDavid C Somayajulu sbq_e[rxr->sbq_next].addr_hi = 105711bcba0SDavid C Somayajulu (uint32_t)(rxb->paddr >> 32); 106711bcba0SDavid C Somayajulu 107711bcba0SDavid C Somayajulu rxr->sbq_next++; 108711bcba0SDavid C Somayajulu if (rxr->sbq_next == NUM_RX_DESCRIPTORS) 109711bcba0SDavid C Somayajulu rxr->sbq_next = 0; 110711bcba0SDavid C Somayajulu 111711bcba0SDavid C Somayajulu rxr->sbq_free++; 112711bcba0SDavid C Somayajulu rxr->rx_free--; 113711bcba0SDavid C Somayajulu } 114711bcba0SDavid C Somayajulu 115711bcba0SDavid C Somayajulu if (rxr->sbq_free == 16) { 116711bcba0SDavid C Somayajulu 117711bcba0SDavid C Somayajulu rxr->sbq_in += 16; 118711bcba0SDavid C Somayajulu rxr->sbq_in = rxr->sbq_in & (NUM_RX_DESCRIPTORS - 1); 119711bcba0SDavid C Somayajulu rxr->sbq_free = 0; 120711bcba0SDavid C Somayajulu 121711bcba0SDavid C Somayajulu Q81_WR_SBQ_PROD_IDX(r_idx, (rxr->sbq_in)); 122711bcba0SDavid C Somayajulu } 123711bcba0SDavid C Somayajulu } 124711bcba0SDavid C Somayajulu } 125711bcba0SDavid C Somayajulu 126711bcba0SDavid C Somayajulu static int 127711bcba0SDavid C Somayajulu qls_rx_comp(qla_host_t *ha, uint32_t rxr_idx, uint32_t cq_idx, q81_rx_t *cq_e) 128711bcba0SDavid C Somayajulu { 129711bcba0SDavid C Somayajulu qla_rx_buf_t *rxb; 130711bcba0SDavid C Somayajulu qla_rx_ring_t *rxr; 131711bcba0SDavid C Somayajulu device_t dev = ha->pci_dev; 132711bcba0SDavid C Somayajulu struct mbuf *mp = NULL; 133711bcba0SDavid C Somayajulu struct ifnet *ifp = ha->ifp; 134711bcba0SDavid C Somayajulu struct lro_ctrl *lro; 135711bcba0SDavid C Somayajulu struct ether_vlan_header *eh; 136711bcba0SDavid C Somayajulu 137711bcba0SDavid C Somayajulu rxr = &ha->rx_ring[rxr_idx]; 138711bcba0SDavid C Somayajulu 139711bcba0SDavid C Somayajulu lro = &rxr->lro; 140711bcba0SDavid C Somayajulu 141711bcba0SDavid C Somayajulu rxb = &rxr->rx_buf[rxr->rx_next]; 142711bcba0SDavid C Somayajulu 143711bcba0SDavid C Somayajulu if (!(cq_e->flags1 & Q81_RX_FLAGS1_DS)) { 144711bcba0SDavid C Somayajulu device_printf(dev, "%s: DS bit not set \n", __func__); 145711bcba0SDavid C Somayajulu return -1; 146711bcba0SDavid C Somayajulu } 147711bcba0SDavid C Somayajulu if (rxb->paddr != cq_e->b_paddr) { 148711bcba0SDavid C Somayajulu 149711bcba0SDavid C Somayajulu device_printf(dev, 150711bcba0SDavid C Somayajulu "%s: (rxb->paddr != cq_e->b_paddr)[%p, %p] \n", 151711bcba0SDavid C Somayajulu __func__, (void *)rxb->paddr, (void *)cq_e->b_paddr); 152711bcba0SDavid C Somayajulu 153711bcba0SDavid C Somayajulu Q81_SET_CQ_INVALID(cq_idx); 154711bcba0SDavid C Somayajulu 155711bcba0SDavid C Somayajulu ha->qla_initiate_recovery = 1; 156711bcba0SDavid C Somayajulu 157711bcba0SDavid C Somayajulu return(-1); 158711bcba0SDavid C Somayajulu } 159711bcba0SDavid C Somayajulu 160711bcba0SDavid C Somayajulu rxr->rx_int++; 161711bcba0SDavid C Somayajulu 162711bcba0SDavid C Somayajulu if ((cq_e->flags1 & Q81_RX_FLAGS1_ERR_MASK) == 0) { 163711bcba0SDavid C Somayajulu 164711bcba0SDavid C Somayajulu mp = rxb->m_head; 165711bcba0SDavid C Somayajulu rxb->m_head = NULL; 166711bcba0SDavid C Somayajulu 167711bcba0SDavid C Somayajulu if (mp == NULL) { 168711bcba0SDavid C Somayajulu device_printf(dev, "%s: mp == NULL\n", __func__); 169711bcba0SDavid C Somayajulu } else { 170711bcba0SDavid C Somayajulu mp->m_flags |= M_PKTHDR; 171711bcba0SDavid C Somayajulu mp->m_pkthdr.len = cq_e->length; 172711bcba0SDavid C Somayajulu mp->m_pkthdr.rcvif = ifp; 173711bcba0SDavid C Somayajulu mp->m_len = cq_e->length; 174711bcba0SDavid C Somayajulu 175711bcba0SDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *); 176711bcba0SDavid C Somayajulu 177711bcba0SDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 178711bcba0SDavid C Somayajulu uint32_t *data = (uint32_t *)eh; 179711bcba0SDavid C Somayajulu 180711bcba0SDavid C Somayajulu mp->m_pkthdr.ether_vtag = ntohs(eh->evl_tag); 181711bcba0SDavid C Somayajulu mp->m_flags |= M_VLANTAG; 182711bcba0SDavid C Somayajulu 183711bcba0SDavid C Somayajulu *(data + 3) = *(data + 2); 184711bcba0SDavid C Somayajulu *(data + 2) = *(data + 1); 185711bcba0SDavid C Somayajulu *(data + 1) = *data; 186711bcba0SDavid C Somayajulu 187711bcba0SDavid C Somayajulu m_adj(mp, ETHER_VLAN_ENCAP_LEN); 188711bcba0SDavid C Somayajulu } 189711bcba0SDavid C Somayajulu 190711bcba0SDavid C Somayajulu if ((cq_e->flags1 & Q81_RX_FLAGS1_RSS_MATCH_MASK)) { 191711bcba0SDavid C Somayajulu rxr->rss_int++; 192711bcba0SDavid C Somayajulu mp->m_pkthdr.flowid = cq_e->rss; 193711bcba0SDavid C Somayajulu mp->m_flags |= M_FLOWID; 194711bcba0SDavid C Somayajulu } 195711bcba0SDavid C Somayajulu if (cq_e->flags0 & (Q81_RX_FLAGS0_TE | 196711bcba0SDavid C Somayajulu Q81_RX_FLAGS0_NU | Q81_RX_FLAGS0_IE)) { 197711bcba0SDavid C Somayajulu mp->m_pkthdr.csum_flags = 0; 198711bcba0SDavid C Somayajulu } else { 199711bcba0SDavid C Somayajulu mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED | 200711bcba0SDavid C Somayajulu CSUM_IP_VALID | CSUM_DATA_VALID | 201711bcba0SDavid C Somayajulu CSUM_PSEUDO_HDR; 202711bcba0SDavid C Somayajulu mp->m_pkthdr.csum_data = 0xFFFF; 203711bcba0SDavid C Somayajulu } 204*c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 205711bcba0SDavid C Somayajulu 206711bcba0SDavid C Somayajulu if (lro->lro_cnt && (tcp_lro_rx(lro, mp, 0) == 0)) { 207711bcba0SDavid C Somayajulu /* LRO packet has been successfuly queued */ 208711bcba0SDavid C Somayajulu } else { 209711bcba0SDavid C Somayajulu (*ifp->if_input)(ifp, mp); 210711bcba0SDavid C Somayajulu } 211711bcba0SDavid C Somayajulu } 212711bcba0SDavid C Somayajulu } else { 213711bcba0SDavid C Somayajulu device_printf(dev, "%s: err [0%08x]\n", __func__, cq_e->flags1); 214711bcba0SDavid C Somayajulu } 215711bcba0SDavid C Somayajulu 216711bcba0SDavid C Somayajulu rxr->rx_free++; 217711bcba0SDavid C Somayajulu rxr->rx_next++; 218711bcba0SDavid C Somayajulu 219711bcba0SDavid C Somayajulu if (rxr->rx_next == NUM_RX_DESCRIPTORS) 220711bcba0SDavid C Somayajulu rxr->rx_next = 0; 221711bcba0SDavid C Somayajulu 222711bcba0SDavid C Somayajulu if ((rxr->rx_free + rxr->sbq_free) >= 16) 223711bcba0SDavid C Somayajulu qls_replenish_rx(ha, rxr_idx); 224711bcba0SDavid C Somayajulu 225711bcba0SDavid C Somayajulu return 0; 226711bcba0SDavid C Somayajulu } 227711bcba0SDavid C Somayajulu 228711bcba0SDavid C Somayajulu static void 229711bcba0SDavid C Somayajulu qls_cq_isr(qla_host_t *ha, uint32_t cq_idx) 230711bcba0SDavid C Somayajulu { 231711bcba0SDavid C Somayajulu q81_cq_e_t *cq_e, *cq_b; 232711bcba0SDavid C Somayajulu uint32_t i, cq_comp_idx; 233711bcba0SDavid C Somayajulu int ret = 0, tx_comp_done = 0; 234711bcba0SDavid C Somayajulu struct lro_ctrl *lro; 235711bcba0SDavid C Somayajulu struct lro_entry *queued; 236711bcba0SDavid C Somayajulu 237711bcba0SDavid C Somayajulu cq_b = ha->rx_ring[cq_idx].cq_base_vaddr; 238711bcba0SDavid C Somayajulu lro = &ha->rx_ring[cq_idx].lro; 239711bcba0SDavid C Somayajulu 240711bcba0SDavid C Somayajulu cq_comp_idx = *(ha->rx_ring[cq_idx].cqi_vaddr); 241711bcba0SDavid C Somayajulu 242711bcba0SDavid C Somayajulu i = ha->rx_ring[cq_idx].cq_next; 243711bcba0SDavid C Somayajulu 244711bcba0SDavid C Somayajulu while (i != cq_comp_idx) { 245711bcba0SDavid C Somayajulu 246711bcba0SDavid C Somayajulu cq_e = &cq_b[i]; 247711bcba0SDavid C Somayajulu 248711bcba0SDavid C Somayajulu switch (cq_e->opcode) { 249711bcba0SDavid C Somayajulu 250711bcba0SDavid C Somayajulu case Q81_IOCB_TX_MAC: 251711bcba0SDavid C Somayajulu case Q81_IOCB_TX_TSO: 252711bcba0SDavid C Somayajulu qls_tx_comp(ha, cq_idx, (q81_tx_mac_comp_t *)cq_e); 253711bcba0SDavid C Somayajulu tx_comp_done++; 254711bcba0SDavid C Somayajulu break; 255711bcba0SDavid C Somayajulu 256711bcba0SDavid C Somayajulu case Q81_IOCB_RX: 257711bcba0SDavid C Somayajulu ret = qls_rx_comp(ha, cq_idx, i, (q81_rx_t *)cq_e); 258711bcba0SDavid C Somayajulu 259711bcba0SDavid C Somayajulu break; 260711bcba0SDavid C Somayajulu 261711bcba0SDavid C Somayajulu case Q81_IOCB_MPI: 262711bcba0SDavid C Somayajulu case Q81_IOCB_SYS: 263711bcba0SDavid C Somayajulu default: 264711bcba0SDavid C Somayajulu device_printf(ha->pci_dev, "%s[%d %d 0x%x]: illegal \n", 265711bcba0SDavid C Somayajulu __func__, i, (*(ha->rx_ring[cq_idx].cqi_vaddr)), 266711bcba0SDavid C Somayajulu cq_e->opcode); 267711bcba0SDavid C Somayajulu qls_dump_buf32(ha, __func__, cq_e, 268711bcba0SDavid C Somayajulu (sizeof (q81_cq_e_t) >> 2)); 269711bcba0SDavid C Somayajulu break; 270711bcba0SDavid C Somayajulu } 271711bcba0SDavid C Somayajulu 272711bcba0SDavid C Somayajulu i++; 273711bcba0SDavid C Somayajulu if (i == NUM_CQ_ENTRIES) 274711bcba0SDavid C Somayajulu i = 0; 275711bcba0SDavid C Somayajulu 276711bcba0SDavid C Somayajulu if (ret) { 277711bcba0SDavid C Somayajulu break; 278711bcba0SDavid C Somayajulu } 279711bcba0SDavid C Somayajulu 280711bcba0SDavid C Somayajulu if (i == cq_comp_idx) { 281711bcba0SDavid C Somayajulu cq_comp_idx = *(ha->rx_ring[cq_idx].cqi_vaddr); 282711bcba0SDavid C Somayajulu } 283711bcba0SDavid C Somayajulu 284711bcba0SDavid C Somayajulu if (tx_comp_done) { 285711bcba0SDavid C Somayajulu taskqueue_enqueue(ha->tx_tq, &ha->tx_task); 286711bcba0SDavid C Somayajulu tx_comp_done = 0; 287711bcba0SDavid C Somayajulu } 288711bcba0SDavid C Somayajulu } 289711bcba0SDavid C Somayajulu 290711bcba0SDavid C Somayajulu while((!SLIST_EMPTY(&lro->lro_active))) { 291711bcba0SDavid C Somayajulu queued = SLIST_FIRST(&lro->lro_active); 292711bcba0SDavid C Somayajulu SLIST_REMOVE_HEAD(&lro->lro_active, next); 293711bcba0SDavid C Somayajulu tcp_lro_flush(lro, queued); 294711bcba0SDavid C Somayajulu } 295711bcba0SDavid C Somayajulu 296711bcba0SDavid C Somayajulu ha->rx_ring[cq_idx].cq_next = cq_comp_idx; 297711bcba0SDavid C Somayajulu 298711bcba0SDavid C Somayajulu if (!ret) { 299711bcba0SDavid C Somayajulu Q81_WR_CQ_CONS_IDX(cq_idx, (ha->rx_ring[cq_idx].cq_next)); 300711bcba0SDavid C Somayajulu } 301711bcba0SDavid C Somayajulu if (tx_comp_done) 302711bcba0SDavid C Somayajulu taskqueue_enqueue(ha->tx_tq, &ha->tx_task); 303711bcba0SDavid C Somayajulu 304711bcba0SDavid C Somayajulu return; 305711bcba0SDavid C Somayajulu } 306711bcba0SDavid C Somayajulu 307711bcba0SDavid C Somayajulu static void 308711bcba0SDavid C Somayajulu qls_mbx_isr(qla_host_t *ha) 309711bcba0SDavid C Somayajulu { 310711bcba0SDavid C Somayajulu uint32_t data; 311711bcba0SDavid C Somayajulu int i; 312711bcba0SDavid C Somayajulu device_t dev = ha->pci_dev; 313711bcba0SDavid C Somayajulu 314711bcba0SDavid C Somayajulu if (qls_mbx_rd_reg(ha, 0, &data) == 0) { 315711bcba0SDavid C Somayajulu 316711bcba0SDavid C Somayajulu if ((data & 0xF000) == 0x4000) { 317711bcba0SDavid C Somayajulu ha->mbox[0] = data; 318711bcba0SDavid C Somayajulu for (i = 1; i < Q81_NUM_MBX_REGISTERS; i++) { 319711bcba0SDavid C Somayajulu if (qls_mbx_rd_reg(ha, i, &data)) 320711bcba0SDavid C Somayajulu break; 321711bcba0SDavid C Somayajulu ha->mbox[i] = data; 322711bcba0SDavid C Somayajulu } 323711bcba0SDavid C Somayajulu ha->mbx_done = 1; 324711bcba0SDavid C Somayajulu } else if ((data & 0xF000) == 0x8000) { 325711bcba0SDavid C Somayajulu 326711bcba0SDavid C Somayajulu /* we have an AEN */ 327711bcba0SDavid C Somayajulu 328711bcba0SDavid C Somayajulu ha->aen[0] = data; 329711bcba0SDavid C Somayajulu for (i = 1; i < Q81_NUM_AEN_REGISTERS; i++) { 330711bcba0SDavid C Somayajulu if (qls_mbx_rd_reg(ha, i, &data)) 331711bcba0SDavid C Somayajulu break; 332711bcba0SDavid C Somayajulu ha->aen[i] = data; 333711bcba0SDavid C Somayajulu } 334711bcba0SDavid C Somayajulu device_printf(dev,"%s: AEN " 335711bcba0SDavid C Somayajulu "[0x%08x 0x%08x 0x%08x 0x%08x 0x%08x" 336711bcba0SDavid C Somayajulu " 0x%08x 0x%08x 0x%08x 0x%08x]\n", 337711bcba0SDavid C Somayajulu __func__, 338711bcba0SDavid C Somayajulu ha->aen[0], ha->aen[1], ha->aen[2], 339711bcba0SDavid C Somayajulu ha->aen[3], ha->aen[4], ha->aen[5], 340711bcba0SDavid C Somayajulu ha->aen[6], ha->aen[7], ha->aen[8]); 341711bcba0SDavid C Somayajulu 342711bcba0SDavid C Somayajulu switch ((ha->aen[0] & 0xFFFF)) { 343711bcba0SDavid C Somayajulu 344711bcba0SDavid C Somayajulu case 0x8011: 345711bcba0SDavid C Somayajulu ha->link_up = 1; 346711bcba0SDavid C Somayajulu break; 347711bcba0SDavid C Somayajulu 348711bcba0SDavid C Somayajulu case 0x8012: 349711bcba0SDavid C Somayajulu ha->link_up = 0; 350711bcba0SDavid C Somayajulu break; 351711bcba0SDavid C Somayajulu 352711bcba0SDavid C Somayajulu case 0x8130: 353711bcba0SDavid C Somayajulu ha->link_hw_info = ha->aen[1]; 354711bcba0SDavid C Somayajulu break; 355711bcba0SDavid C Somayajulu 356711bcba0SDavid C Somayajulu case 0x8131: 357711bcba0SDavid C Somayajulu ha->link_hw_info = 0; 358711bcba0SDavid C Somayajulu break; 359711bcba0SDavid C Somayajulu 360711bcba0SDavid C Somayajulu } 361711bcba0SDavid C Somayajulu } 362711bcba0SDavid C Somayajulu } 363711bcba0SDavid C Somayajulu WRITE_REG32(ha, Q81_CTL_HOST_CMD_STATUS, Q81_CTL_HCS_CMD_CLR_RTH_INTR); 364711bcba0SDavid C Somayajulu 365711bcba0SDavid C Somayajulu return; 366711bcba0SDavid C Somayajulu } 367711bcba0SDavid C Somayajulu 368711bcba0SDavid C Somayajulu void 369711bcba0SDavid C Somayajulu qls_isr(void *arg) 370711bcba0SDavid C Somayajulu { 371711bcba0SDavid C Somayajulu qla_ivec_t *ivec = arg; 372711bcba0SDavid C Somayajulu qla_host_t *ha; 373711bcba0SDavid C Somayajulu uint32_t status; 374711bcba0SDavid C Somayajulu uint32_t cq_idx; 375711bcba0SDavid C Somayajulu device_t dev; 376711bcba0SDavid C Somayajulu 377711bcba0SDavid C Somayajulu ha = ivec->ha; 378711bcba0SDavid C Somayajulu cq_idx = ivec->cq_idx; 379711bcba0SDavid C Somayajulu dev = ha->pci_dev; 380711bcba0SDavid C Somayajulu 381711bcba0SDavid C Somayajulu status = READ_REG32(ha, Q81_CTL_STATUS); 382711bcba0SDavid C Somayajulu 383711bcba0SDavid C Somayajulu if (status & Q81_CTL_STATUS_FE) { 384711bcba0SDavid C Somayajulu device_printf(dev, "%s fatal error\n", __func__); 385711bcba0SDavid C Somayajulu return; 386711bcba0SDavid C Somayajulu } 387711bcba0SDavid C Somayajulu 388711bcba0SDavid C Somayajulu if ((cq_idx == 0) && (status & Q81_CTL_STATUS_PI)) { 389711bcba0SDavid C Somayajulu qls_mbx_isr(ha); 390711bcba0SDavid C Somayajulu } 391711bcba0SDavid C Somayajulu 392711bcba0SDavid C Somayajulu status = READ_REG32(ha, Q81_CTL_INTR_STATUS1); 393711bcba0SDavid C Somayajulu 394711bcba0SDavid C Somayajulu if (status & ( 0x1 << cq_idx)) 395711bcba0SDavid C Somayajulu qls_cq_isr(ha, cq_idx); 396711bcba0SDavid C Somayajulu 397711bcba0SDavid C Somayajulu Q81_ENABLE_INTR(ha, cq_idx); 398711bcba0SDavid C Somayajulu 399711bcba0SDavid C Somayajulu return; 400711bcba0SDavid C Somayajulu } 401711bcba0SDavid C Somayajulu 402