qla_isr.c 54.8 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
A
Andrew Vasquez 已提交
2
 * QLogic Fibre Channel HBA Driver
3
 * Copyright (c)  2003-2008 QLogic Corporation
L
Linus Torvalds 已提交
4
 *
A
Andrew Vasquez 已提交
5
 * See LICENSE.qla2xxx for copyright and licensing details.
L
Linus Torvalds 已提交
6 7 8
 */
#include "qla_def.h"

9
#include <linux/delay.h>
10 11
#include <scsi/scsi_tcq.h>

L
Linus Torvalds 已提交
12
static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
13 14 15
static void qla2x00_process_completed_request(struct scsi_qla_host *,
	struct req_que *, uint32_t);
static void qla2x00_status_entry(scsi_qla_host_t *, struct rsp_que *, void *);
L
Linus Torvalds 已提交
16
static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
17 18
static void qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
	sts_entry_t *);
19
static struct scsi_qla_host *qla2x00_get_rsp_host(struct rsp_que *);
20

L
Linus Torvalds 已提交
21 22 23 24 25 26 27 28 29 30
/**
 * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
 * @irq:
 * @dev_id: SCSI driver HA context
 *
 * Called by system whenever the host adapter generates an interrupt.
 *
 * Returns handled flag.
 */
irqreturn_t
31
qla2100_intr_handler(int irq, void *dev_id)
L
Linus Torvalds 已提交
32
{
33 34
	scsi_qla_host_t	*vha;
	struct qla_hw_data *ha;
35
	struct device_reg_2xxx __iomem *reg;
L
Linus Torvalds 已提交
36 37
	int		status;
	unsigned long	iter;
38
	uint16_t	hccr;
39
	uint16_t	mb[4];
40
	struct rsp_que *rsp;
L
Linus Torvalds 已提交
41

42 43
	rsp = (struct rsp_que *) dev_id;
	if (!rsp) {
L
Linus Torvalds 已提交
44
		printk(KERN_INFO
45
		    "%s(): NULL response queue pointer\n", __func__);
L
Linus Torvalds 已提交
46 47 48
		return (IRQ_NONE);
	}

49
	ha = rsp->hw;
50
	reg = &ha->iobase->isp;
L
Linus Torvalds 已提交
51 52
	status = 0;

53
	spin_lock(&ha->hardware_lock);
54
	vha = qla2x00_get_rsp_host(rsp);
L
Linus Torvalds 已提交
55
	for (iter = 50; iter--; ) {
56 57 58 59 60 61 62 63 64 65 66 67 68
		hccr = RD_REG_WORD(&reg->hccr);
		if (hccr & HCCR_RISC_PAUSE) {
			if (pci_channel_offline(ha->pdev))
				break;

			/*
			 * Issue a "HARD" reset in order for the RISC interrupt
			 * bit to be cleared.  Schedule a big hammmer to get
			 * out of the RISC PAUSED state.
			 */
			WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
			RD_REG_WORD(&reg->hccr);

69 70
			ha->isp_ops->fw_dump(vha, 1);
			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
71 72
			break;
		} else if ((RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) == 0)
L
Linus Torvalds 已提交
73 74 75 76 77 78 79
			break;

		if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
			WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
			RD_REG_WORD(&reg->hccr);

			/* Get mailbox data. */
80 81
			mb[0] = RD_MAILBOX_REG(ha, reg, 0);
			if (mb[0] > 0x3fff && mb[0] < 0x8000) {
82
				qla2x00_mbx_completion(vha, mb[0]);
L
Linus Torvalds 已提交
83
				status |= MBX_INTERRUPT;
84 85 86 87
			} else if (mb[0] > 0x7fff && mb[0] < 0xc000) {
				mb[1] = RD_MAILBOX_REG(ha, reg, 1);
				mb[2] = RD_MAILBOX_REG(ha, reg, 2);
				mb[3] = RD_MAILBOX_REG(ha, reg, 3);
88
				qla2x00_async_event(vha, rsp, mb);
L
Linus Torvalds 已提交
89 90 91
			} else {
				/*EMPTY*/
				DEBUG2(printk("scsi(%ld): Unrecognized "
92
				    "interrupt type (%d).\n",
93
				    vha->host_no, mb[0]));
L
Linus Torvalds 已提交
94 95 96 97 98
			}
			/* Release mailbox registers. */
			WRT_REG_WORD(&reg->semaphore, 0);
			RD_REG_WORD(&reg->semaphore);
		} else {
99
			qla2x00_process_response_queue(rsp);
L
Linus Torvalds 已提交
100 101 102 103 104

			WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
			RD_REG_WORD(&reg->hccr);
		}
	}
105
	spin_unlock(&ha->hardware_lock);
L
Linus Torvalds 已提交
106 107 108 109

	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
110
		complete(&ha->mbx_intr_comp);
L
Linus Torvalds 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
	}

	return (IRQ_HANDLED);
}

/**
 * qla2300_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
 * @irq:
 * @dev_id: SCSI driver HA context
 *
 * Called by system whenever the host adapter generates an interrupt.
 *
 * Returns handled flag.
 */
irqreturn_t
126
qla2300_intr_handler(int irq, void *dev_id)
L
Linus Torvalds 已提交
127
{
128
	scsi_qla_host_t	*vha;
129
	struct device_reg_2xxx __iomem *reg;
L
Linus Torvalds 已提交
130 131 132 133
	int		status;
	unsigned long	iter;
	uint32_t	stat;
	uint16_t	hccr;
134
	uint16_t	mb[4];
135 136
	struct rsp_que *rsp;
	struct qla_hw_data *ha;
L
Linus Torvalds 已提交
137

138 139
	rsp = (struct rsp_que *) dev_id;
	if (!rsp) {
L
Linus Torvalds 已提交
140
		printk(KERN_INFO
141
		    "%s(): NULL response queue pointer\n", __func__);
L
Linus Torvalds 已提交
142 143 144
		return (IRQ_NONE);
	}

145
	ha = rsp->hw;
146
	reg = &ha->iobase->isp;
L
Linus Torvalds 已提交
147 148
	status = 0;

149
	spin_lock(&ha->hardware_lock);
150
	vha = qla2x00_get_rsp_host(rsp);
L
Linus Torvalds 已提交
151 152 153
	for (iter = 50; iter--; ) {
		stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
		if (stat & HSR_RISC_PAUSED) {
154 155 156
			if (pci_channel_offline(ha->pdev))
				break;

L
Linus Torvalds 已提交
157 158
			hccr = RD_REG_WORD(&reg->hccr);
			if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
159 160
				qla_printk(KERN_INFO, ha, "Parity error -- "
				    "HCCR=%x, Dumping firmware!\n", hccr);
L
Linus Torvalds 已提交
161
			else
162 163
				qla_printk(KERN_INFO, ha, "RISC paused -- "
				    "HCCR=%x, Dumping firmware!\n", hccr);
L
Linus Torvalds 已提交
164 165 166 167 168 169 170 171

			/*
			 * Issue a "HARD" reset in order for the RISC
			 * interrupt bit to be cleared.  Schedule a big
			 * hammmer to get out of the RISC PAUSED state.
			 */
			WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
			RD_REG_WORD(&reg->hccr);
172

173 174
			ha->isp_ops->fw_dump(vha, 1);
			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
175 176 177 178 179 180 181 182 183
			break;
		} else if ((stat & HSR_RISC_INT) == 0)
			break;

		switch (stat & 0xff) {
		case 0x1:
		case 0x2:
		case 0x10:
		case 0x11:
184
			qla2x00_mbx_completion(vha, MSW(stat));
L
Linus Torvalds 已提交
185 186 187 188 189 190
			status |= MBX_INTERRUPT;

			/* Release mailbox registers. */
			WRT_REG_WORD(&reg->semaphore, 0);
			break;
		case 0x12:
191 192 193 194
			mb[0] = MSW(stat);
			mb[1] = RD_MAILBOX_REG(ha, reg, 1);
			mb[2] = RD_MAILBOX_REG(ha, reg, 2);
			mb[3] = RD_MAILBOX_REG(ha, reg, 3);
195
			qla2x00_async_event(vha, rsp, mb);
196 197
			break;
		case 0x13:
198
			qla2x00_process_response_queue(rsp);
L
Linus Torvalds 已提交
199 200
			break;
		case 0x15:
201 202
			mb[0] = MBA_CMPLT_1_16BIT;
			mb[1] = MSW(stat);
203
			qla2x00_async_event(vha, rsp, mb);
L
Linus Torvalds 已提交
204 205
			break;
		case 0x16:
206 207 208
			mb[0] = MBA_SCSI_COMPLETION;
			mb[1] = MSW(stat);
			mb[2] = RD_MAILBOX_REG(ha, reg, 2);
209
			qla2x00_async_event(vha, rsp, mb);
L
Linus Torvalds 已提交
210 211 212
			break;
		default:
			DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
213
			    "(%d).\n",
214
			    vha->host_no, stat & 0xff));
L
Linus Torvalds 已提交
215 216 217 218 219
			break;
		}
		WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
		RD_REG_WORD_RELAXED(&reg->hccr);
	}
220
	spin_unlock(&ha->hardware_lock);
L
Linus Torvalds 已提交
221 222 223 224

	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
225
		complete(&ha->mbx_intr_comp);
L
Linus Torvalds 已提交
226 227 228 229 230 231 232 233 234 235 236
	}

	return (IRQ_HANDLED);
}

/**
 * qla2x00_mbx_completion() - Process mailbox command completions.
 * @ha: SCSI driver HA context
 * @mb0: Mailbox0 register
 */
static void
237
qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
L
Linus Torvalds 已提交
238 239 240
{
	uint16_t	cnt;
	uint16_t __iomem *wptr;
241
	struct qla_hw_data *ha = vha->hw;
242
	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
L
Linus Torvalds 已提交
243 244 245 246 247 248 249

	/* Load return mailbox registers. */
	ha->flags.mbox_int = 1;
	ha->mailbox_out[0] = mb0;
	wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 1);

	for (cnt = 1; cnt < ha->mbx_count; cnt++) {
A
Andrew Vasquez 已提交
250
		if (IS_QLA2200(ha) && cnt == 8)
L
Linus Torvalds 已提交
251 252 253 254 255
			wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 8);
		if (cnt == 4 || cnt == 5)
			ha->mailbox_out[cnt] = qla2x00_debounce_register(wptr);
		else
			ha->mailbox_out[cnt] = RD_REG_WORD(wptr);
A
Andrew Vasquez 已提交
256

