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