ql4_isr.c revision 6434080b127088606e03d2ecfe5ffdd797e38d63
1afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu/*
2afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * QLogic iSCSI HBA Driver
3afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * Copyright (c)  2003-2006 QLogic Corporation
4afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu *
5afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * See LICENSE.qla4xxx for copyright and licensing details.
6afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu */
7afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
8afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu#include "ql4_def.h"
9401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu#include "ql4_glbl.h"
10401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu#include "ql4_dbg.h"
11401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu#include "ql4_inline.h"
12afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
13afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu/**
1494bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins * qla4xxx_copy_sense - copy sense data	into cmd sense buffer
1594bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins * @ha: Pointer to host adapter structure.
1694bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins * @sts_entry: Pointer to status entry structure.
1794bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins * @srb: Pointer to srb structure.
1894bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins **/
1994bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higginsstatic void qla4xxx_copy_sense(struct scsi_qla_host *ha,
2094bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins                               struct status_entry *sts_entry,
2194bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins                               struct srb *srb)
2294bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins{
2394bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	struct scsi_cmnd *cmd = srb->cmd;
2494bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	uint16_t sense_len;
2594bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
2694bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
2794bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	sense_len = le16_to_cpu(sts_entry->senseDataByteCnt);
2894bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	if (sense_len == 0)
2994bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		return;
3094bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
3194bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	/* Save total available sense length,
3294bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	 * not to exceed cmd's sense buffer size */
3394bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	sense_len = min_t(uint16_t, sense_len, SCSI_SENSE_BUFFERSIZE);
3494bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	srb->req_sense_ptr = cmd->sense_buffer;
3594bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	srb->req_sense_len = sense_len;
3694bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
3794bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	/* Copy sense from sts_entry pkt */
3894bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	sense_len = min_t(uint16_t, sense_len, IOCB_MAX_SENSEDATA_LEN);
3994bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	memcpy(cmd->sense_buffer, sts_entry->senseData, sense_len);
4094bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
4194bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: %s: sense key = %x, "
4294bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		"ASL= %02x, ASC/ASCQ = %02x/%02x\n", ha->host_no,
4394bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		cmd->device->channel, cmd->device->id,
4494bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		cmd->device->lun, __func__,
4594bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		sts_entry->senseData[2] & 0x0f,
4694bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		sts_entry->senseData[7],
4794bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		sts_entry->senseData[12],
4894bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		sts_entry->senseData[13]));
4994bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
5094bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	DEBUG5(qla4xxx_dump_buffer(cmd->sense_buffer, sense_len));
5194bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	srb->flags |= SRB_GOT_SENSE;
5294bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
5394bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	/* Update srb, in case a sts_cont pkt follows */
5494bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	srb->req_sense_ptr += sense_len;
5594bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	srb->req_sense_len -= sense_len;
5694bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	if (srb->req_sense_len != 0)
5794bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		ha->status_srb = srb;
5894bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	else
5994bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		ha->status_srb = NULL;
6094bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins}
6194bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
6294bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins/**
6394bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins * qla4xxx_status_cont_entry - Process a Status Continuations entry.
6494bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins * @ha: SCSI driver HA context
6594bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins * @sts_cont: Entry pointer
6694bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins *
6794bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins * Extended sense data.
6894bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins */
6994bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higginsstatic void
7094bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higginsqla4xxx_status_cont_entry(struct scsi_qla_host *ha,
7194bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins			  struct status_cont_entry *sts_cont)
7294bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins{
7394bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	struct srb *srb = ha->status_srb;
7494bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	struct scsi_cmnd *cmd;
75735e41543c12c245290cf652727893a66cbd8ab6Vikas Chaudhary	uint16_t sense_len;
7694bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
7794bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	if (srb == NULL)
7894bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		return;
7994bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
8094bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	cmd = srb->cmd;
8194bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	if (cmd == NULL) {
8294bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		DEBUG2(printk(KERN_INFO "scsi%ld: %s: Cmd already returned "
8394bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins			"back to OS srb=%p srb->state:%d\n", ha->host_no,
8494bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins			__func__, srb, srb->state));
8594bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		ha->status_srb = NULL;
8694bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		return;
8794bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	}
8894bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
8994bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	/* Copy sense data. */
9094bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	sense_len = min_t(uint16_t, srb->req_sense_len,
9194bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins			  IOCB_MAX_EXT_SENSEDATA_LEN);
9294bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	memcpy(srb->req_sense_ptr, sts_cont->ext_sense_data, sense_len);
9394bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	DEBUG5(qla4xxx_dump_buffer(srb->req_sense_ptr, sense_len));
9494bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
9594bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	srb->req_sense_ptr += sense_len;
9694bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	srb->req_sense_len -= sense_len;
9794bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
9894bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	/* Place command on done queue. */
9994bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	if (srb->req_sense_len == 0) {
10009a0f719896659a6c32df11426e55795012c06ffVikas Chaudhary		kref_put(&srb->srb_ref, qla4xxx_srb_compl);
10194bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		ha->status_srb = NULL;
10294bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	}
10394bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins}
10494bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins
10594bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins/**
106afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * qla4xxx_status_entry - processes status IOCBs
107afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * @ha: Pointer to host adapter structure.
108afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * @sts_entry: Pointer to status entry structure.
109afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu **/
110afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulustatic void qla4xxx_status_entry(struct scsi_qla_host *ha,
111afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 struct status_entry *sts_entry)
112afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu{
113afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	uint8_t scsi_status;
114afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	struct scsi_cmnd *cmd;
115afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	struct srb *srb;
116afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	struct ddb_entry *ddb_entry;
117afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	uint32_t residual;
118afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
119afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle));
120afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	if (!srb) {
121afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Status Entry invalid "
122afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      "handle 0x%x, sp=%p. This cmd may have already "
123afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      "been completed.\n", ha->host_no, __func__,
124afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      le32_to_cpu(sts_entry->handle), srb));
125c2660df310a3c445194748b54f51b7224639e742Vikas Chaudhary		ql4_printk(KERN_WARNING, ha, "%s invalid status entry:"
126c2660df310a3c445194748b54f51b7224639e742Vikas Chaudhary		    " handle=0x%0x\n", __func__, sts_entry->handle);
1279d56291366cd6ab156be722e42cf487bef20f5fdDavid C Somayajulu		set_bit(DPC_RESET_HA, &ha->dpc_flags);
128afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		return;
129afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	}
130afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
131afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	cmd = srb->cmd;
132afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	if (cmd == NULL) {
133afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		DEBUG2(printk("scsi%ld: %s: Command already returned back to "
134afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      "OS pkt->handle=%d srb=%p srb->state:%d\n",
135afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      ha->host_no, __func__, sts_entry->handle,
136afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      srb, srb->state));
137c2660df310a3c445194748b54f51b7224639e742Vikas Chaudhary		ql4_printk(KERN_WARNING, ha, "Command is NULL:"
138c2660df310a3c445194748b54f51b7224639e742Vikas Chaudhary		    " already returned to OS (srb=%p)\n", srb);
139afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		return;
140afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	}
141afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
142afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	ddb_entry = srb->ddb;
143afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	if (ddb_entry == NULL) {
144afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		cmd->result = DID_NO_CONNECT << 16;
145afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		goto status_entry_exit;
146afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	}
147afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
148afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	residual = le32_to_cpu(sts_entry->residualByteCnt);
149afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
150afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	/* Translate ISP error to a Linux SCSI error. */
151afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	scsi_status = sts_entry->scsiStatus;
152afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	switch (sts_entry->completionStatus) {
153afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	case SCS_COMPLETE:
154afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
1556ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu		if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) {
1566ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu			cmd->result = DID_ERROR << 16;
1576ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu			break;
1586ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu		}
1596ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu
1606ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu		if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) {
1615f7186c841a13abff0bf81ee93754b4f46e19141FUJITA Tomonori			scsi_set_resid(cmd, residual);
1629d56291366cd6ab156be722e42cf487bef20f5fdDavid C Somayajulu			if (!scsi_status && ((scsi_bufflen(cmd) - residual) <
1639d56291366cd6ab156be722e42cf487bef20f5fdDavid C Somayajulu				cmd->underflow)) {
1646ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu
1656ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu				cmd->result = DID_ERROR << 16;
1666ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu
1676ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu				DEBUG2(printk("scsi%ld:%d:%d:%d: %s: "
1686ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					"Mid-layer Data underrun0, "
1696ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					"xferlen = 0x%x, "
1706ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					"residual = 0x%x\n", ha->host_no,
1716ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					cmd->device->channel,
1726ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					cmd->device->id,
1736ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					cmd->device->lun, __func__,
1746ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					scsi_bufflen(cmd), residual));
1756ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu				break;
1766ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu			}
1776ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu		}
178afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
179afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		cmd->result = DID_OK << 16 | scsi_status;
180afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
181afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		if (scsi_status != SCSI_CHECK_CONDITION)
182afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
183afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
184afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/* Copy Sense Data into sense buffer. */
18594bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins		qla4xxx_copy_sense(ha, sts_entry, srb);
186afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		break;
187afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
188afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	case SCS_INCOMPLETE:
189afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/* Always set the status to DID_ERROR, since
190afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * all conditions result in that status anyway */
191afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		cmd->result = DID_ERROR << 16;
192afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		break;
193afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
194afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	case SCS_RESET_OCCURRED:
195afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		DEBUG2(printk("scsi%ld:%d:%d:%d: %s: Device RESET occurred\n",
196afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      ha->host_no, cmd->device->channel,
197afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      cmd->device->id, cmd->device->lun, __func__));
198afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
199afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		cmd->result = DID_RESET << 16;
200afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		break;
201afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
202afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	case SCS_ABORTED:
203afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		DEBUG2(printk("scsi%ld:%d:%d:%d: %s: Abort occurred\n",
204afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      ha->host_no, cmd->device->channel,
205afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      cmd->device->id, cmd->device->lun, __func__));
206afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
207afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		cmd->result = DID_RESET << 16;
208afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		break;
209afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
210afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	case SCS_TIMEOUT:
211afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: Timeout\n",
212afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      ha->host_no, cmd->device->channel,
213afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      cmd->device->id, cmd->device->lun));
214afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
21556d7fcfa815564b40a1b0ec7a30ea8cb3bc0713eMike Christie		cmd->result = DID_TRANSPORT_DISRUPTED << 16;
216afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
217afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/*
218afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * Mark device missing so that we won't continue to send
219afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * I/O to this device.	We should get a ddb state change
220afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * AEN soon.
221afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 */
222afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
223afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			qla4xxx_mark_device_missing(ha, ddb_entry);
224afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		break;
225afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
226afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	case SCS_DATA_UNDERRUN:
227afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	case SCS_DATA_OVERRUN:
2286ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu		if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) ||
229b06fc73a9ebd352065dd4dd3139fb53ed72ac970Mike Christie		     (sts_entry->completionStatus == SCS_DATA_OVERRUN)) {
230b06fc73a9ebd352065dd4dd3139fb53ed72ac970Mike Christie			DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun\n",
231b06fc73a9ebd352065dd4dd3139fb53ed72ac970Mike Christie				      ha->host_no,
232afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      cmd->device->channel, cmd->device->id,
233b06fc73a9ebd352065dd4dd3139fb53ed72ac970Mike Christie				      cmd->device->lun, __func__));
234afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
235afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			cmd->result = DID_ERROR << 16;
236afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
237afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		}
238afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
2396ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu		scsi_set_resid(cmd, residual);
240afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
241afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/*
242afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * If there is scsi_status, it takes precedense over
243afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * underflow condition.
244afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 */
245afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		if (scsi_status != 0) {
246afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			cmd->result = DID_OK << 16 | scsi_status;
247afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
248afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			if (scsi_status != SCSI_CHECK_CONDITION)
249afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				break;
250afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
251afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/* Copy Sense Data into sense buffer. */
25294bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins			qla4xxx_copy_sense(ha, sts_entry, srb);
253afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		} else {
254afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/*
255afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * If RISC reports underrun and target does not
256afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * report it then we must have a lost frame, so
257afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * tell upper layer to retry it by reporting a
258afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * bus busy.
259afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 */
260afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			if ((sts_entry->iscsiFlags &
261afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			     ISCSI_FLAG_RESIDUAL_UNDER) == 0) {
262afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				cmd->result = DID_BUS_BUSY << 16;
2635f7186c841a13abff0bf81ee93754b4f46e19141FUJITA Tomonori			} else if ((scsi_bufflen(cmd) - residual) <
264afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				   cmd->underflow) {
265afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				/*
266afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 * Handle mid-layer underflow???
267afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 *
268afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 * For kernels less than 2.4, the driver must
269afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 * return an error if an underflow is detected.
270afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 * For kernels equal-to and above 2.4, the
271afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 * mid-layer will appearantly handle the
272afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 * underflow by detecting the residual count --
273afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 * unfortunately, we do not see where this is
274afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 * actually being done.	 In the interim, we
275afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 * will return DID_ERROR.
276afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 */
277afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				DEBUG2(printk("scsi%ld:%d:%d:%d: %s: "
2786ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					"Mid-layer Data underrun1, "
2796ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					"xferlen = 0x%x, "
2806ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					"residual = 0x%x\n", ha->host_no,
2816ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					cmd->device->channel,
2826ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					cmd->device->id,
2836ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					cmd->device->lun, __func__,
2846ea7e33ee1b74de9b60327fec1a0cd39afac3983David C Somayajulu					scsi_bufflen(cmd), residual));
285afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
286afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				cmd->result = DID_ERROR << 16;
287afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			} else {
288afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				cmd->result = DID_OK << 16;
289afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			}
290afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		}
291afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		break;
292afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
293afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	case SCS_DEVICE_LOGGED_OUT:
294afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	case SCS_DEVICE_UNAVAILABLE:
295f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: SCS_DEVICE "
296f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    "state: 0x%x\n", ha->host_no,
297f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    cmd->device->channel, cmd->device->id,
298f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    cmd->device->lun, sts_entry->completionStatus));
299afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/*
300afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * Mark device missing so that we won't continue to
301afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * send I/O to this device.  We should get a ddb
302afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * state change AEN soon.
303afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 */
304afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
305afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			qla4xxx_mark_device_missing(ha, ddb_entry);
306afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
30756d7fcfa815564b40a1b0ec7a30ea8cb3bc0713eMike Christie		cmd->result = DID_TRANSPORT_DISRUPTED << 16;
308afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		break;
309afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
310afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	case SCS_QUEUE_FULL:
311afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/*
312afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * SCSI Mid-Layer handles device queue full
313afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 */
314afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		cmd->result = DID_OK << 16 | sts_entry->scsiStatus;
315afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		DEBUG2(printk("scsi%ld:%d:%d: %s: QUEUE FULL detected "
316afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      "compl=%02x, scsi=%02x, state=%02x, iFlags=%02x,"
317afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      " iResp=%02x\n", ha->host_no, cmd->device->id,
318afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      cmd->device->lun, __func__,
319afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      sts_entry->completionStatus,
320afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      sts_entry->scsiStatus, sts_entry->state_flags,
321afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      sts_entry->iscsiFlags,
322afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      sts_entry->iscsiResponse));
323afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		break;
324afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
325afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	default:
326afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		cmd->result = DID_ERROR << 16;
327afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		break;
328afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	}
329afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
330afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulustatus_entry_exit:
331afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
33294bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	/* complete the request, if not waiting for status_continuation pkt */
333afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	srb->cc_stat = sts_entry->completionStatus;
33494bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins	if (ha->status_srb == NULL)
33509a0f719896659a6c32df11426e55795012c06ffVikas Chaudhary		kref_put(&srb->srb_ref, qla4xxx_srb_compl);
336afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu}
337afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
338afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu/**
339afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * qla4xxx_process_response_queue - process response queue completions
340afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * @ha: Pointer to host adapter structure.
341afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu *
342afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * This routine process response queue completions in interrupt context.
343afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * Hardware_lock locked upon entry
344afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu **/
345f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyvoid qla4xxx_process_response_queue(struct scsi_qla_host *ha)
346afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu{
347afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	uint32_t count = 0;
348afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	struct srb *srb = NULL;
349afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	struct status_entry *sts_entry;
350afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
351afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	/* Process all responses from response queue */
352f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	while ((ha->response_ptr->signature != RESPONSE_PROCESSED)) {
353afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		sts_entry = (struct status_entry *) ha->response_ptr;
354afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		count++;
355afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
356afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/* Advance pointers for next entry */
357afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		if (ha->response_out == (RESPONSE_QUEUE_DEPTH - 1)) {
358afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			ha->response_out = 0;
359afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			ha->response_ptr = ha->response_ring;
360afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		} else {
361afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			ha->response_out++;
362afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			ha->response_ptr++;
363afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		}
364afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
365afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/* process entry */
366afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		switch (sts_entry->hdr.entryType) {
367afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case ET_STATUS:
36894bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins			/* Common status */
369afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			qla4xxx_status_entry(ha, sts_entry);
370afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
371afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
372afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case ET_PASSTHRU_STATUS:
373afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
374afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
375afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case ET_STATUS_CONTINUATION:
37694bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins			qla4xxx_status_cont_entry(ha,
37794bced3c1b371014cbd187f2df5539b13a0e3b90Karen Higgins				(struct status_cont_entry *) sts_entry);
378afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
379afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
380afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case ET_COMMAND:
381afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/* ISP device queue is full. Command not
382afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * accepted by ISP.  Queue command for
383afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * later */
384afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
385afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			srb = qla4xxx_del_from_active_array(ha,
386afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu						    le32_to_cpu(sts_entry->
387afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu								handle));
388afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			if (srb == NULL)
389afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				goto exit_prq_invalid_handle;
390afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
391afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			DEBUG2(printk("scsi%ld: %s: FW device queue full, "
392afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      "srb %p\n", ha->host_no, __func__, srb));
393afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
394afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/* ETRY normally by sending it back with
395afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * DID_BUS_BUSY */
396afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			srb->cmd->result = DID_BUS_BUSY << 16;
39709a0f719896659a6c32df11426e55795012c06ffVikas Chaudhary			kref_put(&srb->srb_ref, qla4xxx_srb_compl);
398afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
399afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
400afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case ET_CONTINUE:
401afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/* Just throw away the continuation entries */
402afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			DEBUG2(printk("scsi%ld: %s: Continuation entry - "
403afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      "ignoring\n", ha->host_no, __func__));
404afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
405afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
406afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		default:
407afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/*
408afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * Invalid entry in response queue, reset RISC
409afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * firmware.
410afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 */
411afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			DEBUG2(printk("scsi%ld: %s: Invalid entry %x in "
412afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      "response queue \n", ha->host_no,
413afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      __func__,
414afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      sts_entry->hdr.entryType));
415afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			goto exit_prq_error;
416afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		}
417f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		((struct response *)sts_entry)->signature = RESPONSE_PROCESSED;
418f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		wmb();
419afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	}
420afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
421afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	/*
422f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	 * Tell ISP we're done with response(s). This also clears the interrupt.
423afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	 */
424f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ha->isp_ops->complete_iocb(ha);
425afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
426afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	return;
427afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
428afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajuluexit_prq_invalid_handle:
429afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	DEBUG2(printk("scsi%ld: %s: Invalid handle(srb)=%p type=%x IOCS=%x\n",
430afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		      ha->host_no, __func__, srb, sts_entry->hdr.entryType,
431afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		      sts_entry->completionStatus));
432afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
433afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajuluexit_prq_error:
434f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ha->isp_ops->complete_iocb(ha);
435afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	set_bit(DPC_RESET_HA, &ha->dpc_flags);
436afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu}
437afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
438afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu/**
439afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * qla4xxx_isr_decode_mailbox - decodes mailbox status
440afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * @ha: Pointer to host adapter structure.
441afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * @mailbox_status: Mailbox status.
442afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu *
443afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * This routine decodes the mailbox status during the ISR.
444afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * Hardware_lock locked upon entry. runs in interrupt context.
445afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu **/
446afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulustatic void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
447afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				       uint32_t mbox_status)
448afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu{
449afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	int i;
450f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
451afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
452afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	if ((mbox_status == MBOX_STS_BUSY) ||
453afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	    (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) ||
454afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	    (mbox_status >> 12 == MBOX_COMPLETION_STATUS)) {
455afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		ha->mbox_status[0] = mbox_status;
456afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
457afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		if (test_bit(AF_MBOX_COMMAND, &ha->flags)) {
458afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/*
459afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * Copy all mailbox registers to a temporary
460afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * location and set mailbox command done flag
461afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 */
462f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			for (i = 0; i < ha->mbox_status_count; i++)
463f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				ha->mbox_status[i] = is_qla8022(ha)
464f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				    ? readl(&ha->qla4_8xxx_reg->mailbox_out[i])
465f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				    : readl(&ha->reg->mailbox[i]);
466afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
467afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
468f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
469f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags))
470f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				complete(&ha->mbx_intr_comp);
471afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		}
472afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	} else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
473f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
474f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			mbox_sts[i] = is_qla8022(ha)
475f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			    ? readl(&ha->qla4_8xxx_reg->mailbox_out[i])
476f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			    : readl(&ha->reg->mailbox[i]);
477f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
478afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/* Immediately process the AENs that don't require much work.
479afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * Only queue the database_changed AENs */
480401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu		if (ha->aen_log.count < MAX_AEN_ENTRIES) {
481401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu			for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
482401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu				ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] =
483f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				    mbox_sts[i];
484401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu			ha->aen_log.count++;
485401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu		}
486afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		switch (mbox_status) {
487afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_SYSTEM_ERROR:
488afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/* Log Mailbox registers */
489f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			ql4_printk(KERN_INFO, ha, "%s: System Err\n", __func__);
490afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			if (ql4xdontresethba) {
491f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				DEBUG2(printk("scsi%ld: %s:Don't Reset HBA\n",
492f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				    ha->host_no, __func__));
493afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			} else {
494afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				set_bit(AF_GET_CRASH_RECORD, &ha->flags);
495afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				set_bit(DPC_RESET_HA, &ha->dpc_flags);
496afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			}
497afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
498afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
499afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_REQUEST_TRANSFER_ERROR:
500afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_RESPONSE_TRANSFER_ERROR:
501afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_NVRAM_INVALID:
502afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_IP_ADDRESS_CHANGED:
503afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_DHCP_LEASE_EXPIRED:
504afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			DEBUG2(printk("scsi%ld: AEN %04x, ERROR Status, "
505afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      "Reset HA\n", ha->host_no, mbox_status));
506afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			set_bit(DPC_RESET_HA, &ha->dpc_flags);
507afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
508afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
509afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_LINK_UP:
510afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			set_bit(AF_LINK_UP, &ha->flags);
511065aa1b4db63c7fa68a3e889510c4e63404a1ac7Vikas Chaudhary			if (test_bit(AF_INIT_DONE, &ha->flags))
512065aa1b4db63c7fa68a3e889510c4e63404a1ac7Vikas Chaudhary				set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
513065aa1b4db63c7fa68a3e889510c4e63404a1ac7Vikas Chaudhary
514f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			ql4_printk(KERN_INFO, ha, "%s: LINK UP\n", __func__);
515afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
516afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
517afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_LINK_DOWN:
518afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			clear_bit(AF_LINK_UP, &ha->flags);
519f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			if (test_bit(AF_INIT_DONE, &ha->flags))
520f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
521065aa1b4db63c7fa68a3e889510c4e63404a1ac7Vikas Chaudhary
522f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__);
523afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
524afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
525afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_HEARTBEAT:
526afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			ha->seconds_since_last_heartbeat = 0;
527afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
528afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
529afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_DHCP_LEASE_ACQUIRED:
530afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			DEBUG2(printk("scsi%ld: AEN %04x DHCP LEASE "
531afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      "ACQUIRED\n", ha->host_no, mbox_status));
532afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
533afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
534afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
535afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_PROTOCOL_STATISTIC_ALARM:
536afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_SCSI_COMMAND_PDU_REJECTED: /* Target
537afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu							   * mode
538afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu							   * only */
539afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_UNSOLICITED_PDU_RECEIVED:  /* Connection mode */
540afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR:
541afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_SUBNET_STATE_CHANGE:
542afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/* No action */
543afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			DEBUG2(printk("scsi%ld: AEN %04x\n", ha->host_no,
544afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      mbox_status));
545afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
546afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
547401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu		case MBOX_ASTS_IP_ADDR_STATE_CHANGED:
548f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			printk("scsi%ld: AEN %04x, mbox_sts[2]=%04x, "
549f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			    "mbox_sts[3]=%04x\n", ha->host_no, mbox_sts[0],
550f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			    mbox_sts[2], mbox_sts[3]);
551f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
552f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			/* mbox_sts[2] = Old ACB state
553f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			 * mbox_sts[3] = new ACB state */
554f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			if ((mbox_sts[3] == ACB_STATE_VALID) &&
555f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			    (mbox_sts[2] == ACB_STATE_TENTATIVE))
556401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu				set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
557f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) &&
558f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			    (mbox_sts[2] == ACB_STATE_VALID))
559401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu				set_bit(DPC_RESET_HA, &ha->dpc_flags);
560401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu			break;
561401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu
562afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_MAC_ADDRESS_CHANGED:
563afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_DNS:
564afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/* No action */
565afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x, "
566afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      "mbox_sts[1]=%04x, mbox_sts[2]=%04x\n",
567f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				      ha->host_no, mbox_sts[0],
568f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				      mbox_sts[1], mbox_sts[2]));
569afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
570afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
571afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_SELF_TEST_FAILED:
572afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_LOGIN_FAILED:
573afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/* No action */
574afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			DEBUG2(printk("scsi%ld: AEN %04x, mbox_sts[1]=%04x, "
575afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      "mbox_sts[2]=%04x, mbox_sts[3]=%04x\n",
576f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				      ha->host_no, mbox_sts[0], mbox_sts[1],
577f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				      mbox_sts[2], mbox_sts[3]));
578afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
579afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
580afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_DATABASE_CHANGED:
581afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/* Queue AEN information and process it in the DPC
582afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * routine */
583afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			if (ha->aen_q_count > 0) {
584afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
585afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				/* decrement available counter */
586afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				ha->aen_q_count--;
587afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
588f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
589afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					ha->aen_q[ha->aen_in].mbox_sts[i] =
590f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary					    mbox_sts[i];
591afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
592afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				/* print debug message */
593afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				DEBUG2(printk("scsi%ld: AEN[%d] %04x queued"
594f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				    " mb1:0x%x mb2:0x%x mb3:0x%x mb4:0x%x\n",
595f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				    ha->host_no, ha->aen_in, mbox_sts[0],
596f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				    mbox_sts[1], mbox_sts[2],  mbox_sts[3],
597f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				    mbox_sts[4]));
598f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
599401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu				/* advance pointer */
600401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu				ha->aen_in++;
601401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu				if (ha->aen_in == MAX_AEN_ENTRIES)
602401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu					ha->aen_in = 0;
603afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
604afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				/* The DPC routine will process the aen */
605afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				set_bit(DPC_AEN, &ha->dpc_flags);
606afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			} else {
607afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				DEBUG2(printk("scsi%ld: %s: aen %04x, queue "
608afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      "overflowed!  AEN LOST!!\n",
609afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      ha->host_no, __func__,
610f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary					      mbox_sts[0]));
611afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
612afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				DEBUG2(printk("scsi%ld: DUMP AEN QUEUE\n",
613afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      ha->host_no));
614afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
615afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				for (i = 0; i < MAX_AEN_ENTRIES; i++) {
616afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					DEBUG2(printk("AEN[%d] %04x %04x %04x "
617f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary						      "%04x\n", i, mbox_sts[0],
618f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary						      mbox_sts[1], mbox_sts[2],
619f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary						      mbox_sts[3]));
620afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				}
621afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			}
622afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
623afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
6246434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar		case MBOX_ASTS_TXSCVR_INSERTED:
6256434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar			DEBUG2(printk(KERN_WARNING
6266434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar			    "scsi%ld: AEN %04x Transceiver"
6276434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar			    " inserted\n",  ha->host_no, mbox_sts[0]));
6286434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar			break;
6296434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar
6306434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar		case MBOX_ASTS_TXSCVR_REMOVED:
6316434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar			DEBUG2(printk(KERN_WARNING
6326434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar			    "scsi%ld: AEN %04x Transceiver"
6336434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar			    " removed\n",  ha->host_no, mbox_sts[0]));
6346434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar			break;
6356434080b127088606e03d2ecfe5ffdd797e38d63Shyam Sundar
636afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		default:
637afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			DEBUG2(printk(KERN_WARNING
638afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      "scsi%ld: AEN %04x UNKNOWN\n",
639f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				      ha->host_no, mbox_sts[0]));
640afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
641afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		}
642afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	} else {
643afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		DEBUG2(printk("scsi%ld: Unknown mailbox status %08X\n",
644afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      ha->host_no, mbox_status));
645afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
646afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		ha->mbox_status[0] = mbox_status;
647afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	}
648afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu}
649afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
650afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu/**
651f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * qla4_8xxx_interrupt_service_routine - isr
652f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * @ha: pointer to host adapter structure.
653f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary *
654f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * This is the main interrupt service routine.
655f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * hardware_lock locked upon entry. runs in interrupt context.
656f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary **/
657f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyvoid qla4_8xxx_interrupt_service_routine(struct scsi_qla_host *ha,
658f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary    uint32_t intr_status)
659f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary{
660f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	/* Process response queue interrupt. */
661f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (intr_status & HSRX_RISC_IOCB_INT)
662f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		qla4xxx_process_response_queue(ha);
663f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
664f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	/* Process mailbox/asynch event interrupt.*/
665f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (intr_status & HSRX_RISC_MB_INT)
666f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		qla4xxx_isr_decode_mailbox(ha,
667f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    readl(&ha->qla4_8xxx_reg->mailbox_out[0]));
668f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
669f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	/* clear the interrupt */
670f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	writel(0, &ha->qla4_8xxx_reg->host_int);
671f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	readl(&ha->qla4_8xxx_reg->host_int);
672f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary}
673f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
674f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary/**
675afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * qla4xxx_interrupt_service_routine - isr
676afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * @ha: pointer to host adapter structure.
677afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu *
678afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * This is the main interrupt service routine.
679afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * hardware_lock locked upon entry. runs in interrupt context.
680afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu **/
681afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajuluvoid qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
682afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				       uint32_t intr_status)
683afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu{
684afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	/* Process response queue interrupt. */
685afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	if (intr_status & CSR_SCSI_COMPLETION_INTR)
686afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		qla4xxx_process_response_queue(ha);
687afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
688afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	/* Process mailbox/asynch event	 interrupt.*/
689afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	if (intr_status & CSR_SCSI_PROCESSOR_INTR) {
690afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		qla4xxx_isr_decode_mailbox(ha,
691afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					   readl(&ha->reg->mailbox[0]));
692afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
693afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/* Clear Mailbox Interrupt */
694afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		writel(set_rmask(CSR_SCSI_PROCESSOR_INTR),
695afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		       &ha->reg->ctrl_status);
696afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		readl(&ha->reg->ctrl_status);
697afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	}
698afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu}
699afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
700afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu/**
701f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * qla4_8xxx_spurious_interrupt - processes spurious interrupt
702f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * @ha: pointer to host adapter structure.
703f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * @reqs_count: .
704f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary *
705f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary **/
706f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharystatic void qla4_8xxx_spurious_interrupt(struct scsi_qla_host *ha,
707f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary    uint8_t reqs_count)
708f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary{
709f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (reqs_count)
710f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		return;
711f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
712f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	DEBUG2(ql4_printk(KERN_INFO, ha, "Spurious Interrupt\n"));
713f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (is_qla8022(ha)) {
714f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		writel(0, &ha->qla4_8xxx_reg->host_int);
715f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		if (test_bit(AF_INTx_ENABLED, &ha->flags))
716f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg,
717f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			    0xfbff);
718f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	}
719f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ha->spurious_int_count++;
720f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary}
721f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
722f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary/**
723afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * qla4xxx_intr_handler - hardware interrupt handler.
724afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * @irq: Unused
725afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * @dev_id: Pointer to host adapter structure
726afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu **/
7277d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsirqreturn_t qla4xxx_intr_handler(int irq, void *dev_id)
728afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu{
729afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	struct scsi_qla_host *ha;
730afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	uint32_t intr_status;
731afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	unsigned long flags = 0;
732afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	uint8_t reqs_count = 0;
733afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
734afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	ha = (struct scsi_qla_host *) dev_id;
735afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	if (!ha) {
736afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		DEBUG2(printk(KERN_INFO
737afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			      "qla4xxx: Interrupt with NULL host ptr\n"));
738afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		return IRQ_NONE;
739afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	}
740afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
741afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	spin_lock_irqsave(&ha->hardware_lock, flags);
742afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
743d915058f48745c0d5c4582566e5aa63867264f81David C Somayajulu	ha->isr_count++;
744afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	/*
745afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	 * Repeatedly service interrupts up to a maximum of
746afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	 * MAX_REQS_SERVICED_PER_INTR
747afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	 */
748afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	while (1) {
749afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/*
750afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 * Read interrupt status
751afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		 */
752f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		if (ha->isp_ops->rd_shdw_rsp_q_in(ha) !=
753afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		    ha->response_out)
754afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			intr_status = CSR_SCSI_COMPLETION_INTR;
755afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		else
756afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			intr_status = readl(&ha->reg->ctrl_status);
757afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
758afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		if ((intr_status &
759f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    (CSR_SCSI_RESET_INTR|CSR_FATAL_ERROR|INTR_PENDING)) == 0) {
760afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			if (reqs_count == 0)
761afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				ha->spurious_int_count++;
762afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
763afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		}
764afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
765afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		if (intr_status & CSR_FATAL_ERROR) {
766afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			DEBUG2(printk(KERN_INFO "scsi%ld: Fatal Error, "
767afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      "Status 0x%04x\n", ha->host_no,
768afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				      readl(isp_port_error_status (ha))));
769afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
770afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			/* Issue Soft Reset to clear this error condition.
771afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * This will prevent the RISC from repeatedly
772afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * interrupting the driver; thus, allowing the DPC to
773afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * get scheduled to continue error recovery.
774afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * NOTE: Disabling RISC interrupts does not work in
775afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * this case, as CSR_FATAL_ERROR overrides
776afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			 * CSR_SCSI_INTR_ENABLE */
777afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			if ((readl(&ha->reg->ctrl_status) &
778afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			     CSR_SCSI_RESET_INTR) == 0) {
779afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				writel(set_rmask(CSR_SOFT_RESET),
780afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				       &ha->reg->ctrl_status);
781afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				readl(&ha->reg->ctrl_status);
782afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			}
783afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
784afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			writel(set_rmask(CSR_FATAL_ERROR),
785afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			       &ha->reg->ctrl_status);
786afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			readl(&ha->reg->ctrl_status);
787afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
788afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			__qla4xxx_disable_intrs(ha);
789afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
790afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			set_bit(DPC_RESET_HA, &ha->dpc_flags);
791afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
792afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
793afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		} else if (intr_status & CSR_SCSI_RESET_INTR) {
794afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			clear_bit(AF_ONLINE, &ha->flags);
795afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			__qla4xxx_disable_intrs(ha);
796afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
797afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			writel(set_rmask(CSR_SCSI_RESET_INTR),
798afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			       &ha->reg->ctrl_status);
799afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			readl(&ha->reg->ctrl_status);
800afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
801f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			if (!test_bit(AF_HBA_GOING_AWAY, &ha->flags))
802477ffb9d8732f30e7ab2d20f6ed0c22bad37a4a5David C Somayajulu				set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
803afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
804afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
805afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		} else if (intr_status & INTR_PENDING) {
806f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			ha->isp_ops->interrupt_service_routine(ha, intr_status);
807afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			ha->total_io_count++;
808afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
809afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				break;
810f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		}
811f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	}
812f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
813f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	spin_unlock_irqrestore(&ha->hardware_lock, flags);
814f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
815f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	return IRQ_HANDLED;
816f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary}
817f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
818f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary/**
819f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * qla4_8xxx_intr_handler - hardware interrupt handler.
820f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * @irq: Unused
821f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * @dev_id: Pointer to host adapter structure
822f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary **/
823f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyirqreturn_t qla4_8xxx_intr_handler(int irq, void *dev_id)
824f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary{
825f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	struct scsi_qla_host *ha = dev_id;
826f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	uint32_t intr_status;
827f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	uint32_t status;
828f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	unsigned long flags = 0;
829f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	uint8_t reqs_count = 0;
830f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
8312232be0d5707cd331b92027c0fd7ea5e843c2121Lalit Chandivade	if (unlikely(pci_channel_offline(ha->pdev)))
8322232be0d5707cd331b92027c0fd7ea5e843c2121Lalit Chandivade		return IRQ_HANDLED;
8332232be0d5707cd331b92027c0fd7ea5e843c2121Lalit Chandivade
834f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ha->isr_count++;
835f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	status = qla4_8xxx_rd_32(ha, ISR_INT_VECTOR);
836f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (!(status & ha->nx_legacy_intr.int_vec_bit))
837f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		return IRQ_NONE;
838f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
839f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	status = qla4_8xxx_rd_32(ha, ISR_INT_STATE_REG);
840f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (!ISR_IS_LEGACY_INTR_TRIGGERED(status)) {
841f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		DEBUG2(ql4_printk(KERN_INFO, ha,
842f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    "%s legacy Int not triggered\n", __func__));
843f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		return IRQ_NONE;
844f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	}
845f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
846f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	/* clear the interrupt */
847f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff);
848f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
849f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	/* read twice to ensure write is flushed */
850f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	qla4_8xxx_rd_32(ha, ISR_INT_VECTOR);
851f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	qla4_8xxx_rd_32(ha, ISR_INT_VECTOR);
852f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
853f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	spin_lock_irqsave(&ha->hardware_lock, flags);
854f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	while (1) {
855f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		if (!(readl(&ha->qla4_8xxx_reg->host_int) &
856f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    ISRX_82XX_RISC_INT)) {
857f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			qla4_8xxx_spurious_interrupt(ha, reqs_count);
858f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			break;
859f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		}
860f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		intr_status =  readl(&ha->qla4_8xxx_reg->host_status);
861f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		if ((intr_status &
862f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    (HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0)  {
863f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			qla4_8xxx_spurious_interrupt(ha, reqs_count);
864f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			break;
865f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		}
866f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
867f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		ha->isp_ops->interrupt_service_routine(ha, intr_status);
868f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
869f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		/* Enable Interrupt */
870f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff);
871afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
872f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
873f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			break;
874f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	}
875f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
876f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	spin_unlock_irqrestore(&ha->hardware_lock, flags);
877f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	return IRQ_HANDLED;
878f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary}
879f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
880f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyirqreturn_t
881f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyqla4_8xxx_msi_handler(int irq, void *dev_id)
882f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary{
883f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	struct scsi_qla_host *ha;
884f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
885f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ha = (struct scsi_qla_host *) dev_id;
886f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (!ha) {
887f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		DEBUG2(printk(KERN_INFO
888f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    "qla4xxx: MSIX: Interrupt with NULL host ptr\n"));
889f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		return IRQ_NONE;
890f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	}
891f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
892f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ha->isr_count++;
893f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	/* clear the interrupt */
894f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff);
895f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
896f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	/* read twice to ensure write is flushed */
897f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	qla4_8xxx_rd_32(ha, ISR_INT_VECTOR);
898f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	qla4_8xxx_rd_32(ha, ISR_INT_VECTOR);
899f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
900f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	return qla4_8xxx_default_intr_handler(irq, dev_id);
901f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary}
902f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
903f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary/**
904f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * qla4_8xxx_default_intr_handler - hardware interrupt handler.
905f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * @irq: Unused
906f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * @dev_id: Pointer to host adapter structure
907f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary *
908f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * This interrupt handler is called directly for MSI-X, and
909f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary * called indirectly for MSI.
910f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary **/
911f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyirqreturn_t
912f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyqla4_8xxx_default_intr_handler(int irq, void *dev_id)
913f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary{
914f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	struct scsi_qla_host *ha = dev_id;
915f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	unsigned long   flags;
916f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	uint32_t intr_status;
917f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	uint8_t reqs_count = 0;
918f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
919f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	spin_lock_irqsave(&ha->hardware_lock, flags);
920f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	while (1) {
921f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		if (!(readl(&ha->qla4_8xxx_reg->host_int) &
922f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    ISRX_82XX_RISC_INT)) {
923f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			qla4_8xxx_spurious_interrupt(ha, reqs_count);
924f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			break;
925f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		}
926f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
927f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		intr_status =  readl(&ha->qla4_8xxx_reg->host_status);
928f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		if ((intr_status &
929f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    (HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) {
930f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			qla4_8xxx_spurious_interrupt(ha, reqs_count);
931f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			break;
932afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		}
933f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
934f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		ha->isp_ops->interrupt_service_routine(ha, intr_status);
935f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
936f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
937f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			break;
938afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	}
939afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
940f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ha->isr_count++;
941afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	spin_unlock_irqrestore(&ha->hardware_lock, flags);
942f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	return IRQ_HANDLED;
943f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary}
944afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
945f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyirqreturn_t
946f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyqla4_8xxx_msix_rsp_q(int irq, void *dev_id)
947f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary{
948f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	struct scsi_qla_host *ha = dev_id;
949f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	unsigned long flags;
950f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
951f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	spin_lock_irqsave(&ha->hardware_lock, flags);
952f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	qla4xxx_process_response_queue(ha);
953f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	writel(0, &ha->qla4_8xxx_reg->host_int);
954f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	spin_unlock_irqrestore(&ha->hardware_lock, flags);
955f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
956f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ha->isr_count++;
957afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	return IRQ_HANDLED;
958afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu}
959afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
960afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu/**
961afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * qla4xxx_process_aen - processes AENs generated by firmware
962afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * @ha: pointer to host adapter structure.
963afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * @process_aen: type of AENs to process
964afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu *
965afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * Processes specific types of Asynchronous Events generated by firmware.
966afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu * The type of AENs to process is specified by process_aen and can be
967afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu *	PROCESS_ALL_AENS	 0
968afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu *	FLUSH_DDB_CHANGED_AENS	 1
969afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu *	RELOGIN_DDB_CHANGED_AENS 2
970afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu **/
971afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajuluvoid qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
972afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu{
973afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
974afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	struct aen *aen;
975afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	int i;
976afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	unsigned long flags;
977afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
978afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	spin_lock_irqsave(&ha->hardware_lock, flags);
979afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	while (ha->aen_out != ha->aen_in) {
980afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		aen = &ha->aen_q[ha->aen_out];
981afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		/* copy aen information to local structure */
982afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
983afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			mbox_sts[i] = aen->mbox_sts[i];
984afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
985401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu		ha->aen_q_count++;
986401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu		ha->aen_out++;
987401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu
988401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu		if (ha->aen_out == MAX_AEN_ENTRIES)
989401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu			ha->aen_out = 0;
990401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu
991afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		spin_unlock_irqrestore(&ha->hardware_lock, flags);
992afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
993401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu		DEBUG2(printk("qla4xxx(%ld): AEN[%d]=0x%08x, mbx1=0x%08x mbx2=0x%08x"
994401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu			" mbx3=0x%08x mbx4=0x%08x\n", ha->host_no,
995401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu			(ha->aen_out ? (ha->aen_out-1): (MAX_AEN_ENTRIES-1)),
996401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu			mbox_sts[0], mbox_sts[1], mbox_sts[2],
997401425b1ea005b39dcc544bffea833f338ba84f6David C Somayajulu			mbox_sts[3], mbox_sts[4]));
998afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
999afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		switch (mbox_sts[0]) {
1000afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		case MBOX_ASTS_DATABASE_CHANGED:
1001afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			if (process_aen == FLUSH_DDB_CHANGED_AENS) {
1002afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				DEBUG2(printk("scsi%ld: AEN[%d] %04x, index "
1003afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      "[%d] state=%04x FLUSHED!\n",
1004afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      ha->host_no, ha->aen_out,
1005afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      mbox_sts[0], mbox_sts[2],
1006afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      mbox_sts[3]));
1007afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				break;
1008afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			} else if (process_aen == RELOGIN_DDB_CHANGED_AENS) {
1009afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				/* for use during init time, we only want to
1010afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				 * relogin non-active ddbs */
1011afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				struct ddb_entry *ddb_entry;
1012afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
1013afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				ddb_entry =
1014afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					/* FIXME: name length? */
1015afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					qla4xxx_lookup_ddb_by_fw_index(ha,
1016afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu								       mbox_sts[2]);
1017afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				if (!ddb_entry)
1018afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					break;
1019afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
1020afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				ddb_entry->dev_scan_wait_to_complete_relogin =
1021afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					0;
1022afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				ddb_entry->dev_scan_wait_to_start_relogin =
1023afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					jiffies +
1024afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					((ddb_entry->default_time2wait +
1025afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					  4) * HZ);
1026afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
1027f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary				DEBUG2(printk("scsi%ld: ddb [%d] initate"
1028afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      " RELOGIN after %d seconds\n",
1029afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      ha->host_no,
1030afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      ddb_entry->fw_ddb_index,
1031afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      ddb_entry->default_time2wait +
1032afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu					      4));
1033afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				break;
1034afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			}
1035afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
1036afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			if (mbox_sts[1] == 0) {	/* Global DB change. */
1037afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				qla4xxx_reinitialize_ddb_list(ha);
1038afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			} else if (mbox_sts[1] == 1) {	/* Specific device. */
1039afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu				qla4xxx_process_ddb_changed(ha, mbox_sts[2],
1040821d6e5413481a57bbe1c2722dbe1fee4ff675c4Vikas Chaudhary						mbox_sts[3], mbox_sts[4]);
1041afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			}
1042afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu			break;
1043afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		}
1044afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu		spin_lock_irqsave(&ha->hardware_lock, flags);
1045afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	}
1046afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu	spin_unlock_irqrestore(&ha->hardware_lock, flags);
1047afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu}
1048afaf5a2d341d33b66b47c2716a263ce593460a08David Somayajulu
1049f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyint qla4xxx_request_irqs(struct scsi_qla_host *ha)
1050f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary{
1051f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	int ret;
1052f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
1053f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (!is_qla8022(ha))
1054f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		goto try_intx;
1055f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
1056f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (ql4xenablemsix == 2)
1057f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		goto try_msi;
1058f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
1059f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (ql4xenablemsix == 0 || ql4xenablemsix != 1)
1060f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		goto try_intx;
1061f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
1062f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	/* Trying MSI-X */
1063f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ret = qla4_8xxx_enable_msix(ha);
1064f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (!ret) {
1065f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		DEBUG2(ql4_printk(KERN_INFO, ha,
1066f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    "MSI-X: Enabled (0x%X).\n", ha->revision_id));
1067f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		goto irq_attached;
1068f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	}
1069f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
1070f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ql4_printk(KERN_WARNING, ha,
1071f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	    "MSI-X: Falling back-to MSI mode -- %d.\n", ret);
1072f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
1073f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharytry_msi:
1074f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	/* Trying MSI */
1075f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ret = pci_enable_msi(ha->pdev);
1076f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (!ret) {
1077f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		ret = request_irq(ha->pdev->irq, qla4_8xxx_msi_handler,
1078f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha);
1079f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		if (!ret) {
1080f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			DEBUG2(ql4_printk(KERN_INFO, ha, "MSI: Enabled.\n"));
1081f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			set_bit(AF_MSI_ENABLED, &ha->flags);
1082f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			goto irq_attached;
1083f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		} else {
1084f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			ql4_printk(KERN_WARNING, ha,
1085f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			    "MSI: Failed to reserve interrupt %d "
1086f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			    "already in use.\n", ha->pdev->irq);
1087f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary			pci_disable_msi(ha->pdev);
1088f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		}
1089f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	}
1090f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ql4_printk(KERN_WARNING, ha,
1091f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	    "MSI: Falling back-to INTx mode -- %d.\n", ret);
1092f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
1093f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharytry_intx:
1094f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	/* Trying INTx */
1095f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
1096f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	    IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha);
1097f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (!ret) {
1098f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		DEBUG2(ql4_printk(KERN_INFO, ha, "INTx: Enabled.\n"));
1099f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		set_bit(AF_INTx_ENABLED, &ha->flags);
1100f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		goto irq_attached;
1101f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
1102f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	} else {
1103f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		ql4_printk(KERN_WARNING, ha,
1104f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    "INTx: Failed to reserve interrupt %d already in"
1105f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		    " use.\n", ha->pdev->irq);
1106f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		return ret;
1107f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	}
1108f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
1109f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyirq_attached:
1110f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	set_bit(AF_IRQ_ATTACHED, &ha->flags);
1111f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ha->host->irq = ha->pdev->irq;
1112f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	ql4_printk(KERN_INFO, ha, "%s: irq %d attached\n",
1113f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	    __func__, ha->pdev->irq);
1114f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	return ret;
1115f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary}
1116f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary
1117f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudharyvoid qla4xxx_free_irqs(struct scsi_qla_host *ha)
1118f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary{
1119f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	if (test_bit(AF_MSIX_ENABLED, &ha->flags))
1120f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		qla4_8xxx_disable_msix(ha);
1121f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	else if (test_and_clear_bit(AF_MSI_ENABLED, &ha->flags)) {
1122f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		free_irq(ha->pdev->irq, ha);
1123f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		pci_disable_msi(ha->pdev);
1124f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary	} else if (test_and_clear_bit(AF_INTx_ENABLED, &ha->flags))
1125f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary		free_irq(ha->pdev->irq, ha);
1126f4f5df23bf72208d0c2f1d8be629839924c2f4c2Vikas Chaudhary}
1127