L
Linus Torvalds 已提交
257 258 259 260 261
		wptr++;
	}

	if (ha->mcp) {
		DEBUG3(printk("%s(%ld): Got mailbox completion. cmd=%x.\n",
262
		    __func__, vha->host_no, ha->mcp->mb[0]));
L
Linus Torvalds 已提交
263 264
	} else {
		DEBUG2_3(printk("%s(%ld): MBX pointer ERROR!\n",
265
		    __func__, vha->host_no));
L
Linus Torvalds 已提交
266 267 268
	}
}

269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
static void
qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr)
{
	static char *event[] =
		{ "Complete", "Request Notification", "Time Extension" };
	int rval;
	struct device_reg_24xx __iomem *reg24 = &vha->hw->iobase->isp24;
	uint16_t __iomem *wptr;
	uint16_t cnt, timeout, mb[QLA_IDC_ACK_REGS];

	/* Seed data -- mailbox1 -> mailbox7. */
	wptr = (uint16_t __iomem *)&reg24->mailbox1;
	for (cnt = 0; cnt < QLA_IDC_ACK_REGS; cnt++, wptr++)
		mb[cnt] = RD_REG_WORD(wptr);

	DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
	    "%04x %04x %04x %04x %04x %04x %04x.\n", vha->host_no,
	    event[aen & 0xff],
	    mb[0], mb[1], mb[2], mb[3], mb[4], mb[5], mb[6]));

	/* Acknowledgement needed? [Notify && non-zero timeout]. */
	timeout = (descr >> 8) & 0xf;
	if (aen != MBA_IDC_NOTIFY || !timeout)
		return;

	DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
	    "ACK timeout=%d.\n", vha->host_no, event[aen & 0xff], timeout));

	rval = qla2x00_post_idc_ack_work(vha, mb);
	if (rval != QLA_SUCCESS)
		qla_printk(KERN_WARNING, vha->hw,
		    "IDC failed to post ACK.\n");
}

L
Linus Torvalds 已提交
303 304 305
/**
 * qla2x00_async_event() - Process aynchronous events.
 * @ha: SCSI driver HA context
306
 * @mb: Mailbox registers (0 - 3)
L
Linus Torvalds 已提交
307
 */
308
void
309
qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
L
Linus Torvalds 已提交
310
{
311
#define LS_UNKNOWN	2
312
	static char	*link_speeds[] = { "1", "2", "?", "4", "8", "10" };
L
Linus Torvalds 已提交
313 314 315 316
	char		*link_speed;
	uint16_t	handle_cnt;
	uint16_t	cnt;
	uint32_t	handles[5];
317
	struct qla_hw_data *ha = vha->hw;
318
	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
L
Linus Torvalds 已提交
319 320
	uint32_t	rscn_entry, host_pid;
	uint8_t		rscn_queue_index;
321
	unsigned long	flags;
L
Linus Torvalds 已提交
322 323 324

	/* Setup to process RIO completion. */
	handle_cnt = 0;
325 326
	if (IS_QLA81XX(ha))
		goto skip_rio;
L
Linus Torvalds 已提交
327 328
	switch (mb[0]) {
	case MBA_SCSI_COMPLETION:
329
		handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));
L
Linus Torvalds 已提交
330 331 332
		handle_cnt = 1;
		break;
	case MBA_CMPLT_1_16BIT:
333
		handles[0] = mb[1];
L
Linus Torvalds 已提交
334 335 336 337
		handle_cnt = 1;
		mb[0] = MBA_SCSI_COMPLETION;
		break;
	case MBA_CMPLT_2_16BIT:
338 339
		handles[0] = mb[1];
		handles[1] = mb[2];
L
Linus Torvalds 已提交
340 341 342 343
		handle_cnt = 2;
		mb[0] = MBA_SCSI_COMPLETION;
		break;
	case MBA_CMPLT_3_16BIT:
344 345 346
		handles[0] = mb[1];
		handles[1] = mb[2];
		handles[2] = mb[3];
L
Linus Torvalds 已提交
347 348 349 350
		handle_cnt = 3;
		mb[0] = MBA_SCSI_COMPLETION;
		break;
	case MBA_CMPLT_4_16BIT:
351 352 353
		handles[0] = mb[1];
		handles[1] = mb[2];
		handles[2] = mb[3];
L
Linus Torvalds 已提交
354 355 356 357 358
		handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);
		handle_cnt = 4;
		mb[0] = MBA_SCSI_COMPLETION;
		break;
	case MBA_CMPLT_5_16BIT:
359 360 361
		handles[0] = mb[1];
		handles[1] = mb[2];
		handles[2] = mb[3];
L
Linus Torvalds 已提交
362 363 364 365 366 367
		handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);
		handles[4] = (uint32_t)RD_MAILBOX_REG(ha, reg, 7);
		handle_cnt = 5;
		mb[0] = MBA_SCSI_COMPLETION;
		break;
	case MBA_CMPLT_2_32BIT:
368
		handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));
L
Linus Torvalds 已提交
369 370 371 372 373 374 375 376 377
		handles[1] = le32_to_cpu(
		    ((uint32_t)(RD_MAILBOX_REG(ha, reg, 7) << 16)) |
		    RD_MAILBOX_REG(ha, reg, 6));
		handle_cnt = 2;
		mb[0] = MBA_SCSI_COMPLETION;
		break;
	default:
		break;
	}
378
skip_rio:
L
Linus Torvalds 已提交
379 380
	switch (mb[0]) {
	case MBA_SCSI_COMPLETION:	/* Fast Post */
381
		if (!vha->flags.online)
L
Linus Torvalds 已提交
382 383 384
			break;

		for (cnt = 0; cnt < handle_cnt; cnt++)
385 386
			qla2x00_process_completed_request(vha, rsp->req,
				handles[cnt]);
L
Linus Torvalds 已提交
387 388 389
		break;

	case MBA_RESET:			/* Reset */
390 391
		DEBUG2(printk("scsi(%ld): Asynchronous RESET.\n",
			vha->host_no));
L
Linus Torvalds 已提交
392

393
		set_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
394 395 396 397 398 399 400
		break;

	case MBA_SYSTEM_ERR:		/* System Error */
		qla_printk(KERN_INFO, ha,
		    "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
		    mb[1], mb[2], mb[3]);

401
		ha->isp_ops->fw_dump(vha, 1);
L
Linus Torvalds 已提交
402

403
		if (IS_FWI2_CAPABLE(ha)) {
404 405 406 407
			if (mb[1] == 0 && mb[2] == 0) {
				qla_printk(KERN_ERR, ha,
				    "Unrecoverable Hardware Error: adapter "
				    "marked OFFLINE!\n");
408
				vha->flags.online = 0;
409
			} else
410
				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
411
		} else if (mb[1] == 0) {
L
Linus Torvalds 已提交
412 413 414
			qla_printk(KERN_INFO, ha,
			    "Unrecoverable Hardware Error: adapter marked "
			    "OFFLINE!\n");
415
			vha->flags.online = 0;
L
Linus Torvalds 已提交
416
		} else
417
			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
418 419 420 421
		break;

	case MBA_REQ_TRANSFER_ERR:	/* Request Transfer Error */
		DEBUG2(printk("scsi(%ld): ISP Request Transfer Error.\n",
422
		    vha->host_no));
L
Linus Torvalds 已提交
423 424
		qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n");

425
		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
426 427 428 429
		break;

	case MBA_RSP_TRANSFER_ERR:	/* Response Transfer Error */
		DEBUG2(printk("scsi(%ld): ISP Response Transfer Error.\n",
430
		    vha->host_no));
L
Linus Torvalds 已提交
431 432
		qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n");

433
		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
434 435 436 437
		break;

	case MBA_WAKEUP_THRES:		/* Request Queue Wake-up */
		DEBUG2(printk("scsi(%ld): Asynchronous WAKEUP_THRES.\n",
438
		    vha->host_no));
L
Linus Torvalds 已提交
439 440 441
		break;

	case MBA_LIP_OCCURRED:		/* Loop Initialization Procedure */
442
		DEBUG2(printk("scsi(%ld): LIP occurred (%x).\n", vha->host_no,
L
Linus Torvalds 已提交
443
		    mb[1]));
444
		qla_printk(KERN_INFO, ha, "LIP occurred (%x).\n", mb[1]);
L
Linus Torvalds 已提交
445

446 447 448 449
		if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
			atomic_set(&vha->loop_state, LOOP_DOWN);
			atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
			qla2x00_mark_all_devices_lost(vha, 1);
L
Linus Torvalds 已提交
450 451
		}

452 453 454
		if (vha->vp_idx) {
			atomic_set(&vha->vp_state, VP_FAILED);
			fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
455 456
		}

457 458
		set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
		set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
459

460 461
		vha->flags.management_server_logged_in = 0;
		qla2x00_post_aen_work(vha, FCH_EVT_LIP, mb[1]);
L
Linus Torvalds 已提交
462 463 464 465 466
		break;

	case MBA_LOOP_UP:		/* Loop Up Event */
		if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
			link_speed = link_speeds[0];
467
			ha->link_data_rate = PORT_SPEED_1GB;
L
Linus Torvalds 已提交
468
		} else {
469
			link_speed = link_speeds[LS_UNKNOWN];
L
Linus Torvalds 已提交
470 471
			if (mb[1] < 5)
				link_speed = link_speeds[mb[1]];
472 473
			else if (mb[1] == 0x13)
				link_speed = link_speeds[5];
L
Linus Torvalds 已提交
474 475 476 477
			ha->link_data_rate = mb[1];
		}

		DEBUG2(printk("scsi(%ld): Asynchronous LOOP UP (%s Gbps).\n",
478
		    vha->host_no, link_speed));
L
Linus Torvalds 已提交
479 480 481
		qla_printk(KERN_INFO, ha, "LOOP UP detected (%s Gbps).\n",
		    link_speed);

482 483
		vha->flags.management_server_logged_in = 0;
		qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
L
Linus Torvalds 已提交
484 485 486
		break;

	case MBA_LOOP_DOWN:		/* Loop Down Event */
487
		DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN "
488
		    "(%x %x %x).\n", vha->host_no, mb[1], mb[2], mb[3]));
489 490
		qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x %x %x).\n",
		    mb[1], mb[2], mb[3]);
L
Linus Torvalds 已提交
491

492 493 494 495 496
		if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
			atomic_set(&vha->loop_state, LOOP_DOWN);
			atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
			vha->device_flags |= DFLG_NO_CABLE;
			qla2x00_mark_all_devices_lost(vha, 1);
L
Linus Torvalds 已提交
497 498
		}

499 500 501
		if (vha->vp_idx) {
			atomic_set(&vha->vp_state, VP_FAILED);
			fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
502 503
		}

504
		vha->flags.management_server_logged_in = 0;
505
		ha->link_data_rate = PORT_SPEED_UNKNOWN;
