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