177adf3f0SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
3fa90c54fSAndrew Vasquez * QLogic Fibre Channel HBA Driver
4bd21eaf9SArmen Baloyan * Copyright (c) 2003-2014 QLogic Corporation
51da177e4SLinus Torvalds */
61da177e4SLinus Torvalds #include "qla_def.h"
72d70c103SNicholas Bellinger #include "qla_target.h"
8a0465859SBikash Hazarika #include "qla_gbl.h"
91da177e4SLinus Torvalds
1005236a05SAndrew Vasquez #include <linux/delay.h>
115a0e3ad6STejun Heo #include <linux/slab.h>
12e326d22aSQuinn Tran #include <linux/cpu.h>
1309ce66aeSBart Van Assche #include <linux/t10-pi.h>
14df7baa50SAndrew Vasquez #include <scsi/scsi_tcq.h>
159a069e19SGiridhar Malavali #include <scsi/scsi_bsg_fc.h>
16bad75002SArun Easi #include <scsi/scsi_eh.h>
17d32041ecSJohannes Thumshirn #include <scsi/fc/fc_fs.h>
18d32041ecSJohannes Thumshirn #include <linux/nvme-fc-driver.h>
19df7baa50SAndrew Vasquez
201da177e4SLinus Torvalds static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
2173208dfdSAnirban Chakraborty static void qla2x00_status_entry(scsi_qla_host_t *, struct rsp_que *, void *);
222afa19a9SAnirban Chakraborty static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *);
23c5419e26SQuinn Tran static int qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
2473208dfdSAnirban Chakraborty sts_entry_t *);
259f2475feSShyam Sundar static void qla27xx_process_purex_fpin(struct scsi_qla_host *vha,
269f2475feSShyam Sundar struct purex_item *item);
279f2475feSShyam Sundar static struct purex_item *qla24xx_alloc_purex_item(scsi_qla_host_t *vha,
289f2475feSShyam Sundar uint16_t size);
299f2475feSShyam Sundar static struct purex_item *qla24xx_copy_std_pkt(struct scsi_qla_host *vha,
309f2475feSShyam Sundar void *pkt);
319f2475feSShyam Sundar static struct purex_item *qla27xx_copy_fpin_pkt(struct scsi_qla_host *vha,
329f2475feSShyam Sundar void **pkt, struct rsp_que **rsp);
339f2475feSShyam Sundar
349f2475feSShyam Sundar static void
qla27xx_process_purex_fpin(struct scsi_qla_host * vha,struct purex_item * item)359f2475feSShyam Sundar qla27xx_process_purex_fpin(struct scsi_qla_host *vha, struct purex_item *item)
369f2475feSShyam Sundar {
379f2475feSShyam Sundar void *pkt = &item->iocb;
389f2475feSShyam Sundar uint16_t pkt_size = item->size;
399f2475feSShyam Sundar
409f2475feSShyam Sundar ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x508d,
419f2475feSShyam Sundar "%s: Enter\n", __func__);
429f2475feSShyam Sundar
439f2475feSShyam Sundar ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x508e,
449f2475feSShyam Sundar "-------- ELS REQ -------\n");
459f2475feSShyam Sundar ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x508f,
469f2475feSShyam Sundar pkt, pkt_size);
479f2475feSShyam Sundar
4864fd2ba9SMuneendra fc_host_fpin_rcv(vha->host, pkt_size, (char *)pkt, 0);
499f2475feSShyam Sundar }
509a853f71SAndrew Vasquez
51c4dc7cd3SBart Van Assche const char *const port_state_str[] = {
526e0e85d3SGleb Chesnokov [FCS_UNKNOWN] = "Unknown",
536e0e85d3SGleb Chesnokov [FCS_UNCONFIGURED] = "UNCONFIGURED",
546e0e85d3SGleb Chesnokov [FCS_DEVICE_DEAD] = "DEAD",
556e0e85d3SGleb Chesnokov [FCS_DEVICE_LOST] = "LOST",
566e0e85d3SGleb Chesnokov [FCS_ONLINE] = "ONLINE"
57c4dc7cd3SBart Van Assche };
58c4dc7cd3SBart Van Assche
59cd248a95SBikash Hazarika #define SFP_DISABLE_LASER_INITIATED 0x15 /* Sub code of 8070 AEN */
60cd248a95SBikash Hazarika #define SFP_ENABLE_LASER_INITIATED 0x16 /* Sub code of 8070 AEN */
61cd248a95SBikash Hazarika
display_Laser_info(scsi_qla_host_t * vha,u16 mb1,u16 mb2,u16 mb3)62cd248a95SBikash Hazarika static inline void display_Laser_info(scsi_qla_host_t *vha,
63cd248a95SBikash Hazarika u16 mb1, u16 mb2, u16 mb3) {
64cd248a95SBikash Hazarika
65cd248a95SBikash Hazarika if (mb1 == SFP_DISABLE_LASER_INITIATED)
66cd248a95SBikash Hazarika ql_log(ql_log_warn, vha, 0xf0a2,
67cd248a95SBikash Hazarika "SFP temperature (%d C) reached/exceeded the threshold (%d C). Laser is disabled.\n",
68cd248a95SBikash Hazarika mb3, mb2);
69cd248a95SBikash Hazarika if (mb1 == SFP_ENABLE_LASER_INITIATED)
70cd248a95SBikash Hazarika ql_log(ql_log_warn, vha, 0xf0a3,
71cd248a95SBikash Hazarika "SFP temperature (%d C) reached normal operating level. Laser is enabled.\n",
72cd248a95SBikash Hazarika mb3);
73cd248a95SBikash Hazarika }
74cd248a95SBikash Hazarika
75576bfde8SJoe Carnuccio static void
qla24xx_process_abts(struct scsi_qla_host * vha,struct purex_item * pkt)7662e9dd17SShyam Sundar qla24xx_process_abts(struct scsi_qla_host *vha, struct purex_item *pkt)
77576bfde8SJoe Carnuccio {
7862e9dd17SShyam Sundar struct abts_entry_24xx *abts =
7962e9dd17SShyam Sundar (struct abts_entry_24xx *)&pkt->iocb;
80576bfde8SJoe Carnuccio struct qla_hw_data *ha = vha->hw;
81576bfde8SJoe Carnuccio struct els_entry_24xx *rsp_els;
82576bfde8SJoe Carnuccio struct abts_entry_24xx *abts_rsp;
83576bfde8SJoe Carnuccio dma_addr_t dma;
84576bfde8SJoe Carnuccio uint32_t fctl;
85576bfde8SJoe Carnuccio int rval;
86576bfde8SJoe Carnuccio
87576bfde8SJoe Carnuccio ql_dbg(ql_dbg_init, vha, 0x0286, "%s: entered.\n", __func__);
88576bfde8SJoe Carnuccio
89576bfde8SJoe Carnuccio ql_log(ql_log_warn, vha, 0x0287,
90576bfde8SJoe Carnuccio "Processing ABTS xchg=%#x oxid=%#x rxid=%#x seqid=%#x seqcnt=%#x\n",
91576bfde8SJoe Carnuccio abts->rx_xch_addr_to_abort, abts->ox_id, abts->rx_id,
92576bfde8SJoe Carnuccio abts->seq_id, abts->seq_cnt);
93576bfde8SJoe Carnuccio ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0287,
94576bfde8SJoe Carnuccio "-------- ABTS RCV -------\n");
95576bfde8SJoe Carnuccio ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0287,
96576bfde8SJoe Carnuccio (uint8_t *)abts, sizeof(*abts));
97576bfde8SJoe Carnuccio
98576bfde8SJoe Carnuccio rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), &dma,
99576bfde8SJoe Carnuccio GFP_KERNEL);
100576bfde8SJoe Carnuccio if (!rsp_els) {
101576bfde8SJoe Carnuccio ql_log(ql_log_warn, vha, 0x0287,
102576bfde8SJoe Carnuccio "Failed allocate dma buffer ABTS/ELS RSP.\n");
103576bfde8SJoe Carnuccio return;
104576bfde8SJoe Carnuccio }
105576bfde8SJoe Carnuccio
106576bfde8SJoe Carnuccio /* terminate exchange */
107576bfde8SJoe Carnuccio rsp_els->entry_type = ELS_IOCB_TYPE;
108576bfde8SJoe Carnuccio rsp_els->entry_count = 1;
1097ffa5b93SBart Van Assche rsp_els->nport_handle = cpu_to_le16(~0);
110576bfde8SJoe Carnuccio rsp_els->rx_xchg_address = abts->rx_xch_addr_to_abort;
1117ffa5b93SBart Van Assche rsp_els->control_flags = cpu_to_le16(EPD_RX_XCHG);
112576bfde8SJoe Carnuccio ql_dbg(ql_dbg_init, vha, 0x0283,
113576bfde8SJoe Carnuccio "Sending ELS Response to terminate exchange %#x...\n",
114576bfde8SJoe Carnuccio abts->rx_xch_addr_to_abort);
115576bfde8SJoe Carnuccio ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0283,
116576bfde8SJoe Carnuccio "-------- ELS RSP -------\n");
117576bfde8SJoe Carnuccio ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0283,
118576bfde8SJoe Carnuccio (uint8_t *)rsp_els, sizeof(*rsp_els));
119576bfde8SJoe Carnuccio rval = qla2x00_issue_iocb(vha, rsp_els, dma, 0);
120576bfde8SJoe Carnuccio if (rval) {
121576bfde8SJoe Carnuccio ql_log(ql_log_warn, vha, 0x0288,
122576bfde8SJoe Carnuccio "%s: iocb failed to execute -> %x\n", __func__, rval);
123576bfde8SJoe Carnuccio } else if (rsp_els->comp_status) {
124576bfde8SJoe Carnuccio ql_log(ql_log_warn, vha, 0x0289,
125576bfde8SJoe Carnuccio "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n",
126576bfde8SJoe Carnuccio __func__, rsp_els->comp_status,
127576bfde8SJoe Carnuccio rsp_els->error_subcode_1, rsp_els->error_subcode_2);
128576bfde8SJoe Carnuccio } else {
129576bfde8SJoe Carnuccio ql_dbg(ql_dbg_init, vha, 0x028a,
130576bfde8SJoe Carnuccio "%s: abort exchange done.\n", __func__);
131576bfde8SJoe Carnuccio }
132576bfde8SJoe Carnuccio
133576bfde8SJoe Carnuccio /* send ABTS response */
134576bfde8SJoe Carnuccio abts_rsp = (void *)rsp_els;
135576bfde8SJoe Carnuccio memset(abts_rsp, 0, sizeof(*abts_rsp));
136576bfde8SJoe Carnuccio abts_rsp->entry_type = ABTS_RSP_TYPE;
137576bfde8SJoe Carnuccio abts_rsp->entry_count = 1;
138576bfde8SJoe Carnuccio abts_rsp->nport_handle = abts->nport_handle;
139576bfde8SJoe Carnuccio abts_rsp->vp_idx = abts->vp_idx;
140576bfde8SJoe Carnuccio abts_rsp->sof_type = abts->sof_type & 0xf0;
141576bfde8SJoe Carnuccio abts_rsp->rx_xch_addr = abts->rx_xch_addr;
142576bfde8SJoe Carnuccio abts_rsp->d_id[0] = abts->s_id[0];
143576bfde8SJoe Carnuccio abts_rsp->d_id[1] = abts->s_id[1];
144576bfde8SJoe Carnuccio abts_rsp->d_id[2] = abts->s_id[2];
145576bfde8SJoe Carnuccio abts_rsp->r_ctl = FC_ROUTING_BLD | FC_R_CTL_BLD_BA_ACC;
146576bfde8SJoe Carnuccio abts_rsp->s_id[0] = abts->d_id[0];
147576bfde8SJoe Carnuccio abts_rsp->s_id[1] = abts->d_id[1];
148576bfde8SJoe Carnuccio abts_rsp->s_id[2] = abts->d_id[2];
149576bfde8SJoe Carnuccio abts_rsp->cs_ctl = abts->cs_ctl;
150576bfde8SJoe Carnuccio /* include flipping bit23 in fctl */
151576bfde8SJoe Carnuccio fctl = ~(abts->f_ctl[2] | 0x7F) << 16 |
152576bfde8SJoe Carnuccio FC_F_CTL_LAST_SEQ | FC_F_CTL_END_SEQ | FC_F_CTL_SEQ_INIT;
153576bfde8SJoe Carnuccio abts_rsp->f_ctl[0] = fctl >> 0 & 0xff;
154576bfde8SJoe Carnuccio abts_rsp->f_ctl[1] = fctl >> 8 & 0xff;
155576bfde8SJoe Carnuccio abts_rsp->f_ctl[2] = fctl >> 16 & 0xff;
156576bfde8SJoe Carnuccio abts_rsp->type = FC_TYPE_BLD;
157576bfde8SJoe Carnuccio abts_rsp->rx_id = abts->rx_id;
158576bfde8SJoe Carnuccio abts_rsp->ox_id = abts->ox_id;
159576bfde8SJoe Carnuccio abts_rsp->payload.ba_acc.aborted_rx_id = abts->rx_id;
160576bfde8SJoe Carnuccio abts_rsp->payload.ba_acc.aborted_ox_id = abts->ox_id;
1617ffa5b93SBart Van Assche abts_rsp->payload.ba_acc.high_seq_cnt = cpu_to_le16(~0);
162576bfde8SJoe Carnuccio abts_rsp->rx_xch_addr_to_abort = abts->rx_xch_addr_to_abort;
163576bfde8SJoe Carnuccio ql_dbg(ql_dbg_init, vha, 0x028b,
164576bfde8SJoe Carnuccio "Sending BA ACC response to ABTS %#x...\n",
165576bfde8SJoe Carnuccio abts->rx_xch_addr_to_abort);
166576bfde8SJoe Carnuccio ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x028b,
167576bfde8SJoe Carnuccio "-------- ELS RSP -------\n");
168576bfde8SJoe Carnuccio ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x028b,
169576bfde8SJoe Carnuccio (uint8_t *)abts_rsp, sizeof(*abts_rsp));
170576bfde8SJoe Carnuccio rval = qla2x00_issue_iocb(vha, abts_rsp, dma, 0);
171576bfde8SJoe Carnuccio if (rval) {
172576bfde8SJoe Carnuccio ql_log(ql_log_warn, vha, 0x028c,
173576bfde8SJoe Carnuccio "%s: iocb failed to execute -> %x\n", __func__, rval);
174576bfde8SJoe Carnuccio } else if (abts_rsp->comp_status) {
175576bfde8SJoe Carnuccio ql_log(ql_log_warn, vha, 0x028d,
176576bfde8SJoe Carnuccio "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n",
177576bfde8SJoe Carnuccio __func__, abts_rsp->comp_status,
178576bfde8SJoe Carnuccio abts_rsp->payload.error.subcode1,
179576bfde8SJoe Carnuccio abts_rsp->payload.error.subcode2);
180576bfde8SJoe Carnuccio } else {
181576bfde8SJoe Carnuccio ql_dbg(ql_dbg_init, vha, 0x028ea,
182576bfde8SJoe Carnuccio "%s: done.\n", __func__);
183576bfde8SJoe Carnuccio }
184576bfde8SJoe Carnuccio
185576bfde8SJoe Carnuccio dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), rsp_els, dma);
186576bfde8SJoe Carnuccio }
187576bfde8SJoe Carnuccio
1881da177e4SLinus Torvalds /**
189fac28079SQuinn Tran * __qla_consume_iocb - this routine is used to tell fw driver has processed
190fac28079SQuinn Tran * or consumed the head IOCB along with the continuation IOCB's from the
191fac28079SQuinn Tran * provided respond queue.
192fac28079SQuinn Tran * @vha: host adapter pointer
193fac28079SQuinn Tran * @pkt: pointer to current packet. On return, this pointer shall move
194fac28079SQuinn Tran * to the next packet.
195fac28079SQuinn Tran * @rsp: respond queue pointer.
196fac28079SQuinn Tran *
197fac28079SQuinn Tran * it is assumed pkt is the head iocb, not the continuation iocbk
198fac28079SQuinn Tran */
__qla_consume_iocb(struct scsi_qla_host * vha,void ** pkt,struct rsp_que ** rsp)199fac28079SQuinn Tran void __qla_consume_iocb(struct scsi_qla_host *vha,
200fac28079SQuinn Tran void **pkt, struct rsp_que **rsp)
201fac28079SQuinn Tran {
202fac28079SQuinn Tran struct rsp_que *rsp_q = *rsp;
203fac28079SQuinn Tran response_t *new_pkt;
204fac28079SQuinn Tran uint16_t entry_count_remaining;
205fac28079SQuinn Tran struct purex_entry_24xx *purex = *pkt;
206fac28079SQuinn Tran
207fac28079SQuinn Tran entry_count_remaining = purex->entry_count;
208fac28079SQuinn Tran while (entry_count_remaining > 0) {
209fac28079SQuinn Tran new_pkt = rsp_q->ring_ptr;
210fac28079SQuinn Tran *pkt = new_pkt;
211fac28079SQuinn Tran
212fac28079SQuinn Tran rsp_q->ring_index++;
213fac28079SQuinn Tran if (rsp_q->ring_index == rsp_q->length) {
214fac28079SQuinn Tran rsp_q->ring_index = 0;
215fac28079SQuinn Tran rsp_q->ring_ptr = rsp_q->ring;
216fac28079SQuinn Tran } else {
217fac28079SQuinn Tran rsp_q->ring_ptr++;
218fac28079SQuinn Tran }
219fac28079SQuinn Tran
220fac28079SQuinn Tran new_pkt->signature = RESPONSE_PROCESSED;
221fac28079SQuinn Tran /* flush signature */
222fac28079SQuinn Tran wmb();
223fac28079SQuinn Tran --entry_count_remaining;
224fac28079SQuinn Tran }
225fac28079SQuinn Tran }
226fac28079SQuinn Tran
227fac28079SQuinn Tran /**
228fac28079SQuinn Tran * __qla_copy_purex_to_buffer - extract ELS payload from Purex IOCB
229fac28079SQuinn Tran * and save to provided buffer
230fac28079SQuinn Tran * @vha: host adapter pointer
231fac28079SQuinn Tran * @pkt: pointer Purex IOCB
232fac28079SQuinn Tran * @rsp: respond queue
233fac28079SQuinn Tran * @buf: extracted ELS payload copy here
234fac28079SQuinn Tran * @buf_len: buffer length
235fac28079SQuinn Tran */
__qla_copy_purex_to_buffer(struct scsi_qla_host * vha,void ** pkt,struct rsp_que ** rsp,u8 * buf,u32 buf_len)236fac28079SQuinn Tran int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha,
237fac28079SQuinn Tran void **pkt, struct rsp_que **rsp, u8 *buf, u32 buf_len)
238fac28079SQuinn Tran {
239fac28079SQuinn Tran struct purex_entry_24xx *purex = *pkt;
240fac28079SQuinn Tran struct rsp_que *rsp_q = *rsp;
241fac28079SQuinn Tran sts_cont_entry_t *new_pkt;
242fac28079SQuinn Tran uint16_t no_bytes = 0, total_bytes = 0, pending_bytes = 0;
243fac28079SQuinn Tran uint16_t buffer_copy_offset = 0;
244fac28079SQuinn Tran uint16_t entry_count_remaining;
245fac28079SQuinn Tran u16 tpad;
246fac28079SQuinn Tran
247fac28079SQuinn Tran entry_count_remaining = purex->entry_count;
248fac28079SQuinn Tran total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF)
249fac28079SQuinn Tran - PURX_ELS_HEADER_SIZE;
250fac28079SQuinn Tran
251fac28079SQuinn Tran /*
252fac28079SQuinn Tran * end of payload may not end in 4bytes boundary. Need to
253fac28079SQuinn Tran * round up / pad for room to swap, before saving data
254fac28079SQuinn Tran */
255fac28079SQuinn Tran tpad = roundup(total_bytes, 4);
256fac28079SQuinn Tran
257fac28079SQuinn Tran if (buf_len < tpad) {
258fac28079SQuinn Tran ql_dbg(ql_dbg_async, vha, 0x5084,
259fac28079SQuinn Tran "%s buffer is too small %d < %d\n",
260fac28079SQuinn Tran __func__, buf_len, tpad);
261fac28079SQuinn Tran __qla_consume_iocb(vha, pkt, rsp);
262fac28079SQuinn Tran return -EIO;
263fac28079SQuinn Tran }
264fac28079SQuinn Tran
265fac28079SQuinn Tran pending_bytes = total_bytes = tpad;
266fac28079SQuinn Tran no_bytes = (pending_bytes > sizeof(purex->els_frame_payload)) ?
267fac28079SQuinn Tran sizeof(purex->els_frame_payload) : pending_bytes;
268fac28079SQuinn Tran
269fac28079SQuinn Tran memcpy(buf, &purex->els_frame_payload[0], no_bytes);
270fac28079SQuinn Tran buffer_copy_offset += no_bytes;
271fac28079SQuinn Tran pending_bytes -= no_bytes;
272fac28079SQuinn Tran --entry_count_remaining;
273fac28079SQuinn Tran
274fac28079SQuinn Tran ((response_t *)purex)->signature = RESPONSE_PROCESSED;
275fac28079SQuinn Tran /* flush signature */
276fac28079SQuinn Tran wmb();
277fac28079SQuinn Tran
278fac28079SQuinn Tran do {
279fac28079SQuinn Tran while ((total_bytes > 0) && (entry_count_remaining > 0)) {
280fac28079SQuinn Tran new_pkt = (sts_cont_entry_t *)rsp_q->ring_ptr;
281fac28079SQuinn Tran *pkt = new_pkt;
282fac28079SQuinn Tran
283fac28079SQuinn Tran if (new_pkt->entry_type != STATUS_CONT_TYPE) {
284fac28079SQuinn Tran ql_log(ql_log_warn, vha, 0x507a,
285fac28079SQuinn Tran "Unexpected IOCB type, partial data 0x%x\n",
286fac28079SQuinn Tran buffer_copy_offset);
287fac28079SQuinn Tran break;
288fac28079SQuinn Tran }
289fac28079SQuinn Tran
290fac28079SQuinn Tran rsp_q->ring_index++;
291fac28079SQuinn Tran if (rsp_q->ring_index == rsp_q->length) {
292fac28079SQuinn Tran rsp_q->ring_index = 0;
293fac28079SQuinn Tran rsp_q->ring_ptr = rsp_q->ring;
294fac28079SQuinn Tran } else {
295fac28079SQuinn Tran rsp_q->ring_ptr++;
296fac28079SQuinn Tran }
297fac28079SQuinn Tran no_bytes = (pending_bytes > sizeof(new_pkt->data)) ?
298fac28079SQuinn Tran sizeof(new_pkt->data) : pending_bytes;
299fac28079SQuinn Tran if ((buffer_copy_offset + no_bytes) <= total_bytes) {
300fac28079SQuinn Tran memcpy((buf + buffer_copy_offset), new_pkt->data,
301fac28079SQuinn Tran no_bytes);
302fac28079SQuinn Tran buffer_copy_offset += no_bytes;
303fac28079SQuinn Tran pending_bytes -= no_bytes;
304fac28079SQuinn Tran --entry_count_remaining;
305fac28079SQuinn Tran } else {
306fac28079SQuinn Tran ql_log(ql_log_warn, vha, 0x5044,
307fac28079SQuinn Tran "Attempt to copy more that we got, optimizing..%x\n",
308fac28079SQuinn Tran buffer_copy_offset);
309fac28079SQuinn Tran memcpy((buf + buffer_copy_offset), new_pkt->data,
310fac28079SQuinn Tran total_bytes - buffer_copy_offset);
311fac28079SQuinn Tran }
312fac28079SQuinn Tran
313fac28079SQuinn Tran ((response_t *)new_pkt)->signature = RESPONSE_PROCESSED;
314fac28079SQuinn Tran /* flush signature */
315fac28079SQuinn Tran wmb();
316fac28079SQuinn Tran }
317fac28079SQuinn Tran
318fac28079SQuinn Tran if (pending_bytes != 0 || entry_count_remaining != 0) {
319fac28079SQuinn Tran ql_log(ql_log_fatal, vha, 0x508b,
320fac28079SQuinn Tran "Dropping partial Data, underrun bytes = 0x%x, entry cnts 0x%x\n",
321fac28079SQuinn Tran total_bytes, entry_count_remaining);
322fac28079SQuinn Tran return -EIO;
323fac28079SQuinn Tran }
324fac28079SQuinn Tran } while (entry_count_remaining > 0);
325fac28079SQuinn Tran
326fac28079SQuinn Tran be32_to_cpu_array((u32 *)buf, (__be32 *)buf, total_bytes >> 2);
327fac28079SQuinn Tran
328fac28079SQuinn Tran return 0;
329fac28079SQuinn Tran }
330fac28079SQuinn Tran
331fac28079SQuinn Tran /**
3321da177e4SLinus Torvalds * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
333807eb907SBart Van Assche * @irq: interrupt number
3341da177e4SLinus Torvalds * @dev_id: SCSI driver HA context
3351da177e4SLinus Torvalds *
3361da177e4SLinus Torvalds * Called by system whenever the host adapter generates an interrupt.
3371da177e4SLinus Torvalds *
3381da177e4SLinus Torvalds * Returns handled flag.
3391da177e4SLinus Torvalds */
3401da177e4SLinus Torvalds irqreturn_t
qla2100_intr_handler(int irq,void * dev_id)3417d12e780SDavid Howells qla2100_intr_handler(int irq, void *dev_id)
3421da177e4SLinus Torvalds {
343e315cd28SAnirban Chakraborty scsi_qla_host_t *vha;
344e315cd28SAnirban Chakraborty struct qla_hw_data *ha;
3453d71644cSAndrew Vasquez struct device_reg_2xxx __iomem *reg;
3461da177e4SLinus Torvalds int status;
3471da177e4SLinus Torvalds unsigned long iter;
34814e660e6SSeokmann Ju uint16_t hccr;
3490a59cea4SBart Van Assche uint16_t mb[8];
350e315cd28SAnirban Chakraborty struct rsp_que *rsp;
35143fac4d9SAnirban Chakraborty unsigned long flags;
3521da177e4SLinus Torvalds
353e315cd28SAnirban Chakraborty rsp = (struct rsp_que *) dev_id;
354e315cd28SAnirban Chakraborty if (!rsp) {
3553256b435SChad Dupuis ql_log(ql_log_info, NULL, 0x505d,
3563256b435SChad Dupuis "%s: NULL response queue pointer.\n", __func__);
3571da177e4SLinus Torvalds return (IRQ_NONE);
3581da177e4SLinus Torvalds }
3591da177e4SLinus Torvalds
360e315cd28SAnirban Chakraborty ha = rsp->hw;
3613d71644cSAndrew Vasquez reg = &ha->iobase->isp;
3621da177e4SLinus Torvalds status = 0;
3631da177e4SLinus Torvalds
36443fac4d9SAnirban Chakraborty spin_lock_irqsave(&ha->hardware_lock, flags);
3652afa19a9SAnirban Chakraborty vha = pci_get_drvdata(ha->pdev);
3661da177e4SLinus Torvalds for (iter = 50; iter--; ) {
36704474d3aSBart Van Assche hccr = rd_reg_word(®->hccr);
368c821e0d5SJoe Lawrence if (qla2x00_check_reg16_for_disconnect(vha, hccr))
369f3ddac19SChad Dupuis break;
37014e660e6SSeokmann Ju if (hccr & HCCR_RISC_PAUSE) {
37114e660e6SSeokmann Ju if (pci_channel_offline(ha->pdev))
37214e660e6SSeokmann Ju break;
37314e660e6SSeokmann Ju
37414e660e6SSeokmann Ju /*
37514e660e6SSeokmann Ju * Issue a "HARD" reset in order for the RISC interrupt
376a06a0f8eSJustin P. Mattock * bit to be cleared. Schedule a big hammer to get
37714e660e6SSeokmann Ju * out of the RISC PAUSED state.
37814e660e6SSeokmann Ju */
37904474d3aSBart Van Assche wrt_reg_word(®->hccr, HCCR_RESET_RISC);
38004474d3aSBart Van Assche rd_reg_word(®->hccr);
38114e660e6SSeokmann Ju
3828ae17876SBart Van Assche ha->isp_ops->fw_dump(vha);
383e315cd28SAnirban Chakraborty set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
38414e660e6SSeokmann Ju break;
38504474d3aSBart Van Assche } else if ((rd_reg_word(®->istatus) & ISR_RISC_INT) == 0)
3861da177e4SLinus Torvalds break;
3871da177e4SLinus Torvalds
38804474d3aSBart Van Assche if (rd_reg_word(®->semaphore) & BIT_0) {
38904474d3aSBart Van Assche wrt_reg_word(®->hccr, HCCR_CLR_RISC_INT);
39004474d3aSBart Van Assche rd_reg_word(®->hccr);
3911da177e4SLinus Torvalds
3921da177e4SLinus Torvalds /* Get mailbox data. */
3939a853f71SAndrew Vasquez mb[0] = RD_MAILBOX_REG(ha, reg, 0);
3949a853f71SAndrew Vasquez if (mb[0] > 0x3fff && mb[0] < 0x8000) {
395e315cd28SAnirban Chakraborty qla2x00_mbx_completion(vha, mb[0]);
3961da177e4SLinus Torvalds status |= MBX_INTERRUPT;
3979a853f71SAndrew Vasquez } else if (mb[0] > 0x7fff && mb[0] < 0xc000) {
3989a853f71SAndrew Vasquez mb[1] = RD_MAILBOX_REG(ha, reg, 1);
3999a853f71SAndrew Vasquez mb[2] = RD_MAILBOX_REG(ha, reg, 2);
4009a853f71SAndrew Vasquez mb[3] = RD_MAILBOX_REG(ha, reg, 3);
40173208dfdSAnirban Chakraborty qla2x00_async_event(vha, rsp, mb);
4021da177e4SLinus Torvalds } else {
4031da177e4SLinus Torvalds /*EMPTY*/
4047c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5025,
4057c3df132SSaurav Kashyap "Unrecognized interrupt type (%d).\n",
4067c3df132SSaurav Kashyap mb[0]);
4071da177e4SLinus Torvalds }
4081da177e4SLinus Torvalds /* Release mailbox registers. */
40904474d3aSBart Van Assche wrt_reg_word(®->semaphore, 0);
41004474d3aSBart Van Assche rd_reg_word(®->semaphore);
4111da177e4SLinus Torvalds } else {
41273208dfdSAnirban Chakraborty qla2x00_process_response_queue(rsp);
4131da177e4SLinus Torvalds
41404474d3aSBart Van Assche wrt_reg_word(®->hccr, HCCR_CLR_RISC_INT);
41504474d3aSBart Van Assche rd_reg_word(®->hccr);
4161da177e4SLinus Torvalds }
4171da177e4SLinus Torvalds }
41836439832Sgurinder.shergill@hp.com qla2x00_handle_mbx_completion(ha, status);
41943fac4d9SAnirban Chakraborty spin_unlock_irqrestore(&ha->hardware_lock, flags);
4201da177e4SLinus Torvalds
4211da177e4SLinus Torvalds return (IRQ_HANDLED);
4221da177e4SLinus Torvalds }
4231da177e4SLinus Torvalds
424f3ddac19SChad Dupuis bool
qla2x00_check_reg32_for_disconnect(scsi_qla_host_t * vha,uint32_t reg)425c821e0d5SJoe Lawrence qla2x00_check_reg32_for_disconnect(scsi_qla_host_t *vha, uint32_t reg)
426f3ddac19SChad Dupuis {
427f3ddac19SChad Dupuis /* Check for PCI disconnection */
428a30c2a3bSThadeu Lima de Souza Cascardo if (reg == 0xffffffff && !pci_channel_offline(vha->hw->pdev)) {
429beb9e315SJoe Lawrence if (!test_and_set_bit(PFLG_DISCONNECTED, &vha->pci_flags) &&
4306b383979SJoe Lawrence !test_bit(PFLG_DRIVER_REMOVING, &vha->pci_flags) &&
4316b383979SJoe Lawrence !test_bit(PFLG_DRIVER_PROBING, &vha->pci_flags)) {
432f7a0ed47SQuinn Tran qla_schedule_eeh_work(vha);
433232792b6SJoe Lawrence }
434f3ddac19SChad Dupuis return true;
435f3ddac19SChad Dupuis } else
436f3ddac19SChad Dupuis return false;
437f3ddac19SChad Dupuis }
438f3ddac19SChad Dupuis
439c821e0d5SJoe Lawrence bool
qla2x00_check_reg16_for_disconnect(scsi_qla_host_t * vha,uint16_t reg)440c821e0d5SJoe Lawrence qla2x00_check_reg16_for_disconnect(scsi_qla_host_t *vha, uint16_t reg)
441c821e0d5SJoe Lawrence {
442c821e0d5SJoe Lawrence return qla2x00_check_reg32_for_disconnect(vha, 0xffff0000 | reg);
443c821e0d5SJoe Lawrence }
444c821e0d5SJoe Lawrence
4451da177e4SLinus Torvalds /**
4461da177e4SLinus Torvalds * qla2300_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
447807eb907SBart Van Assche * @irq: interrupt number
4481da177e4SLinus Torvalds * @dev_id: SCSI driver HA context
4491da177e4SLinus Torvalds *
4501da177e4SLinus Torvalds * Called by system whenever the host adapter generates an interrupt.
4511da177e4SLinus Torvalds *
4521da177e4SLinus Torvalds * Returns handled flag.
4531da177e4SLinus Torvalds */
4541da177e4SLinus Torvalds irqreturn_t
qla2300_intr_handler(int irq,void * dev_id)4557d12e780SDavid Howells qla2300_intr_handler(int irq, void *dev_id)
4561da177e4SLinus Torvalds {
457e315cd28SAnirban Chakraborty scsi_qla_host_t *vha;
4583d71644cSAndrew Vasquez struct device_reg_2xxx __iomem *reg;
4591da177e4SLinus Torvalds int status;
4601da177e4SLinus Torvalds unsigned long iter;
4611da177e4SLinus Torvalds uint32_t stat;
4621da177e4SLinus Torvalds uint16_t hccr;
4630a59cea4SBart Van Assche uint16_t mb[8];
464e315cd28SAnirban Chakraborty struct rsp_que *rsp;
465e315cd28SAnirban Chakraborty struct qla_hw_data *ha;
46643fac4d9SAnirban Chakraborty unsigned long flags;
4671da177e4SLinus Torvalds
468e315cd28SAnirban Chakraborty rsp = (struct rsp_que *) dev_id;
469e315cd28SAnirban Chakraborty if (!rsp) {
4703256b435SChad Dupuis ql_log(ql_log_info, NULL, 0x5058,
4713256b435SChad Dupuis "%s: NULL response queue pointer.\n", __func__);
4721da177e4SLinus Torvalds return (IRQ_NONE);
4731da177e4SLinus Torvalds }
4741da177e4SLinus Torvalds
475e315cd28SAnirban Chakraborty ha = rsp->hw;
4763d71644cSAndrew Vasquez reg = &ha->iobase->isp;
4771da177e4SLinus Torvalds status = 0;
4781da177e4SLinus Torvalds
47943fac4d9SAnirban Chakraborty spin_lock_irqsave(&ha->hardware_lock, flags);
4802afa19a9SAnirban Chakraborty vha = pci_get_drvdata(ha->pdev);
4811da177e4SLinus Torvalds for (iter = 50; iter--; ) {
48204474d3aSBart Van Assche stat = rd_reg_dword(®->u.isp2300.host_status);
483c821e0d5SJoe Lawrence if (qla2x00_check_reg32_for_disconnect(vha, stat))
484f3ddac19SChad Dupuis break;
4851da177e4SLinus Torvalds if (stat & HSR_RISC_PAUSED) {
48685880801SAndrew Vasquez if (unlikely(pci_channel_offline(ha->pdev)))
48714e660e6SSeokmann Ju break;
48814e660e6SSeokmann Ju
48904474d3aSBart Van Assche hccr = rd_reg_word(®->hccr);
490f3ddac19SChad Dupuis
4911da177e4SLinus Torvalds if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
4927c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5026,
4937c3df132SSaurav Kashyap "Parity error -- HCCR=%x, Dumping "
4947c3df132SSaurav Kashyap "firmware.\n", hccr);
4951da177e4SLinus Torvalds else
4967c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5027,
4977c3df132SSaurav Kashyap "RISC paused -- HCCR=%x, Dumping "
4987c3df132SSaurav Kashyap "firmware.\n", hccr);
4991da177e4SLinus Torvalds
5001da177e4SLinus Torvalds /*
5011da177e4SLinus Torvalds * Issue a "HARD" reset in order for the RISC
5021da177e4SLinus Torvalds * interrupt bit to be cleared. Schedule a big
503a06a0f8eSJustin P. Mattock * hammer to get out of the RISC PAUSED state.
5041da177e4SLinus Torvalds */
50504474d3aSBart Van Assche wrt_reg_word(®->hccr, HCCR_RESET_RISC);
50604474d3aSBart Van Assche rd_reg_word(®->hccr);
50707f31805SAndrew Vasquez
5088ae17876SBart Van Assche ha->isp_ops->fw_dump(vha);
509e315cd28SAnirban Chakraborty set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
5101da177e4SLinus Torvalds break;
5111da177e4SLinus Torvalds } else if ((stat & HSR_RISC_INT) == 0)
5121da177e4SLinus Torvalds break;
5131da177e4SLinus Torvalds
5141da177e4SLinus Torvalds switch (stat & 0xff) {
5151da177e4SLinus Torvalds case 0x1:
5161da177e4SLinus Torvalds case 0x2:
5171da177e4SLinus Torvalds case 0x10:
5181da177e4SLinus Torvalds case 0x11:
519e315cd28SAnirban Chakraborty qla2x00_mbx_completion(vha, MSW(stat));
5201da177e4SLinus Torvalds status |= MBX_INTERRUPT;
5211da177e4SLinus Torvalds
5221da177e4SLinus Torvalds /* Release mailbox registers. */
52304474d3aSBart Van Assche wrt_reg_word(®->semaphore, 0);
5241da177e4SLinus Torvalds break;
5251da177e4SLinus Torvalds case 0x12:
5269a853f71SAndrew Vasquez mb[0] = MSW(stat);
5279a853f71SAndrew Vasquez mb[1] = RD_MAILBOX_REG(ha, reg, 1);
5289a853f71SAndrew Vasquez mb[2] = RD_MAILBOX_REG(ha, reg, 2);
5299a853f71SAndrew Vasquez mb[3] = RD_MAILBOX_REG(ha, reg, 3);
53073208dfdSAnirban Chakraborty qla2x00_async_event(vha, rsp, mb);
5319a853f71SAndrew Vasquez break;
5329a853f71SAndrew Vasquez case 0x13:
53373208dfdSAnirban Chakraborty qla2x00_process_response_queue(rsp);
5341da177e4SLinus Torvalds break;
5351da177e4SLinus Torvalds case 0x15:
5369a853f71SAndrew Vasquez mb[0] = MBA_CMPLT_1_16BIT;
5379a853f71SAndrew Vasquez mb[1] = MSW(stat);
53873208dfdSAnirban Chakraborty qla2x00_async_event(vha, rsp, mb);
5391da177e4SLinus Torvalds break;
5401da177e4SLinus Torvalds case 0x16:
5419a853f71SAndrew Vasquez mb[0] = MBA_SCSI_COMPLETION;
5429a853f71SAndrew Vasquez mb[1] = MSW(stat);
5439a853f71SAndrew Vasquez mb[2] = RD_MAILBOX_REG(ha, reg, 2);
54473208dfdSAnirban Chakraborty qla2x00_async_event(vha, rsp, mb);
5451da177e4SLinus Torvalds break;
5461da177e4SLinus Torvalds default:
5477c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5028,
5487c3df132SSaurav Kashyap "Unrecognized interrupt type (%d).\n", stat & 0xff);
5491da177e4SLinus Torvalds break;
5501da177e4SLinus Torvalds }
55104474d3aSBart Van Assche wrt_reg_word(®->hccr, HCCR_CLR_RISC_INT);
55204474d3aSBart Van Assche rd_reg_word_relaxed(®->hccr);
5531da177e4SLinus Torvalds }
55436439832Sgurinder.shergill@hp.com qla2x00_handle_mbx_completion(ha, status);
55543fac4d9SAnirban Chakraborty spin_unlock_irqrestore(&ha->hardware_lock, flags);
5561da177e4SLinus Torvalds
5571da177e4SLinus Torvalds return (IRQ_HANDLED);
5581da177e4SLinus Torvalds }
5591da177e4SLinus Torvalds
5601da177e4SLinus Torvalds /**
5611da177e4SLinus Torvalds * qla2x00_mbx_completion() - Process mailbox command completions.
5622db6228dSBart Van Assche * @vha: SCSI driver HA context
5631da177e4SLinus Torvalds * @mb0: Mailbox0 register
5641da177e4SLinus Torvalds */
5651da177e4SLinus Torvalds static void
qla2x00_mbx_completion(scsi_qla_host_t * vha,uint16_t mb0)566e315cd28SAnirban Chakraborty qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
5671da177e4SLinus Torvalds {
5681da177e4SLinus Torvalds uint16_t cnt;
5694fa94f83SAndrew Vasquez uint32_t mboxes;
5707ffa5b93SBart Van Assche __le16 __iomem *wptr;
571e315cd28SAnirban Chakraborty struct qla_hw_data *ha = vha->hw;
5723d71644cSAndrew Vasquez struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
5731da177e4SLinus Torvalds
5744fa94f83SAndrew Vasquez /* Read all mbox registers? */
575c02189e1SBart Van Assche WARN_ON_ONCE(ha->mbx_count > 32);
576c02189e1SBart Van Assche mboxes = (1ULL << ha->mbx_count) - 1;
5774fa94f83SAndrew Vasquez if (!ha->mcp)
578a720101dSMasanari Iida ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERROR.\n");
5794fa94f83SAndrew Vasquez else
5804fa94f83SAndrew Vasquez mboxes = ha->mcp->in_mb;
5814fa94f83SAndrew Vasquez
5821da177e4SLinus Torvalds /* Load return mailbox registers. */
5831da177e4SLinus Torvalds ha->flags.mbox_int = 1;
5841da177e4SLinus Torvalds ha->mailbox_out[0] = mb0;
5854fa94f83SAndrew Vasquez mboxes >>= 1;
5867ffa5b93SBart Van Assche wptr = MAILBOX_REG(ha, reg, 1);
5871da177e4SLinus Torvalds
5881da177e4SLinus Torvalds for (cnt = 1; cnt < ha->mbx_count; cnt++) {
5891da177e4SLinus Torvalds if (IS_QLA2200(ha) && cnt == 8)
5907ffa5b93SBart Van Assche wptr = MAILBOX_REG(ha, reg, 8);
5914fa94f83SAndrew Vasquez if ((cnt == 4 || cnt == 5) && (mboxes & BIT_0))
5921da177e4SLinus Torvalds ha->mailbox_out[cnt] = qla2x00_debounce_register(wptr);
5934fa94f83SAndrew Vasquez else if (mboxes & BIT_0)
59404474d3aSBart Van Assche ha->mailbox_out[cnt] = rd_reg_word(wptr);
5951da177e4SLinus Torvalds
5961da177e4SLinus Torvalds wptr++;
5974fa94f83SAndrew Vasquez mboxes >>= 1;
5981da177e4SLinus Torvalds }
5991da177e4SLinus Torvalds }
6001da177e4SLinus Torvalds
6018a659571SAndrew Vasquez static void
qla81xx_idc_event(scsi_qla_host_t * vha,uint16_t aen,uint16_t descr)6028a659571SAndrew Vasquez qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr)
6038a659571SAndrew Vasquez {
6048a659571SAndrew Vasquez static char *event[] =
6058a659571SAndrew Vasquez { "Complete", "Request Notification", "Time Extension" };
6068a659571SAndrew Vasquez int rval;
6078a659571SAndrew Vasquez struct device_reg_24xx __iomem *reg24 = &vha->hw->iobase->isp24;
6089e5054ecSChad Dupuis struct device_reg_82xx __iomem *reg82 = &vha->hw->iobase->isp82;
60937139da1SBart Van Assche __le16 __iomem *wptr;
6108a659571SAndrew Vasquez uint16_t cnt, timeout, mb[QLA_IDC_ACK_REGS];
6118a659571SAndrew Vasquez
6128a659571SAndrew Vasquez /* Seed data -- mailbox1 -> mailbox7. */
6139e5054ecSChad Dupuis if (IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw))
6147ffa5b93SBart Van Assche wptr = ®24->mailbox1;
6159e5054ecSChad Dupuis else if (IS_QLA8044(vha->hw))
6167ffa5b93SBart Van Assche wptr = ®82->mailbox_out[1];
6179e5054ecSChad Dupuis else
6189e5054ecSChad Dupuis return;
6199e5054ecSChad Dupuis
6208a659571SAndrew Vasquez for (cnt = 0; cnt < QLA_IDC_ACK_REGS; cnt++, wptr++)
62104474d3aSBart Van Assche mb[cnt] = rd_reg_word(wptr);
6228a659571SAndrew Vasquez
6237c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5021,
6246246b8a1SGiridhar Malavali "Inter-Driver Communication %s -- "
6257c3df132SSaurav Kashyap "%04x %04x %04x %04x %04x %04x %04x.\n",
6267c3df132SSaurav Kashyap event[aen & 0xff], mb[0], mb[1], mb[2], mb[3],
6277c3df132SSaurav Kashyap mb[4], mb[5], mb[6]);
628454073c9SSantosh Vernekar switch (aen) {
629454073c9SSantosh Vernekar /* Handle IDC Error completion case. */
630454073c9SSantosh Vernekar case MBA_IDC_COMPLETE:
631454073c9SSantosh Vernekar if (mb[1] >> 15) {
632bf5b8ad7SChad Dupuis vha->hw->flags.idc_compl_status = 1;
6339aaf2ceaSChad Dupuis if (vha->hw->notify_dcbx_comp && !vha->vp_idx)
634bf5b8ad7SChad Dupuis complete(&vha->hw->dcbx_comp);
635bf5b8ad7SChad Dupuis }
636454073c9SSantosh Vernekar break;
6378a659571SAndrew Vasquez
638454073c9SSantosh Vernekar case MBA_IDC_NOTIFY:
6398a659571SAndrew Vasquez /* Acknowledgement needed? [Notify && non-zero timeout]. */
6408a659571SAndrew Vasquez timeout = (descr >> 8) & 0xf;
6417c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5022,
642d8424f68SJoe Perches "%lu Inter-Driver Communication %s -- ACK timeout=%d.\n",
6437c3df132SSaurav Kashyap vha->host_no, event[aen & 0xff], timeout);
6448a659571SAndrew Vasquez
645454073c9SSantosh Vernekar if (!timeout)
646454073c9SSantosh Vernekar return;
6478a659571SAndrew Vasquez rval = qla2x00_post_idc_ack_work(vha, mb);
6488a659571SAndrew Vasquez if (rval != QLA_SUCCESS)
6497c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5023,
6508a659571SAndrew Vasquez "IDC failed to post ACK.\n");
651454073c9SSantosh Vernekar break;
652454073c9SSantosh Vernekar case MBA_IDC_TIME_EXT:
653454073c9SSantosh Vernekar vha->hw->idc_extend_tmo = descr;
654454073c9SSantosh Vernekar ql_dbg(ql_dbg_async, vha, 0x5087,
655454073c9SSantosh Vernekar "%lu Inter-Driver Communication %s -- "
656454073c9SSantosh Vernekar "Extend timeout by=%d.\n",
657454073c9SSantosh Vernekar vha->host_no, event[aen & 0xff], vha->hw->idc_extend_tmo);
658454073c9SSantosh Vernekar break;
659454073c9SSantosh Vernekar }
6608a659571SAndrew Vasquez }
6618a659571SAndrew Vasquez
662daae62a3SChad Dupuis #define LS_UNKNOWN 2
663d0297c9aSJoe Carnuccio const char *
qla2x00_get_link_speed_str(struct qla_hw_data * ha,uint16_t speed)664d0297c9aSJoe Carnuccio qla2x00_get_link_speed_str(struct qla_hw_data *ha, uint16_t speed)
665daae62a3SChad Dupuis {
666d0297c9aSJoe Carnuccio static const char *const link_speeds[] = {
66785818882SQuinn Tran "1", "2", "?", "4", "8", "16", "32", "64", "10"
668d0297c9aSJoe Carnuccio };
669b0a1c5b5SBart Van Assche #define QLA_LAST_SPEED (ARRAY_SIZE(link_speeds) - 1)
670daae62a3SChad Dupuis
671daae62a3SChad Dupuis if (IS_QLA2100(ha) || IS_QLA2200(ha))
672d0297c9aSJoe Carnuccio return link_speeds[0];
673d0297c9aSJoe Carnuccio else if (speed == 0x13)
674f73cb695SChad Dupuis return link_speeds[QLA_LAST_SPEED];
675f73cb695SChad Dupuis else if (speed < QLA_LAST_SPEED)
676d0297c9aSJoe Carnuccio return link_speeds[speed];
677d0297c9aSJoe Carnuccio else
678d0297c9aSJoe Carnuccio return link_speeds[LS_UNKNOWN];
679daae62a3SChad Dupuis }
680daae62a3SChad Dupuis
681fa492630SSaurav Kashyap static void
qla83xx_handle_8200_aen(scsi_qla_host_t * vha,uint16_t * mb)6827d613ac6SSantosh Vernekar qla83xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb)
6837d613ac6SSantosh Vernekar {
6847d613ac6SSantosh Vernekar struct qla_hw_data *ha = vha->hw;
6857d613ac6SSantosh Vernekar
6867d613ac6SSantosh Vernekar /*
6877d613ac6SSantosh Vernekar * 8200 AEN Interpretation:
6887d613ac6SSantosh Vernekar * mb[0] = AEN code
6897d613ac6SSantosh Vernekar * mb[1] = AEN Reason code
6907d613ac6SSantosh Vernekar * mb[2] = LSW of Peg-Halt Status-1 Register
6917d613ac6SSantosh Vernekar * mb[6] = MSW of Peg-Halt Status-1 Register
6927d613ac6SSantosh Vernekar * mb[3] = LSW of Peg-Halt Status-2 register
6937d613ac6SSantosh Vernekar * mb[7] = MSW of Peg-Halt Status-2 register
6947d613ac6SSantosh Vernekar * mb[4] = IDC Device-State Register value
6957d613ac6SSantosh Vernekar * mb[5] = IDC Driver-Presence Register value
6967d613ac6SSantosh Vernekar */
6977d613ac6SSantosh Vernekar ql_dbg(ql_dbg_async, vha, 0x506b, "AEN Code: mb[0] = 0x%x AEN reason: "
6987d613ac6SSantosh Vernekar "mb[1] = 0x%x PH-status1: mb[2] = 0x%x PH-status1: mb[6] = 0x%x.\n",
6997d613ac6SSantosh Vernekar mb[0], mb[1], mb[2], mb[6]);
7007d613ac6SSantosh Vernekar ql_dbg(ql_dbg_async, vha, 0x506c, "PH-status2: mb[3] = 0x%x "
7017d613ac6SSantosh Vernekar "PH-status2: mb[7] = 0x%x Device-State: mb[4] = 0x%x "
7027d613ac6SSantosh Vernekar "Drv-Presence: mb[5] = 0x%x.\n", mb[3], mb[7], mb[4], mb[5]);
7037d613ac6SSantosh Vernekar
7047d613ac6SSantosh Vernekar if (mb[1] & (IDC_PEG_HALT_STATUS_CHANGE | IDC_NIC_FW_REPORTED_FAILURE |
7057d613ac6SSantosh Vernekar IDC_HEARTBEAT_FAILURE)) {
7067d613ac6SSantosh Vernekar ha->flags.nic_core_hung = 1;
7077d613ac6SSantosh Vernekar ql_log(ql_log_warn, vha, 0x5060,
7087d613ac6SSantosh Vernekar "83XX: F/W Error Reported: Check if reset required.\n");
7097d613ac6SSantosh Vernekar
7107d613ac6SSantosh Vernekar if (mb[1] & IDC_PEG_HALT_STATUS_CHANGE) {
7117d613ac6SSantosh Vernekar uint32_t protocol_engine_id, fw_err_code, err_level;
7127d613ac6SSantosh Vernekar
7137d613ac6SSantosh Vernekar /*
7147d613ac6SSantosh Vernekar * IDC_PEG_HALT_STATUS_CHANGE interpretation:
7157d613ac6SSantosh Vernekar * - PEG-Halt Status-1 Register:
7167d613ac6SSantosh Vernekar * (LSW = mb[2], MSW = mb[6])
7177d613ac6SSantosh Vernekar * Bits 0-7 = protocol-engine ID
7187d613ac6SSantosh Vernekar * Bits 8-28 = f/w error code
7197d613ac6SSantosh Vernekar * Bits 29-31 = Error-level
7207d613ac6SSantosh Vernekar * Error-level 0x1 = Non-Fatal error
7217d613ac6SSantosh Vernekar * Error-level 0x2 = Recoverable Fatal error
7227d613ac6SSantosh Vernekar * Error-level 0x4 = UnRecoverable Fatal error
7237d613ac6SSantosh Vernekar * - PEG-Halt Status-2 Register:
7247d613ac6SSantosh Vernekar * (LSW = mb[3], MSW = mb[7])
7257d613ac6SSantosh Vernekar */
7267d613ac6SSantosh Vernekar protocol_engine_id = (mb[2] & 0xff);
7277d613ac6SSantosh Vernekar fw_err_code = (((mb[2] & 0xff00) >> 8) |
7287d613ac6SSantosh Vernekar ((mb[6] & 0x1fff) << 8));
7297d613ac6SSantosh Vernekar err_level = ((mb[6] & 0xe000) >> 13);
7307d613ac6SSantosh Vernekar ql_log(ql_log_warn, vha, 0x5061, "PegHalt Status-1 "
7317d613ac6SSantosh Vernekar "Register: protocol_engine_id=0x%x "
7327d613ac6SSantosh Vernekar "fw_err_code=0x%x err_level=0x%x.\n",
7337d613ac6SSantosh Vernekar protocol_engine_id, fw_err_code, err_level);
7347d613ac6SSantosh Vernekar ql_log(ql_log_warn, vha, 0x5062, "PegHalt Status-2 "
7357d613ac6SSantosh Vernekar "Register: 0x%x%x.\n", mb[7], mb[3]);
7367d613ac6SSantosh Vernekar if (err_level == ERR_LEVEL_NON_FATAL) {
7377d613ac6SSantosh Vernekar ql_log(ql_log_warn, vha, 0x5063,
7380bf0efa1SColin Ian King "Not a fatal error, f/w has recovered itself.\n");
7397d613ac6SSantosh Vernekar } else if (err_level == ERR_LEVEL_RECOVERABLE_FATAL) {
7407d613ac6SSantosh Vernekar ql_log(ql_log_fatal, vha, 0x5064,
7417d613ac6SSantosh Vernekar "Recoverable Fatal error: Chip reset "
7427d613ac6SSantosh Vernekar "required.\n");
7437d613ac6SSantosh Vernekar qla83xx_schedule_work(vha,
7447d613ac6SSantosh Vernekar QLA83XX_NIC_CORE_RESET);
7457d613ac6SSantosh Vernekar } else if (err_level == ERR_LEVEL_UNRECOVERABLE_FATAL) {
7467d613ac6SSantosh Vernekar ql_log(ql_log_fatal, vha, 0x5065,
7477d613ac6SSantosh Vernekar "Unrecoverable Fatal error: Set FAILED "
7487d613ac6SSantosh Vernekar "state, reboot required.\n");
7497d613ac6SSantosh Vernekar qla83xx_schedule_work(vha,
7507d613ac6SSantosh Vernekar QLA83XX_NIC_CORE_UNRECOVERABLE);
7517d613ac6SSantosh Vernekar }
7527d613ac6SSantosh Vernekar }
7537d613ac6SSantosh Vernekar
7547d613ac6SSantosh Vernekar if (mb[1] & IDC_NIC_FW_REPORTED_FAILURE) {
7557d613ac6SSantosh Vernekar uint16_t peg_fw_state, nw_interface_link_up;
7567d613ac6SSantosh Vernekar uint16_t nw_interface_signal_detect, sfp_status;
7577d613ac6SSantosh Vernekar uint16_t htbt_counter, htbt_monitor_enable;
758b4a028a5SColin Ian King uint16_t sfp_additional_info, sfp_multirate;
7597d613ac6SSantosh Vernekar uint16_t sfp_tx_fault, link_speed, dcbx_status;
7607d613ac6SSantosh Vernekar
7617d613ac6SSantosh Vernekar /*
7627d613ac6SSantosh Vernekar * IDC_NIC_FW_REPORTED_FAILURE interpretation:
7637d613ac6SSantosh Vernekar * - PEG-to-FC Status Register:
7647d613ac6SSantosh Vernekar * (LSW = mb[2], MSW = mb[6])
7657d613ac6SSantosh Vernekar * Bits 0-7 = Peg-Firmware state
7667d613ac6SSantosh Vernekar * Bit 8 = N/W Interface Link-up
7677d613ac6SSantosh Vernekar * Bit 9 = N/W Interface signal detected
7687d613ac6SSantosh Vernekar * Bits 10-11 = SFP Status
7697d613ac6SSantosh Vernekar * SFP Status 0x0 = SFP+ transceiver not expected
7707d613ac6SSantosh Vernekar * SFP Status 0x1 = SFP+ transceiver not present
7717d613ac6SSantosh Vernekar * SFP Status 0x2 = SFP+ transceiver invalid
7727d613ac6SSantosh Vernekar * SFP Status 0x3 = SFP+ transceiver present and
7737d613ac6SSantosh Vernekar * valid
7747d613ac6SSantosh Vernekar * Bits 12-14 = Heartbeat Counter
7757d613ac6SSantosh Vernekar * Bit 15 = Heartbeat Monitor Enable
7767d613ac6SSantosh Vernekar * Bits 16-17 = SFP Additional Info
7777d613ac6SSantosh Vernekar * SFP info 0x0 = Unregocnized transceiver for
7787d613ac6SSantosh Vernekar * Ethernet
7797d613ac6SSantosh Vernekar * SFP info 0x1 = SFP+ brand validation failed
7807d613ac6SSantosh Vernekar * SFP info 0x2 = SFP+ speed validation failed
7817d613ac6SSantosh Vernekar * SFP info 0x3 = SFP+ access error
7827d613ac6SSantosh Vernekar * Bit 18 = SFP Multirate
7837d613ac6SSantosh Vernekar * Bit 19 = SFP Tx Fault
7847d613ac6SSantosh Vernekar * Bits 20-22 = Link Speed
7857d613ac6SSantosh Vernekar * Bits 23-27 = Reserved
7867d613ac6SSantosh Vernekar * Bits 28-30 = DCBX Status
7877d613ac6SSantosh Vernekar * DCBX Status 0x0 = DCBX Disabled
7887d613ac6SSantosh Vernekar * DCBX Status 0x1 = DCBX Enabled
7897d613ac6SSantosh Vernekar * DCBX Status 0x2 = DCBX Exchange error
7907d613ac6SSantosh Vernekar * Bit 31 = Reserved
7917d613ac6SSantosh Vernekar */
7927d613ac6SSantosh Vernekar peg_fw_state = (mb[2] & 0x00ff);
7937d613ac6SSantosh Vernekar nw_interface_link_up = ((mb[2] & 0x0100) >> 8);
7947d613ac6SSantosh Vernekar nw_interface_signal_detect = ((mb[2] & 0x0200) >> 9);
7957d613ac6SSantosh Vernekar sfp_status = ((mb[2] & 0x0c00) >> 10);
7967d613ac6SSantosh Vernekar htbt_counter = ((mb[2] & 0x7000) >> 12);
7977d613ac6SSantosh Vernekar htbt_monitor_enable = ((mb[2] & 0x8000) >> 15);
798b4a028a5SColin Ian King sfp_additional_info = (mb[6] & 0x0003);
7997d613ac6SSantosh Vernekar sfp_multirate = ((mb[6] & 0x0004) >> 2);
8007d613ac6SSantosh Vernekar sfp_tx_fault = ((mb[6] & 0x0008) >> 3);
8017d613ac6SSantosh Vernekar link_speed = ((mb[6] & 0x0070) >> 4);
8027d613ac6SSantosh Vernekar dcbx_status = ((mb[6] & 0x7000) >> 12);
8037d613ac6SSantosh Vernekar
8047d613ac6SSantosh Vernekar ql_log(ql_log_warn, vha, 0x5066,
8057d613ac6SSantosh Vernekar "Peg-to-Fc Status Register:\n"
8067d613ac6SSantosh Vernekar "peg_fw_state=0x%x, nw_interface_link_up=0x%x, "
8077d613ac6SSantosh Vernekar "nw_interface_signal_detect=0x%x"
8087d613ac6SSantosh Vernekar "\nsfp_statis=0x%x.\n ", peg_fw_state,
8097d613ac6SSantosh Vernekar nw_interface_link_up, nw_interface_signal_detect,
8107d613ac6SSantosh Vernekar sfp_status);
8117d613ac6SSantosh Vernekar ql_log(ql_log_warn, vha, 0x5067,
8127d613ac6SSantosh Vernekar "htbt_counter=0x%x, htbt_monitor_enable=0x%x, "
813b4a028a5SColin Ian King "sfp_additional_info=0x%x, sfp_multirate=0x%x.\n ",
8147d613ac6SSantosh Vernekar htbt_counter, htbt_monitor_enable,
815b4a028a5SColin Ian King sfp_additional_info, sfp_multirate);
8167d613ac6SSantosh Vernekar ql_log(ql_log_warn, vha, 0x5068,
8177d613ac6SSantosh Vernekar "sfp_tx_fault=0x%x, link_state=0x%x, "
8187d613ac6SSantosh Vernekar "dcbx_status=0x%x.\n", sfp_tx_fault, link_speed,
8197d613ac6SSantosh Vernekar dcbx_status);
8207d613ac6SSantosh Vernekar
8217d613ac6SSantosh Vernekar qla83xx_schedule_work(vha, QLA83XX_NIC_CORE_RESET);
8227d613ac6SSantosh Vernekar }
8237d613ac6SSantosh Vernekar
8247d613ac6SSantosh Vernekar if (mb[1] & IDC_HEARTBEAT_FAILURE) {
8257d613ac6SSantosh Vernekar ql_log(ql_log_warn, vha, 0x5069,
8267d613ac6SSantosh Vernekar "Heartbeat Failure encountered, chip reset "
8277d613ac6SSantosh Vernekar "required.\n");
8287d613ac6SSantosh Vernekar
8297d613ac6SSantosh Vernekar qla83xx_schedule_work(vha, QLA83XX_NIC_CORE_RESET);
8307d613ac6SSantosh Vernekar }
8317d613ac6SSantosh Vernekar }
8327d613ac6SSantosh Vernekar
8337d613ac6SSantosh Vernekar if (mb[1] & IDC_DEVICE_STATE_CHANGE) {
8347d613ac6SSantosh Vernekar ql_log(ql_log_info, vha, 0x506a,
8357d613ac6SSantosh Vernekar "IDC Device-State changed = 0x%x.\n", mb[4]);
8366c3943cdSSaurav Kashyap if (ha->flags.nic_core_reset_owner)
8376c3943cdSSaurav Kashyap return;
8387d613ac6SSantosh Vernekar qla83xx_schedule_work(vha, MBA_IDC_AEN);
8397d613ac6SSantosh Vernekar }
8407d613ac6SSantosh Vernekar }
8417d613ac6SSantosh Vernekar
842875386b9SManish Rangankar /**
843875386b9SManish Rangankar * qla27xx_copy_multiple_pkt() - Copy over purex/purls packets that can
844875386b9SManish Rangankar * span over multiple IOCBs.
845875386b9SManish Rangankar * @vha: SCSI driver HA context
846875386b9SManish Rangankar * @pkt: ELS packet
847875386b9SManish Rangankar * @rsp: Response queue
848875386b9SManish Rangankar * @is_purls: True, for Unsolicited Received FC-NVMe LS rsp IOCB
849875386b9SManish Rangankar * false, for Unsolicited Received ELS IOCB
850875386b9SManish Rangankar * @byte_order: True, to change the byte ordering of iocb payload
851875386b9SManish Rangankar */
852875386b9SManish Rangankar struct purex_item *
qla27xx_copy_multiple_pkt(struct scsi_qla_host * vha,void ** pkt,struct rsp_que ** rsp,bool is_purls,bool byte_order)853875386b9SManish Rangankar qla27xx_copy_multiple_pkt(struct scsi_qla_host *vha, void **pkt,
854875386b9SManish Rangankar struct rsp_que **rsp, bool is_purls,
855875386b9SManish Rangankar bool byte_order)
856875386b9SManish Rangankar {
857875386b9SManish Rangankar struct purex_entry_24xx *purex = NULL;
858875386b9SManish Rangankar struct pt_ls4_rx_unsol *purls = NULL;
859875386b9SManish Rangankar struct rsp_que *rsp_q = *rsp;
860875386b9SManish Rangankar sts_cont_entry_t *new_pkt;
861875386b9SManish Rangankar uint16_t no_bytes = 0, total_bytes = 0, pending_bytes = 0;
862875386b9SManish Rangankar uint16_t buffer_copy_offset = 0, payload_size = 0;
863875386b9SManish Rangankar uint16_t entry_count, entry_count_remaining;
864875386b9SManish Rangankar struct purex_item *item;
865875386b9SManish Rangankar void *iocb_pkt = NULL;
866875386b9SManish Rangankar
867875386b9SManish Rangankar if (is_purls) {
868875386b9SManish Rangankar purls = *pkt;
869875386b9SManish Rangankar total_bytes = (le16_to_cpu(purls->frame_size) & 0x0FFF) -
870875386b9SManish Rangankar PURX_ELS_HEADER_SIZE;
871875386b9SManish Rangankar entry_count = entry_count_remaining = purls->entry_count;
872875386b9SManish Rangankar payload_size = sizeof(purls->payload);
873875386b9SManish Rangankar } else {
874875386b9SManish Rangankar purex = *pkt;
875875386b9SManish Rangankar total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF) -
876875386b9SManish Rangankar PURX_ELS_HEADER_SIZE;
877875386b9SManish Rangankar entry_count = entry_count_remaining = purex->entry_count;
878875386b9SManish Rangankar payload_size = sizeof(purex->els_frame_payload);
879875386b9SManish Rangankar }
880875386b9SManish Rangankar
881875386b9SManish Rangankar pending_bytes = total_bytes;
882875386b9SManish Rangankar no_bytes = (pending_bytes > payload_size) ? payload_size :
883875386b9SManish Rangankar pending_bytes;
884875386b9SManish Rangankar ql_dbg(ql_dbg_async, vha, 0x509a,
885875386b9SManish Rangankar "%s LS, frame_size 0x%x, entry count %d\n",
886875386b9SManish Rangankar (is_purls ? "PURLS" : "FPIN"), total_bytes, entry_count);
887875386b9SManish Rangankar
888875386b9SManish Rangankar item = qla24xx_alloc_purex_item(vha, total_bytes);
889875386b9SManish Rangankar if (!item)
890875386b9SManish Rangankar return item;
891875386b9SManish Rangankar
892875386b9SManish Rangankar iocb_pkt = &item->iocb;
893875386b9SManish Rangankar
894875386b9SManish Rangankar if (is_purls)
895875386b9SManish Rangankar memcpy(iocb_pkt, &purls->payload[0], no_bytes);
896875386b9SManish Rangankar else
897875386b9SManish Rangankar memcpy(iocb_pkt, &purex->els_frame_payload[0], no_bytes);
898875386b9SManish Rangankar buffer_copy_offset += no_bytes;
899875386b9SManish Rangankar pending_bytes -= no_bytes;
900875386b9SManish Rangankar --entry_count_remaining;
901875386b9SManish Rangankar
902875386b9SManish Rangankar if (is_purls)
903875386b9SManish Rangankar ((response_t *)purls)->signature = RESPONSE_PROCESSED;
904875386b9SManish Rangankar else
905875386b9SManish Rangankar ((response_t *)purex)->signature = RESPONSE_PROCESSED;
906875386b9SManish Rangankar wmb();
907875386b9SManish Rangankar
908875386b9SManish Rangankar do {
909875386b9SManish Rangankar while ((total_bytes > 0) && (entry_count_remaining > 0)) {
910875386b9SManish Rangankar if (rsp_q->ring_ptr->signature == RESPONSE_PROCESSED) {
911875386b9SManish Rangankar ql_dbg(ql_dbg_async, vha, 0x5084,
912875386b9SManish Rangankar "Ran out of IOCBs, partial data 0x%x\n",
913875386b9SManish Rangankar buffer_copy_offset);
914875386b9SManish Rangankar cpu_relax();
915875386b9SManish Rangankar continue;
916875386b9SManish Rangankar }
917875386b9SManish Rangankar
918875386b9SManish Rangankar new_pkt = (sts_cont_entry_t *)rsp_q->ring_ptr;
919875386b9SManish Rangankar *pkt = new_pkt;
920875386b9SManish Rangankar
921875386b9SManish Rangankar if (new_pkt->entry_type != STATUS_CONT_TYPE) {
922875386b9SManish Rangankar ql_log(ql_log_warn, vha, 0x507a,
923875386b9SManish Rangankar "Unexpected IOCB type, partial data 0x%x\n",
924875386b9SManish Rangankar buffer_copy_offset);
925875386b9SManish Rangankar break;
926875386b9SManish Rangankar }
927875386b9SManish Rangankar
928875386b9SManish Rangankar rsp_q->ring_index++;
929875386b9SManish Rangankar if (rsp_q->ring_index == rsp_q->length) {
930875386b9SManish Rangankar rsp_q->ring_index = 0;
931875386b9SManish Rangankar rsp_q->ring_ptr = rsp_q->ring;
932875386b9SManish Rangankar } else {
933875386b9SManish Rangankar rsp_q->ring_ptr++;
934875386b9SManish Rangankar }
935875386b9SManish Rangankar no_bytes = (pending_bytes > sizeof(new_pkt->data)) ?
936875386b9SManish Rangankar sizeof(new_pkt->data) : pending_bytes;
937875386b9SManish Rangankar if ((buffer_copy_offset + no_bytes) <= total_bytes) {
938875386b9SManish Rangankar memcpy(((uint8_t *)iocb_pkt + buffer_copy_offset),
939875386b9SManish Rangankar new_pkt->data, no_bytes);
940875386b9SManish Rangankar buffer_copy_offset += no_bytes;
941875386b9SManish Rangankar pending_bytes -= no_bytes;
942875386b9SManish Rangankar --entry_count_remaining;
943875386b9SManish Rangankar } else {
944875386b9SManish Rangankar ql_log(ql_log_warn, vha, 0x5044,
945875386b9SManish Rangankar "Attempt to copy more that we got, optimizing..%x\n",
946875386b9SManish Rangankar buffer_copy_offset);
947875386b9SManish Rangankar memcpy(((uint8_t *)iocb_pkt + buffer_copy_offset),
948875386b9SManish Rangankar new_pkt->data,
949875386b9SManish Rangankar total_bytes - buffer_copy_offset);
950875386b9SManish Rangankar }
951875386b9SManish Rangankar
952875386b9SManish Rangankar ((response_t *)new_pkt)->signature = RESPONSE_PROCESSED;
953875386b9SManish Rangankar wmb();
954875386b9SManish Rangankar }
955875386b9SManish Rangankar
956875386b9SManish Rangankar if (pending_bytes != 0 || entry_count_remaining != 0) {
957875386b9SManish Rangankar ql_log(ql_log_fatal, vha, 0x508b,
958875386b9SManish Rangankar "Dropping partial FPIN, underrun bytes = 0x%x, entry cnts 0x%x\n",
959875386b9SManish Rangankar total_bytes, entry_count_remaining);
960875386b9SManish Rangankar qla24xx_free_purex_item(item);
961875386b9SManish Rangankar return NULL;
962875386b9SManish Rangankar }
963875386b9SManish Rangankar } while (entry_count_remaining > 0);
964875386b9SManish Rangankar
965875386b9SManish Rangankar if (byte_order)
966875386b9SManish Rangankar host_to_fcp_swap((uint8_t *)&item->iocb, total_bytes);
967875386b9SManish Rangankar
968875386b9SManish Rangankar return item;
969875386b9SManish Rangankar }
970875386b9SManish Rangankar
971bb4cf5b7SChad Dupuis int
qla2x00_is_a_vp_did(scsi_qla_host_t * vha,uint32_t rscn_entry)972bb4cf5b7SChad Dupuis qla2x00_is_a_vp_did(scsi_qla_host_t *vha, uint32_t rscn_entry)
973bb4cf5b7SChad Dupuis {
974bb4cf5b7SChad Dupuis struct qla_hw_data *ha = vha->hw;
975bb4cf5b7SChad Dupuis scsi_qla_host_t *vp;
976bb4cf5b7SChad Dupuis uint32_t vp_did;
977bb4cf5b7SChad Dupuis unsigned long flags;
978bb4cf5b7SChad Dupuis int ret = 0;
979bb4cf5b7SChad Dupuis
980bb4cf5b7SChad Dupuis if (!ha->num_vhosts)
981bb4cf5b7SChad Dupuis return ret;
982bb4cf5b7SChad Dupuis
983bb4cf5b7SChad Dupuis spin_lock_irqsave(&ha->vport_slock, flags);
984bb4cf5b7SChad Dupuis list_for_each_entry(vp, &ha->vp_list, list) {
985bb4cf5b7SChad Dupuis vp_did = vp->d_id.b24;
986bb4cf5b7SChad Dupuis if (vp_did == rscn_entry) {
987bb4cf5b7SChad Dupuis ret = 1;
988bb4cf5b7SChad Dupuis break;
989bb4cf5b7SChad Dupuis }
990bb4cf5b7SChad Dupuis }
991bb4cf5b7SChad Dupuis spin_unlock_irqrestore(&ha->vport_slock, flags);
992bb4cf5b7SChad Dupuis
993bb4cf5b7SChad Dupuis return ret;
994bb4cf5b7SChad Dupuis }
995bb4cf5b7SChad Dupuis
996726b8548SQuinn Tran fc_port_t *
qla2x00_find_fcport_by_loopid(scsi_qla_host_t * vha,uint16_t loop_id)99717cac3a1SJoe Carnuccio qla2x00_find_fcport_by_loopid(scsi_qla_host_t *vha, uint16_t loop_id)
99817cac3a1SJoe Carnuccio {
999726b8548SQuinn Tran fc_port_t *f, *tf;
100017cac3a1SJoe Carnuccio
1001726b8548SQuinn Tran f = tf = NULL;
1002726b8548SQuinn Tran list_for_each_entry_safe(f, tf, &vha->vp_fcports, list)
1003726b8548SQuinn Tran if (f->loop_id == loop_id)
1004726b8548SQuinn Tran return f;
1005726b8548SQuinn Tran return NULL;
1006726b8548SQuinn Tran }
1007726b8548SQuinn Tran
1008726b8548SQuinn Tran fc_port_t *
qla2x00_find_fcport_by_wwpn(scsi_qla_host_t * vha,u8 * wwpn,u8 incl_deleted)1009726b8548SQuinn Tran qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *vha, u8 *wwpn, u8 incl_deleted)
1010726b8548SQuinn Tran {
1011726b8548SQuinn Tran fc_port_t *f, *tf;
1012726b8548SQuinn Tran
1013726b8548SQuinn Tran f = tf = NULL;
1014726b8548SQuinn Tran list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
1015726b8548SQuinn Tran if (memcmp(f->port_name, wwpn, WWN_SIZE) == 0) {
1016726b8548SQuinn Tran if (incl_deleted)
1017726b8548SQuinn Tran return f;
1018726b8548SQuinn Tran else if (f->deleted == 0)
1019726b8548SQuinn Tran return f;
1020726b8548SQuinn Tran }
1021726b8548SQuinn Tran }
1022726b8548SQuinn Tran return NULL;
1023726b8548SQuinn Tran }
1024726b8548SQuinn Tran
1025726b8548SQuinn Tran fc_port_t *
qla2x00_find_fcport_by_nportid(scsi_qla_host_t * vha,port_id_t * id,u8 incl_deleted)1026726b8548SQuinn Tran qla2x00_find_fcport_by_nportid(scsi_qla_host_t *vha, port_id_t *id,
1027726b8548SQuinn Tran u8 incl_deleted)
1028726b8548SQuinn Tran {
1029726b8548SQuinn Tran fc_port_t *f, *tf;
1030726b8548SQuinn Tran
1031726b8548SQuinn Tran f = tf = NULL;
1032726b8548SQuinn Tran list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
1033726b8548SQuinn Tran if (f->d_id.b24 == id->b24) {
1034726b8548SQuinn Tran if (incl_deleted)
1035726b8548SQuinn Tran return f;
1036726b8548SQuinn Tran else if (f->deleted == 0)
1037726b8548SQuinn Tran return f;
1038726b8548SQuinn Tran }
1039726b8548SQuinn Tran }
104017cac3a1SJoe Carnuccio return NULL;
104117cac3a1SJoe Carnuccio }
104217cac3a1SJoe Carnuccio
1043cbb01c2fSArun Easi /* Shall be called only on supported adapters. */
1044cbb01c2fSArun Easi static void
qla27xx_handle_8200_aen(scsi_qla_host_t * vha,uint16_t * mb)1045cbb01c2fSArun Easi qla27xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb)
1046cbb01c2fSArun Easi {
1047cbb01c2fSArun Easi struct qla_hw_data *ha = vha->hw;
104871311be1SJiapeng Zhong bool reset_isp_needed = false;
1049cbb01c2fSArun Easi
1050cbb01c2fSArun Easi ql_log(ql_log_warn, vha, 0x02f0,
1051cbb01c2fSArun Easi "MPI Heartbeat stop. MPI reset is%s needed. "
1052cbb01c2fSArun Easi "MB0[%xh] MB1[%xh] MB2[%xh] MB3[%xh]\n",
10537a6cdbd5SArun Easi mb[1] & BIT_8 ? "" : " not",
1054cbb01c2fSArun Easi mb[0], mb[1], mb[2], mb[3]);
1055cbb01c2fSArun Easi
1056cbb01c2fSArun Easi if ((mb[1] & BIT_8) == 0)
1057cbb01c2fSArun Easi return;
1058cbb01c2fSArun Easi
1059cbb01c2fSArun Easi ql_log(ql_log_warn, vha, 0x02f1,
1060cbb01c2fSArun Easi "MPI Heartbeat stop. FW dump needed\n");
1061cbb01c2fSArun Easi
1062cbb01c2fSArun Easi if (ql2xfulldump_on_mpifail) {
10638ae17876SBart Van Assche ha->isp_ops->fw_dump(vha);
106471311be1SJiapeng Zhong reset_isp_needed = true;
1065cbb01c2fSArun Easi }
1066cbb01c2fSArun Easi
1067cbb01c2fSArun Easi ha->isp_ops->mpi_fw_dump(vha, 1);
1068cbb01c2fSArun Easi
1069cbb01c2fSArun Easi if (reset_isp_needed) {
1070cbb01c2fSArun Easi vha->hw->flags.fw_init_done = 0;
1071cbb01c2fSArun Easi set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
1072cbb01c2fSArun Easi qla2xxx_wake_dpc(vha);
1073cbb01c2fSArun Easi }
1074cbb01c2fSArun Easi }
1075cbb01c2fSArun Easi
107658101f15SShyam Sundar static struct purex_item *
qla24xx_alloc_purex_item(scsi_qla_host_t * vha,uint16_t size)107762e9dd17SShyam Sundar qla24xx_alloc_purex_item(scsi_qla_host_t *vha, uint16_t size)
107862e9dd17SShyam Sundar {
107962e9dd17SShyam Sundar struct purex_item *item = NULL;
108062e9dd17SShyam Sundar uint8_t item_hdr_size = sizeof(*item);
108162e9dd17SShyam Sundar
108262e9dd17SShyam Sundar if (size > QLA_DEFAULT_PAYLOAD_SIZE) {
108362e9dd17SShyam Sundar item = kzalloc(item_hdr_size +
108462e9dd17SShyam Sundar (size - QLA_DEFAULT_PAYLOAD_SIZE), GFP_ATOMIC);
108562e9dd17SShyam Sundar } else {
108662e9dd17SShyam Sundar if (atomic_inc_return(&vha->default_item.in_use) == 1) {
108762e9dd17SShyam Sundar item = &vha->default_item;
108862e9dd17SShyam Sundar goto initialize_purex_header;
108962e9dd17SShyam Sundar } else {
109062e9dd17SShyam Sundar item = kzalloc(item_hdr_size, GFP_ATOMIC);
109162e9dd17SShyam Sundar }
109262e9dd17SShyam Sundar }
109362e9dd17SShyam Sundar if (!item) {
109462e9dd17SShyam Sundar ql_log(ql_log_warn, vha, 0x5092,
109562e9dd17SShyam Sundar ">> Failed allocate purex list item.\n");
109662e9dd17SShyam Sundar
109762e9dd17SShyam Sundar return NULL;
109862e9dd17SShyam Sundar }
109962e9dd17SShyam Sundar
110062e9dd17SShyam Sundar initialize_purex_header:
110162e9dd17SShyam Sundar item->vha = vha;
110262e9dd17SShyam Sundar item->size = size;
110362e9dd17SShyam Sundar return item;
110462e9dd17SShyam Sundar }
110562e9dd17SShyam Sundar
1106875386b9SManish Rangankar void
qla24xx_queue_purex_item(scsi_qla_host_t * vha,struct purex_item * pkt,void (* process_item)(struct scsi_qla_host * vha,struct purex_item * pkt))110762e9dd17SShyam Sundar qla24xx_queue_purex_item(scsi_qla_host_t *vha, struct purex_item *pkt,
110862e9dd17SShyam Sundar void (*process_item)(struct scsi_qla_host *vha,
110962e9dd17SShyam Sundar struct purex_item *pkt))
111062e9dd17SShyam Sundar {
111162e9dd17SShyam Sundar struct purex_list *list = &vha->purex_list;
111262e9dd17SShyam Sundar ulong flags;
111362e9dd17SShyam Sundar
111462e9dd17SShyam Sundar pkt->process_item = process_item;
111562e9dd17SShyam Sundar
111662e9dd17SShyam Sundar spin_lock_irqsave(&list->lock, flags);
111762e9dd17SShyam Sundar list_add_tail(&pkt->list, &list->head);
111862e9dd17SShyam Sundar spin_unlock_irqrestore(&list->lock, flags);
111962e9dd17SShyam Sundar
112062e9dd17SShyam Sundar set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags);
112162e9dd17SShyam Sundar }
112262e9dd17SShyam Sundar
112362e9dd17SShyam Sundar /**
112462e9dd17SShyam Sundar * qla24xx_copy_std_pkt() - Copy over purex ELS which is
112562e9dd17SShyam Sundar * contained in a single IOCB.
112662e9dd17SShyam Sundar * purex packet.
112762e9dd17SShyam Sundar * @vha: SCSI driver HA context
112862e9dd17SShyam Sundar * @pkt: ELS packet
112962e9dd17SShyam Sundar */
11309f2475feSShyam Sundar static struct purex_item
qla24xx_copy_std_pkt(struct scsi_qla_host * vha,void * pkt)113162e9dd17SShyam Sundar *qla24xx_copy_std_pkt(struct scsi_qla_host *vha, void *pkt)
113262e9dd17SShyam Sundar {
113362e9dd17SShyam Sundar struct purex_item *item;
113462e9dd17SShyam Sundar
113562e9dd17SShyam Sundar item = qla24xx_alloc_purex_item(vha,
113662e9dd17SShyam Sundar QLA_DEFAULT_PAYLOAD_SIZE);
113762e9dd17SShyam Sundar if (!item)
113862e9dd17SShyam Sundar return item;
113962e9dd17SShyam Sundar
114062e9dd17SShyam Sundar memcpy(&item->iocb, pkt, sizeof(item->iocb));
114162e9dd17SShyam Sundar return item;
114262e9dd17SShyam Sundar }
114362e9dd17SShyam Sundar
11441da177e4SLinus Torvalds /**
11459f2475feSShyam Sundar * qla27xx_copy_fpin_pkt() - Copy over fpin packets that can
11469f2475feSShyam Sundar * span over multiple IOCBs.
11479f2475feSShyam Sundar * @vha: SCSI driver HA context
11489f2475feSShyam Sundar * @pkt: ELS packet
11499f2475feSShyam Sundar * @rsp: Response queue
11509f2475feSShyam Sundar */
11519f2475feSShyam Sundar static struct purex_item *
qla27xx_copy_fpin_pkt(struct scsi_qla_host * vha,void ** pkt,struct rsp_que ** rsp)11529f2475feSShyam Sundar qla27xx_copy_fpin_pkt(struct scsi_qla_host *vha, void **pkt,
11539f2475feSShyam Sundar struct rsp_que **rsp)
11549f2475feSShyam Sundar {
11559f2475feSShyam Sundar struct purex_entry_24xx *purex = *pkt;
11569f2475feSShyam Sundar struct rsp_que *rsp_q = *rsp;
11579f2475feSShyam Sundar sts_cont_entry_t *new_pkt;
11589f2475feSShyam Sundar uint16_t no_bytes = 0, total_bytes = 0, pending_bytes = 0;
11599f2475feSShyam Sundar uint16_t buffer_copy_offset = 0;
11609f2475feSShyam Sundar uint16_t entry_count, entry_count_remaining;
11619f2475feSShyam Sundar struct purex_item *item;
11629f2475feSShyam Sundar void *fpin_pkt = NULL;
11639f2475feSShyam Sundar
116458101f15SShyam Sundar total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF)
11659f2475feSShyam Sundar - PURX_ELS_HEADER_SIZE;
11669f2475feSShyam Sundar pending_bytes = total_bytes;
11679f2475feSShyam Sundar entry_count = entry_count_remaining = purex->entry_count;
11689f2475feSShyam Sundar no_bytes = (pending_bytes > sizeof(purex->els_frame_payload)) ?
11699f2475feSShyam Sundar sizeof(purex->els_frame_payload) : pending_bytes;
11709f2475feSShyam Sundar ql_log(ql_log_info, vha, 0x509a,
11719f2475feSShyam Sundar "FPIN ELS, frame_size 0x%x, entry count %d\n",
11729f2475feSShyam Sundar total_bytes, entry_count);
11739f2475feSShyam Sundar
11749f2475feSShyam Sundar item = qla24xx_alloc_purex_item(vha, total_bytes);
11759f2475feSShyam Sundar if (!item)
11769f2475feSShyam Sundar return item;
11779f2475feSShyam Sundar
11789f2475feSShyam Sundar fpin_pkt = &item->iocb;
11799f2475feSShyam Sundar
11809f2475feSShyam Sundar memcpy(fpin_pkt, &purex->els_frame_payload[0], no_bytes);
11819f2475feSShyam Sundar buffer_copy_offset += no_bytes;
11829f2475feSShyam Sundar pending_bytes -= no_bytes;
11839f2475feSShyam Sundar --entry_count_remaining;
11849f2475feSShyam Sundar
11859f2475feSShyam Sundar ((response_t *)purex)->signature = RESPONSE_PROCESSED;
11869f2475feSShyam Sundar wmb();
11879f2475feSShyam Sundar
11889f2475feSShyam Sundar do {
11899f2475feSShyam Sundar while ((total_bytes > 0) && (entry_count_remaining > 0)) {
11909f2475feSShyam Sundar if (rsp_q->ring_ptr->signature == RESPONSE_PROCESSED) {
11919f2475feSShyam Sundar ql_dbg(ql_dbg_async, vha, 0x5084,
11929f2475feSShyam Sundar "Ran out of IOCBs, partial data 0x%x\n",
11939f2475feSShyam Sundar buffer_copy_offset);
11949f2475feSShyam Sundar cpu_relax();
11959f2475feSShyam Sundar continue;
11969f2475feSShyam Sundar }
11979f2475feSShyam Sundar
11989f2475feSShyam Sundar new_pkt = (sts_cont_entry_t *)rsp_q->ring_ptr;
11999f2475feSShyam Sundar *pkt = new_pkt;
12009f2475feSShyam Sundar
12019f2475feSShyam Sundar if (new_pkt->entry_type != STATUS_CONT_TYPE) {
12029f2475feSShyam Sundar ql_log(ql_log_warn, vha, 0x507a,
12039f2475feSShyam Sundar "Unexpected IOCB type, partial data 0x%x\n",
12049f2475feSShyam Sundar buffer_copy_offset);
12059f2475feSShyam Sundar break;
12069f2475feSShyam Sundar }
12079f2475feSShyam Sundar
12089f2475feSShyam Sundar rsp_q->ring_index++;
12099f2475feSShyam Sundar if (rsp_q->ring_index == rsp_q->length) {
12109f2475feSShyam Sundar rsp_q->ring_index = 0;
12119f2475feSShyam Sundar rsp_q->ring_ptr = rsp_q->ring;
12129f2475feSShyam Sundar } else {
12139f2475feSShyam Sundar rsp_q->ring_ptr++;
12149f2475feSShyam Sundar }
12159f2475feSShyam Sundar no_bytes = (pending_bytes > sizeof(new_pkt->data)) ?
12169f2475feSShyam Sundar sizeof(new_pkt->data) : pending_bytes;
12179f2475feSShyam Sundar if ((buffer_copy_offset + no_bytes) <= total_bytes) {
12189f2475feSShyam Sundar memcpy(((uint8_t *)fpin_pkt +
12199f2475feSShyam Sundar buffer_copy_offset), new_pkt->data,
12209f2475feSShyam Sundar no_bytes);
12219f2475feSShyam Sundar buffer_copy_offset += no_bytes;
12229f2475feSShyam Sundar pending_bytes -= no_bytes;
12239f2475feSShyam Sundar --entry_count_remaining;
12249f2475feSShyam Sundar } else {
12259f2475feSShyam Sundar ql_log(ql_log_warn, vha, 0x5044,
12269f2475feSShyam Sundar "Attempt to copy more that we got, optimizing..%x\n",
12279f2475feSShyam Sundar buffer_copy_offset);
12289f2475feSShyam Sundar memcpy(((uint8_t *)fpin_pkt +
12299f2475feSShyam Sundar buffer_copy_offset), new_pkt->data,
12309f2475feSShyam Sundar total_bytes - buffer_copy_offset);
12319f2475feSShyam Sundar }
12329f2475feSShyam Sundar
12339f2475feSShyam Sundar ((response_t *)new_pkt)->signature = RESPONSE_PROCESSED;
12349f2475feSShyam Sundar wmb();
12359f2475feSShyam Sundar }
12369f2475feSShyam Sundar
12379f2475feSShyam Sundar if (pending_bytes != 0 || entry_count_remaining != 0) {
12389f2475feSShyam Sundar ql_log(ql_log_fatal, vha, 0x508b,
12399f2475feSShyam Sundar "Dropping partial FPIN, underrun bytes = 0x%x, entry cnts 0x%x\n",
12409f2475feSShyam Sundar total_bytes, entry_count_remaining);
12419f2475feSShyam Sundar qla24xx_free_purex_item(item);
12429f2475feSShyam Sundar return NULL;
12439f2475feSShyam Sundar }
12449f2475feSShyam Sundar } while (entry_count_remaining > 0);
12459f2475feSShyam Sundar host_to_fcp_swap((uint8_t *)&item->iocb, total_bytes);
12469f2475feSShyam Sundar return item;
12479f2475feSShyam Sundar }
12489f2475feSShyam Sundar
12499f2475feSShyam Sundar /**
12501da177e4SLinus Torvalds * qla2x00_async_event() - Process aynchronous events.
12512db6228dSBart Van Assche * @vha: SCSI driver HA context
12522db6228dSBart Van Assche * @rsp: response queue
12539a853f71SAndrew Vasquez * @mb: Mailbox registers (0 - 3)
12541da177e4SLinus Torvalds */
12552c3dfe3fSSeokmann Ju void
qla2x00_async_event(scsi_qla_host_t * vha,struct rsp_que * rsp,uint16_t * mb)125673208dfdSAnirban Chakraborty qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
12571da177e4SLinus Torvalds {
12581da177e4SLinus Torvalds uint16_t handle_cnt;
1259bdab23daSAndrew Vasquez uint16_t cnt, mbx;
12601da177e4SLinus Torvalds uint32_t handles[5];
1261e315cd28SAnirban Chakraborty struct qla_hw_data *ha = vha->hw;
12623d71644cSAndrew Vasquez struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
1263bdab23daSAndrew Vasquez struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
1264bc5c2aadSAndrew Vasquez struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
126552c82823SBart Van Assche uint32_t rscn_entry, host_pid;
12664d4df193SHarihara Kadayam unsigned long flags;
1267ef86cb20SChad Dupuis fc_port_t *fcport = NULL;
12681da177e4SLinus Torvalds
12695b51f35dSQuinn Tran if (!vha->hw->flags.fw_started) {
12705b51f35dSQuinn Tran ql_log(ql_log_warn, vha, 0x50ff,
12715b51f35dSQuinn Tran "Dropping AEN - %04x %04x %04x %04x.\n",
12725b51f35dSQuinn Tran mb[0], mb[1], mb[2], mb[3]);
127345235022SQuinn Tran return;
12745b51f35dSQuinn Tran }
127545235022SQuinn Tran
12761da177e4SLinus Torvalds /* Setup to process RIO completion. */
12771da177e4SLinus Torvalds handle_cnt = 0;
12786246b8a1SGiridhar Malavali if (IS_CNA_CAPABLE(ha))
12793a03eb79SAndrew Vasquez goto skip_rio;
12801da177e4SLinus Torvalds switch (mb[0]) {
12811da177e4SLinus Torvalds case MBA_SCSI_COMPLETION:
12827ffa5b93SBart Van Assche handles[0] = make_handle(mb[2], mb[1]);
12831da177e4SLinus Torvalds handle_cnt = 1;
12841da177e4SLinus Torvalds break;
12851da177e4SLinus Torvalds case MBA_CMPLT_1_16BIT:
12869a853f71SAndrew Vasquez handles[0] = mb[1];
12871da177e4SLinus Torvalds handle_cnt = 1;
12881da177e4SLinus Torvalds mb[0] = MBA_SCSI_COMPLETION;
12891da177e4SLinus Torvalds break;
12901da177e4SLinus Torvalds case MBA_CMPLT_2_16BIT:
12919a853f71SAndrew Vasquez handles[0] = mb[1];
12929a853f71SAndrew Vasquez handles[1] = mb[2];
12931da177e4SLinus Torvalds handle_cnt = 2;
12941da177e4SLinus Torvalds mb[0] = MBA_SCSI_COMPLETION;
12951da177e4SLinus Torvalds break;
12961da177e4SLinus Torvalds case MBA_CMPLT_3_16BIT:
12979a853f71SAndrew Vasquez handles[0] = mb[1];
12989a853f71SAndrew Vasquez handles[1] = mb[2];
12999a853f71SAndrew Vasquez handles[2] = mb[3];
13001da177e4SLinus Torvalds handle_cnt = 3;
13011da177e4SLinus Torvalds mb[0] = MBA_SCSI_COMPLETION;
13021da177e4SLinus Torvalds break;
13031da177e4SLinus Torvalds case MBA_CMPLT_4_16BIT:
13049a853f71SAndrew Vasquez handles[0] = mb[1];
13059a853f71SAndrew Vasquez handles[1] = mb[2];
13069a853f71SAndrew Vasquez handles[2] = mb[3];
13071da177e4SLinus Torvalds handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);
13081da177e4SLinus Torvalds handle_cnt = 4;
13091da177e4SLinus Torvalds mb[0] = MBA_SCSI_COMPLETION;
13101da177e4SLinus Torvalds break;
13111da177e4SLinus Torvalds case MBA_CMPLT_5_16BIT:
13129a853f71SAndrew Vasquez handles[0] = mb[1];
13139a853f71SAndrew Vasquez handles[1] = mb[2];
13149a853f71SAndrew Vasquez handles[2] = mb[3];
13151da177e4SLinus Torvalds handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);
13161da177e4SLinus Torvalds handles[4] = (uint32_t)RD_MAILBOX_REG(ha, reg, 7);
13171da177e4SLinus Torvalds handle_cnt = 5;
13181da177e4SLinus Torvalds mb[0] = MBA_SCSI_COMPLETION;
13191da177e4SLinus Torvalds break;
13201da177e4SLinus Torvalds case MBA_CMPLT_2_32BIT:
13217ffa5b93SBart Van Assche handles[0] = make_handle(mb[2], mb[1]);
13227ffa5b93SBart Van Assche handles[1] = make_handle(RD_MAILBOX_REG(ha, reg, 7),
13231da177e4SLinus Torvalds RD_MAILBOX_REG(ha, reg, 6));
13241da177e4SLinus Torvalds handle_cnt = 2;
13251da177e4SLinus Torvalds mb[0] = MBA_SCSI_COMPLETION;
13261da177e4SLinus Torvalds break;
13271da177e4SLinus Torvalds default:
13281da177e4SLinus Torvalds break;
13291da177e4SLinus Torvalds }
13303a03eb79SAndrew Vasquez skip_rio:
13311da177e4SLinus Torvalds switch (mb[0]) {
13321da177e4SLinus Torvalds case MBA_SCSI_COMPLETION: /* Fast Post */
1333e315cd28SAnirban Chakraborty if (!vha->flags.online)
13341da177e4SLinus Torvalds break;
13351da177e4SLinus Torvalds
13361da177e4SLinus Torvalds for (cnt = 0; cnt < handle_cnt; cnt++)
133773208dfdSAnirban Chakraborty qla2x00_process_completed_request(vha, rsp->req,
133873208dfdSAnirban Chakraborty handles[cnt]);
13391da177e4SLinus Torvalds break;
13401da177e4SLinus Torvalds
13411da177e4SLinus Torvalds case MBA_RESET: /* Reset */
13427c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5002,
13437c3df132SSaurav Kashyap "Asynchronous RESET.\n");
13441da177e4SLinus Torvalds
1345e315cd28SAnirban Chakraborty set_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
13461da177e4SLinus Torvalds break;
13471da177e4SLinus Torvalds
13481da177e4SLinus Torvalds case MBA_SYSTEM_ERR: /* System Error */
1349a82c307eSQuinn Tran mbx = 0;
1350dbf1f53cSSaurav Kashyap
1351dbf1f53cSSaurav Kashyap vha->hw_err_cnt++;
1352dbf1f53cSSaurav Kashyap
1353a82c307eSQuinn Tran if (IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
1354a82c307eSQuinn Tran IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
1355a82c307eSQuinn Tran u16 m[4];
1356a82c307eSQuinn Tran
135704474d3aSBart Van Assche m[0] = rd_reg_word(®24->mailbox4);
135804474d3aSBart Van Assche m[1] = rd_reg_word(®24->mailbox5);
135904474d3aSBart Van Assche m[2] = rd_reg_word(®24->mailbox6);
136004474d3aSBart Van Assche mbx = m[3] = rd_reg_word(®24->mailbox7);
1361a82c307eSQuinn Tran
13627c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5003,
1363a82c307eSQuinn Tran "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh mbx4=%xh mbx5=%xh mbx6=%xh mbx7=%xh.\n",
1364a82c307eSQuinn Tran mb[1], mb[2], mb[3], m[0], m[1], m[2], m[3]);
1365a82c307eSQuinn Tran } else
1366a82c307eSQuinn Tran ql_log(ql_log_warn, vha, 0x5003,
1367a82c307eSQuinn Tran "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n ",
1368a82c307eSQuinn Tran mb[1], mb[2], mb[3]);
1369a82c307eSQuinn Tran
1370cbb01c2fSArun Easi if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
137104474d3aSBart Van Assche rd_reg_word(®24->mailbox7) & BIT_8)
1372cbb01c2fSArun Easi ha->isp_ops->mpi_fw_dump(vha, 1);
13738ae17876SBart Van Assche ha->isp_ops->fw_dump(vha);
1374ec7193e2SQuinn Tran ha->flags.fw_init_done = 0;
13754b60c827SQuinn Tran QLA_FW_STOPPED(ha);
13761da177e4SLinus Torvalds
1377e428924cSAndrew Vasquez if (IS_FWI2_CAPABLE(ha)) {
13789a853f71SAndrew Vasquez if (mb[1] == 0 && mb[2] == 0) {
13797c3df132SSaurav Kashyap ql_log(ql_log_fatal, vha, 0x5004,
13809a853f71SAndrew Vasquez "Unrecoverable Hardware Error: adapter "
13819a853f71SAndrew Vasquez "marked OFFLINE!\n");
1382e315cd28SAnirban Chakraborty vha->flags.online = 0;
13836246b8a1SGiridhar Malavali vha->device_flags |= DFLG_DEV_FAILED;
1384b1d46989SMadhuranath Iyengar } else {
138525985edcSLucas De Marchi /* Check to see if MPI timeout occurred */
1386f73cb695SChad Dupuis if ((mbx & MBX_3) && (ha->port_no == 0))
1387b1d46989SMadhuranath Iyengar set_bit(MPI_RESET_NEEDED,
1388b1d46989SMadhuranath Iyengar &vha->dpc_flags);
1389b1d46989SMadhuranath Iyengar
1390e315cd28SAnirban Chakraborty set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
1391b1d46989SMadhuranath Iyengar }
13929a853f71SAndrew Vasquez } else if (mb[1] == 0) {
13937c3df132SSaurav Kashyap ql_log(ql_log_fatal, vha, 0x5005,
13941da177e4SLinus Torvalds "Unrecoverable Hardware Error: adapter marked "
13951da177e4SLinus Torvalds "OFFLINE!\n");
1396e315cd28SAnirban Chakraborty vha->flags.online = 0;
13976246b8a1SGiridhar Malavali vha->device_flags |= DFLG_DEV_FAILED;
13981da177e4SLinus Torvalds } else
1399e315cd28SAnirban Chakraborty set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
14001da177e4SLinus Torvalds break;
14011da177e4SLinus Torvalds
14021da177e4SLinus Torvalds case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */
14037c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5006,
1404bdab23daSAndrew Vasquez "ISP Request Transfer Error (%x).\n", mb[1]);
14051da177e4SLinus Torvalds
1406dbf1f53cSSaurav Kashyap vha->hw_err_cnt++;
1407dbf1f53cSSaurav Kashyap
1408e315cd28SAnirban Chakraborty set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
14091da177e4SLinus Torvalds break;
14101da177e4SLinus Torvalds
14111da177e4SLinus Torvalds case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */
14127c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5007,
141341233cd3SJoe Carnuccio "ISP Response Transfer Error (%x).\n", mb[1]);
14141da177e4SLinus Torvalds
1415dbf1f53cSSaurav Kashyap vha->hw_err_cnt++;
1416dbf1f53cSSaurav Kashyap
1417e315cd28SAnirban Chakraborty set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
14181da177e4SLinus Torvalds break;
14191da177e4SLinus Torvalds
14201da177e4SLinus Torvalds case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
14217c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5008,
142241233cd3SJoe Carnuccio "Asynchronous WAKEUP_THRES (%x).\n", mb[1]);
14232d70c103SNicholas Bellinger break;
142441233cd3SJoe Carnuccio
142541233cd3SJoe Carnuccio case MBA_LOOP_INIT_ERR:
142675d560e0SSawan Chandak ql_log(ql_log_warn, vha, 0x5090,
142741233cd3SJoe Carnuccio "LOOP INIT ERROR (%x).\n", mb[1]);
142841233cd3SJoe Carnuccio set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
142941233cd3SJoe Carnuccio break;
143041233cd3SJoe Carnuccio
14311da177e4SLinus Torvalds case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */
1432ec7193e2SQuinn Tran ha->flags.lip_ae = 1;
1433ec7193e2SQuinn Tran
1434cfb0919cSChad Dupuis ql_dbg(ql_dbg_async, vha, 0x5009,
14357c3df132SSaurav Kashyap "LIP occurred (%x).\n", mb[1]);
14361da177e4SLinus Torvalds
1437e315cd28SAnirban Chakraborty if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
1438e315cd28SAnirban Chakraborty atomic_set(&vha->loop_state, LOOP_DOWN);
1439e315cd28SAnirban Chakraborty atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
14403c75ad1dSHimanshu Madhani qla2x00_mark_all_devices_lost(vha);
14411da177e4SLinus Torvalds }
14421da177e4SLinus Torvalds
1443e315cd28SAnirban Chakraborty if (vha->vp_idx) {
1444e315cd28SAnirban Chakraborty atomic_set(&vha->vp_state, VP_FAILED);
1445e315cd28SAnirban Chakraborty fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
14462c3dfe3fSSeokmann Ju }
14472c3dfe3fSSeokmann Ju
1448e315cd28SAnirban Chakraborty set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
1449e315cd28SAnirban Chakraborty set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
14501da177e4SLinus Torvalds
1451e315cd28SAnirban Chakraborty vha->flags.management_server_logged_in = 0;
1452e315cd28SAnirban Chakraborty qla2x00_post_aen_work(vha, FCH_EVT_LIP, mb[1]);
14531da177e4SLinus Torvalds break;
14541da177e4SLinus Torvalds
14551da177e4SLinus Torvalds case MBA_LOOP_UP: /* Loop Up Event */
1456daae62a3SChad Dupuis if (IS_QLA2100(ha) || IS_QLA2200(ha))
1457d8b45213SAndrew Vasquez ha->link_data_rate = PORT_SPEED_1GB;
1458daae62a3SChad Dupuis else
14591da177e4SLinus Torvalds ha->link_data_rate = mb[1];
14601da177e4SLinus Torvalds
14618e5a9484SChad Dupuis ql_log(ql_log_info, vha, 0x500a,
1462daae62a3SChad Dupuis "LOOP UP detected (%s Gbps).\n",
1463d0297c9aSJoe Carnuccio qla2x00_get_link_speed_str(ha, ha->link_data_rate));
14641da177e4SLinus Torvalds
146575666f4aSHimanshu Madhani if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
146675666f4aSHimanshu Madhani if (mb[2] & BIT_0)
146775666f4aSHimanshu Madhani ql_log(ql_log_info, vha, 0x11a0,
146875666f4aSHimanshu Madhani "FEC=enabled (link up).\n");
146975666f4aSHimanshu Madhani }
147075666f4aSHimanshu Madhani
1471e315cd28SAnirban Chakraborty vha->flags.management_server_logged_in = 0;
1472e315cd28SAnirban Chakraborty qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
1473e4e3a2ceSQuinn Tran
1474dbf1f53cSSaurav Kashyap if (vha->link_down_time < vha->hw->port_down_retry_count) {
1475dbf1f53cSSaurav Kashyap vha->short_link_down_cnt++;
1476dbf1f53cSSaurav Kashyap vha->link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
1477dbf1f53cSSaurav Kashyap }
1478dbf1f53cSSaurav Kashyap
14791da177e4SLinus Torvalds break;
14801da177e4SLinus Torvalds
14811da177e4SLinus Torvalds case MBA_LOOP_DOWN: /* Loop Down Event */
14829cd883f0SQuinn Tran SAVE_TOPO(ha);
1483ec7193e2SQuinn Tran ha->flags.lip_ae = 0;
1484ec7193e2SQuinn Tran ha->current_topology = 0;
1485dbf1f53cSSaurav Kashyap vha->link_down_time = 0;
1486ec7193e2SQuinn Tran
14876246b8a1SGiridhar Malavali mbx = (IS_QLA81XX(ha) || IS_QLA8031(ha))
148804474d3aSBart Van Assche ? rd_reg_word(®24->mailbox4) : 0;
148904474d3aSBart Van Assche mbx = (IS_P3P_TYPE(ha)) ? rd_reg_word(®82->mailbox_out[4])
14907ec0effdSAtul Deshmukh : mbx;
14918e5a9484SChad Dupuis ql_log(ql_log_info, vha, 0x500b,
14927c3df132SSaurav Kashyap "LOOP DOWN detected (%x %x %x %x).\n",
14937c3df132SSaurav Kashyap mb[1], mb[2], mb[3], mbx);
14941da177e4SLinus Torvalds
1495e315cd28SAnirban Chakraborty if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
1496e315cd28SAnirban Chakraborty atomic_set(&vha->loop_state, LOOP_DOWN);
1497e315cd28SAnirban Chakraborty atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
14982486c627SHimanshu Madhani /*
14992486c627SHimanshu Madhani * In case of loop down, restore WWPN from
15002486c627SHimanshu Madhani * NVRAM in case of FA-WWPN capable ISP
1501718abbdcSSawan Chandak * Restore for Physical Port only
15022486c627SHimanshu Madhani */
1503718abbdcSSawan Chandak if (!vha->vp_idx) {
1504dcbf8f80SSawan Chandak if (ha->flags.fawwpn_enabled &&
1505dcbf8f80SSawan Chandak (ha->current_topology == ISP_CFG_F)) {
1506cf3b4fb6SBikash Hazarika memcpy(vha->port_name, ha->port_name, WWN_SIZE);
1507718abbdcSSawan Chandak fc_host_port_name(vha->host) =
1508718abbdcSSawan Chandak wwn_to_u64(vha->port_name);
1509718abbdcSSawan Chandak ql_dbg(ql_dbg_init + ql_dbg_verbose,
151083548fe2SQuinn Tran vha, 0x00d8, "LOOP DOWN detected,"
1511718abbdcSSawan Chandak "restore WWPN %016llx\n",
1512718abbdcSSawan Chandak wwn_to_u64(vha->port_name));
15132486c627SHimanshu Madhani }
15142486c627SHimanshu Madhani
1515ded6411fSSawan Chandak clear_bit(VP_CONFIG_OK, &vha->vp_flags);
1516718abbdcSSawan Chandak }
1517718abbdcSSawan Chandak
1518e315cd28SAnirban Chakraborty vha->device_flags |= DFLG_NO_CABLE;
15193c75ad1dSHimanshu Madhani qla2x00_mark_all_devices_lost(vha);
15201da177e4SLinus Torvalds }
15211da177e4SLinus Torvalds
1522e315cd28SAnirban Chakraborty if (vha->vp_idx) {
1523e315cd28SAnirban Chakraborty atomic_set(&vha->vp_state, VP_FAILED);
1524e315cd28SAnirban Chakraborty fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
15252c3dfe3fSSeokmann Ju }
15262c3dfe3fSSeokmann Ju
1527e315cd28SAnirban Chakraborty vha->flags.management_server_logged_in = 0;
1528d8b45213SAndrew Vasquez ha->link_data_rate = PORT_SPEED_UNKNOWN;
1529e315cd28SAnirban Chakraborty qla2x00_post_aen_work(vha, FCH_EVT_LINKDOWN, 0);
15301da177e4SLinus Torvalds break;
15311da177e4SLinus Torvalds
15321da177e4SLinus Torvalds case MBA_LIP_RESET: /* LIP reset occurred */
1533cfb0919cSChad Dupuis ql_dbg(ql_dbg_async, vha, 0x500c,
1534cc3ef7bcSBjorn Helgaas "LIP reset occurred (%x).\n", mb[1]);
15351da177e4SLinus Torvalds
1536e315cd28SAnirban Chakraborty if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
1537e315cd28SAnirban Chakraborty atomic_set(&vha->loop_state, LOOP_DOWN);
1538e315cd28SAnirban Chakraborty atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
15393c75ad1dSHimanshu Madhani qla2x00_mark_all_devices_lost(vha);
15401da177e4SLinus Torvalds }
15411da177e4SLinus Torvalds
1542e315cd28SAnirban Chakraborty if (vha->vp_idx) {
1543e315cd28SAnirban Chakraborty atomic_set(&vha->vp_state, VP_FAILED);
1544e315cd28SAnirban Chakraborty fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
15452c3dfe3fSSeokmann Ju }
15462c3dfe3fSSeokmann Ju
1547e315cd28SAnirban Chakraborty set_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
15481da177e4SLinus Torvalds
15491da177e4SLinus Torvalds ha->operating_mode = LOOP;
1550e315cd28SAnirban Chakraborty vha->flags.management_server_logged_in = 0;
1551e315cd28SAnirban Chakraborty qla2x00_post_aen_work(vha, FCH_EVT_LIPRESET, mb[1]);
15521da177e4SLinus Torvalds break;
15531da177e4SLinus Torvalds
15543a03eb79SAndrew Vasquez /* case MBA_DCBX_COMPLETE: */
15551da177e4SLinus Torvalds case MBA_POINT_TO_POINT: /* Point-to-Point */
1556ec7193e2SQuinn Tran ha->flags.lip_ae = 0;
1557ec7193e2SQuinn Tran
15581da177e4SLinus Torvalds if (IS_QLA2100(ha))
15591da177e4SLinus Torvalds break;
15601da177e4SLinus Torvalds
15617ec0effdSAtul Deshmukh if (IS_CNA_CAPABLE(ha)) {
15627c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x500d,
15637c3df132SSaurav Kashyap "DCBX Completed -- %04x %04x %04x.\n",
15647c3df132SSaurav Kashyap mb[1], mb[2], mb[3]);
15659aaf2ceaSChad Dupuis if (ha->notify_dcbx_comp && !vha->vp_idx)
156623f2ebd1SSarang Radke complete(&ha->dcbx_comp);
156723f2ebd1SSarang Radke
156823f2ebd1SSarang Radke } else
15697c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x500e,
15707c3df132SSaurav Kashyap "Asynchronous P2P MODE received.\n");
15711da177e4SLinus Torvalds
15721da177e4SLinus Torvalds /*
15731da177e4SLinus Torvalds * Until there's a transition from loop down to loop up, treat
15741da177e4SLinus Torvalds * this as loop down only.
15751da177e4SLinus Torvalds */
1576e315cd28SAnirban Chakraborty if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
1577e315cd28SAnirban Chakraborty atomic_set(&vha->loop_state, LOOP_DOWN);
1578e315cd28SAnirban Chakraborty if (!atomic_read(&vha->loop_down_timer))
1579e315cd28SAnirban Chakraborty atomic_set(&vha->loop_down_timer,
15801da177e4SLinus Torvalds LOOP_DOWN_TIME);
158148acad09SQuinn Tran if (!N2N_TOPO(ha))
15823c75ad1dSHimanshu Madhani qla2x00_mark_all_devices_lost(vha);
15831da177e4SLinus Torvalds }
15841da177e4SLinus Torvalds
1585e315cd28SAnirban Chakraborty if (vha->vp_idx) {
1586e315cd28SAnirban Chakraborty atomic_set(&vha->vp_state, VP_FAILED);
1587e315cd28SAnirban Chakraborty fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
15882c3dfe3fSSeokmann Ju }
15892c3dfe3fSSeokmann Ju
1590e315cd28SAnirban Chakraborty if (!(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)))
1591e315cd28SAnirban Chakraborty set_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
1592e315cd28SAnirban Chakraborty
1593e315cd28SAnirban Chakraborty set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
1594e315cd28SAnirban Chakraborty set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
15954346b149SAndrew Vasquez
1596e315cd28SAnirban Chakraborty vha->flags.management_server_logged_in = 0;
15971da177e4SLinus Torvalds break;
15981da177e4SLinus Torvalds
15991da177e4SLinus Torvalds case MBA_CHG_IN_CONNECTION: /* Change in connection mode */
16001da177e4SLinus Torvalds if (IS_QLA2100(ha))
16011da177e4SLinus Torvalds break;
16021da177e4SLinus Torvalds
1603cfb0919cSChad Dupuis ql_dbg(ql_dbg_async, vha, 0x500f,
16041da177e4SLinus Torvalds "Configuration change detected: value=%x.\n", mb[1]);
16051da177e4SLinus Torvalds
1606e315cd28SAnirban Chakraborty if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
1607e315cd28SAnirban Chakraborty atomic_set(&vha->loop_state, LOOP_DOWN);
1608e315cd28SAnirban Chakraborty if (!atomic_read(&vha->loop_down_timer))
1609e315cd28SAnirban Chakraborty atomic_set(&vha->loop_down_timer,
16101da177e4SLinus Torvalds LOOP_DOWN_TIME);
16113c75ad1dSHimanshu Madhani qla2x00_mark_all_devices_lost(vha);
16121da177e4SLinus Torvalds }
16131da177e4SLinus Torvalds
1614e315cd28SAnirban Chakraborty if (vha->vp_idx) {
1615e315cd28SAnirban Chakraborty atomic_set(&vha->vp_state, VP_FAILED);
1616e315cd28SAnirban Chakraborty fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
16172c3dfe3fSSeokmann Ju }
16182c3dfe3fSSeokmann Ju
1619e315cd28SAnirban Chakraborty set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
1620e315cd28SAnirban Chakraborty set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
16211da177e4SLinus Torvalds break;
16221da177e4SLinus Torvalds
16231da177e4SLinus Torvalds case MBA_PORT_UPDATE: /* Port database update */
162455903b9dSSantosh Vernekar /*
162555903b9dSSantosh Vernekar * Handle only global and vn-port update events
162655903b9dSSantosh Vernekar *
162755903b9dSSantosh Vernekar * Relevant inputs:
162855903b9dSSantosh Vernekar * mb[1] = N_Port handle of changed port
162955903b9dSSantosh Vernekar * OR 0xffff for global event
163055903b9dSSantosh Vernekar * mb[2] = New login state
163155903b9dSSantosh Vernekar * 7 = Port logged out
163255903b9dSSantosh Vernekar * mb[3] = LSB is vp_idx, 0xff = all vps
163355903b9dSSantosh Vernekar *
163455903b9dSSantosh Vernekar * Skip processing if:
163555903b9dSSantosh Vernekar * Event is global, vp_idx is NOT all vps,
163655903b9dSSantosh Vernekar * vp_idx does not match
163755903b9dSSantosh Vernekar * Event is not global, vp_idx does not match
163855903b9dSSantosh Vernekar */
163912cec63eSAndrew Vasquez if (IS_QLA2XXX_MIDTYPE(ha) &&
164012cec63eSAndrew Vasquez ((mb[1] == 0xffff && (mb[3] & 0xff) != 0xff) ||
164112cec63eSAndrew Vasquez (mb[1] != 0xffff)) && vha->vp_idx != (mb[3] & 0xff))
164273208dfdSAnirban Chakraborty break;
164373208dfdSAnirban Chakraborty
164417cac3a1SJoe Carnuccio if (mb[2] == 0x7) {
16457c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5010,
164617cac3a1SJoe Carnuccio "Port %s %04x %04x %04x.\n",
164717cac3a1SJoe Carnuccio mb[1] == 0xffff ? "unavailable" : "logout",
16487c3df132SSaurav Kashyap mb[1], mb[2], mb[3]);
164917cac3a1SJoe Carnuccio
165017cac3a1SJoe Carnuccio if (mb[1] == 0xffff)
165117cac3a1SJoe Carnuccio goto global_port_update;
165217cac3a1SJoe Carnuccio
1653b98ae0d7SQuinn Tran if (mb[1] == NPH_SNS_LID(ha)) {
1654b98ae0d7SQuinn Tran set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
1655b98ae0d7SQuinn Tran set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
1656b98ae0d7SQuinn Tran break;
1657b98ae0d7SQuinn Tran }
1658b98ae0d7SQuinn Tran
1659b98ae0d7SQuinn Tran /* use handle_cnt for loop id/nport handle */
1660b98ae0d7SQuinn Tran if (IS_FWI2_CAPABLE(ha))
1661b98ae0d7SQuinn Tran handle_cnt = NPH_SNS;
1662b98ae0d7SQuinn Tran else
1663b98ae0d7SQuinn Tran handle_cnt = SIMPLE_NAME_SERVER;
1664b98ae0d7SQuinn Tran if (mb[1] == handle_cnt) {
1665b98ae0d7SQuinn Tran set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
1666b98ae0d7SQuinn Tran set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
1667b98ae0d7SQuinn Tran break;
1668b98ae0d7SQuinn Tran }
1669b98ae0d7SQuinn Tran
167017cac3a1SJoe Carnuccio /* Port logout */
167117cac3a1SJoe Carnuccio fcport = qla2x00_find_fcport_by_loopid(vha, mb[1]);
167217cac3a1SJoe Carnuccio if (!fcport)
167317cac3a1SJoe Carnuccio break;
167417cac3a1SJoe Carnuccio if (atomic_read(&fcport->state) != FCS_ONLINE)
167517cac3a1SJoe Carnuccio break;
167617cac3a1SJoe Carnuccio ql_dbg(ql_dbg_async, vha, 0x508a,
167717cac3a1SJoe Carnuccio "Marking port lost loopid=%04x portid=%06x.\n",
167817cac3a1SJoe Carnuccio fcport->loop_id, fcport->d_id.b24);
1679726b8548SQuinn Tran if (qla_ini_mode_enabled(vha)) {
1680726b8548SQuinn Tran fcport->logout_on_delete = 0;
1681d8630bb9SQuinn Tran qlt_schedule_sess_for_deletion(fcport);
1682726b8548SQuinn Tran }
168317cac3a1SJoe Carnuccio break;
168417cac3a1SJoe Carnuccio
168517cac3a1SJoe Carnuccio global_port_update:
16869764ff88SAndrew Vasquez if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
16879764ff88SAndrew Vasquez atomic_set(&vha->loop_state, LOOP_DOWN);
16889764ff88SAndrew Vasquez atomic_set(&vha->loop_down_timer,
16899764ff88SAndrew Vasquez LOOP_DOWN_TIME);
16909764ff88SAndrew Vasquez vha->device_flags |= DFLG_NO_CABLE;
16913c75ad1dSHimanshu Madhani qla2x00_mark_all_devices_lost(vha);
16929764ff88SAndrew Vasquez }
16939764ff88SAndrew Vasquez
16949764ff88SAndrew Vasquez if (vha->vp_idx) {
16959764ff88SAndrew Vasquez atomic_set(&vha->vp_state, VP_FAILED);
16969764ff88SAndrew Vasquez fc_vport_set_state(vha->fc_vport,
16979764ff88SAndrew Vasquez FC_VPORT_FAILED);
16983c75ad1dSHimanshu Madhani qla2x00_mark_all_devices_lost(vha);
16999764ff88SAndrew Vasquez }
17009764ff88SAndrew Vasquez
17019764ff88SAndrew Vasquez vha->flags.management_server_logged_in = 0;
17029764ff88SAndrew Vasquez ha->link_data_rate = PORT_SPEED_UNKNOWN;
17039764ff88SAndrew Vasquez break;
17049764ff88SAndrew Vasquez }
17059764ff88SAndrew Vasquez
17061da177e4SLinus Torvalds /*
1707cc3ef7bcSBjorn Helgaas * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET
17081da177e4SLinus Torvalds * event etc. earlier indicating loop is down) then process
17091da177e4SLinus Torvalds * it. Otherwise ignore it and Wait for RSCN to come in.
17101da177e4SLinus Torvalds */
1711e315cd28SAnirban Chakraborty atomic_set(&vha->loop_down_timer, 0);
17128e5a9484SChad Dupuis if (atomic_read(&vha->loop_state) != LOOP_DOWN &&
1713edd05de1SDuane Grigsby !ha->flags.n2n_ae &&
17148e5a9484SChad Dupuis atomic_read(&vha->loop_state) != LOOP_DEAD) {
17157c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5011,
17167c3df132SSaurav Kashyap "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n",
17177c3df132SSaurav Kashyap mb[1], mb[2], mb[3]);
17181da177e4SLinus Torvalds break;
17191da177e4SLinus Torvalds }
17201da177e4SLinus Torvalds
17217c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5012,
17227c3df132SSaurav Kashyap "Port database changed %04x %04x %04x.\n",
17237c3df132SSaurav Kashyap mb[1], mb[2], mb[3]);
17241da177e4SLinus Torvalds
17251da177e4SLinus Torvalds /*
17261da177e4SLinus Torvalds * Mark all devices as missing so we will login again.
17271da177e4SLinus Torvalds */
1728e315cd28SAnirban Chakraborty atomic_set(&vha->loop_state, LOOP_UP);
17296944dccbSQuinn Tran vha->scan.scan_retry = 0;
17301da177e4SLinus Torvalds
1731e315cd28SAnirban Chakraborty set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
1732e315cd28SAnirban Chakraborty set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
1733ded6411fSSawan Chandak set_bit(VP_CONFIG_OK, &vha->vp_flags);
17341da177e4SLinus Torvalds break;
17351da177e4SLinus Torvalds
17361da177e4SLinus Torvalds case MBA_RSCN_UPDATE: /* State Change Registration */
17373c397400SSeokmann Ju /* Check if the Vport has issued a SCR */
1738e315cd28SAnirban Chakraborty if (vha->vp_idx && test_bit(VP_SCR_NEEDED, &vha->vp_flags))
17392c3dfe3fSSeokmann Ju break;
17403c397400SSeokmann Ju /* Only handle SCNs for our Vport index. */
17410d6e61bcSAndrew Vasquez if (ha->flags.npiv_supported && vha->vp_idx != (mb[3] & 0xff))
17423c397400SSeokmann Ju break;
17430d6e61bcSAndrew Vasquez
1744daaecb41SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5013,
17457c3df132SSaurav Kashyap "RSCN database changed -- %04x %04x %04x.\n",
17467c3df132SSaurav Kashyap mb[1], mb[2], mb[3]);
17471da177e4SLinus Torvalds
174859d72d87SRavi Anand rscn_entry = ((mb[1] & 0xff) << 16) | mb[2];
1749e315cd28SAnirban Chakraborty host_pid = (vha->d_id.b.domain << 16) | (vha->d_id.b.area << 8)
1750e315cd28SAnirban Chakraborty | vha->d_id.b.al_pa;
17511da177e4SLinus Torvalds if (rscn_entry == host_pid) {
17527c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5014,
17537c3df132SSaurav Kashyap "Ignoring RSCN update to local host "
17547c3df132SSaurav Kashyap "port ID (%06x).\n", host_pid);
17551da177e4SLinus Torvalds break;
17561da177e4SLinus Torvalds }
17571da177e4SLinus Torvalds
175859d72d87SRavi Anand /* Ignore reserved bits from RSCN-payload. */
175959d72d87SRavi Anand rscn_entry = ((mb[1] & 0x3ff) << 16) | mb[2];
17601da177e4SLinus Torvalds
1761bb4cf5b7SChad Dupuis /* Skip RSCNs for virtual ports on the same physical port */
1762bb4cf5b7SChad Dupuis if (qla2x00_is_a_vp_did(vha, rscn_entry))
1763bb4cf5b7SChad Dupuis break;
1764bb4cf5b7SChad Dupuis
1765e315cd28SAnirban Chakraborty atomic_set(&vha->loop_down_timer, 0);
1766e315cd28SAnirban Chakraborty vha->flags.management_server_logged_in = 0;
1767726b8548SQuinn Tran {
1768726b8548SQuinn Tran struct event_arg ea;
17691da177e4SLinus Torvalds
1770726b8548SQuinn Tran memset(&ea, 0, sizeof(ea));
1771726b8548SQuinn Tran ea.id.b24 = rscn_entry;
177241dc529aSQuinn Tran ea.id.b.rsvd_1 = rscn_entry >> 24;
1773897def20SBart Van Assche qla2x00_handle_rscn(vha, &ea);
1774e315cd28SAnirban Chakraborty qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
1775726b8548SQuinn Tran }
17761da177e4SLinus Torvalds break;
17779f2475feSShyam Sundar case MBA_CONGN_NOTI_RECV:
17789f2475feSShyam Sundar if (!ha->flags.scm_enabled ||
17799f2475feSShyam Sundar mb[1] != QLA_CON_PRIMITIVE_RECEIVED)
17809f2475feSShyam Sundar break;
17819f2475feSShyam Sundar
17829f2475feSShyam Sundar if (mb[2] == QLA_CONGESTION_ARB_WARNING) {
17839f2475feSShyam Sundar ql_dbg(ql_dbg_async, vha, 0x509b,
17849f2475feSShyam Sundar "Congestion Warning %04x %04x.\n", mb[1], mb[2]);
17859f2475feSShyam Sundar } else if (mb[2] == QLA_CONGESTION_ARB_ALARM) {
17869f2475feSShyam Sundar ql_log(ql_log_warn, vha, 0x509b,
17879f2475feSShyam Sundar "Congestion Alarm %04x %04x.\n", mb[1], mb[2]);
17889f2475feSShyam Sundar }
17899f2475feSShyam Sundar break;
17901da177e4SLinus Torvalds /* case MBA_RIO_RESPONSE: */
17911da177e4SLinus Torvalds case MBA_ZIO_RESPONSE:
17927c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5015,
17937c3df132SSaurav Kashyap "[R|Z]IO update completion.\n");
17941da177e4SLinus Torvalds
1795e428924cSAndrew Vasquez if (IS_FWI2_CAPABLE(ha))
17962afa19a9SAnirban Chakraborty qla24xx_process_response_queue(vha, rsp);
17974fdfefe5SAndrew Vasquez else
179873208dfdSAnirban Chakraborty qla2x00_process_response_queue(rsp);
17991da177e4SLinus Torvalds break;
18009a853f71SAndrew Vasquez
18019a853f71SAndrew Vasquez case MBA_DISCARD_RND_FRAME:
18027c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5016,
18037c3df132SSaurav Kashyap "Discard RND Frame -- %04x %04x %04x.\n",
18047c3df132SSaurav Kashyap mb[1], mb[2], mb[3]);
1805dbf1f53cSSaurav Kashyap vha->interface_err_cnt++;
18069a853f71SAndrew Vasquez break;
180745ebeb56SAndrew Vasquez
180845ebeb56SAndrew Vasquez case MBA_TRACE_NOTIFICATION:
18097c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5017,
18107c3df132SSaurav Kashyap "Trace Notification -- %04x %04x.\n", mb[1], mb[2]);
181145ebeb56SAndrew Vasquez break;
18124d4df193SHarihara Kadayam
18134d4df193SHarihara Kadayam case MBA_ISP84XX_ALERT:
18147c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5018,
18157c3df132SSaurav Kashyap "ISP84XX Alert Notification -- %04x %04x %04x.\n",
18167c3df132SSaurav Kashyap mb[1], mb[2], mb[3]);
18174d4df193SHarihara Kadayam
18184d4df193SHarihara Kadayam spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
18194d4df193SHarihara Kadayam switch (mb[1]) {
18204d4df193SHarihara Kadayam case A84_PANIC_RECOVERY:
18217c3df132SSaurav Kashyap ql_log(ql_log_info, vha, 0x5019,
18227c3df132SSaurav Kashyap "Alert 84XX: panic recovery %04x %04x.\n",
18237c3df132SSaurav Kashyap mb[2], mb[3]);
18244d4df193SHarihara Kadayam break;
18254d4df193SHarihara Kadayam case A84_OP_LOGIN_COMPLETE:
18264d4df193SHarihara Kadayam ha->cs84xx->op_fw_version = mb[3] << 16 | mb[2];
18277c3df132SSaurav Kashyap ql_log(ql_log_info, vha, 0x501a,
18287c3df132SSaurav Kashyap "Alert 84XX: firmware version %x.\n",
18297c3df132SSaurav Kashyap ha->cs84xx->op_fw_version);
18304d4df193SHarihara Kadayam break;
18314d4df193SHarihara Kadayam case A84_DIAG_LOGIN_COMPLETE:
18324d4df193SHarihara Kadayam ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
18337c3df132SSaurav Kashyap ql_log(ql_log_info, vha, 0x501b,
18347c3df132SSaurav Kashyap "Alert 84XX: diagnostic firmware version %x.\n",
18357c3df132SSaurav Kashyap ha->cs84xx->diag_fw_version);
18364d4df193SHarihara Kadayam break;
18374d4df193SHarihara Kadayam case A84_GOLD_LOGIN_COMPLETE:
18384d4df193SHarihara Kadayam ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
18394d4df193SHarihara Kadayam ha->cs84xx->fw_update = 1;
18407c3df132SSaurav Kashyap ql_log(ql_log_info, vha, 0x501c,
18417c3df132SSaurav Kashyap "Alert 84XX: gold firmware version %x.\n",
18427c3df132SSaurav Kashyap ha->cs84xx->gold_fw_version);
18434d4df193SHarihara Kadayam break;
18444d4df193SHarihara Kadayam default:
18457c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x501d,
18467c3df132SSaurav Kashyap "Alert 84xx: Invalid Alert %04x %04x %04x.\n",
18474d4df193SHarihara Kadayam mb[1], mb[2], mb[3]);
18484d4df193SHarihara Kadayam }
18494d4df193SHarihara Kadayam spin_unlock_irqrestore(&ha->cs84xx->access_lock, flags);
18504d4df193SHarihara Kadayam break;
18513a03eb79SAndrew Vasquez case MBA_DCBX_START:
18527c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x501e,
18537c3df132SSaurav Kashyap "DCBX Started -- %04x %04x %04x.\n",
18547c3df132SSaurav Kashyap mb[1], mb[2], mb[3]);
18553a03eb79SAndrew Vasquez break;
18563a03eb79SAndrew Vasquez case MBA_DCBX_PARAM_UPDATE:
18577c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x501f,
18587c3df132SSaurav Kashyap "DCBX Parameters Updated -- %04x %04x %04x.\n",
18597c3df132SSaurav Kashyap mb[1], mb[2], mb[3]);
18603a03eb79SAndrew Vasquez break;
18613a03eb79SAndrew Vasquez case MBA_FCF_CONF_ERR:
18627c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5020,
18637c3df132SSaurav Kashyap "FCF Configuration Error -- %04x %04x %04x.\n",
18647c3df132SSaurav Kashyap mb[1], mb[2], mb[3]);
18653a03eb79SAndrew Vasquez break;
18663a03eb79SAndrew Vasquez case MBA_IDC_NOTIFY:
18677ec0effdSAtul Deshmukh if (IS_QLA8031(vha->hw) || IS_QLA8044(ha)) {
186804474d3aSBart Van Assche mb[4] = rd_reg_word(®24->mailbox4);
186967b2a31fSChad Dupuis if (((mb[2] & 0x7fff) == MBC_PORT_RESET ||
187067b2a31fSChad Dupuis (mb[2] & 0x7fff) == MBC_SET_PORT_CONFIG) &&
187167b2a31fSChad Dupuis (mb[4] & INTERNAL_LOOPBACK_MASK) != 0) {
18728fcd6b8bSChad Dupuis set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
187367b2a31fSChad Dupuis /*
187467b2a31fSChad Dupuis * Extend loop down timer since port is active.
187567b2a31fSChad Dupuis */
187667b2a31fSChad Dupuis if (atomic_read(&vha->loop_state) == LOOP_DOWN)
187767b2a31fSChad Dupuis atomic_set(&vha->loop_down_timer,
187867b2a31fSChad Dupuis LOOP_DOWN_TIME);
18798fcd6b8bSChad Dupuis qla2xxx_wake_dpc(vha);
18808fcd6b8bSChad Dupuis }
188167b2a31fSChad Dupuis }
1882df561f66SGustavo A. R. Silva fallthrough;
18838fcd6b8bSChad Dupuis case MBA_IDC_COMPLETE:
18849aaf2ceaSChad Dupuis if (ha->notify_lb_portup_comp && !vha->vp_idx)
1885f356bef1SChad Dupuis complete(&ha->lb_portup_comp);
1886df561f66SGustavo A. R. Silva fallthrough;
18873a03eb79SAndrew Vasquez case MBA_IDC_TIME_EXT:
18887ec0effdSAtul Deshmukh if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw) ||
18897ec0effdSAtul Deshmukh IS_QLA8044(ha))
18908a659571SAndrew Vasquez qla81xx_idc_event(vha, mb[0], mb[1]);
18913a03eb79SAndrew Vasquez break;
18927d613ac6SSantosh Vernekar
18937d613ac6SSantosh Vernekar case MBA_IDC_AEN:
1894d52cd774SQuinn Tran if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
1895dbf1f53cSSaurav Kashyap vha->hw_err_cnt++;
1896cbb01c2fSArun Easi qla27xx_handle_8200_aen(vha, mb);
1897d52cd774SQuinn Tran } else if (IS_QLA83XX(ha)) {
189804474d3aSBart Van Assche mb[4] = rd_reg_word(®24->mailbox4);
189904474d3aSBart Van Assche mb[5] = rd_reg_word(®24->mailbox5);
190004474d3aSBart Van Assche mb[6] = rd_reg_word(®24->mailbox6);
190104474d3aSBart Van Assche mb[7] = rd_reg_word(®24->mailbox7);
19027d613ac6SSantosh Vernekar qla83xx_handle_8200_aen(vha, mb);
1903d52cd774SQuinn Tran } else {
1904d52cd774SQuinn Tran ql_dbg(ql_dbg_async, vha, 0x5052,
1905d52cd774SQuinn Tran "skip Heartbeat processing mb0-3=[0x%04x] [0x%04x] [0x%04x] [0x%04x]\n",
1906d52cd774SQuinn Tran mb[0], mb[1], mb[2], mb[3]);
1907d52cd774SQuinn Tran }
19087d613ac6SSantosh Vernekar break;
19097d613ac6SSantosh Vernekar
1910b5a340ddSJoe Carnuccio case MBA_DPORT_DIAGNOSTICS:
1911476da8faSBikash Hazarika if ((mb[1] & 0xF) == AEN_DONE_DIAG_TEST_WITH_NOERR ||
1912476da8faSBikash Hazarika (mb[1] & 0xF) == AEN_DONE_DIAG_TEST_WITH_ERR)
1913476da8faSBikash Hazarika vha->dport_status &= ~DPORT_DIAG_IN_PROGRESS;
1914b5a340ddSJoe Carnuccio ql_dbg(ql_dbg_async, vha, 0x5052,
191542521564SJoe Carnuccio "D-Port Diagnostics: %04x %04x %04x %04x\n",
191642521564SJoe Carnuccio mb[0], mb[1], mb[2], mb[3]);
1917e6ad2b79SJoe Carnuccio memcpy(vha->dport_data, mb, sizeof(vha->dport_data));
191842521564SJoe Carnuccio if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
191942521564SJoe Carnuccio static char *results[] = {
192042521564SJoe Carnuccio "start", "done(pass)", "done(error)", "undefined" };
192142521564SJoe Carnuccio static char *types[] = {
192242521564SJoe Carnuccio "none", "dynamic", "static", "other" };
192342521564SJoe Carnuccio uint result = mb[1] >> 0 & 0x3;
192442521564SJoe Carnuccio uint type = mb[1] >> 6 & 0x3;
192542521564SJoe Carnuccio uint sw = mb[1] >> 15 & 0x1;
192642521564SJoe Carnuccio ql_dbg(ql_dbg_async, vha, 0x5052,
192742521564SJoe Carnuccio "D-Port Diagnostics: result=%s type=%s [sw=%u]\n",
192842521564SJoe Carnuccio results[result], types[type], sw);
192942521564SJoe Carnuccio if (result == 2) {
193042521564SJoe Carnuccio static char *reasons[] = {
193142521564SJoe Carnuccio "reserved", "unexpected reject",
193242521564SJoe Carnuccio "unexpected phase", "retry exceeded",
193342521564SJoe Carnuccio "timed out", "not supported",
193442521564SJoe Carnuccio "user stopped" };
193542521564SJoe Carnuccio uint reason = mb[2] >> 0 & 0xf;
193642521564SJoe Carnuccio uint phase = mb[2] >> 12 & 0xf;
193742521564SJoe Carnuccio ql_dbg(ql_dbg_async, vha, 0x5052,
193842521564SJoe Carnuccio "D-Port Diagnostics: reason=%s phase=%u \n",
193942521564SJoe Carnuccio reason < 7 ? reasons[reason] : "other",
194042521564SJoe Carnuccio phase >> 1);
194142521564SJoe Carnuccio }
194242521564SJoe Carnuccio }
1943b5a340ddSJoe Carnuccio break;
1944b5a340ddSJoe Carnuccio
1945a29b3dd7SJoe Carnuccio case MBA_TEMPERATURE_ALERT:
1946cd248a95SBikash Hazarika if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
1947cd248a95SBikash Hazarika display_Laser_info(vha, mb[1], mb[2], mb[3]);
1948a29b3dd7SJoe Carnuccio ql_dbg(ql_dbg_async, vha, 0x505e,
1949a29b3dd7SJoe Carnuccio "TEMPERATURE ALERT: %04x %04x %04x\n", mb[1], mb[2], mb[3]);
1950a29b3dd7SJoe Carnuccio break;
1951a29b3dd7SJoe Carnuccio
195292d4408eSSawan Chandak case MBA_TRANS_INSERT:
195392d4408eSSawan Chandak ql_dbg(ql_dbg_async, vha, 0x5091,
195492d4408eSSawan Chandak "Transceiver Insertion: %04x\n", mb[1]);
1955b0f18eeeSAndrew Vasquez set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags);
1956b0f18eeeSAndrew Vasquez break;
1957b0f18eeeSAndrew Vasquez
1958b0f18eeeSAndrew Vasquez case MBA_TRANS_REMOVE:
1959b0f18eeeSAndrew Vasquez ql_dbg(ql_dbg_async, vha, 0x5091, "Transceiver Removal\n");
196092d4408eSSawan Chandak break;
196192d4408eSSawan Chandak
19626246b8a1SGiridhar Malavali default:
19636246b8a1SGiridhar Malavali ql_dbg(ql_dbg_async, vha, 0x5057,
19646246b8a1SGiridhar Malavali "Unknown AEN:%04x %04x %04x %04x\n",
19656246b8a1SGiridhar Malavali mb[0], mb[1], mb[2], mb[3]);
19661da177e4SLinus Torvalds }
19672c3dfe3fSSeokmann Ju
19682d70c103SNicholas Bellinger qlt_async_event(mb[0], vha, mb);
19692d70c103SNicholas Bellinger
1970e315cd28SAnirban Chakraborty if (!vha->vp_idx && ha->num_vhosts)
197173208dfdSAnirban Chakraborty qla2x00_alert_all_vps(rsp, mb);
19721da177e4SLinus Torvalds }
19731da177e4SLinus Torvalds
19741da177e4SLinus Torvalds /**
19751da177e4SLinus Torvalds * qla2x00_process_completed_request() - Process a Fast Post response.
19762db6228dSBart Van Assche * @vha: SCSI driver HA context
19772db6228dSBart Van Assche * @req: request queue
19781da177e4SLinus Torvalds * @index: SRB index
19791da177e4SLinus Torvalds */
19808ae6d9c7SGiridhar Malavali void
qla2x00_process_completed_request(struct scsi_qla_host * vha,struct req_que * req,uint32_t index)198173208dfdSAnirban Chakraborty qla2x00_process_completed_request(struct scsi_qla_host *vha,
198273208dfdSAnirban Chakraborty struct req_que *req, uint32_t index)
19831da177e4SLinus Torvalds {
19841da177e4SLinus Torvalds srb_t *sp;
1985e315cd28SAnirban Chakraborty struct qla_hw_data *ha = vha->hw;
19861da177e4SLinus Torvalds
19871da177e4SLinus Torvalds /* Validate handle. */
19888d93f550SChad Dupuis if (index >= req->num_outstanding_cmds) {
19897c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x3014,
19907c3df132SSaurav Kashyap "Invalid SCSI command index (%x).\n", index);
19911da177e4SLinus Torvalds
19927ec0effdSAtul Deshmukh if (IS_P3P_TYPE(ha))
19938f7daeadSGiridhar Malavali set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
19948f7daeadSGiridhar Malavali else
1995e315cd28SAnirban Chakraborty set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
19961da177e4SLinus Torvalds return;
19971da177e4SLinus Torvalds }
19981da177e4SLinus Torvalds
1999e315cd28SAnirban Chakraborty sp = req->outstanding_cmds[index];
20001da177e4SLinus Torvalds if (sp) {
20011da177e4SLinus Torvalds /* Free outstanding command slot. */
2002e315cd28SAnirban Chakraborty req->outstanding_cmds[index] = NULL;
20031da177e4SLinus Torvalds
20041da177e4SLinus Torvalds /* Save ISP completion status */
200525ff6af1SJoe Carnuccio sp->done(sp, DID_OK << 16);
20061da177e4SLinus Torvalds } else {
20077c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x3016, "Invalid SCSI SRB.\n");
20081da177e4SLinus Torvalds
20097ec0effdSAtul Deshmukh if (IS_P3P_TYPE(ha))
20108f7daeadSGiridhar Malavali set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
20118f7daeadSGiridhar Malavali else
2012e315cd28SAnirban Chakraborty set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
20131da177e4SLinus Torvalds }
20141da177e4SLinus Torvalds }
20151da177e4SLinus Torvalds
2016b843addeSQuinn Tran static srb_t *
qla_get_sp_from_handle(scsi_qla_host_t * vha,const char * func,struct req_que * req,void * iocb,u16 * ret_index)2017b843addeSQuinn Tran qla_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
2018b843addeSQuinn Tran struct req_que *req, void *iocb, u16 *ret_index)
2019ac280b67SAndrew Vasquez {
2020ac280b67SAndrew Vasquez struct qla_hw_data *ha = vha->hw;
2021ac280b67SAndrew Vasquez sts_entry_t *pkt = iocb;
2022622299f1SDaniel Wagner srb_t *sp;
2023ac280b67SAndrew Vasquez uint16_t index;
2024ac280b67SAndrew Vasquez
2025fac28079SQuinn Tran if (pkt->handle == QLA_SKIP_HANDLE)
2026fac28079SQuinn Tran return NULL;
2027fac28079SQuinn Tran
2028ac280b67SAndrew Vasquez index = LSW(pkt->handle);
20298d93f550SChad Dupuis if (index >= req->num_outstanding_cmds) {
20307c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5031,
20317d88d5dfSDaniel Wagner "%s: Invalid command index (%x) type %8ph.\n",
20327d88d5dfSDaniel Wagner func, index, iocb);
20337ec0effdSAtul Deshmukh if (IS_P3P_TYPE(ha))
20348f7daeadSGiridhar Malavali set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
20358f7daeadSGiridhar Malavali else
2036ac280b67SAndrew Vasquez set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2037622299f1SDaniel Wagner return NULL;
2038ac280b67SAndrew Vasquez }
2039ac280b67SAndrew Vasquez sp = req->outstanding_cmds[index];
2040ac280b67SAndrew Vasquez if (!sp) {
20417c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5032,
20427d88d5dfSDaniel Wagner "%s: Invalid completion handle (%x) -- timed-out.\n",
20437d88d5dfSDaniel Wagner func, index);
2044622299f1SDaniel Wagner return NULL;
2045ac280b67SAndrew Vasquez }
2046ac280b67SAndrew Vasquez if (sp->handle != index) {
20477c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5033,
20487d88d5dfSDaniel Wagner "%s: SRB handle (%x) mismatch %x.\n", func,
20497d88d5dfSDaniel Wagner sp->handle, index);
2050ac280b67SAndrew Vasquez return NULL;
2051ac280b67SAndrew Vasquez }
20529a069e19SGiridhar Malavali
2053b843addeSQuinn Tran *ret_index = index;
2054b843addeSQuinn Tran qla_put_fw_resources(sp->qpair, &sp->iores);
2055b843addeSQuinn Tran return sp;
2056b843addeSQuinn Tran }
2057b843addeSQuinn Tran
2058b843addeSQuinn Tran srb_t *
qla2x00_get_sp_from_handle(scsi_qla_host_t * vha,const char * func,struct req_que * req,void * iocb)2059b843addeSQuinn Tran qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
2060b843addeSQuinn Tran struct req_que *req, void *iocb)
2061b843addeSQuinn Tran {
2062b843addeSQuinn Tran uint16_t index;
2063b843addeSQuinn Tran srb_t *sp;
2064b843addeSQuinn Tran
2065b843addeSQuinn Tran sp = qla_get_sp_from_handle(vha, func, req, iocb, &index);
2066b843addeSQuinn Tran if (sp)
2067ac280b67SAndrew Vasquez req->outstanding_cmds[index] = NULL;
2068d3affdebSQuinn Tran
2069ac280b67SAndrew Vasquez return sp;
2070ac280b67SAndrew Vasquez }
2071ac280b67SAndrew Vasquez
2072ac280b67SAndrew Vasquez static void
qla2x00_mbx_iocb_entry(scsi_qla_host_t * vha,struct req_que * req,struct mbx_entry * mbx)2073ac280b67SAndrew Vasquez qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
2074ac280b67SAndrew Vasquez struct mbx_entry *mbx)
2075ac280b67SAndrew Vasquez {
2076ac280b67SAndrew Vasquez const char func[] = "MBX-IOCB";
2077ac280b67SAndrew Vasquez const char *type;
2078ac280b67SAndrew Vasquez fc_port_t *fcport;
2079ac280b67SAndrew Vasquez srb_t *sp;
20804916392bSMadhuranath Iyengar struct srb_iocb *lio;
208199b0bec7SAndrew Vasquez uint16_t *data;
20825ff1d584SAndrew Vasquez uint16_t status;
2083ac280b67SAndrew Vasquez
2084ac280b67SAndrew Vasquez sp = qla2x00_get_sp_from_handle(vha, func, req, mbx);
2085ac280b67SAndrew Vasquez if (!sp)
2086ac280b67SAndrew Vasquez return;
2087ac280b67SAndrew Vasquez
20889ba56b95SGiridhar Malavali lio = &sp->u.iocb_cmd;
20899ba56b95SGiridhar Malavali type = sp->name;
2090ac280b67SAndrew Vasquez fcport = sp->fcport;
20914916392bSMadhuranath Iyengar data = lio->u.logio.data;
2092ac280b67SAndrew Vasquez
20935ff1d584SAndrew Vasquez data[0] = MBS_COMMAND_ERROR;
20944916392bSMadhuranath Iyengar data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
20955ff1d584SAndrew Vasquez QLA_LOGIO_LOGIN_RETRIED : 0;
2096ac280b67SAndrew Vasquez if (mbx->entry_status) {
20977c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5043,
2098cfb0919cSChad Dupuis "Async-%s error entry - hdl=%x portid=%02x%02x%02x "
2099d3fa9e7dSAndrew Vasquez "entry-status=%x status=%x state-flag=%x "
2100cfb0919cSChad Dupuis "status-flags=%x.\n", type, sp->handle,
2101cfb0919cSChad Dupuis fcport->d_id.b.domain, fcport->d_id.b.area,
2102d3fa9e7dSAndrew Vasquez fcport->d_id.b.al_pa, mbx->entry_status,
2103d3fa9e7dSAndrew Vasquez le16_to_cpu(mbx->status), le16_to_cpu(mbx->state_flags),
21047c3df132SSaurav Kashyap le16_to_cpu(mbx->status_flags));
2105d3fa9e7dSAndrew Vasquez
2106cfb0919cSChad Dupuis ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5029,
2107f8f97b0cSJoe Carnuccio mbx, sizeof(*mbx));
2108ac280b67SAndrew Vasquez
210999b0bec7SAndrew Vasquez goto logio_done;
2110ac280b67SAndrew Vasquez }
2111ac280b67SAndrew Vasquez
21125ff1d584SAndrew Vasquez status = le16_to_cpu(mbx->status);
21139ba56b95SGiridhar Malavali if (status == 0x30 && sp->type == SRB_LOGIN_CMD &&
21145ff1d584SAndrew Vasquez le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE)
21155ff1d584SAndrew Vasquez status = 0;
21165ff1d584SAndrew Vasquez if (!status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) {
21177c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5045,
2118cfb0919cSChad Dupuis "Async-%s complete - hdl=%x portid=%02x%02x%02x mbx1=%x.\n",
2119cfb0919cSChad Dupuis type, sp->handle, fcport->d_id.b.domain,
2120cfb0919cSChad Dupuis fcport->d_id.b.area, fcport->d_id.b.al_pa,
2121cfb0919cSChad Dupuis le16_to_cpu(mbx->mb1));
2122ac280b67SAndrew Vasquez
2123ac280b67SAndrew Vasquez data[0] = MBS_COMMAND_COMPLETE;
21249ba56b95SGiridhar Malavali if (sp->type == SRB_LOGIN_CMD) {
212599b0bec7SAndrew Vasquez fcport->port_type = FCT_TARGET;
212699b0bec7SAndrew Vasquez if (le16_to_cpu(mbx->mb1) & BIT_0)
212799b0bec7SAndrew Vasquez fcport->port_type = FCT_INITIATOR;
21286ac52608SAndrew Vasquez else if (le16_to_cpu(mbx->mb1) & BIT_1)
21298474f3a0SSantosh Vernekar fcport->flags |= FCF_FCP2_DEVICE;
21305ff1d584SAndrew Vasquez }
213199b0bec7SAndrew Vasquez goto logio_done;
2132ac280b67SAndrew Vasquez }
2133ac280b67SAndrew Vasquez
2134ac280b67SAndrew Vasquez data[0] = le16_to_cpu(mbx->mb0);
2135ac280b67SAndrew Vasquez switch (data[0]) {
2136ac280b67SAndrew Vasquez case MBS_PORT_ID_USED:
2137ac280b67SAndrew Vasquez data[1] = le16_to_cpu(mbx->mb1);
2138ac280b67SAndrew Vasquez break;
2139ac280b67SAndrew Vasquez case MBS_LOOP_ID_USED:
2140ac280b67SAndrew Vasquez break;
2141ac280b67SAndrew Vasquez default:
2142ac280b67SAndrew Vasquez data[0] = MBS_COMMAND_ERROR;
2143ac280b67SAndrew Vasquez break;
2144ac280b67SAndrew Vasquez }
2145ac280b67SAndrew Vasquez
21467c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5046,
2147cfb0919cSChad Dupuis "Async-%s failed - hdl=%x portid=%02x%02x%02x status=%x "
2148cfb0919cSChad Dupuis "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n", type, sp->handle,
2149cfb0919cSChad Dupuis fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
2150cfb0919cSChad Dupuis status, le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1),
2151ac280b67SAndrew Vasquez le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6),
21527c3df132SSaurav Kashyap le16_to_cpu(mbx->mb7));
2153ac280b67SAndrew Vasquez
215499b0bec7SAndrew Vasquez logio_done:
215525ff6af1SJoe Carnuccio sp->done(sp, 0);
2156ac280b67SAndrew Vasquez }
2157ac280b67SAndrew Vasquez
2158ac280b67SAndrew Vasquez static void
qla24xx_mbx_iocb_entry(scsi_qla_host_t * vha,struct req_que * req,struct mbx_24xx_entry * pkt)2159726b8548SQuinn Tran qla24xx_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
2160726b8548SQuinn Tran struct mbx_24xx_entry *pkt)
2161726b8548SQuinn Tran {
2162726b8548SQuinn Tran const char func[] = "MBX-IOCB2";
2163657ed8a8SDaniel Wagner struct qla_hw_data *ha = vha->hw;
2164726b8548SQuinn Tran srb_t *sp;
2165726b8548SQuinn Tran struct srb_iocb *si;
2166726b8548SQuinn Tran u16 sz, i;
2167726b8548SQuinn Tran int res;
2168726b8548SQuinn Tran
2169726b8548SQuinn Tran sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
2170726b8548SQuinn Tran if (!sp)
2171726b8548SQuinn Tran return;
2172726b8548SQuinn Tran
2173657ed8a8SDaniel Wagner if (sp->type == SRB_SCSI_CMD ||
2174657ed8a8SDaniel Wagner sp->type == SRB_NVME_CMD ||
2175657ed8a8SDaniel Wagner sp->type == SRB_TM_CMD) {
2176657ed8a8SDaniel Wagner ql_log(ql_log_warn, vha, 0x509d,
2177657ed8a8SDaniel Wagner "Inconsistent event entry type %d\n", sp->type);
2178657ed8a8SDaniel Wagner if (IS_P3P_TYPE(ha))
2179657ed8a8SDaniel Wagner set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
2180657ed8a8SDaniel Wagner else
2181657ed8a8SDaniel Wagner set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2182657ed8a8SDaniel Wagner return;
2183657ed8a8SDaniel Wagner }
2184657ed8a8SDaniel Wagner
2185726b8548SQuinn Tran si = &sp->u.iocb_cmd;
2186726b8548SQuinn Tran sz = min(ARRAY_SIZE(pkt->mb), ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.in_mb));
2187726b8548SQuinn Tran
2188726b8548SQuinn Tran for (i = 0; i < sz; i++)
21897ffa5b93SBart Van Assche si->u.mbx.in_mb[i] = pkt->mb[i];
2190726b8548SQuinn Tran
2191726b8548SQuinn Tran res = (si->u.mbx.in_mb[0] & MBS_MASK);
2192726b8548SQuinn Tran
219325ff6af1SJoe Carnuccio sp->done(sp, res);
2194726b8548SQuinn Tran }
2195726b8548SQuinn Tran
2196726b8548SQuinn Tran static void
qla24xxx_nack_iocb_entry(scsi_qla_host_t * vha,struct req_que * req,struct nack_to_isp * pkt)2197726b8548SQuinn Tran qla24xxx_nack_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
2198726b8548SQuinn Tran struct nack_to_isp *pkt)
2199726b8548SQuinn Tran {
2200726b8548SQuinn Tran const char func[] = "nack";
2201726b8548SQuinn Tran srb_t *sp;
2202726b8548SQuinn Tran int res = 0;
2203726b8548SQuinn Tran
2204726b8548SQuinn Tran sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
2205726b8548SQuinn Tran if (!sp)
2206726b8548SQuinn Tran return;
2207726b8548SQuinn Tran
2208726b8548SQuinn Tran if (pkt->u.isp2x.status != cpu_to_le16(NOTIFY_ACK_SUCCESS))
2209726b8548SQuinn Tran res = QLA_FUNCTION_FAILED;
2210726b8548SQuinn Tran
221125ff6af1SJoe Carnuccio sp->done(sp, res);
2212ac280b67SAndrew Vasquez }
2213ac280b67SAndrew Vasquez
2214ac280b67SAndrew Vasquez static void
qla2x00_ct_entry(scsi_qla_host_t * vha,struct req_que * req,sts_entry_t * pkt,int iocb_type)22159bc4f4fbSHarish Zunjarrao qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
22169bc4f4fbSHarish Zunjarrao sts_entry_t *pkt, int iocb_type)
22179bc4f4fbSHarish Zunjarrao {
22189bc4f4fbSHarish Zunjarrao const char func[] = "CT_IOCB";
22199bc4f4fbSHarish Zunjarrao const char *type;
22209bc4f4fbSHarish Zunjarrao srb_t *sp;
222175cc8cfcSJohannes Thumshirn struct bsg_job *bsg_job;
222201e0e15cSJohannes Thumshirn struct fc_bsg_reply *bsg_reply;
22239bc4f4fbSHarish Zunjarrao uint16_t comp_status;
2224726b8548SQuinn Tran int res = 0;
22259bc4f4fbSHarish Zunjarrao
22269bc4f4fbSHarish Zunjarrao sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
22279bc4f4fbSHarish Zunjarrao if (!sp)
22289bc4f4fbSHarish Zunjarrao return;
22299bc4f4fbSHarish Zunjarrao
2230726b8548SQuinn Tran switch (sp->type) {
2231726b8548SQuinn Tran case SRB_CT_CMD:
22329ba56b95SGiridhar Malavali bsg_job = sp->u.bsg_job;
223301e0e15cSJohannes Thumshirn bsg_reply = bsg_job->reply;
22349bc4f4fbSHarish Zunjarrao
22359bc4f4fbSHarish Zunjarrao type = "ct pass-through";
22369bc4f4fbSHarish Zunjarrao
22379bc4f4fbSHarish Zunjarrao comp_status = le16_to_cpu(pkt->comp_status);
22389bc4f4fbSHarish Zunjarrao
2239726b8548SQuinn Tran /*
2240726b8548SQuinn Tran * return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
22419bc4f4fbSHarish Zunjarrao * fc payload to the caller
22429bc4f4fbSHarish Zunjarrao */
224301e0e15cSJohannes Thumshirn bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
22449bc4f4fbSHarish Zunjarrao bsg_job->reply_len = sizeof(struct fc_bsg_reply);
22459bc4f4fbSHarish Zunjarrao
22469bc4f4fbSHarish Zunjarrao if (comp_status != CS_COMPLETE) {
22479bc4f4fbSHarish Zunjarrao if (comp_status == CS_DATA_UNDERRUN) {
22489ba56b95SGiridhar Malavali res = DID_OK << 16;
224901e0e15cSJohannes Thumshirn bsg_reply->reply_payload_rcv_len =
22501a20719eSBart Van Assche le16_to_cpu(pkt->rsp_info_len);
22519bc4f4fbSHarish Zunjarrao
22527c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5048,
2253726b8548SQuinn Tran "CT pass-through-%s error comp_status=0x%x total_byte=0x%x.\n",
22547c3df132SSaurav Kashyap type, comp_status,
225501e0e15cSJohannes Thumshirn bsg_reply->reply_payload_rcv_len);
22569bc4f4fbSHarish Zunjarrao } else {
22577c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5049,
2258726b8548SQuinn Tran "CT pass-through-%s error comp_status=0x%x.\n",
2259726b8548SQuinn Tran type, comp_status);
22609ba56b95SGiridhar Malavali res = DID_ERROR << 16;
226101e0e15cSJohannes Thumshirn bsg_reply->reply_payload_rcv_len = 0;
22629bc4f4fbSHarish Zunjarrao }
2263cfb0919cSChad Dupuis ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
2264f8f97b0cSJoe Carnuccio pkt, sizeof(*pkt));
22659bc4f4fbSHarish Zunjarrao } else {
22669ba56b95SGiridhar Malavali res = DID_OK << 16;
226701e0e15cSJohannes Thumshirn bsg_reply->reply_payload_rcv_len =
22689bc4f4fbSHarish Zunjarrao bsg_job->reply_payload.payload_len;
22699bc4f4fbSHarish Zunjarrao bsg_job->reply_len = 0;
22709bc4f4fbSHarish Zunjarrao }
2271726b8548SQuinn Tran break;
2272726b8548SQuinn Tran case SRB_CT_PTHRU_CMD:
2273726b8548SQuinn Tran /*
2274726b8548SQuinn Tran * borrowing sts_entry_24xx.comp_status.
2275726b8548SQuinn Tran * same location as ct_entry_24xx.comp_status
2276726b8548SQuinn Tran */
2277726b8548SQuinn Tran res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
2278726b8548SQuinn Tran (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
2279726b8548SQuinn Tran sp->name);
2280726b8548SQuinn Tran break;
2281726b8548SQuinn Tran }
22829bc4f4fbSHarish Zunjarrao
228325ff6af1SJoe Carnuccio sp->done(sp, res);
22849bc4f4fbSHarish Zunjarrao }
22859bc4f4fbSHarish Zunjarrao
22869bc4f4fbSHarish Zunjarrao static void
qla24xx_els_ct_entry(scsi_qla_host_t * v,struct req_que * req,struct sts_entry_24xx * pkt,int iocb_type)228784318a9fSQuinn Tran qla24xx_els_ct_entry(scsi_qla_host_t *v, struct req_que *req,
22889a069e19SGiridhar Malavali struct sts_entry_24xx *pkt, int iocb_type)
22899a069e19SGiridhar Malavali {
22907ffa5b93SBart Van Assche struct els_sts_entry_24xx *ese = (struct els_sts_entry_24xx *)pkt;
22919a069e19SGiridhar Malavali const char func[] = "ELS_CT_IOCB";
22929a069e19SGiridhar Malavali const char *type;
22939a069e19SGiridhar Malavali srb_t *sp;
229475cc8cfcSJohannes Thumshirn struct bsg_job *bsg_job;
229501e0e15cSJohannes Thumshirn struct fc_bsg_reply *bsg_reply;
22969a069e19SGiridhar Malavali uint16_t comp_status;
22979a069e19SGiridhar Malavali uint32_t fw_status[3];
229884318a9fSQuinn Tran int res, logit = 1;
2299edd05de1SDuane Grigsby struct srb_iocb *els;
230084318a9fSQuinn Tran uint n;
230184318a9fSQuinn Tran scsi_qla_host_t *vha;
230284318a9fSQuinn Tran struct els_sts_entry_24xx *e = (struct els_sts_entry_24xx *)pkt;
23039a069e19SGiridhar Malavali
230484318a9fSQuinn Tran sp = qla2x00_get_sp_from_handle(v, func, req, pkt);
23059a069e19SGiridhar Malavali if (!sp)
23069a069e19SGiridhar Malavali return;
230784318a9fSQuinn Tran bsg_job = sp->u.bsg_job;
230884318a9fSQuinn Tran vha = sp->vha;
23099a069e19SGiridhar Malavali
23109a069e19SGiridhar Malavali type = NULL;
231184318a9fSQuinn Tran
231284318a9fSQuinn Tran comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status);
231384318a9fSQuinn Tran fw_status[1] = le32_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_1);
231484318a9fSQuinn Tran fw_status[2] = le32_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_2);
231584318a9fSQuinn Tran
23169ba56b95SGiridhar Malavali switch (sp->type) {
23179a069e19SGiridhar Malavali case SRB_ELS_CMD_RPT:
23189a069e19SGiridhar Malavali case SRB_ELS_CMD_HST:
231984318a9fSQuinn Tran type = "rpt hst";
232084318a9fSQuinn Tran break;
232184318a9fSQuinn Tran case SRB_ELS_CMD_HST_NOLOGIN:
23229a069e19SGiridhar Malavali type = "els";
232384318a9fSQuinn Tran {
232484318a9fSQuinn Tran struct els_entry_24xx *els = (void *)pkt;
232584318a9fSQuinn Tran struct qla_bsg_auth_els_request *p =
232684318a9fSQuinn Tran (struct qla_bsg_auth_els_request *)bsg_job->request;
232784318a9fSQuinn Tran
232884318a9fSQuinn Tran ql_dbg(ql_dbg_user, vha, 0x700f,
232984318a9fSQuinn Tran "%s %s. portid=%02x%02x%02x status %x xchg %x bsg ptr %p\n",
233084318a9fSQuinn Tran __func__, sc_to_str(p->e.sub_cmd),
233184318a9fSQuinn Tran e->d_id[2], e->d_id[1], e->d_id[0],
233284318a9fSQuinn Tran comp_status, p->e.extra_rx_xchg_address, bsg_job);
233384318a9fSQuinn Tran
233484318a9fSQuinn Tran if (!(le16_to_cpu(els->control_flags) & ECF_PAYLOAD_DESCR_MASK)) {
233584318a9fSQuinn Tran if (sp->remap.remapped) {
233684318a9fSQuinn Tran n = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
233784318a9fSQuinn Tran bsg_job->reply_payload.sg_cnt,
233884318a9fSQuinn Tran sp->remap.rsp.buf,
233984318a9fSQuinn Tran sp->remap.rsp.len);
234084318a9fSQuinn Tran ql_dbg(ql_dbg_user + ql_dbg_verbose, vha, 0x700e,
234184318a9fSQuinn Tran "%s: SG copied %x of %x\n",
234284318a9fSQuinn Tran __func__, n, sp->remap.rsp.len);
234384318a9fSQuinn Tran } else {
234484318a9fSQuinn Tran ql_dbg(ql_dbg_user, vha, 0x700f,
234584318a9fSQuinn Tran "%s: NOT REMAPPED (error)...!!!\n",
234684318a9fSQuinn Tran __func__);
234784318a9fSQuinn Tran }
234884318a9fSQuinn Tran }
234984318a9fSQuinn Tran }
23509a069e19SGiridhar Malavali break;
23519a069e19SGiridhar Malavali case SRB_CT_CMD:
23529a069e19SGiridhar Malavali type = "ct pass-through";
23539a069e19SGiridhar Malavali break;
23546eb54715SHimanshu Madhani case SRB_ELS_DCMD:
23556eb54715SHimanshu Madhani type = "Driver ELS logo";
2356edd05de1SDuane Grigsby if (iocb_type != ELS_IOCB_TYPE) {
23576eb54715SHimanshu Madhani ql_dbg(ql_dbg_user, vha, 0x5047,
2358edd05de1SDuane Grigsby "Completing %s: (%p) type=%d.\n",
2359edd05de1SDuane Grigsby type, sp, sp->type);
236025ff6af1SJoe Carnuccio sp->done(sp, 0);
23616eb54715SHimanshu Madhani return;
2362edd05de1SDuane Grigsby }
2363edd05de1SDuane Grigsby break;
2364726b8548SQuinn Tran case SRB_CT_PTHRU_CMD:
2365726b8548SQuinn Tran /* borrowing sts_entry_24xx.comp_status.
2366726b8548SQuinn Tran same location as ct_entry_24xx.comp_status
2367726b8548SQuinn Tran */
23682d73ac61SQuinn Tran res = qla2x00_chk_ms_status(sp->vha, (ms_iocb_entry_t *)pkt,
2369726b8548SQuinn Tran (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
2370726b8548SQuinn Tran sp->name);
237125ff6af1SJoe Carnuccio sp->done(sp, res);
23729a069e19SGiridhar Malavali return;
23739a069e19SGiridhar Malavali default:
23749a069e19SGiridhar Malavali ql_dbg(ql_dbg_user, vha, 0x503e,
23759a069e19SGiridhar Malavali "Unrecognized SRB: (%p) type=%d.\n", sp, sp->type);
23769a069e19SGiridhar Malavali return;
23779a069e19SGiridhar Malavali }
23789a069e19SGiridhar Malavali
2379edd05de1SDuane Grigsby if (iocb_type == ELS_IOCB_TYPE) {
2380edd05de1SDuane Grigsby els = &sp->u.iocb_cmd;
23817ffa5b93SBart Van Assche els->u.els_plogi.fw_status[0] = cpu_to_le32(fw_status[0]);
23827ffa5b93SBart Van Assche els->u.els_plogi.fw_status[1] = cpu_to_le32(fw_status[1]);
23837ffa5b93SBart Van Assche els->u.els_plogi.fw_status[2] = cpu_to_le32(fw_status[2]);
23847ffa5b93SBart Van Assche els->u.els_plogi.comp_status = cpu_to_le16(fw_status[0]);
2385edd05de1SDuane Grigsby if (comp_status == CS_COMPLETE) {
2386edd05de1SDuane Grigsby res = DID_OK << 16;
2387edd05de1SDuane Grigsby } else {
2388edd05de1SDuane Grigsby if (comp_status == CS_DATA_UNDERRUN) {
2389edd05de1SDuane Grigsby res = DID_OK << 16;
23907ffa5b93SBart Van Assche els->u.els_plogi.len = cpu_to_le16(le32_to_cpu(
23917ffa5b93SBart Van Assche ese->total_byte_count));
239284318a9fSQuinn Tran
239384318a9fSQuinn Tran if (sp->remap.remapped &&
239484318a9fSQuinn Tran ((u8 *)sp->remap.rsp.buf)[0] == ELS_LS_ACC) {
239584318a9fSQuinn Tran ql_dbg(ql_dbg_user, vha, 0x503f,
239684318a9fSQuinn Tran "%s IOCB Done LS_ACC %02x%02x%02x -> %02x%02x%02x",
239784318a9fSQuinn Tran __func__, e->s_id[0], e->s_id[2], e->s_id[1],
239884318a9fSQuinn Tran e->d_id[2], e->d_id[1], e->d_id[0]);
239984318a9fSQuinn Tran logit = 0;
240084318a9fSQuinn Tran }
240184318a9fSQuinn Tran
240284318a9fSQuinn Tran } else if (comp_status == CS_PORT_LOGGED_OUT) {
24036c9998ceSQuinn Tran ql_dbg(ql_dbg_disc, vha, 0x911e,
24046c9998ceSQuinn Tran "%s %d schedule session deletion\n",
24056c9998ceSQuinn Tran __func__, __LINE__);
24066c9998ceSQuinn Tran
240784318a9fSQuinn Tran els->u.els_plogi.len = 0;
240884318a9fSQuinn Tran res = DID_IMM_RETRY << 16;
2409b15ce2f3SQuinn Tran qlt_schedule_sess_for_deletion(sp->fcport);
2410edd05de1SDuane Grigsby } else {
2411edd05de1SDuane Grigsby els->u.els_plogi.len = 0;
2412edd05de1SDuane Grigsby res = DID_ERROR << 16;
2413edd05de1SDuane Grigsby }
241484318a9fSQuinn Tran
241584318a9fSQuinn Tran if (sp->remap.remapped &&
241684318a9fSQuinn Tran ((u8 *)sp->remap.rsp.buf)[0] == ELS_LS_RJT) {
2417bcf53607SQuinn Tran if (logit) {
241884318a9fSQuinn Tran ql_dbg(ql_dbg_user, vha, 0x503f,
241984318a9fSQuinn Tran "%s IOCB Done LS_RJT hdl=%x comp_status=0x%x\n",
242084318a9fSQuinn Tran type, sp->handle, comp_status);
242184318a9fSQuinn Tran
242284318a9fSQuinn Tran ql_dbg(ql_dbg_user, vha, 0x503f,
242384318a9fSQuinn Tran "subcode 1=0x%x subcode 2=0x%x bytes=0x%x %02x%02x%02x -> %02x%02x%02x\n",
242484318a9fSQuinn Tran fw_status[1], fw_status[2],
242584318a9fSQuinn Tran le32_to_cpu(((struct els_sts_entry_24xx *)
242684318a9fSQuinn Tran pkt)->total_byte_count),
242784318a9fSQuinn Tran e->s_id[0], e->s_id[2], e->s_id[1],
242884318a9fSQuinn Tran e->d_id[2], e->d_id[1], e->d_id[0]);
2429bcf53607SQuinn Tran }
2430bcf53607SQuinn Tran if (sp->fcport && sp->fcport->flags & FCF_FCSP_DEVICE &&
2431bcf53607SQuinn Tran sp->type == SRB_ELS_CMD_HST_NOLOGIN) {
2432bcf53607SQuinn Tran ql_dbg(ql_dbg_edif, vha, 0x911e,
2433bcf53607SQuinn Tran "%s rcv reject. Sched delete\n", __func__);
2434bcf53607SQuinn Tran qlt_schedule_sess_for_deletion(sp->fcport);
2435bcf53607SQuinn Tran }
2436bcf53607SQuinn Tran } else if (logit) {
243784318a9fSQuinn Tran ql_log(ql_log_info, vha, 0x503f,
243884318a9fSQuinn Tran "%s IOCB Done hdl=%x comp_status=0x%x\n",
243984318a9fSQuinn Tran type, sp->handle, comp_status);
244084318a9fSQuinn Tran ql_log(ql_log_info, vha, 0x503f,
244184318a9fSQuinn Tran "subcode 1=0x%x subcode 2=0x%x bytes=0x%x %02x%02x%02x -> %02x%02x%02x\n",
244284318a9fSQuinn Tran fw_status[1], fw_status[2],
244384318a9fSQuinn Tran le32_to_cpu(((struct els_sts_entry_24xx *)
244484318a9fSQuinn Tran pkt)->total_byte_count),
244584318a9fSQuinn Tran e->s_id[0], e->s_id[2], e->s_id[1],
244684318a9fSQuinn Tran e->d_id[2], e->d_id[1], e->d_id[0]);
2447edd05de1SDuane Grigsby }
244884318a9fSQuinn Tran }
2449edd05de1SDuane Grigsby goto els_ct_done;
2450edd05de1SDuane Grigsby }
2451edd05de1SDuane Grigsby
24529a069e19SGiridhar Malavali /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
24539a069e19SGiridhar Malavali * fc payload to the caller
24549a069e19SGiridhar Malavali */
2455a1730595SDuane Grigsby bsg_job = sp->u.bsg_job;
2456a1730595SDuane Grigsby bsg_reply = bsg_job->reply;
245701e0e15cSJohannes Thumshirn bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
24589a069e19SGiridhar Malavali bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(fw_status);
24599a069e19SGiridhar Malavali
24609a069e19SGiridhar Malavali if (comp_status != CS_COMPLETE) {
24619a069e19SGiridhar Malavali if (comp_status == CS_DATA_UNDERRUN) {
24629ba56b95SGiridhar Malavali res = DID_OK << 16;
246301e0e15cSJohannes Thumshirn bsg_reply->reply_payload_rcv_len =
24647ffa5b93SBart Van Assche le32_to_cpu(ese->total_byte_count);
24659a069e19SGiridhar Malavali
246637fed3eeSAndrew Vasquez ql_dbg(ql_dbg_user, vha, 0x503f,
2467cfb0919cSChad Dupuis "ELS-CT pass-through-%s error hdl=%x comp_status-status=0x%x "
24689a069e19SGiridhar Malavali "error subcode 1=0x%x error subcode 2=0x%x total_byte = 0x%x.\n",
2469cfb0919cSChad Dupuis type, sp->handle, comp_status, fw_status[1], fw_status[2],
24707ffa5b93SBart Van Assche le32_to_cpu(ese->total_byte_count));
247105231a3bSChristoph Hellwig } else {
247237fed3eeSAndrew Vasquez ql_dbg(ql_dbg_user, vha, 0x5040,
2473cfb0919cSChad Dupuis "ELS-CT pass-through-%s error hdl=%x comp_status-status=0x%x "
24749a069e19SGiridhar Malavali "error subcode 1=0x%x error subcode 2=0x%x.\n",
2475cfb0919cSChad Dupuis type, sp->handle, comp_status,
24767ffa5b93SBart Van Assche le32_to_cpu(ese->error_subcode_1),
24777ffa5b93SBart Van Assche le32_to_cpu(ese->error_subcode_2));
24789ba56b95SGiridhar Malavali res = DID_ERROR << 16;
247901e0e15cSJohannes Thumshirn bsg_reply->reply_payload_rcv_len = 0;
24809a069e19SGiridhar Malavali }
248105231a3bSChristoph Hellwig memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply),
248205231a3bSChristoph Hellwig fw_status, sizeof(fw_status));
248337fed3eeSAndrew Vasquez ql_dump_buffer(ql_dbg_user + ql_dbg_buffer, vha, 0x5056,
2484f8f97b0cSJoe Carnuccio pkt, sizeof(*pkt));
24859a069e19SGiridhar Malavali }
24869a069e19SGiridhar Malavali else {
24879ba56b95SGiridhar Malavali res = DID_OK << 16;
248801e0e15cSJohannes Thumshirn bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
24899a069e19SGiridhar Malavali bsg_job->reply_len = 0;
24909a069e19SGiridhar Malavali }
2491edd05de1SDuane Grigsby els_ct_done:
24929a069e19SGiridhar Malavali
249325ff6af1SJoe Carnuccio sp->done(sp, res);
24949a069e19SGiridhar Malavali }
24959a069e19SGiridhar Malavali
24969a069e19SGiridhar Malavali static void
qla24xx_logio_entry(scsi_qla_host_t * vha,struct req_que * req,struct logio_entry_24xx * logio)2497ac280b67SAndrew Vasquez qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
2498ac280b67SAndrew Vasquez struct logio_entry_24xx *logio)
2499ac280b67SAndrew Vasquez {
2500ac280b67SAndrew Vasquez const char func[] = "LOGIO-IOCB";
2501ac280b67SAndrew Vasquez const char *type;
2502ac280b67SAndrew Vasquez fc_port_t *fcport;
2503ac280b67SAndrew Vasquez srb_t *sp;
25044916392bSMadhuranath Iyengar struct srb_iocb *lio;
250599b0bec7SAndrew Vasquez uint16_t *data;
2506ac280b67SAndrew Vasquez uint32_t iop[2];
2507a5741427SArun Easi int logit = 1;
2508ac280b67SAndrew Vasquez
2509ac280b67SAndrew Vasquez sp = qla2x00_get_sp_from_handle(vha, func, req, logio);
2510ac280b67SAndrew Vasquez if (!sp)
2511ac280b67SAndrew Vasquez return;
2512ac280b67SAndrew Vasquez
25139ba56b95SGiridhar Malavali lio = &sp->u.iocb_cmd;
25149ba56b95SGiridhar Malavali type = sp->name;
2515ac280b67SAndrew Vasquez fcport = sp->fcport;
25164916392bSMadhuranath Iyengar data = lio->u.logio.data;
2517ac280b67SAndrew Vasquez
25185ff1d584SAndrew Vasquez data[0] = MBS_COMMAND_ERROR;
25194916392bSMadhuranath Iyengar data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
25205ff1d584SAndrew Vasquez QLA_LOGIO_LOGIN_RETRIED : 0;
2521ac280b67SAndrew Vasquez if (logio->entry_status) {
25225e19ed90SArun Easi ql_log(ql_log_warn, fcport->vha, 0x5034,
25235b33469aSQuinn Tran "Async-%s error entry - %8phC hdl=%x"
2524d3fa9e7dSAndrew Vasquez "portid=%02x%02x%02x entry-status=%x.\n",
25255b33469aSQuinn Tran type, fcport->port_name, sp->handle, fcport->d_id.b.domain,
2526cfb0919cSChad Dupuis fcport->d_id.b.area, fcport->d_id.b.al_pa,
2527cfb0919cSChad Dupuis logio->entry_status);
2528cfb0919cSChad Dupuis ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x504d,
2529f8f97b0cSJoe Carnuccio logio, sizeof(*logio));
2530ac280b67SAndrew Vasquez
253199b0bec7SAndrew Vasquez goto logio_done;
2532ac280b67SAndrew Vasquez }
2533ac280b67SAndrew Vasquez
2534ac280b67SAndrew Vasquez if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) {
2535cbe729a6SJoe Carnuccio ql_dbg(ql_dbg_async, sp->vha, 0x5036,
2536cbe729a6SJoe Carnuccio "Async-%s complete: handle=%x pid=%06x wwpn=%8phC iop0=%x\n",
2537cbe729a6SJoe Carnuccio type, sp->handle, fcport->d_id.b24, fcport->port_name,
25387c3df132SSaurav Kashyap le32_to_cpu(logio->io_parameter[0]));
2539ac280b67SAndrew Vasquez
2540ead03855SQuinn Tran vha->hw->exch_starvation = 0;
2541ac280b67SAndrew Vasquez data[0] = MBS_COMMAND_COMPLETE;
254203aaa89fSDarren Trapp
254303aaa89fSDarren Trapp if (sp->type == SRB_PRLI_CMD) {
254403aaa89fSDarren Trapp lio->u.logio.iop[0] =
254503aaa89fSDarren Trapp le32_to_cpu(logio->io_parameter[0]);
254603aaa89fSDarren Trapp lio->u.logio.iop[1] =
254703aaa89fSDarren Trapp le32_to_cpu(logio->io_parameter[1]);
254803aaa89fSDarren Trapp goto logio_done;
254903aaa89fSDarren Trapp }
255003aaa89fSDarren Trapp
25519ba56b95SGiridhar Malavali if (sp->type != SRB_LOGIN_CMD)
255299b0bec7SAndrew Vasquez goto logio_done;
2553ac280b67SAndrew Vasquez
25549efea843SQuinn Tran lio->u.logio.iop[1] = le32_to_cpu(logio->io_parameter[5]);
25559efea843SQuinn Tran if (le32_to_cpu(logio->io_parameter[5]) & LIO_COMM_FEAT_FCSP)
25569efea843SQuinn Tran fcport->flags |= FCF_FCSP_DEVICE;
25579efea843SQuinn Tran
2558ac280b67SAndrew Vasquez iop[0] = le32_to_cpu(logio->io_parameter[0]);
2559ac280b67SAndrew Vasquez if (iop[0] & BIT_4) {
2560ac280b67SAndrew Vasquez fcport->port_type = FCT_TARGET;
2561ac280b67SAndrew Vasquez if (iop[0] & BIT_8)
25628474f3a0SSantosh Vernekar fcport->flags |= FCF_FCP2_DEVICE;
2563b0cd579cSAndrew Vasquez } else if (iop[0] & BIT_5)
2564ac280b67SAndrew Vasquez fcport->port_type = FCT_INITIATOR;
2565b0cd579cSAndrew Vasquez
25662d70c103SNicholas Bellinger if (iop[0] & BIT_7)
25672d70c103SNicholas Bellinger fcport->flags |= FCF_CONF_COMP_SUPPORTED;
25682d70c103SNicholas Bellinger
2569ac280b67SAndrew Vasquez if (logio->io_parameter[7] || logio->io_parameter[8])
2570ac280b67SAndrew Vasquez fcport->supported_classes |= FC_COS_CLASS2;
2571ac280b67SAndrew Vasquez if (logio->io_parameter[9] || logio->io_parameter[10])
2572ac280b67SAndrew Vasquez fcport->supported_classes |= FC_COS_CLASS3;
2573ac280b67SAndrew Vasquez
257499b0bec7SAndrew Vasquez goto logio_done;
2575ac280b67SAndrew Vasquez }
2576ac280b67SAndrew Vasquez
2577ac280b67SAndrew Vasquez iop[0] = le32_to_cpu(logio->io_parameter[0]);
2578ac280b67SAndrew Vasquez iop[1] = le32_to_cpu(logio->io_parameter[1]);
2579726b8548SQuinn Tran lio->u.logio.iop[0] = iop[0];
2580726b8548SQuinn Tran lio->u.logio.iop[1] = iop[1];
2581ac280b67SAndrew Vasquez switch (iop[0]) {
2582ac280b67SAndrew Vasquez case LSC_SCODE_PORTID_USED:
2583ac280b67SAndrew Vasquez data[0] = MBS_PORT_ID_USED;
2584ac280b67SAndrew Vasquez data[1] = LSW(iop[1]);
2585a5741427SArun Easi logit = 0;
2586ac280b67SAndrew Vasquez break;
2587ac280b67SAndrew Vasquez case LSC_SCODE_NPORT_USED:
2588ac280b67SAndrew Vasquez data[0] = MBS_LOOP_ID_USED;
2589a5741427SArun Easi logit = 0;
2590ac280b67SAndrew Vasquez break;
25915b33469aSQuinn Tran case LSC_SCODE_CMD_FAILED:
25925b33469aSQuinn Tran if (iop[1] == 0x0606) {
25935b33469aSQuinn Tran /*
25945b33469aSQuinn Tran * PLOGI/PRLI Completed. We must have Recv PLOGI/PRLI,
25955b33469aSQuinn Tran * Target side acked.
25965b33469aSQuinn Tran */
25975b33469aSQuinn Tran data[0] = MBS_COMMAND_COMPLETE;
25985b33469aSQuinn Tran goto logio_done;
25995b33469aSQuinn Tran }
26005b33469aSQuinn Tran data[0] = MBS_COMMAND_ERROR;
26015b33469aSQuinn Tran break;
2602ead03855SQuinn Tran case LSC_SCODE_NOXCB:
2603ead03855SQuinn Tran vha->hw->exch_starvation++;
2604ead03855SQuinn Tran if (vha->hw->exch_starvation > 5) {
260583548fe2SQuinn Tran ql_log(ql_log_warn, vha, 0xd046,
2606ead03855SQuinn Tran "Exchange starvation. Resetting RISC\n");
2607ead03855SQuinn Tran
2608ead03855SQuinn Tran vha->hw->exch_starvation = 0;
2609ead03855SQuinn Tran
2610ead03855SQuinn Tran if (IS_P3P_TYPE(vha->hw))
2611ead03855SQuinn Tran set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
2612ead03855SQuinn Tran else
2613ead03855SQuinn Tran set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2614ead03855SQuinn Tran qla2xxx_wake_dpc(vha);
2615ead03855SQuinn Tran }
2616df561f66SGustavo A. R. Silva fallthrough;
2617ac280b67SAndrew Vasquez default:
2618ac280b67SAndrew Vasquez data[0] = MBS_COMMAND_ERROR;
2619ac280b67SAndrew Vasquez break;
2620ac280b67SAndrew Vasquez }
2621ac280b67SAndrew Vasquez
2622a5741427SArun Easi if (logit)
2623a5741427SArun Easi ql_log(ql_log_warn, sp->vha, 0x5037, "Async-%s failed: "
2624a5741427SArun Easi "handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n",
2625a5741427SArun Easi type, sp->handle, fcport->d_id.b24, fcport->port_name,
2626a5741427SArun Easi le16_to_cpu(logio->comp_status),
2627a5741427SArun Easi le32_to_cpu(logio->io_parameter[0]),
2628a5741427SArun Easi le32_to_cpu(logio->io_parameter[1]));
2629a5741427SArun Easi else
2630a5741427SArun Easi ql_dbg(ql_dbg_disc, sp->vha, 0x5037, "Async-%s failed: "
2631a5741427SArun Easi "handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n",
2632cbe729a6SJoe Carnuccio type, sp->handle, fcport->d_id.b24, fcport->port_name,
2633ac280b67SAndrew Vasquez le16_to_cpu(logio->comp_status),
2634ac280b67SAndrew Vasquez le32_to_cpu(logio->io_parameter[0]),
26357c3df132SSaurav Kashyap le32_to_cpu(logio->io_parameter[1]));
2636ac280b67SAndrew Vasquez
263799b0bec7SAndrew Vasquez logio_done:
263825ff6af1SJoe Carnuccio sp->done(sp, 0);
2639ac280b67SAndrew Vasquez }
2640ac280b67SAndrew Vasquez
26413822263eSMadhuranath Iyengar static void
qla24xx_tm_iocb_entry(scsi_qla_host_t * vha,struct req_que * req,void * tsk)2642faef62d1SArmen Baloyan qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk)
26433822263eSMadhuranath Iyengar {
26443822263eSMadhuranath Iyengar const char func[] = "TMF-IOCB";
26453822263eSMadhuranath Iyengar const char *type;
26463822263eSMadhuranath Iyengar fc_port_t *fcport;
26473822263eSMadhuranath Iyengar srb_t *sp;
26483822263eSMadhuranath Iyengar struct srb_iocb *iocb;
26493822263eSMadhuranath Iyengar struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk;
2650e4fc78f4SQuinn Tran u16 comp_status;
26513822263eSMadhuranath Iyengar
26523822263eSMadhuranath Iyengar sp = qla2x00_get_sp_from_handle(vha, func, req, tsk);
26533822263eSMadhuranath Iyengar if (!sp)
26543822263eSMadhuranath Iyengar return;
26553822263eSMadhuranath Iyengar
2656e4fc78f4SQuinn Tran comp_status = le16_to_cpu(sts->comp_status);
26579ba56b95SGiridhar Malavali iocb = &sp->u.iocb_cmd;
26589ba56b95SGiridhar Malavali type = sp->name;
26593822263eSMadhuranath Iyengar fcport = sp->fcport;
2660faef62d1SArmen Baloyan iocb->u.tmf.data = QLA_SUCCESS;
26613822263eSMadhuranath Iyengar
26623822263eSMadhuranath Iyengar if (sts->entry_status) {
26635e19ed90SArun Easi ql_log(ql_log_warn, fcport->vha, 0x5038,
2664cfb0919cSChad Dupuis "Async-%s error - hdl=%x entry-status(%x).\n",
2665cfb0919cSChad Dupuis type, sp->handle, sts->entry_status);
2666faef62d1SArmen Baloyan iocb->u.tmf.data = QLA_FUNCTION_FAILED;
2667ad950360SBart Van Assche } else if (sts->comp_status != cpu_to_le16(CS_COMPLETE)) {
26685e19ed90SArun Easi ql_log(ql_log_warn, fcport->vha, 0x5039,
2669cfb0919cSChad Dupuis "Async-%s error - hdl=%x completion status(%x).\n",
2670e4fc78f4SQuinn Tran type, sp->handle, comp_status);
2671faef62d1SArmen Baloyan iocb->u.tmf.data = QLA_FUNCTION_FAILED;
2672faef62d1SArmen Baloyan } else if ((le16_to_cpu(sts->scsi_status) &
26733822263eSMadhuranath Iyengar SS_RESPONSE_INFO_LEN_VALID)) {
267458ca5999SQuinn Tran host_to_fcp_swap(sts->data, sizeof(sts->data));
2675faef62d1SArmen Baloyan if (le32_to_cpu(sts->rsp_data_len) < 4) {
26765e19ed90SArun Easi ql_log(ql_log_warn, fcport->vha, 0x503b,
2677cfb0919cSChad Dupuis "Async-%s error - hdl=%x not enough response(%d).\n",
2678cfb0919cSChad Dupuis type, sp->handle, sts->rsp_data_len);
26793822263eSMadhuranath Iyengar } else if (sts->data[3]) {
26805e19ed90SArun Easi ql_log(ql_log_warn, fcport->vha, 0x503c,
2681cfb0919cSChad Dupuis "Async-%s error - hdl=%x response(%x).\n",
2682cfb0919cSChad Dupuis type, sp->handle, sts->data[3]);
2683faef62d1SArmen Baloyan iocb->u.tmf.data = QLA_FUNCTION_FAILED;
2684faef62d1SArmen Baloyan }
26853822263eSMadhuranath Iyengar }
26863822263eSMadhuranath Iyengar
2687e4fc78f4SQuinn Tran switch (comp_status) {
2688e4fc78f4SQuinn Tran case CS_PORT_LOGGED_OUT:
2689e4fc78f4SQuinn Tran case CS_PORT_CONFIG_CHG:
2690e4fc78f4SQuinn Tran case CS_PORT_BUSY:
2691e4fc78f4SQuinn Tran case CS_INCOMPLETE:
2692e4fc78f4SQuinn Tran case CS_PORT_UNAVAILABLE:
2693e4fc78f4SQuinn Tran case CS_RESET:
2694e4fc78f4SQuinn Tran if (atomic_read(&fcport->state) == FCS_ONLINE) {
2695e4fc78f4SQuinn Tran ql_dbg(ql_dbg_disc, fcport->vha, 0x3021,
2696e4fc78f4SQuinn Tran "-Port to be marked lost on fcport=%02x%02x%02x, current port state= %s comp_status %x.\n",
2697e4fc78f4SQuinn Tran fcport->d_id.b.domain, fcport->d_id.b.area,
2698e4fc78f4SQuinn Tran fcport->d_id.b.al_pa,
2699e4fc78f4SQuinn Tran port_state_str[FCS_ONLINE],
2700e4fc78f4SQuinn Tran comp_status);
2701e4fc78f4SQuinn Tran
2702e4fc78f4SQuinn Tran qlt_schedule_sess_for_deletion(fcport);
2703e4fc78f4SQuinn Tran }
2704e4fc78f4SQuinn Tran break;
2705e4fc78f4SQuinn Tran
2706e4fc78f4SQuinn Tran default:
2707e4fc78f4SQuinn Tran break;
2708e4fc78f4SQuinn Tran }
2709e4fc78f4SQuinn Tran
2710faef62d1SArmen Baloyan if (iocb->u.tmf.data != QLA_SUCCESS)
2711f8f97b0cSJoe Carnuccio ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, sp->vha, 0x5055,
2712f8f97b0cSJoe Carnuccio sts, sizeof(*sts));
27133822263eSMadhuranath Iyengar
271425ff6af1SJoe Carnuccio sp->done(sp, 0);
27153822263eSMadhuranath Iyengar }
27163822263eSMadhuranath Iyengar
qla24xx_nvme_iocb_entry(scsi_qla_host_t * vha,struct req_que * req,void * tsk,srb_t * sp)271760dd6e8eSDarren Trapp static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
271860dd6e8eSDarren Trapp void *tsk, srb_t *sp)
27197401bc18SDuane Grigsby {
27207401bc18SDuane Grigsby fc_port_t *fcport;
27217401bc18SDuane Grigsby struct srb_iocb *iocb;
27227401bc18SDuane Grigsby struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk;
27237401bc18SDuane Grigsby uint16_t state_flags;
27247401bc18SDuane Grigsby struct nvmefc_fcp_req *fd;
27254072e1dcSDarren Trapp uint16_t ret = QLA_SUCCESS;
27267ffa5b93SBart Van Assche __le16 comp_status = sts->comp_status;
27273d582b34SArun Easi int logit = 0;
27287401bc18SDuane Grigsby
27297401bc18SDuane Grigsby iocb = &sp->u.iocb_cmd;
27307401bc18SDuane Grigsby fcport = sp->fcport;
27314072e1dcSDarren Trapp iocb->u.nvme.comp_status = comp_status;
27327401bc18SDuane Grigsby state_flags = le16_to_cpu(sts->state_flags);
27337401bc18SDuane Grigsby fd = iocb->u.nvme.desc;
27347401bc18SDuane Grigsby
273560dd6e8eSDarren Trapp if (unlikely(iocb->u.nvme.aen_op))
2736deeae7a6SDuane Grigsby atomic_dec(&sp->vha->hw->nvme_active_aen_cnt);
2737d94d8158SQuinn Tran else
2738d94d8158SQuinn Tran sp->qpair->cmd_completion_cnt++;
27397401bc18SDuane Grigsby
27403d582b34SArun Easi if (unlikely(comp_status != CS_COMPLETE))
27413d582b34SArun Easi logit = 1;
27423d582b34SArun Easi
27433d582b34SArun Easi fd->transferred_length = fd->payload_length -
27443d582b34SArun Easi le32_to_cpu(sts->residual_len);
27453d582b34SArun Easi
27467401bc18SDuane Grigsby /*
27477401bc18SDuane Grigsby * State flags: Bit 6 and 0.
27487401bc18SDuane Grigsby * If 0 is set, we don't care about 6.
27497401bc18SDuane Grigsby * both cases resp was dma'd to host buffer
27507401bc18SDuane Grigsby * if both are 0, that is good path case.
27517401bc18SDuane Grigsby * if six is set and 0 is clear, we need to
27527401bc18SDuane Grigsby * copy resp data from status iocb to resp buffer.
27537401bc18SDuane Grigsby */
27547401bc18SDuane Grigsby if (!(state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP))) {
27557401bc18SDuane Grigsby iocb->u.nvme.rsp_pyld_len = 0;
27563d582b34SArun Easi } else if ((state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP)) ==
27573d582b34SArun Easi (SF_FCP_RSP_DMA | SF_NVME_ERSP)) {
27583d582b34SArun Easi /* Response already DMA'd to fd->rspaddr. */
27597ffa5b93SBart Van Assche iocb->u.nvme.rsp_pyld_len = sts->nvme_rsp_pyld_len;
27603d582b34SArun Easi } else if ((state_flags & SF_FCP_RSP_DMA)) {
27613d582b34SArun Easi /*
27623d582b34SArun Easi * Non-zero value in first 12 bytes of NVMe_RSP IU, treat this
27633d582b34SArun Easi * as an error.
27643d582b34SArun Easi */
27653d582b34SArun Easi iocb->u.nvme.rsp_pyld_len = 0;
27663d582b34SArun Easi fd->transferred_length = 0;
27673d582b34SArun Easi ql_dbg(ql_dbg_io, fcport->vha, 0x307a,
27683d582b34SArun Easi "Unexpected values in NVMe_RSP IU.\n");
27693d582b34SArun Easi logit = 1;
27707401bc18SDuane Grigsby } else if (state_flags & SF_NVME_ERSP) {
27717401bc18SDuane Grigsby uint32_t *inbuf, *outbuf;
27727401bc18SDuane Grigsby uint16_t iter;
27737401bc18SDuane Grigsby
27747401bc18SDuane Grigsby inbuf = (uint32_t *)&sts->nvme_ersp_data;
27757401bc18SDuane Grigsby outbuf = (uint32_t *)fd->rspaddr;
27767ffa5b93SBart Van Assche iocb->u.nvme.rsp_pyld_len = sts->nvme_rsp_pyld_len;
27777ffa5b93SBart Van Assche if (unlikely(le16_to_cpu(iocb->u.nvme.rsp_pyld_len) >
277800fe717eSArun Easi sizeof(struct nvme_fc_ersp_iu))) {
277900fe717eSArun Easi if (ql_mask_match(ql_dbg_io)) {
278000fe717eSArun Easi WARN_ONCE(1, "Unexpected response payload length %u.\n",
278100fe717eSArun Easi iocb->u.nvme.rsp_pyld_len);
278200fe717eSArun Easi ql_log(ql_log_warn, fcport->vha, 0x5100,
278300fe717eSArun Easi "Unexpected response payload length %u.\n",
278400fe717eSArun Easi iocb->u.nvme.rsp_pyld_len);
278500fe717eSArun Easi }
278600fe717eSArun Easi iocb->u.nvme.rsp_pyld_len =
27877ffa5b93SBart Van Assche cpu_to_le16(sizeof(struct nvme_fc_ersp_iu));
278800fe717eSArun Easi }
27897ffa5b93SBart Van Assche iter = le16_to_cpu(iocb->u.nvme.rsp_pyld_len) >> 2;
27907401bc18SDuane Grigsby for (; iter; iter--)
27917401bc18SDuane Grigsby *outbuf++ = swab32(*inbuf++);
27927401bc18SDuane Grigsby }
27937401bc18SDuane Grigsby
27943d582b34SArun Easi if (state_flags & SF_NVME_ERSP) {
27953d582b34SArun Easi struct nvme_fc_ersp_iu *rsp_iu = fd->rspaddr;
27963d582b34SArun Easi u32 tgt_xfer_len;
27977401bc18SDuane Grigsby
27983d582b34SArun Easi tgt_xfer_len = be32_to_cpu(rsp_iu->xfrd_len);
27993d582b34SArun Easi if (fd->transferred_length != tgt_xfer_len) {
2800daaecb41SSaurav Kashyap ql_log(ql_log_warn, fcport->vha, 0x3079,
28013d582b34SArun Easi "Dropped frame(s) detected (sent/rcvd=%u/%u).\n",
28023d582b34SArun Easi tgt_xfer_len, fd->transferred_length);
28033d582b34SArun Easi logit = 1;
28047ffa5b93SBart Van Assche } else if (le16_to_cpu(comp_status) == CS_DATA_UNDERRUN) {
28053d582b34SArun Easi /*
28063d582b34SArun Easi * Do not log if this is just an underflow and there
28073d582b34SArun Easi * is no data loss.
28083d582b34SArun Easi */
28093d582b34SArun Easi logit = 0;
28103d582b34SArun Easi }
28113d582b34SArun Easi }
28123d582b34SArun Easi
28133d582b34SArun Easi if (unlikely(logit))
2814bff4873cSArun Easi ql_dbg(ql_dbg_io, fcport->vha, 0x5060,
28154072e1dcSDarren Trapp "NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n",
28164072e1dcSDarren Trapp sp->name, sp->handle, comp_status,
28174072e1dcSDarren Trapp fd->transferred_length, le32_to_cpu(sts->residual_len),
28184072e1dcSDarren Trapp sts->ox_id);
28194072e1dcSDarren Trapp
28204072e1dcSDarren Trapp /*
28214072e1dcSDarren Trapp * If transport error then Failure (HBA rejects request)
28224072e1dcSDarren Trapp * otherwise transport will handle.
28234072e1dcSDarren Trapp */
28247ffa5b93SBart Van Assche switch (le16_to_cpu(comp_status)) {
282549b3d5f6Shimanshu.madhani@cavium.com case CS_COMPLETE:
282649b3d5f6Shimanshu.madhani@cavium.com break;
28274072e1dcSDarren Trapp
282849b3d5f6Shimanshu.madhani@cavium.com case CS_RESET:
282949b3d5f6Shimanshu.madhani@cavium.com case CS_PORT_UNAVAILABLE:
283049b3d5f6Shimanshu.madhani@cavium.com case CS_PORT_LOGGED_OUT:
28314072e1dcSDarren Trapp fcport->nvme_flag |= NVME_FLAG_RESETTING;
28327a8ff7d9SQuinn Tran if (atomic_read(&fcport->state) == FCS_ONLINE) {
28337a8ff7d9SQuinn Tran ql_dbg(ql_dbg_disc, fcport->vha, 0x3021,
28347a8ff7d9SQuinn Tran "Port to be marked lost on fcport=%06x, current "
28357a8ff7d9SQuinn Tran "port state= %s comp_status %x.\n",
28367a8ff7d9SQuinn Tran fcport->d_id.b24, port_state_str[FCS_ONLINE],
28377a8ff7d9SQuinn Tran comp_status);
28387a8ff7d9SQuinn Tran
28397a8ff7d9SQuinn Tran qlt_schedule_sess_for_deletion(fcport);
28407a8ff7d9SQuinn Tran }
2841df561f66SGustavo A. R. Silva fallthrough;
28424072e1dcSDarren Trapp case CS_ABORTED:
284349b3d5f6Shimanshu.madhani@cavium.com case CS_PORT_BUSY:
28449dd9686bSDarren Trapp fd->transferred_length = 0;
28459dd9686bSDarren Trapp iocb->u.nvme.rsp_pyld_len = 0;
284649b3d5f6Shimanshu.madhani@cavium.com ret = QLA_ABORTED;
284749b3d5f6Shimanshu.madhani@cavium.com break;
28484072e1dcSDarren Trapp case CS_DATA_UNDERRUN:
28494072e1dcSDarren Trapp break;
285049b3d5f6Shimanshu.madhani@cavium.com default:
28517401bc18SDuane Grigsby ret = QLA_FUNCTION_FAILED;
285249b3d5f6Shimanshu.madhani@cavium.com break;
285349b3d5f6Shimanshu.madhani@cavium.com }
28547401bc18SDuane Grigsby sp->done(sp, ret);
28557401bc18SDuane Grigsby }
28567401bc18SDuane Grigsby
qla_ctrlvp_completed(scsi_qla_host_t * vha,struct req_que * req,struct vp_ctrl_entry_24xx * vce)28572853192eSQuinn Tran static void qla_ctrlvp_completed(scsi_qla_host_t *vha, struct req_que *req,
28582853192eSQuinn Tran struct vp_ctrl_entry_24xx *vce)
28592853192eSQuinn Tran {
28602853192eSQuinn Tran const char func[] = "CTRLVP-IOCB";
28612853192eSQuinn Tran srb_t *sp;
28622853192eSQuinn Tran int rval = QLA_SUCCESS;
28632853192eSQuinn Tran
28642853192eSQuinn Tran sp = qla2x00_get_sp_from_handle(vha, func, req, vce);
28652853192eSQuinn Tran if (!sp)
28662853192eSQuinn Tran return;
28672853192eSQuinn Tran
28682853192eSQuinn Tran if (vce->entry_status != 0) {
28692853192eSQuinn Tran ql_dbg(ql_dbg_vport, vha, 0x10c4,
28702853192eSQuinn Tran "%s: Failed to complete IOCB -- error status (%x)\n",
28712853192eSQuinn Tran sp->name, vce->entry_status);
28722853192eSQuinn Tran rval = QLA_FUNCTION_FAILED;
28732853192eSQuinn Tran } else if (vce->comp_status != cpu_to_le16(CS_COMPLETE)) {
28742853192eSQuinn Tran ql_dbg(ql_dbg_vport, vha, 0x10c5,
28752853192eSQuinn Tran "%s: Failed to complete IOCB -- completion status (%x) vpidx %x\n",
28762853192eSQuinn Tran sp->name, le16_to_cpu(vce->comp_status),
28772853192eSQuinn Tran le16_to_cpu(vce->vp_idx_failed));
28782853192eSQuinn Tran rval = QLA_FUNCTION_FAILED;
28792853192eSQuinn Tran } else {
28802853192eSQuinn Tran ql_dbg(ql_dbg_vport, vha, 0x10c6,
28812853192eSQuinn Tran "Done %s.\n", __func__);
28822853192eSQuinn Tran }
28832853192eSQuinn Tran
28842853192eSQuinn Tran sp->rc = rval;
28852853192eSQuinn Tran sp->done(sp, rval);
28862853192eSQuinn Tran }
28872853192eSQuinn Tran
28887b006b97SBart Van Assche /* Process a single response queue entry. */
qla2x00_process_response_entry(struct scsi_qla_host * vha,struct rsp_que * rsp,sts_entry_t * pkt)28897b006b97SBart Van Assche static void qla2x00_process_response_entry(struct scsi_qla_host *vha,
28907b006b97SBart Van Assche struct rsp_que *rsp,
28917b006b97SBart Van Assche sts_entry_t *pkt)
28927b006b97SBart Van Assche {
28937b006b97SBart Van Assche sts21_entry_t *sts21_entry;
28947b006b97SBart Van Assche sts22_entry_t *sts22_entry;
28957b006b97SBart Van Assche uint16_t handle_cnt;
28967b006b97SBart Van Assche uint16_t cnt;
28977b006b97SBart Van Assche
28987b006b97SBart Van Assche switch (pkt->entry_type) {
28997b006b97SBart Van Assche case STATUS_TYPE:
29007b006b97SBart Van Assche qla2x00_status_entry(vha, rsp, pkt);
29017b006b97SBart Van Assche break;
29027b006b97SBart Van Assche case STATUS_TYPE_21:
29037b006b97SBart Van Assche sts21_entry = (sts21_entry_t *)pkt;
29047b006b97SBart Van Assche handle_cnt = sts21_entry->handle_count;
29057b006b97SBart Van Assche for (cnt = 0; cnt < handle_cnt; cnt++)
29067b006b97SBart Van Assche qla2x00_process_completed_request(vha, rsp->req,
29077b006b97SBart Van Assche sts21_entry->handle[cnt]);
29087b006b97SBart Van Assche break;
29097b006b97SBart Van Assche case STATUS_TYPE_22:
29107b006b97SBart Van Assche sts22_entry = (sts22_entry_t *)pkt;
29117b006b97SBart Van Assche handle_cnt = sts22_entry->handle_count;
29127b006b97SBart Van Assche for (cnt = 0; cnt < handle_cnt; cnt++)
29137b006b97SBart Van Assche qla2x00_process_completed_request(vha, rsp->req,
29147b006b97SBart Van Assche sts22_entry->handle[cnt]);
29157b006b97SBart Van Assche break;
29167b006b97SBart Van Assche case STATUS_CONT_TYPE:
29177b006b97SBart Van Assche qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt);
29187b006b97SBart Van Assche break;
29197b006b97SBart Van Assche case MBX_IOCB_TYPE:
29207b006b97SBart Van Assche qla2x00_mbx_iocb_entry(vha, rsp->req, (struct mbx_entry *)pkt);
29217b006b97SBart Van Assche break;
29227b006b97SBart Van Assche case CT_IOCB_TYPE:
29237b006b97SBart Van Assche qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
29247b006b97SBart Van Assche break;
29257b006b97SBart Van Assche default:
29267b006b97SBart Van Assche /* Type Not Supported. */
29277b006b97SBart Van Assche ql_log(ql_log_warn, vha, 0x504a,
29287b006b97SBart Van Assche "Received unknown response pkt type %x entry status=%x.\n",
29297b006b97SBart Van Assche pkt->entry_type, pkt->entry_status);
29307b006b97SBart Van Assche break;
29317b006b97SBart Van Assche }
29327b006b97SBart Van Assche }
29337b006b97SBart Van Assche
29341da177e4SLinus Torvalds /**
29351da177e4SLinus Torvalds * qla2x00_process_response_queue() - Process response queue entries.
29362db6228dSBart Van Assche * @rsp: response queue
29371da177e4SLinus Torvalds */
29381da177e4SLinus Torvalds void
qla2x00_process_response_queue(struct rsp_que * rsp)293973208dfdSAnirban Chakraborty qla2x00_process_response_queue(struct rsp_que *rsp)
29401da177e4SLinus Torvalds {
294173208dfdSAnirban Chakraborty struct scsi_qla_host *vha;
294273208dfdSAnirban Chakraborty struct qla_hw_data *ha = rsp->hw;
29433d71644cSAndrew Vasquez struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
29441da177e4SLinus Torvalds sts_entry_t *pkt;
294573208dfdSAnirban Chakraborty
29462afa19a9SAnirban Chakraborty vha = pci_get_drvdata(ha->pdev);
29471da177e4SLinus Torvalds
2948e315cd28SAnirban Chakraborty if (!vha->flags.online)
29491da177e4SLinus Torvalds return;
29501da177e4SLinus Torvalds
2951e315cd28SAnirban Chakraborty while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
2952e315cd28SAnirban Chakraborty pkt = (sts_entry_t *)rsp->ring_ptr;
29531da177e4SLinus Torvalds
2954e315cd28SAnirban Chakraborty rsp->ring_index++;
2955e315cd28SAnirban Chakraborty if (rsp->ring_index == rsp->length) {
2956e315cd28SAnirban Chakraborty rsp->ring_index = 0;
2957e315cd28SAnirban Chakraborty rsp->ring_ptr = rsp->ring;
29581da177e4SLinus Torvalds } else {
2959e315cd28SAnirban Chakraborty rsp->ring_ptr++;
29601da177e4SLinus Torvalds }
29611da177e4SLinus Torvalds
29621da177e4SLinus Torvalds if (pkt->entry_status != 0) {
296373208dfdSAnirban Chakraborty qla2x00_error_entry(vha, rsp, pkt);
29641da177e4SLinus Torvalds ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
29651da177e4SLinus Torvalds wmb();
29661da177e4SLinus Torvalds continue;
29671da177e4SLinus Torvalds }
29681da177e4SLinus Torvalds
29697b006b97SBart Van Assche qla2x00_process_response_entry(vha, rsp, pkt);
29701da177e4SLinus Torvalds ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
29711da177e4SLinus Torvalds wmb();
29721da177e4SLinus Torvalds }
29731da177e4SLinus Torvalds
29741da177e4SLinus Torvalds /* Adjust ring index */
297504474d3aSBart Van Assche wrt_reg_word(ISP_RSP_Q_OUT(ha, reg), rsp->ring_index);
29761da177e4SLinus Torvalds }
29771da177e4SLinus Torvalds
29784733fcb1SAndrew Vasquez static inline void
qla2x00_handle_sense(srb_t * sp,uint8_t * sense_data,uint32_t par_sense_len,uint32_t sense_len,struct rsp_que * rsp,int res)29795544213bSAndrew Vasquez qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
29809ba56b95SGiridhar Malavali uint32_t sense_len, struct rsp_que *rsp, int res)
29814733fcb1SAndrew Vasquez {
298225ff6af1SJoe Carnuccio struct scsi_qla_host *vha = sp->vha;
29839ba56b95SGiridhar Malavali struct scsi_cmnd *cp = GET_CMD_SP(sp);
29849ba56b95SGiridhar Malavali uint32_t track_sense_len;
29854733fcb1SAndrew Vasquez
29864733fcb1SAndrew Vasquez if (sense_len >= SCSI_SENSE_BUFFERSIZE)
29874733fcb1SAndrew Vasquez sense_len = SCSI_SENSE_BUFFERSIZE;
29884733fcb1SAndrew Vasquez
29899ba56b95SGiridhar Malavali SET_CMD_SENSE_LEN(sp, sense_len);
29909ba56b95SGiridhar Malavali SET_CMD_SENSE_PTR(sp, cp->sense_buffer);
29919ba56b95SGiridhar Malavali track_sense_len = sense_len;
29929ba56b95SGiridhar Malavali
29939ba56b95SGiridhar Malavali if (sense_len > par_sense_len)
29945544213bSAndrew Vasquez sense_len = par_sense_len;
29954733fcb1SAndrew Vasquez
29964733fcb1SAndrew Vasquez memcpy(cp->sense_buffer, sense_data, sense_len);
29974733fcb1SAndrew Vasquez
29989ba56b95SGiridhar Malavali SET_CMD_SENSE_PTR(sp, cp->sense_buffer + sense_len);
29999ba56b95SGiridhar Malavali track_sense_len -= sense_len;
30009ba56b95SGiridhar Malavali SET_CMD_SENSE_LEN(sp, track_sense_len);
30019ba56b95SGiridhar Malavali
30029ba56b95SGiridhar Malavali if (track_sense_len != 0) {
30032afa19a9SAnirban Chakraborty rsp->status_srb = sp;
30049ba56b95SGiridhar Malavali cp->result = res;
30059ba56b95SGiridhar Malavali }
30064733fcb1SAndrew Vasquez
3007cfb0919cSChad Dupuis if (sense_len) {
3008cfb0919cSChad Dupuis ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x301c,
30099cb78c16SHannes Reinecke "Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n",
301025ff6af1SJoe Carnuccio sp->vha->host_no, cp->device->id, cp->device->lun,
3011cfb0919cSChad Dupuis cp);
30127c3df132SSaurav Kashyap ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302b,
30137c3df132SSaurav Kashyap cp->sense_buffer, sense_len);
30144733fcb1SAndrew Vasquez }
3015cfb0919cSChad Dupuis }
30164733fcb1SAndrew Vasquez
3017bad75002SArun Easi /*
3018bad75002SArun Easi * Checks the guard or meta-data for the type of error
3019bad75002SArun Easi * detected by the HBA. In case of errors, we set the
3020bad75002SArun Easi * ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST
3021bad75002SArun Easi * to indicate to the kernel that the HBA detected error.
3022bad75002SArun Easi */
30238cb2049cSArun Easi static inline int
qla2x00_handle_dif_error(srb_t * sp,struct sts_entry_24xx * sts24)3024bad75002SArun Easi qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
3025bad75002SArun Easi {
302625ff6af1SJoe Carnuccio struct scsi_qla_host *vha = sp->vha;
30279ba56b95SGiridhar Malavali struct scsi_cmnd *cmd = GET_CMD_SP(sp);
30288cb2049cSArun Easi uint8_t *ap = &sts24->data[12];
30298cb2049cSArun Easi uint8_t *ep = &sts24->data[20];
3030bad75002SArun Easi uint32_t e_ref_tag, a_ref_tag;
3031bad75002SArun Easi uint16_t e_app_tag, a_app_tag;
3032bad75002SArun Easi uint16_t e_guard, a_guard;
3033bad75002SArun Easi
30348cb2049cSArun Easi /*
30358cb2049cSArun Easi * swab32 of the "data" field in the beginning of qla2x00_status_entry()
30368cb2049cSArun Easi * would make guard field appear at offset 2
30378cb2049cSArun Easi */
3038a9c4ae10SBart Van Assche a_guard = get_unaligned_le16(ap + 2);
3039a9c4ae10SBart Van Assche a_app_tag = get_unaligned_le16(ap + 0);
3040a9c4ae10SBart Van Assche a_ref_tag = get_unaligned_le32(ap + 4);
3041a9c4ae10SBart Van Assche e_guard = get_unaligned_le16(ep + 2);
3042a9c4ae10SBart Van Assche e_app_tag = get_unaligned_le16(ep + 0);
3043a9c4ae10SBart Van Assche e_ref_tag = get_unaligned_le32(ep + 4);
3044bad75002SArun Easi
30457c3df132SSaurav Kashyap ql_dbg(ql_dbg_io, vha, 0x3023,
30467c3df132SSaurav Kashyap "iocb(s) %p Returned STATUS.\n", sts24);
3047bad75002SArun Easi
30487c3df132SSaurav Kashyap ql_dbg(ql_dbg_io, vha, 0x3024,
30497c3df132SSaurav Kashyap "DIF ERROR in cmd 0x%x lba 0x%llx act ref"
3050bad75002SArun Easi " tag=0x%x, exp ref_tag=0x%x, act app tag=0x%x, exp app"
30517c3df132SSaurav Kashyap " tag=0x%x, act guard=0x%x, exp guard=0x%x.\n",
3052bad75002SArun Easi cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag,
30537c3df132SSaurav Kashyap a_app_tag, e_app_tag, a_guard, e_guard);
3054bad75002SArun Easi
30558cb2049cSArun Easi /*
30568cb2049cSArun Easi * Ignore sector if:
30578cb2049cSArun Easi * For type 3: ref & app tag is all 'f's
30588cb2049cSArun Easi * For type 0,1,2: app tag is all 'f's
30598cb2049cSArun Easi */
30607ffa5b93SBart Van Assche if (a_app_tag == be16_to_cpu(T10_PI_APP_ESCAPE) &&
30617ffa5b93SBart Van Assche (scsi_get_prot_type(cmd) != SCSI_PROT_DIF_TYPE3 ||
30627ffa5b93SBart Van Assche a_ref_tag == be32_to_cpu(T10_PI_REF_ESCAPE))) {
30638cb2049cSArun Easi uint32_t blocks_done, resid;
30648cb2049cSArun Easi sector_t lba_s = scsi_get_lba(cmd);
30658cb2049cSArun Easi
30668cb2049cSArun Easi /* 2TB boundary case covered automatically with this */
30678cb2049cSArun Easi blocks_done = e_ref_tag - (uint32_t)lba_s + 1;
30688cb2049cSArun Easi
30698cb2049cSArun Easi resid = scsi_bufflen(cmd) - (blocks_done *
30708cb2049cSArun Easi cmd->device->sector_size);
30718cb2049cSArun Easi
30728cb2049cSArun Easi scsi_set_resid(cmd, resid);
30738cb2049cSArun Easi cmd->result = DID_OK << 16;
30748cb2049cSArun Easi
30758cb2049cSArun Easi /* Update protection tag */
30768cb2049cSArun Easi if (scsi_prot_sg_count(cmd)) {
30778cb2049cSArun Easi uint32_t i, j = 0, k = 0, num_ent;
30788cb2049cSArun Easi struct scatterlist *sg;
307927c0e83bSChristoph Hellwig struct t10_pi_tuple *spt;
30808cb2049cSArun Easi
30818cb2049cSArun Easi /* Patch the corresponding protection tags */
30828cb2049cSArun Easi scsi_for_each_prot_sg(cmd, sg,
30838cb2049cSArun Easi scsi_prot_sg_count(cmd), i) {
30848cb2049cSArun Easi num_ent = sg_dma_len(sg) / 8;
30858cb2049cSArun Easi if (k + num_ent < blocks_done) {
30868cb2049cSArun Easi k += num_ent;
30878cb2049cSArun Easi continue;
30888cb2049cSArun Easi }
30898cb2049cSArun Easi j = blocks_done - k - 1;
30908cb2049cSArun Easi k = blocks_done;
30918cb2049cSArun Easi break;
30928cb2049cSArun Easi }
30938cb2049cSArun Easi
30948cb2049cSArun Easi if (k != blocks_done) {
3095cfb0919cSChad Dupuis ql_log(ql_log_warn, vha, 0x302f,
30968ec9c7fbSRandy Dunlap "unexpected tag values tag:lba=%x:%llx)\n",
30978ec9c7fbSRandy Dunlap e_ref_tag, (unsigned long long)lba_s);
30988cb2049cSArun Easi return 1;
30998cb2049cSArun Easi }
31008cb2049cSArun Easi
31018cb2049cSArun Easi spt = page_address(sg_page(sg)) + sg->offset;
31028cb2049cSArun Easi spt += j;
31038cb2049cSArun Easi
3104128b6f9fSDmitry Monakhov spt->app_tag = T10_PI_APP_ESCAPE;
31058cb2049cSArun Easi if (scsi_get_prot_type(cmd) == SCSI_PROT_DIF_TYPE3)
3106128b6f9fSDmitry Monakhov spt->ref_tag = T10_PI_REF_ESCAPE;
31078cb2049cSArun Easi }
31088cb2049cSArun Easi
31098cb2049cSArun Easi return 0;
31108cb2049cSArun Easi }
31118cb2049cSArun Easi
3112bad75002SArun Easi /* check guard */
3113bad75002SArun Easi if (e_guard != a_guard) {
3114f2b1e9c6SHannes Reinecke scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1);
3115bad75002SArun Easi set_host_byte(cmd, DID_ABORT);
31168cb2049cSArun Easi return 1;
3117bad75002SArun Easi }
3118bad75002SArun Easi
3119e02587d7SArun Easi /* check ref tag */
3120e02587d7SArun Easi if (e_ref_tag != a_ref_tag) {
3121f2b1e9c6SHannes Reinecke scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3);
3122e02587d7SArun Easi set_host_byte(cmd, DID_ABORT);
3123e02587d7SArun Easi return 1;
3124e02587d7SArun Easi }
3125e02587d7SArun Easi
3126bad75002SArun Easi /* check appl tag */
3127bad75002SArun Easi if (e_app_tag != a_app_tag) {
3128f2b1e9c6SHannes Reinecke scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2);
3129bad75002SArun Easi set_host_byte(cmd, DID_ABORT);
31308cb2049cSArun Easi return 1;
3131bad75002SArun Easi }
3132bad75002SArun Easi
31338cb2049cSArun Easi return 1;
3134bad75002SArun Easi }
3135bad75002SArun Easi
3136a9b6f722SSaurav Kashyap static void
qla25xx_process_bidir_status_iocb(scsi_qla_host_t * vha,void * pkt,struct req_que * req,uint32_t index)3137a9b6f722SSaurav Kashyap qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt,
3138a9b6f722SSaurav Kashyap struct req_que *req, uint32_t index)
3139a9b6f722SSaurav Kashyap {
3140a9b6f722SSaurav Kashyap struct qla_hw_data *ha = vha->hw;
3141a9b6f722SSaurav Kashyap srb_t *sp;
3142a9b6f722SSaurav Kashyap uint16_t comp_status;
3143a9b6f722SSaurav Kashyap uint16_t scsi_status;
3144a9b6f722SSaurav Kashyap uint16_t thread_id;
3145a9b6f722SSaurav Kashyap uint32_t rval = EXT_STATUS_OK;
314675cc8cfcSJohannes Thumshirn struct bsg_job *bsg_job = NULL;
314701e0e15cSJohannes Thumshirn struct fc_bsg_request *bsg_request;
314801e0e15cSJohannes Thumshirn struct fc_bsg_reply *bsg_reply;
31491a20719eSBart Van Assche sts_entry_t *sts = pkt;
31501a20719eSBart Van Assche struct sts_entry_24xx *sts24 = pkt;
3151a9b6f722SSaurav Kashyap
3152a9b6f722SSaurav Kashyap /* Validate handle. */
31538d93f550SChad Dupuis if (index >= req->num_outstanding_cmds) {
3154a9b6f722SSaurav Kashyap ql_log(ql_log_warn, vha, 0x70af,
3155a9b6f722SSaurav Kashyap "Invalid SCSI completion handle 0x%x.\n", index);
3156a9b6f722SSaurav Kashyap set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
3157a9b6f722SSaurav Kashyap return;
3158a9b6f722SSaurav Kashyap }
3159a9b6f722SSaurav Kashyap
3160a9b6f722SSaurav Kashyap sp = req->outstanding_cmds[index];
316101e0e15cSJohannes Thumshirn if (!sp) {
3162a9b6f722SSaurav Kashyap ql_log(ql_log_warn, vha, 0x70b0,
3163a9b6f722SSaurav Kashyap "Req:%d: Invalid ISP SCSI completion handle(0x%x)\n",
3164a9b6f722SSaurav Kashyap req->id, index);
3165a9b6f722SSaurav Kashyap
3166a9b6f722SSaurav Kashyap set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
3167a9b6f722SSaurav Kashyap return;
3168a9b6f722SSaurav Kashyap }
3169a9b6f722SSaurav Kashyap
317001e0e15cSJohannes Thumshirn /* Free outstanding command slot. */
317101e0e15cSJohannes Thumshirn req->outstanding_cmds[index] = NULL;
317201e0e15cSJohannes Thumshirn bsg_job = sp->u.bsg_job;
317301e0e15cSJohannes Thumshirn bsg_request = bsg_job->request;
317401e0e15cSJohannes Thumshirn bsg_reply = bsg_job->reply;
317501e0e15cSJohannes Thumshirn
3176a9b6f722SSaurav Kashyap if (IS_FWI2_CAPABLE(ha)) {
3177a9b6f722SSaurav Kashyap comp_status = le16_to_cpu(sts24->comp_status);
3178a9b6f722SSaurav Kashyap scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
3179a9b6f722SSaurav Kashyap } else {
3180a9b6f722SSaurav Kashyap comp_status = le16_to_cpu(sts->comp_status);
3181a9b6f722SSaurav Kashyap scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK;
3182a9b6f722SSaurav Kashyap }
3183a9b6f722SSaurav Kashyap
318401e0e15cSJohannes Thumshirn thread_id = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
3185a9b6f722SSaurav Kashyap switch (comp_status) {
3186a9b6f722SSaurav Kashyap case CS_COMPLETE:
3187a9b6f722SSaurav Kashyap if (scsi_status == 0) {
318801e0e15cSJohannes Thumshirn bsg_reply->reply_payload_rcv_len =
3189a9b6f722SSaurav Kashyap bsg_job->reply_payload.payload_len;
3190fabbb8dfSJoe Carnuccio vha->qla_stats.input_bytes +=
319101e0e15cSJohannes Thumshirn bsg_reply->reply_payload_rcv_len;
3192fabbb8dfSJoe Carnuccio vha->qla_stats.input_requests++;
3193a9b6f722SSaurav Kashyap rval = EXT_STATUS_OK;
3194a9b6f722SSaurav Kashyap }
3195a9b6f722SSaurav Kashyap goto done;
3196a9b6f722SSaurav Kashyap
3197a9b6f722SSaurav Kashyap case CS_DATA_OVERRUN:
3198a9b6f722SSaurav Kashyap ql_dbg(ql_dbg_user, vha, 0x70b1,
31995a68a1c2SMilan P Gandhi "Command completed with data overrun thread_id=%d\n",
3200a9b6f722SSaurav Kashyap thread_id);
3201a9b6f722SSaurav Kashyap rval = EXT_STATUS_DATA_OVERRUN;
3202a9b6f722SSaurav Kashyap break;
3203a9b6f722SSaurav Kashyap
3204a9b6f722SSaurav Kashyap case CS_DATA_UNDERRUN:
3205a9b6f722SSaurav Kashyap ql_dbg(ql_dbg_user, vha, 0x70b2,
32065a68a1c2SMilan P Gandhi "Command completed with data underrun thread_id=%d\n",
3207a9b6f722SSaurav Kashyap thread_id);
3208a9b6f722SSaurav Kashyap rval = EXT_STATUS_DATA_UNDERRUN;
3209a9b6f722SSaurav Kashyap break;
3210a9b6f722SSaurav Kashyap case CS_BIDIR_RD_OVERRUN:
3211a9b6f722SSaurav Kashyap ql_dbg(ql_dbg_user, vha, 0x70b3,
3212a9b6f722SSaurav Kashyap "Command completed with read data overrun thread_id=%d\n",
3213a9b6f722SSaurav Kashyap thread_id);
3214a9b6f722SSaurav Kashyap rval = EXT_STATUS_DATA_OVERRUN;
3215a9b6f722SSaurav Kashyap break;
3216a9b6f722SSaurav Kashyap
3217a9b6f722SSaurav Kashyap case CS_BIDIR_RD_WR_OVERRUN:
3218a9b6f722SSaurav Kashyap ql_dbg(ql_dbg_user, vha, 0x70b4,
3219a9b6f722SSaurav Kashyap "Command completed with read and write data overrun "
3220a9b6f722SSaurav Kashyap "thread_id=%d\n", thread_id);
3221a9b6f722SSaurav Kashyap rval = EXT_STATUS_DATA_OVERRUN;
3222a9b6f722SSaurav Kashyap break;
3223a9b6f722SSaurav Kashyap
3224a9b6f722SSaurav Kashyap case CS_BIDIR_RD_OVERRUN_WR_UNDERRUN:
3225a9b6f722SSaurav Kashyap ql_dbg(ql_dbg_user, vha, 0x70b5,
3226a9b6f722SSaurav Kashyap "Command completed with read data over and write data "
3227a9b6f722SSaurav Kashyap "underrun thread_id=%d\n", thread_id);
3228a9b6f722SSaurav Kashyap rval = EXT_STATUS_DATA_OVERRUN;
3229a9b6f722SSaurav Kashyap break;
3230a9b6f722SSaurav Kashyap
3231a9b6f722SSaurav Kashyap case CS_BIDIR_RD_UNDERRUN:
3232a9b6f722SSaurav Kashyap ql_dbg(ql_dbg_user, vha, 0x70b6,
32335a68a1c2SMilan P Gandhi "Command completed with read data underrun "
3234a9b6f722SSaurav Kashyap "thread_id=%d\n", thread_id);
3235a9b6f722SSaurav Kashyap rval = EXT_STATUS_DATA_UNDERRUN;
3236a9b6f722SSaurav Kashyap break;
3237a9b6f722SSaurav Kashyap
3238a9b6f722SSaurav Kashyap case CS_BIDIR_RD_UNDERRUN_WR_OVERRUN:
3239a9b6f722SSaurav Kashyap ql_dbg(ql_dbg_user, vha, 0x70b7,
3240a9b6f722SSaurav Kashyap "Command completed with read data under and write data "
3241a9b6f722SSaurav Kashyap "overrun thread_id=%d\n", thread_id);
3242a9b6f722SSaurav Kashyap rval = EXT_STATUS_DATA_UNDERRUN;
3243a9b6f722SSaurav Kashyap break;
3244a9b6f722SSaurav Kashyap
3245a9b6f722SSaurav Kashyap case CS_BIDIR_RD_WR_UNDERRUN:
3246a9b6f722SSaurav Kashyap ql_dbg(ql_dbg_user, vha, 0x70b8,
3247a9b6f722SSaurav Kashyap "Command completed with read and write data underrun "
3248a9b6f722SSaurav Kashyap "thread_id=%d\n", thread_id);
3249a9b6f722SSaurav Kashyap rval = EXT_STATUS_DATA_UNDERRUN;
3250a9b6f722SSaurav Kashyap break;
3251a9b6f722SSaurav Kashyap
3252a9b6f722SSaurav Kashyap case CS_BIDIR_DMA:
3253a9b6f722SSaurav Kashyap ql_dbg(ql_dbg_user, vha, 0x70b9,
3254a9b6f722SSaurav Kashyap "Command completed with data DMA error thread_id=%d\n",
3255a9b6f722SSaurav Kashyap thread_id);
3256a9b6f722SSaurav Kashyap rval = EXT_STATUS_DMA_ERR;
3257a9b6f722SSaurav Kashyap break;
3258a9b6f722SSaurav Kashyap
3259a9b6f722SSaurav Kashyap case CS_TIMEOUT:
3260a9b6f722SSaurav Kashyap ql_dbg(ql_dbg_user, vha, 0x70ba,
3261a9b6f722SSaurav Kashyap "Command completed with timeout thread_id=%d\n",
3262a9b6f722SSaurav Kashyap thread_id);
3263a9b6f722SSaurav Kashyap rval = EXT_STATUS_TIMEOUT;
3264a9b6f722SSaurav Kashyap break;
3265a9b6f722SSaurav Kashyap default:
3266a9b6f722SSaurav Kashyap ql_dbg(ql_dbg_user, vha, 0x70bb,
3267a9b6f722SSaurav Kashyap "Command completed with completion status=0x%x "
3268a9b6f722SSaurav Kashyap "thread_id=%d\n", comp_status, thread_id);
3269a9b6f722SSaurav Kashyap rval = EXT_STATUS_ERR;
3270a9b6f722SSaurav Kashyap break;
3271a9b6f722SSaurav Kashyap }
327201e0e15cSJohannes Thumshirn bsg_reply->reply_payload_rcv_len = 0;
3273a9b6f722SSaurav Kashyap
3274a9b6f722SSaurav Kashyap done:
3275a9b6f722SSaurav Kashyap /* Return the vendor specific reply to API */
327601e0e15cSJohannes Thumshirn bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
3277a9b6f722SSaurav Kashyap bsg_job->reply_len = sizeof(struct fc_bsg_reply);
3278a9b6f722SSaurav Kashyap /* Always return DID_OK, bsg will send the vendor specific response
3279a9b6f722SSaurav Kashyap * in this case only */
3280f7d5182cSJohannes Thumshirn sp->done(sp, DID_OK << 16);
3281a9b6f722SSaurav Kashyap
3282a9b6f722SSaurav Kashyap }
3283a9b6f722SSaurav Kashyap
32841da177e4SLinus Torvalds /**
32851da177e4SLinus Torvalds * qla2x00_status_entry() - Process a Status IOCB entry.
32862db6228dSBart Van Assche * @vha: SCSI driver HA context
32872db6228dSBart Van Assche * @rsp: response queue
32881da177e4SLinus Torvalds * @pkt: Entry pointer
32891da177e4SLinus Torvalds */
32901da177e4SLinus Torvalds static void
qla2x00_status_entry(scsi_qla_host_t * vha,struct rsp_que * rsp,void * pkt)329173208dfdSAnirban Chakraborty qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
32921da177e4SLinus Torvalds {
32931da177e4SLinus Torvalds srb_t *sp;
32941da177e4SLinus Torvalds fc_port_t *fcport;
32951da177e4SLinus Torvalds struct scsi_cmnd *cp;
32961a20719eSBart Van Assche sts_entry_t *sts = pkt;
32971a20719eSBart Van Assche struct sts_entry_24xx *sts24 = pkt;
32981da177e4SLinus Torvalds uint16_t comp_status;
32991da177e4SLinus Torvalds uint16_t scsi_status;
3300b7d2280cSAndrew Vasquez uint16_t ox_id;
33011da177e4SLinus Torvalds uint8_t lscsi_status;
33021da177e4SLinus Torvalds int32_t resid;
33035544213bSAndrew Vasquez uint32_t sense_len, par_sense_len, rsp_info_len, resid_len,
33045544213bSAndrew Vasquez fw_resid_len;
33059a853f71SAndrew Vasquez uint8_t *rsp_info, *sense_data;
3306e315cd28SAnirban Chakraborty struct qla_hw_data *ha = vha->hw;
33072afa19a9SAnirban Chakraborty uint32_t handle;
33082afa19a9SAnirban Chakraborty uint16_t que;
33092afa19a9SAnirban Chakraborty struct req_que *req;
3310b7d2280cSAndrew Vasquez int logit = 1;
33119ba56b95SGiridhar Malavali int res = 0;
3312a9b6f722SSaurav Kashyap uint16_t state_flags = 0;
33133aac0c0fSArun Easi uint16_t sts_qual = 0;
33149a853f71SAndrew Vasquez
3315e428924cSAndrew Vasquez if (IS_FWI2_CAPABLE(ha)) {
33169a853f71SAndrew Vasquez comp_status = le16_to_cpu(sts24->comp_status);
33179a853f71SAndrew Vasquez scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
3318a9b6f722SSaurav Kashyap state_flags = le16_to_cpu(sts24->state_flags);
33199a853f71SAndrew Vasquez } else {
33209a853f71SAndrew Vasquez comp_status = le16_to_cpu(sts->comp_status);
33219a853f71SAndrew Vasquez scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK;
33229a853f71SAndrew Vasquez }
33232afa19a9SAnirban Chakraborty handle = (uint32_t) LSW(sts->handle);
33242afa19a9SAnirban Chakraborty que = MSW(sts->handle);
33252afa19a9SAnirban Chakraborty req = ha->req_q_map[que];
3326a9083016SGiridhar Malavali
332736008cf1SChad Dupuis /* Check for invalid queue pointer */
332836008cf1SChad Dupuis if (req == NULL ||
332936008cf1SChad Dupuis que >= find_first_zero_bit(ha->req_qid_map, ha->max_req_queues)) {
333036008cf1SChad Dupuis ql_dbg(ql_dbg_io, vha, 0x3059,
333136008cf1SChad Dupuis "Invalid status handle (0x%x): Bad req pointer. req=%p, "
333236008cf1SChad Dupuis "que=%u.\n", sts->handle, req, que);
333336008cf1SChad Dupuis return;
333436008cf1SChad Dupuis }
333536008cf1SChad Dupuis
33361da177e4SLinus Torvalds /* Validate handle. */
3337c7bc4caeSChad Dupuis if (handle < req->num_outstanding_cmds) {
33382afa19a9SAnirban Chakraborty sp = req->outstanding_cmds[handle];
3339c7bc4caeSChad Dupuis if (!sp) {
3340c7bc4caeSChad Dupuis ql_dbg(ql_dbg_io, vha, 0x3075,
3341c7bc4caeSChad Dupuis "%s(%ld): Already returned command for status handle (0x%x).\n",
3342c7bc4caeSChad Dupuis __func__, vha->host_no, sts->handle);
3343c7bc4caeSChad Dupuis return;
3344c7bc4caeSChad Dupuis }
3345c7bc4caeSChad Dupuis } else {
3346cfb0919cSChad Dupuis ql_dbg(ql_dbg_io, vha, 0x3017,
3347c7bc4caeSChad Dupuis "Invalid status handle, out of range (0x%x).\n",
3348c7bc4caeSChad Dupuis sts->handle);
33491da177e4SLinus Torvalds
3350acd3ce88SChad Dupuis if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) {
33517ec0effdSAtul Deshmukh if (IS_P3P_TYPE(ha))
33528f7daeadSGiridhar Malavali set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
33538f7daeadSGiridhar Malavali else
3354e315cd28SAnirban Chakraborty set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
3355e315cd28SAnirban Chakraborty qla2xxx_wake_dpc(vha);
3356acd3ce88SChad Dupuis }
33571da177e4SLinus Torvalds return;
33581da177e4SLinus Torvalds }
335941e5afe5SQuinn Tran qla_put_fw_resources(sp->qpair, &sp->iores);
3360a9b6f722SSaurav Kashyap
3361c5419e26SQuinn Tran if (sp->cmd_type != TYPE_SRB) {
3362c5419e26SQuinn Tran req->outstanding_cmds[handle] = NULL;
3363c5419e26SQuinn Tran ql_dbg(ql_dbg_io, vha, 0x3015,
3364c5419e26SQuinn Tran "Unknown sp->cmd_type %x %p).\n",
3365c5419e26SQuinn Tran sp->cmd_type, sp);
3366c5419e26SQuinn Tran return;
3367c5419e26SQuinn Tran }
3368c5419e26SQuinn Tran
33697401bc18SDuane Grigsby /* NVME completion. */
33707401bc18SDuane Grigsby if (sp->type == SRB_NVME_CMD) {
337160dd6e8eSDarren Trapp req->outstanding_cmds[handle] = NULL;
337260dd6e8eSDarren Trapp qla24xx_nvme_iocb_entry(vha, req, pkt, sp);
33737401bc18SDuane Grigsby return;
33747401bc18SDuane Grigsby }
33757401bc18SDuane Grigsby
3376a9b6f722SSaurav Kashyap if (unlikely((state_flags & BIT_1) && (sp->type == SRB_BIDI_CMD))) {
3377a9b6f722SSaurav Kashyap qla25xx_process_bidir_status_iocb(vha, pkt, req, handle);
3378a9b6f722SSaurav Kashyap return;
3379a9b6f722SSaurav Kashyap }
3380a9b6f722SSaurav Kashyap
3381faef62d1SArmen Baloyan /* Task Management completion. */
3382faef62d1SArmen Baloyan if (sp->type == SRB_TM_CMD) {
3383faef62d1SArmen Baloyan qla24xx_tm_iocb_entry(vha, req, pkt);
3384faef62d1SArmen Baloyan return;
3385faef62d1SArmen Baloyan }
3386faef62d1SArmen Baloyan
3387a9b6f722SSaurav Kashyap /* Fast path completion. */
3388dd30706eSQuinn Tran qla_chk_edif_rx_sa_delete_pending(vha, sp, sts24);
338971bef502SQuinn Tran sp->qpair->cmd_completion_cnt++;
3390dd30706eSQuinn Tran
3391a9b6f722SSaurav Kashyap if (comp_status == CS_COMPLETE && scsi_status == 0) {
3392a9b6f722SSaurav Kashyap qla2x00_process_completed_request(vha, req, handle);
3393a9b6f722SSaurav Kashyap
3394a9b6f722SSaurav Kashyap return;
3395a9b6f722SSaurav Kashyap }
3396a9b6f722SSaurav Kashyap
33979ba56b95SGiridhar Malavali cp = GET_CMD_SP(sp);
33981da177e4SLinus Torvalds if (cp == NULL) {
3399cfb0919cSChad Dupuis ql_dbg(ql_dbg_io, vha, 0x3018,
34007c3df132SSaurav Kashyap "Command already returned (0x%x/%p).\n",
34017c3df132SSaurav Kashyap sts->handle, sp);
34021da177e4SLinus Torvalds
3403b843addeSQuinn Tran req->outstanding_cmds[handle] = NULL;
34041da177e4SLinus Torvalds return;
34051da177e4SLinus Torvalds }
34061da177e4SLinus Torvalds
34071da177e4SLinus Torvalds lscsi_status = scsi_status & STATUS_MASK;
34081da177e4SLinus Torvalds
3409bdf79621S fcport = sp->fcport;
34101da177e4SLinus Torvalds
3411b7d2280cSAndrew Vasquez ox_id = 0;
34125544213bSAndrew Vasquez sense_len = par_sense_len = rsp_info_len = resid_len =
34135544213bSAndrew Vasquez fw_resid_len = 0;
3414e428924cSAndrew Vasquez if (IS_FWI2_CAPABLE(ha)) {
34150f00a206SLalit Chandivade if (scsi_status & SS_SENSE_LEN_VALID)
34169a853f71SAndrew Vasquez sense_len = le32_to_cpu(sts24->sense_len);
34170f00a206SLalit Chandivade if (scsi_status & SS_RESPONSE_INFO_LEN_VALID)
34189a853f71SAndrew Vasquez rsp_info_len = le32_to_cpu(sts24->rsp_data_len);
34190f00a206SLalit Chandivade if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER))
34209a853f71SAndrew Vasquez resid_len = le32_to_cpu(sts24->rsp_residual_count);
34210f00a206SLalit Chandivade if (comp_status == CS_DATA_UNDERRUN)
3422ed17c71bSRavi Anand fw_resid_len = le32_to_cpu(sts24->residual_len);
34239a853f71SAndrew Vasquez rsp_info = sts24->data;
34249a853f71SAndrew Vasquez sense_data = sts24->data;
34259a853f71SAndrew Vasquez host_to_fcp_swap(sts24->data, sizeof(sts24->data));
3426b7d2280cSAndrew Vasquez ox_id = le16_to_cpu(sts24->ox_id);
34275544213bSAndrew Vasquez par_sense_len = sizeof(sts24->data);
34283aac0c0fSArun Easi sts_qual = le16_to_cpu(sts24->status_qualifier);
34299a853f71SAndrew Vasquez } else {
34300f00a206SLalit Chandivade if (scsi_status & SS_SENSE_LEN_VALID)
34319a853f71SAndrew Vasquez sense_len = le16_to_cpu(sts->req_sense_length);
34320f00a206SLalit Chandivade if (scsi_status & SS_RESPONSE_INFO_LEN_VALID)
34339a853f71SAndrew Vasquez rsp_info_len = le16_to_cpu(sts->rsp_info_len);
34349a853f71SAndrew Vasquez resid_len = le32_to_cpu(sts->residual_length);
34359a853f71SAndrew Vasquez rsp_info = sts->rsp_info;
34369a853f71SAndrew Vasquez sense_data = sts->req_sense_data;
34375544213bSAndrew Vasquez par_sense_len = sizeof(sts->req_sense_data);
34389a853f71SAndrew Vasquez }
34399a853f71SAndrew Vasquez
34401da177e4SLinus Torvalds /* Check for any FCP transport errors. */
34411da177e4SLinus Torvalds if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) {
34429a853f71SAndrew Vasquez /* Sense data lies beyond any FCP RESPONSE data. */
34435544213bSAndrew Vasquez if (IS_FWI2_CAPABLE(ha)) {
34449a853f71SAndrew Vasquez sense_data += rsp_info_len;
34455544213bSAndrew Vasquez par_sense_len -= rsp_info_len;
34465544213bSAndrew Vasquez }
34479a853f71SAndrew Vasquez if (rsp_info_len > 3 && rsp_info[3]) {
34485e19ed90SArun Easi ql_dbg(ql_dbg_io, fcport->vha, 0x3019,
34497c3df132SSaurav Kashyap "FCP I/O protocol failure (0x%x/0x%x).\n",
34507c3df132SSaurav Kashyap rsp_info_len, rsp_info[3]);
34511da177e4SLinus Torvalds
34529ba56b95SGiridhar Malavali res = DID_BUS_BUSY << 16;
3453b7d2280cSAndrew Vasquez goto out;
34541da177e4SLinus Torvalds }
34551da177e4SLinus Torvalds }
34561da177e4SLinus Torvalds
34573e8ce320SAndrew Vasquez /* Check for overrun. */
34583e8ce320SAndrew Vasquez if (IS_FWI2_CAPABLE(ha) && comp_status == CS_COMPLETE &&
34593e8ce320SAndrew Vasquez scsi_status & SS_RESIDUAL_OVER)
34603e8ce320SAndrew Vasquez comp_status = CS_DATA_OVERRUN;
34613e8ce320SAndrew Vasquez
34621da177e4SLinus Torvalds /*
3463e05fe292SChad Dupuis * Check retry_delay_timer value if we receive a busy or
3464e05fe292SChad Dupuis * queue full.
3465e05fe292SChad Dupuis */
34663aac0c0fSArun Easi if (unlikely(lscsi_status == SAM_STAT_TASK_SET_FULL ||
34673aac0c0fSArun Easi lscsi_status == SAM_STAT_BUSY))
34683aac0c0fSArun Easi qla2x00_set_retry_delay_timestamp(fcport, sts_qual);
3469e05fe292SChad Dupuis
3470e05fe292SChad Dupuis /*
34711da177e4SLinus Torvalds * Based on Host and scsi status generate status code for Linux
34721da177e4SLinus Torvalds */
34731da177e4SLinus Torvalds switch (comp_status) {
34741da177e4SLinus Torvalds case CS_COMPLETE:
3475df7baa50SAndrew Vasquez case CS_QUEUE_FULL:
34761da177e4SLinus Torvalds if (scsi_status == 0) {
34779ba56b95SGiridhar Malavali res = DID_OK << 16;
34781da177e4SLinus Torvalds break;
34791da177e4SLinus Torvalds }
34801da177e4SLinus Torvalds if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) {
34819a853f71SAndrew Vasquez resid = resid_len;
3482385d70b4SFUJITA Tomonori scsi_set_resid(cp, resid);
34830da69df1SAndrew Vasquez
34840da69df1SAndrew Vasquez if (!lscsi_status &&
3485385d70b4SFUJITA Tomonori ((unsigned)(scsi_bufflen(cp) - resid) <
34860da69df1SAndrew Vasquez cp->underflow)) {
34875e19ed90SArun Easi ql_dbg(ql_dbg_io, fcport->vha, 0x301a,
348883548fe2SQuinn Tran "Mid-layer underflow detected (0x%x of 0x%x bytes).\n",
34897c3df132SSaurav Kashyap resid, scsi_bufflen(cp));
34900da69df1SAndrew Vasquez
34919ba56b95SGiridhar Malavali res = DID_ERROR << 16;
34920da69df1SAndrew Vasquez break;
34930da69df1SAndrew Vasquez }
34941da177e4SLinus Torvalds }
34959ba56b95SGiridhar Malavali res = DID_OK << 16 | lscsi_status;
34961da177e4SLinus Torvalds
3497df7baa50SAndrew Vasquez if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
34985e19ed90SArun Easi ql_dbg(ql_dbg_io, fcport->vha, 0x301b,
34997c3df132SSaurav Kashyap "QUEUE FULL detected.\n");
3500df7baa50SAndrew Vasquez break;
3501df7baa50SAndrew Vasquez }
3502b7d2280cSAndrew Vasquez logit = 0;
35031da177e4SLinus Torvalds if (lscsi_status != SS_CHECK_CONDITION)
35041da177e4SLinus Torvalds break;
35051da177e4SLinus Torvalds
3506b80ca4f7SFUJITA Tomonori memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
35071da177e4SLinus Torvalds if (!(scsi_status & SS_SENSE_LEN_VALID))
35081da177e4SLinus Torvalds break;
35091da177e4SLinus Torvalds
35105544213bSAndrew Vasquez qla2x00_handle_sense(sp, sense_data, par_sense_len, sense_len,
35119ba56b95SGiridhar Malavali rsp, res);
35121da177e4SLinus Torvalds break;
35131da177e4SLinus Torvalds
35141da177e4SLinus Torvalds case CS_DATA_UNDERRUN:
35150f00a206SLalit Chandivade /* Use F/W calculated residual length. */
35160f00a206SLalit Chandivade resid = IS_FWI2_CAPABLE(ha) ? fw_resid_len : resid_len;
35170f00a206SLalit Chandivade scsi_set_resid(cp, resid);
35180f00a206SLalit Chandivade if (scsi_status & SS_RESIDUAL_UNDER) {
35190f00a206SLalit Chandivade if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) {
3520daaecb41SSaurav Kashyap ql_log(ql_log_warn, fcport->vha, 0x301d,
352183548fe2SQuinn Tran "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
35227c3df132SSaurav Kashyap resid, scsi_bufflen(cp));
35230f00a206SLalit Chandivade
35249ba56b95SGiridhar Malavali res = DID_ERROR << 16 | lscsi_status;
35254e85e3d9SArun Easi goto check_scsi_status;
35261da177e4SLinus Torvalds }
35271da177e4SLinus Torvalds
35280f00a206SLalit Chandivade if (!lscsi_status &&
35290f00a206SLalit Chandivade ((unsigned)(scsi_bufflen(cp) - resid) <
35300f00a206SLalit Chandivade cp->underflow)) {
35315e19ed90SArun Easi ql_dbg(ql_dbg_io, fcport->vha, 0x301e,
353283548fe2SQuinn Tran "Mid-layer underflow detected (0x%x of 0x%x bytes).\n",
35337c3df132SSaurav Kashyap resid, scsi_bufflen(cp));
35340f00a206SLalit Chandivade
35359ba56b95SGiridhar Malavali res = DID_ERROR << 16;
35360f00a206SLalit Chandivade break;
35370f00a206SLalit Chandivade }
35384aee5766SGiridhar Malavali } else if (lscsi_status != SAM_STAT_TASK_SET_FULL &&
35394aee5766SGiridhar Malavali lscsi_status != SAM_STAT_BUSY) {
35404aee5766SGiridhar Malavali /*
35414aee5766SGiridhar Malavali * scsi status of task set and busy are considered to be
35424aee5766SGiridhar Malavali * task not completed.
35434aee5766SGiridhar Malavali */
35444aee5766SGiridhar Malavali
3545daaecb41SSaurav Kashyap ql_log(ql_log_warn, fcport->vha, 0x301f,
354683548fe2SQuinn Tran "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
354783548fe2SQuinn Tran resid, scsi_bufflen(cp));
35480f00a206SLalit Chandivade
3549dbf1f53cSSaurav Kashyap vha->interface_err_cnt++;
3550dbf1f53cSSaurav Kashyap
35519ba56b95SGiridhar Malavali res = DID_ERROR << 16 | lscsi_status;
35520374f55eSLalit Chandivade goto check_scsi_status;
35534aee5766SGiridhar Malavali } else {
35544aee5766SGiridhar Malavali ql_dbg(ql_dbg_io, fcport->vha, 0x3030,
35554aee5766SGiridhar Malavali "scsi_status: 0x%x, lscsi_status: 0x%x\n",
35564aee5766SGiridhar Malavali scsi_status, lscsi_status);
35570f00a206SLalit Chandivade }
35580f00a206SLalit Chandivade
35599ba56b95SGiridhar Malavali res = DID_OK << 16 | lscsi_status;
3560b7d2280cSAndrew Vasquez logit = 0;
35610f00a206SLalit Chandivade
35620374f55eSLalit Chandivade check_scsi_status:
35631da177e4SLinus Torvalds /*
35641da177e4SLinus Torvalds * Check to see if SCSI Status is non zero. If so report SCSI
35651da177e4SLinus Torvalds * Status.
35661da177e4SLinus Torvalds */
35671da177e4SLinus Torvalds if (lscsi_status != 0) {
3568ffec28a3SAndrew Vasquez if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
35695e19ed90SArun Easi ql_dbg(ql_dbg_io, fcport->vha, 0x3020,
35707c3df132SSaurav Kashyap "QUEUE FULL detected.\n");
3571b7d2280cSAndrew Vasquez logit = 1;
3572ffec28a3SAndrew Vasquez break;
3573ffec28a3SAndrew Vasquez }
35741da177e4SLinus Torvalds if (lscsi_status != SS_CHECK_CONDITION)
35751da177e4SLinus Torvalds break;
35761da177e4SLinus Torvalds
3577b80ca4f7SFUJITA Tomonori memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
35781da177e4SLinus Torvalds if (!(scsi_status & SS_SENSE_LEN_VALID))
35791da177e4SLinus Torvalds break;
35801da177e4SLinus Torvalds
35815544213bSAndrew Vasquez qla2x00_handle_sense(sp, sense_data, par_sense_len,
35829ba56b95SGiridhar Malavali sense_len, rsp, res);
35831da177e4SLinus Torvalds }
35841da177e4SLinus Torvalds break;
35851da177e4SLinus Torvalds
35861da177e4SLinus Torvalds case CS_PORT_LOGGED_OUT:
35871da177e4SLinus Torvalds case CS_PORT_CONFIG_CHG:
35881da177e4SLinus Torvalds case CS_PORT_BUSY:
35891da177e4SLinus Torvalds case CS_INCOMPLETE:
35901da177e4SLinus Torvalds case CS_PORT_UNAVAILABLE:
35911da177e4SLinus Torvalds case CS_TIMEOUT:
3592ff454b01SChad Dupuis case CS_RESET:
3593d7e2e4a6SQuinn Tran case CS_EDIF_INV_REQ:
3594ff454b01SChad Dupuis
3595056a4483SMike Christie /*
3596056a4483SMike Christie * We are going to have the fc class block the rport
3597056a4483SMike Christie * while we try to recover so instruct the mid layer
3598056a4483SMike Christie * to requeue until the class decides how to handle this.
3599056a4483SMike Christie */
36009ba56b95SGiridhar Malavali res = DID_TRANSPORT_DISRUPTED << 16;
36011da177e4SLinus Torvalds
3602b7d2280cSAndrew Vasquez if (comp_status == CS_TIMEOUT) {
3603b7d2280cSAndrew Vasquez if (IS_FWI2_CAPABLE(ha))
3604b7d2280cSAndrew Vasquez break;
3605b7d2280cSAndrew Vasquez else if ((le16_to_cpu(sts->status_flags) &
3606b7d2280cSAndrew Vasquez SF_LOGOUT_SENT) == 0)
36079a853f71SAndrew Vasquez break;
36081da177e4SLinus Torvalds }
36099a853f71SAndrew Vasquez
3610726b8548SQuinn Tran if (atomic_read(&fcport->state) == FCS_ONLINE) {
3611726b8548SQuinn Tran ql_dbg(ql_dbg_disc, fcport->vha, 0x3021,
36120e948975SChad Dupuis "Port to be marked lost on fcport=%02x%02x%02x, current "
3613726b8548SQuinn Tran "port state= %s comp_status %x.\n", fcport->d_id.b.domain,
36140e948975SChad Dupuis fcport->d_id.b.area, fcport->d_id.b.al_pa,
3615282d1056SBart Van Assche port_state_str[FCS_ONLINE],
3616726b8548SQuinn Tran comp_status);
3617b7d2280cSAndrew Vasquez
3618d8630bb9SQuinn Tran qlt_schedule_sess_for_deletion(fcport);
3619726b8548SQuinn Tran }
3620726b8548SQuinn Tran
36211da177e4SLinus Torvalds break;
36221da177e4SLinus Torvalds
3623b7d2280cSAndrew Vasquez case CS_ABORTED:
36249ba56b95SGiridhar Malavali res = DID_RESET << 16;
3625b7d2280cSAndrew Vasquez break;
3626bad75002SArun Easi
3627bad75002SArun Easi case CS_DIF_ERROR:
36288cb2049cSArun Easi logit = qla2x00_handle_dif_error(sp, sts24);
3629fb6e4668SArun Easi res = cp->result;
3630bad75002SArun Easi break;
36319e522cd8SArun Easi
36329e522cd8SArun Easi case CS_TRANSPORT:
36339e522cd8SArun Easi res = DID_ERROR << 16;
3634dbf1f53cSSaurav Kashyap vha->hw_err_cnt++;
36359e522cd8SArun Easi
36369e522cd8SArun Easi if (!IS_PI_SPLIT_DET_CAPABLE(ha))
36379e522cd8SArun Easi break;
36389e522cd8SArun Easi
36399e522cd8SArun Easi if (state_flags & BIT_4)
36409e522cd8SArun Easi scmd_printk(KERN_WARNING, cp,
36419e522cd8SArun Easi "Unsupported device '%s' found.\n",
36429e522cd8SArun Easi cp->device->vendor);
36439e522cd8SArun Easi break;
36449e522cd8SArun Easi
364550b81275SGiridhar Malavali case CS_DMA:
364650b81275SGiridhar Malavali ql_log(ql_log_info, fcport->vha, 0x3022,
364750b81275SGiridhar Malavali "CS_DMA error: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%06x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
364850b81275SGiridhar Malavali comp_status, scsi_status, res, vha->host_no,
364950b81275SGiridhar Malavali cp->device->id, cp->device->lun, fcport->d_id.b24,
365050b81275SGiridhar Malavali ox_id, cp->cmnd, scsi_bufflen(cp), rsp_info_len,
365150b81275SGiridhar Malavali resid_len, fw_resid_len, sp, cp);
365250b81275SGiridhar Malavali ql_dump_buffer(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe0ee,
365350b81275SGiridhar Malavali pkt, sizeof(*sts24));
365450b81275SGiridhar Malavali res = DID_ERROR << 16;
3655dbf1f53cSSaurav Kashyap vha->hw_err_cnt++;
365650b81275SGiridhar Malavali break;
36571da177e4SLinus Torvalds default:
36589ba56b95SGiridhar Malavali res = DID_ERROR << 16;
36591da177e4SLinus Torvalds break;
36601da177e4SLinus Torvalds }
36611da177e4SLinus Torvalds
3662b7d2280cSAndrew Vasquez out:
3663b7d2280cSAndrew Vasquez if (logit)
3664bff4873cSArun Easi ql_dbg(ql_dbg_io, fcport->vha, 0x3022,
3665daaecb41SSaurav Kashyap "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
36669ba56b95SGiridhar Malavali comp_status, scsi_status, res, vha->host_no,
3667cfb0919cSChad Dupuis cp->device->id, cp->device->lun, fcport->d_id.b.domain,
3668cfb0919cSChad Dupuis fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
36697b833558SOleksandr Khoshaba cp->cmnd, scsi_bufflen(cp), rsp_info_len,
3670c7bc4caeSChad Dupuis resid_len, fw_resid_len, sp, cp);
3671b7d2280cSAndrew Vasquez
36722afa19a9SAnirban Chakraborty if (rsp->status_srb == NULL)
367325ff6af1SJoe Carnuccio sp->done(sp, res);
3674b843addeSQuinn Tran
3675b843addeSQuinn Tran /* for io's, clearing of outstanding_cmds[handle] means scsi_done was called */
3676b843addeSQuinn Tran req->outstanding_cmds[handle] = NULL;
36771da177e4SLinus Torvalds }
36781da177e4SLinus Torvalds
36791da177e4SLinus Torvalds /**
36801da177e4SLinus Torvalds * qla2x00_status_cont_entry() - Process a Status Continuations entry.
36812db6228dSBart Van Assche * @rsp: response queue
36821da177e4SLinus Torvalds * @pkt: Entry pointer
36831da177e4SLinus Torvalds *
36841da177e4SLinus Torvalds * Extended sense data.
36851da177e4SLinus Torvalds */
36861da177e4SLinus Torvalds static void
qla2x00_status_cont_entry(struct rsp_que * rsp,sts_cont_entry_t * pkt)36872afa19a9SAnirban Chakraborty qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
36881da177e4SLinus Torvalds {
36891da177e4SLinus Torvalds uint8_t sense_sz = 0;
36902afa19a9SAnirban Chakraborty struct qla_hw_data *ha = rsp->hw;
36917c3df132SSaurav Kashyap struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
36922afa19a9SAnirban Chakraborty srb_t *sp = rsp->status_srb;
36931da177e4SLinus Torvalds struct scsi_cmnd *cp;
36949ba56b95SGiridhar Malavali uint32_t sense_len;
36959ba56b95SGiridhar Malavali uint8_t *sense_ptr;
36961da177e4SLinus Torvalds
36979ba56b95SGiridhar Malavali if (!sp || !GET_CMD_SENSE_LEN(sp))
36989ba56b95SGiridhar Malavali return;
36999ba56b95SGiridhar Malavali
37009ba56b95SGiridhar Malavali sense_len = GET_CMD_SENSE_LEN(sp);
37019ba56b95SGiridhar Malavali sense_ptr = GET_CMD_SENSE_PTR(sp);
37029ba56b95SGiridhar Malavali
37039ba56b95SGiridhar Malavali cp = GET_CMD_SP(sp);
37041da177e4SLinus Torvalds if (cp == NULL) {
37057c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x3025,
37069ba56b95SGiridhar Malavali "cmd is NULL: already returned to OS (sp=%p).\n", sp);
37071da177e4SLinus Torvalds
37082afa19a9SAnirban Chakraborty rsp->status_srb = NULL;
37091da177e4SLinus Torvalds return;
37101da177e4SLinus Torvalds }
37111da177e4SLinus Torvalds
37129ba56b95SGiridhar Malavali if (sense_len > sizeof(pkt->data))
37131da177e4SLinus Torvalds sense_sz = sizeof(pkt->data);
37149ba56b95SGiridhar Malavali else
37159ba56b95SGiridhar Malavali sense_sz = sense_len;
37161da177e4SLinus Torvalds
37171da177e4SLinus Torvalds /* Move sense data. */
3718e428924cSAndrew Vasquez if (IS_FWI2_CAPABLE(ha))
37199a853f71SAndrew Vasquez host_to_fcp_swap(pkt->data, sizeof(pkt->data));
37209ba56b95SGiridhar Malavali memcpy(sense_ptr, pkt->data, sense_sz);
37217c3df132SSaurav Kashyap ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302c,
37229ba56b95SGiridhar Malavali sense_ptr, sense_sz);
37231da177e4SLinus Torvalds
37249ba56b95SGiridhar Malavali sense_len -= sense_sz;
37259ba56b95SGiridhar Malavali sense_ptr += sense_sz;
37269ba56b95SGiridhar Malavali
37279ba56b95SGiridhar Malavali SET_CMD_SENSE_PTR(sp, sense_ptr);
37289ba56b95SGiridhar Malavali SET_CMD_SENSE_LEN(sp, sense_len);
37291da177e4SLinus Torvalds
37301da177e4SLinus Torvalds /* Place command on done queue. */
37319ba56b95SGiridhar Malavali if (sense_len == 0) {
37322afa19a9SAnirban Chakraborty rsp->status_srb = NULL;
373325ff6af1SJoe Carnuccio sp->done(sp, cp->result);
37341da177e4SLinus Torvalds }
37351da177e4SLinus Torvalds }
3736c4631191SGiridhar Malavali
37371da177e4SLinus Torvalds /**
37381da177e4SLinus Torvalds * qla2x00_error_entry() - Process an error entry.
37392db6228dSBart Van Assche * @vha: SCSI driver HA context
37402db6228dSBart Van Assche * @rsp: response queue
37411da177e4SLinus Torvalds * @pkt: Entry pointer
3742c5419e26SQuinn Tran * return : 1=allow further error analysis. 0=no additional error analysis.
37431da177e4SLinus Torvalds */
3744c5419e26SQuinn Tran static int
qla2x00_error_entry(scsi_qla_host_t * vha,struct rsp_que * rsp,sts_entry_t * pkt)374573208dfdSAnirban Chakraborty qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
37461da177e4SLinus Torvalds {
37471da177e4SLinus Torvalds srb_t *sp;
3748e315cd28SAnirban Chakraborty struct qla_hw_data *ha = vha->hw;
3749c4631191SGiridhar Malavali const char func[] = "ERROR-IOCB";
37502afa19a9SAnirban Chakraborty uint16_t que = MSW(pkt->handle);
3751a6fe35c0SArun Easi struct req_que *req = NULL;
37529ba56b95SGiridhar Malavali int res = DID_ERROR << 16;
3753b843addeSQuinn Tran u16 index;
37547c3df132SSaurav Kashyap
37557c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x502a,
375682de802aSQuinn Tran "iocb type %xh with error status %xh, handle %xh, rspq id %d\n",
375782de802aSQuinn Tran pkt->entry_type, pkt->entry_status, pkt->handle, rsp->id);
37589ba56b95SGiridhar Malavali
3759a6fe35c0SArun Easi if (que >= ha->max_req_queues || !ha->req_q_map[que])
3760a6fe35c0SArun Easi goto fatal;
3761a6fe35c0SArun Easi
3762a6fe35c0SArun Easi req = ha->req_q_map[que];
3763a6fe35c0SArun Easi
37649ba56b95SGiridhar Malavali if (pkt->entry_status & RF_BUSY)
37659ba56b95SGiridhar Malavali res = DID_BUS_BUSY << 16;
37661da177e4SLinus Torvalds
3767c5419e26SQuinn Tran if ((pkt->handle & ~QLA_TGT_HANDLE_MASK) == QLA_TGT_SKIP_HANDLE)
3768c5419e26SQuinn Tran return 0;
37694f060736SQuinn Tran
3770c5419e26SQuinn Tran switch (pkt->entry_type) {
3771c5419e26SQuinn Tran case NOTIFY_ACK_TYPE:
3772c5419e26SQuinn Tran case STATUS_CONT_TYPE:
3773c5419e26SQuinn Tran case LOGINOUT_PORT_IOCB_TYPE:
3774c5419e26SQuinn Tran case CT_IOCB_TYPE:
3775c5419e26SQuinn Tran case ELS_IOCB_TYPE:
3776c5419e26SQuinn Tran case ABORT_IOCB_TYPE:
3777c5419e26SQuinn Tran case MBX_IOCB_TYPE:
3778527b8ae3SQuinn Tran default:
3779c4631191SGiridhar Malavali sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
3780a6fe35c0SArun Easi if (sp) {
378125ff6af1SJoe Carnuccio sp->done(sp, res);
3782c5419e26SQuinn Tran return 0;
3783c5419e26SQuinn Tran }
3784c5419e26SQuinn Tran break;
3785c5419e26SQuinn Tran
3786dd30706eSQuinn Tran case SA_UPDATE_IOCB_TYPE:
3787c5419e26SQuinn Tran case ABTS_RESP_24XX:
3788c5419e26SQuinn Tran case CTIO_TYPE7:
3789c5419e26SQuinn Tran case CTIO_CRC2:
3790c5419e26SQuinn Tran return 1;
3791b843addeSQuinn Tran case STATUS_TYPE:
3792b843addeSQuinn Tran sp = qla_get_sp_from_handle(vha, func, req, pkt, &index);
3793b843addeSQuinn Tran if (sp) {
3794b843addeSQuinn Tran sp->done(sp, res);
3795b843addeSQuinn Tran req->outstanding_cmds[index] = NULL;
3796b843addeSQuinn Tran return 0;
3797b843addeSQuinn Tran }
3798b843addeSQuinn Tran break;
3799a6fe35c0SArun Easi }
3800a6fe35c0SArun Easi fatal:
38017c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x5030,
3802fd49a540SChad Dupuis "Error entry - invalid handle/queue (%04x).\n", que);
3803c5419e26SQuinn Tran return 0;
38041da177e4SLinus Torvalds }
38051da177e4SLinus Torvalds
38061da177e4SLinus Torvalds /**
38079a853f71SAndrew Vasquez * qla24xx_mbx_completion() - Process mailbox command completions.
38082db6228dSBart Van Assche * @vha: SCSI driver HA context
38099a853f71SAndrew Vasquez * @mb0: Mailbox0 register
38109a853f71SAndrew Vasquez */
38119a853f71SAndrew Vasquez static void
qla24xx_mbx_completion(scsi_qla_host_t * vha,uint16_t mb0)3812e315cd28SAnirban Chakraborty qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
38139a853f71SAndrew Vasquez {
38149a853f71SAndrew Vasquez uint16_t cnt;
38154fa94f83SAndrew Vasquez uint32_t mboxes;
381637139da1SBart Van Assche __le16 __iomem *wptr;
3817e315cd28SAnirban Chakraborty struct qla_hw_data *ha = vha->hw;
38189a853f71SAndrew Vasquez struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
38199a853f71SAndrew Vasquez
38204fa94f83SAndrew Vasquez /* Read all mbox registers? */
3821c02189e1SBart Van Assche WARN_ON_ONCE(ha->mbx_count > 32);
3822c02189e1SBart Van Assche mboxes = (1ULL << ha->mbx_count) - 1;
38234fa94f83SAndrew Vasquez if (!ha->mcp)
3824a720101dSMasanari Iida ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERROR.\n");
38254fa94f83SAndrew Vasquez else
38264fa94f83SAndrew Vasquez mboxes = ha->mcp->in_mb;
38274fa94f83SAndrew Vasquez
38289a853f71SAndrew Vasquez /* Load return mailbox registers. */
38299a853f71SAndrew Vasquez ha->flags.mbox_int = 1;
38309a853f71SAndrew Vasquez ha->mailbox_out[0] = mb0;
38314fa94f83SAndrew Vasquez mboxes >>= 1;
38327ffa5b93SBart Van Assche wptr = ®->mailbox1;
38339a853f71SAndrew Vasquez
38349a853f71SAndrew Vasquez for (cnt = 1; cnt < ha->mbx_count; cnt++) {
38354fa94f83SAndrew Vasquez if (mboxes & BIT_0)
383604474d3aSBart Van Assche ha->mailbox_out[cnt] = rd_reg_word(wptr);
38374fa94f83SAndrew Vasquez
38384fa94f83SAndrew Vasquez mboxes >>= 1;
38399a853f71SAndrew Vasquez wptr++;
38409a853f71SAndrew Vasquez }
38419a853f71SAndrew Vasquez }
38429a853f71SAndrew Vasquez
38434440e46dSArmen Baloyan static void
qla24xx_abort_iocb_entry(scsi_qla_host_t * vha,struct req_que * req,struct abort_entry_24xx * pkt)38444440e46dSArmen Baloyan qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
38454440e46dSArmen Baloyan struct abort_entry_24xx *pkt)
38464440e46dSArmen Baloyan {
38474440e46dSArmen Baloyan const char func[] = "ABT_IOCB";
38484440e46dSArmen Baloyan srb_t *sp;
3849a0465859SBikash Hazarika srb_t *orig_sp = NULL;
38504440e46dSArmen Baloyan struct srb_iocb *abt;
38514440e46dSArmen Baloyan
38524440e46dSArmen Baloyan sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
38534440e46dSArmen Baloyan if (!sp)
38544440e46dSArmen Baloyan return;
38554440e46dSArmen Baloyan
38564440e46dSArmen Baloyan abt = &sp->u.iocb_cmd;
385737ce4f35SBart Van Assche abt->u.abt.comp_status = pkt->comp_status;
3858a0465859SBikash Hazarika orig_sp = sp->cmd_sp;
3859a0465859SBikash Hazarika /* Need to pass original sp */
3860a0465859SBikash Hazarika if (orig_sp)
3861a0465859SBikash Hazarika qla_nvme_abort_process_comp_status(pkt, orig_sp);
3862a0465859SBikash Hazarika
386325ff6af1SJoe Carnuccio sp->done(sp, 0);
38644440e46dSArmen Baloyan }
38654440e46dSArmen Baloyan
qla24xx_nvme_ls4_iocb(struct scsi_qla_host * vha,struct pt_ls4_request * pkt,struct req_que * req)38660f7e51f6Shimanshu.madhani@cavium.com void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha,
38670f7e51f6Shimanshu.madhani@cavium.com struct pt_ls4_request *pkt, struct req_que *req)
3868e84067d7SDuane Grigsby {
3869e84067d7SDuane Grigsby srb_t *sp;
3870e84067d7SDuane Grigsby const char func[] = "LS4_IOCB";
3871e84067d7SDuane Grigsby uint16_t comp_status;
3872e84067d7SDuane Grigsby
3873e84067d7SDuane Grigsby sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
3874e84067d7SDuane Grigsby if (!sp)
3875e84067d7SDuane Grigsby return;
3876e84067d7SDuane Grigsby
3877e84067d7SDuane Grigsby comp_status = le16_to_cpu(pkt->status);
3878e84067d7SDuane Grigsby sp->done(sp, comp_status);
3879e84067d7SDuane Grigsby }
3880e84067d7SDuane Grigsby
38819a853f71SAndrew Vasquez /**
3882fac28079SQuinn Tran * qla_chk_cont_iocb_avail - check for all continuation iocbs are available
3883fac28079SQuinn Tran * before iocb processing can start.
3884fac28079SQuinn Tran * @vha: host adapter pointer
3885fac28079SQuinn Tran * @rsp: respond queue
3886fac28079SQuinn Tran * @pkt: head iocb describing how many continuation iocb
3887fac28079SQuinn Tran * Return: 0 all iocbs has arrived, xx- all iocbs have not arrived.
3888fac28079SQuinn Tran */
qla_chk_cont_iocb_avail(struct scsi_qla_host * vha,struct rsp_que * rsp,response_t * pkt,u32 rsp_q_in)3889fac28079SQuinn Tran static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
3890c019cd65SQuinn Tran struct rsp_que *rsp, response_t *pkt, u32 rsp_q_in)
3891fac28079SQuinn Tran {
3892c019cd65SQuinn Tran int start_pkt_ring_index;
3893c019cd65SQuinn Tran u32 iocb_cnt = 0;
3894fac28079SQuinn Tran int rc = 0;
3895fac28079SQuinn Tran
3896fac28079SQuinn Tran if (pkt->entry_count == 1)
3897fac28079SQuinn Tran return rc;
3898fac28079SQuinn Tran
3899fac28079SQuinn Tran /* ring_index was pre-increment. set it back to current pkt */
3900fac28079SQuinn Tran if (rsp->ring_index == 0)
3901fac28079SQuinn Tran start_pkt_ring_index = rsp->length - 1;
3902fac28079SQuinn Tran else
3903fac28079SQuinn Tran start_pkt_ring_index = rsp->ring_index - 1;
3904fac28079SQuinn Tran
3905c019cd65SQuinn Tran if (rsp_q_in < start_pkt_ring_index)
3906c019cd65SQuinn Tran /* q in ptr is wrapped */
3907c019cd65SQuinn Tran iocb_cnt = rsp->length - start_pkt_ring_index + rsp_q_in;
3908fac28079SQuinn Tran else
3909c019cd65SQuinn Tran iocb_cnt = rsp_q_in - start_pkt_ring_index;
3910fac28079SQuinn Tran
3911c019cd65SQuinn Tran if (iocb_cnt < pkt->entry_count)
3912fac28079SQuinn Tran rc = -EIO;
3913fac28079SQuinn Tran
3914c019cd65SQuinn Tran ql_dbg(ql_dbg_init, vha, 0x5091,
3915c019cd65SQuinn Tran "%s - ring %p pkt %p entry count %d iocb_cnt %d rsp_q_in %d rc %d\n",
3916c019cd65SQuinn Tran __func__, rsp->ring, pkt, pkt->entry_count, iocb_cnt, rsp_q_in, rc);
3917fac28079SQuinn Tran
3918fac28079SQuinn Tran return rc;
3919fac28079SQuinn Tran }
3920fac28079SQuinn Tran
qla_marker_iocb_entry(scsi_qla_host_t * vha,struct req_que * req,struct mrk_entry_24xx * pkt)39219803fb5dSQuinn Tran static void qla_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
39229803fb5dSQuinn Tran struct mrk_entry_24xx *pkt)
39239803fb5dSQuinn Tran {
39249803fb5dSQuinn Tran const char func[] = "MRK-IOCB";
39259803fb5dSQuinn Tran srb_t *sp;
39269803fb5dSQuinn Tran int res = QLA_SUCCESS;
39279803fb5dSQuinn Tran
39289803fb5dSQuinn Tran if (!IS_FWI2_CAPABLE(vha->hw))
39299803fb5dSQuinn Tran return;
39309803fb5dSQuinn Tran
39319803fb5dSQuinn Tran sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
39329803fb5dSQuinn Tran if (!sp)
39339803fb5dSQuinn Tran return;
39349803fb5dSQuinn Tran
39359803fb5dSQuinn Tran if (pkt->entry_status) {
39369803fb5dSQuinn Tran ql_dbg(ql_dbg_taskm, vha, 0x8025, "marker failure.\n");
39379803fb5dSQuinn Tran res = QLA_COMMAND_ERROR;
39389803fb5dSQuinn Tran }
39399803fb5dSQuinn Tran sp->u.iocb_cmd.u.tmf.data = res;
39409803fb5dSQuinn Tran sp->done(sp, res);
39419803fb5dSQuinn Tran }
39429803fb5dSQuinn Tran
3943fac28079SQuinn Tran /**
39449a853f71SAndrew Vasquez * qla24xx_process_response_queue() - Process response queue entries.
39452db6228dSBart Van Assche * @vha: SCSI driver HA context
39462db6228dSBart Van Assche * @rsp: response queue
39479a853f71SAndrew Vasquez */
qla24xx_process_response_queue(struct scsi_qla_host * vha,struct rsp_que * rsp)39482afa19a9SAnirban Chakraborty void qla24xx_process_response_queue(struct scsi_qla_host *vha,
39492afa19a9SAnirban Chakraborty struct rsp_que *rsp)
39509a853f71SAndrew Vasquez {
39519a853f71SAndrew Vasquez struct sts_entry_24xx *pkt;
3952a9083016SGiridhar Malavali struct qla_hw_data *ha = vha->hw;
39539f2475feSShyam Sundar struct purex_entry_24xx *purex_entry;
395462e9dd17SShyam Sundar struct purex_item *pure_item;
3955875386b9SManish Rangankar struct pt_ls4_rx_unsol *p;
3956e4f8a29dSArun Easi u16 rsp_in = 0, cur_ring_index;
3957e4f8a29dSArun Easi int is_shadow_hba;
39589a853f71SAndrew Vasquez
3959ec7193e2SQuinn Tran if (!ha->flags.fw_started)
39609a853f71SAndrew Vasquez return;
39619a853f71SAndrew Vasquez
3962*59f10a05SNilesh Javali if (rsp->qpair->cpuid != raw_smp_processor_id() || !rsp->qpair->rcv_intr) {
396349db4d4eSQuinn Tran rsp->qpair->rcv_intr = 1;
3964d54820b2SGleb Chesnokov
3965d54820b2SGleb Chesnokov if (!rsp->qpair->cpu_mapped)
3966d54820b2SGleb Chesnokov qla_cpu_update(rsp->qpair, raw_smp_processor_id());
396749db4d4eSQuinn Tran }
3968e326d22aSQuinn Tran
3969e4f8a29dSArun Easi #define __update_rsp_in(_is_shadow_hba, _rsp, _rsp_in) \
3970e4f8a29dSArun Easi do { \
3971e4f8a29dSArun Easi _rsp_in = _is_shadow_hba ? *(_rsp)->in_ptr : \
3972e4f8a29dSArun Easi rd_reg_dword_relaxed((_rsp)->rsp_q_in); \
3973e4f8a29dSArun Easi } while (0)
3974e4f8a29dSArun Easi
3975e4f8a29dSArun Easi is_shadow_hba = IS_SHADOW_REG_CAPABLE(ha);
3976e4f8a29dSArun Easi
3977e4f8a29dSArun Easi __update_rsp_in(is_shadow_hba, rsp, rsp_in);
3978e4f8a29dSArun Easi
3979e4f8a29dSArun Easi while (rsp->ring_index != rsp_in &&
3980e4f8a29dSArun Easi rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
3981e315cd28SAnirban Chakraborty pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
3982c019cd65SQuinn Tran cur_ring_index = rsp->ring_index;
39839a853f71SAndrew Vasquez
3984e315cd28SAnirban Chakraborty rsp->ring_index++;
3985e315cd28SAnirban Chakraborty if (rsp->ring_index == rsp->length) {
3986e315cd28SAnirban Chakraborty rsp->ring_index = 0;
3987e315cd28SAnirban Chakraborty rsp->ring_ptr = rsp->ring;
39889a853f71SAndrew Vasquez } else {
3989e315cd28SAnirban Chakraborty rsp->ring_ptr++;
39909a853f71SAndrew Vasquez }
39919a853f71SAndrew Vasquez
39929a853f71SAndrew Vasquez if (pkt->entry_status != 0) {
3993c5419e26SQuinn Tran if (qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt))
3994f83adb61SQuinn Tran goto process_err;
39952d70c103SNicholas Bellinger
39969a853f71SAndrew Vasquez ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
39979a853f71SAndrew Vasquez wmb();
39989a853f71SAndrew Vasquez continue;
39999a853f71SAndrew Vasquez }
4000f83adb61SQuinn Tran process_err:
40019a853f71SAndrew Vasquez
40029a853f71SAndrew Vasquez switch (pkt->entry_type) {
40039a853f71SAndrew Vasquez case STATUS_TYPE:
400473208dfdSAnirban Chakraborty qla2x00_status_entry(vha, rsp, pkt);
40059a853f71SAndrew Vasquez break;
40069a853f71SAndrew Vasquez case STATUS_CONT_TYPE:
40072afa19a9SAnirban Chakraborty qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt);
40089a853f71SAndrew Vasquez break;
40092c3dfe3fSSeokmann Ju case VP_RPT_ID_IOCB_TYPE:
4010e315cd28SAnirban Chakraborty qla24xx_report_id_acquisition(vha,
40112c3dfe3fSSeokmann Ju (struct vp_rpt_id_entry_24xx *)pkt);
40122c3dfe3fSSeokmann Ju break;
4013ac280b67SAndrew Vasquez case LOGINOUT_PORT_IOCB_TYPE:
4014ac280b67SAndrew Vasquez qla24xx_logio_entry(vha, rsp->req,
4015ac280b67SAndrew Vasquez (struct logio_entry_24xx *)pkt);
4016ac280b67SAndrew Vasquez break;
40179a069e19SGiridhar Malavali case CT_IOCB_TYPE:
40189a069e19SGiridhar Malavali qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
40199a069e19SGiridhar Malavali break;
40209a069e19SGiridhar Malavali case ELS_IOCB_TYPE:
40219a069e19SGiridhar Malavali qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE);
40229a069e19SGiridhar Malavali break;
40232d70c103SNicholas Bellinger case ABTS_RECV_24XX:
4024576bfde8SJoe Carnuccio if (qla_ini_mode_enabled(vha)) {
402562e9dd17SShyam Sundar pure_item = qla24xx_copy_std_pkt(vha, pkt);
402662e9dd17SShyam Sundar if (!pure_item)
402762e9dd17SShyam Sundar break;
402862e9dd17SShyam Sundar qla24xx_queue_purex_item(vha, pure_item,
4029576bfde8SJoe Carnuccio qla24xx_process_abts);
4030576bfde8SJoe Carnuccio break;
4031576bfde8SJoe Carnuccio }
4032ecc89f25SJoe Carnuccio if (IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
4033ecc89f25SJoe Carnuccio IS_QLA28XX(ha)) {
40342d70c103SNicholas Bellinger /* ensure that the ATIO queue is empty */
403582de802aSQuinn Tran qlt_handle_abts_recv(vha, rsp,
403682de802aSQuinn Tran (response_t *)pkt);
40372f424b9bSQuinn Tran break;
40382f424b9bSQuinn Tran } else {
40392f424b9bSQuinn Tran qlt_24xx_process_atio_queue(vha, 1);
40402f424b9bSQuinn Tran }
4041df561f66SGustavo A. R. Silva fallthrough;
40422d70c103SNicholas Bellinger case ABTS_RESP_24XX:
40432d70c103SNicholas Bellinger case CTIO_TYPE7:
4044f83adb61SQuinn Tran case CTIO_CRC2:
404582de802aSQuinn Tran qlt_response_pkt_all_vps(vha, rsp, (response_t *)pkt);
40462d70c103SNicholas Bellinger break;
4047e84067d7SDuane Grigsby case PT_LS4_REQUEST:
4048e84067d7SDuane Grigsby qla24xx_nvme_ls4_iocb(vha, (struct pt_ls4_request *)pkt,
4049e84067d7SDuane Grigsby rsp->req);
4050e84067d7SDuane Grigsby break;
4051726b8548SQuinn Tran case NOTIFY_ACK_TYPE:
4052726b8548SQuinn Tran if (pkt->handle == QLA_TGT_SKIP_HANDLE)
405382de802aSQuinn Tran qlt_response_pkt_all_vps(vha, rsp,
405482de802aSQuinn Tran (response_t *)pkt);
4055726b8548SQuinn Tran else
4056726b8548SQuinn Tran qla24xxx_nack_iocb_entry(vha, rsp->req,
4057726b8548SQuinn Tran (struct nack_to_isp *)pkt);
4058726b8548SQuinn Tran break;
405954883291SSaurav Kashyap case MARKER_TYPE:
40609803fb5dSQuinn Tran qla_marker_iocb_entry(vha, rsp->req, (struct mrk_entry_24xx *)pkt);
406154883291SSaurav Kashyap break;
40624440e46dSArmen Baloyan case ABORT_IOCB_TYPE:
40634440e46dSArmen Baloyan qla24xx_abort_iocb_entry(vha, rsp->req,
40644440e46dSArmen Baloyan (struct abort_entry_24xx *)pkt);
40654440e46dSArmen Baloyan break;
4066726b8548SQuinn Tran case MBX_IOCB_TYPE:
4067657ed8a8SDaniel Wagner qla24xx_mbx_iocb_entry(vha, rsp->req,
4068657ed8a8SDaniel Wagner (struct mbx_24xx_entry *)pkt);
4069726b8548SQuinn Tran break;
40702853192eSQuinn Tran case VP_CTRL_IOCB_TYPE:
40712853192eSQuinn Tran qla_ctrlvp_completed(vha, rsp->req,
40722853192eSQuinn Tran (struct vp_ctrl_entry_24xx *)pkt);
40732853192eSQuinn Tran break;
4074d83a80eeSJoe Carnuccio case PUREX_IOCB_TYPE:
40759f2475feSShyam Sundar purex_entry = (void *)pkt;
40769f2475feSShyam Sundar switch (purex_entry->els_frame_payload[3]) {
40779f2475feSShyam Sundar case ELS_RDP:
407862e9dd17SShyam Sundar pure_item = qla24xx_copy_std_pkt(vha, pkt);
407962e9dd17SShyam Sundar if (!pure_item)
408062e9dd17SShyam Sundar break;
408162e9dd17SShyam Sundar qla24xx_queue_purex_item(vha, pure_item,
408262e9dd17SShyam Sundar qla24xx_process_purex_rdp);
4083576bfde8SJoe Carnuccio break;
40849f2475feSShyam Sundar case ELS_FPIN:
40859f2475feSShyam Sundar if (!vha->hw->flags.scm_enabled) {
40869f2475feSShyam Sundar ql_log(ql_log_warn, vha, 0x5094,
40879f2475feSShyam Sundar "SCM not active for this port\n");
40889f2475feSShyam Sundar break;
4089576bfde8SJoe Carnuccio }
40909f2475feSShyam Sundar pure_item = qla27xx_copy_fpin_pkt(vha,
40919f2475feSShyam Sundar (void **)&pkt, &rsp);
4092e4f8a29dSArun Easi __update_rsp_in(is_shadow_hba, rsp, rsp_in);
40939f2475feSShyam Sundar if (!pure_item)
40949f2475feSShyam Sundar break;
40959f2475feSShyam Sundar qla24xx_queue_purex_item(vha, pure_item,
40969f2475feSShyam Sundar qla27xx_process_purex_fpin);
40979f2475feSShyam Sundar break;
40989f2475feSShyam Sundar
4099fac28079SQuinn Tran case ELS_AUTH_ELS:
4100c019cd65SQuinn Tran if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt, rsp_in)) {
4101c019cd65SQuinn Tran /*
4102c019cd65SQuinn Tran * ring_ptr and ring_index were
4103c019cd65SQuinn Tran * pre-incremented above. Reset them
4104c019cd65SQuinn Tran * back to current. Wait for next
4105c019cd65SQuinn Tran * interrupt with all IOCBs to arrive
4106c019cd65SQuinn Tran * and re-process.
4107c019cd65SQuinn Tran */
4108c019cd65SQuinn Tran rsp->ring_ptr = (response_t *)pkt;
4109c019cd65SQuinn Tran rsp->ring_index = cur_ring_index;
4110c019cd65SQuinn Tran
4111fac28079SQuinn Tran ql_dbg(ql_dbg_init, vha, 0x5091,
4112fac28079SQuinn Tran "Defer processing ELS opcode %#x...\n",
4113fac28079SQuinn Tran purex_entry->els_frame_payload[3]);
4114fac28079SQuinn Tran return;
4115fac28079SQuinn Tran }
4116fac28079SQuinn Tran qla24xx_auth_els(vha, (void **)&pkt, &rsp);
4117fac28079SQuinn Tran break;
41189f2475feSShyam Sundar default:
41199f2475feSShyam Sundar ql_log(ql_log_warn, vha, 0x509c,
41209f2475feSShyam Sundar "Discarding ELS Request opcode 0x%x\n",
41219f2475feSShyam Sundar purex_entry->els_frame_payload[3]);
41229f2475feSShyam Sundar }
41239f2475feSShyam Sundar break;
4124dd30706eSQuinn Tran case SA_UPDATE_IOCB_TYPE:
4125dd30706eSQuinn Tran qla28xx_sa_update_iocb_entry(vha, rsp->req,
4126dd30706eSQuinn Tran (struct sa_update_28xx *)pkt);
4127dd30706eSQuinn Tran break;
4128875386b9SManish Rangankar case PT_LS4_UNSOL:
4129875386b9SManish Rangankar p = (void *)pkt;
4130875386b9SManish Rangankar if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt, rsp_in)) {
4131875386b9SManish Rangankar rsp->ring_ptr = (response_t *)pkt;
4132875386b9SManish Rangankar rsp->ring_index = cur_ring_index;
4133dd30706eSQuinn Tran
4134875386b9SManish Rangankar ql_dbg(ql_dbg_init, vha, 0x2124,
4135875386b9SManish Rangankar "Defer processing UNSOL LS req opcode %#x...\n",
4136875386b9SManish Rangankar p->payload[0]);
4137875386b9SManish Rangankar return;
4138875386b9SManish Rangankar }
4139875386b9SManish Rangankar qla2xxx_process_purls_iocb((void **)&pkt, &rsp);
4140875386b9SManish Rangankar break;
41419a853f71SAndrew Vasquez default:
41429a853f71SAndrew Vasquez /* Type Not Supported. */
41437c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5042,
41449f2475feSShyam Sundar "Received unknown response pkt type 0x%x entry status=%x.\n",
41457c3df132SSaurav Kashyap pkt->entry_type, pkt->entry_status);
41469a853f71SAndrew Vasquez break;
41479a853f71SAndrew Vasquez }
41489a853f71SAndrew Vasquez ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
41499a853f71SAndrew Vasquez wmb();
41509a853f71SAndrew Vasquez }
41519a853f71SAndrew Vasquez
41529a853f71SAndrew Vasquez /* Adjust ring index */
41537ec0effdSAtul Deshmukh if (IS_P3P_TYPE(ha)) {
4154a9083016SGiridhar Malavali struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
4155bd432bb5SBart Van Assche
415604474d3aSBart Van Assche wrt_reg_dword(®->rsp_q_out[0], rsp->ring_index);
4157726b8548SQuinn Tran } else {
415804474d3aSBart Van Assche wrt_reg_dword(rsp->rsp_q_out, rsp->ring_index);
41599a853f71SAndrew Vasquez }
4160726b8548SQuinn Tran }
41619a853f71SAndrew Vasquez
416205236a05SAndrew Vasquez static void
qla2xxx_check_risc_status(scsi_qla_host_t * vha)4163e315cd28SAnirban Chakraborty qla2xxx_check_risc_status(scsi_qla_host_t *vha)
416405236a05SAndrew Vasquez {
416505236a05SAndrew Vasquez int rval;
416605236a05SAndrew Vasquez uint32_t cnt;
4167e315cd28SAnirban Chakraborty struct qla_hw_data *ha = vha->hw;
416805236a05SAndrew Vasquez struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
416905236a05SAndrew Vasquez
4170f73cb695SChad Dupuis if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
4171ecc89f25SJoe Carnuccio !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
417205236a05SAndrew Vasquez return;
417305236a05SAndrew Vasquez
417405236a05SAndrew Vasquez rval = QLA_SUCCESS;
417504474d3aSBart Van Assche wrt_reg_dword(®->iobase_addr, 0x7C00);
417604474d3aSBart Van Assche rd_reg_dword(®->iobase_addr);
417704474d3aSBart Van Assche wrt_reg_dword(®->iobase_window, 0x0001);
417804474d3aSBart Van Assche for (cnt = 10000; (rd_reg_dword(®->iobase_window) & BIT_0) == 0 &&
417905236a05SAndrew Vasquez rval == QLA_SUCCESS; cnt--) {
418005236a05SAndrew Vasquez if (cnt) {
418104474d3aSBart Van Assche wrt_reg_dword(®->iobase_window, 0x0001);
418205236a05SAndrew Vasquez udelay(10);
418305236a05SAndrew Vasquez } else
418405236a05SAndrew Vasquez rval = QLA_FUNCTION_TIMEOUT;
418505236a05SAndrew Vasquez }
418605236a05SAndrew Vasquez if (rval == QLA_SUCCESS)
418705236a05SAndrew Vasquez goto next_test;
418805236a05SAndrew Vasquez
4189b2ec76c5SBart Van Assche rval = QLA_SUCCESS;
419004474d3aSBart Van Assche wrt_reg_dword(®->iobase_window, 0x0003);
419104474d3aSBart Van Assche for (cnt = 100; (rd_reg_dword(®->iobase_window) & BIT_0) == 0 &&
419205236a05SAndrew Vasquez rval == QLA_SUCCESS; cnt--) {
419305236a05SAndrew Vasquez if (cnt) {
419404474d3aSBart Van Assche wrt_reg_dword(®->iobase_window, 0x0003);
419505236a05SAndrew Vasquez udelay(10);
419605236a05SAndrew Vasquez } else
419705236a05SAndrew Vasquez rval = QLA_FUNCTION_TIMEOUT;
419805236a05SAndrew Vasquez }
419905236a05SAndrew Vasquez if (rval != QLA_SUCCESS)
420005236a05SAndrew Vasquez goto done;
420105236a05SAndrew Vasquez
420205236a05SAndrew Vasquez next_test:
420304474d3aSBart Van Assche if (rd_reg_dword(®->iobase_c8) & BIT_3)
42047c3df132SSaurav Kashyap ql_log(ql_log_info, vha, 0x504c,
42057c3df132SSaurav Kashyap "Additional code -- 0x55AA.\n");
420605236a05SAndrew Vasquez
420705236a05SAndrew Vasquez done:
420804474d3aSBart Van Assche wrt_reg_dword(®->iobase_window, 0x0000);
420904474d3aSBart Van Assche rd_reg_dword(®->iobase_window);
421005236a05SAndrew Vasquez }
421105236a05SAndrew Vasquez
42129a853f71SAndrew Vasquez /**
42136246b8a1SGiridhar Malavali * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP24xx.
4214807eb907SBart Van Assche * @irq: interrupt number
42159a853f71SAndrew Vasquez * @dev_id: SCSI driver HA context
42169a853f71SAndrew Vasquez *
42179a853f71SAndrew Vasquez * Called by system whenever the host adapter generates an interrupt.
42189a853f71SAndrew Vasquez *
42199a853f71SAndrew Vasquez * Returns handled flag.
42209a853f71SAndrew Vasquez */
42219a853f71SAndrew Vasquez irqreturn_t
qla24xx_intr_handler(int irq,void * dev_id)42227d12e780SDavid Howells qla24xx_intr_handler(int irq, void *dev_id)
42239a853f71SAndrew Vasquez {
4224e315cd28SAnirban Chakraborty scsi_qla_host_t *vha;
4225e315cd28SAnirban Chakraborty struct qla_hw_data *ha;
42269a853f71SAndrew Vasquez struct device_reg_24xx __iomem *reg;
42279a853f71SAndrew Vasquez int status;
42289a853f71SAndrew Vasquez unsigned long iter;
42299a853f71SAndrew Vasquez uint32_t stat;
42309a853f71SAndrew Vasquez uint32_t hccr;
42317d613ac6SSantosh Vernekar uint16_t mb[8];
4232e315cd28SAnirban Chakraborty struct rsp_que *rsp;
423343fac4d9SAnirban Chakraborty unsigned long flags;
42341073daa4SQuinn Tran bool process_atio = false;
42359a853f71SAndrew Vasquez
4236e315cd28SAnirban Chakraborty rsp = (struct rsp_que *) dev_id;
4237e315cd28SAnirban Chakraborty if (!rsp) {
42383256b435SChad Dupuis ql_log(ql_log_info, NULL, 0x5059,
42393256b435SChad Dupuis "%s: NULL response queue pointer.\n", __func__);
42409a853f71SAndrew Vasquez return IRQ_NONE;
42419a853f71SAndrew Vasquez }
42429a853f71SAndrew Vasquez
4243e315cd28SAnirban Chakraborty ha = rsp->hw;
42449a853f71SAndrew Vasquez reg = &ha->iobase->isp24;
42459a853f71SAndrew Vasquez status = 0;
42469a853f71SAndrew Vasquez
424785880801SAndrew Vasquez if (unlikely(pci_channel_offline(ha->pdev)))
424885880801SAndrew Vasquez return IRQ_HANDLED;
424985880801SAndrew Vasquez
425043fac4d9SAnirban Chakraborty spin_lock_irqsave(&ha->hardware_lock, flags);
42512afa19a9SAnirban Chakraborty vha = pci_get_drvdata(ha->pdev);
42529a853f71SAndrew Vasquez for (iter = 50; iter--; ) {
425304474d3aSBart Van Assche stat = rd_reg_dword(®->host_status);
4254c821e0d5SJoe Lawrence if (qla2x00_check_reg32_for_disconnect(vha, stat))
4255f3ddac19SChad Dupuis break;
42569a853f71SAndrew Vasquez if (stat & HSRX_RISC_PAUSED) {
425785880801SAndrew Vasquez if (unlikely(pci_channel_offline(ha->pdev)))
425814e660e6SSeokmann Ju break;
425914e660e6SSeokmann Ju
426004474d3aSBart Van Assche hccr = rd_reg_dword(®->hccr);
42619a853f71SAndrew Vasquez
42627c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x504b,
42637c3df132SSaurav Kashyap "RISC paused -- HCCR=%x, Dumping firmware.\n",
42647c3df132SSaurav Kashyap hccr);
426505236a05SAndrew Vasquez
4266e315cd28SAnirban Chakraborty qla2xxx_check_risc_status(vha);
426705236a05SAndrew Vasquez
42688ae17876SBart Van Assche ha->isp_ops->fw_dump(vha);
4269e315cd28SAnirban Chakraborty set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
42709a853f71SAndrew Vasquez break;
42719a853f71SAndrew Vasquez } else if ((stat & HSRX_RISC_INT) == 0)
42729a853f71SAndrew Vasquez break;
42739a853f71SAndrew Vasquez
42749a853f71SAndrew Vasquez switch (stat & 0xff) {
4275fafbda9fSArun Easi case INTR_ROM_MB_SUCCESS:
4276fafbda9fSArun Easi case INTR_ROM_MB_FAILED:
4277fafbda9fSArun Easi case INTR_MB_SUCCESS:
4278fafbda9fSArun Easi case INTR_MB_FAILED:
4279e315cd28SAnirban Chakraborty qla24xx_mbx_completion(vha, MSW(stat));
42809a853f71SAndrew Vasquez status |= MBX_INTERRUPT;
42819a853f71SAndrew Vasquez
42829a853f71SAndrew Vasquez break;
4283fafbda9fSArun Easi case INTR_ASYNC_EVENT:
42849a853f71SAndrew Vasquez mb[0] = MSW(stat);
428504474d3aSBart Van Assche mb[1] = rd_reg_word(®->mailbox1);
428604474d3aSBart Van Assche mb[2] = rd_reg_word(®->mailbox2);
428704474d3aSBart Van Assche mb[3] = rd_reg_word(®->mailbox3);
428873208dfdSAnirban Chakraborty qla2x00_async_event(vha, rsp, mb);
42899a853f71SAndrew Vasquez break;
4290fafbda9fSArun Easi case INTR_RSP_QUE_UPDATE:
4291fafbda9fSArun Easi case INTR_RSP_QUE_UPDATE_83XX:
42922afa19a9SAnirban Chakraborty qla24xx_process_response_queue(vha, rsp);
42939a853f71SAndrew Vasquez break;
4294c9558869SHimanshu Madhani case INTR_ATIO_QUE_UPDATE_27XX:
42951073daa4SQuinn Tran case INTR_ATIO_QUE_UPDATE:
42961073daa4SQuinn Tran process_atio = true;
42972d70c103SNicholas Bellinger break;
42981073daa4SQuinn Tran case INTR_ATIO_RSP_QUE_UPDATE:
42991073daa4SQuinn Tran process_atio = true;
43002d70c103SNicholas Bellinger qla24xx_process_response_queue(vha, rsp);
43012d70c103SNicholas Bellinger break;
43029a853f71SAndrew Vasquez default:
43037c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x504f,
43047c3df132SSaurav Kashyap "Unrecognized interrupt type (%d).\n", stat * 0xff);
43059a853f71SAndrew Vasquez break;
43069a853f71SAndrew Vasquez }
430704474d3aSBart Van Assche wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
430804474d3aSBart Van Assche rd_reg_dword_relaxed(®->hccr);
4309cb860bbdSGiridhar Malavali if (unlikely(IS_QLA83XX(ha) && (ha->pdev->revision == 1)))
4310cb860bbdSGiridhar Malavali ndelay(3500);
43119a853f71SAndrew Vasquez }
431236439832Sgurinder.shergill@hp.com qla2x00_handle_mbx_completion(ha, status);
431343fac4d9SAnirban Chakraborty spin_unlock_irqrestore(&ha->hardware_lock, flags);
43149a853f71SAndrew Vasquez
43151073daa4SQuinn Tran if (process_atio) {
43161073daa4SQuinn Tran spin_lock_irqsave(&ha->tgt.atio_lock, flags);
43171073daa4SQuinn Tran qlt_24xx_process_atio_queue(vha, 0);
43181073daa4SQuinn Tran spin_unlock_irqrestore(&ha->tgt.atio_lock, flags);
43191073daa4SQuinn Tran }
43201073daa4SQuinn Tran
43219a853f71SAndrew Vasquez return IRQ_HANDLED;
43229a853f71SAndrew Vasquez }
43239a853f71SAndrew Vasquez
4324a8488abeSAndrew Vasquez static irqreturn_t
qla24xx_msix_rsp_q(int irq,void * dev_id)4325a8488abeSAndrew Vasquez qla24xx_msix_rsp_q(int irq, void *dev_id)
4326a8488abeSAndrew Vasquez {
4327e315cd28SAnirban Chakraborty struct qla_hw_data *ha;
4328e315cd28SAnirban Chakraborty struct rsp_que *rsp;
4329a8488abeSAndrew Vasquez struct device_reg_24xx __iomem *reg;
43302afa19a9SAnirban Chakraborty struct scsi_qla_host *vha;
43310f19bc68SXiaotian Feng unsigned long flags;
4332a8488abeSAndrew Vasquez
4333e315cd28SAnirban Chakraborty rsp = (struct rsp_que *) dev_id;
4334e315cd28SAnirban Chakraborty if (!rsp) {
43353256b435SChad Dupuis ql_log(ql_log_info, NULL, 0x505a,
43363256b435SChad Dupuis "%s: NULL response queue pointer.\n", __func__);
4337e315cd28SAnirban Chakraborty return IRQ_NONE;
4338e315cd28SAnirban Chakraborty }
4339e315cd28SAnirban Chakraborty ha = rsp->hw;
4340a8488abeSAndrew Vasquez reg = &ha->iobase->isp24;
4341a8488abeSAndrew Vasquez
43420f19bc68SXiaotian Feng spin_lock_irqsave(&ha->hardware_lock, flags);
4343a8488abeSAndrew Vasquez
4344a67093d4SAnirban Chakraborty vha = pci_get_drvdata(ha->pdev);
43452afa19a9SAnirban Chakraborty qla24xx_process_response_queue(vha, rsp);
43463155754aSAnirban Chakraborty if (!ha->flags.disable_msix_handshake) {
434704474d3aSBart Van Assche wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
434804474d3aSBart Van Assche rd_reg_dword_relaxed(®->hccr);
4349eb94114bSAnirban Chakraborty }
43500f19bc68SXiaotian Feng spin_unlock_irqrestore(&ha->hardware_lock, flags);
435173208dfdSAnirban Chakraborty
435273208dfdSAnirban Chakraborty return IRQ_HANDLED;
435373208dfdSAnirban Chakraborty }
435473208dfdSAnirban Chakraborty
435573208dfdSAnirban Chakraborty static irqreturn_t
qla24xx_msix_default(int irq,void * dev_id)4356a8488abeSAndrew Vasquez qla24xx_msix_default(int irq, void *dev_id)
4357a8488abeSAndrew Vasquez {
4358e315cd28SAnirban Chakraborty scsi_qla_host_t *vha;
4359e315cd28SAnirban Chakraborty struct qla_hw_data *ha;
4360e315cd28SAnirban Chakraborty struct rsp_que *rsp;
4361a8488abeSAndrew Vasquez struct device_reg_24xx __iomem *reg;
4362a8488abeSAndrew Vasquez int status;
4363a8488abeSAndrew Vasquez uint32_t stat;
4364a8488abeSAndrew Vasquez uint32_t hccr;
43657d613ac6SSantosh Vernekar uint16_t mb[8];
43660f19bc68SXiaotian Feng unsigned long flags;
43671073daa4SQuinn Tran bool process_atio = false;
4368a8488abeSAndrew Vasquez
4369e315cd28SAnirban Chakraborty rsp = (struct rsp_que *) dev_id;
4370e315cd28SAnirban Chakraborty if (!rsp) {
43713256b435SChad Dupuis ql_log(ql_log_info, NULL, 0x505c,
43723256b435SChad Dupuis "%s: NULL response queue pointer.\n", __func__);
4373e315cd28SAnirban Chakraborty return IRQ_NONE;
4374e315cd28SAnirban Chakraborty }
4375e315cd28SAnirban Chakraborty ha = rsp->hw;
4376a8488abeSAndrew Vasquez reg = &ha->iobase->isp24;
4377a8488abeSAndrew Vasquez status = 0;
4378a8488abeSAndrew Vasquez
43790f19bc68SXiaotian Feng spin_lock_irqsave(&ha->hardware_lock, flags);
43802afa19a9SAnirban Chakraborty vha = pci_get_drvdata(ha->pdev);
438187f27015SAndrew Vasquez do {
438204474d3aSBart Van Assche stat = rd_reg_dword(®->host_status);
4383c821e0d5SJoe Lawrence if (qla2x00_check_reg32_for_disconnect(vha, stat))
4384f3ddac19SChad Dupuis break;
4385a8488abeSAndrew Vasquez if (stat & HSRX_RISC_PAUSED) {
438685880801SAndrew Vasquez if (unlikely(pci_channel_offline(ha->pdev)))
438714e660e6SSeokmann Ju break;
438814e660e6SSeokmann Ju
438904474d3aSBart Van Assche hccr = rd_reg_dword(®->hccr);
4390a8488abeSAndrew Vasquez
43917c3df132SSaurav Kashyap ql_log(ql_log_info, vha, 0x5050,
43927c3df132SSaurav Kashyap "RISC paused -- HCCR=%x, Dumping firmware.\n",
43937c3df132SSaurav Kashyap hccr);
439405236a05SAndrew Vasquez
4395e315cd28SAnirban Chakraborty qla2xxx_check_risc_status(vha);
4396dbf1f53cSSaurav Kashyap vha->hw_err_cnt++;
439705236a05SAndrew Vasquez
43988ae17876SBart Van Assche ha->isp_ops->fw_dump(vha);
4399e315cd28SAnirban Chakraborty set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
4400a8488abeSAndrew Vasquez break;
4401a8488abeSAndrew Vasquez } else if ((stat & HSRX_RISC_INT) == 0)
4402a8488abeSAndrew Vasquez break;
4403a8488abeSAndrew Vasquez
4404a8488abeSAndrew Vasquez switch (stat & 0xff) {
4405fafbda9fSArun Easi case INTR_ROM_MB_SUCCESS:
4406fafbda9fSArun Easi case INTR_ROM_MB_FAILED:
4407fafbda9fSArun Easi case INTR_MB_SUCCESS:
4408fafbda9fSArun Easi case INTR_MB_FAILED:
4409e315cd28SAnirban Chakraborty qla24xx_mbx_completion(vha, MSW(stat));
4410a8488abeSAndrew Vasquez status |= MBX_INTERRUPT;
4411a8488abeSAndrew Vasquez
4412a8488abeSAndrew Vasquez break;
4413fafbda9fSArun Easi case INTR_ASYNC_EVENT:
4414a8488abeSAndrew Vasquez mb[0] = MSW(stat);
441504474d3aSBart Van Assche mb[1] = rd_reg_word(®->mailbox1);
441604474d3aSBart Van Assche mb[2] = rd_reg_word(®->mailbox2);
441704474d3aSBart Van Assche mb[3] = rd_reg_word(®->mailbox3);
441873208dfdSAnirban Chakraborty qla2x00_async_event(vha, rsp, mb);
4419a8488abeSAndrew Vasquez break;
4420fafbda9fSArun Easi case INTR_RSP_QUE_UPDATE:
4421fafbda9fSArun Easi case INTR_RSP_QUE_UPDATE_83XX:
44222afa19a9SAnirban Chakraborty qla24xx_process_response_queue(vha, rsp);
4423a8488abeSAndrew Vasquez break;
4424c9558869SHimanshu Madhani case INTR_ATIO_QUE_UPDATE_27XX:
44251073daa4SQuinn Tran case INTR_ATIO_QUE_UPDATE:
44261073daa4SQuinn Tran process_atio = true;
44272d70c103SNicholas Bellinger break;
44281073daa4SQuinn Tran case INTR_ATIO_RSP_QUE_UPDATE:
44291073daa4SQuinn Tran process_atio = true;
44302d70c103SNicholas Bellinger qla24xx_process_response_queue(vha, rsp);
44312d70c103SNicholas Bellinger break;
4432a8488abeSAndrew Vasquez default:
44337c3df132SSaurav Kashyap ql_dbg(ql_dbg_async, vha, 0x5051,
44347c3df132SSaurav Kashyap "Unrecognized interrupt type (%d).\n", stat & 0xff);
4435a8488abeSAndrew Vasquez break;
4436a8488abeSAndrew Vasquez }
443704474d3aSBart Van Assche wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
443887f27015SAndrew Vasquez } while (0);
443936439832Sgurinder.shergill@hp.com qla2x00_handle_mbx_completion(ha, status);
44400f19bc68SXiaotian Feng spin_unlock_irqrestore(&ha->hardware_lock, flags);
4441a8488abeSAndrew Vasquez
44421073daa4SQuinn Tran if (process_atio) {
44431073daa4SQuinn Tran spin_lock_irqsave(&ha->tgt.atio_lock, flags);
44441073daa4SQuinn Tran qlt_24xx_process_atio_queue(vha, 0);
44451073daa4SQuinn Tran spin_unlock_irqrestore(&ha->tgt.atio_lock, flags);
44461073daa4SQuinn Tran }
44471073daa4SQuinn Tran
4448a8488abeSAndrew Vasquez return IRQ_HANDLED;
4449a8488abeSAndrew Vasquez }
4450a8488abeSAndrew Vasquez
4451d7459527SMichael Hernandez irqreturn_t
qla2xxx_msix_rsp_q(int irq,void * dev_id)4452d7459527SMichael Hernandez qla2xxx_msix_rsp_q(int irq, void *dev_id)
4453d7459527SMichael Hernandez {
4454d7459527SMichael Hernandez struct qla_hw_data *ha;
4455d7459527SMichael Hernandez struct qla_qpair *qpair;
44567b2a7396SAndrew Vasquez
44577b2a7396SAndrew Vasquez qpair = dev_id;
44587b2a7396SAndrew Vasquez if (!qpair) {
44597b2a7396SAndrew Vasquez ql_log(ql_log_info, NULL, 0x505b,
44607b2a7396SAndrew Vasquez "%s: NULL response queue pointer.\n", __func__);
44617b2a7396SAndrew Vasquez return IRQ_NONE;
44627b2a7396SAndrew Vasquez }
44637b2a7396SAndrew Vasquez ha = qpair->hw;
44647b2a7396SAndrew Vasquez
4465*59f10a05SNilesh Javali queue_work(ha->wq, &qpair->q_work);
44667b2a7396SAndrew Vasquez
44677b2a7396SAndrew Vasquez return IRQ_HANDLED;
44687b2a7396SAndrew Vasquez }
44697b2a7396SAndrew Vasquez
44707b2a7396SAndrew Vasquez irqreturn_t
qla2xxx_msix_rsp_q_hs(int irq,void * dev_id)44717b2a7396SAndrew Vasquez qla2xxx_msix_rsp_q_hs(int irq, void *dev_id)
44727b2a7396SAndrew Vasquez {
44737b2a7396SAndrew Vasquez struct qla_hw_data *ha;
44747b2a7396SAndrew Vasquez struct qla_qpair *qpair;
4475d7459527SMichael Hernandez struct device_reg_24xx __iomem *reg;
4476d7459527SMichael Hernandez unsigned long flags;
4477d7459527SMichael Hernandez
4478d7459527SMichael Hernandez qpair = dev_id;
4479d7459527SMichael Hernandez if (!qpair) {
4480d7459527SMichael Hernandez ql_log(ql_log_info, NULL, 0x505b,
4481d7459527SMichael Hernandez "%s: NULL response queue pointer.\n", __func__);
4482d7459527SMichael Hernandez return IRQ_NONE;
4483d7459527SMichael Hernandez }
4484d7459527SMichael Hernandez ha = qpair->hw;
4485d7459527SMichael Hernandez
4486d7459527SMichael Hernandez reg = &ha->iobase->isp24;
4487d7459527SMichael Hernandez spin_lock_irqsave(&ha->hardware_lock, flags);
448804474d3aSBart Van Assche wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
4489d7459527SMichael Hernandez spin_unlock_irqrestore(&ha->hardware_lock, flags);
4490d7459527SMichael Hernandez
4491*59f10a05SNilesh Javali queue_work(ha->wq, &qpair->q_work);
4492d7459527SMichael Hernandez
4493d7459527SMichael Hernandez return IRQ_HANDLED;
4494d7459527SMichael Hernandez }
4495d7459527SMichael Hernandez
4496a8488abeSAndrew Vasquez /* Interrupt handling helpers. */
4497a8488abeSAndrew Vasquez
4498a8488abeSAndrew Vasquez struct qla_init_msix_entry {
4499a8488abeSAndrew Vasquez const char *name;
4500476834c2SJeff Garzik irq_handler_t handler;
4501a8488abeSAndrew Vasquez };
4502a8488abeSAndrew Vasquez
450344a8f954SNicolas Iooss static const struct qla_init_msix_entry msix_entries[] = {
4504e326d22aSQuinn Tran { "default", qla24xx_msix_default },
4505e326d22aSQuinn Tran { "rsp_q", qla24xx_msix_rsp_q },
4506e326d22aSQuinn Tran { "atio_q", qla83xx_msix_atio_q },
4507e326d22aSQuinn Tran { "qpair_multiq", qla2xxx_msix_rsp_q },
45087b2a7396SAndrew Vasquez { "qpair_multiq_hs", qla2xxx_msix_rsp_q_hs },
4509aa230bc5SArun Easi };
4510aa230bc5SArun Easi
451144a8f954SNicolas Iooss static const struct qla_init_msix_entry qla82xx_msix_entries[] = {
45122afa19a9SAnirban Chakraborty { "qla2xxx (default)", qla82xx_msix_default },
45132afa19a9SAnirban Chakraborty { "qla2xxx (rsp_q)", qla82xx_msix_rsp_q },
451468ca949cSAnirban Chakraborty };
4515a8488abeSAndrew Vasquez
4516a8488abeSAndrew Vasquez static int
qla24xx_enable_msix(struct qla_hw_data * ha,struct rsp_que * rsp)451773208dfdSAnirban Chakraborty qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
4518a8488abeSAndrew Vasquez {
4519a8488abeSAndrew Vasquez int i, ret;
4520a8488abeSAndrew Vasquez struct qla_msix_entry *qentry;
45217c3df132SSaurav Kashyap scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
452267f2db87SMichael Hernandez int min_vecs = QLA_BASE_VECTORS;
452317e5fc58SChristoph Hellwig struct irq_affinity desc = {
452417e5fc58SChristoph Hellwig .pre_vectors = QLA_BASE_VECTORS,
452517e5fc58SChristoph Hellwig };
4526a8488abeSAndrew Vasquez
4527c9558869SHimanshu Madhani if (QLA_TGT_MODE_ENABLED() && (ql2xenablemsix != 0) &&
4528c9558869SHimanshu Madhani IS_ATIO_MSIX_CAPABLE(ha)) {
452917e5fc58SChristoph Hellwig desc.pre_vectors++;
453067f2db87SMichael Hernandez min_vecs++;
453167f2db87SMichael Hernandez }
453217e5fc58SChristoph Hellwig
4533f3e02695SGiridhar Malavali if (USER_CTRL_IRQ(ha) || !ha->mqiobase) {
453409620eebSQuinn Tran /* user wants to control IRQ setting for target mode */
453509620eebSQuinn Tran ret = pci_alloc_irq_vectors(ha->pdev, min_vecs,
4536f02d4086SRoman Bolshakov min((u16)ha->msix_count, (u16)(num_online_cpus() + min_vecs)),
4537a6dcfe08SQuinn Tran PCI_IRQ_MSIX);
453809620eebSQuinn Tran } else
453967f2db87SMichael Hernandez ret = pci_alloc_irq_vectors_affinity(ha->pdev, min_vecs,
4540f02d4086SRoman Bolshakov min((u16)ha->msix_count, (u16)(num_online_cpus() + min_vecs)),
4541a6dcfe08SQuinn Tran PCI_IRQ_MSIX | PCI_IRQ_AFFINITY,
454217e5fc58SChristoph Hellwig &desc);
454317e5fc58SChristoph Hellwig
454484e32a06SAlexander Gordeev if (ret < 0) {
45457c3df132SSaurav Kashyap ql_log(ql_log_fatal, vha, 0x00c7,
45467c3df132SSaurav Kashyap "MSI-X: Failed to enable support, "
45477c3df132SSaurav Kashyap "giving up -- %d/%d.\n",
454873208dfdSAnirban Chakraborty ha->msix_count, ret);
454973208dfdSAnirban Chakraborty goto msix_out;
455084e32a06SAlexander Gordeev } else if (ret < ha->msix_count) {
4551da48b824SHimanshu Madhani ql_log(ql_log_info, vha, 0x00c6,
4552da48b824SHimanshu Madhani "MSI-X: Using %d vectors\n", ret);
455384e32a06SAlexander Gordeev ha->msix_count = ret;
4554d7459527SMichael Hernandez /* Recalculate queue values */
4555c38d1bafSHimanshu Madhani if (ha->mqiobase && (ql2xmqsupport || ql2xnvmeenable)) {
4556d7459527SMichael Hernandez ha->max_req_queues = ha->msix_count - 1;
4557d7459527SMichael Hernandez
4558d7459527SMichael Hernandez /* ATIOQ needs 1 vector. That's 1 less QPair */
4559d7459527SMichael Hernandez if (QLA_TGT_MODE_ENABLED())
4560d7459527SMichael Hernandez ha->max_req_queues--;
4561d7459527SMichael Hernandez
4562d7459527SMichael Hernandez ha->max_rsp_queues = ha->max_req_queues;
4563d7459527SMichael Hernandez
4564d7459527SMichael Hernandez ha->max_qpairs = ha->max_req_queues - 1;
4565d7459527SMichael Hernandez ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0190,
4566d7459527SMichael Hernandez "Adjusted Max no of queues pairs: %d.\n", ha->max_qpairs);
4567d7459527SMichael Hernandez }
4568cb43285fSQuinn Tran }
4569f0783d43SMing Lei vha->irq_offset = desc.pre_vectors;
45706396bb22SKees Cook ha->msix_entries = kcalloc(ha->msix_count,
45716396bb22SKees Cook sizeof(struct qla_msix_entry),
45726396bb22SKees Cook GFP_KERNEL);
457373208dfdSAnirban Chakraborty if (!ha->msix_entries) {
45747c3df132SSaurav Kashyap ql_log(ql_log_fatal, vha, 0x00c8,
45757c3df132SSaurav Kashyap "Failed to allocate memory for ha->msix_entries.\n");
457673208dfdSAnirban Chakraborty ret = -ENOMEM;
457724afabdbSBart Van Assche goto free_irqs;
4578a8488abeSAndrew Vasquez }
4579a8488abeSAndrew Vasquez ha->flags.msix_enabled = 1;
4580a8488abeSAndrew Vasquez
458173208dfdSAnirban Chakraborty for (i = 0; i < ha->msix_count; i++) {
458273208dfdSAnirban Chakraborty qentry = &ha->msix_entries[i];
45834fa18345SMichael Hernandez qentry->vector = pci_irq_vector(ha->pdev, i);
45841d201c81SShreyas Deodhar qentry->vector_base0 = i;
45854fa18345SMichael Hernandez qentry->entry = i;
4586a8488abeSAndrew Vasquez qentry->have_irq = 0;
4587d7459527SMichael Hernandez qentry->in_use = 0;
45884fa18345SMichael Hernandez qentry->handle = NULL;
458973208dfdSAnirban Chakraborty }
459073208dfdSAnirban Chakraborty
45912afa19a9SAnirban Chakraborty /* Enable MSI-X vectors for the base queue */
459217e5fc58SChristoph Hellwig for (i = 0; i < QLA_BASE_VECTORS; i++) {
45932afa19a9SAnirban Chakraborty qentry = &ha->msix_entries[i];
45944fa18345SMichael Hernandez qentry->handle = rsp;
4595ef8d1d51SJohannes Thumshirn rsp->msix = qentry;
4596d7459527SMichael Hernandez scnprintf(qentry->name, sizeof(qentry->name),
4597e326d22aSQuinn Tran "qla2xxx%lu_%s", vha->host_no, msix_entries[i].name);
4598f324777eSChad Dupuis if (IS_P3P_TYPE(ha))
4599a9083016SGiridhar Malavali ret = request_irq(qentry->vector,
4600a9083016SGiridhar Malavali qla82xx_msix_entries[i].handler,
4601a9083016SGiridhar Malavali 0, qla82xx_msix_entries[i].name, rsp);
4602f324777eSChad Dupuis else
4603a9083016SGiridhar Malavali ret = request_irq(qentry->vector,
4604a9083016SGiridhar Malavali msix_entries[i].handler,
4605e326d22aSQuinn Tran 0, qentry->name, rsp);
4606f324777eSChad Dupuis if (ret)
4607f324777eSChad Dupuis goto msix_register_fail;
4608f324777eSChad Dupuis qentry->have_irq = 1;
4609093df737SQuinn Tran qentry->in_use = 1;
4610a9083016SGiridhar Malavali }
4611f324777eSChad Dupuis
4612f324777eSChad Dupuis /*
4613f324777eSChad Dupuis * If target mode is enable, also request the vector for the ATIO
4614f324777eSChad Dupuis * queue.
4615f324777eSChad Dupuis */
4616c9558869SHimanshu Madhani if (QLA_TGT_MODE_ENABLED() && (ql2xenablemsix != 0) &&
4617c9558869SHimanshu Madhani IS_ATIO_MSIX_CAPABLE(ha)) {
4618093df737SQuinn Tran qentry = &ha->msix_entries[QLA_ATIO_VECTOR];
4619ef8d1d51SJohannes Thumshirn rsp->msix = qentry;
4620d7459527SMichael Hernandez qentry->handle = rsp;
4621d7459527SMichael Hernandez scnprintf(qentry->name, sizeof(qentry->name),
4622e326d22aSQuinn Tran "qla2xxx%lu_%s", vha->host_no,
4623e326d22aSQuinn Tran msix_entries[QLA_ATIO_VECTOR].name);
4624093df737SQuinn Tran qentry->in_use = 1;
4625f324777eSChad Dupuis ret = request_irq(qentry->vector,
4626093df737SQuinn Tran msix_entries[QLA_ATIO_VECTOR].handler,
4627e326d22aSQuinn Tran 0, qentry->name, rsp);
4628f324777eSChad Dupuis qentry->have_irq = 1;
4629f324777eSChad Dupuis }
4630f324777eSChad Dupuis
4631f324777eSChad Dupuis msix_register_fail:
4632a8488abeSAndrew Vasquez if (ret) {
46337c3df132SSaurav Kashyap ql_log(ql_log_fatal, vha, 0x00cb,
46347c3df132SSaurav Kashyap "MSI-X: unable to register handler -- %x/%d.\n",
463573208dfdSAnirban Chakraborty qentry->vector, ret);
46364fa18345SMichael Hernandez qla2x00_free_irqs(vha);
46372afa19a9SAnirban Chakraborty ha->mqenable = 0;
4638a8488abeSAndrew Vasquez goto msix_out;
4639a8488abeSAndrew Vasquez }
464073208dfdSAnirban Chakraborty
464173208dfdSAnirban Chakraborty /* Enable MSI-X vector for response queue update for queue 0 */
46425304673bSQuinn Tran if (IS_MQUE_CAPABLE(ha) &&
46435304673bSQuinn Tran (ha->msixbase && ha->mqiobase && ha->max_qpairs))
46446246b8a1SGiridhar Malavali ha->mqenable = 1;
46455304673bSQuinn Tran else
46465304673bSQuinn Tran ha->mqenable = 0;
46475304673bSQuinn Tran
46487c3df132SSaurav Kashyap ql_dbg(ql_dbg_multiq, vha, 0xc005,
46497c3df132SSaurav Kashyap "mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n",
46507c3df132SSaurav Kashyap ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
46517c3df132SSaurav Kashyap ql_dbg(ql_dbg_init, vha, 0x0055,
46527c3df132SSaurav Kashyap "mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n",
46537c3df132SSaurav Kashyap ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
465473208dfdSAnirban Chakraborty
4655a8488abeSAndrew Vasquez msix_out:
4656a8488abeSAndrew Vasquez return ret;
465724afabdbSBart Van Assche
465824afabdbSBart Van Assche free_irqs:
465924afabdbSBart Van Assche pci_free_irq_vectors(ha->pdev);
466024afabdbSBart Van Assche goto msix_out;
4661a8488abeSAndrew Vasquez }
4662a8488abeSAndrew Vasquez
4663a8488abeSAndrew Vasquez int
qla2x00_request_irqs(struct qla_hw_data * ha,struct rsp_que * rsp)466473208dfdSAnirban Chakraborty qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
4665a8488abeSAndrew Vasquez {
46667fa3e239SSawan Chandak int ret = QLA_FUNCTION_FAILED;
4667f73cb695SChad Dupuis device_reg_t *reg = ha->iobase;
46687c3df132SSaurav Kashyap scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
4669a8488abeSAndrew Vasquez
4670a8488abeSAndrew Vasquez /* If possible, enable MSI-X. */
4671e7240af5SHimanshu Madhani if (ql2xenablemsix == 0 || (!IS_QLA2432(ha) && !IS_QLA2532(ha) &&
4672e7240af5SHimanshu Madhani !IS_QLA8432(ha) && !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) &&
4673ecc89f25SJoe Carnuccio !IS_QLAFX00(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)))
46746377a7aeSBen Hutchings goto skip_msi;
4675a8488abeSAndrew Vasquez
4676e7240af5SHimanshu Madhani if (ql2xenablemsix == 2)
4677e7240af5SHimanshu Madhani goto skip_msix;
4678e7240af5SHimanshu Madhani
4679da7429f9SAndrew Vasquez if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
4680da7429f9SAndrew Vasquez (ha->pdev->subsystem_device == 0x7040 ||
4681da7429f9SAndrew Vasquez ha->pdev->subsystem_device == 0x7041 ||
4682da7429f9SAndrew Vasquez ha->pdev->subsystem_device == 0x1705)) {
46837c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x0034,
4684da7429f9SAndrew Vasquez "MSI-X: Unsupported ISP 2432 SSVID/SSDID (0x%X,0x%X).\n",
4685da7429f9SAndrew Vasquez ha->pdev->subsystem_vendor,
46867c3df132SSaurav Kashyap ha->pdev->subsystem_device);
4687da7429f9SAndrew Vasquez goto skip_msi;
4688da7429f9SAndrew Vasquez }
4689da7429f9SAndrew Vasquez
469042cd4f5dSChad Dupuis if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX)) {
46917c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x0035,
46927c3df132SSaurav Kashyap "MSI-X; Unsupported ISP2432 (0x%X, 0x%X).\n",
469342cd4f5dSChad Dupuis ha->pdev->revision, QLA_MSIX_CHIP_REV_24XX);
46946377a7aeSBen Hutchings goto skip_msix;
46956377a7aeSBen Hutchings }
46966377a7aeSBen Hutchings
469773208dfdSAnirban Chakraborty ret = qla24xx_enable_msix(ha, rsp);
4698a8488abeSAndrew Vasquez if (!ret) {
46997c3df132SSaurav Kashyap ql_dbg(ql_dbg_init, vha, 0x0036,
47007c3df132SSaurav Kashyap "MSI-X: Enabled (0x%X, 0x%X).\n",
47017c3df132SSaurav Kashyap ha->chip_revision, ha->fw_attributes);
4702963b0fddSAndrew Vasquez goto clear_risc_ints;
4703a8488abeSAndrew Vasquez }
47047fa3e239SSawan Chandak
4705a8488abeSAndrew Vasquez skip_msix:
4706cbedb601SAndrew Vasquez
47077fa3e239SSawan Chandak ql_log(ql_log_info, vha, 0x0037,
470845dc8f2dSHuacai Chen "Falling back-to MSI mode -- ret=%d.\n", ret);
47097fa3e239SSawan Chandak
47103a03eb79SAndrew Vasquez if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
4711f73cb695SChad Dupuis !IS_QLA8001(ha) && !IS_P3P_TYPE(ha) && !IS_QLAFX00(ha) &&
4712ecc89f25SJoe Carnuccio !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
4713cbedb601SAndrew Vasquez goto skip_msi;
4714cbedb601SAndrew Vasquez
47154fa18345SMichael Hernandez ret = pci_alloc_irq_vectors(ha->pdev, 1, 1, PCI_IRQ_MSI);
471645dc8f2dSHuacai Chen if (ret > 0) {
47177c3df132SSaurav Kashyap ql_dbg(ql_dbg_init, vha, 0x0038,
47187c3df132SSaurav Kashyap "MSI: Enabled.\n");
4719cbedb601SAndrew Vasquez ha->flags.msi_enabled = 1;
4720a9083016SGiridhar Malavali } else
47217c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x0039,
472245dc8f2dSHuacai Chen "Falling back-to INTa mode -- ret=%d.\n", ret);
47237fa3e239SSawan Chandak skip_msi:
4724a033b655SGiridhar Malavali
4725a033b655SGiridhar Malavali /* Skip INTx on ISP82xx. */
4726a033b655SGiridhar Malavali if (!ha->flags.msi_enabled && IS_QLA82XX(ha))
4727a033b655SGiridhar Malavali return QLA_FUNCTION_FAILED;
4728a033b655SGiridhar Malavali
4729fd34f556SAndrew Vasquez ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
47307992abfcSMike Hernandez ha->flags.msi_enabled ? 0 : IRQF_SHARED,
47317992abfcSMike Hernandez QLA2XXX_DRIVER_NAME, rsp);
4732963b0fddSAndrew Vasquez if (ret) {
47337c3df132SSaurav Kashyap ql_log(ql_log_warn, vha, 0x003a,
4734a8488abeSAndrew Vasquez "Failed to reserve interrupt %d already in use.\n",
4735a8488abeSAndrew Vasquez ha->pdev->irq);
4736963b0fddSAndrew Vasquez goto fail;
47378ae6d9c7SGiridhar Malavali } else if (!ha->flags.msi_enabled) {
473868d91cbdSSaurav Kashyap ql_dbg(ql_dbg_init, vha, 0x0125,
473968d91cbdSSaurav Kashyap "INTa mode: Enabled.\n");
47408ae6d9c7SGiridhar Malavali ha->flags.mr_intr_valid = 1;
47414a0a542fSSaurav Kashyap /* Set max_qpair to 0, as MSI-X and MSI in not enabled */
47424a0a542fSSaurav Kashyap ha->max_qpairs = 0;
47438ae6d9c7SGiridhar Malavali }
47447992abfcSMike Hernandez
4745963b0fddSAndrew Vasquez clear_risc_ints:
47464bb2efc4SJoe Carnuccio if (IS_FWI2_CAPABLE(ha) || IS_QLAFX00(ha))
47474bb2efc4SJoe Carnuccio goto fail;
4748a8488abeSAndrew Vasquez
4749c6952483SAndrew Vasquez spin_lock_irq(&ha->hardware_lock);
475004474d3aSBart Van Assche wrt_reg_word(®->isp.semaphore, 0);
4751c6952483SAndrew Vasquez spin_unlock_irq(&ha->hardware_lock);
4752963b0fddSAndrew Vasquez
4753963b0fddSAndrew Vasquez fail:
4754a8488abeSAndrew Vasquez return ret;
4755a8488abeSAndrew Vasquez }
4756a8488abeSAndrew Vasquez
4757a8488abeSAndrew Vasquez void
qla2x00_free_irqs(scsi_qla_host_t * vha)4758e315cd28SAnirban Chakraborty qla2x00_free_irqs(scsi_qla_host_t *vha)
4759a8488abeSAndrew Vasquez {
4760e315cd28SAnirban Chakraborty struct qla_hw_data *ha = vha->hw;
47619a347ff4SChad Dupuis struct rsp_que *rsp;
47624fa18345SMichael Hernandez struct qla_msix_entry *qentry;
47634fa18345SMichael Hernandez int i;
47649a347ff4SChad Dupuis
47659a347ff4SChad Dupuis /*
47669a347ff4SChad Dupuis * We need to check that ha->rsp_q_map is valid in case we are called
47679a347ff4SChad Dupuis * from a probe failure context.
47689a347ff4SChad Dupuis */
47699a347ff4SChad Dupuis if (!ha->rsp_q_map || !ha->rsp_q_map[0])
477027873de9SBart Van Assche goto free_irqs;
47719a347ff4SChad Dupuis rsp = ha->rsp_q_map[0];
4772a8488abeSAndrew Vasquez
47734fa18345SMichael Hernandez if (ha->flags.msix_enabled) {
47744fa18345SMichael Hernandez for (i = 0; i < ha->msix_count; i++) {
47754fa18345SMichael Hernandez qentry = &ha->msix_entries[i];
47764fa18345SMichael Hernandez if (qentry->have_irq) {
47774fa18345SMichael Hernandez irq_set_affinity_notifier(qentry->vector, NULL);
47784fa18345SMichael Hernandez free_irq(pci_irq_vector(ha->pdev, i), qentry->handle);
47794fa18345SMichael Hernandez }
47804fa18345SMichael Hernandez }
47814fa18345SMichael Hernandez kfree(ha->msix_entries);
47824fa18345SMichael Hernandez ha->msix_entries = NULL;
47834fa18345SMichael Hernandez ha->flags.msix_enabled = 0;
47844fa18345SMichael Hernandez ql_dbg(ql_dbg_init, vha, 0x0042,
47854fa18345SMichael Hernandez "Disabled MSI-X.\n");
47864fa18345SMichael Hernandez } else {
47874fa18345SMichael Hernandez free_irq(pci_irq_vector(ha->pdev, 0), rsp);
4788a8488abeSAndrew Vasquez }
4789e315cd28SAnirban Chakraborty
479027873de9SBart Van Assche free_irqs:
47914fa18345SMichael Hernandez pci_free_irq_vectors(ha->pdev);
47921da177e4SLinus Torvalds }
479373208dfdSAnirban Chakraborty
qla25xx_request_irq(struct qla_hw_data * ha,struct qla_qpair * qpair,struct qla_msix_entry * msix,int vector_type)4794d7459527SMichael Hernandez int qla25xx_request_irq(struct qla_hw_data *ha, struct qla_qpair *qpair,
4795d7459527SMichael Hernandez struct qla_msix_entry *msix, int vector_type)
479673208dfdSAnirban Chakraborty {
479744a8f954SNicolas Iooss const struct qla_init_msix_entry *intr = &msix_entries[vector_type];
47987c3df132SSaurav Kashyap scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
479973208dfdSAnirban Chakraborty int ret;
480073208dfdSAnirban Chakraborty
4801d7459527SMichael Hernandez scnprintf(msix->name, sizeof(msix->name),
4802d7459527SMichael Hernandez "qla2xxx%lu_qpair%d", vha->host_no, qpair->id);
4803d7459527SMichael Hernandez ret = request_irq(msix->vector, intr->handler, 0, msix->name, qpair);
480473208dfdSAnirban Chakraborty if (ret) {
48057c3df132SSaurav Kashyap ql_log(ql_log_fatal, vha, 0x00e6,
480673208dfdSAnirban Chakraborty "MSI-X: Unable to register handler -- %x/%d.\n",
480773208dfdSAnirban Chakraborty msix->vector, ret);
480873208dfdSAnirban Chakraborty return ret;
480973208dfdSAnirban Chakraborty }
481073208dfdSAnirban Chakraborty msix->have_irq = 1;
4811d7459527SMichael Hernandez msix->handle = qpair;
48121d201c81SShreyas Deodhar qla_mapq_init_qp_cpu_map(ha, msix, qpair);
481373208dfdSAnirban Chakraborty return ret;
481473208dfdSAnirban Chakraborty }
4815