506
		qla2x00_post_aen_work(vha, FCH_EVT_LINKDOWN, 0);
L
Linus Torvalds 已提交
507 508 509 510
		break;

	case MBA_LIP_RESET:		/* LIP reset occurred */
		DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n",
511
		    vha->host_no, mb[1]));
L
Linus Torvalds 已提交
512
		qla_printk(KERN_INFO, ha,
513
		    "LIP reset occurred (%x).\n", mb[1]);
L
Linus Torvalds 已提交
514

515 516 517 518
		if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
			atomic_set(&vha->loop_state, LOOP_DOWN);
			atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
			qla2x00_mark_all_devices_lost(vha, 1);
L
Linus Torvalds 已提交
519 520
		}

521 522 523
		if (vha->vp_idx) {
			atomic_set(&vha->vp_state, VP_FAILED);
			fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
524 525
		}

526
		set_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
527 528

		ha->operating_mode = LOOP;
529 530
		vha->flags.management_server_logged_in = 0;
		qla2x00_post_aen_work(vha, FCH_EVT_LIPRESET, mb[1]);
L
Linus Torvalds 已提交
531 532
		break;

533
	/* case MBA_DCBX_COMPLETE: */
L
Linus Torvalds 已提交
534 535 536 537
	case MBA_POINT_TO_POINT:	/* Point-to-Point */
		if (IS_QLA2100(ha))
			break;

538 539 540 541 542 543
		if (IS_QLA81XX(ha))
			DEBUG2(printk("scsi(%ld): DCBX Completed -- %04x %04x "
			    "%04x\n", vha->host_no, mb[1], mb[2], mb[3]));
		else
			DEBUG2(printk("scsi(%ld): Asynchronous P2P MODE "
			    "received.\n", vha->host_no));
L
Linus Torvalds 已提交
544 545 546 547 548

		/*
		 * Until there's a transition from loop down to loop up, treat
		 * this as loop down only.
		 */
549 550 551 552
		if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
			atomic_set(&vha->loop_state, LOOP_DOWN);
			if (!atomic_read(&vha->loop_down_timer))
				atomic_set(&vha->loop_down_timer,
L
Linus Torvalds 已提交
553
				    LOOP_DOWN_TIME);
554
			qla2x00_mark_all_devices_lost(vha, 1);
L
Linus Torvalds 已提交
555 556
		}

557 558 559
		if (vha->vp_idx) {
			atomic_set(&vha->vp_state, VP_FAILED);
			fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
560 561
		}

562 563 564 565 566
		if (!(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)))
			set_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);

		set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
		set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
567 568

		ha->flags.gpsc_supported = 1;
569
		vha->flags.management_server_logged_in = 0;
L
Linus Torvalds 已提交
570 571 572 573 574 575 576 577
		break;

	case MBA_CHG_IN_CONNECTION:	/* Change in connection mode */
		if (IS_QLA2100(ha))
			break;

		DEBUG2(printk("scsi(%ld): Asynchronous Change In Connection "
		    "received.\n",
578
		    vha->host_no));
L
Linus Torvalds 已提交
579 580 581
		qla_printk(KERN_INFO, ha,
		    "Configuration change detected: value=%x.\n", mb[1]);

582 583 584 585
		if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
			atomic_set(&vha->loop_state, LOOP_DOWN);
			if (!atomic_read(&vha->loop_down_timer))
				atomic_set(&vha->loop_down_timer,
L
Linus Torvalds 已提交
586
				    LOOP_DOWN_TIME);
587
			qla2x00_mark_all_devices_lost(vha, 1);
L
Linus Torvalds 已提交
588 589
		}

590 591 592
		if (vha->vp_idx) {
			atomic_set(&vha->vp_state, VP_FAILED);
			fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED);
593 594
		}

595 596
		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
L
Linus Torvalds 已提交
597 598 599
		break;

	case MBA_PORT_UPDATE:		/* Port database update */
600 601 602 603
		/* Only handle SCNs for our Vport index. */
		if (vha->vp_idx && vha->vp_idx != (mb[3] & 0xff))
			break;

L
Linus Torvalds 已提交
604
		/*
605
		 * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET
L
Linus Torvalds 已提交
606 607 608
		 * event etc. earlier indicating loop is down) then process
		 * it.  Otherwise ignore it and Wait for RSCN to come in.
		 */
609 610 611
		atomic_set(&vha->loop_down_timer, 0);
		if (atomic_read(&vha->loop_state) != LOOP_DOWN &&
		    atomic_read(&vha->loop_state) != LOOP_DEAD) {
L
Linus Torvalds 已提交
612
			DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE "
613
			    "ignored %04x/%04x/%04x.\n", vha->host_no, mb[1],
614
			    mb[2], mb[3]));
L
Linus Torvalds 已提交
615 616 617 618
			break;
		}

		DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n",
619
		    vha->host_no));
L
Linus Torvalds 已提交
620
		DEBUG(printk(KERN_INFO
621
		    "scsi(%ld): Port database changed %04x %04x %04x.\n",
622
		    vha->host_no, mb[1], mb[2], mb[3]));
L
Linus Torvalds 已提交
623 624 625 626

		/*
		 * Mark all devices as missing so we will login again.
		 */
627
		atomic_set(&vha->loop_state, LOOP_UP);
L
Linus Torvalds 已提交
628

629
		qla2x00_mark_all_devices_lost(vha, 1);
L
Linus Torvalds 已提交
630

631
		vha->flags.rscn_queue_overflow = 1;
L
Linus Torvalds 已提交
632

633 634
		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
L
Linus Torvalds 已提交
635 636 637
		break;

	case MBA_RSCN_UPDATE:		/* State Change Registration */
638
		/* Check if the Vport has issued a SCR */
639
		if (vha->vp_idx && test_bit(VP_SCR_NEEDED, &vha->vp_flags))
640 641
			break;
		/* Only handle SCNs for our Vport index. */
642
		if (vha->vp_idx && vha->vp_idx != (mb[3] & 0xff))
643
			break;
L
Linus Torvalds 已提交
644
		DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
645
		    vha->host_no));
L
Linus Torvalds 已提交
646
		DEBUG(printk(KERN_INFO
647
		    "scsi(%ld): RSCN database changed -- %04x %04x %04x.\n",
648
		    vha->host_no, mb[1], mb[2], mb[3]));
L
Linus Torvalds 已提交
649

650
		rscn_entry = ((mb[1] & 0xff) << 16) | mb[2];
651 652
		host_pid = (vha->d_id.b.domain << 16) | (vha->d_id.b.area << 8)
				| vha->d_id.b.al_pa;
L
Linus Torvalds 已提交
653 654 655 656
		if (rscn_entry == host_pid) {
			DEBUG(printk(KERN_INFO
			    "scsi(%ld): Ignoring RSCN update to local host "
			    "port ID (%06x)\n",
657
			    vha->host_no, host_pid));
L
Linus Torvalds 已提交
658 659 660
			break;
		}

661 662
		/* Ignore reserved bits from RSCN-payload. */
		rscn_entry = ((mb[1] & 0x3ff) << 16) | mb[2];
663
		rscn_queue_index = vha->rscn_in_ptr + 1;
L
Linus Torvalds 已提交
664 665
		if (rscn_queue_index == MAX_RSCN_COUNT)
			rscn_queue_index = 0;
666 667 668
		if (rscn_queue_index != vha->rscn_out_ptr) {
			vha->rscn_queue[vha->rscn_in_ptr] = rscn_entry;
			vha->rscn_in_ptr = rscn_queue_index;
L
Linus Torvalds 已提交
669
		} else {
670
			vha->flags.rscn_queue_overflow = 1;
L
Linus Torvalds 已提交
671 672
		}

673 674 675
		atomic_set(&vha->loop_state, LOOP_UPDATE);
		atomic_set(&vha->loop_down_timer, 0);
		vha->flags.management_server_logged_in = 0;
L
Linus Torvalds 已提交
676

677 678 679
		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
		set_bit(RSCN_UPDATE, &vha->dpc_flags);
		qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
L
Linus Torvalds 已提交
680 681 682 683
		break;

	/* case MBA_RIO_RESPONSE: */
	case MBA_ZIO_RESPONSE:
684
		DEBUG3(printk("scsi(%ld): [R|Z]IO update completion.\n",
685
		    vha->host_no));
L
Linus Torvalds 已提交
686

687
		if (IS_FWI2_CAPABLE(ha))
688
			qla24xx_process_response_queue(rsp);
689
		else
690
			qla2x00_process_response_queue(rsp);
L
Linus Torvalds 已提交
691
		break;
692 693 694

	case MBA_DISCARD_RND_FRAME:
		DEBUG2(printk("scsi(%ld): Discard RND Frame -- %04x %04x "
695
		    "%04x.\n", vha->host_no, mb[1], mb[2], mb[3]));
696
		break;
697 698 699

	case MBA_TRACE_NOTIFICATION:
		DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n",
700
		vha->host_no, mb[1], mb[2]));
701
		break;
702 703 704

	case MBA_ISP84XX_ALERT:
		DEBUG2(printk("scsi(%ld): ISP84XX Alert Notification -- "
705
		    "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737

		spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
		switch (mb[1]) {
		case A84_PANIC_RECOVERY:
			qla_printk(KERN_INFO, ha, "Alert 84XX: panic recovery "
			    "%04x %04x\n", mb[2], mb[3]);
			break;
		case A84_OP_LOGIN_COMPLETE:
			ha->cs84xx->op_fw_version = mb[3] << 16 | mb[2];
			DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
			    "firmware version %x\n", ha->cs84xx->op_fw_version));
			break;
		case A84_DIAG_LOGIN_COMPLETE:
			ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
			DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
			    "diagnostic firmware version %x\n",
			    ha->cs84xx->diag_fw_version));
			break;
		case A84_GOLD_LOGIN_COMPLETE:
			ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
			ha->cs84xx->fw_update = 1;
			DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX: gold "
			    "firmware version %x\n",
			    ha->cs84xx->gold_fw_version));
			break;
		default:
			qla_printk(KERN_ERR, ha,
			    "Alert 84xx: Invalid Alert %04x %04x %04x\n",
			    mb[1], mb[2], mb[3]);
		}
		spin_unlock_irqrestore(&ha->cs84xx->access_lock, flags);
		break;
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
	case MBA_DCBX_START:
		DEBUG2(printk("scsi(%ld): DCBX Started -- %04x %04x %04x\n",
		    vha->host_no, mb[1], mb[2], mb[3]));
		break;
	case MBA_DCBX_PARAM_UPDATE:
		DEBUG2(printk("scsi(%ld): DCBX Parameters Updated -- "
		    "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
		break;
	case MBA_FCF_CONF_ERR:
		DEBUG2(printk("scsi(%ld): FCF Configuration Error -- "
		    "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
		break;
	case MBA_IDC_COMPLETE:
	case MBA_IDC_NOTIFY:
	case MBA_IDC_TIME_EXT:
753
		qla81xx_idc_event(vha, mb[0], mb[1]);
754
		break;
L
Linus Torvalds 已提交
755
	}
756

757
	if (!vha->vp_idx && ha->num_vhosts)
758
		qla2x00_alert_all_vps(rsp, mb);
L
Linus Torvalds 已提交
759 760
}

761 762 763 764
static void
qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, void *data)
{
	fc_port_t *fcport = data;
765 766 767 768 769 770 771 772
	struct scsi_qla_host *vha = fcport->vha;
	struct qla_hw_data *ha = vha->hw;
	struct req_que *req = NULL;

	req = ha->req_q_map[vha->req_ques[0]];
	if (!req)
		return;
	if (req->max_q_depth <= sdev->queue_depth)
773 774 775 776 777 778 779 780 781 782 783
		return;

	if (sdev->ordered_tags)
		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
		    sdev->queue_depth + 1);
	else
		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
		    sdev->queue_depth + 1);

	fcport->last_ramp_up = jiffies;

