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