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