784
	DEBUG2(qla_printk(KERN_INFO, ha,
785
	    "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n",
786
	    fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
787 788 789 790 791 792 793 794 795 796 797
	    sdev->queue_depth));
}

static void
qla2x00_adjust_sdev_qdepth_down(struct scsi_device *sdev, void *data)
{
	fc_port_t *fcport = data;

	if (!scsi_track_queue_full(sdev, sdev->queue_depth - 1))
		return;

798
	DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw,
799
	    "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n",
800
	    fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
801 802 803 804
	    sdev->queue_depth));
}

static inline void
805 806
qla2x00_ramp_up_queue_depth(scsi_qla_host_t *vha, struct req_que *req,
								srb_t *sp)
807 808 809 810 811
{
	fc_port_t *fcport;
	struct scsi_device *sdev;

	sdev = sp->cmd->device;
812
	if (sdev->queue_depth >= req->max_q_depth)
813 814 815 816 817 818 819 820 821 822 823 824 825 826
		return;

	fcport = sp->fcport;
	if (time_before(jiffies,
	    fcport->last_ramp_up + ql2xqfullrampup * HZ))
		return;
	if (time_before(jiffies,
	    fcport->last_queue_full + ql2xqfullrampup * HZ))
		return;

	starget_for_each_device(sdev->sdev_target, fcport,
	    qla2x00_adjust_sdev_qdepth_up);
}

L
Linus Torvalds 已提交
827 828 829 830 831 832
/**
 * qla2x00_process_completed_request() - Process a Fast Post response.
 * @ha: SCSI driver HA context
 * @index: SRB index
 */
static void
833 834
qla2x00_process_completed_request(struct scsi_qla_host *vha,
				struct req_que *req, uint32_t index)
L
Linus Torvalds 已提交
835 836
{
	srb_t *sp;
837
	struct qla_hw_data *ha = vha->hw;
L
Linus Torvalds 已提交
838 839 840 841

	/* Validate handle. */
	if (index >= MAX_OUTSTANDING_COMMANDS) {
		DEBUG2(printk("scsi(%ld): Invalid SCSI completion handle %d.\n",
842
		    vha->host_no, index));
L
Linus Torvalds 已提交
843 844 845
		qla_printk(KERN_WARNING, ha,
		    "Invalid SCSI completion handle %d.\n", index);

846
		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
847 848 849
		return;
	}

850
	sp = req->outstanding_cmds[index];
L
Linus Torvalds 已提交
851 852
	if (sp) {
		/* Free outstanding command slot. */
853
		req->outstanding_cmds[index] = NULL;
L
Linus Torvalds 已提交
854 855 856

		/* Save ISP completion status */
		sp->cmd->result = DID_OK << 16;
857

858 859
		qla2x00_ramp_up_queue_depth(vha, req, sp);
		qla2x00_sp_compl(ha, sp);
L
Linus Torvalds 已提交
860 861
	} else {
		DEBUG2(printk("scsi(%ld): Invalid ISP SCSI completion handle\n",
862
		    vha->host_no));
L
Linus Torvalds 已提交
863 864 865
		qla_printk(KERN_WARNING, ha,
		    "Invalid ISP SCSI completion handle\n");

866
		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
L
Linus Torvalds 已提交
867 868 869 870 871 872 873 874
	}
}

/**
 * qla2x00_process_response_queue() - Process response queue entries.
 * @ha: SCSI driver HA context
 */
void
875
qla2x00_process_response_queue(struct rsp_que *rsp)
L
Linus Torvalds 已提交
876
{
877 878
	struct scsi_qla_host *vha;
	struct qla_hw_data *ha = rsp->hw;
879
	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
L
Linus Torvalds 已提交
880 881 882
	sts_entry_t	*pkt;
	uint16_t        handle_cnt;
	uint16_t        cnt;
883 884

	vha = qla2x00_get_rsp_host(rsp);
L
Linus Torvalds 已提交
885

886
	if (!vha->flags.online)
L
Linus Torvalds 已提交
887 888
		return;

889 890
	while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
		pkt = (sts_entry_t *)rsp->ring_ptr;
L
Linus Torvalds 已提交
891

892 893 894 895
		rsp->ring_index++;
		if (rsp->ring_index == rsp->length) {
			rsp->ring_index = 0;
			rsp->ring_ptr = rsp->ring;
L
Linus Torvalds 已提交
896
		} else {
897
			rsp->ring_ptr++;
L
Linus Torvalds 已提交
898 899 900 901
		}

		if (pkt->entry_status != 0) {
			DEBUG3(printk(KERN_INFO
902
			    "scsi(%ld): Process error entry.\n", vha->host_no));
L
Linus Torvalds 已提交
903

904
			qla2x00_error_entry(vha, rsp, pkt);
L
Linus Torvalds 已提交
905 906 907 908 909 910 911
			((response_t *)pkt)->signature = RESPONSE_PROCESSED;
			wmb();
			continue;
		}

		switch (pkt->entry_type) {
		case STATUS_TYPE:
912
			qla2x00_status_entry(vha, rsp, pkt);
L
Linus Torvalds 已提交
913 914 915 916
			break;
		case STATUS_TYPE_21:
			handle_cnt = ((sts21_entry_t *)pkt)->handle_count;
			for (cnt = 0; cnt < handle_cnt; cnt++) {
917
				qla2x00_process_completed_request(vha, rsp->req,
L
Linus Torvalds 已提交
918 919 920 921 922 923
				    ((sts21_entry_t *)pkt)->handle[cnt]);
			}
			break;
		case STATUS_TYPE_22:
			handle_cnt = ((sts22_entry_t *)pkt)->handle_count;
			for (cnt = 0; cnt < handle_cnt; cnt++) {
924
				qla2x00_process_completed_request(vha, rsp->req,
L
Linus Torvalds 已提交
925 926 927 928
				    ((sts22_entry_t *)pkt)->handle[cnt]);
			}
			break;
		case STATUS_CONT_TYPE:
929
			qla2x00_status_cont_entry(vha, (sts_cont_entry_t *)pkt);
L
Linus Torvalds 已提交
930 931 932 933 934 935
			break;
		default:
			/* Type Not Supported. */
			DEBUG4(printk(KERN_WARNING
			    "scsi(%ld): Received unknown response pkt type %x "
			    "entry status=%x.\n",
936
			    vha->host_no, pkt->entry_type, pkt->entry_status));
L
Linus Torvalds 已提交
937 938 939 940 941 942 943
			break;
		}
		((response_t *)pkt)->signature = RESPONSE_PROCESSED;
		wmb();
	}

	/* Adjust ring index */
944
	WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), rsp->ring_index);
L
Linus Torvalds 已提交
945 946
}

947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964
static inline void
qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len)
{
	struct scsi_cmnd *cp = sp->cmd;

	if (sense_len >= SCSI_SENSE_BUFFERSIZE)
		sense_len = SCSI_SENSE_BUFFERSIZE;

	sp->request_sense_length = sense_len;
	sp->request_sense_ptr = cp->sense_buffer;
	if (sp->request_sense_length > 32)
		sense_len = 32;

	memcpy(cp->sense_buffer, sense_data, sense_len);

	sp->request_sense_ptr += sense_len;
	sp->request_sense_length -= sense_len;
	if (sp->request_sense_length != 0)
965
		sp->fcport->vha->status_srb = sp;
966 967

	DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) "
968
	    "cmd=%p pid=%ld\n", __func__, sp->fcport->vha->host_no,
969 970
	    cp->device->channel, cp->device->id, cp->device->lun, cp,
	    cp->serial_number));
971
	if (sense_len)
972
		DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len));
973 974
}

L
Linus Torvalds 已提交
975 976 977 978 979 980
/**
 * qla2x00_status_entry() - Process a Status IOCB entry.
 * @ha: SCSI driver HA context
 * @pkt: Entry pointer
 */
