1718cf2ccSPedro F. Giffuni /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
4711bcba0SDavid C Somayajulu * Copyright (c) 2013-2014 Qlogic Corporation
5711bcba0SDavid C Somayajulu * All rights reserved.
6711bcba0SDavid C Somayajulu *
7711bcba0SDavid C Somayajulu * Redistribution and use in source and binary forms, with or without
8711bcba0SDavid C Somayajulu * modification, are permitted provided that the following conditions
9711bcba0SDavid C Somayajulu * are met:
10711bcba0SDavid C Somayajulu *
11711bcba0SDavid C Somayajulu * 1. Redistributions of source code must retain the above copyright
12711bcba0SDavid C Somayajulu * notice, this list of conditions and the following disclaimer.
13711bcba0SDavid C Somayajulu * 2. Redistributions in binary form must reproduce the above copyright
14711bcba0SDavid C Somayajulu * notice, this list of conditions and the following disclaimer in the
15711bcba0SDavid C Somayajulu * documentation and/or other materials provided with the distribution.
16711bcba0SDavid C Somayajulu *
17711bcba0SDavid C Somayajulu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18711bcba0SDavid C Somayajulu * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19711bcba0SDavid C Somayajulu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20711bcba0SDavid C Somayajulu * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21711bcba0SDavid C Somayajulu * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22711bcba0SDavid C Somayajulu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23711bcba0SDavid C Somayajulu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24711bcba0SDavid C Somayajulu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25711bcba0SDavid C Somayajulu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26711bcba0SDavid C Somayajulu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27711bcba0SDavid C Somayajulu * POSSIBILITY OF SUCH DAMAGE.
28711bcba0SDavid C Somayajulu */
29711bcba0SDavid C Somayajulu
30711bcba0SDavid C Somayajulu /*
31711bcba0SDavid C Somayajulu * File: qls_isr.c
32711bcba0SDavid C Somayajulu * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
33711bcba0SDavid C Somayajulu */
34711bcba0SDavid C Somayajulu #include <sys/cdefs.h>
35711bcba0SDavid C Somayajulu #include "qls_os.h"
36711bcba0SDavid C Somayajulu #include "qls_hw.h"
37711bcba0SDavid C Somayajulu #include "qls_def.h"
38711bcba0SDavid C Somayajulu #include "qls_inline.h"
39711bcba0SDavid C Somayajulu #include "qls_ver.h"
40711bcba0SDavid C Somayajulu #include "qls_glbl.h"
41711bcba0SDavid C Somayajulu #include "qls_dbg.h"
42711bcba0SDavid C Somayajulu
43711bcba0SDavid C Somayajulu static void
qls_tx_comp(qla_host_t * ha,uint32_t txr_idx,q81_tx_mac_comp_t * tx_comp)44711bcba0SDavid C Somayajulu qls_tx_comp(qla_host_t *ha, uint32_t txr_idx, q81_tx_mac_comp_t *tx_comp)
45711bcba0SDavid C Somayajulu {
46711bcba0SDavid C Somayajulu qla_tx_buf_t *txb;
47711bcba0SDavid C Somayajulu uint32_t tx_idx = tx_comp->tid_lo;
48711bcba0SDavid C Somayajulu
49711bcba0SDavid C Somayajulu if (tx_idx >= NUM_TX_DESCRIPTORS) {
50711bcba0SDavid C Somayajulu ha->qla_initiate_recovery = 1;
51711bcba0SDavid C Somayajulu return;
52711bcba0SDavid C Somayajulu }
53711bcba0SDavid C Somayajulu
54711bcba0SDavid C Somayajulu txb = &ha->tx_ring[txr_idx].tx_buf[tx_idx];
55711bcba0SDavid C Somayajulu
56711bcba0SDavid C Somayajulu if (txb->m_head) {
57c8dfaf38SGleb Smirnoff if_inc_counter(ha->ifp, IFCOUNTER_OPACKETS, 1);
58711bcba0SDavid C Somayajulu bus_dmamap_sync(ha->tx_tag, txb->map,
59711bcba0SDavid C Somayajulu BUS_DMASYNC_POSTWRITE);
60711bcba0SDavid C Somayajulu bus_dmamap_unload(ha->tx_tag, txb->map);
61711bcba0SDavid C Somayajulu m_freem(txb->m_head);
62711bcba0SDavid C Somayajulu
63711bcba0SDavid C Somayajulu txb->m_head = NULL;
64711bcba0SDavid C Somayajulu }
65711bcba0SDavid C Somayajulu
66711bcba0SDavid C Somayajulu ha->tx_ring[txr_idx].txr_done++;
67711bcba0SDavid C Somayajulu
68711bcba0SDavid C Somayajulu if (ha->tx_ring[txr_idx].txr_done == NUM_TX_DESCRIPTORS)
69711bcba0SDavid C Somayajulu ha->tx_ring[txr_idx].txr_done = 0;
70711bcba0SDavid C Somayajulu }
71711bcba0SDavid C Somayajulu
72711bcba0SDavid C Somayajulu static void
qls_replenish_rx(qla_host_t * ha,uint32_t r_idx)73711bcba0SDavid C Somayajulu qls_replenish_rx(qla_host_t *ha, uint32_t r_idx)
74711bcba0SDavid C Somayajulu {
75711bcba0SDavid C Somayajulu qla_rx_buf_t *rxb;
76711bcba0SDavid C Somayajulu qla_rx_ring_t *rxr;
77711bcba0SDavid C Somayajulu int count;
78711bcba0SDavid C Somayajulu volatile q81_bq_addr_e_t *sbq_e;
79711bcba0SDavid C Somayajulu
80711bcba0SDavid C Somayajulu rxr = &ha->rx_ring[r_idx];
81711bcba0SDavid C Somayajulu
82711bcba0SDavid C Somayajulu count = rxr->rx_free;
83711bcba0SDavid C Somayajulu sbq_e = rxr->sbq_vaddr;
84711bcba0SDavid C Somayajulu
85711bcba0SDavid C Somayajulu while (count--) {
86711bcba0SDavid C Somayajulu rxb = &rxr->rx_buf[rxr->sbq_next];
87711bcba0SDavid C Somayajulu
88711bcba0SDavid C Somayajulu if (rxb->m_head == NULL) {
89711bcba0SDavid C Somayajulu if (qls_get_mbuf(ha, rxb, NULL) != 0) {
90711bcba0SDavid C Somayajulu device_printf(ha->pci_dev,
91711bcba0SDavid C Somayajulu "%s: qls_get_mbuf [0,%d,%d] failed\n",
92711bcba0SDavid C Somayajulu __func__, rxr->sbq_next, r_idx);
93711bcba0SDavid C Somayajulu rxb->m_head = NULL;
94711bcba0SDavid C Somayajulu break;
95711bcba0SDavid C Somayajulu }
96711bcba0SDavid C Somayajulu }
97711bcba0SDavid C Somayajulu
98711bcba0SDavid C Somayajulu if (rxb->m_head != NULL) {
99711bcba0SDavid C Somayajulu sbq_e[rxr->sbq_next].addr_lo = (uint32_t)rxb->paddr;
100711bcba0SDavid C Somayajulu sbq_e[rxr->sbq_next].addr_hi =
101711bcba0SDavid C Somayajulu (uint32_t)(rxb->paddr >> 32);
102711bcba0SDavid C Somayajulu
103711bcba0SDavid C Somayajulu rxr->sbq_next++;
104711bcba0SDavid C Somayajulu if (rxr->sbq_next == NUM_RX_DESCRIPTORS)
105711bcba0SDavid C Somayajulu rxr->sbq_next = 0;
106711bcba0SDavid C Somayajulu
107711bcba0SDavid C Somayajulu rxr->sbq_free++;
108711bcba0SDavid C Somayajulu rxr->rx_free--;
109711bcba0SDavid C Somayajulu }
110711bcba0SDavid C Somayajulu
111711bcba0SDavid C Somayajulu if (rxr->sbq_free == 16) {
112711bcba0SDavid C Somayajulu rxr->sbq_in += 16;
113711bcba0SDavid C Somayajulu rxr->sbq_in = rxr->sbq_in & (NUM_RX_DESCRIPTORS - 1);
114711bcba0SDavid C Somayajulu rxr->sbq_free = 0;
115711bcba0SDavid C Somayajulu
116711bcba0SDavid C Somayajulu Q81_WR_SBQ_PROD_IDX(r_idx, (rxr->sbq_in));
117711bcba0SDavid C Somayajulu }
118711bcba0SDavid C Somayajulu }
119711bcba0SDavid C Somayajulu }
120711bcba0SDavid C Somayajulu
121711bcba0SDavid C Somayajulu static int
qls_rx_comp(qla_host_t * ha,uint32_t rxr_idx,uint32_t cq_idx,q81_rx_t * cq_e)122711bcba0SDavid C Somayajulu qls_rx_comp(qla_host_t *ha, uint32_t rxr_idx, uint32_t cq_idx, q81_rx_t *cq_e)
123711bcba0SDavid C Somayajulu {
124711bcba0SDavid C Somayajulu qla_rx_buf_t *rxb;
125711bcba0SDavid C Somayajulu qla_rx_ring_t *rxr;
126711bcba0SDavid C Somayajulu device_t dev = ha->pci_dev;
127711bcba0SDavid C Somayajulu struct mbuf *mp = NULL;
12864c618edSJustin Hibbits if_t ifp = ha->ifp;
129618aa8cdSJohn Baldwin #if defined(INET) || defined(INET6)
130711bcba0SDavid C Somayajulu struct lro_ctrl *lro;
131618aa8cdSJohn Baldwin #endif
132711bcba0SDavid C Somayajulu struct ether_vlan_header *eh;
133711bcba0SDavid C Somayajulu
134711bcba0SDavid C Somayajulu rxr = &ha->rx_ring[rxr_idx];
135711bcba0SDavid C Somayajulu
136618aa8cdSJohn Baldwin #if defined(INET) || defined(INET6)
137711bcba0SDavid C Somayajulu lro = &rxr->lro;
138618aa8cdSJohn Baldwin #endif
139711bcba0SDavid C Somayajulu
140711bcba0SDavid C Somayajulu rxb = &rxr->rx_buf[rxr->rx_next];
141711bcba0SDavid C Somayajulu
142711bcba0SDavid C Somayajulu if (!(cq_e->flags1 & Q81_RX_FLAGS1_DS)) {
143711bcba0SDavid C Somayajulu device_printf(dev, "%s: DS bit not set \n", __func__);
144711bcba0SDavid C Somayajulu return -1;
145711bcba0SDavid C Somayajulu }
146711bcba0SDavid C Somayajulu if (rxb->paddr != cq_e->b_paddr) {
147711bcba0SDavid C Somayajulu device_printf(dev,
148711bcba0SDavid C Somayajulu "%s: (rxb->paddr != cq_e->b_paddr)[%p, %p] \n",
149711bcba0SDavid C Somayajulu __func__, (void *)rxb->paddr, (void *)cq_e->b_paddr);
150711bcba0SDavid C Somayajulu
151711bcba0SDavid C Somayajulu Q81_SET_CQ_INVALID(cq_idx);
152711bcba0SDavid C Somayajulu
153711bcba0SDavid C Somayajulu ha->qla_initiate_recovery = 1;
154711bcba0SDavid C Somayajulu
155711bcba0SDavid C Somayajulu return(-1);
156711bcba0SDavid C Somayajulu }
157711bcba0SDavid C Somayajulu
158711bcba0SDavid C Somayajulu rxr->rx_int++;
159711bcba0SDavid C Somayajulu
160711bcba0SDavid C Somayajulu if ((cq_e->flags1 & Q81_RX_FLAGS1_ERR_MASK) == 0) {
161711bcba0SDavid C Somayajulu mp = rxb->m_head;
162711bcba0SDavid C Somayajulu rxb->m_head = NULL;
163711bcba0SDavid C Somayajulu
164711bcba0SDavid C Somayajulu if (mp == NULL) {
165711bcba0SDavid C Somayajulu device_printf(dev, "%s: mp == NULL\n", __func__);
166711bcba0SDavid C Somayajulu } else {
167711bcba0SDavid C Somayajulu mp->m_flags |= M_PKTHDR;
168711bcba0SDavid C Somayajulu mp->m_pkthdr.len = cq_e->length;
169711bcba0SDavid C Somayajulu mp->m_pkthdr.rcvif = ifp;
170711bcba0SDavid C Somayajulu mp->m_len = cq_e->length;
171711bcba0SDavid C Somayajulu
172711bcba0SDavid C Somayajulu eh = mtod(mp, struct ether_vlan_header *);
173711bcba0SDavid C Somayajulu
174711bcba0SDavid C Somayajulu if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
175711bcba0SDavid C Somayajulu uint32_t *data = (uint32_t *)eh;
176711bcba0SDavid C Somayajulu
177711bcba0SDavid C Somayajulu mp->m_pkthdr.ether_vtag = ntohs(eh->evl_tag);
178711bcba0SDavid C Somayajulu mp->m_flags |= M_VLANTAG;
179711bcba0SDavid C Somayajulu
180711bcba0SDavid C Somayajulu *(data + 3) = *(data + 2);
181711bcba0SDavid C Somayajulu *(data + 2) = *(data + 1);
182711bcba0SDavid C Somayajulu *(data + 1) = *data;
183711bcba0SDavid C Somayajulu
184711bcba0SDavid C Somayajulu m_adj(mp, ETHER_VLAN_ENCAP_LEN);
185711bcba0SDavid C Somayajulu }
186711bcba0SDavid C Somayajulu
187711bcba0SDavid C Somayajulu if ((cq_e->flags1 & Q81_RX_FLAGS1_RSS_MATCH_MASK)) {
188711bcba0SDavid C Somayajulu rxr->rss_int++;
189711bcba0SDavid C Somayajulu mp->m_pkthdr.flowid = cq_e->rss;
19036ad8372SSepherosa Ziehau M_HASHTYPE_SET(mp, M_HASHTYPE_OPAQUE_HASH);
191711bcba0SDavid C Somayajulu }
192711bcba0SDavid C Somayajulu if (cq_e->flags0 & (Q81_RX_FLAGS0_TE |
193711bcba0SDavid C Somayajulu Q81_RX_FLAGS0_NU | Q81_RX_FLAGS0_IE)) {
194711bcba0SDavid C Somayajulu mp->m_pkthdr.csum_flags = 0;
195711bcba0SDavid C Somayajulu } else {
196711bcba0SDavid C Somayajulu mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED |
197711bcba0SDavid C Somayajulu CSUM_IP_VALID | CSUM_DATA_VALID |
198711bcba0SDavid C Somayajulu CSUM_PSEUDO_HDR;
199711bcba0SDavid C Somayajulu mp->m_pkthdr.csum_data = 0xFFFF;
200711bcba0SDavid C Somayajulu }
201c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
202711bcba0SDavid C Somayajulu
203618aa8cdSJohn Baldwin #if defined(INET) || defined(INET6)
204711bcba0SDavid C Somayajulu if (lro->lro_cnt && (tcp_lro_rx(lro, mp, 0) == 0)) {
205453130d9SPedro F. Giffuni /* LRO packet has been successfully queued */
206618aa8cdSJohn Baldwin } else
207618aa8cdSJohn Baldwin #endif
208618aa8cdSJohn Baldwin {
20964c618edSJustin Hibbits if_input(ifp, mp);
210711bcba0SDavid C Somayajulu }
211711bcba0SDavid C Somayajulu }
212711bcba0SDavid C Somayajulu } else {
213711bcba0SDavid C Somayajulu device_printf(dev, "%s: err [0%08x]\n", __func__, cq_e->flags1);
214711bcba0SDavid C Somayajulu }
215711bcba0SDavid C Somayajulu
216711bcba0SDavid C Somayajulu rxr->rx_free++;
217711bcba0SDavid C Somayajulu rxr->rx_next++;
218711bcba0SDavid C Somayajulu
219711bcba0SDavid C Somayajulu if (rxr->rx_next == NUM_RX_DESCRIPTORS)
220711bcba0SDavid C Somayajulu rxr->rx_next = 0;
221711bcba0SDavid C Somayajulu
222711bcba0SDavid C Somayajulu if ((rxr->rx_free + rxr->sbq_free) >= 16)
223711bcba0SDavid C Somayajulu qls_replenish_rx(ha, rxr_idx);
224711bcba0SDavid C Somayajulu
225711bcba0SDavid C Somayajulu return 0;
226711bcba0SDavid C Somayajulu }
227711bcba0SDavid C Somayajulu
228711bcba0SDavid C Somayajulu static void
qls_cq_isr(qla_host_t * ha,uint32_t cq_idx)229711bcba0SDavid C Somayajulu qls_cq_isr(qla_host_t *ha, uint32_t cq_idx)
230711bcba0SDavid C Somayajulu {
231711bcba0SDavid C Somayajulu q81_cq_e_t *cq_e, *cq_b;
232711bcba0SDavid C Somayajulu uint32_t i, cq_comp_idx;
233711bcba0SDavid C Somayajulu int ret = 0, tx_comp_done = 0;
234618aa8cdSJohn Baldwin #if defined(INET) || defined(INET6)
235618aa8cdSJohn Baldwin struct lro_ctrl *lro = &ha->rx_ring[cq_idx].lro;
236618aa8cdSJohn Baldwin #endif
237711bcba0SDavid C Somayajulu
238711bcba0SDavid C Somayajulu cq_b = ha->rx_ring[cq_idx].cq_base_vaddr;
239711bcba0SDavid C Somayajulu
240711bcba0SDavid C Somayajulu cq_comp_idx = *(ha->rx_ring[cq_idx].cqi_vaddr);
241711bcba0SDavid C Somayajulu
242711bcba0SDavid C Somayajulu i = ha->rx_ring[cq_idx].cq_next;
243711bcba0SDavid C Somayajulu
244711bcba0SDavid C Somayajulu while (i != cq_comp_idx) {
245711bcba0SDavid C Somayajulu cq_e = &cq_b[i];
246711bcba0SDavid C Somayajulu
247711bcba0SDavid C Somayajulu switch (cq_e->opcode) {
248711bcba0SDavid C Somayajulu case Q81_IOCB_TX_MAC:
249711bcba0SDavid C Somayajulu case Q81_IOCB_TX_TSO:
250711bcba0SDavid C Somayajulu qls_tx_comp(ha, cq_idx, (q81_tx_mac_comp_t *)cq_e);
251711bcba0SDavid C Somayajulu tx_comp_done++;
252711bcba0SDavid C Somayajulu break;
253711bcba0SDavid C Somayajulu
254711bcba0SDavid C Somayajulu case Q81_IOCB_RX:
255711bcba0SDavid C Somayajulu ret = qls_rx_comp(ha, cq_idx, i, (q81_rx_t *)cq_e);
256711bcba0SDavid C Somayajulu
257711bcba0SDavid C Somayajulu break;
258711bcba0SDavid C Somayajulu
259711bcba0SDavid C Somayajulu case Q81_IOCB_MPI:
260711bcba0SDavid C Somayajulu case Q81_IOCB_SYS:
261711bcba0SDavid C Somayajulu default:
262711bcba0SDavid C Somayajulu device_printf(ha->pci_dev, "%s[%d %d 0x%x]: illegal \n",
263711bcba0SDavid C Somayajulu __func__, i, (*(ha->rx_ring[cq_idx].cqi_vaddr)),
264711bcba0SDavid C Somayajulu cq_e->opcode);
265711bcba0SDavid C Somayajulu qls_dump_buf32(ha, __func__, cq_e,
266711bcba0SDavid C Somayajulu (sizeof (q81_cq_e_t) >> 2));
267711bcba0SDavid C Somayajulu break;
268711bcba0SDavid C Somayajulu }
269711bcba0SDavid C Somayajulu
270711bcba0SDavid C Somayajulu i++;
271711bcba0SDavid C Somayajulu if (i == NUM_CQ_ENTRIES)
272711bcba0SDavid C Somayajulu i = 0;
273711bcba0SDavid C Somayajulu
274711bcba0SDavid C Somayajulu if (ret) {
275711bcba0SDavid C Somayajulu break;
276711bcba0SDavid C Somayajulu }
277711bcba0SDavid C Somayajulu
278711bcba0SDavid C Somayajulu if (i == cq_comp_idx) {
279711bcba0SDavid C Somayajulu cq_comp_idx = *(ha->rx_ring[cq_idx].cqi_vaddr);
280711bcba0SDavid C Somayajulu }
281711bcba0SDavid C Somayajulu
282711bcba0SDavid C Somayajulu if (tx_comp_done) {
283711bcba0SDavid C Somayajulu taskqueue_enqueue(ha->tx_tq, &ha->tx_task);
284711bcba0SDavid C Somayajulu tx_comp_done = 0;
285711bcba0SDavid C Somayajulu }
286711bcba0SDavid C Somayajulu }
287711bcba0SDavid C Somayajulu
288618aa8cdSJohn Baldwin #if defined(INET) || defined(INET6)
2896dd38b87SSepherosa Ziehau tcp_lro_flush_all(lro);
290618aa8cdSJohn Baldwin #endif
291711bcba0SDavid C Somayajulu
292711bcba0SDavid C Somayajulu ha->rx_ring[cq_idx].cq_next = cq_comp_idx;
293711bcba0SDavid C Somayajulu
294711bcba0SDavid C Somayajulu if (!ret) {
295711bcba0SDavid C Somayajulu Q81_WR_CQ_CONS_IDX(cq_idx, (ha->rx_ring[cq_idx].cq_next));
296711bcba0SDavid C Somayajulu }
297711bcba0SDavid C Somayajulu if (tx_comp_done)
298711bcba0SDavid C Somayajulu taskqueue_enqueue(ha->tx_tq, &ha->tx_task);
299711bcba0SDavid C Somayajulu
300711bcba0SDavid C Somayajulu return;
301711bcba0SDavid C Somayajulu }
302711bcba0SDavid C Somayajulu
303711bcba0SDavid C Somayajulu static void
qls_mbx_isr(qla_host_t * ha)304711bcba0SDavid C Somayajulu qls_mbx_isr(qla_host_t *ha)
305711bcba0SDavid C Somayajulu {
306711bcba0SDavid C Somayajulu uint32_t data;
307711bcba0SDavid C Somayajulu int i;
308711bcba0SDavid C Somayajulu device_t dev = ha->pci_dev;
309711bcba0SDavid C Somayajulu
310711bcba0SDavid C Somayajulu if (qls_mbx_rd_reg(ha, 0, &data) == 0) {
311711bcba0SDavid C Somayajulu if ((data & 0xF000) == 0x4000) {
312711bcba0SDavid C Somayajulu ha->mbox[0] = data;
313711bcba0SDavid C Somayajulu for (i = 1; i < Q81_NUM_MBX_REGISTERS; i++) {
314711bcba0SDavid C Somayajulu if (qls_mbx_rd_reg(ha, i, &data))
315711bcba0SDavid C Somayajulu break;
316711bcba0SDavid C Somayajulu ha->mbox[i] = data;
317711bcba0SDavid C Somayajulu }
318711bcba0SDavid C Somayajulu ha->mbx_done = 1;
319711bcba0SDavid C Somayajulu } else if ((data & 0xF000) == 0x8000) {
320711bcba0SDavid C Somayajulu /* we have an AEN */
321711bcba0SDavid C Somayajulu
322711bcba0SDavid C Somayajulu ha->aen[0] = data;
323711bcba0SDavid C Somayajulu for (i = 1; i < Q81_NUM_AEN_REGISTERS; i++) {
324711bcba0SDavid C Somayajulu if (qls_mbx_rd_reg(ha, i, &data))
325711bcba0SDavid C Somayajulu break;
326711bcba0SDavid C Somayajulu ha->aen[i] = data;
327711bcba0SDavid C Somayajulu }
328711bcba0SDavid C Somayajulu device_printf(dev,"%s: AEN "
329711bcba0SDavid C Somayajulu "[0x%08x 0x%08x 0x%08x 0x%08x 0x%08x"
330711bcba0SDavid C Somayajulu " 0x%08x 0x%08x 0x%08x 0x%08x]\n",
331711bcba0SDavid C Somayajulu __func__,
332711bcba0SDavid C Somayajulu ha->aen[0], ha->aen[1], ha->aen[2],
333711bcba0SDavid C Somayajulu ha->aen[3], ha->aen[4], ha->aen[5],
334711bcba0SDavid C Somayajulu ha->aen[6], ha->aen[7], ha->aen[8]);
335711bcba0SDavid C Somayajulu
336711bcba0SDavid C Somayajulu switch ((ha->aen[0] & 0xFFFF)) {
337711bcba0SDavid C Somayajulu case 0x8011:
338711bcba0SDavid C Somayajulu ha->link_up = 1;
339711bcba0SDavid C Somayajulu break;
340711bcba0SDavid C Somayajulu
341711bcba0SDavid C Somayajulu case 0x8012:
342711bcba0SDavid C Somayajulu ha->link_up = 0;
343711bcba0SDavid C Somayajulu break;
344711bcba0SDavid C Somayajulu
345711bcba0SDavid C Somayajulu case 0x8130:
346711bcba0SDavid C Somayajulu ha->link_hw_info = ha->aen[1];
347711bcba0SDavid C Somayajulu break;
348711bcba0SDavid C Somayajulu
349711bcba0SDavid C Somayajulu case 0x8131:
350711bcba0SDavid C Somayajulu ha->link_hw_info = 0;
351711bcba0SDavid C Somayajulu break;
352711bcba0SDavid C Somayajulu }
353711bcba0SDavid C Somayajulu }
354711bcba0SDavid C Somayajulu }
355711bcba0SDavid C Somayajulu WRITE_REG32(ha, Q81_CTL_HOST_CMD_STATUS, Q81_CTL_HCS_CMD_CLR_RTH_INTR);
356711bcba0SDavid C Somayajulu
357711bcba0SDavid C Somayajulu return;
358711bcba0SDavid C Somayajulu }
359711bcba0SDavid C Somayajulu
360711bcba0SDavid C Somayajulu void
qls_isr(void * arg)361711bcba0SDavid C Somayajulu qls_isr(void *arg)
362711bcba0SDavid C Somayajulu {
363711bcba0SDavid C Somayajulu qla_ivec_t *ivec = arg;
364711bcba0SDavid C Somayajulu qla_host_t *ha;
365711bcba0SDavid C Somayajulu uint32_t status;
366711bcba0SDavid C Somayajulu uint32_t cq_idx;
367711bcba0SDavid C Somayajulu device_t dev;
368711bcba0SDavid C Somayajulu
369711bcba0SDavid C Somayajulu ha = ivec->ha;
370711bcba0SDavid C Somayajulu cq_idx = ivec->cq_idx;
371711bcba0SDavid C Somayajulu dev = ha->pci_dev;
372711bcba0SDavid C Somayajulu
373711bcba0SDavid C Somayajulu status = READ_REG32(ha, Q81_CTL_STATUS);
374711bcba0SDavid C Somayajulu
375711bcba0SDavid C Somayajulu if (status & Q81_CTL_STATUS_FE) {
376711bcba0SDavid C Somayajulu device_printf(dev, "%s fatal error\n", __func__);
377711bcba0SDavid C Somayajulu return;
378711bcba0SDavid C Somayajulu }
379711bcba0SDavid C Somayajulu
380711bcba0SDavid C Somayajulu if ((cq_idx == 0) && (status & Q81_CTL_STATUS_PI)) {
381711bcba0SDavid C Somayajulu qls_mbx_isr(ha);
382711bcba0SDavid C Somayajulu }
383711bcba0SDavid C Somayajulu
384711bcba0SDavid C Somayajulu status = READ_REG32(ha, Q81_CTL_INTR_STATUS1);
385711bcba0SDavid C Somayajulu
386711bcba0SDavid C Somayajulu if (status & ( 0x1 << cq_idx))
387711bcba0SDavid C Somayajulu qls_cq_isr(ha, cq_idx);
388711bcba0SDavid C Somayajulu
389711bcba0SDavid C Somayajulu Q81_ENABLE_INTR(ha, cq_idx);
390711bcba0SDavid C Somayajulu
391711bcba0SDavid C Somayajulu return;
392711bcba0SDavid C Somayajulu }
393