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