1250661Sdavidcs/* 2250661Sdavidcs * Copyright (c) 2013-2014 Qlogic Corporation 3250661Sdavidcs * All rights reserved. 4250661Sdavidcs * 5250661Sdavidcs * Redistribution and use in source and binary forms, with or without 6250661Sdavidcs * modification, are permitted provided that the following conditions 7250661Sdavidcs * are met: 8250661Sdavidcs * 9250661Sdavidcs * 1. Redistributions of source code must retain the above copyright 10250661Sdavidcs * notice, this list of conditions and the following disclaimer. 11250661Sdavidcs * 2. Redistributions in binary form must reproduce the above copyright 12250661Sdavidcs * notice, this list of conditions and the following disclaimer in the 13250661Sdavidcs * documentation and/or other materials provided with the distribution. 14250661Sdavidcs * 15250661Sdavidcs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16250661Sdavidcs * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17250661Sdavidcs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18250661Sdavidcs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19250661Sdavidcs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20250661Sdavidcs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21250661Sdavidcs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22250661Sdavidcs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23250661Sdavidcs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24250661Sdavidcs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25250661Sdavidcs * POSSIBILITY OF SUCH DAMAGE. 26250661Sdavidcs */ 27250661Sdavidcs 28250661Sdavidcs/* 29250661Sdavidcs * File: ql_isr.c 30250661Sdavidcs * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656. 31250661Sdavidcs */ 32250661Sdavidcs 33250661Sdavidcs#include <sys/cdefs.h> 34250661Sdavidcs__FBSDID("$FreeBSD$"); 35250661Sdavidcs 36250661Sdavidcs 37250661Sdavidcs#include "ql_os.h" 38250661Sdavidcs#include "ql_hw.h" 39250661Sdavidcs#include "ql_def.h" 40250661Sdavidcs#include "ql_inline.h" 41250661Sdavidcs#include "ql_ver.h" 42250661Sdavidcs#include "ql_glbl.h" 43250661Sdavidcs#include "ql_dbg.h" 44250661Sdavidcs 45250661Sdavidcsstatic void qla_replenish_normal_rx(qla_host_t *ha, qla_sds_t *sdsp, 46250661Sdavidcs uint32_t r_idx); 47250661Sdavidcs 48250661Sdavidcsstatic void 49250661Sdavidcsqla_rcv_error(qla_host_t *ha) 50250661Sdavidcs{ 51250661Sdavidcs ha->flags.stop_rcv = 1; 52250661Sdavidcs ha->qla_initiate_recovery = 1; 53250661Sdavidcs} 54250661Sdavidcs 55250661Sdavidcs 56250661Sdavidcs/* 57250661Sdavidcs * Name: qla_rx_intr 58250661Sdavidcs * Function: Handles normal ethernet frames received 59250661Sdavidcs */ 60250661Sdavidcsstatic void 61250661Sdavidcsqla_rx_intr(qla_host_t *ha, qla_sgl_rcv_t *sgc, uint32_t sds_idx) 62250661Sdavidcs{ 63250661Sdavidcs qla_rx_buf_t *rxb; 64250661Sdavidcs struct mbuf *mp = NULL, *mpf = NULL, *mpl = NULL; 65250661Sdavidcs struct ifnet *ifp = ha->ifp; 66250661Sdavidcs qla_sds_t *sdsp; 67250661Sdavidcs struct ether_vlan_header *eh; 68250661Sdavidcs uint32_t i, rem_len = 0; 69250661Sdavidcs uint32_t r_idx = 0; 70250661Sdavidcs qla_rx_ring_t *rx_ring; 71250661Sdavidcs 72250661Sdavidcs if (ha->hw.num_rds_rings > 1) 73250661Sdavidcs r_idx = sds_idx; 74250661Sdavidcs 75250661Sdavidcs ha->hw.rds[r_idx].count++; 76250661Sdavidcs 77250661Sdavidcs sdsp = &ha->hw.sds[sds_idx]; 78250661Sdavidcs rx_ring = &ha->rx_ring[r_idx]; 79250661Sdavidcs 80250661Sdavidcs for (i = 0; i < sgc->num_handles; i++) { 81250661Sdavidcs rxb = &rx_ring->rx_buf[sgc->handle[i] & 0x7FFF]; 82250661Sdavidcs 83250661Sdavidcs QL_ASSERT(ha, (rxb != NULL), 84250661Sdavidcs ("%s: [sds_idx]=[%d] rxb != NULL\n", __func__,\ 85250661Sdavidcs sds_idx)); 86250661Sdavidcs 87250661Sdavidcs if ((rxb == NULL) || QL_ERR_INJECT(ha, INJCT_RX_RXB_INVAL)) { 88250661Sdavidcs /* log the error */ 89250661Sdavidcs device_printf(ha->pci_dev, 90250661Sdavidcs "%s invalid rxb[%d, %d, 0x%04x]\n", 91250661Sdavidcs __func__, sds_idx, i, sgc->handle[i]); 92250661Sdavidcs qla_rcv_error(ha); 93250661Sdavidcs return; 94250661Sdavidcs } 95250661Sdavidcs 96250661Sdavidcs mp = rxb->m_head; 97250661Sdavidcs if (i == 0) 98250661Sdavidcs mpf = mp; 99250661Sdavidcs 100250661Sdavidcs QL_ASSERT(ha, (mp != NULL), 101250661Sdavidcs ("%s: [sds_idx]=[%d] mp != NULL\n", __func__,\ 102250661Sdavidcs sds_idx)); 103250661Sdavidcs 104250661Sdavidcs bus_dmamap_sync(ha->rx_tag, rxb->map, BUS_DMASYNC_POSTREAD); 105250661Sdavidcs 106250661Sdavidcs rxb->m_head = NULL; 107250661Sdavidcs rxb->next = sdsp->rxb_free; 108250661Sdavidcs sdsp->rxb_free = rxb; 109250661Sdavidcs sdsp->rx_free++; 110250661Sdavidcs 111250661Sdavidcs if ((mp == NULL) || QL_ERR_INJECT(ha, INJCT_RX_MP_NULL)) { 112250661Sdavidcs /* log the error */ 113250661Sdavidcs device_printf(ha->pci_dev, 114250661Sdavidcs "%s mp == NULL [%d, %d, 0x%04x]\n", 115250661Sdavidcs __func__, sds_idx, i, sgc->handle[i]); 116250661Sdavidcs qla_rcv_error(ha); 117250661Sdavidcs return; 118250661Sdavidcs } 119250661Sdavidcs 120250661Sdavidcs if (i == 0) { 121250661Sdavidcs mpl = mpf = mp; 122250661Sdavidcs mp->m_flags |= M_PKTHDR; 123250661Sdavidcs mp->m_pkthdr.len = sgc->pkt_length; 124250661Sdavidcs mp->m_pkthdr.rcvif = ifp; 125250661Sdavidcs rem_len = mp->m_pkthdr.len; 126250661Sdavidcs } else { 127250661Sdavidcs mp->m_flags &= ~M_PKTHDR; 128250661Sdavidcs mpl->m_next = mp; 129250661Sdavidcs mpl = mp; 130250661Sdavidcs rem_len = rem_len - mp->m_len; 131250661Sdavidcs } 132250661Sdavidcs } 133250661Sdavidcs 134250661Sdavidcs mpl->m_len = rem_len; 135250661Sdavidcs 136250661Sdavidcs eh = mtod(mpf, struct ether_vlan_header *); 137250661Sdavidcs 138250661Sdavidcs if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 139250661Sdavidcs uint32_t *data = (uint32_t *)eh; 140250661Sdavidcs 141250661Sdavidcs mpf->m_pkthdr.ether_vtag = ntohs(eh->evl_tag); 142250661Sdavidcs mpf->m_flags |= M_VLANTAG; 143250661Sdavidcs 144250661Sdavidcs *(data + 3) = *(data + 2); 145250661Sdavidcs *(data + 2) = *(data + 1); 146250661Sdavidcs *(data + 1) = *data; 147250661Sdavidcs 148250661Sdavidcs m_adj(mpf, ETHER_VLAN_ENCAP_LEN); 149250661Sdavidcs } 150250661Sdavidcs 151250661Sdavidcs if (sgc->chksum_status == Q8_STAT_DESC_STATUS_CHKSUM_OK) { 152250661Sdavidcs mpf->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID | 153250661Sdavidcs CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 154250661Sdavidcs mpf->m_pkthdr.csum_data = 0xFFFF; 155250661Sdavidcs } else { 156250661Sdavidcs mpf->m_pkthdr.csum_flags = 0; 157250661Sdavidcs } 158250661Sdavidcs 159250661Sdavidcs ifp->if_ipackets++; 160250661Sdavidcs 161250661Sdavidcs mpf->m_pkthdr.flowid = sgc->rss_hash; 162250661Sdavidcs mpf->m_flags |= M_FLOWID; 163250661Sdavidcs 164250661Sdavidcs (*ifp->if_input)(ifp, mpf); 165250661Sdavidcs 166250661Sdavidcs if (sdsp->rx_free > ha->std_replenish) 167250661Sdavidcs qla_replenish_normal_rx(ha, sdsp, r_idx); 168250661Sdavidcs 169250661Sdavidcs return; 170250661Sdavidcs} 171250661Sdavidcs 172250661Sdavidcs#define QLA_TCP_HDR_SIZE 20 173250661Sdavidcs#define QLA_TCP_TS_OPTION_SIZE 12 174250661Sdavidcs 175250661Sdavidcs/* 176250661Sdavidcs * Name: qla_lro_intr 177250661Sdavidcs * Function: Handles normal ethernet frames received 178250661Sdavidcs */ 179250661Sdavidcsstatic int 180250661Sdavidcsqla_lro_intr(qla_host_t *ha, qla_sgl_lro_t *sgc, uint32_t sds_idx) 181250661Sdavidcs{ 182250661Sdavidcs qla_rx_buf_t *rxb; 183250661Sdavidcs struct mbuf *mp = NULL, *mpf = NULL, *mpl = NULL; 184250661Sdavidcs struct ifnet *ifp = ha->ifp; 185250661Sdavidcs qla_sds_t *sdsp; 186250661Sdavidcs struct ether_vlan_header *eh; 187250661Sdavidcs uint32_t i, rem_len = 0, pkt_length, iplen; 188250661Sdavidcs struct tcphdr *th; 189250661Sdavidcs struct ip *ip = NULL; 190250661Sdavidcs struct ip6_hdr *ip6 = NULL; 191250661Sdavidcs uint16_t etype; 192250661Sdavidcs uint32_t r_idx = 0; 193250661Sdavidcs qla_rx_ring_t *rx_ring; 194250661Sdavidcs 195250661Sdavidcs if (ha->hw.num_rds_rings > 1) 196250661Sdavidcs r_idx = sds_idx; 197250661Sdavidcs 198250661Sdavidcs ha->hw.rds[r_idx].count++; 199250661Sdavidcs 200250661Sdavidcs rx_ring = &ha->rx_ring[r_idx]; 201250661Sdavidcs 202250661Sdavidcs ha->lro_pkt_count++; 203250661Sdavidcs 204250661Sdavidcs sdsp = &ha->hw.sds[sds_idx]; 205250661Sdavidcs 206250661Sdavidcs pkt_length = sgc->payload_length + sgc->l4_offset; 207250661Sdavidcs 208250661Sdavidcs if (sgc->flags & Q8_LRO_COMP_TS) { 209250661Sdavidcs pkt_length += QLA_TCP_HDR_SIZE + QLA_TCP_TS_OPTION_SIZE; 210250661Sdavidcs } else { 211250661Sdavidcs pkt_length += QLA_TCP_HDR_SIZE; 212250661Sdavidcs } 213250661Sdavidcs ha->lro_bytes += pkt_length; 214250661Sdavidcs 215250661Sdavidcs for (i = 0; i < sgc->num_handles; i++) { 216250661Sdavidcs rxb = &rx_ring->rx_buf[sgc->handle[i] & 0x7FFF]; 217250661Sdavidcs 218250661Sdavidcs QL_ASSERT(ha, (rxb != NULL), 219250661Sdavidcs ("%s: [sds_idx]=[%d] rxb != NULL\n", __func__,\ 220250661Sdavidcs sds_idx)); 221250661Sdavidcs 222250661Sdavidcs if ((rxb == NULL) || QL_ERR_INJECT(ha, INJCT_LRO_RXB_INVAL)) { 223250661Sdavidcs /* log the error */ 224250661Sdavidcs device_printf(ha->pci_dev, 225250661Sdavidcs "%s invalid rxb[%d, %d, 0x%04x]\n", 226250661Sdavidcs __func__, sds_idx, i, sgc->handle[i]); 227250661Sdavidcs qla_rcv_error(ha); 228250661Sdavidcs return (0); 229250661Sdavidcs } 230250661Sdavidcs 231250661Sdavidcs mp = rxb->m_head; 232250661Sdavidcs if (i == 0) 233250661Sdavidcs mpf = mp; 234250661Sdavidcs 235250661Sdavidcs QL_ASSERT(ha, (mp != NULL), 236250661Sdavidcs ("%s: [sds_idx]=[%d] mp != NULL\n", __func__,\ 237250661Sdavidcs sds_idx)); 238250661Sdavidcs 239250661Sdavidcs bus_dmamap_sync(ha->rx_tag, rxb->map, BUS_DMASYNC_POSTREAD); 240250661Sdavidcs 241250661Sdavidcs rxb->m_head = NULL; 242250661Sdavidcs rxb->next = sdsp->rxb_free; 243250661Sdavidcs sdsp->rxb_free = rxb; 244250661Sdavidcs sdsp->rx_free++; 245250661Sdavidcs 246250661Sdavidcs if ((mp == NULL) || QL_ERR_INJECT(ha, INJCT_LRO_MP_NULL)) { 247250661Sdavidcs /* log the error */ 248250661Sdavidcs device_printf(ha->pci_dev, 249250661Sdavidcs "%s mp == NULL [%d, %d, 0x%04x]\n", 250250661Sdavidcs __func__, sds_idx, i, sgc->handle[i]); 251250661Sdavidcs qla_rcv_error(ha); 252250661Sdavidcs return (0); 253250661Sdavidcs } 254250661Sdavidcs 255250661Sdavidcs if (i == 0) { 256250661Sdavidcs mpl = mpf = mp; 257250661Sdavidcs mp->m_flags |= M_PKTHDR; 258250661Sdavidcs mp->m_pkthdr.len = pkt_length; 259250661Sdavidcs mp->m_pkthdr.rcvif = ifp; 260250661Sdavidcs rem_len = mp->m_pkthdr.len; 261250661Sdavidcs } else { 262250661Sdavidcs mp->m_flags &= ~M_PKTHDR; 263250661Sdavidcs mpl->m_next = mp; 264250661Sdavidcs mpl = mp; 265250661Sdavidcs rem_len = rem_len - mp->m_len; 266250661Sdavidcs } 267250661Sdavidcs } 268250661Sdavidcs 269250661Sdavidcs mpl->m_len = rem_len; 270250661Sdavidcs 271250661Sdavidcs th = (struct tcphdr *)(mpf->m_data + sgc->l4_offset); 272250661Sdavidcs 273250661Sdavidcs if (sgc->flags & Q8_LRO_COMP_PUSH_BIT) 274250661Sdavidcs th->th_flags |= TH_PUSH; 275250661Sdavidcs 276250661Sdavidcs m_adj(mpf, sgc->l2_offset); 277250661Sdavidcs 278250661Sdavidcs eh = mtod(mpf, struct ether_vlan_header *); 279250661Sdavidcs 280250661Sdavidcs if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { 281250661Sdavidcs uint32_t *data = (uint32_t *)eh; 282250661Sdavidcs 283250661Sdavidcs mpf->m_pkthdr.ether_vtag = ntohs(eh->evl_tag); 284250661Sdavidcs mpf->m_flags |= M_VLANTAG; 285250661Sdavidcs 286250661Sdavidcs *(data + 3) = *(data + 2); 287250661Sdavidcs *(data + 2) = *(data + 1); 288250661Sdavidcs *(data + 1) = *data; 289250661Sdavidcs 290250661Sdavidcs m_adj(mpf, ETHER_VLAN_ENCAP_LEN); 291250661Sdavidcs 292250661Sdavidcs etype = ntohs(eh->evl_proto); 293250661Sdavidcs } else { 294250661Sdavidcs etype = ntohs(eh->evl_encap_proto); 295250661Sdavidcs } 296250661Sdavidcs 297250661Sdavidcs if (etype == ETHERTYPE_IP) { 298250661Sdavidcs ip = (struct ip *)(mpf->m_data + ETHER_HDR_LEN); 299250661Sdavidcs 300250661Sdavidcs iplen = (ip->ip_hl << 2) + (th->th_off << 2) + 301250661Sdavidcs sgc->payload_length; 302250661Sdavidcs 303250661Sdavidcs ip->ip_len = htons(iplen); 304250661Sdavidcs 305250661Sdavidcs ha->ipv4_lro++; 306250661Sdavidcs } else if (etype == ETHERTYPE_IPV6) { 307250661Sdavidcs ip6 = (struct ip6_hdr *)(mpf->m_data + ETHER_HDR_LEN); 308250661Sdavidcs 309250661Sdavidcs iplen = (th->th_off << 2) + sgc->payload_length; 310250661Sdavidcs 311250661Sdavidcs ip6->ip6_plen = htons(iplen); 312250661Sdavidcs 313250661Sdavidcs ha->ipv6_lro++; 314250661Sdavidcs } else { 315250661Sdavidcs m_freem(mpf); 316250661Sdavidcs 317250661Sdavidcs if (sdsp->rx_free > ha->std_replenish) 318250661Sdavidcs qla_replenish_normal_rx(ha, sdsp, r_idx); 319250661Sdavidcs return 0; 320250661Sdavidcs } 321250661Sdavidcs 322250661Sdavidcs mpf->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID | 323250661Sdavidcs CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 324250661Sdavidcs mpf->m_pkthdr.csum_data = 0xFFFF; 325250661Sdavidcs 326250661Sdavidcs mpf->m_pkthdr.flowid = sgc->rss_hash; 327250661Sdavidcs mpf->m_flags |= M_FLOWID; 328250661Sdavidcs 329250661Sdavidcs ifp->if_ipackets++; 330250661Sdavidcs 331250661Sdavidcs (*ifp->if_input)(ifp, mpf); 332250661Sdavidcs 333250661Sdavidcs if (sdsp->rx_free > ha->std_replenish) 334250661Sdavidcs qla_replenish_normal_rx(ha, sdsp, r_idx); 335250661Sdavidcs 336250661Sdavidcs return (0); 337250661Sdavidcs} 338250661Sdavidcs 339250661Sdavidcsstatic int 340250661Sdavidcsqla_rcv_cont_sds(qla_host_t *ha, uint32_t sds_idx, uint32_t comp_idx, 341250661Sdavidcs uint32_t dcount, uint16_t *handle, uint16_t *nhandles) 342250661Sdavidcs{ 343250661Sdavidcs uint32_t i; 344250661Sdavidcs uint16_t num_handles; 345250661Sdavidcs q80_stat_desc_t *sdesc; 346250661Sdavidcs uint32_t opcode; 347250661Sdavidcs 348250661Sdavidcs *nhandles = 0; 349250661Sdavidcs dcount--; 350250661Sdavidcs 351250661Sdavidcs for (i = 0; i < dcount; i++) { 352250661Sdavidcs comp_idx = (comp_idx + 1) & (NUM_STATUS_DESCRIPTORS-1); 353250661Sdavidcs sdesc = (q80_stat_desc_t *) 354250661Sdavidcs &ha->hw.sds[sds_idx].sds_ring_base[comp_idx]; 355250661Sdavidcs 356250661Sdavidcs opcode = Q8_STAT_DESC_OPCODE((sdesc->data[1])); 357250661Sdavidcs 358250661Sdavidcs if (!opcode) { 359250661Sdavidcs device_printf(ha->pci_dev, "%s: opcode=0 %p %p\n", 360250661Sdavidcs __func__, (void *)sdesc->data[0], 361250661Sdavidcs (void *)sdesc->data[1]); 362250661Sdavidcs return -1; 363250661Sdavidcs } 364250661Sdavidcs 365250661Sdavidcs num_handles = Q8_SGL_STAT_DESC_NUM_HANDLES((sdesc->data[1])); 366250661Sdavidcs if (!num_handles) { 367250661Sdavidcs device_printf(ha->pci_dev, "%s: opcode=0 %p %p\n", 368250661Sdavidcs __func__, (void *)sdesc->data[0], 369250661Sdavidcs (void *)sdesc->data[1]); 370250661Sdavidcs return -1; 371250661Sdavidcs } 372250661Sdavidcs 373250661Sdavidcs if (QL_ERR_INJECT(ha, INJCT_NUM_HNDLE_INVALID)) 374250661Sdavidcs num_handles = -1; 375250661Sdavidcs 376250661Sdavidcs switch (num_handles) { 377250661Sdavidcs 378250661Sdavidcs case 1: 379250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0])); 380250661Sdavidcs break; 381250661Sdavidcs 382250661Sdavidcs case 2: 383250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0])); 384250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0])); 385250661Sdavidcs break; 386250661Sdavidcs 387250661Sdavidcs case 3: 388250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0])); 389250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0])); 390250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE3((sdesc->data[0])); 391250661Sdavidcs break; 392250661Sdavidcs 393250661Sdavidcs case 4: 394250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0])); 395250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0])); 396250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE3((sdesc->data[0])); 397250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE4((sdesc->data[0])); 398250661Sdavidcs break; 399250661Sdavidcs 400250661Sdavidcs case 5: 401250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0])); 402250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0])); 403250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE3((sdesc->data[0])); 404250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE4((sdesc->data[0])); 405250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE5((sdesc->data[1])); 406250661Sdavidcs break; 407250661Sdavidcs 408250661Sdavidcs case 6: 409250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0])); 410250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0])); 411250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE3((sdesc->data[0])); 412250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE4((sdesc->data[0])); 413250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE5((sdesc->data[1])); 414250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE6((sdesc->data[1])); 415250661Sdavidcs break; 416250661Sdavidcs 417250661Sdavidcs case 7: 418250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0])); 419250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0])); 420250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE3((sdesc->data[0])); 421250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE4((sdesc->data[0])); 422250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE5((sdesc->data[1])); 423250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE6((sdesc->data[1])); 424250661Sdavidcs *handle++ = Q8_SGL_STAT_DESC_HANDLE7((sdesc->data[1])); 425250661Sdavidcs break; 426250661Sdavidcs 427250661Sdavidcs default: 428250661Sdavidcs device_printf(ha->pci_dev, 429250661Sdavidcs "%s: invalid num handles %p %p\n", 430250661Sdavidcs __func__, (void *)sdesc->data[0], 431250661Sdavidcs (void *)sdesc->data[1]); 432250661Sdavidcs 433250661Sdavidcs QL_ASSERT(ha, (0),\ 434250661Sdavidcs ("%s: %s [nh, sds, d0, d1]=[%d, %d, %p, %p]\n", 435250661Sdavidcs __func__, "invalid num handles", sds_idx, num_handles, 436250661Sdavidcs (void *)sdesc->data[0],(void *)sdesc->data[1])); 437250661Sdavidcs 438250661Sdavidcs qla_rcv_error(ha); 439250661Sdavidcs return 0; 440250661Sdavidcs } 441250661Sdavidcs *nhandles = *nhandles + num_handles; 442250661Sdavidcs } 443250661Sdavidcs return 0; 444250661Sdavidcs} 445250661Sdavidcs 446250661Sdavidcs/* 447250661Sdavidcs * Name: qla_rcv_isr 448250661Sdavidcs * Function: Main Interrupt Service Routine 449250661Sdavidcs */ 450250661Sdavidcsstatic uint32_t 451250661Sdavidcsqla_rcv_isr(qla_host_t *ha, uint32_t sds_idx, uint32_t count) 452250661Sdavidcs{ 453250661Sdavidcs device_t dev; 454250661Sdavidcs qla_hw_t *hw; 455250661Sdavidcs uint32_t comp_idx, c_idx = 0, desc_count = 0, opcode; 456250661Sdavidcs volatile q80_stat_desc_t *sdesc, *sdesc0 = NULL; 457250661Sdavidcs uint32_t ret = 0; 458250661Sdavidcs qla_sgl_comp_t sgc; 459250661Sdavidcs uint16_t nhandles; 460250661Sdavidcs uint32_t sds_replenish_threshold = 0; 461250661Sdavidcs 462250661Sdavidcs dev = ha->pci_dev; 463250661Sdavidcs hw = &ha->hw; 464250661Sdavidcs 465250661Sdavidcs hw->sds[sds_idx].rcv_active = 1; 466250661Sdavidcs if (ha->flags.stop_rcv) { 467250661Sdavidcs hw->sds[sds_idx].rcv_active = 0; 468250661Sdavidcs return 0; 469250661Sdavidcs } 470250661Sdavidcs 471250661Sdavidcs QL_DPRINT2(ha, (dev, "%s: [%d]enter\n", __func__, sds_idx)); 472250661Sdavidcs 473250661Sdavidcs /* 474250661Sdavidcs * receive interrupts 475250661Sdavidcs */ 476250661Sdavidcs comp_idx = hw->sds[sds_idx].sdsr_next; 477250661Sdavidcs 478250661Sdavidcs while (count-- && !ha->flags.stop_rcv) { 479250661Sdavidcs 480250661Sdavidcs sdesc = (q80_stat_desc_t *) 481250661Sdavidcs &hw->sds[sds_idx].sds_ring_base[comp_idx]; 482250661Sdavidcs 483250661Sdavidcs opcode = Q8_STAT_DESC_OPCODE((sdesc->data[1])); 484250661Sdavidcs 485250661Sdavidcs if (!opcode) 486250661Sdavidcs break; 487250661Sdavidcs 488250661Sdavidcs hw->sds[sds_idx].intr_count++; 489250661Sdavidcs switch (opcode) { 490250661Sdavidcs 491250661Sdavidcs case Q8_STAT_DESC_OPCODE_RCV_PKT: 492250661Sdavidcs 493250661Sdavidcs desc_count = 1; 494250661Sdavidcs 495250661Sdavidcs bzero(&sgc, sizeof(qla_sgl_comp_t)); 496250661Sdavidcs 497250661Sdavidcs sgc.rcv.pkt_length = 498250661Sdavidcs Q8_STAT_DESC_TOTAL_LENGTH((sdesc->data[0])); 499250661Sdavidcs sgc.rcv.num_handles = 1; 500250661Sdavidcs sgc.rcv.handle[0] = 501250661Sdavidcs Q8_STAT_DESC_HANDLE((sdesc->data[0])); 502250661Sdavidcs sgc.rcv.chksum_status = 503250661Sdavidcs Q8_STAT_DESC_STATUS((sdesc->data[1])); 504250661Sdavidcs 505250661Sdavidcs sgc.rcv.rss_hash = 506250661Sdavidcs Q8_STAT_DESC_RSS_HASH((sdesc->data[0])); 507250661Sdavidcs 508250661Sdavidcs if (Q8_STAT_DESC_VLAN((sdesc->data[1]))) { 509250661Sdavidcs sgc.rcv.vlan_tag = 510250661Sdavidcs Q8_STAT_DESC_VLAN_ID((sdesc->data[1])); 511250661Sdavidcs } 512250661Sdavidcs qla_rx_intr(ha, &sgc.rcv, sds_idx); 513250661Sdavidcs break; 514250661Sdavidcs 515250661Sdavidcs case Q8_STAT_DESC_OPCODE_SGL_RCV: 516250661Sdavidcs 517250661Sdavidcs desc_count = 518250661Sdavidcs Q8_STAT_DESC_COUNT_SGL_RCV((sdesc->data[1])); 519250661Sdavidcs 520250661Sdavidcs if (desc_count > 1) { 521250661Sdavidcs c_idx = (comp_idx + desc_count -1) & 522250661Sdavidcs (NUM_STATUS_DESCRIPTORS-1); 523250661Sdavidcs sdesc0 = (q80_stat_desc_t *) 524250661Sdavidcs &hw->sds[sds_idx].sds_ring_base[c_idx]; 525250661Sdavidcs 526250661Sdavidcs if (Q8_STAT_DESC_OPCODE((sdesc0->data[1])) != 527250661Sdavidcs Q8_STAT_DESC_OPCODE_CONT) { 528250661Sdavidcs desc_count = 0; 529250661Sdavidcs break; 530250661Sdavidcs } 531250661Sdavidcs } 532250661Sdavidcs 533250661Sdavidcs bzero(&sgc, sizeof(qla_sgl_comp_t)); 534250661Sdavidcs 535250661Sdavidcs sgc.rcv.pkt_length = 536250661Sdavidcs Q8_STAT_DESC_TOTAL_LENGTH_SGL_RCV(\ 537250661Sdavidcs (sdesc->data[0])); 538250661Sdavidcs sgc.rcv.chksum_status = 539250661Sdavidcs Q8_STAT_DESC_STATUS((sdesc->data[1])); 540250661Sdavidcs 541250661Sdavidcs sgc.rcv.rss_hash = 542250661Sdavidcs Q8_STAT_DESC_RSS_HASH((sdesc->data[0])); 543250661Sdavidcs 544250661Sdavidcs if (Q8_STAT_DESC_VLAN((sdesc->data[1]))) { 545250661Sdavidcs sgc.rcv.vlan_tag = 546250661Sdavidcs Q8_STAT_DESC_VLAN_ID((sdesc->data[1])); 547250661Sdavidcs } 548250661Sdavidcs 549250661Sdavidcs QL_ASSERT(ha, (desc_count <= 2) ,\ 550250661Sdavidcs ("%s: [sds_idx, data0, data1]="\ 551250661Sdavidcs "%d, %p, %p]\n", __func__, sds_idx,\ 552250661Sdavidcs (void *)sdesc->data[0],\ 553250661Sdavidcs (void *)sdesc->data[1])); 554250661Sdavidcs 555250661Sdavidcs sgc.rcv.num_handles = 1; 556250661Sdavidcs sgc.rcv.handle[0] = 557250661Sdavidcs Q8_STAT_DESC_HANDLE((sdesc->data[0])); 558250661Sdavidcs 559250661Sdavidcs if (qla_rcv_cont_sds(ha, sds_idx, comp_idx, desc_count, 560250661Sdavidcs &sgc.rcv.handle[1], &nhandles)) { 561250661Sdavidcs device_printf(dev, 562250661Sdavidcs "%s: [sds_idx, dcount, data0, data1]=" 563250661Sdavidcs "[%d, %d, 0x%llx, 0x%llx]\n", 564250661Sdavidcs __func__, sds_idx, desc_count, 565250661Sdavidcs (long long unsigned int)sdesc->data[0], 566250661Sdavidcs (long long unsigned int)sdesc->data[1]); 567250661Sdavidcs desc_count = 0; 568250661Sdavidcs break; 569250661Sdavidcs } 570250661Sdavidcs 571250661Sdavidcs sgc.rcv.num_handles += nhandles; 572250661Sdavidcs 573250661Sdavidcs qla_rx_intr(ha, &sgc.rcv, sds_idx); 574250661Sdavidcs 575250661Sdavidcs break; 576250661Sdavidcs 577250661Sdavidcs case Q8_STAT_DESC_OPCODE_SGL_LRO: 578250661Sdavidcs 579250661Sdavidcs desc_count = 580250661Sdavidcs Q8_STAT_DESC_COUNT_SGL_LRO((sdesc->data[1])); 581250661Sdavidcs 582250661Sdavidcs if (desc_count > 1) { 583250661Sdavidcs c_idx = (comp_idx + desc_count -1) & 584250661Sdavidcs (NUM_STATUS_DESCRIPTORS-1); 585250661Sdavidcs sdesc0 = (q80_stat_desc_t *) 586250661Sdavidcs &hw->sds[sds_idx].sds_ring_base[c_idx]; 587250661Sdavidcs 588250661Sdavidcs if (Q8_STAT_DESC_OPCODE((sdesc0->data[1])) != 589250661Sdavidcs Q8_STAT_DESC_OPCODE_CONT) { 590250661Sdavidcs desc_count = 0; 591250661Sdavidcs break; 592250661Sdavidcs } 593250661Sdavidcs } 594250661Sdavidcs bzero(&sgc, sizeof(qla_sgl_comp_t)); 595250661Sdavidcs 596250661Sdavidcs sgc.lro.payload_length = 597250661Sdavidcs Q8_STAT_DESC_TOTAL_LENGTH_SGL_RCV((sdesc->data[0])); 598250661Sdavidcs 599250661Sdavidcs sgc.lro.rss_hash = 600250661Sdavidcs Q8_STAT_DESC_RSS_HASH((sdesc->data[0])); 601250661Sdavidcs 602250661Sdavidcs sgc.lro.num_handles = 1; 603250661Sdavidcs sgc.lro.handle[0] = 604250661Sdavidcs Q8_STAT_DESC_HANDLE((sdesc->data[0])); 605250661Sdavidcs 606250661Sdavidcs if (Q8_SGL_LRO_STAT_TS((sdesc->data[1]))) 607250661Sdavidcs sgc.lro.flags |= Q8_LRO_COMP_TS; 608250661Sdavidcs 609250661Sdavidcs if (Q8_SGL_LRO_STAT_PUSH_BIT((sdesc->data[1]))) 610250661Sdavidcs sgc.lro.flags |= Q8_LRO_COMP_PUSH_BIT; 611250661Sdavidcs 612250661Sdavidcs sgc.lro.l2_offset = 613250661Sdavidcs Q8_SGL_LRO_STAT_L2_OFFSET((sdesc->data[1])); 614250661Sdavidcs sgc.lro.l4_offset = 615250661Sdavidcs Q8_SGL_LRO_STAT_L4_OFFSET((sdesc->data[1])); 616250661Sdavidcs 617250661Sdavidcs if (Q8_STAT_DESC_VLAN((sdesc->data[1]))) { 618250661Sdavidcs sgc.lro.vlan_tag = 619250661Sdavidcs Q8_STAT_DESC_VLAN_ID((sdesc->data[1])); 620250661Sdavidcs } 621250661Sdavidcs 622250661Sdavidcs QL_ASSERT(ha, (desc_count <= 7) ,\ 623250661Sdavidcs ("%s: [sds_idx, data0, data1]="\ 624250661Sdavidcs "[%d, 0x%llx, 0x%llx]\n",\ 625250661Sdavidcs __func__, sds_idx,\ 626250661Sdavidcs (long long unsigned int)sdesc->data[0],\ 627250661Sdavidcs (long long unsigned int)sdesc->data[1])); 628250661Sdavidcs 629250661Sdavidcs if (qla_rcv_cont_sds(ha, sds_idx, comp_idx, 630250661Sdavidcs desc_count, &sgc.lro.handle[1], &nhandles)) { 631250661Sdavidcs device_printf(dev, 632250661Sdavidcs "%s: [sds_idx, data0, data1]="\ 633250661Sdavidcs "[%d, 0x%llx, 0x%llx]\n",\ 634250661Sdavidcs __func__, sds_idx,\ 635250661Sdavidcs (long long unsigned int)sdesc->data[0],\ 636250661Sdavidcs (long long unsigned int)sdesc->data[1]); 637250661Sdavidcs 638250661Sdavidcs desc_count = 0; 639250661Sdavidcs break; 640250661Sdavidcs } 641250661Sdavidcs 642250661Sdavidcs sgc.lro.num_handles += nhandles; 643250661Sdavidcs 644250661Sdavidcs if (qla_lro_intr(ha, &sgc.lro, sds_idx)) { 645250661Sdavidcs device_printf(dev, 646250661Sdavidcs "%s: [sds_idx, data0, data1]="\ 647250661Sdavidcs "[%d, 0x%llx, 0x%llx]\n",\ 648250661Sdavidcs __func__, sds_idx,\ 649250661Sdavidcs (long long unsigned int)sdesc->data[0],\ 650250661Sdavidcs (long long unsigned int)sdesc->data[1]); 651250661Sdavidcs device_printf(dev, 652250661Sdavidcs "%s: [comp_idx, c_idx, dcount, nhndls]="\ 653250661Sdavidcs "[%d, %d, %d, %d]\n",\ 654250661Sdavidcs __func__, comp_idx, c_idx, desc_count, 655250661Sdavidcs sgc.lro.num_handles); 656250661Sdavidcs if (desc_count > 1) { 657250661Sdavidcs device_printf(dev, 658250661Sdavidcs "%s: [sds_idx, data0, data1]="\ 659250661Sdavidcs "[%d, 0x%llx, 0x%llx]\n",\ 660250661Sdavidcs __func__, sds_idx,\ 661250661Sdavidcs (long long unsigned int)sdesc0->data[0],\ 662250661Sdavidcs (long long unsigned int)sdesc0->data[1]); 663250661Sdavidcs } 664250661Sdavidcs } 665250661Sdavidcs 666250661Sdavidcs break; 667250661Sdavidcs 668250661Sdavidcs default: 669250661Sdavidcs device_printf(dev, "%s: default 0x%llx!\n", __func__, 670250661Sdavidcs (long long unsigned int)sdesc->data[0]); 671250661Sdavidcs break; 672250661Sdavidcs } 673250661Sdavidcs 674250661Sdavidcs if (desc_count == 0) 675250661Sdavidcs break; 676250661Sdavidcs 677250661Sdavidcs sds_replenish_threshold += desc_count; 678250661Sdavidcs 679250661Sdavidcs 680250661Sdavidcs while (desc_count--) { 681250661Sdavidcs sdesc->data[0] = 0ULL; 682250661Sdavidcs sdesc->data[1] = 0ULL; 683250661Sdavidcs comp_idx = (comp_idx + 1) & (NUM_STATUS_DESCRIPTORS-1); 684250661Sdavidcs sdesc = (q80_stat_desc_t *) 685250661Sdavidcs &hw->sds[sds_idx].sds_ring_base[comp_idx]; 686250661Sdavidcs } 687250661Sdavidcs 688250661Sdavidcs if (sds_replenish_threshold > ha->hw.sds_cidx_thres) { 689250661Sdavidcs sds_replenish_threshold = 0; 690250661Sdavidcs if (hw->sds[sds_idx].sdsr_next != comp_idx) { 691250661Sdavidcs QL_UPDATE_SDS_CONSUMER_INDEX(ha, sds_idx,\ 692250661Sdavidcs comp_idx); 693250661Sdavidcs } 694250661Sdavidcs hw->sds[sds_idx].sdsr_next = comp_idx; 695250661Sdavidcs } 696250661Sdavidcs } 697250661Sdavidcs 698250661Sdavidcs if (ha->flags.stop_rcv) 699250661Sdavidcs goto qla_rcv_isr_exit; 700250661Sdavidcs 701250661Sdavidcs if (hw->sds[sds_idx].sdsr_next != comp_idx) { 702250661Sdavidcs QL_UPDATE_SDS_CONSUMER_INDEX(ha, sds_idx, comp_idx); 703250661Sdavidcs } 704250661Sdavidcs hw->sds[sds_idx].sdsr_next = comp_idx; 705250661Sdavidcs 706250661Sdavidcs sdesc = (q80_stat_desc_t *)&hw->sds[sds_idx].sds_ring_base[comp_idx]; 707250661Sdavidcs opcode = Q8_STAT_DESC_OPCODE((sdesc->data[1])); 708250661Sdavidcs 709250661Sdavidcs if (opcode) 710250661Sdavidcs ret = -1; 711250661Sdavidcs 712250661Sdavidcsqla_rcv_isr_exit: 713250661Sdavidcs hw->sds[sds_idx].rcv_active = 0; 714250661Sdavidcs 715250661Sdavidcs return (ret); 716250661Sdavidcs} 717250661Sdavidcs 718250661Sdavidcsvoid 719250661Sdavidcsql_mbx_isr(void *arg) 720250661Sdavidcs{ 721250661Sdavidcs qla_host_t *ha; 722250661Sdavidcs uint32_t data; 723250661Sdavidcs uint32_t prev_link_state; 724250661Sdavidcs 725250661Sdavidcs ha = arg; 726250661Sdavidcs 727250661Sdavidcs if (ha == NULL) { 728250661Sdavidcs device_printf(ha->pci_dev, "%s: arg == NULL\n", __func__); 729250661Sdavidcs return; 730250661Sdavidcs } 731250661Sdavidcs 732250661Sdavidcs data = READ_REG32(ha, Q8_FW_MBOX_CNTRL); 733250661Sdavidcs if ((data & 0x3) != 0x1) { 734250661Sdavidcs WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0); 735250661Sdavidcs return; 736250661Sdavidcs } 737250661Sdavidcs 738250661Sdavidcs data = READ_REG32(ha, Q8_FW_MBOX0); 739250661Sdavidcs 740250661Sdavidcs if ((data & 0xF000) != 0x8000) 741250661Sdavidcs return; 742250661Sdavidcs 743250661Sdavidcs data = data & 0xFFFF; 744250661Sdavidcs 745250661Sdavidcs switch (data) { 746250661Sdavidcs 747250661Sdavidcs case 0x8001: /* It's an AEN */ 748250661Sdavidcs 749250661Sdavidcs ha->hw.cable_oui = READ_REG32(ha, (Q8_FW_MBOX0 + 4)); 750250661Sdavidcs 751250661Sdavidcs data = READ_REG32(ha, (Q8_FW_MBOX0 + 8)); 752250661Sdavidcs ha->hw.cable_length = data & 0xFFFF; 753250661Sdavidcs 754250661Sdavidcs data = data >> 16; 755250661Sdavidcs ha->hw.link_speed = data & 0xFFF; 756250661Sdavidcs 757250661Sdavidcs data = READ_REG32(ha, (Q8_FW_MBOX0 + 12)); 758250661Sdavidcs 759250661Sdavidcs prev_link_state = ha->hw.link_up; 760250661Sdavidcs ha->hw.link_up = (((data & 0xFF) == 0) ? 0 : 1); 761250661Sdavidcs 762250661Sdavidcs if (prev_link_state != ha->hw.link_up) { 763250661Sdavidcs if (ha->hw.link_up) 764250661Sdavidcs if_link_state_change(ha->ifp, LINK_STATE_UP); 765250661Sdavidcs else 766250661Sdavidcs if_link_state_change(ha->ifp, LINK_STATE_DOWN); 767250661Sdavidcs } 768250661Sdavidcs 769250661Sdavidcs 770250661Sdavidcs ha->hw.module_type = ((data >> 8) & 0xFF); 771250661Sdavidcs ha->hw.flags.fduplex = (((data & 0xFF0000) == 0) ? 0 : 1); 772250661Sdavidcs ha->hw.flags.autoneg = (((data & 0xFF000000) == 0) ? 0 : 1); 773250661Sdavidcs 774250661Sdavidcs data = READ_REG32(ha, (Q8_FW_MBOX0 + 16)); 775250661Sdavidcs ha->hw.flags.loopback_mode = data & 0x03; 776250661Sdavidcs 777250661Sdavidcs ha->hw.link_faults = (data >> 3) & 0xFF; 778250661Sdavidcs 779250661Sdavidcs WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0); 780250661Sdavidcs WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0); 781250661Sdavidcs break; 782250661Sdavidcs 783250661Sdavidcs default: 784250661Sdavidcs device_printf(ha->pci_dev, "%s: AEN[0x%08x]\n", __func__, data); 785250661Sdavidcs WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0); 786250661Sdavidcs WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0); 787250661Sdavidcs break; 788250661Sdavidcs } 789250661Sdavidcs return; 790250661Sdavidcs} 791250661Sdavidcs 792250661Sdavidcs 793250661Sdavidcsstatic void 794250661Sdavidcsqla_replenish_normal_rx(qla_host_t *ha, qla_sds_t *sdsp, uint32_t r_idx) 795250661Sdavidcs{ 796250661Sdavidcs qla_rx_buf_t *rxb; 797250661Sdavidcs int count = sdsp->rx_free; 798250661Sdavidcs uint32_t rx_next; 799250661Sdavidcs qla_rdesc_t *rdesc; 800250661Sdavidcs 801250661Sdavidcs /* we can play with this value via a sysctl */ 802250661Sdavidcs uint32_t replenish_thresh = ha->hw.rds_pidx_thres; 803250661Sdavidcs 804250661Sdavidcs rdesc = &ha->hw.rds[r_idx]; 805250661Sdavidcs 806250661Sdavidcs rx_next = rdesc->rx_next; 807250661Sdavidcs 808250661Sdavidcs while (count--) { 809250661Sdavidcs rxb = sdsp->rxb_free; 810250661Sdavidcs 811250661Sdavidcs if (rxb == NULL) 812250661Sdavidcs break; 813250661Sdavidcs 814250661Sdavidcs sdsp->rxb_free = rxb->next; 815250661Sdavidcs sdsp->rx_free--; 816250661Sdavidcs 817250661Sdavidcs if (ql_get_mbuf(ha, rxb, NULL) == 0) { 818250661Sdavidcs qla_set_hw_rcv_desc(ha, r_idx, rdesc->rx_in, 819250661Sdavidcs rxb->handle, 820250661Sdavidcs rxb->paddr, (rxb->m_head)->m_pkthdr.len); 821250661Sdavidcs rdesc->rx_in++; 822250661Sdavidcs if (rdesc->rx_in == NUM_RX_DESCRIPTORS) 823250661Sdavidcs rdesc->rx_in = 0; 824250661Sdavidcs rdesc->rx_next++; 825250661Sdavidcs if (rdesc->rx_next == NUM_RX_DESCRIPTORS) 826250661Sdavidcs rdesc->rx_next = 0; 827250661Sdavidcs } else { 828250661Sdavidcs device_printf(ha->pci_dev, 829250661Sdavidcs "%s: ql_get_mbuf [0,(%d),(%d)] failed\n", 830250661Sdavidcs __func__, rdesc->rx_in, rxb->handle); 831250661Sdavidcs 832250661Sdavidcs rxb->m_head = NULL; 833250661Sdavidcs rxb->next = sdsp->rxb_free; 834250661Sdavidcs sdsp->rxb_free = rxb; 835250661Sdavidcs sdsp->rx_free++; 836250661Sdavidcs 837250661Sdavidcs break; 838250661Sdavidcs } 839250661Sdavidcs if (replenish_thresh-- == 0) { 840250661Sdavidcs QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std, 841250661Sdavidcs rdesc->rx_next); 842250661Sdavidcs rx_next = rdesc->rx_next; 843250661Sdavidcs replenish_thresh = ha->hw.rds_pidx_thres; 844250661Sdavidcs } 845250661Sdavidcs } 846250661Sdavidcs 847250661Sdavidcs if (rx_next != rdesc->rx_next) { 848250661Sdavidcs QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std, 849250661Sdavidcs rdesc->rx_next); 850250661Sdavidcs } 851250661Sdavidcs} 852250661Sdavidcs 853250661Sdavidcsvoid 854250661Sdavidcsql_isr(void *arg) 855250661Sdavidcs{ 856250661Sdavidcs qla_ivec_t *ivec = arg; 857250661Sdavidcs qla_host_t *ha ; 858250661Sdavidcs int idx; 859250661Sdavidcs qla_hw_t *hw; 860250661Sdavidcs struct ifnet *ifp; 861250661Sdavidcs uint32_t ret = 0; 862250661Sdavidcs 863250661Sdavidcs ha = ivec->ha; 864250661Sdavidcs hw = &ha->hw; 865250661Sdavidcs ifp = ha->ifp; 866250661Sdavidcs 867250661Sdavidcs if ((idx = ivec->sds_idx) >= ha->hw.num_sds_rings) 868250661Sdavidcs return; 869250661Sdavidcs 870250661Sdavidcs if (idx == 0) 871250661Sdavidcs taskqueue_enqueue(ha->tx_tq, &ha->tx_task); 872250661Sdavidcs 873251605Sdavidcs ret = qla_rcv_isr(ha, idx, -1); 874250661Sdavidcs 875250661Sdavidcs if (idx == 0) 876250661Sdavidcs taskqueue_enqueue(ha->tx_tq, &ha->tx_task); 877250661Sdavidcs 878250661Sdavidcs if (!ha->flags.stop_rcv) { 879250661Sdavidcs QL_ENABLE_INTERRUPTS(ha, idx); 880250661Sdavidcs } 881250661Sdavidcs return; 882250661Sdavidcs} 883250661Sdavidcs 884