static void
981
qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
L
Linus Torvalds 已提交
982 983 984 985
{
	srb_t		*sp;
	fc_port_t	*fcport;
	struct scsi_cmnd *cp;
986 987
	sts_entry_t *sts;
	struct sts_entry_24xx *sts24;
L
Linus Torvalds 已提交
988 989 990 991
	uint16_t	comp_status;
	uint16_t	scsi_status;
	uint8_t		lscsi_status;
	int32_t		resid;
992
	uint32_t	sense_len, rsp_info_len, resid_len, fw_resid_len;
993
	uint8_t		*rsp_info, *sense_data;
994
	struct qla_hw_data *ha = vha->hw;
995
	struct req_que *req = rsp->req;
996 997 998

	sts = (sts_entry_t *) pkt;
	sts24 = (struct sts_entry_24xx *) pkt;
999
	if (IS_FWI2_CAPABLE(ha)) {
1000 1001 1002 1003 1004 1005
		comp_status = le16_to_cpu(sts24->comp_status);
		scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
	} else {
		comp_status = le16_to_cpu(sts->comp_status);
		scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK;
	}
L
Linus Torvalds 已提交
1006 1007

	/* Fast path completion. */
1008
	if (comp_status == CS_COMPLETE && scsi_status == 0) {
1009
		qla2x00_process_completed_request(vha, req, sts->handle);
L
Linus Torvalds 已提交
1010 1011 1012 1013 1014

		return;
	}

	/* Validate handle. */
1015
	if (sts->handle < MAX_OUTSTANDING_COMMANDS) {
1016 1017
		sp = req->outstanding_cmds[sts->handle];
		req->outstanding_cmds[sts->handle] = NULL;
L
Linus Torvalds 已提交
1018 1019 1020 1021 1022
	} else
		sp = NULL;

	if (sp == NULL) {
		DEBUG2(printk("scsi(%ld): Status Entry invalid handle.\n",
1023
		    vha->host_no));
L
Linus Torvalds 已提交
1024 1025
		qla_printk(KERN_WARNING, ha, "Status Entry invalid handle.\n");

1026 1027
		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
		qla2xxx_wake_dpc(vha);
L
Linus Torvalds 已提交
1028 1029 1030 1031 1032
		return;
	}
	cp = sp->cmd;
	if (cp == NULL) {
		DEBUG2(printk("scsi(%ld): Command already returned back to OS "
1033
		    "pkt->handle=%d sp=%p.\n", vha->host_no, sts->handle, sp));
L
Linus Torvalds 已提交
1034 1035 1036 1037 1038 1039
		qla_printk(KERN_WARNING, ha,
		    "Command is NULL: already returned to OS (sp=%p)\n", sp);

		return;
	}

1040
  	lscsi_status = scsi_status & STATUS_MASK;
L
Linus Torvalds 已提交
1041

1042
	fcport = sp->fcport;
L
Linus Torvalds 已提交
1043

1044
	sense_len = rsp_info_len = resid_len = fw_resid_len = 0;
1045
	if (IS_FWI2_CAPABLE(ha)) {
1046 1047 1048
		sense_len = le32_to_cpu(sts24->sense_len);
		rsp_info_len = le32_to_cpu(sts24->rsp_data_len);
		resid_len = le32_to_cpu(sts24->rsp_residual_count);
1049
		fw_resid_len = le32_to_cpu(sts24->residual_len);
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
		rsp_info = sts24->data;
		sense_data = sts24->data;
		host_to_fcp_swap(sts24->data, sizeof(sts24->data));
	} else {
		sense_len = le16_to_cpu(sts->req_sense_length);
		rsp_info_len = le16_to_cpu(sts->rsp_info_len);
		resid_len = le32_to_cpu(sts->residual_length);
		rsp_info = sts->rsp_info;
		sense_data = sts->req_sense_data;
	}

L
Linus Torvalds 已提交
1061 1062
	/* Check for any FCP transport errors. */
	if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) {
1063
		/* Sense data lies beyond any FCP RESPONSE data. */
1064
		if (IS_FWI2_CAPABLE(ha))
1065 1066
			sense_data += rsp_info_len;
		if (rsp_info_len > 3 && rsp_info[3]) {
L
Linus Torvalds 已提交
1067 1068
			DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol "
			    "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..."
1069
			    "retrying command\n", vha->host_no,
1070 1071 1072 1073
			    cp->device->channel, cp->device->id,
			    cp->device->lun, rsp_info_len, rsp_info[0],
			    rsp_info[1], rsp_info[2], rsp_info[3], rsp_info[4],
			    rsp_info[5], rsp_info[6], rsp_info[7]));
L
Linus Torvalds 已提交
1074 1075

			cp->result = DID_BUS_BUSY << 16;
1076
			qla2x00_sp_compl(ha, sp);
L
Linus Torvalds 已提交
1077 1078 1079 1080
			return;
		}
	}

1081 1082 1083 1084 1085
	/* Check for overrun. */
	if (IS_FWI2_CAPABLE(ha) && comp_status == CS_COMPLETE &&
	    scsi_status & SS_RESIDUAL_OVER)
		comp_status = CS_DATA_OVERRUN;

L
Linus Torvalds 已提交
1086 1087 1088 1089 1090
	/*
	 * Based on Host and scsi status generate status code for Linux
	 */
	switch (comp_status) {
	case CS_COMPLETE:
1091
	case CS_QUEUE_FULL:
L
Linus Torvalds 已提交
1092 1093 1094 1095 1096
		if (scsi_status == 0) {
			cp->result = DID_OK << 16;
			break;
		}
		if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) {
1097
			resid = resid_len;
1098
			scsi_set_resid(cp, resid);
1099 1100

			if (!lscsi_status &&
1101
			    ((unsigned)(scsi_bufflen(cp) - resid) <
1102 1103
			     cp->underflow)) {
				qla_printk(KERN_INFO, ha,
1104 1105
					   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
					   "detected (%x of %x bytes)...returning "
1106
					   "error status.\n", vha->host_no,
1107 1108 1109
					   cp->device->channel, cp->device->id,
					   cp->device->lun, resid,
					   scsi_bufflen(cp));
1110 1111 1112 1113

				cp->result = DID_ERROR << 16;
				break;
			}
L
Linus Torvalds 已提交
1114 1115 1116
		}
		cp->result = DID_OK << 16 | lscsi_status;

1117 1118 1119
		if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
			DEBUG2(printk(KERN_INFO
			    "scsi(%ld): QUEUE FULL status detected "
1120
			    "0x%x-0x%x.\n", vha->host_no, comp_status,
1121 1122 1123 1124 1125 1126 1127 1128
			    scsi_status));

			/* Adjust queue depth for all luns on the port. */
			fcport->last_queue_full = jiffies;
			starget_for_each_device(cp->device->sdev_target,
			    fcport, qla2x00_adjust_sdev_qdepth_down);
			break;
		}
L
Linus Torvalds 已提交
1129 1130 1131
		if (lscsi_status != SS_CHECK_CONDITION)
			break;

1132
		memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
L
Linus Torvalds 已提交
1133 1134 1135
		if (!(scsi_status & SS_SENSE_LEN_VALID))
			break;

1136
		qla2x00_handle_sense(sp, sense_data, sense_len);
L
Linus Torvalds 已提交
1137 1138 1139
		break;

	case CS_DATA_UNDERRUN:
1140
		resid = resid_len;
1141
		/* Use F/W calculated residual length. */
1142
		if (IS_FWI2_CAPABLE(ha)) {
1143 1144 1145
			if (!(scsi_status & SS_RESIDUAL_UNDER)) {
				lscsi_status = 0;
			} else if (resid != fw_resid_len) {
1146 1147 1148
				scsi_status &= ~SS_RESIDUAL_UNDER;
				lscsi_status = 0;
			}
1149
			resid = fw_resid_len;
1150
		}
1151

L
Linus Torvalds 已提交
1152
		if (scsi_status & SS_RESIDUAL_UNDER) {
1153
			scsi_set_resid(cp, resid);
1154 1155 1156
		} else {
			DEBUG2(printk(KERN_INFO
			    "scsi(%ld:%d:%d) UNDERRUN status detected "
1157
			    "0x%x-0x%x. resid=0x%x fw_resid=0x%x cdb=0x%x "
1158
			    "os_underflow=0x%x\n", vha->host_no,
1159 1160 1161
			    cp->device->id, cp->device->lun, comp_status,
			    scsi_status, resid_len, resid, cp->cmnd[0],
			    cp->underflow));
1162

L
Linus Torvalds 已提交
1163 1164 1165
		}

		/*
A
Andrew Vasquez 已提交
1166
		 * Check to see if SCSI Status is non zero. If so report SCSI
L
Linus Torvalds 已提交
1167 1168 1169 1170 1171
		 * Status.
		 */
		if (lscsi_status != 0) {
			cp->result = DID_OK << 16 | lscsi_status;

1172 1173 1174
			if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
				DEBUG2(printk(KERN_INFO
				    "scsi(%ld): QUEUE FULL status detected "
1175
				    "0x%x-0x%x.\n", vha->host_no, comp_status,
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
				    scsi_status));

				/*
				 * Adjust queue depth for all luns on the
				 * port.
				 */
				fcport->last_queue_full = jiffies;
				starget_for_each_device(
				    cp->device->sdev_target, fcport,
				    qla2x00_adjust_sdev_qdepth_down);
				break;
			}
L
Linus Torvalds 已提交
1188 1189 1190
			if (lscsi_status != SS_CHECK_CONDITION)
				break;

1191
			memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
L
Linus Torvalds 已提交
1192 1193 1194
			if (!(scsi_status & SS_SENSE_LEN_VALID))
				break;

1195
			qla2x00_handle_sense(sp, sense_data, sense_len);
L
Linus Torvalds 已提交
1196 1197 1198 1199 1200 1201 1202 1203
		} else {
			/*
			 * If RISC reports underrun and target does not report
			 * it then we must have a lost frame, so tell upper
			 * layer to retry it by reporting a bus busy.
			 */
			if (!(scsi_status & SS_RESIDUAL_UNDER)) {
				DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped "
1204
					      "frame(s) detected (%x of %x bytes)..."
1205 1206 1207 1208
					      "retrying command.\n",
					vha->host_no, cp->device->channel,
					cp->device->id, cp->device->lun, resid,
					scsi_bufflen(cp)));
L
Linus Torvalds 已提交
1209 1210 1211 1212 1213 1214

				cp->result = DID_BUS_BUSY << 16;
				break;
			}

			/* Handle mid-layer underflow */
1215
			if ((unsigned)(scsi_bufflen(cp) - resid) <
L
Linus Torvalds 已提交
1216 1217
			    cp->underflow) {
				qla_printk(KERN_INFO, ha,
1218 1219
					   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
					   "detected (%x of %x bytes)...returning "
1220
					   "error status.\n", vha->host_no,
1221 1222 1223
					   cp->device->channel, cp->device->id,
					   cp->device->lun, resid,
					   scsi_bufflen(cp));
L
Linus Torvalds 已提交
1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236

				cp->result = DID_ERROR << 16;
				break;
			}

			/* Everybody online, looking good... */
			cp->result = DID_OK << 16;
		}
		break;

	case CS_DATA_OVERRUN:
		DEBUG2(printk(KERN_INFO
		    "scsi(%ld:%d:%d): OVERRUN status detected 0x%x-0x%x\n",
1237
		    vha->host_no, cp->device->id, cp->device->lun, comp_status,
1238
		    scsi_status));
L
Linus Torvalds 已提交
1239 1240 1241 1242 1243 1244 1245
		DEBUG2(printk(KERN_INFO
		    "CDB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
		    cp->cmnd[0], cp->cmnd[1], cp->cmnd[2], cp->cmnd[3],
		    cp->cmnd[4], cp->cmnd[5]));
		DEBUG2(printk(KERN_INFO
		    "PID=0x%lx req=0x%x xtra=0x%x -- returning DID_ERROR "
		    "status!\n",
1246
		    cp->serial_number, scsi_bufflen(cp), resid_len));
