blob: 40385bc1d1fa45097656f4adb7fd2319253b5008 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Andrew Vasquezfa90c542005-10-27 11:10:08 -07002 * QLogic Fibre Channel HBA Driver
Armen Baloyanbd21eaf2014-04-11 16:54:24 -04003 * Copyright (c) 2003-2014 QLogic Corporation
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Andrew Vasquezfa90c542005-10-27 11:10:08 -07005 * See LICENSE.qla2xxx for copyright and licensing details.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
7#include "qla_def.h"
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04008#include "qla_target.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -07009
Andrew Vasquez05236a02007-09-20 14:07:37 -070010#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090011#include <linux/slab.h>
Quinn Trane326d222017-06-13 20:47:18 -070012#include <linux/cpu.h>
Bart Van Assche09ce66a2016-11-15 11:21:46 -080013#include <linux/t10-pi.h>
Andrew Vasquezdf7baa52006-10-13 09:33:39 -070014#include <scsi/scsi_tcq.h>
Giridhar Malavali9a069e12010-01-12 13:02:47 -080015#include <scsi/scsi_bsg_fc.h>
Arun Easibad75002010-05-04 15:01:30 -070016#include <scsi/scsi_eh.h>
Andrew Vasquezdf7baa52006-10-13 09:33:39 -070017
Linus Torvalds1da177e2005-04-16 15:20:36 -070018static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
Anirban Chakraborty73208df2008-12-09 16:45:39 -080019static void qla2x00_status_entry(scsi_qla_host_t *, struct rsp_que *, void *);
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -070020static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *);
Quinn Tranc5419e22017-06-13 20:47:16 -070021static int qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
Anirban Chakraborty73208df2008-12-09 16:45:39 -080022 sts_entry_t *);
Andrew Vasquez9a853f72005-07-06 10:31:27 -070023
Linus Torvalds1da177e2005-04-16 15:20:36 -070024/**
25 * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
26 * @irq:
27 * @dev_id: SCSI driver HA context
Linus Torvalds1da177e2005-04-16 15:20:36 -070028 *
29 * Called by system whenever the host adapter generates an interrupt.
30 *
31 * Returns handled flag.
32 */
33irqreturn_t
David Howells7d12e782006-10-05 14:55:46 +010034qla2100_intr_handler(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -070035{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -080036 scsi_qla_host_t *vha;
37 struct qla_hw_data *ha;
Andrew Vasquez3d716442005-07-06 10:30:26 -070038 struct device_reg_2xxx __iomem *reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -070039 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 unsigned long iter;
Seokmann Ju14e660e2007-09-20 14:07:36 -070041 uint16_t hccr;
Andrew Vasquez9a853f72005-07-06 10:31:27 -070042 uint16_t mb[4];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -080043 struct rsp_que *rsp;
Anirban Chakraborty43fac4d2009-06-10 13:55:11 -070044 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
Anirban Chakrabortye315cd22008-11-06 10:40:51 -080046 rsp = (struct rsp_que *) dev_id;
47 if (!rsp) {
Chad Dupuis3256b432012-02-09 11:15:47 -080048 ql_log(ql_log_info, NULL, 0x505d,
49 "%s: NULL response queue pointer.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 return (IRQ_NONE);
51 }
52
Anirban Chakrabortye315cd22008-11-06 10:40:51 -080053 ha = rsp->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -070054 reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 status = 0;
56
Anirban Chakraborty43fac4d2009-06-10 13:55:11 -070057 spin_lock_irqsave(&ha->hardware_lock, flags);
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -070058 vha = pci_get_drvdata(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 for (iter = 50; iter--; ) {
Seokmann Ju14e660e2007-09-20 14:07:36 -070060 hccr = RD_REG_WORD(&reg->hccr);
Joe Lawrencec821e0d2014-08-26 17:11:41 -040061 if (qla2x00_check_reg16_for_disconnect(vha, hccr))
Chad Dupuisf3ddac12013-10-30 03:38:16 -040062 break;
Seokmann Ju14e660e2007-09-20 14:07:36 -070063 if (hccr & HCCR_RISC_PAUSE) {
64 if (pci_channel_offline(ha->pdev))
65 break;
66
67 /*
68 * Issue a "HARD" reset in order for the RISC interrupt
Justin P. Mattocka06a0f82011-06-23 23:22:27 -070069 * bit to be cleared. Schedule a big hammer to get
Seokmann Ju14e660e2007-09-20 14:07:36 -070070 * out of the RISC PAUSED state.
71 */
72 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
73 RD_REG_WORD(&reg->hccr);
74
Anirban Chakrabortye315cd22008-11-06 10:40:51 -080075 ha->isp_ops->fw_dump(vha, 1);
76 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Seokmann Ju14e660e2007-09-20 14:07:36 -070077 break;
78 } else if ((RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 break;
80
81 if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
82 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
83 RD_REG_WORD(&reg->hccr);
84
85 /* Get mailbox data. */
Andrew Vasquez9a853f72005-07-06 10:31:27 -070086 mb[0] = RD_MAILBOX_REG(ha, reg, 0);
87 if (mb[0] > 0x3fff && mb[0] < 0x8000) {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -080088 qla2x00_mbx_completion(vha, mb[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 status |= MBX_INTERRUPT;
Andrew Vasquez9a853f72005-07-06 10:31:27 -070090 } else if (mb[0] > 0x7fff && mb[0] < 0xc000) {
91 mb[1] = RD_MAILBOX_REG(ha, reg, 1);
92 mb[2] = RD_MAILBOX_REG(ha, reg, 2);
93 mb[3] = RD_MAILBOX_REG(ha, reg, 3);
Anirban Chakraborty73208df2008-12-09 16:45:39 -080094 qla2x00_async_event(vha, rsp, mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 } else {
96 /*EMPTY*/
Saurav Kashyap7c3df132011-07-14 12:00:13 -070097 ql_dbg(ql_dbg_async, vha, 0x5025,
98 "Unrecognized interrupt type (%d).\n",
99 mb[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 }
101 /* Release mailbox registers. */
102 WRT_REG_WORD(&reg->semaphore, 0);
103 RD_REG_WORD(&reg->semaphore);
104 } else {
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800105 qla2x00_process_response_queue(rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
107 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
108 RD_REG_WORD(&reg->hccr);
109 }
110 }
gurinder.shergill@hp.com36439832013-04-23 10:13:17 -0700111 qla2x00_handle_mbx_completion(ha, status);
Anirban Chakraborty43fac4d2009-06-10 13:55:11 -0700112 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 return (IRQ_HANDLED);
115}
116
Chad Dupuisf3ddac12013-10-30 03:38:16 -0400117bool
Joe Lawrencec821e0d2014-08-26 17:11:41 -0400118qla2x00_check_reg32_for_disconnect(scsi_qla_host_t *vha, uint32_t reg)
Chad Dupuisf3ddac12013-10-30 03:38:16 -0400119{
120 /* Check for PCI disconnection */
Thadeu Lima de Souza Cascardoa30c2a32015-04-30 09:13:05 -0300121 if (reg == 0xffffffff && !pci_channel_offline(vha->hw->pdev)) {
Joe Lawrencebeb9e312014-08-26 17:12:14 -0400122 if (!test_and_set_bit(PFLG_DISCONNECTED, &vha->pci_flags) &&
Joe Lawrence6b383972014-08-26 17:12:29 -0400123 !test_bit(PFLG_DRIVER_REMOVING, &vha->pci_flags) &&
124 !test_bit(PFLG_DRIVER_PROBING, &vha->pci_flags)) {
Joe Lawrence232792b2014-08-26 17:12:01 -0400125 /*
126 * Schedule this (only once) on the default system
127 * workqueue so that all the adapter workqueues and the
128 * DPC thread can be shutdown cleanly.
129 */
130 schedule_work(&vha->hw->board_disable);
131 }
Chad Dupuisf3ddac12013-10-30 03:38:16 -0400132 return true;
133 } else
134 return false;
135}
136
Joe Lawrencec821e0d2014-08-26 17:11:41 -0400137bool
138qla2x00_check_reg16_for_disconnect(scsi_qla_host_t *vha, uint16_t reg)
139{
140 return qla2x00_check_reg32_for_disconnect(vha, 0xffff0000 | reg);
141}
142
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143/**
144 * qla2300_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
145 * @irq:
146 * @dev_id: SCSI driver HA context
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 *
148 * Called by system whenever the host adapter generates an interrupt.
149 *
150 * Returns handled flag.
151 */
152irqreturn_t
David Howells7d12e782006-10-05 14:55:46 +0100153qla2300_intr_handler(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800155 scsi_qla_host_t *vha;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700156 struct device_reg_2xxx __iomem *reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 unsigned long iter;
159 uint32_t stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 uint16_t hccr;
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700161 uint16_t mb[4];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800162 struct rsp_que *rsp;
163 struct qla_hw_data *ha;
Anirban Chakraborty43fac4d2009-06-10 13:55:11 -0700164 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800166 rsp = (struct rsp_que *) dev_id;
167 if (!rsp) {
Chad Dupuis3256b432012-02-09 11:15:47 -0800168 ql_log(ql_log_info, NULL, 0x5058,
169 "%s: NULL response queue pointer.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 return (IRQ_NONE);
171 }
172
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800173 ha = rsp->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700174 reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 status = 0;
176
Anirban Chakraborty43fac4d2009-06-10 13:55:11 -0700177 spin_lock_irqsave(&ha->hardware_lock, flags);
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -0700178 vha = pci_get_drvdata(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 for (iter = 50; iter--; ) {
180 stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
Joe Lawrencec821e0d2014-08-26 17:11:41 -0400181 if (qla2x00_check_reg32_for_disconnect(vha, stat))
Chad Dupuisf3ddac12013-10-30 03:38:16 -0400182 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 if (stat & HSR_RISC_PAUSED) {
Andrew Vasquez85880802009-12-15 21:29:46 -0800184 if (unlikely(pci_channel_offline(ha->pdev)))
Seokmann Ju14e660e2007-09-20 14:07:36 -0700185 break;
186
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 hccr = RD_REG_WORD(&reg->hccr);
Chad Dupuisf3ddac12013-10-30 03:38:16 -0400188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700190 ql_log(ql_log_warn, vha, 0x5026,
191 "Parity error -- HCCR=%x, Dumping "
192 "firmware.\n", hccr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 else
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700194 ql_log(ql_log_warn, vha, 0x5027,
195 "RISC paused -- HCCR=%x, Dumping "
196 "firmware.\n", hccr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197
198 /*
199 * Issue a "HARD" reset in order for the RISC
200 * interrupt bit to be cleared. Schedule a big
Justin P. Mattocka06a0f82011-06-23 23:22:27 -0700201 * hammer to get out of the RISC PAUSED state.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 */
203 WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
204 RD_REG_WORD(&reg->hccr);
Andrew Vasquez07f31802006-12-13 19:20:31 -0800205
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800206 ha->isp_ops->fw_dump(vha, 1);
207 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 break;
209 } else if ((stat & HSR_RISC_INT) == 0)
210 break;
211
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 switch (stat & 0xff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 case 0x1:
214 case 0x2:
215 case 0x10:
216 case 0x11:
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800217 qla2x00_mbx_completion(vha, MSW(stat));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 status |= MBX_INTERRUPT;
219
220 /* Release mailbox registers. */
221 WRT_REG_WORD(&reg->semaphore, 0);
222 break;
223 case 0x12:
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700224 mb[0] = MSW(stat);
225 mb[1] = RD_MAILBOX_REG(ha, reg, 1);
226 mb[2] = RD_MAILBOX_REG(ha, reg, 2);
227 mb[3] = RD_MAILBOX_REG(ha, reg, 3);
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800228 qla2x00_async_event(vha, rsp, mb);
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700229 break;
230 case 0x13:
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800231 qla2x00_process_response_queue(rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 break;
233 case 0x15:
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700234 mb[0] = MBA_CMPLT_1_16BIT;
235 mb[1] = MSW(stat);
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800236 qla2x00_async_event(vha, rsp, mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 break;
238 case 0x16:
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700239 mb[0] = MBA_SCSI_COMPLETION;
240 mb[1] = MSW(stat);
241 mb[2] = RD_MAILBOX_REG(ha, reg, 2);
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800242 qla2x00_async_event(vha, rsp, mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 break;
244 default:
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700245 ql_dbg(ql_dbg_async, vha, 0x5028,
246 "Unrecognized interrupt type (%d).\n", stat & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 break;
248 }
249 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
250 RD_REG_WORD_RELAXED(&reg->hccr);
251 }
gurinder.shergill@hp.com36439832013-04-23 10:13:17 -0700252 qla2x00_handle_mbx_completion(ha, status);
Anirban Chakraborty43fac4d2009-06-10 13:55:11 -0700253 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 return (IRQ_HANDLED);
256}
257
258/**
259 * qla2x00_mbx_completion() - Process mailbox command completions.
260 * @ha: SCSI driver HA context
261 * @mb0: Mailbox0 register
262 */
263static void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800264qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265{
266 uint16_t cnt;
Andrew Vasquez4fa94f82011-11-18 09:03:09 -0800267 uint32_t mboxes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 uint16_t __iomem *wptr;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800269 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700270 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
Andrew Vasquez4fa94f82011-11-18 09:03:09 -0800272 /* Read all mbox registers? */
273 mboxes = (1 << ha->mbx_count) - 1;
274 if (!ha->mcp)
Masanari Iidaa7201012012-11-21 02:40:42 -0500275 ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERROR.\n");
Andrew Vasquez4fa94f82011-11-18 09:03:09 -0800276 else
277 mboxes = ha->mcp->in_mb;
278
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 /* Load return mailbox registers. */
280 ha->flags.mbox_int = 1;
281 ha->mailbox_out[0] = mb0;
Andrew Vasquez4fa94f82011-11-18 09:03:09 -0800282 mboxes >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 1);
284
285 for (cnt = 1; cnt < ha->mbx_count; cnt++) {
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700286 if (IS_QLA2200(ha) && cnt == 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 8);
Andrew Vasquez4fa94f82011-11-18 09:03:09 -0800288 if ((cnt == 4 || cnt == 5) && (mboxes & BIT_0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 ha->mailbox_out[cnt] = qla2x00_debounce_register(wptr);
Andrew Vasquez4fa94f82011-11-18 09:03:09 -0800290 else if (mboxes & BIT_0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 ha->mailbox_out[cnt] = RD_REG_WORD(wptr);
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700292
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 wptr++;
Andrew Vasquez4fa94f82011-11-18 09:03:09 -0800294 mboxes >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296}
297
Andrew Vasquez8a659572009-02-08 20:50:12 -0800298static void
299qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr)
300{
301 static char *event[] =
302 { "Complete", "Request Notification", "Time Extension" };
303 int rval;
304 struct device_reg_24xx __iomem *reg24 = &vha->hw->iobase->isp24;
Chad Dupuis9e5054e2013-10-30 03:38:23 -0400305 struct device_reg_82xx __iomem *reg82 = &vha->hw->iobase->isp82;
Andrew Vasquez8a659572009-02-08 20:50:12 -0800306 uint16_t __iomem *wptr;
307 uint16_t cnt, timeout, mb[QLA_IDC_ACK_REGS];
308
309 /* Seed data -- mailbox1 -> mailbox7. */
Chad Dupuis9e5054e2013-10-30 03:38:23 -0400310 if (IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw))
311 wptr = (uint16_t __iomem *)&reg24->mailbox1;
312 else if (IS_QLA8044(vha->hw))
313 wptr = (uint16_t __iomem *)&reg82->mailbox_out[1];
314 else
315 return;
316
Andrew Vasquez8a659572009-02-08 20:50:12 -0800317 for (cnt = 0; cnt < QLA_IDC_ACK_REGS; cnt++, wptr++)
318 mb[cnt] = RD_REG_WORD(wptr);
319
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700320 ql_dbg(ql_dbg_async, vha, 0x5021,
Giridhar Malavali6246b8a2012-02-09 11:15:34 -0800321 "Inter-Driver Communication %s -- "
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700322 "%04x %04x %04x %04x %04x %04x %04x.\n",
323 event[aen & 0xff], mb[0], mb[1], mb[2], mb[3],
324 mb[4], mb[5], mb[6]);
Santosh Vernekar454073c2013-08-27 01:37:48 -0400325 switch (aen) {
326 /* Handle IDC Error completion case. */
327 case MBA_IDC_COMPLETE:
328 if (mb[1] >> 15) {
329 vha->hw->flags.idc_compl_status = 1;
Chad Dupuis9aaf2ce2013-10-30 03:38:25 -0400330 if (vha->hw->notify_dcbx_comp && !vha->vp_idx)
Santosh Vernekar454073c2013-08-27 01:37:48 -0400331 complete(&vha->hw->dcbx_comp);
332 }
333 break;
334
335 case MBA_IDC_NOTIFY:
336 /* Acknowledgement needed? [Notify && non-zero timeout]. */
337 timeout = (descr >> 8) & 0xf;
338 ql_dbg(ql_dbg_async, vha, 0x5022,
339 "%lu Inter-Driver Communication %s -- ACK timeout=%d.\n",
340 vha->host_no, event[aen & 0xff], timeout);
341
342 if (!timeout)
343 return;
344 rval = qla2x00_post_idc_ack_work(vha, mb);
345 if (rval != QLA_SUCCESS)
346 ql_log(ql_log_warn, vha, 0x5023,
347 "IDC failed to post ACK.\n");
348 break;
349 case MBA_IDC_TIME_EXT:
350 vha->hw->idc_extend_tmo = descr;
351 ql_dbg(ql_dbg_async, vha, 0x5087,
352 "%lu Inter-Driver Communication %s -- "
353 "Extend timeout by=%d.\n",
354 vha->host_no, event[aen & 0xff], vha->hw->idc_extend_tmo);
355 break;
Chad Dupuis8fcd6b82012-08-22 14:21:06 -0400356 }
Andrew Vasquez8a659572009-02-08 20:50:12 -0800357}
358
Chad Dupuisdaae62a2012-05-15 14:34:23 -0400359#define LS_UNKNOWN 2
Joe Carnucciod0297c92012-11-21 02:40:40 -0500360const char *
361qla2x00_get_link_speed_str(struct qla_hw_data *ha, uint16_t speed)
Chad Dupuisdaae62a2012-05-15 14:34:23 -0400362{
Chad Dupuisf73cb692014-02-26 04:15:06 -0500363 static const char *const link_speeds[] = {
364 "1", "2", "?", "4", "8", "16", "32", "10"
Joe Carnucciod0297c92012-11-21 02:40:40 -0500365 };
Chad Dupuisf73cb692014-02-26 04:15:06 -0500366#define QLA_LAST_SPEED 7
Chad Dupuisdaae62a2012-05-15 14:34:23 -0400367
368 if (IS_QLA2100(ha) || IS_QLA2200(ha))
Joe Carnucciod0297c92012-11-21 02:40:40 -0500369 return link_speeds[0];
370 else if (speed == 0x13)
Chad Dupuisf73cb692014-02-26 04:15:06 -0500371 return link_speeds[QLA_LAST_SPEED];
372 else if (speed < QLA_LAST_SPEED)
Joe Carnucciod0297c92012-11-21 02:40:40 -0500373 return link_speeds[speed];
374 else
375 return link_speeds[LS_UNKNOWN];
Chad Dupuisdaae62a2012-05-15 14:34:23 -0400376}
377
Saurav Kashyapfa492632012-11-21 02:40:29 -0500378static void
Santosh Vernekar7d613ac2012-08-22 14:21:03 -0400379qla83xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb)
380{
381 struct qla_hw_data *ha = vha->hw;
382
383 /*
384 * 8200 AEN Interpretation:
385 * mb[0] = AEN code
386 * mb[1] = AEN Reason code
387 * mb[2] = LSW of Peg-Halt Status-1 Register
388 * mb[6] = MSW of Peg-Halt Status-1 Register
389 * mb[3] = LSW of Peg-Halt Status-2 register
390 * mb[7] = MSW of Peg-Halt Status-2 register
391 * mb[4] = IDC Device-State Register value
392 * mb[5] = IDC Driver-Presence Register value
393 */
394 ql_dbg(ql_dbg_async, vha, 0x506b, "AEN Code: mb[0] = 0x%x AEN reason: "
395 "mb[1] = 0x%x PH-status1: mb[2] = 0x%x PH-status1: mb[6] = 0x%x.\n",
396 mb[0], mb[1], mb[2], mb[6]);
397 ql_dbg(ql_dbg_async, vha, 0x506c, "PH-status2: mb[3] = 0x%x "
398 "PH-status2: mb[7] = 0x%x Device-State: mb[4] = 0x%x "
399 "Drv-Presence: mb[5] = 0x%x.\n", mb[3], mb[7], mb[4], mb[5]);
400
401 if (mb[1] & (IDC_PEG_HALT_STATUS_CHANGE | IDC_NIC_FW_REPORTED_FAILURE |
402 IDC_HEARTBEAT_FAILURE)) {
403 ha->flags.nic_core_hung = 1;
404 ql_log(ql_log_warn, vha, 0x5060,
405 "83XX: F/W Error Reported: Check if reset required.\n");
406
407 if (mb[1] & IDC_PEG_HALT_STATUS_CHANGE) {
408 uint32_t protocol_engine_id, fw_err_code, err_level;
409
410 /*
411 * IDC_PEG_HALT_STATUS_CHANGE interpretation:
412 * - PEG-Halt Status-1 Register:
413 * (LSW = mb[2], MSW = mb[6])
414 * Bits 0-7 = protocol-engine ID
415 * Bits 8-28 = f/w error code
416 * Bits 29-31 = Error-level
417 * Error-level 0x1 = Non-Fatal error
418 * Error-level 0x2 = Recoverable Fatal error
419 * Error-level 0x4 = UnRecoverable Fatal error
420 * - PEG-Halt Status-2 Register:
421 * (LSW = mb[3], MSW = mb[7])
422 */
423 protocol_engine_id = (mb[2] & 0xff);
424 fw_err_code = (((mb[2] & 0xff00) >> 8) |
425 ((mb[6] & 0x1fff) << 8));
426 err_level = ((mb[6] & 0xe000) >> 13);
427 ql_log(ql_log_warn, vha, 0x5061, "PegHalt Status-1 "
428 "Register: protocol_engine_id=0x%x "
429 "fw_err_code=0x%x err_level=0x%x.\n",
430 protocol_engine_id, fw_err_code, err_level);
431 ql_log(ql_log_warn, vha, 0x5062, "PegHalt Status-2 "
432 "Register: 0x%x%x.\n", mb[7], mb[3]);
433 if (err_level == ERR_LEVEL_NON_FATAL) {
434 ql_log(ql_log_warn, vha, 0x5063,
435 "Not a fatal error, f/w has recovered "
436 "iteself.\n");
437 } else if (err_level == ERR_LEVEL_RECOVERABLE_FATAL) {
438 ql_log(ql_log_fatal, vha, 0x5064,
439 "Recoverable Fatal error: Chip reset "
440 "required.\n");
441 qla83xx_schedule_work(vha,
442 QLA83XX_NIC_CORE_RESET);
443 } else if (err_level == ERR_LEVEL_UNRECOVERABLE_FATAL) {
444 ql_log(ql_log_fatal, vha, 0x5065,
445 "Unrecoverable Fatal error: Set FAILED "
446 "state, reboot required.\n");
447 qla83xx_schedule_work(vha,
448 QLA83XX_NIC_CORE_UNRECOVERABLE);
449 }
450 }
451
452 if (mb[1] & IDC_NIC_FW_REPORTED_FAILURE) {
453 uint16_t peg_fw_state, nw_interface_link_up;
454 uint16_t nw_interface_signal_detect, sfp_status;
455 uint16_t htbt_counter, htbt_monitor_enable;
456 uint16_t sfp_additonal_info, sfp_multirate;
457 uint16_t sfp_tx_fault, link_speed, dcbx_status;
458
459 /*
460 * IDC_NIC_FW_REPORTED_FAILURE interpretation:
461 * - PEG-to-FC Status Register:
462 * (LSW = mb[2], MSW = mb[6])
463 * Bits 0-7 = Peg-Firmware state
464 * Bit 8 = N/W Interface Link-up
465 * Bit 9 = N/W Interface signal detected
466 * Bits 10-11 = SFP Status
467 * SFP Status 0x0 = SFP+ transceiver not expected
468 * SFP Status 0x1 = SFP+ transceiver not present
469 * SFP Status 0x2 = SFP+ transceiver invalid
470 * SFP Status 0x3 = SFP+ transceiver present and
471 * valid
472 * Bits 12-14 = Heartbeat Counter
473 * Bit 15 = Heartbeat Monitor Enable
474 * Bits 16-17 = SFP Additional Info
475 * SFP info 0x0 = Unregocnized transceiver for
476 * Ethernet
477 * SFP info 0x1 = SFP+ brand validation failed
478 * SFP info 0x2 = SFP+ speed validation failed
479 * SFP info 0x3 = SFP+ access error
480 * Bit 18 = SFP Multirate
481 * Bit 19 = SFP Tx Fault
482 * Bits 20-22 = Link Speed
483 * Bits 23-27 = Reserved
484 * Bits 28-30 = DCBX Status
485 * DCBX Status 0x0 = DCBX Disabled
486 * DCBX Status 0x1 = DCBX Enabled
487 * DCBX Status 0x2 = DCBX Exchange error
488 * Bit 31 = Reserved
489 */
490 peg_fw_state = (mb[2] & 0x00ff);
491 nw_interface_link_up = ((mb[2] & 0x0100) >> 8);
492 nw_interface_signal_detect = ((mb[2] & 0x0200) >> 9);
493 sfp_status = ((mb[2] & 0x0c00) >> 10);
494 htbt_counter = ((mb[2] & 0x7000) >> 12);
495 htbt_monitor_enable = ((mb[2] & 0x8000) >> 15);
496 sfp_additonal_info = (mb[6] & 0x0003);
497 sfp_multirate = ((mb[6] & 0x0004) >> 2);
498 sfp_tx_fault = ((mb[6] & 0x0008) >> 3);
499 link_speed = ((mb[6] & 0x0070) >> 4);
500 dcbx_status = ((mb[6] & 0x7000) >> 12);
501
502 ql_log(ql_log_warn, vha, 0x5066,
503 "Peg-to-Fc Status Register:\n"
504 "peg_fw_state=0x%x, nw_interface_link_up=0x%x, "
505 "nw_interface_signal_detect=0x%x"
506 "\nsfp_statis=0x%x.\n ", peg_fw_state,
507 nw_interface_link_up, nw_interface_signal_detect,
508 sfp_status);
509 ql_log(ql_log_warn, vha, 0x5067,
510 "htbt_counter=0x%x, htbt_monitor_enable=0x%x, "
511 "sfp_additonal_info=0x%x, sfp_multirate=0x%x.\n ",
512 htbt_counter, htbt_monitor_enable,
513 sfp_additonal_info, sfp_multirate);
514 ql_log(ql_log_warn, vha, 0x5068,
515 "sfp_tx_fault=0x%x, link_state=0x%x, "
516 "dcbx_status=0x%x.\n", sfp_tx_fault, link_speed,
517 dcbx_status);
518
519 qla83xx_schedule_work(vha, QLA83XX_NIC_CORE_RESET);
520 }
521
522 if (mb[1] & IDC_HEARTBEAT_FAILURE) {
523 ql_log(ql_log_warn, vha, 0x5069,
524 "Heartbeat Failure encountered, chip reset "
525 "required.\n");
526
527 qla83xx_schedule_work(vha, QLA83XX_NIC_CORE_RESET);
528 }
529 }
530
531 if (mb[1] & IDC_DEVICE_STATE_CHANGE) {
532 ql_log(ql_log_info, vha, 0x506a,
533 "IDC Device-State changed = 0x%x.\n", mb[4]);
Saurav Kashyap6c3943c2013-02-08 01:58:02 -0500534 if (ha->flags.nic_core_reset_owner)
535 return;
Santosh Vernekar7d613ac2012-08-22 14:21:03 -0400536 qla83xx_schedule_work(vha, MBA_IDC_AEN);
537 }
538}
539
Chad Dupuisbb4cf5b2013-02-08 01:58:01 -0500540int
541qla2x00_is_a_vp_did(scsi_qla_host_t *vha, uint32_t rscn_entry)
542{
543 struct qla_hw_data *ha = vha->hw;
544 scsi_qla_host_t *vp;
545 uint32_t vp_did;
546 unsigned long flags;
547 int ret = 0;
548
549 if (!ha->num_vhosts)
550 return ret;
551
552 spin_lock_irqsave(&ha->vport_slock, flags);
553 list_for_each_entry(vp, &ha->vp_list, list) {
554 vp_did = vp->d_id.b24;
555 if (vp_did == rscn_entry) {
556 ret = 1;
557 break;
558 }
559 }
560 spin_unlock_irqrestore(&ha->vport_slock, flags);
561
562 return ret;
563}
564
Quinn Tran726b8542017-01-19 22:28:00 -0800565fc_port_t *
Joe Carnuccio17cac3a2015-08-04 13:37:52 -0400566qla2x00_find_fcport_by_loopid(scsi_qla_host_t *vha, uint16_t loop_id)
567{
Quinn Tran726b8542017-01-19 22:28:00 -0800568 fc_port_t *f, *tf;
Joe Carnuccio17cac3a2015-08-04 13:37:52 -0400569
Quinn Tran726b8542017-01-19 22:28:00 -0800570 f = tf = NULL;
571 list_for_each_entry_safe(f, tf, &vha->vp_fcports, list)
572 if (f->loop_id == loop_id)
573 return f;
574 return NULL;
575}
576
577fc_port_t *
578qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *vha, u8 *wwpn, u8 incl_deleted)
579{
580 fc_port_t *f, *tf;
581
582 f = tf = NULL;
583 list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
584 if (memcmp(f->port_name, wwpn, WWN_SIZE) == 0) {
585 if (incl_deleted)
586 return f;
587 else if (f->deleted == 0)
588 return f;
589 }
590 }
591 return NULL;
592}
593
594fc_port_t *
595qla2x00_find_fcport_by_nportid(scsi_qla_host_t *vha, port_id_t *id,
596 u8 incl_deleted)
597{
598 fc_port_t *f, *tf;
599
600 f = tf = NULL;
601 list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
602 if (f->d_id.b24 == id->b24) {
603 if (incl_deleted)
604 return f;
605 else if (f->deleted == 0)
606 return f;
607 }
608 }
Joe Carnuccio17cac3a2015-08-04 13:37:52 -0400609 return NULL;
610}
611
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612/**
613 * qla2x00_async_event() - Process aynchronous events.
614 * @ha: SCSI driver HA context
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700615 * @mb: Mailbox registers (0 - 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 */
Seokmann Ju2c3dfe32007-07-05 13:16:51 -0700617void
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800618qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 uint16_t handle_cnt;
Andrew Vasquezbdab23d2009-10-13 15:16:46 -0700621 uint16_t cnt, mbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 uint32_t handles[5];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800623 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700624 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Andrew Vasquezbdab23d2009-10-13 15:16:46 -0700625 struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
Andrew Vasquezbc5c2aa2010-12-21 16:00:24 -0800626 struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
Bart Van Assche52c82822015-07-09 07:23:26 -0700627 uint32_t rscn_entry, host_pid;
Harihara Kadayam4d4df192008-04-03 13:13:26 -0700628 unsigned long flags;
Chad Dupuisef86cb22014-09-25 05:17:01 -0400629 fc_port_t *fcport = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
631 /* Setup to process RIO completion. */
632 handle_cnt = 0;
Giridhar Malavali6246b8a2012-02-09 11:15:34 -0800633 if (IS_CNA_CAPABLE(ha))
Andrew Vasquez3a03eb72009-01-05 11:18:11 -0800634 goto skip_rio;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 switch (mb[0]) {
636 case MBA_SCSI_COMPLETION:
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700637 handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 handle_cnt = 1;
639 break;
640 case MBA_CMPLT_1_16BIT:
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700641 handles[0] = mb[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 handle_cnt = 1;
643 mb[0] = MBA_SCSI_COMPLETION;
644 break;
645 case MBA_CMPLT_2_16BIT:
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700646 handles[0] = mb[1];
647 handles[1] = mb[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 handle_cnt = 2;
649 mb[0] = MBA_SCSI_COMPLETION;
650 break;
651 case MBA_CMPLT_3_16BIT:
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700652 handles[0] = mb[1];
653 handles[1] = mb[2];
654 handles[2] = mb[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 handle_cnt = 3;
656 mb[0] = MBA_SCSI_COMPLETION;
657 break;
658 case MBA_CMPLT_4_16BIT:
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700659 handles[0] = mb[1];
660 handles[1] = mb[2];
661 handles[2] = mb[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);
663 handle_cnt = 4;
664 mb[0] = MBA_SCSI_COMPLETION;
665 break;
666 case MBA_CMPLT_5_16BIT:
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700667 handles[0] = mb[1];
668 handles[1] = mb[2];
669 handles[2] = mb[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);
671 handles[4] = (uint32_t)RD_MAILBOX_REG(ha, reg, 7);
672 handle_cnt = 5;
673 mb[0] = MBA_SCSI_COMPLETION;
674 break;
675 case MBA_CMPLT_2_32BIT:
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700676 handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 handles[1] = le32_to_cpu(
678 ((uint32_t)(RD_MAILBOX_REG(ha, reg, 7) << 16)) |
679 RD_MAILBOX_REG(ha, reg, 6));
680 handle_cnt = 2;
681 mb[0] = MBA_SCSI_COMPLETION;
682 break;
683 default:
684 break;
685 }
Andrew Vasquez3a03eb72009-01-05 11:18:11 -0800686skip_rio:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 switch (mb[0]) {
688 case MBA_SCSI_COMPLETION: /* Fast Post */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800689 if (!vha->flags.online)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 break;
691
692 for (cnt = 0; cnt < handle_cnt; cnt++)
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800693 qla2x00_process_completed_request(vha, rsp->req,
694 handles[cnt]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 break;
696
697 case MBA_RESET: /* Reset */
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700698 ql_dbg(ql_dbg_async, vha, 0x5002,
699 "Asynchronous RESET.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800701 set_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 break;
703
704 case MBA_SYSTEM_ERR: /* System Error */
Chad Dupuisf73cb692014-02-26 04:15:06 -0500705 mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) ?
Giridhar Malavali6246b8a2012-02-09 11:15:34 -0800706 RD_REG_WORD(&reg24->mailbox7) : 0;
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700707 ql_log(ql_log_warn, vha, 0x5003,
Andrew Vasquezbdab23d2009-10-13 15:16:46 -0700708 "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh "
709 "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800711 ha->isp_ops->fw_dump(vha, 1);
Quinn Tranec7193e2017-03-15 09:48:55 -0700712 ha->flags.fw_init_done = 0;
Quinn Tran4b60c822017-06-13 20:47:21 -0700713 QLA_FW_STOPPED(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
Andrew Vasqueze4289242007-07-19 15:05:56 -0700715 if (IS_FWI2_CAPABLE(ha)) {
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700716 if (mb[1] == 0 && mb[2] == 0) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700717 ql_log(ql_log_fatal, vha, 0x5004,
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700718 "Unrecoverable Hardware Error: adapter "
719 "marked OFFLINE!\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800720 vha->flags.online = 0;
Giridhar Malavali6246b8a2012-02-09 11:15:34 -0800721 vha->device_flags |= DFLG_DEV_FAILED;
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -0700722 } else {
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300723 /* Check to see if MPI timeout occurred */
Chad Dupuisf73cb692014-02-26 04:15:06 -0500724 if ((mbx & MBX_3) && (ha->port_no == 0))
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -0700725 set_bit(MPI_RESET_NEEDED,
726 &vha->dpc_flags);
727
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800728 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Madhuranath Iyengarb1d469892010-09-03 15:20:54 -0700729 }
Andrew Vasquez9a853f72005-07-06 10:31:27 -0700730 } else if (mb[1] == 0) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700731 ql_log(ql_log_fatal, vha, 0x5005,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 "Unrecoverable Hardware Error: adapter marked "
733 "OFFLINE!\n");
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800734 vha->flags.online = 0;
Giridhar Malavali6246b8a2012-02-09 11:15:34 -0800735 vha->device_flags |= DFLG_DEV_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 } else
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800737 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 break;
739
740 case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700741 ql_log(ql_log_warn, vha, 0x5006,
742 "ISP Request Transfer Error (%x).\n", mb[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800744 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 break;
746
747 case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700748 ql_log(ql_log_warn, vha, 0x5007,
Joe Carnuccio41233cd2016-07-06 11:14:29 -0400749 "ISP Response Transfer Error (%x).\n", mb[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800751 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 break;
753
754 case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700755 ql_dbg(ql_dbg_async, vha, 0x5008,
Joe Carnuccio41233cd2016-07-06 11:14:29 -0400756 "Asynchronous WAKEUP_THRES (%x).\n", mb[1]);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -0400757 break;
Joe Carnuccio41233cd2016-07-06 11:14:29 -0400758
759 case MBA_LOOP_INIT_ERR:
Sawan Chandak75d560e2016-07-06 11:14:33 -0400760 ql_log(ql_log_warn, vha, 0x5090,
Joe Carnuccio41233cd2016-07-06 11:14:29 -0400761 "LOOP INIT ERROR (%x).\n", mb[1]);
762 ha->isp_ops->fw_dump(vha, 1);
763 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
764 break;
765
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */
Quinn Tranec7193e2017-03-15 09:48:55 -0700767 ha->flags.lip_ae = 1;
768 ha->flags.n2n_ae = 0;
769
Chad Dupuiscfb09192011-11-18 09:03:07 -0800770 ql_dbg(ql_dbg_async, vha, 0x5009,
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700771 "LIP occurred (%x).\n", mb[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800773 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
774 atomic_set(&vha->loop_state, LOOP_DOWN);
775 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
776 qla2x00_mark_all_devices_lost(vha, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 }
778
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800779 if (vha->vp_idx) {
780 atomic_set(&vha->vp_state, VP_FAILED);
781 fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -0700782 }
783
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800784 set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
785 set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800787 vha->flags.management_server_logged_in = 0;
788 qla2x00_post_aen_work(vha, FCH_EVT_LIP, mb[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 break;
790
791 case MBA_LOOP_UP: /* Loop Up Event */
Chad Dupuisdaae62a2012-05-15 14:34:23 -0400792 if (IS_QLA2100(ha) || IS_QLA2200(ha))
Andrew Vasquezd8b45212006-10-02 12:00:43 -0700793 ha->link_data_rate = PORT_SPEED_1GB;
Chad Dupuisdaae62a2012-05-15 14:34:23 -0400794 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 ha->link_data_rate = mb[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
Chad Dupuis8e5a9482014-08-08 07:38:09 -0400797 ql_log(ql_log_info, vha, 0x500a,
Chad Dupuisdaae62a2012-05-15 14:34:23 -0400798 "LOOP UP detected (%s Gbps).\n",
Joe Carnucciod0297c92012-11-21 02:40:40 -0500799 qla2x00_get_link_speed_str(ha, ha->link_data_rate));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800801 vha->flags.management_server_logged_in = 0;
802 qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 break;
804
805 case MBA_LOOP_DOWN: /* Loop Down Event */
Quinn Tranec7193e2017-03-15 09:48:55 -0700806 ha->flags.n2n_ae = 0;
807 ha->flags.lip_ae = 0;
808 ha->current_topology = 0;
809
Giridhar Malavali6246b8a2012-02-09 11:15:34 -0800810 mbx = (IS_QLA81XX(ha) || IS_QLA8031(ha))
811 ? RD_REG_WORD(&reg24->mailbox4) : 0;
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -0400812 mbx = (IS_P3P_TYPE(ha)) ? RD_REG_WORD(&reg82->mailbox_out[4])
813 : mbx;
Chad Dupuis8e5a9482014-08-08 07:38:09 -0400814 ql_log(ql_log_info, vha, 0x500b,
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700815 "LOOP DOWN detected (%x %x %x %x).\n",
816 mb[1], mb[2], mb[3], mbx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800818 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
819 atomic_set(&vha->loop_state, LOOP_DOWN);
820 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
Himanshu Madhani2486c622014-09-25 05:17:00 -0400821 /*
822 * In case of loop down, restore WWPN from
823 * NVRAM in case of FA-WWPN capable ISP
Sawan Chandak718abbd2015-04-09 15:00:07 -0400824 * Restore for Physical Port only
Himanshu Madhani2486c622014-09-25 05:17:00 -0400825 */
Sawan Chandak718abbd2015-04-09 15:00:07 -0400826 if (!vha->vp_idx) {
827 if (ha->flags.fawwpn_enabled) {
828 void *wwpn = ha->init_cb->port_name;
829 memcpy(vha->port_name, wwpn, WWN_SIZE);
830 fc_host_port_name(vha->host) =
831 wwn_to_u64(vha->port_name);
832 ql_dbg(ql_dbg_init + ql_dbg_verbose,
Quinn Tran83548fe2017-06-02 09:12:01 -0700833 vha, 0x00d8, "LOOP DOWN detected,"
Sawan Chandak718abbd2015-04-09 15:00:07 -0400834 "restore WWPN %016llx\n",
835 wwn_to_u64(vha->port_name));
836 }
Himanshu Madhani2486c622014-09-25 05:17:00 -0400837
Sawan Chandak718abbd2015-04-09 15:00:07 -0400838 clear_bit(VP_CONFIG_OK, &vha->vp_flags);
Himanshu Madhani2486c622014-09-25 05:17:00 -0400839 }
840
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800841 vha->device_flags |= DFLG_NO_CABLE;
842 qla2x00_mark_all_devices_lost(vha, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 }
844
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800845 if (vha->vp_idx) {
846 atomic_set(&vha->vp_state, VP_FAILED);
847 fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -0700848 }
849
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800850 vha->flags.management_server_logged_in = 0;
Andrew Vasquezd8b45212006-10-02 12:00:43 -0700851 ha->link_data_rate = PORT_SPEED_UNKNOWN;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800852 qla2x00_post_aen_work(vha, FCH_EVT_LINKDOWN, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 break;
854
855 case MBA_LIP_RESET: /* LIP reset occurred */
Chad Dupuiscfb09192011-11-18 09:03:07 -0800856 ql_dbg(ql_dbg_async, vha, 0x500c,
Bjorn Helgaascc3ef7b2008-09-11 21:22:51 -0700857 "LIP reset occurred (%x).\n", mb[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800859 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
860 atomic_set(&vha->loop_state, LOOP_DOWN);
861 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
862 qla2x00_mark_all_devices_lost(vha, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 }
864
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800865 if (vha->vp_idx) {
866 atomic_set(&vha->vp_state, VP_FAILED);
867 fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -0700868 }
869
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800870 set_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
872 ha->operating_mode = LOOP;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800873 vha->flags.management_server_logged_in = 0;
874 qla2x00_post_aen_work(vha, FCH_EVT_LIPRESET, mb[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 break;
876
Andrew Vasquez3a03eb72009-01-05 11:18:11 -0800877 /* case MBA_DCBX_COMPLETE: */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 case MBA_POINT_TO_POINT: /* Point-to-Point */
Quinn Tranec7193e2017-03-15 09:48:55 -0700879 ha->flags.lip_ae = 0;
880 ha->flags.n2n_ae = 1;
881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 if (IS_QLA2100(ha))
883 break;
884
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -0400885 if (IS_CNA_CAPABLE(ha)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700886 ql_dbg(ql_dbg_async, vha, 0x500d,
887 "DCBX Completed -- %04x %04x %04x.\n",
888 mb[1], mb[2], mb[3]);
Chad Dupuis9aaf2ce2013-10-30 03:38:25 -0400889 if (ha->notify_dcbx_comp && !vha->vp_idx)
Sarang Radke23f2ebd2010-05-28 15:08:21 -0700890 complete(&ha->dcbx_comp);
891
892 } else
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700893 ql_dbg(ql_dbg_async, vha, 0x500e,
894 "Asynchronous P2P MODE received.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895
896 /*
897 * Until there's a transition from loop down to loop up, treat
898 * this as loop down only.
899 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800900 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
901 atomic_set(&vha->loop_state, LOOP_DOWN);
902 if (!atomic_read(&vha->loop_down_timer))
903 atomic_set(&vha->loop_down_timer,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 LOOP_DOWN_TIME);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800905 qla2x00_mark_all_devices_lost(vha, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 }
907
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800908 if (vha->vp_idx) {
909 atomic_set(&vha->vp_state, VP_FAILED);
910 fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -0700911 }
912
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800913 if (!(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)))
914 set_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
915
916 set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
917 set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
Andrew Vasquez4346b142006-12-13 19:20:28 -0800918
919 ha->flags.gpsc_supported = 1;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800920 vha->flags.management_server_logged_in = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 break;
922
923 case MBA_CHG_IN_CONNECTION: /* Change in connection mode */
924 if (IS_QLA2100(ha))
925 break;
926
Chad Dupuiscfb09192011-11-18 09:03:07 -0800927 ql_dbg(ql_dbg_async, vha, 0x500f,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 "Configuration change detected: value=%x.\n", mb[1]);
929
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800930 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
931 atomic_set(&vha->loop_state, LOOP_DOWN);
932 if (!atomic_read(&vha->loop_down_timer))
933 atomic_set(&vha->loop_down_timer,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 LOOP_DOWN_TIME);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800935 qla2x00_mark_all_devices_lost(vha, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 }
937
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800938 if (vha->vp_idx) {
939 atomic_set(&vha->vp_state, VP_FAILED);
940 fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
Seokmann Ju2c3dfe32007-07-05 13:16:51 -0700941 }
942
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800943 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
944 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 break;
946
947 case MBA_PORT_UPDATE: /* Port database update */
Santosh Vernekar55903b92009-07-31 15:09:25 -0700948 /*
949 * Handle only global and vn-port update events
950 *
951 * Relevant inputs:
952 * mb[1] = N_Port handle of changed port
953 * OR 0xffff for global event
954 * mb[2] = New login state
955 * 7 = Port logged out
956 * mb[3] = LSB is vp_idx, 0xff = all vps
957 *
958 * Skip processing if:
959 * Event is global, vp_idx is NOT all vps,
960 * vp_idx does not match
961 * Event is not global, vp_idx does not match
962 */
Andrew Vasquez12cec63e42010-03-19 16:59:17 -0700963 if (IS_QLA2XXX_MIDTYPE(ha) &&
964 ((mb[1] == 0xffff && (mb[3] & 0xff) != 0xff) ||
965 (mb[1] != 0xffff)) && vha->vp_idx != (mb[3] & 0xff))
966 break;
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800967
Joe Carnuccio17cac3a2015-08-04 13:37:52 -0400968 if (mb[2] == 0x7) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700969 ql_dbg(ql_dbg_async, vha, 0x5010,
Joe Carnuccio17cac3a2015-08-04 13:37:52 -0400970 "Port %s %04x %04x %04x.\n",
971 mb[1] == 0xffff ? "unavailable" : "logout",
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700972 mb[1], mb[2], mb[3]);
Joe Carnuccio17cac3a2015-08-04 13:37:52 -0400973
974 if (mb[1] == 0xffff)
975 goto global_port_update;
976
Quinn Tranb98ae0d2017-06-02 09:12:00 -0700977 if (mb[1] == NPH_SNS_LID(ha)) {
978 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
979 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
980 break;
981 }
982
983 /* use handle_cnt for loop id/nport handle */
984 if (IS_FWI2_CAPABLE(ha))
985 handle_cnt = NPH_SNS;
986 else
987 handle_cnt = SIMPLE_NAME_SERVER;
988 if (mb[1] == handle_cnt) {
989 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
990 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
991 break;
992 }
993
Joe Carnuccio17cac3a2015-08-04 13:37:52 -0400994 /* Port logout */
995 fcport = qla2x00_find_fcport_by_loopid(vha, mb[1]);
996 if (!fcport)
997 break;
998 if (atomic_read(&fcport->state) != FCS_ONLINE)
999 break;
1000 ql_dbg(ql_dbg_async, vha, 0x508a,
1001 "Marking port lost loopid=%04x portid=%06x.\n",
1002 fcport->loop_id, fcport->d_id.b24);
Quinn Tran726b8542017-01-19 22:28:00 -08001003 if (qla_ini_mode_enabled(vha)) {
1004 qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
1005 fcport->logout_on_delete = 0;
1006 qlt_schedule_sess_for_deletion_lock(fcport);
1007 }
Joe Carnuccio17cac3a2015-08-04 13:37:52 -04001008 break;
1009
1010global_port_update:
Andrew Vasquez9764ff82009-07-31 15:09:24 -07001011 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
1012 atomic_set(&vha->loop_state, LOOP_DOWN);
1013 atomic_set(&vha->loop_down_timer,
1014 LOOP_DOWN_TIME);
1015 vha->device_flags |= DFLG_NO_CABLE;
1016 qla2x00_mark_all_devices_lost(vha, 1);
1017 }
1018
1019 if (vha->vp_idx) {
1020 atomic_set(&vha->vp_state, VP_FAILED);
1021 fc_vport_set_state(vha->fc_vport,
1022 FC_VPORT_FAILED);
Santosh Vernekarfaadc5e2009-07-31 15:09:26 -07001023 qla2x00_mark_all_devices_lost(vha, 1);
Andrew Vasquez9764ff82009-07-31 15:09:24 -07001024 }
1025
1026 vha->flags.management_server_logged_in = 0;
1027 ha->link_data_rate = PORT_SPEED_UNKNOWN;
1028 break;
1029 }
1030
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 /*
Bjorn Helgaascc3ef7b2008-09-11 21:22:51 -07001032 * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 * event etc. earlier indicating loop is down) then process
1034 * it. Otherwise ignore it and Wait for RSCN to come in.
1035 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001036 atomic_set(&vha->loop_down_timer, 0);
Chad Dupuis8e5a9482014-08-08 07:38:09 -04001037 if (atomic_read(&vha->loop_state) != LOOP_DOWN &&
1038 atomic_read(&vha->loop_state) != LOOP_DEAD) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001039 ql_dbg(ql_dbg_async, vha, 0x5011,
1040 "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n",
1041 mb[1], mb[2], mb[3]);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04001042
1043 qlt_async_event(mb[0], vha, mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 break;
1045 }
1046
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001047 ql_dbg(ql_dbg_async, vha, 0x5012,
1048 "Port database changed %04x %04x %04x.\n",
1049 mb[1], mb[2], mb[3]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
1051 /*
1052 * Mark all devices as missing so we will login again.
1053 */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001054 atomic_set(&vha->loop_state, LOOP_UP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001056 qla2x00_mark_all_devices_lost(vha, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001058 set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
1059 set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
Sawan Chandakded64112015-04-09 15:00:06 -04001060 set_bit(VP_CONFIG_OK, &vha->vp_flags);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04001061
1062 qlt_async_event(mb[0], vha, mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 break;
1064
1065 case MBA_RSCN_UPDATE: /* State Change Registration */
Seokmann Ju3c397402008-05-19 14:25:39 -07001066 /* Check if the Vport has issued a SCR */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001067 if (vha->vp_idx && test_bit(VP_SCR_NEEDED, &vha->vp_flags))
Seokmann Ju3c397402008-05-19 14:25:39 -07001068 break;
1069 /* Only handle SCNs for our Vport index. */
Andrew Vasquez0d6e61b2009-08-25 11:36:19 -07001070 if (ha->flags.npiv_supported && vha->vp_idx != (mb[3] & 0xff))
Seokmann Ju3c397402008-05-19 14:25:39 -07001071 break;
Andrew Vasquez0d6e61b2009-08-25 11:36:19 -07001072
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001073 ql_dbg(ql_dbg_async, vha, 0x5013,
1074 "RSCN database changed -- %04x %04x %04x.\n",
1075 mb[1], mb[2], mb[3]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
Ravi Anand59d72d82008-09-11 21:22:53 -07001077 rscn_entry = ((mb[1] & 0xff) << 16) | mb[2];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001078 host_pid = (vha->d_id.b.domain << 16) | (vha->d_id.b.area << 8)
1079 | vha->d_id.b.al_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 if (rscn_entry == host_pid) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001081 ql_dbg(ql_dbg_async, vha, 0x5014,
1082 "Ignoring RSCN update to local host "
1083 "port ID (%06x).\n", host_pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 break;
1085 }
1086
Ravi Anand59d72d82008-09-11 21:22:53 -07001087 /* Ignore reserved bits from RSCN-payload. */
1088 rscn_entry = ((mb[1] & 0x3ff) << 16) | mb[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
Chad Dupuisbb4cf5b2013-02-08 01:58:01 -05001090 /* Skip RSCNs for virtual ports on the same physical port */
1091 if (qla2x00_is_a_vp_did(vha, rscn_entry))
1092 break;
1093
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001094 atomic_set(&vha->loop_down_timer, 0);
1095 vha->flags.management_server_logged_in = 0;
Quinn Tran726b8542017-01-19 22:28:00 -08001096 {
1097 struct event_arg ea;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
Quinn Tran726b8542017-01-19 22:28:00 -08001099 memset(&ea, 0, sizeof(ea));
1100 ea.event = FCME_RSCN;
1101 ea.id.b24 = rscn_entry;
Quinn Tran41dc5292017-01-19 22:28:03 -08001102 ea.id.b.rsvd_1 = rscn_entry >> 24;
Quinn Tran726b8542017-01-19 22:28:00 -08001103 qla2x00_fcport_event_handler(vha, &ea);
Quinn Tran41dc5292017-01-19 22:28:03 -08001104 qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
Quinn Tran726b8542017-01-19 22:28:00 -08001105 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 /* case MBA_RIO_RESPONSE: */
1108 case MBA_ZIO_RESPONSE:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001109 ql_dbg(ql_dbg_async, vha, 0x5015,
1110 "[R|Z]IO update completion.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
Andrew Vasqueze4289242007-07-19 15:05:56 -07001112 if (IS_FWI2_CAPABLE(ha))
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07001113 qla24xx_process_response_queue(vha, rsp);
Andrew Vasquez4fdfefe2005-10-27 11:09:48 -07001114 else
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001115 qla2x00_process_response_queue(rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 break;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07001117
1118 case MBA_DISCARD_RND_FRAME:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001119 ql_dbg(ql_dbg_async, vha, 0x5016,
1120 "Discard RND Frame -- %04x %04x %04x.\n",
1121 mb[1], mb[2], mb[3]);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07001122 break;
Andrew Vasquez45ebeb52006-08-01 13:48:14 -07001123
1124 case MBA_TRACE_NOTIFICATION:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001125 ql_dbg(ql_dbg_async, vha, 0x5017,
1126 "Trace Notification -- %04x %04x.\n", mb[1], mb[2]);
Andrew Vasquez45ebeb52006-08-01 13:48:14 -07001127 break;
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001128
1129 case MBA_ISP84XX_ALERT:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001130 ql_dbg(ql_dbg_async, vha, 0x5018,
1131 "ISP84XX Alert Notification -- %04x %04x %04x.\n",
1132 mb[1], mb[2], mb[3]);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001133
1134 spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
1135 switch (mb[1]) {
1136 case A84_PANIC_RECOVERY:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001137 ql_log(ql_log_info, vha, 0x5019,
1138 "Alert 84XX: panic recovery %04x %04x.\n",
1139 mb[2], mb[3]);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001140 break;
1141 case A84_OP_LOGIN_COMPLETE:
1142 ha->cs84xx->op_fw_version = mb[3] << 16 | mb[2];
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001143 ql_log(ql_log_info, vha, 0x501a,
1144 "Alert 84XX: firmware version %x.\n",
1145 ha->cs84xx->op_fw_version);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001146 break;
1147 case A84_DIAG_LOGIN_COMPLETE:
1148 ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001149 ql_log(ql_log_info, vha, 0x501b,
1150 "Alert 84XX: diagnostic firmware version %x.\n",
1151 ha->cs84xx->diag_fw_version);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001152 break;
1153 case A84_GOLD_LOGIN_COMPLETE:
1154 ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
1155 ha->cs84xx->fw_update = 1;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001156 ql_log(ql_log_info, vha, 0x501c,
1157 "Alert 84XX: gold firmware version %x.\n",
1158 ha->cs84xx->gold_fw_version);
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001159 break;
1160 default:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001161 ql_log(ql_log_warn, vha, 0x501d,
1162 "Alert 84xx: Invalid Alert %04x %04x %04x.\n",
Harihara Kadayam4d4df192008-04-03 13:13:26 -07001163 mb[1], mb[2], mb[3]);
1164 }
1165 spin_unlock_irqrestore(&ha->cs84xx->access_lock, flags);
1166 break;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001167 case MBA_DCBX_START:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001168 ql_dbg(ql_dbg_async, vha, 0x501e,
1169 "DCBX Started -- %04x %04x %04x.\n",
1170 mb[1], mb[2], mb[3]);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001171 break;
1172 case MBA_DCBX_PARAM_UPDATE:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001173 ql_dbg(ql_dbg_async, vha, 0x501f,
1174 "DCBX Parameters Updated -- %04x %04x %04x.\n",
1175 mb[1], mb[2], mb[3]);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001176 break;
1177 case MBA_FCF_CONF_ERR:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001178 ql_dbg(ql_dbg_async, vha, 0x5020,
1179 "FCF Configuration Error -- %04x %04x %04x.\n",
1180 mb[1], mb[2], mb[3]);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001181 break;
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001182 case MBA_IDC_NOTIFY:
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04001183 if (IS_QLA8031(vha->hw) || IS_QLA8044(ha)) {
Chad Dupuis67b2a312013-02-08 01:57:51 -05001184 mb[4] = RD_REG_WORD(&reg24->mailbox4);
1185 if (((mb[2] & 0x7fff) == MBC_PORT_RESET ||
1186 (mb[2] & 0x7fff) == MBC_SET_PORT_CONFIG) &&
1187 (mb[4] & INTERNAL_LOOPBACK_MASK) != 0) {
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04001188 set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
Chad Dupuis67b2a312013-02-08 01:57:51 -05001189 /*
1190 * Extend loop down timer since port is active.
1191 */
1192 if (atomic_read(&vha->loop_state) == LOOP_DOWN)
1193 atomic_set(&vha->loop_down_timer,
1194 LOOP_DOWN_TIME);
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04001195 qla2xxx_wake_dpc(vha);
1196 }
Chad Dupuis67b2a312013-02-08 01:57:51 -05001197 }
Chad Dupuis8fcd6b82012-08-22 14:21:06 -04001198 case MBA_IDC_COMPLETE:
Chad Dupuis9aaf2ce2013-10-30 03:38:25 -04001199 if (ha->notify_lb_portup_comp && !vha->vp_idx)
Chad Dupuisf356bef2013-02-08 01:58:04 -05001200 complete(&ha->lb_portup_comp);
1201 /* Fallthru */
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001202 case MBA_IDC_TIME_EXT:
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04001203 if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw) ||
1204 IS_QLA8044(ha))
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04001205 qla81xx_idc_event(vha, mb[0], mb[1]);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001206 break;
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04001207
1208 case MBA_IDC_AEN:
1209 mb[4] = RD_REG_WORD(&reg24->mailbox4);
1210 mb[5] = RD_REG_WORD(&reg24->mailbox5);
1211 mb[6] = RD_REG_WORD(&reg24->mailbox6);
1212 mb[7] = RD_REG_WORD(&reg24->mailbox7);
1213 qla83xx_handle_8200_aen(vha, mb);
1214 break;
1215
Joe Carnucciob5a340d2014-09-25 05:16:48 -04001216 case MBA_DPORT_DIAGNOSTICS:
1217 ql_dbg(ql_dbg_async, vha, 0x5052,
Joe Carnuccioef55e512016-07-06 11:14:30 -04001218 "D-Port Diagnostics: %04x result=%s\n",
Joe Carnuccioec891462016-07-06 11:14:26 -04001219 mb[0],
Joe Carnucciob5a340d2014-09-25 05:16:48 -04001220 mb[1] == 0 ? "start" :
Joe Carnuccioef55e512016-07-06 11:14:30 -04001221 mb[1] == 1 ? "done (pass)" :
1222 mb[1] == 2 ? "done (error)" : "other");
Joe Carnucciob5a340d2014-09-25 05:16:48 -04001223 break;
1224
Joe Carnuccioa29b3dd2016-07-06 11:14:19 -04001225 case MBA_TEMPERATURE_ALERT:
1226 ql_dbg(ql_dbg_async, vha, 0x505e,
1227 "TEMPERATURE ALERT: %04x %04x %04x\n", mb[1], mb[2], mb[3]);
1228 if (mb[1] == 0x12)
1229 schedule_work(&ha->board_disable);
1230 break;
1231
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08001232 default:
1233 ql_dbg(ql_dbg_async, vha, 0x5057,
1234 "Unknown AEN:%04x %04x %04x %04x\n",
1235 mb[0], mb[1], mb[2], mb[3]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 }
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07001237
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04001238 qlt_async_event(mb[0], vha, mb);
1239
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001240 if (!vha->vp_idx && ha->num_vhosts)
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001241 qla2x00_alert_all_vps(rsp, mb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242}
1243
1244/**
1245 * qla2x00_process_completed_request() - Process a Fast Post response.
1246 * @ha: SCSI driver HA context
1247 * @index: SRB index
1248 */
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04001249void
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001250qla2x00_process_completed_request(struct scsi_qla_host *vha,
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04001251 struct req_que *req, uint32_t index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252{
1253 srb_t *sp;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001254 struct qla_hw_data *ha = vha->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
1256 /* Validate handle. */
Chad Dupuis8d93f552013-01-30 03:34:37 -05001257 if (index >= req->num_outstanding_cmds) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001258 ql_log(ql_log_warn, vha, 0x3014,
1259 "Invalid SCSI command index (%x).\n", index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04001261 if (IS_P3P_TYPE(ha))
Giridhar Malavali8f7daea2011-03-30 11:46:26 -07001262 set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
1263 else
1264 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 return;
1266 }
1267
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001268 sp = req->outstanding_cmds[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 if (sp) {
1270 /* Free outstanding command slot. */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001271 req->outstanding_cmds[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 /* Save ISP completion status */
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001274 sp->done(sp, DID_OK << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001276 ql_log(ql_log_warn, vha, 0x3016, "Invalid SCSI SRB.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04001278 if (IS_P3P_TYPE(ha))
Giridhar Malavali8f7daea2011-03-30 11:46:26 -07001279 set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
1280 else
1281 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 }
1283}
1284
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04001285srb_t *
Andrew Vasquezac280b62009-08-20 11:06:05 -07001286qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
1287 struct req_que *req, void *iocb)
1288{
1289 struct qla_hw_data *ha = vha->hw;
1290 sts_entry_t *pkt = iocb;
1291 srb_t *sp = NULL;
1292 uint16_t index;
1293
1294 index = LSW(pkt->handle);
Chad Dupuis8d93f552013-01-30 03:34:37 -05001295 if (index >= req->num_outstanding_cmds) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001296 ql_log(ql_log_warn, vha, 0x5031,
Quinn Tran726b8542017-01-19 22:28:00 -08001297 "Invalid command index (%x) type %8ph.\n",
1298 index, iocb);
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04001299 if (IS_P3P_TYPE(ha))
Giridhar Malavali8f7daea2011-03-30 11:46:26 -07001300 set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
1301 else
1302 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Andrew Vasquezac280b62009-08-20 11:06:05 -07001303 goto done;
1304 }
1305 sp = req->outstanding_cmds[index];
1306 if (!sp) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001307 ql_log(ql_log_warn, vha, 0x5032,
1308 "Invalid completion handle (%x) -- timed-out.\n", index);
Andrew Vasquezac280b62009-08-20 11:06:05 -07001309 return sp;
1310 }
1311 if (sp->handle != index) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001312 ql_log(ql_log_warn, vha, 0x5033,
1313 "SRB handle (%x) mismatch %x.\n", sp->handle, index);
Andrew Vasquezac280b62009-08-20 11:06:05 -07001314 return NULL;
1315 }
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001316
Andrew Vasquezac280b62009-08-20 11:06:05 -07001317 req->outstanding_cmds[index] = NULL;
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001318
Andrew Vasquezac280b62009-08-20 11:06:05 -07001319done:
1320 return sp;
1321}
1322
1323static void
1324qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
1325 struct mbx_entry *mbx)
1326{
1327 const char func[] = "MBX-IOCB";
1328 const char *type;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001329 fc_port_t *fcport;
1330 srb_t *sp;
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001331 struct srb_iocb *lio;
Andrew Vasquez99b0bec2010-05-04 15:01:25 -07001332 uint16_t *data;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001333 uint16_t status;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001334
1335 sp = qla2x00_get_sp_from_handle(vha, func, req, mbx);
1336 if (!sp)
1337 return;
1338
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001339 lio = &sp->u.iocb_cmd;
1340 type = sp->name;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001341 fcport = sp->fcport;
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001342 data = lio->u.logio.data;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001343
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001344 data[0] = MBS_COMMAND_ERROR;
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001345 data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001346 QLA_LOGIO_LOGIN_RETRIED : 0;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001347 if (mbx->entry_status) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001348 ql_dbg(ql_dbg_async, vha, 0x5043,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001349 "Async-%s error entry - hdl=%x portid=%02x%02x%02x "
Andrew Vasquezd3fa9e72010-05-28 15:08:16 -07001350 "entry-status=%x status=%x state-flag=%x "
Chad Dupuiscfb09192011-11-18 09:03:07 -08001351 "status-flags=%x.\n", type, sp->handle,
1352 fcport->d_id.b.domain, fcport->d_id.b.area,
Andrew Vasquezd3fa9e72010-05-28 15:08:16 -07001353 fcport->d_id.b.al_pa, mbx->entry_status,
1354 le16_to_cpu(mbx->status), le16_to_cpu(mbx->state_flags),
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001355 le16_to_cpu(mbx->status_flags));
Andrew Vasquezd3fa9e72010-05-28 15:08:16 -07001356
Chad Dupuiscfb09192011-11-18 09:03:07 -08001357 ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5029,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001358 (uint8_t *)mbx, sizeof(*mbx));
Andrew Vasquezac280b62009-08-20 11:06:05 -07001359
Andrew Vasquez99b0bec2010-05-04 15:01:25 -07001360 goto logio_done;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001361 }
1362
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001363 status = le16_to_cpu(mbx->status);
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001364 if (status == 0x30 && sp->type == SRB_LOGIN_CMD &&
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001365 le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE)
1366 status = 0;
1367 if (!status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001368 ql_dbg(ql_dbg_async, vha, 0x5045,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001369 "Async-%s complete - hdl=%x portid=%02x%02x%02x mbx1=%x.\n",
1370 type, sp->handle, fcport->d_id.b.domain,
1371 fcport->d_id.b.area, fcport->d_id.b.al_pa,
1372 le16_to_cpu(mbx->mb1));
Andrew Vasquezac280b62009-08-20 11:06:05 -07001373
1374 data[0] = MBS_COMMAND_COMPLETE;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001375 if (sp->type == SRB_LOGIN_CMD) {
Andrew Vasquez99b0bec2010-05-04 15:01:25 -07001376 fcport->port_type = FCT_TARGET;
1377 if (le16_to_cpu(mbx->mb1) & BIT_0)
1378 fcport->port_type = FCT_INITIATOR;
Andrew Vasquez6ac52602010-05-28 15:08:19 -07001379 else if (le16_to_cpu(mbx->mb1) & BIT_1)
Andrew Vasquez99b0bec2010-05-04 15:01:25 -07001380 fcport->flags |= FCF_FCP2_DEVICE;
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001381 }
Andrew Vasquez99b0bec2010-05-04 15:01:25 -07001382 goto logio_done;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001383 }
1384
1385 data[0] = le16_to_cpu(mbx->mb0);
1386 switch (data[0]) {
1387 case MBS_PORT_ID_USED:
1388 data[1] = le16_to_cpu(mbx->mb1);
1389 break;
1390 case MBS_LOOP_ID_USED:
1391 break;
1392 default:
1393 data[0] = MBS_COMMAND_ERROR;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001394 break;
1395 }
1396
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001397 ql_log(ql_log_warn, vha, 0x5046,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001398 "Async-%s failed - hdl=%x portid=%02x%02x%02x status=%x "
1399 "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n", type, sp->handle,
1400 fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
1401 status, le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1),
Andrew Vasquezac280b62009-08-20 11:06:05 -07001402 le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6),
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001403 le16_to_cpu(mbx->mb7));
Andrew Vasquezac280b62009-08-20 11:06:05 -07001404
Andrew Vasquez99b0bec2010-05-04 15:01:25 -07001405logio_done:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001406 sp->done(sp, 0);
Andrew Vasquezac280b62009-08-20 11:06:05 -07001407}
1408
1409static void
Quinn Tran726b8542017-01-19 22:28:00 -08001410qla24xx_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
1411 struct mbx_24xx_entry *pkt)
1412{
1413 const char func[] = "MBX-IOCB2";
1414 srb_t *sp;
1415 struct srb_iocb *si;
1416 u16 sz, i;
1417 int res;
1418
1419 sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
1420 if (!sp)
1421 return;
1422
1423 si = &sp->u.iocb_cmd;
1424 sz = min(ARRAY_SIZE(pkt->mb), ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.in_mb));
1425
1426 for (i = 0; i < sz; i++)
1427 si->u.mbx.in_mb[i] = le16_to_cpu(pkt->mb[i]);
1428
1429 res = (si->u.mbx.in_mb[0] & MBS_MASK);
1430
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001431 sp->done(sp, res);
Quinn Tran726b8542017-01-19 22:28:00 -08001432}
1433
1434static void
1435qla24xxx_nack_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
1436 struct nack_to_isp *pkt)
1437{
1438 const char func[] = "nack";
1439 srb_t *sp;
1440 int res = 0;
1441
1442 sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
1443 if (!sp)
1444 return;
1445
1446 if (pkt->u.isp2x.status != cpu_to_le16(NOTIFY_ACK_SUCCESS))
1447 res = QLA_FUNCTION_FAILED;
1448
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001449 sp->done(sp, res);
Andrew Vasquezac280b62009-08-20 11:06:05 -07001450}
1451
1452static void
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001453qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
1454 sts_entry_t *pkt, int iocb_type)
1455{
1456 const char func[] = "CT_IOCB";
1457 const char *type;
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001458 srb_t *sp;
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01001459 struct bsg_job *bsg_job;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001460 struct fc_bsg_reply *bsg_reply;
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001461 uint16_t comp_status;
Quinn Tran726b8542017-01-19 22:28:00 -08001462 int res = 0;
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001463
1464 sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
1465 if (!sp)
1466 return;
1467
Quinn Tran726b8542017-01-19 22:28:00 -08001468 switch (sp->type) {
1469 case SRB_CT_CMD:
1470 bsg_job = sp->u.bsg_job;
1471 bsg_reply = bsg_job->reply;
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001472
Quinn Tran726b8542017-01-19 22:28:00 -08001473 type = "ct pass-through";
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001474
Quinn Tran726b8542017-01-19 22:28:00 -08001475 comp_status = le16_to_cpu(pkt->comp_status);
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001476
Quinn Tran726b8542017-01-19 22:28:00 -08001477 /*
1478 * return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
1479 * fc payload to the caller
1480 */
1481 bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
1482 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001483
Quinn Tran726b8542017-01-19 22:28:00 -08001484 if (comp_status != CS_COMPLETE) {
1485 if (comp_status == CS_DATA_UNDERRUN) {
1486 res = DID_OK << 16;
1487 bsg_reply->reply_payload_rcv_len =
1488 le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001489
Quinn Tran726b8542017-01-19 22:28:00 -08001490 ql_log(ql_log_warn, vha, 0x5048,
1491 "CT pass-through-%s error comp_status=0x%x total_byte=0x%x.\n",
1492 type, comp_status,
1493 bsg_reply->reply_payload_rcv_len);
1494 } else {
1495 ql_log(ql_log_warn, vha, 0x5049,
1496 "CT pass-through-%s error comp_status=0x%x.\n",
1497 type, comp_status);
1498 res = DID_ERROR << 16;
1499 bsg_reply->reply_payload_rcv_len = 0;
1500 }
1501 ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
1502 (uint8_t *)pkt, sizeof(*pkt));
1503 } else {
1504 res = DID_OK << 16;
1505 bsg_reply->reply_payload_rcv_len =
1506 bsg_job->reply_payload.payload_len;
1507 bsg_job->reply_len = 0;
1508 }
1509 break;
1510 case SRB_CT_PTHRU_CMD:
1511 /*
1512 * borrowing sts_entry_24xx.comp_status.
1513 * same location as ct_entry_24xx.comp_status
1514 */
1515 res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
1516 (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
1517 sp->name);
1518 break;
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001519 }
1520
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001521 sp->done(sp, res);
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001522}
1523
1524static void
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001525qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
1526 struct sts_entry_24xx *pkt, int iocb_type)
1527{
1528 const char func[] = "ELS_CT_IOCB";
1529 const char *type;
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001530 srb_t *sp;
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01001531 struct bsg_job *bsg_job;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001532 struct fc_bsg_reply *bsg_reply;
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001533 uint16_t comp_status;
1534 uint32_t fw_status[3];
1535 uint8_t* fw_sts_ptr;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001536 int res;
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001537
1538 sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
1539 if (!sp)
1540 return;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001541 bsg_job = sp->u.bsg_job;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001542 bsg_reply = bsg_job->reply;
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001543
1544 type = NULL;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001545 switch (sp->type) {
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001546 case SRB_ELS_CMD_RPT:
1547 case SRB_ELS_CMD_HST:
1548 type = "els";
1549 break;
1550 case SRB_CT_CMD:
1551 type = "ct pass-through";
1552 break;
Himanshu Madhani6eb54712015-12-17 14:57:00 -05001553 case SRB_ELS_DCMD:
1554 type = "Driver ELS logo";
1555 ql_dbg(ql_dbg_user, vha, 0x5047,
1556 "Completing %s: (%p) type=%d.\n", type, sp, sp->type);
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001557 sp->done(sp, 0);
Himanshu Madhani6eb54712015-12-17 14:57:00 -05001558 return;
Quinn Tran726b8542017-01-19 22:28:00 -08001559 case SRB_CT_PTHRU_CMD:
1560 /* borrowing sts_entry_24xx.comp_status.
1561 same location as ct_entry_24xx.comp_status
1562 */
1563 res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
1564 (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
1565 sp->name);
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001566 sp->done(sp, res);
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001567 return;
1568 default:
1569 ql_dbg(ql_dbg_user, vha, 0x503e,
1570 "Unrecognized SRB: (%p) type=%d.\n", sp, sp->type);
1571 return;
1572 }
1573
1574 comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status);
1575 fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1);
1576 fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2);
1577
1578 /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
1579 * fc payload to the caller
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001580 */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001581 bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001582 bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(fw_status);
1583
1584 if (comp_status != CS_COMPLETE) {
1585 if (comp_status == CS_DATA_UNDERRUN) {
1586 res = DID_OK << 16;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001587 bsg_reply->reply_payload_rcv_len =
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001588 le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->total_byte_count);
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001589
Andrew Vasquez37fed3e2012-02-09 11:15:37 -08001590 ql_dbg(ql_dbg_user, vha, 0x503f,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001591 "ELS-CT pass-through-%s error hdl=%x comp_status-status=0x%x "
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001592 "error subcode 1=0x%x error subcode 2=0x%x total_byte = 0x%x.\n",
Chad Dupuiscfb09192011-11-18 09:03:07 -08001593 type, sp->handle, comp_status, fw_status[1], fw_status[2],
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001594 le16_to_cpu(((struct els_sts_entry_24xx *)
1595 pkt)->total_byte_count));
Christoph Hellwig82ed4db2017-01-27 09:46:29 +01001596 fw_sts_ptr = ((uint8_t*)scsi_req(bsg_job->req)->sense) +
1597 sizeof(struct fc_bsg_reply);
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001598 memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
1599 }
1600 else {
Andrew Vasquez37fed3e2012-02-09 11:15:37 -08001601 ql_dbg(ql_dbg_user, vha, 0x5040,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001602 "ELS-CT pass-through-%s error hdl=%x comp_status-status=0x%x "
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001603 "error subcode 1=0x%x error subcode 2=0x%x.\n",
Chad Dupuiscfb09192011-11-18 09:03:07 -08001604 type, sp->handle, comp_status,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001605 le16_to_cpu(((struct els_sts_entry_24xx *)
1606 pkt)->error_subcode_1),
1607 le16_to_cpu(((struct els_sts_entry_24xx *)
1608 pkt)->error_subcode_2));
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001609 res = DID_ERROR << 16;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001610 bsg_reply->reply_payload_rcv_len = 0;
Christoph Hellwig82ed4db2017-01-27 09:46:29 +01001611 fw_sts_ptr = ((uint8_t*)scsi_req(bsg_job->req)->sense) +
1612 sizeof(struct fc_bsg_reply);
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001613 memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
1614 }
Andrew Vasquez37fed3e2012-02-09 11:15:37 -08001615 ql_dump_buffer(ql_dbg_user + ql_dbg_buffer, vha, 0x5056,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001616 (uint8_t *)pkt, sizeof(*pkt));
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001617 }
1618 else {
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001619 res = DID_OK << 16;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01001620 bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001621 bsg_job->reply_len = 0;
1622 }
1623
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001624 sp->done(sp, res);
Giridhar Malavali9a069e12010-01-12 13:02:47 -08001625}
1626
1627static void
Andrew Vasquezac280b62009-08-20 11:06:05 -07001628qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
1629 struct logio_entry_24xx *logio)
1630{
1631 const char func[] = "LOGIO-IOCB";
1632 const char *type;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001633 fc_port_t *fcport;
1634 srb_t *sp;
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001635 struct srb_iocb *lio;
Andrew Vasquez99b0bec2010-05-04 15:01:25 -07001636 uint16_t *data;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001637 uint32_t iop[2];
1638
1639 sp = qla2x00_get_sp_from_handle(vha, func, req, logio);
1640 if (!sp)
1641 return;
1642
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001643 lio = &sp->u.iocb_cmd;
1644 type = sp->name;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001645 fcport = sp->fcport;
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001646 data = lio->u.logio.data;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001647
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001648 data[0] = MBS_COMMAND_ERROR;
Madhuranath Iyengar49163922010-05-04 15:01:28 -07001649 data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
Andrew Vasquez5ff1d582010-05-04 15:01:26 -07001650 QLA_LOGIO_LOGIN_RETRIED : 0;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001651 if (logio->entry_status) {
Arun Easi5e19ed92012-02-09 11:15:51 -08001652 ql_log(ql_log_warn, fcport->vha, 0x5034,
Quinn Tran5b334692017-03-15 09:48:48 -07001653 "Async-%s error entry - %8phC hdl=%x"
Andrew Vasquezd3fa9e72010-05-28 15:08:16 -07001654 "portid=%02x%02x%02x entry-status=%x.\n",
Quinn Tran5b334692017-03-15 09:48:48 -07001655 type, fcport->port_name, sp->handle, fcport->d_id.b.domain,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001656 fcport->d_id.b.area, fcport->d_id.b.al_pa,
1657 logio->entry_status);
1658 ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x504d,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001659 (uint8_t *)logio, sizeof(*logio));
Andrew Vasquezac280b62009-08-20 11:06:05 -07001660
Andrew Vasquez99b0bec2010-05-04 15:01:25 -07001661 goto logio_done;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001662 }
1663
1664 if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) {
Arun Easi5e19ed92012-02-09 11:15:51 -08001665 ql_dbg(ql_dbg_async, fcport->vha, 0x5036,
Quinn Tran5b334692017-03-15 09:48:48 -07001666 "Async-%s complete - %8phC hdl=%x portid=%02x%02x%02x "
1667 "iop0=%x.\n", type, fcport->port_name, sp->handle,
1668 fcport->d_id.b.domain,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001669 fcport->d_id.b.area, fcport->d_id.b.al_pa,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001670 le32_to_cpu(logio->io_parameter[0]));
Andrew Vasquezac280b62009-08-20 11:06:05 -07001671
Quinn Tranead03852017-01-19 22:28:01 -08001672 vha->hw->exch_starvation = 0;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001673 data[0] = MBS_COMMAND_COMPLETE;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001674 if (sp->type != SRB_LOGIN_CMD)
Andrew Vasquez99b0bec2010-05-04 15:01:25 -07001675 goto logio_done;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001676
1677 iop[0] = le32_to_cpu(logio->io_parameter[0]);
1678 if (iop[0] & BIT_4) {
1679 fcport->port_type = FCT_TARGET;
1680 if (iop[0] & BIT_8)
Santosh Vernekar8474f3a2009-08-25 11:36:16 -07001681 fcport->flags |= FCF_FCP2_DEVICE;
Andrew Vasquezb0cd5792010-05-28 15:08:22 -07001682 } else if (iop[0] & BIT_5)
Andrew Vasquezac280b62009-08-20 11:06:05 -07001683 fcport->port_type = FCT_INITIATOR;
Andrew Vasquezb0cd5792010-05-28 15:08:22 -07001684
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04001685 if (iop[0] & BIT_7)
1686 fcport->flags |= FCF_CONF_COMP_SUPPORTED;
1687
Andrew Vasquezac280b62009-08-20 11:06:05 -07001688 if (logio->io_parameter[7] || logio->io_parameter[8])
1689 fcport->supported_classes |= FC_COS_CLASS2;
1690 if (logio->io_parameter[9] || logio->io_parameter[10])
1691 fcport->supported_classes |= FC_COS_CLASS3;
1692
Andrew Vasquez99b0bec2010-05-04 15:01:25 -07001693 goto logio_done;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001694 }
1695
1696 iop[0] = le32_to_cpu(logio->io_parameter[0]);
1697 iop[1] = le32_to_cpu(logio->io_parameter[1]);
Quinn Tran726b8542017-01-19 22:28:00 -08001698 lio->u.logio.iop[0] = iop[0];
1699 lio->u.logio.iop[1] = iop[1];
Andrew Vasquezac280b62009-08-20 11:06:05 -07001700 switch (iop[0]) {
1701 case LSC_SCODE_PORTID_USED:
1702 data[0] = MBS_PORT_ID_USED;
1703 data[1] = LSW(iop[1]);
1704 break;
1705 case LSC_SCODE_NPORT_USED:
1706 data[0] = MBS_LOOP_ID_USED;
1707 break;
Quinn Tran5b334692017-03-15 09:48:48 -07001708 case LSC_SCODE_CMD_FAILED:
1709 if (iop[1] == 0x0606) {
1710 /*
1711 * PLOGI/PRLI Completed. We must have Recv PLOGI/PRLI,
1712 * Target side acked.
1713 */
1714 data[0] = MBS_COMMAND_COMPLETE;
1715 goto logio_done;
1716 }
1717 data[0] = MBS_COMMAND_ERROR;
1718 break;
Quinn Tranead03852017-01-19 22:28:01 -08001719 case LSC_SCODE_NOXCB:
1720 vha->hw->exch_starvation++;
1721 if (vha->hw->exch_starvation > 5) {
Quinn Tran83548fe2017-06-02 09:12:01 -07001722 ql_log(ql_log_warn, vha, 0xd046,
Quinn Tranead03852017-01-19 22:28:01 -08001723 "Exchange starvation. Resetting RISC\n");
1724
1725 vha->hw->exch_starvation = 0;
1726
1727 if (IS_P3P_TYPE(vha->hw))
1728 set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
1729 else
1730 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
1731 qla2xxx_wake_dpc(vha);
1732 }
1733 /* drop through */
Andrew Vasquezac280b62009-08-20 11:06:05 -07001734 default:
1735 data[0] = MBS_COMMAND_ERROR;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001736 break;
1737 }
1738
Arun Easi5e19ed92012-02-09 11:15:51 -08001739 ql_dbg(ql_dbg_async, fcport->vha, 0x5037,
Quinn Tran5b334692017-03-15 09:48:48 -07001740 "Async-%s failed - %8phC hdl=%x portid=%02x%02x%02x comp=%x "
1741 "iop0=%x iop1=%x.\n", type, fcport->port_name,
1742 sp->handle, fcport->d_id.b.domain,
Andrew Vasquezd3fa9e72010-05-28 15:08:16 -07001743 fcport->d_id.b.area, fcport->d_id.b.al_pa,
Andrew Vasquezac280b62009-08-20 11:06:05 -07001744 le16_to_cpu(logio->comp_status),
1745 le32_to_cpu(logio->io_parameter[0]),
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001746 le32_to_cpu(logio->io_parameter[1]));
Andrew Vasquezac280b62009-08-20 11:06:05 -07001747
Andrew Vasquez99b0bec2010-05-04 15:01:25 -07001748logio_done:
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001749 sp->done(sp, 0);
Andrew Vasquezac280b62009-08-20 11:06:05 -07001750}
1751
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001752static void
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001753qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk)
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001754{
1755 const char func[] = "TMF-IOCB";
1756 const char *type;
1757 fc_port_t *fcport;
1758 srb_t *sp;
1759 struct srb_iocb *iocb;
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001760 struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk;
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001761
1762 sp = qla2x00_get_sp_from_handle(vha, func, req, tsk);
1763 if (!sp)
1764 return;
1765
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001766 iocb = &sp->u.iocb_cmd;
1767 type = sp->name;
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001768 fcport = sp->fcport;
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001769 iocb->u.tmf.data = QLA_SUCCESS;
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001770
1771 if (sts->entry_status) {
Arun Easi5e19ed92012-02-09 11:15:51 -08001772 ql_log(ql_log_warn, fcport->vha, 0x5038,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001773 "Async-%s error - hdl=%x entry-status(%x).\n",
1774 type, sp->handle, sts->entry_status);
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001775 iocb->u.tmf.data = QLA_FUNCTION_FAILED;
Bart Van Asschead950362015-07-09 07:24:08 -07001776 } else if (sts->comp_status != cpu_to_le16(CS_COMPLETE)) {
Arun Easi5e19ed92012-02-09 11:15:51 -08001777 ql_log(ql_log_warn, fcport->vha, 0x5039,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001778 "Async-%s error - hdl=%x completion status(%x).\n",
1779 type, sp->handle, sts->comp_status);
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001780 iocb->u.tmf.data = QLA_FUNCTION_FAILED;
1781 } else if ((le16_to_cpu(sts->scsi_status) &
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001782 SS_RESPONSE_INFO_LEN_VALID)) {
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001783 if (le32_to_cpu(sts->rsp_data_len) < 4) {
1784 ql_log(ql_log_warn, fcport->vha, 0x503b,
1785 "Async-%s error - hdl=%x not enough response(%d).\n",
1786 type, sp->handle, sts->rsp_data_len);
1787 } else if (sts->data[3]) {
1788 ql_log(ql_log_warn, fcport->vha, 0x503c,
1789 "Async-%s error - hdl=%x response(%x).\n",
1790 type, sp->handle, sts->data[3]);
Bart Van Assche8d2b21d2015-06-04 15:58:09 -07001791 iocb->u.tmf.data = QLA_FUNCTION_FAILED;
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001792 }
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001793 }
1794
Armen Baloyanfaef62d2014-02-26 04:15:17 -05001795 if (iocb->u.tmf.data != QLA_SUCCESS)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001796 ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055,
1797 (uint8_t *)sts, sizeof(*sts));
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001798
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001799 sp->done(sp, 0);
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001800}
1801
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802/**
1803 * qla2x00_process_response_queue() - Process response queue entries.
1804 * @ha: SCSI driver HA context
1805 */
1806void
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001807qla2x00_process_response_queue(struct rsp_que *rsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808{
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001809 struct scsi_qla_host *vha;
1810 struct qla_hw_data *ha = rsp->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -07001811 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 sts_entry_t *pkt;
1813 uint16_t handle_cnt;
1814 uint16_t cnt;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001815
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07001816 vha = pci_get_drvdata(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001818 if (!vha->flags.online)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 return;
1820
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001821 while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
1822 pkt = (sts_entry_t *)rsp->ring_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001824 rsp->ring_index++;
1825 if (rsp->ring_index == rsp->length) {
1826 rsp->ring_index = 0;
1827 rsp->ring_ptr = rsp->ring;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 } else {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001829 rsp->ring_ptr++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 }
1831
1832 if (pkt->entry_status != 0) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001833 qla2x00_error_entry(vha, rsp, pkt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
1835 wmb();
1836 continue;
1837 }
1838
1839 switch (pkt->entry_type) {
1840 case STATUS_TYPE:
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001841 qla2x00_status_entry(vha, rsp, pkt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 break;
1843 case STATUS_TYPE_21:
1844 handle_cnt = ((sts21_entry_t *)pkt)->handle_count;
1845 for (cnt = 0; cnt < handle_cnt; cnt++) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001846 qla2x00_process_completed_request(vha, rsp->req,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 ((sts21_entry_t *)pkt)->handle[cnt]);
1848 }
1849 break;
1850 case STATUS_TYPE_22:
1851 handle_cnt = ((sts22_entry_t *)pkt)->handle_count;
1852 for (cnt = 0; cnt < handle_cnt; cnt++) {
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001853 qla2x00_process_completed_request(vha, rsp->req,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 ((sts22_entry_t *)pkt)->handle[cnt]);
1855 }
1856 break;
1857 case STATUS_CONT_TYPE:
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07001858 qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 break;
Andrew Vasquezac280b62009-08-20 11:06:05 -07001860 case MBX_IOCB_TYPE:
1861 qla2x00_mbx_iocb_entry(vha, rsp->req,
1862 (struct mbx_entry *)pkt);
Madhuranath Iyengar38222632010-05-04 15:01:29 -07001863 break;
Harish Zunjarrao9bc4f4f2010-07-23 15:28:32 +05001864 case CT_IOCB_TYPE:
1865 qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
1866 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 default:
1868 /* Type Not Supported. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001869 ql_log(ql_log_warn, vha, 0x504a,
1870 "Received unknown response pkt type %x "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 "entry status=%x.\n",
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001872 pkt->entry_type, pkt->entry_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 break;
1874 }
1875 ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
1876 wmb();
1877 }
1878
1879 /* Adjust ring index */
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08001880 WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), rsp->ring_index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881}
1882
Andrew Vasquez4733fcb2008-01-17 09:02:07 -08001883static inline void
Andrew Vasquez55442132010-07-23 15:28:27 +05001884qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001885 uint32_t sense_len, struct rsp_que *rsp, int res)
Andrew Vasquez4733fcb2008-01-17 09:02:07 -08001886{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001887 struct scsi_qla_host *vha = sp->vha;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001888 struct scsi_cmnd *cp = GET_CMD_SP(sp);
1889 uint32_t track_sense_len;
Andrew Vasquez4733fcb2008-01-17 09:02:07 -08001890
1891 if (sense_len >= SCSI_SENSE_BUFFERSIZE)
1892 sense_len = SCSI_SENSE_BUFFERSIZE;
1893
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001894 SET_CMD_SENSE_LEN(sp, sense_len);
1895 SET_CMD_SENSE_PTR(sp, cp->sense_buffer);
1896 track_sense_len = sense_len;
1897
1898 if (sense_len > par_sense_len)
Andrew Vasquez55442132010-07-23 15:28:27 +05001899 sense_len = par_sense_len;
Andrew Vasquez4733fcb2008-01-17 09:02:07 -08001900
1901 memcpy(cp->sense_buffer, sense_data, sense_len);
1902
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001903 SET_CMD_SENSE_PTR(sp, cp->sense_buffer + sense_len);
1904 track_sense_len -= sense_len;
1905 SET_CMD_SENSE_LEN(sp, track_sense_len);
1906
1907 if (track_sense_len != 0) {
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07001908 rsp->status_srb = sp;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001909 cp->result = res;
1910 }
Andrew Vasquez4733fcb2008-01-17 09:02:07 -08001911
Chad Dupuiscfb09192011-11-18 09:03:07 -08001912 if (sense_len) {
1913 ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x301c,
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02001914 "Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n",
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001915 sp->vha->host_no, cp->device->id, cp->device->lun,
Chad Dupuiscfb09192011-11-18 09:03:07 -08001916 cp);
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001917 ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302b,
1918 cp->sense_buffer, sense_len);
Chad Dupuiscfb09192011-11-18 09:03:07 -08001919 }
Andrew Vasquez4733fcb2008-01-17 09:02:07 -08001920}
1921
Arun Easibad75002010-05-04 15:01:30 -07001922struct scsi_dif_tuple {
1923 __be16 guard; /* Checksum */
Masanari Iidad6a03582012-08-22 14:20:58 -04001924 __be16 app_tag; /* APPL identifier */
Arun Easibad75002010-05-04 15:01:30 -07001925 __be32 ref_tag; /* Target LBA or indirect LBA */
1926};
1927
1928/*
1929 * Checks the guard or meta-data for the type of error
1930 * detected by the HBA. In case of errors, we set the
1931 * ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST
1932 * to indicate to the kernel that the HBA detected error.
1933 */
Arun Easi8cb20492011-08-16 11:29:22 -07001934static inline int
Arun Easibad75002010-05-04 15:01:30 -07001935qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
1936{
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08001937 struct scsi_qla_host *vha = sp->vha;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08001938 struct scsi_cmnd *cmd = GET_CMD_SP(sp);
Arun Easi8cb20492011-08-16 11:29:22 -07001939 uint8_t *ap = &sts24->data[12];
1940 uint8_t *ep = &sts24->data[20];
Arun Easibad75002010-05-04 15:01:30 -07001941 uint32_t e_ref_tag, a_ref_tag;
1942 uint16_t e_app_tag, a_app_tag;
1943 uint16_t e_guard, a_guard;
1944
Arun Easi8cb20492011-08-16 11:29:22 -07001945 /*
1946 * swab32 of the "data" field in the beginning of qla2x00_status_entry()
1947 * would make guard field appear at offset 2
1948 */
1949 a_guard = le16_to_cpu(*(uint16_t *)(ap + 2));
1950 a_app_tag = le16_to_cpu(*(uint16_t *)(ap + 0));
1951 a_ref_tag = le32_to_cpu(*(uint32_t *)(ap + 4));
1952 e_guard = le16_to_cpu(*(uint16_t *)(ep + 2));
1953 e_app_tag = le16_to_cpu(*(uint16_t *)(ep + 0));
1954 e_ref_tag = le32_to_cpu(*(uint32_t *)(ep + 4));
Arun Easibad75002010-05-04 15:01:30 -07001955
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001956 ql_dbg(ql_dbg_io, vha, 0x3023,
1957 "iocb(s) %p Returned STATUS.\n", sts24);
Arun Easibad75002010-05-04 15:01:30 -07001958
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001959 ql_dbg(ql_dbg_io, vha, 0x3024,
1960 "DIF ERROR in cmd 0x%x lba 0x%llx act ref"
Arun Easibad75002010-05-04 15:01:30 -07001961 " tag=0x%x, exp ref_tag=0x%x, act app tag=0x%x, exp app"
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001962 " tag=0x%x, act guard=0x%x, exp guard=0x%x.\n",
Arun Easibad75002010-05-04 15:01:30 -07001963 cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001964 a_app_tag, e_app_tag, a_guard, e_guard);
Arun Easibad75002010-05-04 15:01:30 -07001965
Arun Easi8cb20492011-08-16 11:29:22 -07001966 /*
1967 * Ignore sector if:
1968 * For type 3: ref & app tag is all 'f's
1969 * For type 0,1,2: app tag is all 'f's
1970 */
1971 if ((a_app_tag == 0xffff) &&
1972 ((scsi_get_prot_type(cmd) != SCSI_PROT_DIF_TYPE3) ||
1973 (a_ref_tag == 0xffffffff))) {
1974 uint32_t blocks_done, resid;
1975 sector_t lba_s = scsi_get_lba(cmd);
1976
1977 /* 2TB boundary case covered automatically with this */
1978 blocks_done = e_ref_tag - (uint32_t)lba_s + 1;
1979
1980 resid = scsi_bufflen(cmd) - (blocks_done *
1981 cmd->device->sector_size);
1982
1983 scsi_set_resid(cmd, resid);
1984 cmd->result = DID_OK << 16;
1985
1986 /* Update protection tag */
1987 if (scsi_prot_sg_count(cmd)) {
1988 uint32_t i, j = 0, k = 0, num_ent;
1989 struct scatterlist *sg;
Christoph Hellwig27c0e832016-09-11 19:35:40 +02001990 struct t10_pi_tuple *spt;
Arun Easi8cb20492011-08-16 11:29:22 -07001991
1992 /* Patch the corresponding protection tags */
1993 scsi_for_each_prot_sg(cmd, sg,
1994 scsi_prot_sg_count(cmd), i) {
1995 num_ent = sg_dma_len(sg) / 8;
1996 if (k + num_ent < blocks_done) {
1997 k += num_ent;
1998 continue;
1999 }
2000 j = blocks_done - k - 1;
2001 k = blocks_done;
2002 break;
2003 }
2004
2005 if (k != blocks_done) {
Chad Dupuiscfb09192011-11-18 09:03:07 -08002006 ql_log(ql_log_warn, vha, 0x302f,
Randy Dunlap8ec9c7f2011-09-23 15:40:50 -07002007 "unexpected tag values tag:lba=%x:%llx)\n",
2008 e_ref_tag, (unsigned long long)lba_s);
Arun Easi8cb20492011-08-16 11:29:22 -07002009 return 1;
2010 }
2011
2012 spt = page_address(sg_page(sg)) + sg->offset;
2013 spt += j;
2014
2015 spt->app_tag = 0xffff;
2016 if (scsi_get_prot_type(cmd) == SCSI_PROT_DIF_TYPE3)
2017 spt->ref_tag = 0xffffffff;
2018 }
2019
2020 return 0;
2021 }
2022
Arun Easibad75002010-05-04 15:01:30 -07002023 /* check guard */
2024 if (e_guard != a_guard) {
2025 scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
2026 0x10, 0x1);
2027 set_driver_byte(cmd, DRIVER_SENSE);
2028 set_host_byte(cmd, DID_ABORT);
2029 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
Arun Easi8cb20492011-08-16 11:29:22 -07002030 return 1;
Arun Easibad75002010-05-04 15:01:30 -07002031 }
2032
Arun Easie02587d2011-08-16 11:29:23 -07002033 /* check ref tag */
2034 if (e_ref_tag != a_ref_tag) {
2035 scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
2036 0x10, 0x3);
2037 set_driver_byte(cmd, DRIVER_SENSE);
2038 set_host_byte(cmd, DID_ABORT);
2039 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
2040 return 1;
2041 }
2042
Arun Easibad75002010-05-04 15:01:30 -07002043 /* check appl tag */
2044 if (e_app_tag != a_app_tag) {
2045 scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
2046 0x10, 0x2);
2047 set_driver_byte(cmd, DRIVER_SENSE);
2048 set_host_byte(cmd, DID_ABORT);
2049 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
Arun Easi8cb20492011-08-16 11:29:22 -07002050 return 1;
Arun Easibad75002010-05-04 15:01:30 -07002051 }
2052
Arun Easi8cb20492011-08-16 11:29:22 -07002053 return 1;
Arun Easibad75002010-05-04 15:01:30 -07002054}
2055
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002056static void
2057qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt,
2058 struct req_que *req, uint32_t index)
2059{
2060 struct qla_hw_data *ha = vha->hw;
2061 srb_t *sp;
2062 uint16_t comp_status;
2063 uint16_t scsi_status;
2064 uint16_t thread_id;
2065 uint32_t rval = EXT_STATUS_OK;
Johannes Thumshirn75cc8cf2016-11-17 10:31:19 +01002066 struct bsg_job *bsg_job = NULL;
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002067 struct fc_bsg_request *bsg_request;
2068 struct fc_bsg_reply *bsg_reply;
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002069 sts_entry_t *sts;
2070 struct sts_entry_24xx *sts24;
2071 sts = (sts_entry_t *) pkt;
2072 sts24 = (struct sts_entry_24xx *) pkt;
2073
2074 /* Validate handle. */
Chad Dupuis8d93f552013-01-30 03:34:37 -05002075 if (index >= req->num_outstanding_cmds) {
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002076 ql_log(ql_log_warn, vha, 0x70af,
2077 "Invalid SCSI completion handle 0x%x.\n", index);
2078 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2079 return;
2080 }
2081
2082 sp = req->outstanding_cmds[index];
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002083 if (!sp) {
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002084 ql_log(ql_log_warn, vha, 0x70b0,
2085 "Req:%d: Invalid ISP SCSI completion handle(0x%x)\n",
2086 req->id, index);
2087
2088 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2089 return;
2090 }
2091
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002092 /* Free outstanding command slot. */
2093 req->outstanding_cmds[index] = NULL;
2094 bsg_job = sp->u.bsg_job;
2095 bsg_request = bsg_job->request;
2096 bsg_reply = bsg_job->reply;
2097
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002098 if (IS_FWI2_CAPABLE(ha)) {
2099 comp_status = le16_to_cpu(sts24->comp_status);
2100 scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
2101 } else {
2102 comp_status = le16_to_cpu(sts->comp_status);
2103 scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK;
2104 }
2105
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002106 thread_id = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002107 switch (comp_status) {
2108 case CS_COMPLETE:
2109 if (scsi_status == 0) {
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002110 bsg_reply->reply_payload_rcv_len =
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002111 bsg_job->reply_payload.payload_len;
Joe Carnucciofabbb8d2013-08-27 01:37:40 -04002112 vha->qla_stats.input_bytes +=
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002113 bsg_reply->reply_payload_rcv_len;
Joe Carnucciofabbb8d2013-08-27 01:37:40 -04002114 vha->qla_stats.input_requests++;
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002115 rval = EXT_STATUS_OK;
2116 }
2117 goto done;
2118
2119 case CS_DATA_OVERRUN:
2120 ql_dbg(ql_dbg_user, vha, 0x70b1,
Milan P Gandhi5a68a1c2017-03-31 14:37:04 -07002121 "Command completed with data overrun thread_id=%d\n",
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002122 thread_id);
2123 rval = EXT_STATUS_DATA_OVERRUN;
2124 break;
2125
2126 case CS_DATA_UNDERRUN:
2127 ql_dbg(ql_dbg_user, vha, 0x70b2,
Milan P Gandhi5a68a1c2017-03-31 14:37:04 -07002128 "Command completed with data underrun thread_id=%d\n",
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002129 thread_id);
2130 rval = EXT_STATUS_DATA_UNDERRUN;
2131 break;
2132 case CS_BIDIR_RD_OVERRUN:
2133 ql_dbg(ql_dbg_user, vha, 0x70b3,
2134 "Command completed with read data overrun thread_id=%d\n",
2135 thread_id);
2136 rval = EXT_STATUS_DATA_OVERRUN;
2137 break;
2138
2139 case CS_BIDIR_RD_WR_OVERRUN:
2140 ql_dbg(ql_dbg_user, vha, 0x70b4,
2141 "Command completed with read and write data overrun "
2142 "thread_id=%d\n", thread_id);
2143 rval = EXT_STATUS_DATA_OVERRUN;
2144 break;
2145
2146 case CS_BIDIR_RD_OVERRUN_WR_UNDERRUN:
2147 ql_dbg(ql_dbg_user, vha, 0x70b5,
2148 "Command completed with read data over and write data "
2149 "underrun thread_id=%d\n", thread_id);
2150 rval = EXT_STATUS_DATA_OVERRUN;
2151 break;
2152
2153 case CS_BIDIR_RD_UNDERRUN:
2154 ql_dbg(ql_dbg_user, vha, 0x70b6,
Milan P Gandhi5a68a1c2017-03-31 14:37:04 -07002155 "Command completed with read data underrun "
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002156 "thread_id=%d\n", thread_id);
2157 rval = EXT_STATUS_DATA_UNDERRUN;
2158 break;
2159
2160 case CS_BIDIR_RD_UNDERRUN_WR_OVERRUN:
2161 ql_dbg(ql_dbg_user, vha, 0x70b7,
2162 "Command completed with read data under and write data "
2163 "overrun thread_id=%d\n", thread_id);
2164 rval = EXT_STATUS_DATA_UNDERRUN;
2165 break;
2166
2167 case CS_BIDIR_RD_WR_UNDERRUN:
2168 ql_dbg(ql_dbg_user, vha, 0x70b8,
2169 "Command completed with read and write data underrun "
2170 "thread_id=%d\n", thread_id);
2171 rval = EXT_STATUS_DATA_UNDERRUN;
2172 break;
2173
2174 case CS_BIDIR_DMA:
2175 ql_dbg(ql_dbg_user, vha, 0x70b9,
2176 "Command completed with data DMA error thread_id=%d\n",
2177 thread_id);
2178 rval = EXT_STATUS_DMA_ERR;
2179 break;
2180
2181 case CS_TIMEOUT:
2182 ql_dbg(ql_dbg_user, vha, 0x70ba,
2183 "Command completed with timeout thread_id=%d\n",
2184 thread_id);
2185 rval = EXT_STATUS_TIMEOUT;
2186 break;
2187 default:
2188 ql_dbg(ql_dbg_user, vha, 0x70bb,
2189 "Command completed with completion status=0x%x "
2190 "thread_id=%d\n", comp_status, thread_id);
2191 rval = EXT_STATUS_ERR;
2192 break;
2193 }
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002194 bsg_reply->reply_payload_rcv_len = 0;
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002195
2196done:
2197 /* Return the vendor specific reply to API */
Johannes Thumshirn01e0e152016-11-17 10:31:12 +01002198 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002199 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2200 /* Always return DID_OK, bsg will send the vendor specific response
2201 * in this case only */
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08002202 sp->done(sp, DID_OK << 6);
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002203
2204}
2205
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206/**
2207 * qla2x00_status_entry() - Process a Status IOCB entry.
2208 * @ha: SCSI driver HA context
2209 * @pkt: Entry pointer
2210 */
2211static void
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002212qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 srb_t *sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 fc_port_t *fcport;
2216 struct scsi_cmnd *cp;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002217 sts_entry_t *sts;
2218 struct sts_entry_24xx *sts24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 uint16_t comp_status;
2220 uint16_t scsi_status;
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002221 uint16_t ox_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 uint8_t lscsi_status;
2223 int32_t resid;
Andrew Vasquez55442132010-07-23 15:28:27 +05002224 uint32_t sense_len, par_sense_len, rsp_info_len, resid_len,
2225 fw_resid_len;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002226 uint8_t *rsp_info, *sense_data;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002227 struct qla_hw_data *ha = vha->hw;
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002228 uint32_t handle;
2229 uint16_t que;
2230 struct req_que *req;
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002231 int logit = 1;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002232 int res = 0;
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002233 uint16_t state_flags = 0;
Chad Dupuise05fe292014-09-25 05:16:59 -04002234 uint16_t retry_delay = 0;
Quinn Tran726b8542017-01-19 22:28:00 -08002235 uint8_t no_logout = 0;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002236
2237 sts = (sts_entry_t *) pkt;
2238 sts24 = (struct sts_entry_24xx *) pkt;
Andrew Vasqueze4289242007-07-19 15:05:56 -07002239 if (IS_FWI2_CAPABLE(ha)) {
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002240 comp_status = le16_to_cpu(sts24->comp_status);
2241 scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002242 state_flags = le16_to_cpu(sts24->state_flags);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002243 } else {
2244 comp_status = le16_to_cpu(sts->comp_status);
2245 scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK;
2246 }
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002247 handle = (uint32_t) LSW(sts->handle);
2248 que = MSW(sts->handle);
2249 req = ha->req_q_map[que];
Giridhar Malavalia9083012010-04-12 17:59:55 -07002250
Chad Dupuis36008cf2013-10-03 03:21:13 -04002251 /* Check for invalid queue pointer */
2252 if (req == NULL ||
2253 que >= find_first_zero_bit(ha->req_qid_map, ha->max_req_queues)) {
2254 ql_dbg(ql_dbg_io, vha, 0x3059,
2255 "Invalid status handle (0x%x): Bad req pointer. req=%p, "
2256 "que=%u.\n", sts->handle, req, que);
2257 return;
2258 }
2259
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 /* Validate handle. */
Chad Dupuisc7bc4ca2015-08-04 13:37:57 -04002261 if (handle < req->num_outstanding_cmds) {
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002262 sp = req->outstanding_cmds[handle];
Chad Dupuisc7bc4ca2015-08-04 13:37:57 -04002263 if (!sp) {
2264 ql_dbg(ql_dbg_io, vha, 0x3075,
2265 "%s(%ld): Already returned command for status handle (0x%x).\n",
2266 __func__, vha->host_no, sts->handle);
2267 return;
2268 }
2269 } else {
Chad Dupuiscfb09192011-11-18 09:03:07 -08002270 ql_dbg(ql_dbg_io, vha, 0x3017,
Chad Dupuisc7bc4ca2015-08-04 13:37:57 -04002271 "Invalid status handle, out of range (0x%x).\n",
2272 sts->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273
Chad Dupuisacd3ce882014-04-11 16:54:07 -04002274 if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) {
2275 if (IS_P3P_TYPE(ha))
2276 set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
2277 else
2278 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2279 qla2xxx_wake_dpc(vha);
2280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 return;
2282 }
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002283
Quinn Tranc5419e22017-06-13 20:47:16 -07002284 if (sp->cmd_type != TYPE_SRB) {
2285 req->outstanding_cmds[handle] = NULL;
2286 ql_dbg(ql_dbg_io, vha, 0x3015,
2287 "Unknown sp->cmd_type %x %p).\n",
2288 sp->cmd_type, sp);
2289 return;
2290 }
2291
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002292 if (unlikely((state_flags & BIT_1) && (sp->type == SRB_BIDI_CMD))) {
2293 qla25xx_process_bidir_status_iocb(vha, pkt, req, handle);
2294 return;
2295 }
2296
Armen Baloyanfaef62d2014-02-26 04:15:17 -05002297 /* Task Management completion. */
2298 if (sp->type == SRB_TM_CMD) {
2299 qla24xx_tm_iocb_entry(vha, req, pkt);
2300 return;
2301 }
2302
Saurav Kashyapa9b6f722012-08-22 14:21:01 -04002303 /* Fast path completion. */
2304 if (comp_status == CS_COMPLETE && scsi_status == 0) {
2305 qla2x00_process_completed_request(vha, req, handle);
2306
2307 return;
2308 }
2309
2310 req->outstanding_cmds[handle] = NULL;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002311 cp = GET_CMD_SP(sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 if (cp == NULL) {
Chad Dupuiscfb09192011-11-18 09:03:07 -08002313 ql_dbg(ql_dbg_io, vha, 0x3018,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002314 "Command already returned (0x%x/%p).\n",
2315 sts->handle, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316
2317 return;
2318 }
2319
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04002320 lscsi_status = scsi_status & STATUS_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321
bdf79622005-04-17 15:06:53 -05002322 fcport = sp->fcport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002324 ox_id = 0;
Andrew Vasquez55442132010-07-23 15:28:27 +05002325 sense_len = par_sense_len = rsp_info_len = resid_len =
2326 fw_resid_len = 0;
Andrew Vasqueze4289242007-07-19 15:05:56 -07002327 if (IS_FWI2_CAPABLE(ha)) {
Lalit Chandivade0f00a202009-10-13 15:16:52 -07002328 if (scsi_status & SS_SENSE_LEN_VALID)
2329 sense_len = le32_to_cpu(sts24->sense_len);
2330 if (scsi_status & SS_RESPONSE_INFO_LEN_VALID)
2331 rsp_info_len = le32_to_cpu(sts24->rsp_data_len);
2332 if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER))
2333 resid_len = le32_to_cpu(sts24->rsp_residual_count);
2334 if (comp_status == CS_DATA_UNDERRUN)
2335 fw_resid_len = le32_to_cpu(sts24->residual_len);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002336 rsp_info = sts24->data;
2337 sense_data = sts24->data;
2338 host_to_fcp_swap(sts24->data, sizeof(sts24->data));
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002339 ox_id = le16_to_cpu(sts24->ox_id);
Andrew Vasquez55442132010-07-23 15:28:27 +05002340 par_sense_len = sizeof(sts24->data);
Chad Dupuise05fe292014-09-25 05:16:59 -04002341 /* Valid values of the retry delay timer are 0x1-0xffef */
2342 if (sts24->retry_delay > 0 && sts24->retry_delay < 0xfff1)
2343 retry_delay = sts24->retry_delay;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002344 } else {
Lalit Chandivade0f00a202009-10-13 15:16:52 -07002345 if (scsi_status & SS_SENSE_LEN_VALID)
2346 sense_len = le16_to_cpu(sts->req_sense_length);
2347 if (scsi_status & SS_RESPONSE_INFO_LEN_VALID)
2348 rsp_info_len = le16_to_cpu(sts->rsp_info_len);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002349 resid_len = le32_to_cpu(sts->residual_length);
2350 rsp_info = sts->rsp_info;
2351 sense_data = sts->req_sense_data;
Andrew Vasquez55442132010-07-23 15:28:27 +05002352 par_sense_len = sizeof(sts->req_sense_data);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002353 }
2354
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 /* Check for any FCP transport errors. */
2356 if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) {
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002357 /* Sense data lies beyond any FCP RESPONSE data. */
Andrew Vasquez55442132010-07-23 15:28:27 +05002358 if (IS_FWI2_CAPABLE(ha)) {
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002359 sense_data += rsp_info_len;
Andrew Vasquez55442132010-07-23 15:28:27 +05002360 par_sense_len -= rsp_info_len;
2361 }
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002362 if (rsp_info_len > 3 && rsp_info[3]) {
Arun Easi5e19ed92012-02-09 11:15:51 -08002363 ql_dbg(ql_dbg_io, fcport->vha, 0x3019,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002364 "FCP I/O protocol failure (0x%x/0x%x).\n",
2365 rsp_info_len, rsp_info[3]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002367 res = DID_BUS_BUSY << 16;
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002368 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 }
2370 }
2371
Andrew Vasquez3e8ce322008-02-28 14:06:10 -08002372 /* Check for overrun. */
2373 if (IS_FWI2_CAPABLE(ha) && comp_status == CS_COMPLETE &&
2374 scsi_status & SS_RESIDUAL_OVER)
2375 comp_status = CS_DATA_OVERRUN;
2376
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 /*
Chad Dupuise05fe292014-09-25 05:16:59 -04002378 * Check retry_delay_timer value if we receive a busy or
2379 * queue full.
2380 */
2381 if (lscsi_status == SAM_STAT_TASK_SET_FULL ||
2382 lscsi_status == SAM_STAT_BUSY)
2383 qla2x00_set_retry_delay_timestamp(fcport, retry_delay);
2384
2385 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 * Based on Host and scsi status generate status code for Linux
2387 */
2388 switch (comp_status) {
2389 case CS_COMPLETE:
Andrew Vasquezdf7baa52006-10-13 09:33:39 -07002390 case CS_QUEUE_FULL:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 if (scsi_status == 0) {
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002392 res = DID_OK << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 break;
2394 }
2395 if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) {
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002396 resid = resid_len;
FUJITA Tomonori385d70b2007-05-26 01:55:38 +09002397 scsi_set_resid(cp, resid);
Andrew Vasquez0da69df2005-12-06 10:58:06 -08002398
2399 if (!lscsi_status &&
FUJITA Tomonori385d70b2007-05-26 01:55:38 +09002400 ((unsigned)(scsi_bufflen(cp) - resid) <
Andrew Vasquez0da69df2005-12-06 10:58:06 -08002401 cp->underflow)) {
Arun Easi5e19ed92012-02-09 11:15:51 -08002402 ql_dbg(ql_dbg_io, fcport->vha, 0x301a,
Quinn Tran83548fe2017-06-02 09:12:01 -07002403 "Mid-layer underflow detected (0x%x of 0x%x bytes).\n",
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002404 resid, scsi_bufflen(cp));
Andrew Vasquez0da69df2005-12-06 10:58:06 -08002405
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002406 res = DID_ERROR << 16;
Andrew Vasquez0da69df2005-12-06 10:58:06 -08002407 break;
2408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 }
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002410 res = DID_OK << 16 | lscsi_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411
Andrew Vasquezdf7baa52006-10-13 09:33:39 -07002412 if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
Arun Easi5e19ed92012-02-09 11:15:51 -08002413 ql_dbg(ql_dbg_io, fcport->vha, 0x301b,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002414 "QUEUE FULL detected.\n");
Andrew Vasquezdf7baa52006-10-13 09:33:39 -07002415 break;
2416 }
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002417 logit = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 if (lscsi_status != SS_CHECK_CONDITION)
2419 break;
2420
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +09002421 memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 if (!(scsi_status & SS_SENSE_LEN_VALID))
2423 break;
2424
Andrew Vasquez55442132010-07-23 15:28:27 +05002425 qla2x00_handle_sense(sp, sense_data, par_sense_len, sense_len,
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002426 rsp, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 break;
2428
2429 case CS_DATA_UNDERRUN:
Ravi Ananded17c71b52006-05-17 15:08:55 -07002430 /* Use F/W calculated residual length. */
Lalit Chandivade0f00a202009-10-13 15:16:52 -07002431 resid = IS_FWI2_CAPABLE(ha) ? fw_resid_len : resid_len;
2432 scsi_set_resid(cp, resid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 if (scsi_status & SS_RESIDUAL_UNDER) {
Lalit Chandivade0f00a202009-10-13 15:16:52 -07002434 if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) {
Arun Easi5e19ed92012-02-09 11:15:51 -08002435 ql_dbg(ql_dbg_io, fcport->vha, 0x301d,
Quinn Tran83548fe2017-06-02 09:12:01 -07002436 "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002437 resid, scsi_bufflen(cp));
andrew.vasquez@qlogic.come038a1b2006-01-13 17:04:59 -08002438
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002439 res = DID_ERROR << 16 | lscsi_status;
Arun Easi4e85e3d2011-11-18 09:02:10 -08002440 goto check_scsi_status;
Lalit Chandivade0f00a202009-10-13 15:16:52 -07002441 }
2442
2443 if (!lscsi_status &&
2444 ((unsigned)(scsi_bufflen(cp) - resid) <
2445 cp->underflow)) {
Arun Easi5e19ed92012-02-09 11:15:51 -08002446 ql_dbg(ql_dbg_io, fcport->vha, 0x301e,
Quinn Tran83548fe2017-06-02 09:12:01 -07002447 "Mid-layer underflow detected (0x%x of 0x%x bytes).\n",
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002448 resid, scsi_bufflen(cp));
Lalit Chandivade0f00a202009-10-13 15:16:52 -07002449
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002450 res = DID_ERROR << 16;
Lalit Chandivade0f00a202009-10-13 15:16:52 -07002451 break;
2452 }
Giridhar Malavali4aee5762012-04-25 07:26:15 -07002453 } else if (lscsi_status != SAM_STAT_TASK_SET_FULL &&
2454 lscsi_status != SAM_STAT_BUSY) {
2455 /*
2456 * scsi status of task set and busy are considered to be
2457 * task not completed.
2458 */
2459
Arun Easi5e19ed92012-02-09 11:15:51 -08002460 ql_dbg(ql_dbg_io, fcport->vha, 0x301f,
Quinn Tran83548fe2017-06-02 09:12:01 -07002461 "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
2462 resid, scsi_bufflen(cp));
Lalit Chandivade0f00a202009-10-13 15:16:52 -07002463
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002464 res = DID_ERROR << 16 | lscsi_status;
Lalit Chandivade0374f552010-09-03 14:57:04 -07002465 goto check_scsi_status;
Giridhar Malavali4aee5762012-04-25 07:26:15 -07002466 } else {
2467 ql_dbg(ql_dbg_io, fcport->vha, 0x3030,
2468 "scsi_status: 0x%x, lscsi_status: 0x%x\n",
2469 scsi_status, lscsi_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 }
2471
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002472 res = DID_OK << 16 | lscsi_status;
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002473 logit = 0;
Lalit Chandivade0f00a202009-10-13 15:16:52 -07002474
Lalit Chandivade0374f552010-09-03 14:57:04 -07002475check_scsi_status:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 /*
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07002477 * Check to see if SCSI Status is non zero. If so report SCSI
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 * Status.
2479 */
2480 if (lscsi_status != 0) {
Andrew Vasquezffec28a2007-01-29 10:22:27 -08002481 if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
Arun Easi5e19ed92012-02-09 11:15:51 -08002482 ql_dbg(ql_dbg_io, fcport->vha, 0x3020,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002483 "QUEUE FULL detected.\n");
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002484 logit = 1;
Andrew Vasquezffec28a2007-01-29 10:22:27 -08002485 break;
2486 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 if (lscsi_status != SS_CHECK_CONDITION)
2488 break;
2489
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +09002490 memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491 if (!(scsi_status & SS_SENSE_LEN_VALID))
2492 break;
2493
Andrew Vasquez55442132010-07-23 15:28:27 +05002494 qla2x00_handle_sense(sp, sense_data, par_sense_len,
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002495 sense_len, rsp, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 }
2497 break;
2498
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 case CS_PORT_LOGGED_OUT:
Quinn Tran726b8542017-01-19 22:28:00 -08002500 no_logout = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 case CS_PORT_CONFIG_CHG:
2502 case CS_PORT_BUSY:
2503 case CS_INCOMPLETE:
2504 case CS_PORT_UNAVAILABLE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 case CS_TIMEOUT:
Chad Dupuisff454b02010-10-15 11:27:42 -07002506 case CS_RESET:
2507
Mike Christie056a4482008-08-19 18:45:29 -05002508 /*
2509 * We are going to have the fc class block the rport
2510 * while we try to recover so instruct the mid layer
2511 * to requeue until the class decides how to handle this.
2512 */
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002513 res = DID_TRANSPORT_DISRUPTED << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002515 if (comp_status == CS_TIMEOUT) {
2516 if (IS_FWI2_CAPABLE(ha))
2517 break;
2518 else if ((le16_to_cpu(sts->status_flags) &
2519 SF_LOGOUT_SENT) == 0)
2520 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 }
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002522
Quinn Tran726b8542017-01-19 22:28:00 -08002523 if (atomic_read(&fcport->state) == FCS_ONLINE) {
2524 ql_dbg(ql_dbg_disc, fcport->vha, 0x3021,
2525 "Port to be marked lost on fcport=%02x%02x%02x, current "
2526 "port state= %s comp_status %x.\n", fcport->d_id.b.domain,
2527 fcport->d_id.b.area, fcport->d_id.b.al_pa,
2528 port_state_str[atomic_read(&fcport->state)],
2529 comp_status);
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002530
Quinn Tran726b8542017-01-19 22:28:00 -08002531 if (no_logout)
2532 fcport->logout_on_delete = 0;
2533
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002534 qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
Quinn Tran726b8542017-01-19 22:28:00 -08002535 qlt_schedule_sess_for_deletion_lock(fcport);
2536 }
2537
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 break;
2539
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002540 case CS_ABORTED:
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002541 res = DID_RESET << 16;
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002542 break;
Arun Easibad75002010-05-04 15:01:30 -07002543
2544 case CS_DIF_ERROR:
Arun Easi8cb20492011-08-16 11:29:22 -07002545 logit = qla2x00_handle_dif_error(sp, sts24);
Arun Easifb6e4662012-08-22 14:21:32 -04002546 res = cp->result;
Arun Easibad75002010-05-04 15:01:30 -07002547 break;
Arun Easi9e522cd2012-08-22 14:21:31 -04002548
2549 case CS_TRANSPORT:
2550 res = DID_ERROR << 16;
2551
2552 if (!IS_PI_SPLIT_DET_CAPABLE(ha))
2553 break;
2554
2555 if (state_flags & BIT_4)
2556 scmd_printk(KERN_WARNING, cp,
2557 "Unsupported device '%s' found.\n",
2558 cp->device->vendor);
2559 break;
2560
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 default:
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002562 res = DID_ERROR << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 break;
2564 }
2565
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002566out:
2567 if (logit)
Arun Easi5e19ed92012-02-09 11:15:51 -08002568 ql_dbg(ql_dbg_io, fcport->vha, 0x3022,
Hannes Reinecke9cb78c12014-06-25 15:27:36 +02002569 "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu "
Oleksandr Khoshaba7b833552013-08-27 01:37:27 -04002570 "portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x "
Chad Dupuisc7bc4ca2015-08-04 13:37:57 -04002571 "rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002572 comp_status, scsi_status, res, vha->host_no,
Chad Dupuiscfb09192011-11-18 09:03:07 -08002573 cp->device->id, cp->device->lun, fcport->d_id.b.domain,
2574 fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
Oleksandr Khoshaba7b833552013-08-27 01:37:27 -04002575 cp->cmnd, scsi_bufflen(cp), rsp_info_len,
Chad Dupuisc7bc4ca2015-08-04 13:37:57 -04002576 resid_len, fw_resid_len, sp, cp);
Andrew Vasquezb7d22802010-05-04 15:01:27 -07002577
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002578 if (rsp->status_srb == NULL)
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08002579 sp->done(sp, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580}
2581
2582/**
2583 * qla2x00_status_cont_entry() - Process a Status Continuations entry.
2584 * @ha: SCSI driver HA context
2585 * @pkt: Entry pointer
2586 *
2587 * Extended sense data.
2588 */
2589static void
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002590qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591{
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002592 uint8_t sense_sz = 0;
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002593 struct qla_hw_data *ha = rsp->hw;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002594 struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002595 srb_t *sp = rsp->status_srb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 struct scsi_cmnd *cp;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002597 uint32_t sense_len;
2598 uint8_t *sense_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002600 if (!sp || !GET_CMD_SENSE_LEN(sp))
2601 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002603 sense_len = GET_CMD_SENSE_LEN(sp);
2604 sense_ptr = GET_CMD_SENSE_PTR(sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002606 cp = GET_CMD_SP(sp);
2607 if (cp == NULL) {
2608 ql_log(ql_log_warn, vha, 0x3025,
2609 "cmd is NULL: already returned to OS (sp=%p).\n", sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002611 rsp->status_srb = NULL;
2612 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002615 if (sense_len > sizeof(pkt->data))
2616 sense_sz = sizeof(pkt->data);
2617 else
2618 sense_sz = sense_len;
Giridhar Malavalic4631192011-11-18 09:03:08 -08002619
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002620 /* Move sense data. */
2621 if (IS_FWI2_CAPABLE(ha))
2622 host_to_fcp_swap(pkt->data, sizeof(pkt->data));
2623 memcpy(sense_ptr, pkt->data, sense_sz);
2624 ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302c,
2625 sense_ptr, sense_sz);
Giridhar Malavalic4631192011-11-18 09:03:08 -08002626
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002627 sense_len -= sense_sz;
2628 sense_ptr += sense_sz;
Giridhar Malavalic4631192011-11-18 09:03:08 -08002629
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002630 SET_CMD_SENSE_PTR(sp, sense_ptr);
2631 SET_CMD_SENSE_LEN(sp, sense_len);
Giridhar Malavalic4631192011-11-18 09:03:08 -08002632
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002633 /* Place command on done queue. */
2634 if (sense_len == 0) {
2635 rsp->status_srb = NULL;
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08002636 sp->done(sp, cp->result);
Giridhar Malavalic4631192011-11-18 09:03:08 -08002637 }
Giridhar Malavalic4631192011-11-18 09:03:08 -08002638}
2639
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640/**
2641 * qla2x00_error_entry() - Process an error entry.
2642 * @ha: SCSI driver HA context
2643 * @pkt: Entry pointer
Quinn Tranc5419e22017-06-13 20:47:16 -07002644 * return : 1=allow further error analysis. 0=no additional error analysis.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 */
Quinn Tranc5419e22017-06-13 20:47:16 -07002646static int
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002647qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648{
2649 srb_t *sp;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002650 struct qla_hw_data *ha = vha->hw;
Giridhar Malavalic4631192011-11-18 09:03:08 -08002651 const char func[] = "ERROR-IOCB";
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002652 uint16_t que = MSW(pkt->handle);
Arun Easia6fe35c2012-02-09 11:16:01 -08002653 struct req_que *req = NULL;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002654 int res = DID_ERROR << 16;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002655
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002656 ql_dbg(ql_dbg_async, vha, 0x502a,
Quinn Tran82de8022017-06-13 20:47:17 -07002657 "iocb type %xh with error status %xh, handle %xh, rspq id %d\n",
2658 pkt->entry_type, pkt->entry_status, pkt->handle, rsp->id);
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002659
Arun Easia6fe35c2012-02-09 11:16:01 -08002660 if (que >= ha->max_req_queues || !ha->req_q_map[que])
2661 goto fatal;
2662
2663 req = ha->req_q_map[que];
2664
Giridhar Malavali9ba56b92012-02-09 11:15:36 -08002665 if (pkt->entry_status & RF_BUSY)
2666 res = DID_BUS_BUSY << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
Quinn Tranc5419e22017-06-13 20:47:16 -07002668 if ((pkt->handle & ~QLA_TGT_HANDLE_MASK) == QLA_TGT_SKIP_HANDLE)
2669 return 0;
Quinn Tran4f060732016-12-23 18:06:13 -08002670
Quinn Tranc5419e22017-06-13 20:47:16 -07002671 switch (pkt->entry_type) {
2672 case NOTIFY_ACK_TYPE:
2673 case STATUS_TYPE:
2674 case STATUS_CONT_TYPE:
2675 case LOGINOUT_PORT_IOCB_TYPE:
2676 case CT_IOCB_TYPE:
2677 case ELS_IOCB_TYPE:
2678 case ABORT_IOCB_TYPE:
2679 case MBX_IOCB_TYPE:
2680 sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
2681 if (sp) {
2682 sp->done(sp, res);
2683 return 0;
2684 }
2685 break;
2686
2687 case ABTS_RESP_24XX:
2688 case CTIO_TYPE7:
2689 case CTIO_CRC2:
2690 default:
2691 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 }
Arun Easia6fe35c2012-02-09 11:16:01 -08002693fatal:
2694 ql_log(ql_log_warn, vha, 0x5030,
Chad Dupuisfd49a542015-08-04 13:37:58 -04002695 "Error entry - invalid handle/queue (%04x).\n", que);
Quinn Tranc5419e22017-06-13 20:47:16 -07002696 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697}
2698
2699/**
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002700 * qla24xx_mbx_completion() - Process mailbox command completions.
2701 * @ha: SCSI driver HA context
2702 * @mb0: Mailbox0 register
2703 */
2704static void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002705qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002706{
2707 uint16_t cnt;
Andrew Vasquez4fa94f82011-11-18 09:03:09 -08002708 uint32_t mboxes;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002709 uint16_t __iomem *wptr;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002710 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002711 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
2712
Andrew Vasquez4fa94f82011-11-18 09:03:09 -08002713 /* Read all mbox registers? */
2714 mboxes = (1 << ha->mbx_count) - 1;
2715 if (!ha->mcp)
Masanari Iidaa7201012012-11-21 02:40:42 -05002716 ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERROR.\n");
Andrew Vasquez4fa94f82011-11-18 09:03:09 -08002717 else
2718 mboxes = ha->mcp->in_mb;
2719
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002720 /* Load return mailbox registers. */
2721 ha->flags.mbox_int = 1;
2722 ha->mailbox_out[0] = mb0;
Andrew Vasquez4fa94f82011-11-18 09:03:09 -08002723 mboxes >>= 1;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002724 wptr = (uint16_t __iomem *)&reg->mailbox1;
2725
2726 for (cnt = 1; cnt < ha->mbx_count; cnt++) {
Andrew Vasquez4fa94f82011-11-18 09:03:09 -08002727 if (mboxes & BIT_0)
2728 ha->mailbox_out[cnt] = RD_REG_WORD(wptr);
2729
2730 mboxes >>= 1;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002731 wptr++;
2732 }
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002733}
2734
Armen Baloyan4440e462014-02-26 04:15:18 -05002735static void
2736qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
2737 struct abort_entry_24xx *pkt)
2738{
2739 const char func[] = "ABT_IOCB";
2740 srb_t *sp;
2741 struct srb_iocb *abt;
2742
2743 sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
2744 if (!sp)
2745 return;
2746
2747 abt = &sp->u.iocb_cmd;
Quinn Tran15f30a52017-03-15 09:48:52 -07002748 abt->u.abt.comp_status = le16_to_cpu(pkt->nport_handle);
Joe Carnuccio25ff6af2017-01-19 22:28:04 -08002749 sp->done(sp, 0);
Armen Baloyan4440e462014-02-26 04:15:18 -05002750}
2751
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002752/**
2753 * qla24xx_process_response_queue() - Process response queue entries.
2754 * @ha: SCSI driver HA context
2755 */
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002756void qla24xx_process_response_queue(struct scsi_qla_host *vha,
2757 struct rsp_que *rsp)
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002758{
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002759 struct sts_entry_24xx *pkt;
Giridhar Malavalia9083012010-04-12 17:59:55 -07002760 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002761
Quinn Tranec7193e2017-03-15 09:48:55 -07002762 if (!ha->flags.fw_started)
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002763 return;
2764
Quinn Trane326d222017-06-13 20:47:18 -07002765 if (rsp->qpair->cpuid != smp_processor_id())
2766 qla_cpu_update(rsp->qpair, smp_processor_id());
2767
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002768 while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
2769 pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002770
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002771 rsp->ring_index++;
2772 if (rsp->ring_index == rsp->length) {
2773 rsp->ring_index = 0;
2774 rsp->ring_ptr = rsp->ring;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002775 } else {
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002776 rsp->ring_ptr++;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002777 }
2778
2779 if (pkt->entry_status != 0) {
Quinn Tranc5419e22017-06-13 20:47:16 -07002780 if (qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt))
Quinn Tranf83adb62014-04-11 16:54:43 -04002781 goto process_err;
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002782
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002783 ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
2784 wmb();
2785 continue;
2786 }
Quinn Tranf83adb62014-04-11 16:54:43 -04002787process_err:
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002788
2789 switch (pkt->entry_type) {
2790 case STATUS_TYPE:
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002791 qla2x00_status_entry(vha, rsp, pkt);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002792 break;
2793 case STATUS_CONT_TYPE:
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002794 qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002795 break;
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07002796 case VP_RPT_ID_IOCB_TYPE:
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002797 qla24xx_report_id_acquisition(vha,
Seokmann Ju2c3dfe32007-07-05 13:16:51 -07002798 (struct vp_rpt_id_entry_24xx *)pkt);
2799 break;
Andrew Vasquezac280b62009-08-20 11:06:05 -07002800 case LOGINOUT_PORT_IOCB_TYPE:
2801 qla24xx_logio_entry(vha, rsp->req,
2802 (struct logio_entry_24xx *)pkt);
2803 break;
Quinn Tranf83adb62014-04-11 16:54:43 -04002804 case CT_IOCB_TYPE:
Giridhar Malavali9a069e12010-01-12 13:02:47 -08002805 qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
Giridhar Malavali9a069e12010-01-12 13:02:47 -08002806 break;
Quinn Tranf83adb62014-04-11 16:54:43 -04002807 case ELS_IOCB_TYPE:
Giridhar Malavali9a069e12010-01-12 13:02:47 -08002808 qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE);
2809 break;
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002810 case ABTS_RECV_24XX:
Quinn Tran2f424b92015-12-17 14:57:07 -05002811 if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
2812 /* ensure that the ATIO queue is empty */
Quinn Tran82de8022017-06-13 20:47:17 -07002813 qlt_handle_abts_recv(vha, rsp,
2814 (response_t *)pkt);
Quinn Tran2f424b92015-12-17 14:57:07 -05002815 break;
2816 } else {
2817 /* drop through */
2818 qlt_24xx_process_atio_queue(vha, 1);
2819 }
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002820 case ABTS_RESP_24XX:
2821 case CTIO_TYPE7:
Quinn Tranf83adb62014-04-11 16:54:43 -04002822 case CTIO_CRC2:
Quinn Tran82de8022017-06-13 20:47:17 -07002823 qlt_response_pkt_all_vps(vha, rsp, (response_t *)pkt);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04002824 break;
Quinn Tran726b8542017-01-19 22:28:00 -08002825 case NOTIFY_ACK_TYPE:
2826 if (pkt->handle == QLA_TGT_SKIP_HANDLE)
Quinn Tran82de8022017-06-13 20:47:17 -07002827 qlt_response_pkt_all_vps(vha, rsp,
2828 (response_t *)pkt);
Quinn Tran726b8542017-01-19 22:28:00 -08002829 else
2830 qla24xxx_nack_iocb_entry(vha, rsp->req,
2831 (struct nack_to_isp *)pkt);
2832 break;
Saurav Kashyap54883292011-08-16 11:31:48 -07002833 case MARKER_TYPE:
2834 /* Do nothing in this case, this check is to prevent it
2835 * from falling into default case
2836 */
2837 break;
Armen Baloyan4440e462014-02-26 04:15:18 -05002838 case ABORT_IOCB_TYPE:
2839 qla24xx_abort_iocb_entry(vha, rsp->req,
2840 (struct abort_entry_24xx *)pkt);
2841 break;
Quinn Tran726b8542017-01-19 22:28:00 -08002842 case MBX_IOCB_TYPE:
2843 qla24xx_mbx_iocb_entry(vha, rsp->req,
2844 (struct mbx_24xx_entry *)pkt);
2845 break;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002846 default:
2847 /* Type Not Supported. */
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002848 ql_dbg(ql_dbg_async, vha, 0x5042,
2849 "Received unknown response pkt type %x "
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002850 "entry status=%x.\n",
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002851 pkt->entry_type, pkt->entry_status);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002852 break;
2853 }
2854 ((response_t *)pkt)->signature = RESPONSE_PROCESSED;
2855 wmb();
2856 }
2857
2858 /* Adjust ring index */
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -04002859 if (IS_P3P_TYPE(ha)) {
Giridhar Malavalia9083012010-04-12 17:59:55 -07002860 struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
2861 WRT_REG_DWORD(&reg->rsp_q_out[0], rsp->ring_index);
Quinn Tran726b8542017-01-19 22:28:00 -08002862 } else {
Giridhar Malavalia9083012010-04-12 17:59:55 -07002863 WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
Quinn Tran726b8542017-01-19 22:28:00 -08002864 }
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002865}
2866
Andrew Vasquez05236a02007-09-20 14:07:37 -07002867static void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002868qla2xxx_check_risc_status(scsi_qla_host_t *vha)
Andrew Vasquez05236a02007-09-20 14:07:37 -07002869{
2870 int rval;
2871 uint32_t cnt;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002872 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez05236a02007-09-20 14:07:37 -07002873 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
2874
Chad Dupuisf73cb692014-02-26 04:15:06 -05002875 if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
2876 !IS_QLA27XX(ha))
Andrew Vasquez05236a02007-09-20 14:07:37 -07002877 return;
2878
2879 rval = QLA_SUCCESS;
2880 WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
2881 RD_REG_DWORD(&reg->iobase_addr);
2882 WRT_REG_DWORD(&reg->iobase_window, 0x0001);
2883 for (cnt = 10000; (RD_REG_DWORD(&reg->iobase_window) & BIT_0) == 0 &&
2884 rval == QLA_SUCCESS; cnt--) {
2885 if (cnt) {
2886 WRT_REG_DWORD(&reg->iobase_window, 0x0001);
2887 udelay(10);
2888 } else
2889 rval = QLA_FUNCTION_TIMEOUT;
2890 }
2891 if (rval == QLA_SUCCESS)
2892 goto next_test;
2893
Bart Van Asscheb2ec76c2013-06-25 11:27:29 -04002894 rval = QLA_SUCCESS;
Andrew Vasquez05236a02007-09-20 14:07:37 -07002895 WRT_REG_DWORD(&reg->iobase_window, 0x0003);
2896 for (cnt = 100; (RD_REG_DWORD(&reg->iobase_window) & BIT_0) == 0 &&
2897 rval == QLA_SUCCESS; cnt--) {
2898 if (cnt) {
2899 WRT_REG_DWORD(&reg->iobase_window, 0x0003);
2900 udelay(10);
2901 } else
2902 rval = QLA_FUNCTION_TIMEOUT;
2903 }
2904 if (rval != QLA_SUCCESS)
2905 goto done;
2906
2907next_test:
2908 if (RD_REG_DWORD(&reg->iobase_c8) & BIT_3)
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002909 ql_log(ql_log_info, vha, 0x504c,
2910 "Additional code -- 0x55AA.\n");
Andrew Vasquez05236a02007-09-20 14:07:37 -07002911
2912done:
2913 WRT_REG_DWORD(&reg->iobase_window, 0x0000);
2914 RD_REG_DWORD(&reg->iobase_window);
2915}
2916
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002917/**
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08002918 * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP24xx.
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002919 * @irq:
2920 * @dev_id: SCSI driver HA context
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002921 *
2922 * Called by system whenever the host adapter generates an interrupt.
2923 *
2924 * Returns handled flag.
2925 */
2926irqreturn_t
David Howells7d12e782006-10-05 14:55:46 +01002927qla24xx_intr_handler(int irq, void *dev_id)
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002928{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002929 scsi_qla_host_t *vha;
2930 struct qla_hw_data *ha;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002931 struct device_reg_24xx __iomem *reg;
2932 int status;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002933 unsigned long iter;
2934 uint32_t stat;
2935 uint32_t hccr;
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04002936 uint16_t mb[8];
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002937 struct rsp_que *rsp;
Anirban Chakraborty43fac4d2009-06-10 13:55:11 -07002938 unsigned long flags;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002939
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002940 rsp = (struct rsp_que *) dev_id;
2941 if (!rsp) {
Chad Dupuis3256b432012-02-09 11:15:47 -08002942 ql_log(ql_log_info, NULL, 0x5059,
2943 "%s: NULL response queue pointer.\n", __func__);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002944 return IRQ_NONE;
2945 }
2946
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002947 ha = rsp->hw;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002948 reg = &ha->iobase->isp24;
2949 status = 0;
2950
Andrew Vasquez85880802009-12-15 21:29:46 -08002951 if (unlikely(pci_channel_offline(ha->pdev)))
2952 return IRQ_HANDLED;
2953
Anirban Chakraborty43fac4d2009-06-10 13:55:11 -07002954 spin_lock_irqsave(&ha->hardware_lock, flags);
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002955 vha = pci_get_drvdata(ha->pdev);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002956 for (iter = 50; iter--; ) {
2957 stat = RD_REG_DWORD(&reg->host_status);
Joe Lawrencec821e0d2014-08-26 17:11:41 -04002958 if (qla2x00_check_reg32_for_disconnect(vha, stat))
Chad Dupuisf3ddac12013-10-30 03:38:16 -04002959 break;
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002960 if (stat & HSRX_RISC_PAUSED) {
Andrew Vasquez85880802009-12-15 21:29:46 -08002961 if (unlikely(pci_channel_offline(ha->pdev)))
Seokmann Ju14e660e2007-09-20 14:07:36 -07002962 break;
2963
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002964 hccr = RD_REG_DWORD(&reg->hccr);
2965
Saurav Kashyap7c3df132011-07-14 12:00:13 -07002966 ql_log(ql_log_warn, vha, 0x504b,
2967 "RISC paused -- HCCR=%x, Dumping firmware.\n",
2968 hccr);
Andrew Vasquez05236a02007-09-20 14:07:37 -07002969
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002970 qla2xxx_check_risc_status(vha);
Andrew Vasquez05236a02007-09-20 14:07:37 -07002971
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002972 ha->isp_ops->fw_dump(vha, 1);
2973 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002974 break;
2975 } else if ((stat & HSRX_RISC_INT) == 0)
2976 break;
2977
2978 switch (stat & 0xff) {
Arun Easifafbda92012-08-22 14:21:16 -04002979 case INTR_ROM_MB_SUCCESS:
2980 case INTR_ROM_MB_FAILED:
2981 case INTR_MB_SUCCESS:
2982 case INTR_MB_FAILED:
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08002983 qla24xx_mbx_completion(vha, MSW(stat));
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002984 status |= MBX_INTERRUPT;
2985
2986 break;
Arun Easifafbda92012-08-22 14:21:16 -04002987 case INTR_ASYNC_EVENT:
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002988 mb[0] = MSW(stat);
2989 mb[1] = RD_REG_WORD(&reg->mailbox1);
2990 mb[2] = RD_REG_WORD(&reg->mailbox2);
2991 mb[3] = RD_REG_WORD(&reg->mailbox3);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08002992 qla2x00_async_event(vha, rsp, mb);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002993 break;
Arun Easifafbda92012-08-22 14:21:16 -04002994 case INTR_RSP_QUE_UPDATE:
2995 case INTR_RSP_QUE_UPDATE_83XX:
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07002996 qla24xx_process_response_queue(vha, rsp);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07002997 break;
Quinn Tran2f424b92015-12-17 14:57:07 -05002998 case INTR_ATIO_QUE_UPDATE:{
2999 unsigned long flags2;
3000 spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
3001 qlt_24xx_process_atio_queue(vha, 1);
3002 spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003003 break;
Quinn Tran2f424b92015-12-17 14:57:07 -05003004 }
3005 case INTR_ATIO_RSP_QUE_UPDATE: {
3006 unsigned long flags2;
3007 spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
3008 qlt_24xx_process_atio_queue(vha, 1);
3009 spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2);
3010
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003011 qla24xx_process_response_queue(vha, rsp);
3012 break;
Quinn Tran2f424b92015-12-17 14:57:07 -05003013 }
Andrew Vasquez9a853f72005-07-06 10:31:27 -07003014 default:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003015 ql_dbg(ql_dbg_async, vha, 0x504f,
3016 "Unrecognized interrupt type (%d).\n", stat * 0xff);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07003017 break;
3018 }
3019 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
3020 RD_REG_DWORD_RELAXED(&reg->hccr);
Giridhar Malavalicb860bb2012-08-22 14:21:30 -04003021 if (unlikely(IS_QLA83XX(ha) && (ha->pdev->revision == 1)))
3022 ndelay(3500);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07003023 }
gurinder.shergill@hp.com36439832013-04-23 10:13:17 -07003024 qla2x00_handle_mbx_completion(ha, status);
Anirban Chakraborty43fac4d2009-06-10 13:55:11 -07003025 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Andrew Vasquez9a853f72005-07-06 10:31:27 -07003026
Andrew Vasquez9a853f72005-07-06 10:31:27 -07003027 return IRQ_HANDLED;
3028}
3029
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003030static irqreturn_t
3031qla24xx_msix_rsp_q(int irq, void *dev_id)
3032{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003033 struct qla_hw_data *ha;
3034 struct rsp_que *rsp;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003035 struct device_reg_24xx __iomem *reg;
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003036 struct scsi_qla_host *vha;
Xiaotian Feng0f19bc62010-01-29 18:09:30 +08003037 unsigned long flags;
Chad Dupuisf3ddac12013-10-30 03:38:16 -04003038 uint32_t stat = 0;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003039
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003040 rsp = (struct rsp_que *) dev_id;
3041 if (!rsp) {
Chad Dupuis3256b432012-02-09 11:15:47 -08003042 ql_log(ql_log_info, NULL, 0x505a,
3043 "%s: NULL response queue pointer.\n", __func__);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003044 return IRQ_NONE;
3045 }
3046 ha = rsp->hw;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003047 reg = &ha->iobase->isp24;
3048
Xiaotian Feng0f19bc62010-01-29 18:09:30 +08003049 spin_lock_irqsave(&ha->hardware_lock, flags);
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003050
Anirban Chakrabortya67093d2010-02-04 14:17:59 -08003051 vha = pci_get_drvdata(ha->pdev);
Chad Dupuisf3ddac12013-10-30 03:38:16 -04003052 /*
3053 * Use host_status register to check to PCI disconnection before we
3054 * we process the response queue.
3055 */
3056 stat = RD_REG_DWORD(&reg->host_status);
Joe Lawrencec821e0d2014-08-26 17:11:41 -04003057 if (qla2x00_check_reg32_for_disconnect(vha, stat))
Chad Dupuisf3ddac12013-10-30 03:38:16 -04003058 goto out;
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003059 qla24xx_process_response_queue(vha, rsp);
Anirban Chakraborty31557542009-12-02 10:36:55 -08003060 if (!ha->flags.disable_msix_handshake) {
Anirban Chakrabortyeb941142009-08-04 16:12:13 -07003061 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
3062 RD_REG_DWORD_RELAXED(&reg->hccr);
3063 }
Chad Dupuisf3ddac12013-10-30 03:38:16 -04003064out:
Xiaotian Feng0f19bc62010-01-29 18:09:30 +08003065 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003066
3067 return IRQ_HANDLED;
3068}
3069
3070static irqreturn_t
3071qla24xx_msix_default(int irq, void *dev_id)
3072{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003073 scsi_qla_host_t *vha;
3074 struct qla_hw_data *ha;
3075 struct rsp_que *rsp;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003076 struct device_reg_24xx __iomem *reg;
3077 int status;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003078 uint32_t stat;
3079 uint32_t hccr;
Santosh Vernekar7d613ac2012-08-22 14:21:03 -04003080 uint16_t mb[8];
Xiaotian Feng0f19bc62010-01-29 18:09:30 +08003081 unsigned long flags;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003082
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003083 rsp = (struct rsp_que *) dev_id;
3084 if (!rsp) {
Chad Dupuis3256b432012-02-09 11:15:47 -08003085 ql_log(ql_log_info, NULL, 0x505c,
3086 "%s: NULL response queue pointer.\n", __func__);
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003087 return IRQ_NONE;
3088 }
3089 ha = rsp->hw;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003090 reg = &ha->iobase->isp24;
3091 status = 0;
3092
Xiaotian Feng0f19bc62010-01-29 18:09:30 +08003093 spin_lock_irqsave(&ha->hardware_lock, flags);
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003094 vha = pci_get_drvdata(ha->pdev);
Andrew Vasquez87f27012007-09-20 14:07:49 -07003095 do {
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003096 stat = RD_REG_DWORD(&reg->host_status);
Joe Lawrencec821e0d2014-08-26 17:11:41 -04003097 if (qla2x00_check_reg32_for_disconnect(vha, stat))
Chad Dupuisf3ddac12013-10-30 03:38:16 -04003098 break;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003099 if (stat & HSRX_RISC_PAUSED) {
Andrew Vasquez85880802009-12-15 21:29:46 -08003100 if (unlikely(pci_channel_offline(ha->pdev)))
Seokmann Ju14e660e2007-09-20 14:07:36 -07003101 break;
3102
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003103 hccr = RD_REG_DWORD(&reg->hccr);
3104
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003105 ql_log(ql_log_info, vha, 0x5050,
3106 "RISC paused -- HCCR=%x, Dumping firmware.\n",
3107 hccr);
Andrew Vasquez05236a02007-09-20 14:07:37 -07003108
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003109 qla2xxx_check_risc_status(vha);
Andrew Vasquez05236a02007-09-20 14:07:37 -07003110
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003111 ha->isp_ops->fw_dump(vha, 1);
3112 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003113 break;
3114 } else if ((stat & HSRX_RISC_INT) == 0)
3115 break;
3116
3117 switch (stat & 0xff) {
Arun Easifafbda92012-08-22 14:21:16 -04003118 case INTR_ROM_MB_SUCCESS:
3119 case INTR_ROM_MB_FAILED:
3120 case INTR_MB_SUCCESS:
3121 case INTR_MB_FAILED:
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003122 qla24xx_mbx_completion(vha, MSW(stat));
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003123 status |= MBX_INTERRUPT;
3124
3125 break;
Arun Easifafbda92012-08-22 14:21:16 -04003126 case INTR_ASYNC_EVENT:
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003127 mb[0] = MSW(stat);
3128 mb[1] = RD_REG_WORD(&reg->mailbox1);
3129 mb[2] = RD_REG_WORD(&reg->mailbox2);
3130 mb[3] = RD_REG_WORD(&reg->mailbox3);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003131 qla2x00_async_event(vha, rsp, mb);
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003132 break;
Arun Easifafbda92012-08-22 14:21:16 -04003133 case INTR_RSP_QUE_UPDATE:
3134 case INTR_RSP_QUE_UPDATE_83XX:
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003135 qla24xx_process_response_queue(vha, rsp);
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003136 break;
Quinn Tran2f424b92015-12-17 14:57:07 -05003137 case INTR_ATIO_QUE_UPDATE:{
3138 unsigned long flags2;
3139 spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
3140 qlt_24xx_process_atio_queue(vha, 1);
3141 spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2);
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003142 break;
Quinn Tran2f424b92015-12-17 14:57:07 -05003143 }
3144 case INTR_ATIO_RSP_QUE_UPDATE: {
3145 unsigned long flags2;
3146 spin_lock_irqsave(&ha->tgt.atio_lock, flags2);
3147 qlt_24xx_process_atio_queue(vha, 1);
3148 spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2);
3149
Nicholas Bellinger2d70c102012-05-15 14:34:28 -04003150 qla24xx_process_response_queue(vha, rsp);
3151 break;
Quinn Tran2f424b92015-12-17 14:57:07 -05003152 }
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003153 default:
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003154 ql_dbg(ql_dbg_async, vha, 0x5051,
3155 "Unrecognized interrupt type (%d).\n", stat & 0xff);
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003156 break;
3157 }
3158 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
Andrew Vasquez87f27012007-09-20 14:07:49 -07003159 } while (0);
gurinder.shergill@hp.com36439832013-04-23 10:13:17 -07003160 qla2x00_handle_mbx_completion(ha, status);
Xiaotian Feng0f19bc62010-01-29 18:09:30 +08003161 spin_unlock_irqrestore(&ha->hardware_lock, flags);
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003162
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003163 return IRQ_HANDLED;
3164}
3165
Michael Hernandezd7459522016-12-12 14:40:07 -08003166irqreturn_t
3167qla2xxx_msix_rsp_q(int irq, void *dev_id)
3168{
3169 struct qla_hw_data *ha;
3170 struct qla_qpair *qpair;
3171 struct device_reg_24xx __iomem *reg;
3172 unsigned long flags;
3173
3174 qpair = dev_id;
3175 if (!qpair) {
3176 ql_log(ql_log_info, NULL, 0x505b,
3177 "%s: NULL response queue pointer.\n", __func__);
3178 return IRQ_NONE;
3179 }
3180 ha = qpair->hw;
3181
3182 /* Clear the interrupt, if enabled, for this response queue */
3183 if (unlikely(!ha->flags.disable_msix_handshake)) {
3184 reg = &ha->iobase->isp24;
3185 spin_lock_irqsave(&ha->hardware_lock, flags);
3186 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
3187 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3188 }
3189
3190 queue_work(ha->wq, &qpair->q_work);
3191
3192 return IRQ_HANDLED;
3193}
3194
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003195/* Interrupt handling helpers. */
3196
3197struct qla_init_msix_entry {
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003198 const char *name;
Jeff Garzik476834c2007-05-23 14:41:44 -07003199 irq_handler_t handler;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003200};
3201
Nicolas Iooss44a8f952016-12-26 14:23:10 +01003202static const struct qla_init_msix_entry msix_entries[] = {
Quinn Trane326d222017-06-13 20:47:18 -07003203 { "default", qla24xx_msix_default },
3204 { "rsp_q", qla24xx_msix_rsp_q },
3205 { "atio_q", qla83xx_msix_atio_q },
3206 { "qpair_multiq", qla2xxx_msix_rsp_q },
Arun Easiaa230bc2013-01-30 03:34:39 -05003207};
3208
Nicolas Iooss44a8f952016-12-26 14:23:10 +01003209static const struct qla_init_msix_entry qla82xx_msix_entries[] = {
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003210 { "qla2xxx (default)", qla82xx_msix_default },
3211 { "qla2xxx (rsp_q)", qla82xx_msix_rsp_q },
Anirban Chakraborty68ca9492009-04-06 22:33:41 -07003212};
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003213
3214static int
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003215qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003216{
3217 int i, ret;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003218 struct qla_msix_entry *qentry;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003219 scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
Michael Hernandez67f2db82017-02-15 15:37:21 -08003220 int min_vecs = QLA_BASE_VECTORS;
Christoph Hellwig17e5fc52017-01-11 17:55:45 +01003221 struct irq_affinity desc = {
3222 .pre_vectors = QLA_BASE_VECTORS,
3223 };
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003224
Michael Hernandez67f2db82017-02-15 15:37:21 -08003225 if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
Christoph Hellwig17e5fc52017-01-11 17:55:45 +01003226 desc.pre_vectors++;
Michael Hernandez67f2db82017-02-15 15:37:21 -08003227 min_vecs++;
3228 }
Christoph Hellwig17e5fc52017-01-11 17:55:45 +01003229
Quinn Tran09620ee2017-06-13 20:47:20 -07003230 if (USER_CTRL_IRQ(ha)) {
3231 /* user wants to control IRQ setting for target mode */
3232 ret = pci_alloc_irq_vectors(ha->pdev, min_vecs,
3233 ha->msix_count, PCI_IRQ_MSIX);
3234 } else
3235 ret = pci_alloc_irq_vectors_affinity(ha->pdev, min_vecs,
3236 ha->msix_count, PCI_IRQ_MSIX | PCI_IRQ_AFFINITY,
3237 &desc);
Christoph Hellwig17e5fc52017-01-11 17:55:45 +01003238
Alexander Gordeev84e32a02014-08-18 08:01:47 +02003239 if (ret < 0) {
3240 ql_log(ql_log_fatal, vha, 0x00c7,
3241 "MSI-X: Failed to enable support, "
3242 "giving up -- %d/%d.\n",
3243 ha->msix_count, ret);
3244 goto msix_out;
3245 } else if (ret < ha->msix_count) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003246 ql_log(ql_log_warn, vha, 0x00c6,
3247 "MSI-X: Failed to enable support "
Michael Hernandezd7459522016-12-12 14:40:07 -08003248 "with %d vectors, using %d vectors.\n",
3249 ha->msix_count, ret);
Quinn Trancb432852016-02-04 11:45:16 -05003250 ha->msix_count = ret;
Michael Hernandezd7459522016-12-12 14:40:07 -08003251 /* Recalculate queue values */
3252 if (ha->mqiobase && ql2xmqsupport) {
3253 ha->max_req_queues = ha->msix_count - 1;
3254
3255 /* ATIOQ needs 1 vector. That's 1 less QPair */
3256 if (QLA_TGT_MODE_ENABLED())
3257 ha->max_req_queues--;
3258
3259 ha->max_rsp_queues = ha->max_req_queues;
3260
3261 ha->max_qpairs = ha->max_req_queues - 1;
3262 ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0190,
3263 "Adjusted Max no of queues pairs: %d.\n", ha->max_qpairs);
3264 }
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003265 }
3266 ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) *
3267 ha->msix_count, GFP_KERNEL);
3268 if (!ha->msix_entries) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003269 ql_log(ql_log_fatal, vha, 0x00c8,
3270 "Failed to allocate memory for ha->msix_entries.\n");
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003271 ret = -ENOMEM;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003272 goto msix_out;
3273 }
3274 ha->flags.msix_enabled = 1;
3275
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003276 for (i = 0; i < ha->msix_count; i++) {
3277 qentry = &ha->msix_entries[i];
Michael Hernandez4fa18342016-12-12 14:40:06 -08003278 qentry->vector = pci_irq_vector(ha->pdev, i);
3279 qentry->entry = i;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003280 qentry->have_irq = 0;
Michael Hernandezd7459522016-12-12 14:40:07 -08003281 qentry->in_use = 0;
Michael Hernandez4fa18342016-12-12 14:40:06 -08003282 qentry->handle = NULL;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003283 }
3284
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003285 /* Enable MSI-X vectors for the base queue */
Christoph Hellwig17e5fc52017-01-11 17:55:45 +01003286 for (i = 0; i < QLA_BASE_VECTORS; i++) {
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003287 qentry = &ha->msix_entries[i];
Michael Hernandez4fa18342016-12-12 14:40:06 -08003288 qentry->handle = rsp;
Johannes Thumshirnef8d1d512016-07-06 09:51:50 +02003289 rsp->msix = qentry;
Michael Hernandezd7459522016-12-12 14:40:07 -08003290 scnprintf(qentry->name, sizeof(qentry->name),
Quinn Trane326d222017-06-13 20:47:18 -07003291 "qla2xxx%lu_%s", vha->host_no, msix_entries[i].name);
Chad Dupuisf3247772014-02-26 04:15:14 -05003292 if (IS_P3P_TYPE(ha))
Giridhar Malavalia9083012010-04-12 17:59:55 -07003293 ret = request_irq(qentry->vector,
3294 qla82xx_msix_entries[i].handler,
3295 0, qla82xx_msix_entries[i].name, rsp);
Chad Dupuisf3247772014-02-26 04:15:14 -05003296 else
Giridhar Malavalia9083012010-04-12 17:59:55 -07003297 ret = request_irq(qentry->vector,
3298 msix_entries[i].handler,
Quinn Trane326d222017-06-13 20:47:18 -07003299 0, qentry->name, rsp);
Chad Dupuisf3247772014-02-26 04:15:14 -05003300 if (ret)
3301 goto msix_register_fail;
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -07003302 qentry->have_irq = 1;
Quinn Tran093df732016-12-12 14:40:09 -08003303 qentry->in_use = 1;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003304 }
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003305
Chad Dupuisf3247772014-02-26 04:15:14 -05003306 /*
3307 * If target mode is enable, also request the vector for the ATIO
3308 * queue.
3309 */
3310 if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
Quinn Tran093df732016-12-12 14:40:09 -08003311 qentry = &ha->msix_entries[QLA_ATIO_VECTOR];
Johannes Thumshirnef8d1d512016-07-06 09:51:50 +02003312 rsp->msix = qentry;
Michael Hernandezd7459522016-12-12 14:40:07 -08003313 qentry->handle = rsp;
3314 scnprintf(qentry->name, sizeof(qentry->name),
Quinn Trane326d222017-06-13 20:47:18 -07003315 "qla2xxx%lu_%s", vha->host_no,
3316 msix_entries[QLA_ATIO_VECTOR].name);
Quinn Tran093df732016-12-12 14:40:09 -08003317 qentry->in_use = 1;
Chad Dupuisf3247772014-02-26 04:15:14 -05003318 ret = request_irq(qentry->vector,
Quinn Tran093df732016-12-12 14:40:09 -08003319 msix_entries[QLA_ATIO_VECTOR].handler,
Quinn Trane326d222017-06-13 20:47:18 -07003320 0, qentry->name, rsp);
Chad Dupuisf3247772014-02-26 04:15:14 -05003321 qentry->have_irq = 1;
Chad Dupuisf3247772014-02-26 04:15:14 -05003322 }
3323
3324msix_register_fail:
3325 if (ret) {
3326 ql_log(ql_log_fatal, vha, 0x00cb,
3327 "MSI-X: unable to register handler -- %x/%d.\n",
3328 qentry->vector, ret);
Michael Hernandez4fa18342016-12-12 14:40:06 -08003329 qla2x00_free_irqs(vha);
Chad Dupuisf3247772014-02-26 04:15:14 -05003330 ha->mqenable = 0;
3331 goto msix_out;
3332 }
3333
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003334 /* Enable MSI-X vector for response queue update for queue 0 */
himanshu.madhani@cavium.comcb590702017-05-24 18:06:18 -07003335 if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003336 if (ha->msixbase && ha->mqiobase &&
Michael Hernandezd7459522016-12-12 14:40:07 -08003337 (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
3338 ql2xmqsupport))
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003339 ha->mqenable = 1;
3340 } else
Michael Hernandezd7459522016-12-12 14:40:07 -08003341 if (ha->mqiobase &&
3342 (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
3343 ql2xmqsupport))
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003344 ha->mqenable = 1;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003345 ql_dbg(ql_dbg_multiq, vha, 0xc005,
3346 "mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n",
3347 ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
3348 ql_dbg(ql_dbg_init, vha, 0x0055,
3349 "mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n",
3350 ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003351
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003352msix_out:
3353 return ret;
3354}
3355
3356int
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003357qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003358{
Sawan Chandak7fa3e232013-10-30 03:38:10 -04003359 int ret = QLA_FUNCTION_FAILED;
Chad Dupuisf73cb692014-02-26 04:15:06 -05003360 device_reg_t *reg = ha->iobase;
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003361 scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003362
3363 /* If possible, enable MSI-X. */
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08003364 if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
Chad Dupuisf73cb692014-02-26 04:15:06 -05003365 !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && !IS_QLAFX00(ha) &&
3366 !IS_QLA27XX(ha))
Ben Hutchings6377a7a2010-03-19 16:59:19 -07003367 goto skip_msi;
3368
3369 if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
3370 (ha->pdev->subsystem_device == 0x7040 ||
3371 ha->pdev->subsystem_device == 0x7041 ||
3372 ha->pdev->subsystem_device == 0x1705)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003373 ql_log(ql_log_warn, vha, 0x0034,
3374 "MSI-X: Unsupported ISP 2432 SSVID/SSDID (0x%X,0x%X).\n",
Ben Hutchings6377a7a2010-03-19 16:59:19 -07003375 ha->pdev->subsystem_vendor,
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003376 ha->pdev->subsystem_device);
Ben Hutchings6377a7a2010-03-19 16:59:19 -07003377 goto skip_msi;
3378 }
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003379
Chad Dupuis42cd4f52011-08-16 11:29:24 -07003380 if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX)) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003381 ql_log(ql_log_warn, vha, 0x0035,
3382 "MSI-X; Unsupported ISP2432 (0x%X, 0x%X).\n",
Chad Dupuis42cd4f52011-08-16 11:29:24 -07003383 ha->pdev->revision, QLA_MSIX_CHIP_REV_24XX);
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003384 goto skip_msix;
3385 }
3386
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003387 ret = qla24xx_enable_msix(ha, rsp);
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003388 if (!ret) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003389 ql_dbg(ql_dbg_init, vha, 0x0036,
3390 "MSI-X: Enabled (0x%X, 0x%X).\n",
3391 ha->chip_revision, ha->fw_attributes);
Andrew Vasquez963b0fd2008-01-31 12:33:50 -08003392 goto clear_risc_ints;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003393 }
Sawan Chandak7fa3e232013-10-30 03:38:10 -04003394
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003395skip_msix:
Andrew Vasquezcbedb602007-05-07 07:43:02 -07003396
Sawan Chandak7fa3e232013-10-30 03:38:10 -04003397 ql_log(ql_log_info, vha, 0x0037,
3398 "Falling back-to MSI mode -%d.\n", ret);
3399
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08003400 if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
Chad Dupuisf73cb692014-02-26 04:15:06 -05003401 !IS_QLA8001(ha) && !IS_P3P_TYPE(ha) && !IS_QLAFX00(ha) &&
3402 !IS_QLA27XX(ha))
Andrew Vasquezcbedb602007-05-07 07:43:02 -07003403 goto skip_msi;
3404
Michael Hernandez4fa18342016-12-12 14:40:06 -08003405 ret = pci_alloc_irq_vectors(ha->pdev, 1, 1, PCI_IRQ_MSI);
Andrew Vasquezcbedb602007-05-07 07:43:02 -07003406 if (!ret) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003407 ql_dbg(ql_dbg_init, vha, 0x0038,
3408 "MSI: Enabled.\n");
Andrew Vasquezcbedb602007-05-07 07:43:02 -07003409 ha->flags.msi_enabled = 1;
Giridhar Malavalia9083012010-04-12 17:59:55 -07003410 } else
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003411 ql_log(ql_log_warn, vha, 0x0039,
Sawan Chandak7fa3e232013-10-30 03:38:10 -04003412 "Falling back-to INTa mode -- %d.\n", ret);
3413skip_msi:
Giridhar Malavalia033b652012-08-22 14:21:07 -04003414
3415 /* Skip INTx on ISP82xx. */
3416 if (!ha->flags.msi_enabled && IS_QLA82XX(ha))
3417 return QLA_FUNCTION_FAILED;
3418
Andrew Vasquezfd34f552007-07-19 15:06:00 -07003419 ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
Mike Hernandez7992abf2010-11-23 16:52:47 -08003420 ha->flags.msi_enabled ? 0 : IRQF_SHARED,
3421 QLA2XXX_DRIVER_NAME, rsp);
Andrew Vasquez963b0fd2008-01-31 12:33:50 -08003422 if (ret) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003423 ql_log(ql_log_warn, vha, 0x003a,
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003424 "Failed to reserve interrupt %d already in use.\n",
3425 ha->pdev->irq);
Andrew Vasquez963b0fd2008-01-31 12:33:50 -08003426 goto fail;
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003427 } else if (!ha->flags.msi_enabled) {
Saurav Kashyap68d91cb2012-11-21 02:40:44 -05003428 ql_dbg(ql_dbg_init, vha, 0x0125,
3429 "INTa mode: Enabled.\n");
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04003430 ha->flags.mr_intr_valid = 1;
3431 }
Mike Hernandez7992abf2010-11-23 16:52:47 -08003432
Andrew Vasquez963b0fd2008-01-31 12:33:50 -08003433clear_risc_ints:
Joe Carnuccio4bb2efc2014-09-25 05:16:42 -04003434 if (IS_FWI2_CAPABLE(ha) || IS_QLAFX00(ha))
3435 goto fail;
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003436
Andrew Vasquezc6952482008-04-03 13:13:17 -07003437 spin_lock_irq(&ha->hardware_lock);
Joe Carnuccio4bb2efc2014-09-25 05:16:42 -04003438 WRT_REG_WORD(&reg->isp.semaphore, 0);
Andrew Vasquezc6952482008-04-03 13:13:17 -07003439 spin_unlock_irq(&ha->hardware_lock);
Andrew Vasquez963b0fd2008-01-31 12:33:50 -08003440
3441fail:
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003442 return ret;
3443}
3444
3445void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003446qla2x00_free_irqs(scsi_qla_host_t *vha)
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003447{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003448 struct qla_hw_data *ha = vha->hw;
Chad Dupuis9a347ff2012-05-15 14:34:14 -04003449 struct rsp_que *rsp;
Michael Hernandez4fa18342016-12-12 14:40:06 -08003450 struct qla_msix_entry *qentry;
3451 int i;
Chad Dupuis9a347ff2012-05-15 14:34:14 -04003452
3453 /*
3454 * We need to check that ha->rsp_q_map is valid in case we are called
3455 * from a probe failure context.
3456 */
3457 if (!ha->rsp_q_map || !ha->rsp_q_map[0])
Bart Van Assche27873de2017-01-23 08:34:45 -08003458 goto free_irqs;
Chad Dupuis9a347ff2012-05-15 14:34:14 -04003459 rsp = ha->rsp_q_map[0];
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003460
Michael Hernandez4fa18342016-12-12 14:40:06 -08003461 if (ha->flags.msix_enabled) {
3462 for (i = 0; i < ha->msix_count; i++) {
3463 qentry = &ha->msix_entries[i];
3464 if (qentry->have_irq) {
3465 irq_set_affinity_notifier(qentry->vector, NULL);
3466 free_irq(pci_irq_vector(ha->pdev, i), qentry->handle);
3467 }
3468 }
3469 kfree(ha->msix_entries);
3470 ha->msix_entries = NULL;
3471 ha->flags.msix_enabled = 0;
3472 ql_dbg(ql_dbg_init, vha, 0x0042,
3473 "Disabled MSI-X.\n");
3474 } else {
3475 free_irq(pci_irq_vector(ha->pdev, 0), rsp);
3476 }
3477
Bart Van Assche27873de2017-01-23 08:34:45 -08003478free_irqs:
Michael Hernandez4fa18342016-12-12 14:40:06 -08003479 pci_free_irq_vectors(ha->pdev);
Andrew Vasqueza8488ab2007-01-29 10:22:19 -08003480}
Anirban Chakrabortye315cd22008-11-06 10:40:51 -08003481
Michael Hernandezd7459522016-12-12 14:40:07 -08003482int qla25xx_request_irq(struct qla_hw_data *ha, struct qla_qpair *qpair,
3483 struct qla_msix_entry *msix, int vector_type)
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003484{
Nicolas Iooss44a8f952016-12-26 14:23:10 +01003485 const struct qla_init_msix_entry *intr = &msix_entries[vector_type];
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003486 scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003487 int ret;
3488
Michael Hernandezd7459522016-12-12 14:40:07 -08003489 scnprintf(msix->name, sizeof(msix->name),
3490 "qla2xxx%lu_qpair%d", vha->host_no, qpair->id);
3491 ret = request_irq(msix->vector, intr->handler, 0, msix->name, qpair);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003492 if (ret) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07003493 ql_log(ql_log_fatal, vha, 0x00e6,
3494 "MSI-X: Unable to register handler -- %x/%d.\n",
3495 msix->vector, ret);
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003496 return ret;
3497 }
3498 msix->have_irq = 1;
Michael Hernandezd7459522016-12-12 14:40:07 -08003499 msix->handle = qpair;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08003500 return ret;
3501}