The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/qlxgbe/ql_isr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2013-2016 Qlogic Corporation
    5  * All rights reserved.
    6  *
    7  *  Redistribution and use in source and binary forms, with or without
    8  *  modification, are permitted provided that the following conditions
    9  *  are met:
   10  *
   11  *  1. Redistributions of source code must retain the above copyright
   12  *     notice, this list of conditions and the following disclaimer.
   13  *  2. Redistributions in binary form must reproduce the above copyright
   14  *     notice, this list of conditions and the following disclaimer in the
   15  *     documentation and/or other materials provided with the distribution.
   16  *
   17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   18  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   21  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27  *  POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * File: ql_isr.c
   32  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD$");
   37 
   38 #include "ql_os.h"
   39 #include "ql_hw.h"
   40 #include "ql_def.h"
   41 #include "ql_inline.h"
   42 #include "ql_ver.h"
   43 #include "ql_glbl.h"
   44 #include "ql_dbg.h"
   45 
   46 static void qla_replenish_normal_rx(qla_host_t *ha, qla_sds_t *sdsp,
   47                 uint32_t r_idx);
   48 
   49 static void
   50 qla_rcv_error(qla_host_t *ha)
   51 {
   52         ha->stop_rcv = 1;
   53         QL_INITIATE_RECOVERY(ha);
   54 }
   55 
   56 /*
   57  * Name: qla_rx_intr
   58  * Function: Handles normal ethernet frames received
   59  */
   60 static void
   61 qla_rx_intr(qla_host_t *ha, qla_sgl_rcv_t *sgc, uint32_t sds_idx)
   62 {
   63         qla_rx_buf_t            *rxb;
   64         struct mbuf             *mp = NULL, *mpf = NULL, *mpl = NULL;
   65         struct ifnet            *ifp = ha->ifp;
   66         qla_sds_t               *sdsp;
   67         struct ether_vlan_header *eh;
   68         uint32_t                i, rem_len = 0;
   69         uint32_t                r_idx = 0;
   70         qla_rx_ring_t           *rx_ring;
   71 #if defined(INET) || defined(INET6)
   72         struct lro_ctrl         *lro;
   73 
   74         lro = &ha->hw.sds[sds_idx].lro;
   75 #endif
   76 
   77         if (ha->hw.num_rds_rings > 1)
   78                 r_idx = sds_idx;
   79 
   80         ha->hw.rds[r_idx].count++;
   81 
   82         sdsp = &ha->hw.sds[sds_idx];
   83         rx_ring = &ha->rx_ring[r_idx];
   84 
   85         for (i = 0; i < sgc->num_handles; i++) {
   86                 rxb = &rx_ring->rx_buf[sgc->handle[i] & 0x7FFF];
   87 
   88                 QL_ASSERT(ha, (rxb != NULL),
   89                         ("%s: [sds_idx]=[%d] rxb != NULL\n", __func__,\
   90                         sds_idx));
   91 
   92                 if ((rxb == NULL) || QL_ERR_INJECT(ha, INJCT_RX_RXB_INVAL)) {
   93                         /* log the error */
   94                         device_printf(ha->pci_dev,
   95                                 "%s invalid rxb[%d, %d, 0x%04x]\n",
   96                                 __func__, sds_idx, i, sgc->handle[i]);
   97                         qla_rcv_error(ha);
   98                         return;
   99                 }
  100 
  101                 mp = rxb->m_head;
  102                 if (i == 0) 
  103                         mpf = mp;
  104 
  105                 QL_ASSERT(ha, (mp != NULL),
  106                         ("%s: [sds_idx]=[%d] mp != NULL\n", __func__,\
  107                         sds_idx));
  108 
  109                 bus_dmamap_sync(ha->rx_tag, rxb->map, BUS_DMASYNC_POSTREAD);
  110 
  111                 rxb->m_head = NULL;
  112                 rxb->next = sdsp->rxb_free;
  113                 sdsp->rxb_free = rxb;
  114                 sdsp->rx_free++;
  115 
  116                 if ((mp == NULL) || QL_ERR_INJECT(ha, INJCT_RX_MP_NULL)) {
  117                         /* log the error */
  118                         device_printf(ha->pci_dev,
  119                                 "%s mp  == NULL [%d, %d, 0x%04x]\n",
  120                                 __func__, sds_idx, i, sgc->handle[i]);
  121                         qla_rcv_error(ha);
  122                         return;
  123                 }
  124 
  125                 if (i == 0) {
  126                         mpl = mpf = mp;
  127                         mp->m_flags |= M_PKTHDR;
  128                         mp->m_pkthdr.len = sgc->pkt_length;
  129                         mp->m_pkthdr.rcvif = ifp;
  130                         rem_len = mp->m_pkthdr.len;
  131                 } else {
  132                         mp->m_flags &= ~M_PKTHDR;
  133                         mpl->m_next = mp;
  134                         mpl = mp;
  135                         rem_len = rem_len - mp->m_len;
  136                 }
  137         }
  138 
  139         mpl->m_len = rem_len;
  140 
  141         eh = mtod(mpf, struct ether_vlan_header *);
  142 
  143         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
  144                 uint32_t *data = (uint32_t *)eh;
  145 
  146                 mpf->m_pkthdr.ether_vtag = ntohs(eh->evl_tag);
  147                 mpf->m_flags |= M_VLANTAG;
  148 
  149                 *(data + 3) = *(data + 2);
  150                 *(data + 2) = *(data + 1);
  151                 *(data + 1) = *data;
  152 
  153                 m_adj(mpf, ETHER_VLAN_ENCAP_LEN);
  154         }
  155 
  156         if (sgc->chksum_status == Q8_STAT_DESC_STATUS_CHKSUM_OK) {
  157                 mpf->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID |
  158                         CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
  159                 mpf->m_pkthdr.csum_data = 0xFFFF;
  160         } else {
  161                 mpf->m_pkthdr.csum_flags = 0;
  162         }
  163 
  164         if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
  165 
  166         mpf->m_pkthdr.flowid = sgc->rss_hash;
  167 
  168 #if __FreeBSD_version >= 1100000
  169         M_HASHTYPE_SET(mpf, M_HASHTYPE_OPAQUE_HASH);
  170 #else
  171 #if (__FreeBSD_version >= 903511 && __FreeBSD_version < 1100000) 
  172         M_HASHTYPE_SET(mpf, M_HASHTYPE_OPAQUE);
  173 #else
  174         M_HASHTYPE_SET(mpf, M_HASHTYPE_NONE);
  175 #endif
  176 #endif /* #if __FreeBSD_version >= 1100000 */
  177 
  178 #if defined(INET) || defined(INET6)
  179         if (ha->hw.enable_soft_lro) {
  180 #if (__FreeBSD_version >= 1100101)
  181 
  182                 tcp_lro_queue_mbuf(lro, mpf);
  183 
  184 #else
  185                 if (tcp_lro_rx(lro, mpf, 0))
  186                         (*ifp->if_input)(ifp, mpf);
  187 
  188 #endif /* #if (__FreeBSD_version >= 1100101) */
  189 
  190         } else
  191 #endif
  192         {
  193                 (*ifp->if_input)(ifp, mpf);
  194         }
  195 
  196         if (sdsp->rx_free > ha->std_replenish)
  197                 qla_replenish_normal_rx(ha, sdsp, r_idx);
  198 
  199         return;
  200 }
  201 
  202 #define QLA_TCP_HDR_SIZE        20
  203 #define QLA_TCP_TS_OPTION_SIZE  12
  204 
  205 /*
  206  * Name: qla_lro_intr
  207  * Function: Handles normal ethernet frames received
  208  */
  209 static int
  210 qla_lro_intr(qla_host_t *ha, qla_sgl_lro_t *sgc, uint32_t sds_idx)
  211 {
  212         qla_rx_buf_t *rxb;
  213         struct mbuf *mp = NULL, *mpf = NULL, *mpl = NULL;
  214         struct ifnet *ifp = ha->ifp;
  215         qla_sds_t *sdsp;
  216         struct ether_vlan_header *eh;
  217         uint32_t i, rem_len = 0, pkt_length, iplen;
  218         struct tcphdr *th;
  219         struct ip *ip = NULL;
  220         struct ip6_hdr *ip6 = NULL;
  221         uint16_t etype;
  222         uint32_t r_idx = 0;
  223         qla_rx_ring_t *rx_ring;
  224 
  225         if (ha->hw.num_rds_rings > 1)
  226                 r_idx = sds_idx;
  227 
  228         ha->hw.rds[r_idx].count++;
  229 
  230         rx_ring = &ha->rx_ring[r_idx];
  231 
  232         ha->hw.rds[r_idx].lro_pkt_count++;
  233 
  234         sdsp = &ha->hw.sds[sds_idx];
  235 
  236         pkt_length = sgc->payload_length + sgc->l4_offset;
  237 
  238         if (sgc->flags & Q8_LRO_COMP_TS) {
  239                 pkt_length += QLA_TCP_HDR_SIZE + QLA_TCP_TS_OPTION_SIZE;
  240         } else {
  241                 pkt_length += QLA_TCP_HDR_SIZE;
  242         }
  243         ha->hw.rds[r_idx].lro_bytes += pkt_length;
  244 
  245         for (i = 0; i < sgc->num_handles; i++) {
  246                 rxb = &rx_ring->rx_buf[sgc->handle[i] & 0x7FFF];
  247 
  248                 QL_ASSERT(ha, (rxb != NULL),
  249                         ("%s: [sds_idx]=[%d] rxb != NULL\n", __func__,\
  250                         sds_idx));
  251 
  252                 if ((rxb == NULL) || QL_ERR_INJECT(ha, INJCT_LRO_RXB_INVAL)) {
  253                         /* log the error */
  254                         device_printf(ha->pci_dev,
  255                                 "%s invalid rxb[%d, %d, 0x%04x]\n",
  256                                 __func__, sds_idx, i, sgc->handle[i]);
  257                         qla_rcv_error(ha);
  258                         return (0);
  259                 }
  260 
  261                 mp = rxb->m_head;
  262                 if (i == 0) 
  263                         mpf = mp;
  264 
  265                 QL_ASSERT(ha, (mp != NULL),
  266                         ("%s: [sds_idx]=[%d] mp != NULL\n", __func__,\
  267                         sds_idx));
  268 
  269                 bus_dmamap_sync(ha->rx_tag, rxb->map, BUS_DMASYNC_POSTREAD);
  270 
  271                 rxb->m_head = NULL;
  272                 rxb->next = sdsp->rxb_free;
  273                 sdsp->rxb_free = rxb;
  274                 sdsp->rx_free++;
  275 
  276                 if ((mp == NULL) || QL_ERR_INJECT(ha, INJCT_LRO_MP_NULL)) {
  277                         /* log the error */
  278                         device_printf(ha->pci_dev,
  279                                 "%s mp  == NULL [%d, %d, 0x%04x]\n",
  280                                 __func__, sds_idx, i, sgc->handle[i]);
  281                         qla_rcv_error(ha);
  282                         return (0);
  283                 }
  284 
  285                 if (i == 0) {
  286                         mpl = mpf = mp;
  287                         mp->m_flags |= M_PKTHDR;
  288                         mp->m_pkthdr.len = pkt_length;
  289                         mp->m_pkthdr.rcvif = ifp;
  290                         rem_len = mp->m_pkthdr.len;
  291                 } else {
  292                         mp->m_flags &= ~M_PKTHDR;
  293                         mpl->m_next = mp;
  294                         mpl = mp;
  295                         rem_len = rem_len - mp->m_len;
  296                 }
  297         }
  298 
  299         mpl->m_len = rem_len;
  300 
  301         th = (struct tcphdr *)(mpf->m_data + sgc->l4_offset);
  302 
  303         if (sgc->flags & Q8_LRO_COMP_PUSH_BIT)
  304                 th->th_flags |= TH_PUSH;
  305 
  306         m_adj(mpf, sgc->l2_offset);
  307 
  308         eh = mtod(mpf, struct ether_vlan_header *);
  309 
  310         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
  311                 uint32_t *data = (uint32_t *)eh;
  312 
  313                 mpf->m_pkthdr.ether_vtag = ntohs(eh->evl_tag);
  314                 mpf->m_flags |= M_VLANTAG;
  315 
  316                 *(data + 3) = *(data + 2);
  317                 *(data + 2) = *(data + 1);
  318                 *(data + 1) = *data;
  319 
  320                 m_adj(mpf, ETHER_VLAN_ENCAP_LEN);
  321 
  322                 etype = ntohs(eh->evl_proto);
  323         } else {
  324                 etype = ntohs(eh->evl_encap_proto);
  325         }
  326 
  327         if (etype == ETHERTYPE_IP) {
  328                 ip = (struct ip *)(mpf->m_data + ETHER_HDR_LEN);
  329 
  330                 iplen = (ip->ip_hl << 2) + (th->th_off << 2) +
  331                                 sgc->payload_length;
  332 
  333                 ip->ip_len = htons(iplen);
  334 
  335                 ha->ipv4_lro++;
  336 
  337                 M_HASHTYPE_SET(mpf, M_HASHTYPE_RSS_TCP_IPV4);
  338 
  339         } else if (etype == ETHERTYPE_IPV6) {
  340                 ip6 = (struct ip6_hdr *)(mpf->m_data + ETHER_HDR_LEN);
  341 
  342                 iplen = (th->th_off << 2) + sgc->payload_length;
  343 
  344                 ip6->ip6_plen = htons(iplen);
  345 
  346                 ha->ipv6_lro++;
  347 
  348                 M_HASHTYPE_SET(mpf, M_HASHTYPE_RSS_TCP_IPV6);
  349 
  350         } else {
  351                 m_freem(mpf);
  352 
  353                 if (sdsp->rx_free > ha->std_replenish)
  354                         qla_replenish_normal_rx(ha, sdsp, r_idx);
  355                 return 0;
  356         }
  357 
  358         mpf->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID |
  359                                         CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
  360         mpf->m_pkthdr.csum_data = 0xFFFF;
  361 
  362         mpf->m_pkthdr.flowid = sgc->rss_hash;
  363 
  364         if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
  365 
  366         (*ifp->if_input)(ifp, mpf);
  367 
  368         if (sdsp->rx_free > ha->std_replenish)
  369                 qla_replenish_normal_rx(ha, sdsp, r_idx);
  370 
  371         return (0);
  372 }
  373 
  374 static int
  375 qla_rcv_cont_sds(qla_host_t *ha, uint32_t sds_idx, uint32_t comp_idx,
  376         uint32_t dcount, uint16_t *handle, uint16_t *nhandles)
  377 {
  378         uint32_t i;
  379         uint16_t num_handles;
  380         q80_stat_desc_t *sdesc;
  381         uint32_t opcode;
  382 
  383         *nhandles = 0;
  384         dcount--;
  385 
  386         for (i = 0; i < dcount; i++) {
  387                 comp_idx = (comp_idx + 1) & (NUM_STATUS_DESCRIPTORS-1);
  388                 sdesc = (q80_stat_desc_t *)
  389                                 &ha->hw.sds[sds_idx].sds_ring_base[comp_idx];
  390 
  391                 opcode = Q8_STAT_DESC_OPCODE((sdesc->data[1]));
  392 
  393                 if (!opcode || QL_ERR_INJECT(ha, INJCT_INV_CONT_OPCODE)) {
  394                         device_printf(ha->pci_dev, "%s: opcode=0 %p %p\n",
  395                                 __func__, (void *)sdesc->data[0],
  396                                 (void *)sdesc->data[1]);
  397                         return -1;
  398                 }
  399 
  400                 num_handles = Q8_SGL_STAT_DESC_NUM_HANDLES((sdesc->data[1]));
  401                 if (!num_handles) {
  402                         device_printf(ha->pci_dev, "%s: opcode=0 %p %p\n",
  403                                 __func__, (void *)sdesc->data[0],
  404                                 (void *)sdesc->data[1]);
  405                         return -1;
  406                 }
  407 
  408                 if (QL_ERR_INJECT(ha, INJCT_NUM_HNDLE_INVALID))
  409                         num_handles = -1;
  410 
  411                 switch (num_handles) {
  412                 case 1:
  413                         *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0]));
  414                         break;
  415 
  416                 case 2:
  417                         *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0]));
  418                         *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0]));
  419                         break;
  420 
  421                 case 3:
  422                         *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0]));
  423                         *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0]));
  424                         *handle++ = Q8_SGL_STAT_DESC_HANDLE3((sdesc->data[0]));
  425                         break;
  426 
  427                 case 4:
  428                         *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0]));
  429                         *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0]));
  430                         *handle++ = Q8_SGL_STAT_DESC_HANDLE3((sdesc->data[0]));
  431                         *handle++ = Q8_SGL_STAT_DESC_HANDLE4((sdesc->data[0]));
  432                         break;
  433 
  434                 case 5:
  435                         *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0]));
  436                         *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0]));
  437                         *handle++ = Q8_SGL_STAT_DESC_HANDLE3((sdesc->data[0]));
  438                         *handle++ = Q8_SGL_STAT_DESC_HANDLE4((sdesc->data[0]));
  439                         *handle++ = Q8_SGL_STAT_DESC_HANDLE5((sdesc->data[1]));
  440                         break;
  441 
  442                 case 6:
  443                         *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0]));
  444                         *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0]));
  445                         *handle++ = Q8_SGL_STAT_DESC_HANDLE3((sdesc->data[0]));
  446                         *handle++ = Q8_SGL_STAT_DESC_HANDLE4((sdesc->data[0]));
  447                         *handle++ = Q8_SGL_STAT_DESC_HANDLE5((sdesc->data[1]));
  448                         *handle++ = Q8_SGL_STAT_DESC_HANDLE6((sdesc->data[1]));
  449                         break;
  450 
  451                 case 7:
  452                         *handle++ = Q8_SGL_STAT_DESC_HANDLE1((sdesc->data[0]));
  453                         *handle++ = Q8_SGL_STAT_DESC_HANDLE2((sdesc->data[0]));
  454                         *handle++ = Q8_SGL_STAT_DESC_HANDLE3((sdesc->data[0]));
  455                         *handle++ = Q8_SGL_STAT_DESC_HANDLE4((sdesc->data[0]));
  456                         *handle++ = Q8_SGL_STAT_DESC_HANDLE5((sdesc->data[1]));
  457                         *handle++ = Q8_SGL_STAT_DESC_HANDLE6((sdesc->data[1]));
  458                         *handle++ = Q8_SGL_STAT_DESC_HANDLE7((sdesc->data[1]));
  459                         break;
  460 
  461                 default:
  462                         device_printf(ha->pci_dev,
  463                                 "%s: invalid num handles %p %p\n",
  464                                 __func__, (void *)sdesc->data[0],
  465                                 (void *)sdesc->data[1]);
  466 
  467                         QL_ASSERT(ha, (0),\
  468                         ("%s: %s [nh, sds, d0, d1]=[%d, %d, %p, %p]\n",
  469                         __func__, "invalid num handles", sds_idx, num_handles,
  470                         (void *)sdesc->data[0],(void *)sdesc->data[1]));
  471 
  472                         qla_rcv_error(ha);
  473                         return 0;
  474                 }
  475                 *nhandles = *nhandles + num_handles;
  476         }
  477         return 0;
  478 }
  479 
  480 /*
  481  * Name: ql_rcv_isr
  482  * Function: Main Interrupt Service Routine
  483  */
  484 uint32_t
  485 ql_rcv_isr(qla_host_t *ha, uint32_t sds_idx, uint32_t count)
  486 {
  487         device_t dev;
  488         qla_hw_t *hw;
  489         uint32_t comp_idx, c_idx = 0, desc_count = 0, opcode;
  490         volatile q80_stat_desc_t *sdesc, *sdesc0 = NULL;
  491         uint32_t ret = 0;
  492         qla_sgl_comp_t sgc;
  493         uint16_t nhandles;
  494         uint32_t sds_replenish_threshold = 0;
  495         uint32_t r_idx = 0;
  496         qla_sds_t *sdsp;
  497 
  498         dev = ha->pci_dev;
  499         hw = &ha->hw;
  500 
  501         hw->sds[sds_idx].rcv_active = 1;
  502         if (ha->stop_rcv) {
  503                 hw->sds[sds_idx].rcv_active = 0;
  504                 return 0;
  505         }
  506 
  507         QL_DPRINT2(ha, (dev, "%s: [%d]enter\n", __func__, sds_idx));
  508 
  509         /*
  510          * receive interrupts
  511          */
  512         comp_idx = hw->sds[sds_idx].sdsr_next;
  513 
  514         while (count-- && !ha->stop_rcv) {
  515                 sdesc = (q80_stat_desc_t *)
  516                                 &hw->sds[sds_idx].sds_ring_base[comp_idx];
  517 
  518                 opcode = Q8_STAT_DESC_OPCODE((sdesc->data[1]));
  519 
  520                 if (!opcode)
  521                         break;
  522 
  523                 switch (opcode) {
  524                 case Q8_STAT_DESC_OPCODE_RCV_PKT:
  525 
  526                         desc_count = 1;
  527 
  528                         bzero(&sgc, sizeof(qla_sgl_comp_t));
  529 
  530                         sgc.rcv.pkt_length =
  531                                 Q8_STAT_DESC_TOTAL_LENGTH((sdesc->data[0]));
  532                         sgc.rcv.num_handles = 1;
  533                         sgc.rcv.handle[0] =
  534                                 Q8_STAT_DESC_HANDLE((sdesc->data[0]));
  535                         sgc.rcv.chksum_status =
  536                                 Q8_STAT_DESC_STATUS((sdesc->data[1]));
  537 
  538                         sgc.rcv.rss_hash =
  539                                 Q8_STAT_DESC_RSS_HASH((sdesc->data[0]));
  540 
  541                         if (Q8_STAT_DESC_VLAN((sdesc->data[1]))) {
  542                                 sgc.rcv.vlan_tag =
  543                                         Q8_STAT_DESC_VLAN_ID((sdesc->data[1]));
  544                         }
  545                         qla_rx_intr(ha, &sgc.rcv, sds_idx);
  546                         break;
  547 
  548                 case Q8_STAT_DESC_OPCODE_SGL_RCV:
  549 
  550                         desc_count =
  551                                 Q8_STAT_DESC_COUNT_SGL_RCV((sdesc->data[1]));
  552 
  553                         if (desc_count > 1) {
  554                                 c_idx = (comp_idx + desc_count -1) &
  555                                                 (NUM_STATUS_DESCRIPTORS-1);
  556                                 sdesc0 = (q80_stat_desc_t *)
  557                                         &hw->sds[sds_idx].sds_ring_base[c_idx];
  558 
  559                                 if ((Q8_STAT_DESC_OPCODE((sdesc0->data[1])) !=
  560                                                 Q8_STAT_DESC_OPCODE_CONT) ||
  561                                 QL_ERR_INJECT(ha, INJCT_SGL_RCV_INV_DESC_COUNT)) {
  562                                         desc_count = 0;
  563                                         break;
  564                                 }
  565                         }
  566 
  567                         bzero(&sgc, sizeof(qla_sgl_comp_t));
  568 
  569                         sgc.rcv.pkt_length =
  570                                 Q8_STAT_DESC_TOTAL_LENGTH_SGL_RCV(\
  571                                         (sdesc->data[0]));
  572                         sgc.rcv.chksum_status =
  573                                 Q8_STAT_DESC_STATUS((sdesc->data[1]));
  574 
  575                         sgc.rcv.rss_hash =
  576                                 Q8_STAT_DESC_RSS_HASH((sdesc->data[0]));
  577 
  578                         if (Q8_STAT_DESC_VLAN((sdesc->data[1]))) {
  579                                 sgc.rcv.vlan_tag =
  580                                         Q8_STAT_DESC_VLAN_ID((sdesc->data[1]));
  581                         }
  582 
  583                         QL_ASSERT(ha, (desc_count <= 2) ,\
  584                                 ("%s: [sds_idx, data0, data1]="\
  585                                 "%d, %p, %p]\n", __func__, sds_idx,\
  586                                 (void *)sdesc->data[0],\
  587                                 (void *)sdesc->data[1]));
  588 
  589                         sgc.rcv.num_handles = 1;
  590                         sgc.rcv.handle[0] = 
  591                                 Q8_STAT_DESC_HANDLE((sdesc->data[0]));
  592                         
  593                         if (qla_rcv_cont_sds(ha, sds_idx, comp_idx, desc_count,
  594                                 &sgc.rcv.handle[1], &nhandles)) {
  595                                 device_printf(dev,
  596                                         "%s: [sds_idx, dcount, data0, data1]="
  597                                          "[%d, %d, 0x%llx, 0x%llx]\n",
  598                                         __func__, sds_idx, desc_count,
  599                                         (long long unsigned int)sdesc->data[0],
  600                                         (long long unsigned int)sdesc->data[1]);
  601                                 desc_count = 0;
  602                                 break;  
  603                         }
  604 
  605                         sgc.rcv.num_handles += nhandles;
  606 
  607                         qla_rx_intr(ha, &sgc.rcv, sds_idx);
  608                         
  609                         break;
  610 
  611                 case Q8_STAT_DESC_OPCODE_SGL_LRO:
  612 
  613                         desc_count =
  614                                 Q8_STAT_DESC_COUNT_SGL_LRO((sdesc->data[1]));
  615 
  616                         if (desc_count > 1) {
  617                                 c_idx = (comp_idx + desc_count -1) &
  618                                                 (NUM_STATUS_DESCRIPTORS-1);
  619                                 sdesc0 = (q80_stat_desc_t *)
  620                                         &hw->sds[sds_idx].sds_ring_base[c_idx];
  621 
  622                                 if ((Q8_STAT_DESC_OPCODE((sdesc0->data[1])) !=
  623                                                 Q8_STAT_DESC_OPCODE_CONT) ||
  624                                 QL_ERR_INJECT(ha, INJCT_SGL_LRO_INV_DESC_COUNT)) {
  625                                         desc_count = 0;
  626                                         break;
  627                                 }
  628                         }
  629                         bzero(&sgc, sizeof(qla_sgl_comp_t));
  630 
  631                         sgc.lro.payload_length =
  632                         Q8_STAT_DESC_TOTAL_LENGTH_SGL_RCV((sdesc->data[0]));
  633                                 
  634                         sgc.lro.rss_hash =
  635                                 Q8_STAT_DESC_RSS_HASH((sdesc->data[0]));
  636                         
  637                         sgc.lro.num_handles = 1;
  638                         sgc.lro.handle[0] =
  639                                 Q8_STAT_DESC_HANDLE((sdesc->data[0]));
  640 
  641                         if (Q8_SGL_LRO_STAT_TS((sdesc->data[1])))
  642                                 sgc.lro.flags |= Q8_LRO_COMP_TS;
  643 
  644                         if (Q8_SGL_LRO_STAT_PUSH_BIT((sdesc->data[1])))
  645                                 sgc.lro.flags |= Q8_LRO_COMP_PUSH_BIT;
  646 
  647                         sgc.lro.l2_offset =
  648                                 Q8_SGL_LRO_STAT_L2_OFFSET((sdesc->data[1]));
  649                         sgc.lro.l4_offset =
  650                                 Q8_SGL_LRO_STAT_L4_OFFSET((sdesc->data[1]));
  651 
  652                         if (Q8_STAT_DESC_VLAN((sdesc->data[1]))) {
  653                                 sgc.lro.vlan_tag =
  654                                         Q8_STAT_DESC_VLAN_ID((sdesc->data[1]));
  655                         }
  656 
  657                         QL_ASSERT(ha, (desc_count <= 7) ,\
  658                                 ("%s: [sds_idx, data0, data1]="\
  659                                  "[%d, 0x%llx, 0x%llx]\n",\
  660                                 __func__, sds_idx,\
  661                                 (long long unsigned int)sdesc->data[0],\
  662                                 (long long unsigned int)sdesc->data[1]));
  663                                 
  664                         if (qla_rcv_cont_sds(ha, sds_idx, comp_idx, 
  665                                 desc_count, &sgc.lro.handle[1], &nhandles)) {
  666                                 device_printf(dev,
  667                                 "%s: [sds_idx, data0, data1]="\
  668                                  "[%d, 0x%llx, 0x%llx]\n",\
  669                                 __func__, sds_idx,\
  670                                 (long long unsigned int)sdesc->data[0],\
  671                                 (long long unsigned int)sdesc->data[1]);
  672 
  673                                 desc_count = 0;
  674                                 break;  
  675                         }
  676 
  677                         sgc.lro.num_handles += nhandles;
  678 
  679                         if (qla_lro_intr(ha, &sgc.lro, sds_idx)) {
  680                                 device_printf(dev,
  681                                 "%s: [sds_idx, data0, data1]="\
  682                                  "[%d, 0x%llx, 0x%llx]\n",\
  683                                 __func__, sds_idx,\
  684                                 (long long unsigned int)sdesc->data[0],\
  685                                 (long long unsigned int)sdesc->data[1]);
  686                                 device_printf(dev,
  687                                 "%s: [comp_idx, c_idx, dcount, nhndls]="\
  688                                  "[%d, %d, %d, %d]\n",\
  689                                 __func__, comp_idx, c_idx, desc_count,
  690                                 sgc.lro.num_handles);
  691                                 if (desc_count > 1) {
  692                                 device_printf(dev,
  693                                 "%s: [sds_idx, data0, data1]="\
  694                                  "[%d, 0x%llx, 0x%llx]\n",\
  695                                 __func__, sds_idx,\
  696                                 (long long unsigned int)sdesc0->data[0],\
  697                                 (long long unsigned int)sdesc0->data[1]);
  698                                 }
  699                         }
  700                         
  701                         break;
  702 
  703                 default:
  704                         desc_count = 0;
  705                         device_printf(dev, "%s: default 0x%llx!\n", __func__,
  706                                         (long long unsigned int)sdesc->data[0]);
  707                         break;
  708                 }
  709 
  710                 if (desc_count == 0)
  711                         break;
  712 
  713                 sds_replenish_threshold += desc_count;
  714 
  715                 while (desc_count--) {
  716                         sdesc->data[0] = 0ULL;
  717                         sdesc->data[1] = 0ULL;
  718                         comp_idx = (comp_idx + 1) & (NUM_STATUS_DESCRIPTORS-1);
  719                         sdesc = (q80_stat_desc_t *)
  720                                 &hw->sds[sds_idx].sds_ring_base[comp_idx];
  721                 }
  722 
  723                 if (sds_replenish_threshold > ha->hw.sds_cidx_thres) {
  724                         sds_replenish_threshold = 0;
  725                         if (hw->sds[sds_idx].sdsr_next != comp_idx) {
  726                                 QL_UPDATE_SDS_CONSUMER_INDEX(ha, sds_idx,\
  727                                         comp_idx);
  728                         }
  729                         hw->sds[sds_idx].sdsr_next = comp_idx;
  730                 }
  731         }
  732 
  733 #if defined(INET) || defined(INET6)
  734         if (ha->hw.enable_soft_lro) {
  735                 struct lro_ctrl         *lro;
  736 
  737                 lro = &ha->hw.sds[sds_idx].lro;
  738 
  739 #if (__FreeBSD_version >= 1100101)
  740 
  741                 tcp_lro_flush_all(lro);
  742 
  743 #else
  744                 struct lro_entry *queued;
  745 
  746                 while ((!SLIST_EMPTY(&lro->lro_active))) {
  747                         queued = SLIST_FIRST(&lro->lro_active);
  748                         SLIST_REMOVE_HEAD(&lro->lro_active, next);
  749                         tcp_lro_flush(lro, queued);
  750                 }
  751 
  752 #endif /* #if (__FreeBSD_version >= 1100101) */
  753         }
  754 #endif
  755 
  756         if (ha->stop_rcv)
  757                 goto ql_rcv_isr_exit;
  758 
  759         if (hw->sds[sds_idx].sdsr_next != comp_idx) {
  760                 QL_UPDATE_SDS_CONSUMER_INDEX(ha, sds_idx, comp_idx);
  761                 hw->sds[sds_idx].sdsr_next = comp_idx;
  762         } else {
  763                 if (ha->hw.num_rds_rings > 1)
  764                         r_idx = sds_idx;
  765 
  766                 sdsp = &ha->hw.sds[sds_idx];
  767 
  768                 if (sdsp->rx_free > ha->std_replenish)
  769                         qla_replenish_normal_rx(ha, sdsp, r_idx);
  770         }
  771 
  772         sdesc = (q80_stat_desc_t *)&hw->sds[sds_idx].sds_ring_base[comp_idx];
  773         opcode = Q8_STAT_DESC_OPCODE((sdesc->data[1]));
  774 
  775         if (opcode)
  776                 ret = -1;
  777 
  778 ql_rcv_isr_exit:
  779         hw->sds[sds_idx].rcv_active = 0;
  780 
  781         return (ret);
  782 }
  783 
  784 void
  785 ql_mbx_isr(void *arg)
  786 {
  787         qla_host_t *ha;
  788         uint32_t data;
  789         uint32_t prev_link_state;
  790 
  791         ha = arg;
  792 
  793         if (ha == NULL) {
  794                 printf("%s: arg == NULL\n", __func__);
  795                 return;
  796         }
  797 
  798         data = READ_REG32(ha, Q8_FW_MBOX_CNTRL);
  799         if ((data & 0x3) != 0x1) {
  800                 WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0);
  801                 return;
  802         }
  803 
  804         data = READ_REG32(ha, Q8_FW_MBOX0);
  805 
  806         if ((data & 0xF000) != 0x8000)
  807                 return;
  808 
  809         data = data & 0xFFFF;
  810 
  811         switch (data) {
  812         case 0x8001:  /* It's an AEN */
  813                 
  814                 ha->hw.cable_oui = READ_REG32(ha, (Q8_FW_MBOX0 + 4));
  815 
  816                 data = READ_REG32(ha, (Q8_FW_MBOX0 + 8));
  817                 ha->hw.cable_length = data & 0xFFFF;
  818 
  819                 data = data >> 16;
  820                 ha->hw.link_speed = data & 0xFFF;
  821 
  822                 data = READ_REG32(ha, (Q8_FW_MBOX0 + 12));
  823 
  824                 prev_link_state =  ha->hw.link_up;
  825 
  826                 data = (((data & 0xFF) == 0) ? 0 : 1);
  827                 atomic_store_rel_8(&ha->hw.link_up, (uint8_t)data);
  828 
  829                 device_printf(ha->pci_dev,
  830                         "%s: AEN[0x8001] data = 0x%08x, prev_link_state = 0x%08x\n",
  831                         __func__, data, prev_link_state);
  832 
  833                 if (prev_link_state !=  ha->hw.link_up) {
  834                         if (ha->hw.link_up)
  835                                 if_link_state_change(ha->ifp, LINK_STATE_UP);
  836                         else
  837                                 if_link_state_change(ha->ifp, LINK_STATE_DOWN);
  838                 }
  839 
  840                 ha->hw.module_type = ((data >> 8) & 0xFF);
  841                 ha->hw.fduplex = (((data & 0xFF0000) == 0) ? 0 : 1);
  842                 ha->hw.autoneg = (((data & 0xFF000000) == 0) ? 0 : 1);
  843                 
  844                 data = READ_REG32(ha, (Q8_FW_MBOX0 + 16));
  845                 ha->hw.loopback_mode = data & 0x03;
  846 
  847                 ha->hw.link_faults = (data >> 3) & 0xFF;
  848 
  849                 break;
  850 
  851         case 0x8100:
  852                 device_printf(ha->pci_dev, "%s: AEN[0x%08x]\n", __func__, data);
  853                 ha->hw.imd_compl=1;
  854                 break;
  855 
  856         case 0x8101:
  857                 ha->async_event = 1;
  858                 ha->hw.aen_mb0 = 0x8101;
  859                 ha->hw.aen_mb1 = READ_REG32(ha, (Q8_FW_MBOX0 + 4));
  860                 ha->hw.aen_mb2 = READ_REG32(ha, (Q8_FW_MBOX0 + 8));
  861                 ha->hw.aen_mb3 = READ_REG32(ha, (Q8_FW_MBOX0 + 12));
  862                 ha->hw.aen_mb4 = READ_REG32(ha, (Q8_FW_MBOX0 + 16));
  863                 device_printf(ha->pci_dev, "%s: AEN[0x%08x 0x%08x 0x%08x 0%08x 0x%08x]\n",
  864                         __func__, data, ha->hw.aen_mb1, ha->hw.aen_mb2,
  865                         ha->hw.aen_mb3, ha->hw.aen_mb4);
  866                 break;
  867 
  868         case 0x8110:
  869                 /* for now just dump the registers */
  870                 {
  871                         uint32_t ombx[5];
  872 
  873                         ombx[0] = READ_REG32(ha, (Q8_FW_MBOX0 + 4));
  874                         ombx[1] = READ_REG32(ha, (Q8_FW_MBOX0 + 8));
  875                         ombx[2] = READ_REG32(ha, (Q8_FW_MBOX0 + 12));
  876                         ombx[3] = READ_REG32(ha, (Q8_FW_MBOX0 + 16));
  877                         ombx[4] = READ_REG32(ha, (Q8_FW_MBOX0 + 20));
  878 
  879                         device_printf(ha->pci_dev, "%s: "
  880                                 "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
  881                                 __func__, data, ombx[0], ombx[1], ombx[2],
  882                                 ombx[3], ombx[4]);
  883                 }
  884 
  885                 break;
  886 
  887         case 0x8130:
  888                 /* sfp insertion aen */
  889                 device_printf(ha->pci_dev, "%s: sfp inserted [0x%08x]\n",
  890                         __func__, READ_REG32(ha, (Q8_FW_MBOX0 + 4)));
  891                 break;
  892 
  893         case 0x8131:
  894                 /* sfp removal aen */
  895                 device_printf(ha->pci_dev, "%s: sfp removed]\n", __func__);
  896                 break;
  897 
  898         case 0x8140:
  899                 {
  900                         uint32_t ombx[3];
  901 
  902                         ombx[0] = READ_REG32(ha, (Q8_FW_MBOX0 + 4));
  903                         ombx[1] = READ_REG32(ha, (Q8_FW_MBOX0 + 8));
  904                         ombx[2] = READ_REG32(ha, (Q8_FW_MBOX0 + 12));
  905 
  906                         device_printf(ha->pci_dev, "%s: "
  907                                 "0x%08x 0x%08x 0x%08x 0x%08x \n",
  908                                 __func__, data, ombx[0], ombx[1], ombx[2]);
  909                 }
  910                 break;
  911 
  912         default:
  913                 device_printf(ha->pci_dev, "%s: AEN[0x%08x]\n", __func__, data);
  914                 break;
  915         }
  916         WRITE_REG32(ha, Q8_FW_MBOX_CNTRL, 0x0);
  917         WRITE_REG32(ha, ha->hw.mbx_intr_mask_offset, 0x0);
  918         return;
  919 }
  920 
  921 static void
  922 qla_replenish_normal_rx(qla_host_t *ha, qla_sds_t *sdsp, uint32_t r_idx)
  923 {
  924         qla_rx_buf_t *rxb;
  925         int count = sdsp->rx_free;
  926         uint32_t rx_next;
  927         qla_rdesc_t *rdesc;
  928 
  929         /* we can play with this value via a sysctl */
  930         uint32_t replenish_thresh = ha->hw.rds_pidx_thres;
  931 
  932         rdesc = &ha->hw.rds[r_idx];
  933 
  934         rx_next = rdesc->rx_next;
  935 
  936         while (count--) {
  937                 rxb = sdsp->rxb_free;
  938 
  939                 if (rxb == NULL)
  940                         break;
  941 
  942                 sdsp->rxb_free = rxb->next;
  943                 sdsp->rx_free--;
  944 
  945                 if (ql_get_mbuf(ha, rxb, NULL) == 0) {
  946                         qla_set_hw_rcv_desc(ha, r_idx, rdesc->rx_in,
  947                                 rxb->handle,
  948                                 rxb->paddr, (rxb->m_head)->m_pkthdr.len);
  949                         rdesc->rx_in++;
  950                         if (rdesc->rx_in == NUM_RX_DESCRIPTORS)
  951                                 rdesc->rx_in = 0;
  952                         rdesc->rx_next++;
  953                         if (rdesc->rx_next == NUM_RX_DESCRIPTORS)
  954                                 rdesc->rx_next = 0;
  955                 } else {
  956                         device_printf(ha->pci_dev,
  957                                 "%s: qla_get_mbuf [(%d),(%d),(%d)] failed\n",
  958                                 __func__, r_idx, rdesc->rx_in, rxb->handle);
  959 
  960                         rxb->m_head = NULL;
  961                         rxb->next = sdsp->rxb_free;
  962                         sdsp->rxb_free = rxb;
  963                         sdsp->rx_free++;
  964 
  965                         break;
  966                 }
  967                 if (replenish_thresh-- == 0) {
  968                         QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,
  969                                 rdesc->rx_next);
  970                         rx_next = rdesc->rx_next;
  971                         replenish_thresh = ha->hw.rds_pidx_thres;
  972                 }
  973         }
  974 
  975         if (rx_next != rdesc->rx_next) {
  976                 QL_UPDATE_RDS_PRODUCER_INDEX(ha, rdesc->prod_std,
  977                         rdesc->rx_next);
  978         }
  979 }
  980 
  981 void
  982 ql_isr(void *arg)
  983 {
  984         qla_ivec_t *ivec = arg;
  985         qla_host_t *ha ;
  986         int idx;
  987         qla_hw_t *hw;
  988         struct ifnet *ifp;
  989         qla_tx_fp_t *fp;
  990 
  991         ha = ivec->ha;
  992         hw = &ha->hw;
  993         ifp = ha->ifp;
  994 
  995         if ((idx = ivec->sds_idx) >= ha->hw.num_sds_rings)
  996                 return;
  997 
  998         fp = &ha->tx_fp[idx];
  999         hw->sds[idx].intr_count++;
 1000 
 1001         if ((fp->fp_taskqueue != NULL) &&
 1002                 (ifp->if_drv_flags & IFF_DRV_RUNNING))
 1003                 taskqueue_enqueue(fp->fp_taskqueue, &fp->fp_task);
 1004 
 1005         return;
 1006 }

Cache object: 657db2ec90ca82649b75573f0fab489a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.