L
Linus Torvalds 已提交
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262

		cp->result = DID_ERROR << 16;
		break;

	case CS_PORT_LOGGED_OUT:
	case CS_PORT_CONFIG_CHG:
	case CS_PORT_BUSY:
	case CS_INCOMPLETE:
	case CS_PORT_UNAVAILABLE:
		/*
		 * If the port is in Target Down state, return all IOs for this
		 * Target with DID_NO_CONNECT ELSE Queue the IOs in the
		 * retry_queue.
		 */
		DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down "
		    "pid=%ld, compl status=0x%x, port state=0x%x\n",
1263
		    vha->host_no, cp->device->id, cp->device->lun,
1264
		    cp->serial_number, comp_status,
L
Linus Torvalds 已提交
1265 1266
		    atomic_read(&fcport->state)));

1267 1268 1269 1270 1271 1272
		/*
		 * We are going to have the fc class block the rport
		 * while we try to recover so instruct the mid layer
		 * to requeue until the class decides how to handle this.
		 */
		cp->result = DID_TRANSPORT_DISRUPTED << 16;
1273
		if (atomic_read(&fcport->state) == FCS_ONLINE)
1274
			qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
L
Linus Torvalds 已提交
1275 1276 1277 1278 1279
		break;

	case CS_RESET:
		DEBUG2(printk(KERN_INFO
		    "scsi(%ld): RESET status detected 0x%x-0x%x.\n",
1280
		    vha->host_no, comp_status, scsi_status));
L
Linus Torvalds 已提交
1281

已提交
1282
		cp->result = DID_RESET << 16;
L
Linus Torvalds 已提交
1283 1284 1285
		break;

	case CS_ABORTED:
A
Andrew Vasquez 已提交
1286
		/*
L
Linus Torvalds 已提交
1287 1288 1289 1290 1291 1292
		 * hv2.19.12 - DID_ABORT does not retry the request if we
		 * aborted this request then abort otherwise it must be a
		 * reset.
		 */
		DEBUG2(printk(KERN_INFO
		    "scsi(%ld): ABORT status detected 0x%x-0x%x.\n",
1293
		    vha->host_no, comp_status, scsi_status));
L
Linus Torvalds 已提交
1294 1295 1296 1297 1298

		cp->result = DID_RESET << 16;
		break;

	case CS_TIMEOUT:
1299 1300 1301 1302 1303 1304
		/*
		 * We are going to have the fc class block the rport
		 * while we try to recover so instruct the mid layer
		 * to requeue until the class decides how to handle this.
		 */
		cp->result = DID_TRANSPORT_DISRUPTED << 16;
1305

1306
		if (IS_FWI2_CAPABLE(ha)) {
1307 1308
			DEBUG2(printk(KERN_INFO
			    "scsi(%ld:%d:%d:%d): TIMEOUT status detected "
1309
			    "0x%x-0x%x\n", vha->host_no, cp->device->channel,
1310 1311 1312 1313
			    cp->device->id, cp->device->lun, comp_status,
			    scsi_status));
			break;
		}
L
Linus Torvalds 已提交
1314 1315
		DEBUG2(printk(KERN_INFO
		    "scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x "
1316
		    "sflags=%x.\n", vha->host_no, cp->device->channel,
1317 1318
		    cp->device->id, cp->device->lun, comp_status, scsi_status,
		    le16_to_cpu(sts->status_flags)));
L
Linus Torvalds 已提交
1319

1320 1321
		/* Check to see if logout occurred. */
		if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT))
1322
			qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
L
Linus Torvalds 已提交
1323 1324 1325 1326
		break;

	default:
		DEBUG3(printk("scsi(%ld): Error detected (unknown status) "
1327
		    "0x%x-0x%x.\n", vha->host_no, comp_status, scsi_status));
L
Linus Torvalds 已提交
1328 1329 1330 1331 1332 1333 1334 1335 1336
		qla_printk(KERN_INFO, ha,
		    "Unknown status detected 0x%x-0x%x.\n",
		    comp_status, scsi_status);

		cp->result = DID_ERROR << 16;
		break;
	}

	/* Place command on done queue. */
1337
	if (vha->status_srb == NULL)
1338
		qla2x00_sp_compl(ha, sp);
L
Linus Torvalds 已提交
1339 1340 1341 1342 1343 1344 1345 1346 1347 1348
}

/**
 * qla2x00_status_cont_entry() - Process a Status Continuations entry.
 * @ha: SCSI driver HA context
 * @pkt: Entry pointer
 *
 * Extended sense data.
 */
static void
1349
qla2x00_status_cont_entry(scsi_qla_host_t *vha, sts_cont_entry_t *pkt)
L
Linus Torvalds 已提交
1350 1351
{
	uint8_t		sense_sz = 0;
1352 1353
	struct qla_hw_data *ha = vha->hw;
	srb_t		*sp = vha->status_srb;
L
Linus Torvalds 已提交
1354 1355 1356 1357 1358 1359
	struct scsi_cmnd *cp;

	if (sp != NULL && sp->request_sense_length != 0) {
		cp = sp->cmd;
		if (cp == NULL) {
			DEBUG2(printk("%s(): Cmd already returned back to OS "
1360
			    "sp=%p.\n", __func__, sp));
L
Linus Torvalds 已提交
1361 1362
			qla_printk(KERN_INFO, ha,
			    "cmd is NULL: already returned to OS (sp=%p)\n",
A
Andrew Vasquez 已提交
1363
			    sp);
L
Linus Torvalds 已提交
1364

1365
			vha->status_srb = NULL;
L
Linus Torvalds 已提交
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375
			return;
		}

		if (sp->request_sense_length > sizeof(pkt->data)) {
			sense_sz = sizeof(pkt->data);
		} else {
			sense_sz = sp->request_sense_length;
		}

		/* Move sense data. */
1376
		if (IS_FWI2_CAPABLE(ha))
1377
			host_to_fcp_swap(pkt->data, sizeof(pkt->data));
L
Linus Torvalds 已提交
1378 1379 1380 1381 1382 1383 1384 1385
		memcpy(sp->request_sense_ptr, pkt->data, sense_sz);
		DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz));

		sp->request_sense_ptr += sense_sz;
		sp->request_sense_length -= sense_sz;

		/* Place command on done queue. */
		if (sp->request_sense_length == 0) {
1386
			vha->status_srb = NULL;
1387
			qla2x00_sp_compl(ha, sp);
L
Linus Torvalds 已提交
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397
		}
	}
}

/**
 * qla2x00_error_entry() - Process an error entry.
 * @ha: SCSI driver HA context
 * @pkt: Entry pointer
 */
static void
1398
qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
L
Linus Torvalds 已提交
1399 1400
{
	srb_t *sp;
1401
	struct qla_hw_data *ha = vha->hw;
1402
	struct req_que *req = rsp->req;
L
Linus Torvalds 已提交
1403 1404 1405 1406 1407 1408
#if defined(QL_DEBUG_LEVEL_2)
	if (pkt->entry_status & RF_INV_E_ORDER)
		qla_printk(KERN_ERR, ha, "%s: Invalid Entry Order\n", __func__);
	else if (pkt->entry_status & RF_INV_E_COUNT)
		qla_printk(KERN_ERR, ha, "%s: Invalid Entry Count\n", __func__);
	else if (pkt->entry_status & RF_INV_E_PARAM)
A
Andrew Vasquez 已提交
1409
		qla_printk(KERN_ERR, ha,
L
Linus Torvalds 已提交
1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420
		    "%s: Invalid Entry Parameter\n", __func__);
	else if (pkt->entry_status & RF_INV_E_TYPE)
		qla_printk(KERN_ERR, ha, "%s: Invalid Entry Type\n", __func__);
	else if (pkt->entry_status & RF_BUSY)
		qla_printk(KERN_ERR, ha, "%s: Busy\n", __func__);
	else
		qla_printk(KERN_ERR, ha, "%s: UNKNOWN flag error\n", __func__);
#endif

	/* Validate handle. */
	if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
1421
		sp = req->outstanding_cmds[pkt->handle];
L
Linus Torvalds 已提交
1422 1423 1424 1425 1426
	else
		sp = NULL;

	if (sp) {
		/* Free outstanding command slot. */
1427
		req->outstanding_cmds[pkt->handle] = NULL;
1428

L
Linus Torvalds 已提交
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438
		/* Bad payload or header */
		if (pkt->entry_status &
		    (RF_INV_E_ORDER | RF_INV_E_COUNT |
		     RF_INV_E_PARAM | RF_INV_E_TYPE)) {
			sp->cmd->result = DID_ERROR << 16;
		} else if (pkt->entry_status & RF_BUSY) {
			sp->cmd->result = DID_BUS_BUSY << 16;
		} else {
			sp->cmd->result = DID_ERROR << 16;
		}
1439
		qla2x00_sp_compl(ha, sp);
L
Linus Torvalds 已提交
1440

1441 1442
	} else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type ==
	    COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7) {
L
Linus Torvalds 已提交
1443
		DEBUG2(printk("scsi(%ld): Error entry - invalid handle\n",
1444
		    vha->host_no));
L
Linus Torvalds 已提交
1445 1446 1447
		qla_printk(KERN_WARNING, ha,
		    "Error entry - invalid handle\n");

1448 1449
		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
		qla2xxx_wake_dpc(vha);
L
Linus Torvalds 已提交
1450 1451 1452
	}
}

1453 1454 1455 1456 1457 1458
/**
 * qla24xx_mbx_completion() - Process mailbox command completions.
 * @ha: SCSI driver HA context
 * @mb0: Mailbox0 register
 */
static void
1459
qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
1460 1461 1462
{
	uint16_t	cnt;
	uint16_t __iomem *wptr;
1463
	struct qla_hw_data *ha = vha->hw;
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;

	/* Load return mailbox registers. */
	ha->flags.mbox_int = 1;
	ha->mailbox_out[0] = mb0;
	wptr = (uint16_t __iomem *)&reg->mailbox1;

	for (cnt = 1; cnt < ha->mbx_count; cnt++) {
		ha->mailbox_out[cnt] = RD_REG_WORD(wptr);
		wptr++;
	}

	if (ha->mcp) {
		DEBUG3(printk("%s(%ld): Got mailbox completion. cmd=%x.\n",
1478
		    __func__, vha->host_no, ha->mcp->mb[0]));
1479 1480
	} else {
		DEBUG2_3(printk("%s(%ld): MBX pointer ERROR!\n",
1481
		    __func__, vha->host_no));
1482 1483 1484 1485 1486 1487 1488 1489
	}
}

/**
 * qla24xx_process_response_queue() - Process response queue entries.
 * @ha: SCSI driver HA context
 */
void
1490
qla24xx_process_response_queue(struct rsp_que *rsp)
1491 1492
{
	struct sts_entry_24xx *pkt;
1493 1494 1495
	struct scsi_qla_host *vha;

	vha = qla2x00_get_rsp_host(rsp);
1496

1497
	if (!vha->flags.online)
1498 1499
		return;

1500 1501
	while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
		pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
1502

1503 1504 1505 1506
		rsp->ring_index++;
		if (rsp->ring_index == rsp->length) {
			rsp->ring_index = 0;
			rsp->ring_ptr = rsp->ring;
1507
		} else {
1508
			rsp->ring_ptr++;
1509 1510 1511 1512
		}

		if (pkt->entry_status != 0) {
			DEBUG3(printk(KERN_INFO
1513
			    "scsi(%ld): Process error entry.\n", vha->host_no));
1514

1515
			qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt);
1516 1517 1518 1519 1520 1521 1522
			((response_t *)pkt)->signature = RESPONSE_PROCESSED;
			wmb();
			continue;
		}

		switch (pkt->entry_type) {
		case STATUS_TYPE:
1523
			qla2x00_status_entry(vha, rsp, pkt);
1524 1525
			break;
		case STATUS_CONT_TYPE:
1526
			qla2x00_status_cont_entry(vha, (sts_cont_entry_t *)pkt);
1527
			break;
1528
		case VP_RPT_ID_IOCB_TYPE:
1529
			qla24xx_report_id_acquisition(vha,
1530 1531
			    (struct vp_rpt_id_entry_24xx *)pkt);
			break;
1532 1533 1534 1535 1536
		default:
			/* Type Not Supported. */
			DEBUG4(printk(KERN_WARNING
			    "scsi(%ld): Received unknown response pkt type %x "
			    "entry status=%x.\n",
1537
			    vha->host_no, pkt->entry_type, pkt->entry_status));
1538 1539 1540 1541 1542 1543 1544
			break;
		}
		((response_t *)pkt)->signature = RESPONSE_PROCESSED;
		wmb();
	}

	/* Adjust ring index */
1545
	WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
1546 1547
}

1548
static void
1549
qla2xxx_check_risc_status(scsi_qla_host_t *vha)
1550 1551 1552
{
	int rval;
	uint32_t cnt;
1553
	struct qla_hw_data *ha = vha->hw;
1554 1555
	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;

1556
	if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))
1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594
		return;

	rval = QLA_SUCCESS;
	WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
	RD_REG_DWORD(&reg->iobase_addr);
	WRT_REG_DWORD(&reg->iobase_window, 0x0001);
	for (cnt = 10000; (RD_REG_DWORD(&reg->iobase_window) & BIT_0) == 0 &&
	    rval == QLA_SUCCESS; cnt--) {
		if (cnt) {
			WRT_REG_DWORD(&reg->iobase_window, 0x0001);
			udelay(10);
		} else
			rval = QLA_FUNCTION_TIMEOUT;
	}
	if (rval == QLA_SUCCESS)
		goto next_test;

	WRT_REG_DWORD(&reg->iobase_window, 0x0003);
	for (cnt = 100; (RD_REG_DWORD(&reg->iobase_window) & BIT_0) == 0 &&
	    rval == QLA_SUCCESS; cnt--) {
		if (cnt) {
			WRT_REG_DWORD(&reg->iobase_window, 0x0003);
			udelay(10);
		} else
			rval = QLA_FUNCTION_TIMEOUT;
	}
	if (rval != QLA_SUCCESS)
		goto done;

next_test:
	if (RD_REG_DWORD(&reg->iobase_c8) & BIT_3)
		qla_printk(KERN_INFO, ha, "Additional code -- 0x55AA.\n");

done:
	WRT_REG_DWORD(&reg->iobase_window, 0x0000);
	RD_REG_DWORD(&reg->iobase_window);
}

1595 1596 1597 1598 1599 1600 1601 1602 1603 1604
/**
 * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx.
 * @irq:
 * @dev_id: SCSI driver HA context
 *
 * Called by system whenever the host adapter generates an interrupt.
 *
 * Returns handled flag.
 */
irqreturn_t
1605
qla24xx_intr_handler(int irq, void *dev_id)
1606
{
1607 1608
	scsi_qla_host_t	*vha;
	struct qla_hw_data *ha;
1609 1610 1611 1612 1613 1614
	struct device_reg_24xx __iomem *reg;
	int		status;
	unsigned long	iter;
	uint32_t	stat;
	uint32_t	hccr;
	uint16_t	mb[4];
1615
	struct rsp_que *rsp;
1616

1617 1618
	rsp = (struct rsp_que *) dev_id;
	if (!rsp) {
1619
		printk(KERN_INFO
1620
		    "%s(): NULL response queue pointer\n", __func__);
1621 1622 1623
		return IRQ_NONE;
	}

1624
	ha = rsp->hw;
1625 1626 1627
	reg = &ha->iobase->isp24;
	status = 0;

1628
	spin_lock(&ha->hardware_lock);
1629
	vha = qla2x00_get_rsp_host(rsp);
1630 1631 1632
	for (iter = 50; iter--; ) {
		stat = RD_REG_DWORD(&reg->host_status);
		if (stat & HSRX_RISC_PAUSED) {
1633 1634 1635
			if (pci_channel_offline(ha->pdev))
				break;

1636 1637 1638 1639
			hccr = RD_REG_DWORD(&reg->hccr);

			qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
			    "Dumping firmware!\n", hccr);
1640

1641
			qla2xxx_check_risc_status(vha);
1642

1643 1644
			ha->isp_ops->fw_dump(vha, 1);
			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
1645 1646 1647 1648 1649 1650 1651 1652 1653
			break;
		} else if ((stat & HSRX_RISC_INT) == 0)
			break;

		switch (stat & 0xff) {
		case 0x1:
		case 0x2:
		case 0x10:
		case 0x11:
1654
			qla24xx_mbx_completion(vha, MSW(stat));
1655 1656 1657 1658 1659 1660 1661 1662
			status |= MBX_INTERRUPT;

			break;
		case 0x12:
			mb[0] = MSW(stat);
			mb[1] = RD_REG_WORD(&reg->mailbox1);
			mb[2] = RD_REG_WORD(&reg->mailbox2);
			mb[3] = RD_REG_WORD(&reg->mailbox3);
1663
			qla2x00_async_event(vha, rsp, mb);
1664 1665
			break;
		case 0x13:
1666 1667
		case 0x14:
			qla24xx_process_response_queue(rsp);
1668 1669 1670 1671
			break;
		default:
			DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
			    "(%d).\n",
1672
			    vha->host_no, stat & 0xff));
1673 1674 1675 1676 1677
			break;
		}
		WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
		RD_REG_DWORD_RELAXED(&reg->hccr);
	}
1678
	spin_unlock(&ha->hardware_lock);
1679 1680 1681 1682

	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
1683
		complete(&ha->mbx_intr_comp);
1684 1685 1686 1687 1688
	}

	return IRQ_HANDLED;
}

1689 1690 1691
static irqreturn_t
qla24xx_msix_rsp_q(int irq, void *dev_id)
{
1692 1693
	struct qla_hw_data *ha;
	struct rsp_que *rsp;
1694 1695
	struct device_reg_24xx __iomem *reg;

1696 1697 1698 1699 1700 1701 1702
	rsp = (struct rsp_que *) dev_id;
	if (!rsp) {
		printk(KERN_INFO
		"%s(): NULL response queue pointer\n", __func__);
		return IRQ_NONE;
	}
	ha = rsp->hw;
1703 1704
	reg = &ha->iobase->isp24;

1705
	spin_lock_irq(&ha->hardware_lock);
1706

1707
	qla24xx_process_response_queue(rsp);
1708 1709
	WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);

1710
	spin_unlock_irq(&ha->hardware_lock);
1711 1712 1713 1714

	return IRQ_HANDLED;
}

1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739
static irqreturn_t
qla25xx_msix_rsp_q(int irq, void *dev_id)
{
	struct qla_hw_data *ha;
	struct rsp_que *rsp;
	struct device_reg_24xx __iomem *reg;

	rsp = (struct rsp_que *) dev_id;
	if (!rsp) {
		printk(KERN_INFO
			"%s(): NULL response queue pointer\n", __func__);
		return IRQ_NONE;
	}
	ha = rsp->hw;
	reg = &ha->iobase->isp24;

	spin_lock_irq(&ha->hardware_lock);

	qla24xx_process_response_queue(rsp);

	spin_unlock_irq(&ha->hardware_lock);

	return IRQ_HANDLED;
}

1740 1741 1742
static irqreturn_t
qla24xx_msix_default(int irq, void *dev_id)
{
1743 1744 1745
	scsi_qla_host_t	*vha;
	struct qla_hw_data *ha;
	struct rsp_que *rsp;
1746 1747 1748 1749 1750 1751
	struct device_reg_24xx __iomem *reg;
	int		status;
	uint32_t	stat;
	uint32_t	hccr;
	uint16_t	mb[4];

1752 1753 1754 1755 1756 1757 1758
	rsp = (struct rsp_que *) dev_id;
	if (!rsp) {
		DEBUG(printk(
		"%s(): NULL response queue pointer\n", __func__));
		return IRQ_NONE;
	}
	ha = rsp->hw;
1759 1760 1761
	reg = &ha->iobase->isp24;
	status = 0;

1762
	spin_lock_irq(&ha->hardware_lock);
1763
	vha = qla2x00_get_rsp_host(rsp);
1764
	do {
1765 1766
		stat = RD_REG_DWORD(&reg->host_status);
		if (stat & HSRX_RISC_PAUSED) {
1767 1768 1769
			if (pci_channel_offline(ha->pdev))
				break;

1770 1771 1772 1773
			hccr = RD_REG_DWORD(&reg->hccr);

			qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
			    "Dumping firmware!\n", hccr);
1774

1775
			qla2xxx_check_risc_status(vha);
1776

1777 1778
			ha->isp_ops->fw_dump(vha, 1);
			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
1779 1780 1781 1782 1783 1784 1785 1786 1787
			break;
		} else if ((stat & HSRX_RISC_INT) == 0)
			break;

		switch (stat & 0xff) {
		case 0x1:
		case 0x2:
		case 0x10:
		case 0x11:
1788
			qla24xx_mbx_completion(vha, MSW(stat));
1789 1790 1791 1792 1793 1794 1795 1796
			status |= MBX_INTERRUPT;

			break;
		case 0x12:
			mb[0] = MSW(stat);
			mb[1] = RD_REG_WORD(&reg->mailbox1);
			mb[2] = RD_REG_WORD(&reg->mailbox2);
			mb[3] = RD_REG_WORD(&reg->mailbox3);
1797
			qla2x00_async_event(vha, rsp, mb);
1798 1799
			break;
		case 0x13:
1800 1801
		case 0x14:
			qla24xx_process_response_queue(rsp);
1802 1803 1804 1805
			break;
		default:
			DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
			    "(%d).\n",
1806
			    vha->host_no, stat & 0xff));
1807 1808 1809
			break;
		}
		WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
1810
	} while (0);
1811
	spin_unlock_irq(&ha->hardware_lock);
1812 1813 1814 1815

	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
1816
		complete(&ha->mbx_intr_comp);
1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827
	}

	return IRQ_HANDLED;
}

/* Interrupt handling helpers. */

struct qla_init_msix_entry {
	uint16_t entry;
	uint16_t index;
	const char *name;
1828
	irq_handler_t handler;
1829 1830
};

1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843
static struct qla_init_msix_entry base_queue = {
	.entry = 0,
	.index = 0,
	.name = "qla2xxx (default)",
	.handler = qla24xx_msix_default,
};

static struct qla_init_msix_entry base_rsp_queue = {
	.entry = 1,
	.index = 1,
	.name = "qla2xxx (rsp_q)",
	.handler = qla24xx_msix_rsp_q,
};
1844

1845 1846 1847 1848 1849
static struct qla_init_msix_entry multi_rsp_queue = {
	.entry = 1,
	.index = 1,
	.name = "qla2xxx (multi_q)",
	.handler = qla25xx_msix_rsp_q,
1850 1851 1852
};

static void
1853
qla24xx_disable_msix(struct qla_hw_data *ha)
1854 1855 1856 1857
{
	int i;
	struct qla_msix_entry *qentry;

1858 1859
	for (i = 0; i < ha->msix_count; i++) {
		qentry = &ha->msix_entries[i];
1860
		if (qentry->have_irq)
1861
			free_irq(qentry->vector, qentry->rsp);
1862 1863
	}
	pci_disable_msix(ha->pdev);
1864 1865 1866
	kfree(ha->msix_entries);
	ha->msix_entries = NULL;
	ha->flags.msix_enabled = 0;
1867 1868 1869
}

static int
1870
qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
1871
{
1872
#define MIN_MSIX_COUNT	2
1873
	int i, ret;
1874
	struct msix_entry *entries;
1875
	struct qla_msix_entry *qentry;
1876 1877 1878 1879 1880 1881
	struct qla_init_msix_entry *msix_queue;

	entries = kzalloc(sizeof(struct msix_entry) * ha->msix_count,
					GFP_KERNEL);
	if (!entries)
		return -ENOMEM;
1882

1883 1884
	for (i = 0; i < ha->msix_count; i++)
		entries[i].entry = i;
1885

1886
	ret = pci_enable_msix(ha->pdev, entries, ha->msix_count);
1887
	if (ret) {
1888 1889 1890
		if (ret < MIN_MSIX_COUNT)
			goto msix_failed;

1891
		qla_printk(KERN_WARNING, ha,
1892 1893 1894 1895 1896
			"MSI-X: Failed to enable support -- %d/%d\n"
			" Retry with %d vectors\n", ha->msix_count, ret, ret);
		ha->msix_count = ret;
		ret = pci_enable_msix(ha->pdev, entries, ha->msix_count);
		if (ret) {
1897
msix_failed:
1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908
			qla_printk(KERN_WARNING, ha, "MSI-X: Failed to enable"
				" support, giving up -- %d/%d\n",
				ha->msix_count, ret);
			goto msix_out;
		}
		ha->max_queues = ha->msix_count - 1;
	}
	ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) *
				ha->msix_count, GFP_KERNEL);
	if (!ha->msix_entries) {
		ret = -ENOMEM;
1909 1910 1911 1912
		goto msix_out;
	}
	ha->flags.msix_enabled = 1;

1913 1914 1915 1916
	for (i = 0; i < ha->msix_count; i++) {
		qentry = &ha->msix_entries[i];
		qentry->vector = entries[i].vector;
		qentry->entry = entries[i].entry;
1917
		qentry->have_irq = 0;
1918
		qentry->rsp = NULL;
1919 1920
	}

1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960
	/* Enable MSI-X for AENs for queue 0 */
	qentry = &ha->msix_entries[0];
	ret = request_irq(qentry->vector, base_queue.handler, 0,
					base_queue.name, rsp);
	if (ret) {
		qla_printk(KERN_WARNING, ha,
			"MSI-X: Unable to register handler -- %x/%d.\n",
			qentry->vector, ret);
		qla24xx_disable_msix(ha);
		goto msix_out;
	}
	qentry->have_irq = 1;
	qentry->rsp = rsp;

	/* Enable MSI-X vector for response queue update for queue 0 */
	if (ha->max_queues > 1 && ha->mqiobase) {
		ha->mqenable = 1;
		msix_queue = &multi_rsp_queue;
		qla_printk(KERN_INFO, ha,
				"MQ enabled, Number of Queue Resources: %d \n",
				ha->max_queues);
	} else {
		ha->mqenable = 0;
		msix_queue = &base_rsp_queue;
	}

	qentry = &ha->msix_entries[1];
	ret = request_irq(qentry->vector, msix_queue->handler, 0,
						msix_queue->name, rsp);
	if (ret) {
		qla_printk(KERN_WARNING, ha,
			"MSI-X: Unable to register handler -- %x/%d.\n",
			qentry->vector, ret);
		qla24xx_disable_msix(ha);
		ha->mqenable = 0;
		goto msix_out;
	}
	qentry->have_irq = 1;
	qentry->rsp = rsp;

1961
msix_out:
1962
	kfree(entries);
1963 1964 1965 1966
	return ret;
}

int
1967
qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
1968 1969
{
	int ret;
1970
	device_reg_t __iomem *reg = ha->iobase;
1971 1972

	/* If possible, enable MSI-X. */
1973 1974
	if (!IS_QLA2432(ha) && !IS_QLA2532(ha) &&
	    !IS_QLA8432(ha) && !IS_QLA8001(ha))
1975 1976
		goto skip_msix;

1977 1978
	if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX ||
		!QLA_MSIX_FW_MODE_1(ha->fw_attributes))) {
1979
		DEBUG2(qla_printk(KERN_WARNING, ha,
1980 1981
		"MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n",
			ha->pdev->revision, ha->fw_attributes));
1982 1983 1984 1985

		goto skip_msix;
	}

1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997
	if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
	    (ha->pdev->subsystem_device == 0x7040 ||
		ha->pdev->subsystem_device == 0x7041 ||
		ha->pdev->subsystem_device == 0x1705)) {
		DEBUG2(qla_printk(KERN_WARNING, ha,
		    "MSI-X: Unsupported ISP2432 SSVID/SSDID (0x%X, 0x%X).\n",
		    ha->pdev->subsystem_vendor,
		    ha->pdev->subsystem_device));

		goto skip_msi;
	}

1998
	ret = qla24xx_enable_msix(ha, rsp);
1999 2000 2001 2002
	if (!ret) {
		DEBUG2(qla_printk(KERN_INFO, ha,
		    "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision,
		    ha->fw_attributes));
2003
		goto clear_risc_ints;
2004 2005 2006 2007
	}
	qla_printk(KERN_WARNING, ha,
	    "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
skip_msix:
2008

2009 2010
	if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
	    !IS_QLA8001(ha))
2011 2012 2013 2014 2015 2016 2017 2018 2019
		goto skip_msi;

	ret = pci_enable_msi(ha->pdev);
	if (!ret) {
		DEBUG2(qla_printk(KERN_INFO, ha, "MSI: Enabled.\n"));
		ha->flags.msi_enabled = 1;
	}
skip_msi:

2020
	ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
2021
	    IRQF_SHARED, QLA2XXX_DRIVER_NAME, rsp);
2022
	if (ret) {
2023 2024 2025
		qla_printk(KERN_WARNING, ha,
		    "Failed to reserve interrupt %d already in use.\n",
		    ha->pdev->irq);
2026 2027 2028 2029 2030
		goto fail;
	}
	ha->flags.inta_enabled = 1;
clear_risc_ints:

2031 2032 2033 2034 2035 2036
	/*
	 * FIXME: Noted that 8014s were being dropped during NK testing.
	 * Timing deltas during MSI-X/INTa transitions?
	 */
	if (IS_QLA81XX(ha))
		goto fail;
2037
	spin_lock_irq(&ha->hardware_lock);
2038 2039 2040 2041 2042 2043 2044
	if (IS_FWI2_CAPABLE(ha)) {
		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
		WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);
	} else {
		WRT_REG_WORD(&reg->isp.semaphore, 0);
		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_RISC_INT);
		WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_HOST_INT);
2045
	}
2046
	spin_unlock_irq(&ha->hardware_lock);
2047

2048
fail:
2049 2050 2051 2052
	return ret;
}

void
2053
qla2x00_free_irqs(scsi_qla_host_t *vha)
2054
{
2055
	struct qla_hw_data *ha = vha->hw;
2056
	struct rsp_que *rsp = ha->rsp_q_map[0];
2057 2058 2059

	if (ha->flags.msix_enabled)
		qla24xx_disable_msix(ha);
2060
	else if (ha->flags.inta_enabled) {
2061
		free_irq(ha->pdev->irq, rsp);
2062 2063
		pci_disable_msi(ha->pdev);
	}
2064
}
2065 2066 2067 2068 2069 2070 2071

static struct scsi_qla_host *
qla2x00_get_rsp_host(struct rsp_que *rsp)
{
	srb_t *sp;
	struct qla_hw_data *ha = rsp->hw;
	struct scsi_qla_host *vha = NULL;
2072 2073 2074 2075 2076 2077 2078 2079 2080
	struct sts_entry_24xx *pkt;
	struct req_que *req;

	if (rsp->id) {
		pkt = (struct sts_entry_24xx *) rsp->ring_ptr;
		req = rsp->req;
		if (pkt && pkt->handle < MAX_OUTSTANDING_COMMANDS) {
			sp = req->outstanding_cmds[pkt->handle];
			if (sp)
2081
				vha = sp->fcport->vha;
2082
		}
2083 2084
	}
	if (!vha)
2085
	/* handle it in base queue */
2086 2087 2088 2089
		vha = pci_get_drvdata(ha->pdev);

	return vha;
}
2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108

int qla25xx_request_irq(struct rsp_que *rsp)
{
	struct qla_hw_data *ha = rsp->hw;
	struct qla_init_msix_entry *intr = &multi_rsp_queue;
	struct qla_msix_entry *msix = rsp->msix;
	int ret;

	ret = request_irq(msix->vector, intr->handler, 0, intr->name, rsp);
	if (ret) {
		qla_printk(KERN_WARNING, ha,
			"MSI-X: Unable to register handler -- %x/%d.\n",
			msix->vector, ret);
		return ret;
	}
	msix->have_irq = 1;
	msix->rsp = rsp;
	return ret;
}