PageRenderTime 89ms CodeModel.GetById 12ms app.highlight 66ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/scsi/qla4xxx/ql4_isr.c

http://github.com/mirrors/linux
C | 1622 lines | 1162 code | 226 blank | 234 comment | 218 complexity | cece5415a89c1a0202b44e3f7879d2a2 MD5 | raw file
   1/*
   2 * QLogic iSCSI HBA Driver
   3 * Copyright (c)  2003-2013 QLogic Corporation
   4 *
   5 * See LICENSE.qla4xxx for copyright and licensing details.
   6 */
   7
   8#include "ql4_def.h"
   9#include "ql4_glbl.h"
  10#include "ql4_dbg.h"
  11#include "ql4_inline.h"
  12
  13/**
  14 * qla4xxx_copy_sense - copy sense data	into cmd sense buffer
  15 * @ha: Pointer to host adapter structure.
  16 * @sts_entry: Pointer to status entry structure.
  17 * @srb: Pointer to srb structure.
  18 **/
  19static void qla4xxx_copy_sense(struct scsi_qla_host *ha,
  20                               struct status_entry *sts_entry,
  21                               struct srb *srb)
  22{
  23	struct scsi_cmnd *cmd = srb->cmd;
  24	uint16_t sense_len;
  25
  26	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
  27	sense_len = le16_to_cpu(sts_entry->senseDataByteCnt);
  28	if (sense_len == 0) {
  29		DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d:%llu: %s:"
  30				  " sense len 0\n", ha->host_no,
  31				  cmd->device->channel, cmd->device->id,
  32				  cmd->device->lun, __func__));
  33		ha->status_srb = NULL;
  34		return;
  35	}
  36	/* Save total available sense length,
  37	 * not to exceed cmd's sense buffer size */
  38	sense_len = min_t(uint16_t, sense_len, SCSI_SENSE_BUFFERSIZE);
  39	srb->req_sense_ptr = cmd->sense_buffer;
  40	srb->req_sense_len = sense_len;
  41
  42	/* Copy sense from sts_entry pkt */
  43	sense_len = min_t(uint16_t, sense_len, IOCB_MAX_SENSEDATA_LEN);
  44	memcpy(cmd->sense_buffer, sts_entry->senseData, sense_len);
  45
  46	DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: %s: sense key = %x, "
  47		"ASL= %02x, ASC/ASCQ = %02x/%02x\n", ha->host_no,
  48		cmd->device->channel, cmd->device->id,
  49		cmd->device->lun, __func__,
  50		sts_entry->senseData[2] & 0x0f,
  51		sts_entry->senseData[7],
  52		sts_entry->senseData[12],
  53		sts_entry->senseData[13]));
  54
  55	DEBUG5(qla4xxx_dump_buffer(cmd->sense_buffer, sense_len));
  56	srb->flags |= SRB_GOT_SENSE;
  57
  58	/* Update srb, in case a sts_cont pkt follows */
  59	srb->req_sense_ptr += sense_len;
  60	srb->req_sense_len -= sense_len;
  61	if (srb->req_sense_len != 0)
  62		ha->status_srb = srb;
  63	else
  64		ha->status_srb = NULL;
  65}
  66
  67/**
  68 * qla4xxx_status_cont_entry - Process a Status Continuations entry.
  69 * @ha: SCSI driver HA context
  70 * @sts_cont: Entry pointer
  71 *
  72 * Extended sense data.
  73 */
  74static void
  75qla4xxx_status_cont_entry(struct scsi_qla_host *ha,
  76			  struct status_cont_entry *sts_cont)
  77{
  78	struct srb *srb = ha->status_srb;
  79	struct scsi_cmnd *cmd;
  80	uint16_t sense_len;
  81
  82	if (srb == NULL)
  83		return;
  84
  85	cmd = srb->cmd;
  86	if (cmd == NULL) {
  87		DEBUG2(printk(KERN_INFO "scsi%ld: %s: Cmd already returned "
  88			"back to OS srb=%p srb->state:%d\n", ha->host_no,
  89			__func__, srb, srb->state));
  90		ha->status_srb = NULL;
  91		return;
  92	}
  93
  94	/* Copy sense data. */
  95	sense_len = min_t(uint16_t, srb->req_sense_len,
  96			  IOCB_MAX_EXT_SENSEDATA_LEN);
  97	memcpy(srb->req_sense_ptr, sts_cont->ext_sense_data, sense_len);
  98	DEBUG5(qla4xxx_dump_buffer(srb->req_sense_ptr, sense_len));
  99
 100	srb->req_sense_ptr += sense_len;
 101	srb->req_sense_len -= sense_len;
 102
 103	/* Place command on done queue. */
 104	if (srb->req_sense_len == 0) {
 105		kref_put(&srb->srb_ref, qla4xxx_srb_compl);
 106		ha->status_srb = NULL;
 107	}
 108}
 109
 110/**
 111 * qla4xxx_status_entry - processes status IOCBs
 112 * @ha: Pointer to host adapter structure.
 113 * @sts_entry: Pointer to status entry structure.
 114 **/
 115static void qla4xxx_status_entry(struct scsi_qla_host *ha,
 116				 struct status_entry *sts_entry)
 117{
 118	uint8_t scsi_status;
 119	struct scsi_cmnd *cmd;
 120	struct srb *srb;
 121	struct ddb_entry *ddb_entry;
 122	uint32_t residual;
 123
 124	srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle));
 125	if (!srb) {
 126		ql4_printk(KERN_WARNING, ha, "%s invalid status entry: "
 127			   "handle=0x%0x, srb=%p\n", __func__,
 128			   sts_entry->handle, srb);
 129		if (is_qla80XX(ha))
 130			set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
 131		else
 132			set_bit(DPC_RESET_HA, &ha->dpc_flags);
 133		return;
 134	}
 135
 136	cmd = srb->cmd;
 137	if (cmd == NULL) {
 138		DEBUG2(printk("scsi%ld: %s: Command already returned back to "
 139			      "OS pkt->handle=%d srb=%p srb->state:%d\n",
 140			      ha->host_no, __func__, sts_entry->handle,
 141			      srb, srb->state));
 142		ql4_printk(KERN_WARNING, ha, "Command is NULL:"
 143		    " already returned to OS (srb=%p)\n", srb);
 144		return;
 145	}
 146
 147	ddb_entry = srb->ddb;
 148	if (ddb_entry == NULL) {
 149		cmd->result = DID_NO_CONNECT << 16;
 150		goto status_entry_exit;
 151	}
 152
 153	residual = le32_to_cpu(sts_entry->residualByteCnt);
 154
 155	/* Translate ISP error to a Linux SCSI error. */
 156	scsi_status = sts_entry->scsiStatus;
 157	switch (sts_entry->completionStatus) {
 158	case SCS_COMPLETE:
 159
 160		if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) {
 161			cmd->result = DID_ERROR << 16;
 162			break;
 163		}
 164
 165		if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) {
 166			scsi_set_resid(cmd, residual);
 167			if (!scsi_status && ((scsi_bufflen(cmd) - residual) <
 168				cmd->underflow)) {
 169
 170				cmd->result = DID_ERROR << 16;
 171
 172				DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: "
 173					"Mid-layer Data underrun0, "
 174					"xferlen = 0x%x, "
 175					"residual = 0x%x\n", ha->host_no,
 176					cmd->device->channel,
 177					cmd->device->id,
 178					cmd->device->lun, __func__,
 179					scsi_bufflen(cmd), residual));
 180				break;
 181			}
 182		}
 183
 184		cmd->result = DID_OK << 16 | scsi_status;
 185
 186		if (scsi_status != SCSI_CHECK_CONDITION)
 187			break;
 188
 189		/* Copy Sense Data into sense buffer. */
 190		qla4xxx_copy_sense(ha, sts_entry, srb);
 191		break;
 192
 193	case SCS_INCOMPLETE:
 194		/* Always set the status to DID_ERROR, since
 195		 * all conditions result in that status anyway */
 196		cmd->result = DID_ERROR << 16;
 197		break;
 198
 199	case SCS_RESET_OCCURRED:
 200		DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: Device RESET occurred\n",
 201			      ha->host_no, cmd->device->channel,
 202			      cmd->device->id, cmd->device->lun, __func__));
 203
 204		cmd->result = DID_RESET << 16;
 205		break;
 206
 207	case SCS_ABORTED:
 208		DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: Abort occurred\n",
 209			      ha->host_no, cmd->device->channel,
 210			      cmd->device->id, cmd->device->lun, __func__));
 211
 212		cmd->result = DID_RESET << 16;
 213		break;
 214
 215	case SCS_TIMEOUT:
 216		DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: Timeout\n",
 217			      ha->host_no, cmd->device->channel,
 218			      cmd->device->id, cmd->device->lun));
 219
 220		cmd->result = DID_TRANSPORT_DISRUPTED << 16;
 221
 222		/*
 223		 * Mark device missing so that we won't continue to send
 224		 * I/O to this device.	We should get a ddb state change
 225		 * AEN soon.
 226		 */
 227		if (iscsi_is_session_online(ddb_entry->sess))
 228			qla4xxx_mark_device_missing(ddb_entry->sess);
 229		break;
 230
 231	case SCS_DATA_UNDERRUN:
 232	case SCS_DATA_OVERRUN:
 233		if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) ||
 234		     (sts_entry->completionStatus == SCS_DATA_OVERRUN)) {
 235			DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: " "Data overrun\n",
 236				      ha->host_no,
 237				      cmd->device->channel, cmd->device->id,
 238				      cmd->device->lun, __func__));
 239
 240			cmd->result = DID_ERROR << 16;
 241			break;
 242		}
 243
 244		scsi_set_resid(cmd, residual);
 245
 246		if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_UNDER) {
 247
 248			/* Both the firmware and target reported UNDERRUN:
 249			 *
 250			 * MID-LAYER UNDERFLOW case:
 251			 * Some kernels do not properly detect midlayer
 252			 * underflow, so we manually check it and return
 253			 * ERROR if the minimum required data was not
 254			 * received.
 255			 *
 256			 * ALL OTHER cases:
 257			 * Fall thru to check scsi_status
 258			 */
 259			if (!scsi_status && (scsi_bufflen(cmd) - residual) <
 260			    cmd->underflow) {
 261				DEBUG2(ql4_printk(KERN_INFO, ha,
 262						  "scsi%ld:%d:%d:%llu: %s: Mid-layer Data underrun, xferlen = 0x%x,residual = 0x%x\n",
 263						   ha->host_no,
 264						   cmd->device->channel,
 265						   cmd->device->id,
 266						   cmd->device->lun, __func__,
 267						   scsi_bufflen(cmd),
 268						   residual));
 269
 270				cmd->result = DID_ERROR << 16;
 271				break;
 272			}
 273
 274		} else if (scsi_status != SAM_STAT_TASK_SET_FULL &&
 275			   scsi_status != SAM_STAT_BUSY) {
 276
 277			/*
 278			 * The firmware reports UNDERRUN, but the target does
 279			 * not report it:
 280			 *
 281			 *   scsi_status     |    host_byte       device_byte
 282			 *                   |     (19:16)          (7:0)
 283			 *   =============   |    =========       ===========
 284			 *   TASK_SET_FULL   |    DID_OK          scsi_status
 285			 *   BUSY            |    DID_OK          scsi_status
 286			 *   ALL OTHERS      |    DID_ERROR       scsi_status
 287			 *
 288			 *   Note: If scsi_status is task set full or busy,
 289			 *   then this else if would fall thru to check the
 290			 *   scsi_status and return DID_OK.
 291			 */
 292
 293			DEBUG2(ql4_printk(KERN_INFO, ha,
 294					  "scsi%ld:%d:%d:%llu: %s: Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
 295					  ha->host_no,
 296					  cmd->device->channel,
 297					  cmd->device->id,
 298					  cmd->device->lun, __func__,
 299					  residual,
 300					  scsi_bufflen(cmd)));
 301
 302			cmd->result = DID_ERROR << 16 | scsi_status;
 303			goto check_scsi_status;
 304		}
 305
 306		cmd->result = DID_OK << 16 | scsi_status;
 307
 308check_scsi_status:
 309		if (scsi_status == SAM_STAT_CHECK_CONDITION)
 310			qla4xxx_copy_sense(ha, sts_entry, srb);
 311
 312		break;
 313
 314	case SCS_DEVICE_LOGGED_OUT:
 315	case SCS_DEVICE_UNAVAILABLE:
 316		DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: SCS_DEVICE "
 317		    "state: 0x%x\n", ha->host_no,
 318		    cmd->device->channel, cmd->device->id,
 319		    cmd->device->lun, sts_entry->completionStatus));
 320		/*
 321		 * Mark device missing so that we won't continue to
 322		 * send I/O to this device.  We should get a ddb
 323		 * state change AEN soon.
 324		 */
 325		if (iscsi_is_session_online(ddb_entry->sess))
 326			qla4xxx_mark_device_missing(ddb_entry->sess);
 327
 328		cmd->result = DID_TRANSPORT_DISRUPTED << 16;
 329		break;
 330
 331	case SCS_QUEUE_FULL:
 332		/*
 333		 * SCSI Mid-Layer handles device queue full
 334		 */
 335		cmd->result = DID_OK << 16 | sts_entry->scsiStatus;
 336		DEBUG2(printk("scsi%ld:%d:%llu: %s: QUEUE FULL detected "
 337			      "compl=%02x, scsi=%02x, state=%02x, iFlags=%02x,"
 338			      " iResp=%02x\n", ha->host_no, cmd->device->id,
 339			      cmd->device->lun, __func__,
 340			      sts_entry->completionStatus,
 341			      sts_entry->scsiStatus, sts_entry->state_flags,
 342			      sts_entry->iscsiFlags,
 343			      sts_entry->iscsiResponse));
 344		break;
 345
 346	default:
 347		cmd->result = DID_ERROR << 16;
 348		break;
 349	}
 350
 351status_entry_exit:
 352
 353	/* complete the request, if not waiting for status_continuation pkt */
 354	srb->cc_stat = sts_entry->completionStatus;
 355	if (ha->status_srb == NULL)
 356		kref_put(&srb->srb_ref, qla4xxx_srb_compl);
 357}
 358
 359/**
 360 * qla4xxx_passthru_status_entry - processes passthru status IOCBs (0x3C)
 361 * @ha: Pointer to host adapter structure.
 362 * @sts_entry: Pointer to status entry structure.
 363 **/
 364static void qla4xxx_passthru_status_entry(struct scsi_qla_host *ha,
 365					  struct passthru_status *sts_entry)
 366{
 367	struct iscsi_task *task;
 368	struct ddb_entry *ddb_entry;
 369	struct ql4_task_data *task_data;
 370	struct iscsi_cls_conn *cls_conn;
 371	struct iscsi_conn *conn;
 372	itt_t itt;
 373	uint32_t fw_ddb_index;
 374
 375	itt = sts_entry->handle;
 376	fw_ddb_index = le32_to_cpu(sts_entry->target);
 377
 378	ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
 379
 380	if (ddb_entry == NULL) {
 381		ql4_printk(KERN_ERR, ha, "%s: Invalid target index = 0x%x\n",
 382			   __func__, sts_entry->target);
 383		return;
 384	}
 385
 386	cls_conn = ddb_entry->conn;
 387	conn = cls_conn->dd_data;
 388	spin_lock(&conn->session->back_lock);
 389	task = iscsi_itt_to_task(conn, itt);
 390	spin_unlock(&conn->session->back_lock);
 391
 392	if (task == NULL) {
 393		ql4_printk(KERN_ERR, ha, "%s: Task is NULL\n", __func__);
 394		return;
 395	}
 396
 397	task_data = task->dd_data;
 398	memcpy(&task_data->sts, sts_entry, sizeof(struct passthru_status));
 399	ha->iocb_cnt -= task_data->iocb_req_cnt;
 400	queue_work(ha->task_wq, &task_data->task_work);
 401}
 402
 403static struct mrb *qla4xxx_del_mrb_from_active_array(struct scsi_qla_host *ha,
 404						     uint32_t index)
 405{
 406	struct mrb *mrb = NULL;
 407
 408	/* validate handle and remove from active array */
 409	if (index >= MAX_MRB)
 410		return mrb;
 411
 412	mrb = ha->active_mrb_array[index];
 413	ha->active_mrb_array[index] = NULL;
 414	if (!mrb)
 415		return mrb;
 416
 417	/* update counters */
 418	ha->iocb_cnt -= mrb->iocb_cnt;
 419
 420	return mrb;
 421}
 422
 423static void qla4xxx_mbox_status_entry(struct scsi_qla_host *ha,
 424				      struct mbox_status_iocb *mbox_sts_entry)
 425{
 426	struct mrb *mrb;
 427	uint32_t status;
 428	uint32_t data_size;
 429
 430	mrb = qla4xxx_del_mrb_from_active_array(ha,
 431					le32_to_cpu(mbox_sts_entry->handle));
 432
 433	if (mrb == NULL) {
 434		ql4_printk(KERN_WARNING, ha, "%s: mrb[%d] is null\n", __func__,
 435			   mbox_sts_entry->handle);
 436		return;
 437	}
 438
 439	switch (mrb->mbox_cmd) {
 440	case MBOX_CMD_PING:
 441		DEBUG2(ql4_printk(KERN_INFO, ha, "%s: mbox_cmd = 0x%x, "
 442				  "mbox_sts[0] = 0x%x, mbox_sts[6] = 0x%x\n",
 443				  __func__, mrb->mbox_cmd,
 444				  mbox_sts_entry->out_mbox[0],
 445				  mbox_sts_entry->out_mbox[6]));
 446
 447		if (mbox_sts_entry->out_mbox[0] == MBOX_STS_COMMAND_COMPLETE)
 448			status = ISCSI_PING_SUCCESS;
 449		else
 450			status = mbox_sts_entry->out_mbox[6];
 451
 452		data_size = sizeof(mbox_sts_entry->out_mbox);
 453
 454		qla4xxx_post_ping_evt_work(ha, status, mrb->pid, data_size,
 455					(uint8_t *) mbox_sts_entry->out_mbox);
 456		break;
 457
 458	default:
 459		DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: invalid mbox_cmd = "
 460				  "0x%x\n", __func__, mrb->mbox_cmd));
 461	}
 462
 463	kfree(mrb);
 464	return;
 465}
 466
 467/**
 468 * qla4xxx_process_response_queue - process response queue completions
 469 * @ha: Pointer to host adapter structure.
 470 *
 471 * This routine process response queue completions in interrupt context.
 472 * Hardware_lock locked upon entry
 473 **/
 474void qla4xxx_process_response_queue(struct scsi_qla_host *ha)
 475{
 476	uint32_t count = 0;
 477	struct srb *srb = NULL;
 478	struct status_entry *sts_entry;
 479
 480	/* Process all responses from response queue */
 481	while ((ha->response_ptr->signature != RESPONSE_PROCESSED)) {
 482		sts_entry = (struct status_entry *) ha->response_ptr;
 483		count++;
 484
 485		/* Advance pointers for next entry */
 486		if (ha->response_out == (RESPONSE_QUEUE_DEPTH - 1)) {
 487			ha->response_out = 0;
 488			ha->response_ptr = ha->response_ring;
 489		} else {
 490			ha->response_out++;
 491			ha->response_ptr++;
 492		}
 493
 494		/* process entry */
 495		switch (sts_entry->hdr.entryType) {
 496		case ET_STATUS:
 497			/* Common status */
 498			qla4xxx_status_entry(ha, sts_entry);
 499			break;
 500
 501		case ET_PASSTHRU_STATUS:
 502			if (sts_entry->hdr.systemDefined == SD_ISCSI_PDU)
 503				qla4xxx_passthru_status_entry(ha,
 504					(struct passthru_status *)sts_entry);
 505			else
 506				ql4_printk(KERN_ERR, ha,
 507					   "%s: Invalid status received\n",
 508					   __func__);
 509
 510			break;
 511
 512		case ET_STATUS_CONTINUATION:
 513			qla4xxx_status_cont_entry(ha,
 514				(struct status_cont_entry *) sts_entry);
 515			break;
 516
 517		case ET_COMMAND:
 518			/* ISP device queue is full. Command not
 519			 * accepted by ISP.  Queue command for
 520			 * later */
 521
 522			srb = qla4xxx_del_from_active_array(ha,
 523						    le32_to_cpu(sts_entry->
 524								handle));
 525			if (srb == NULL)
 526				goto exit_prq_invalid_handle;
 527
 528			DEBUG2(printk("scsi%ld: %s: FW device queue full, "
 529				      "srb %p\n", ha->host_no, __func__, srb));
 530
 531			/* ETRY normally by sending it back with
 532			 * DID_BUS_BUSY */
 533			srb->cmd->result = DID_BUS_BUSY << 16;
 534			kref_put(&srb->srb_ref, qla4xxx_srb_compl);
 535			break;
 536
 537		case ET_CONTINUE:
 538			/* Just throw away the continuation entries */
 539			DEBUG2(printk("scsi%ld: %s: Continuation entry - "
 540				      "ignoring\n", ha->host_no, __func__));
 541			break;
 542
 543		case ET_MBOX_STATUS:
 544			DEBUG2(ql4_printk(KERN_INFO, ha,
 545					  "%s: mbox status IOCB\n", __func__));
 546			qla4xxx_mbox_status_entry(ha,
 547					(struct mbox_status_iocb *)sts_entry);
 548			break;
 549
 550		default:
 551			/*
 552			 * Invalid entry in response queue, reset RISC
 553			 * firmware.
 554			 */
 555			DEBUG2(printk("scsi%ld: %s: Invalid entry %x in "
 556				      "response queue \n", ha->host_no,
 557				      __func__,
 558				      sts_entry->hdr.entryType));
 559			goto exit_prq_error;
 560		}
 561		((struct response *)sts_entry)->signature = RESPONSE_PROCESSED;
 562		wmb();
 563	}
 564
 565	/*
 566	 * Tell ISP we're done with response(s). This also clears the interrupt.
 567	 */
 568	ha->isp_ops->complete_iocb(ha);
 569
 570	return;
 571
 572exit_prq_invalid_handle:
 573	DEBUG2(printk("scsi%ld: %s: Invalid handle(srb)=%p type=%x IOCS=%x\n",
 574		      ha->host_no, __func__, srb, sts_entry->hdr.entryType,
 575		      sts_entry->completionStatus));
 576
 577exit_prq_error:
 578	ha->isp_ops->complete_iocb(ha);
 579	set_bit(DPC_RESET_HA, &ha->dpc_flags);
 580}
 581
 582/**
 583 * qla4_83xx_loopback_in_progress: Is loopback in progress?
 584 * @ha: Pointer to host adapter structure.
 585 * @ret: 1 = loopback in progress, 0 = loopback not in progress
 586 **/
 587static int qla4_83xx_loopback_in_progress(struct scsi_qla_host *ha)
 588{
 589	int rval = 1;
 590
 591	if (is_qla8032(ha) || is_qla8042(ha)) {
 592		if ((ha->idc_info.info2 & ENABLE_INTERNAL_LOOPBACK) ||
 593		    (ha->idc_info.info2 & ENABLE_EXTERNAL_LOOPBACK)) {
 594			DEBUG2(ql4_printk(KERN_INFO, ha,
 595					  "%s: Loopback diagnostics in progress\n",
 596					  __func__));
 597			rval = 1;
 598		} else {
 599			DEBUG2(ql4_printk(KERN_INFO, ha,
 600					  "%s: Loopback diagnostics not in progress\n",
 601					  __func__));
 602			rval = 0;
 603		}
 604	}
 605
 606	return rval;
 607}
 608
 609static void qla4xxx_update_ipaddr_state(struct scsi_qla_host *ha,
 610					uint32_t ipaddr_idx,
 611					uint32_t ipaddr_fw_state)
 612{
 613	uint8_t ipaddr_state;
 614	uint8_t ip_idx;
 615
 616	ip_idx = ipaddr_idx & 0xF;
 617	ipaddr_state = qla4xxx_set_ipaddr_state((uint8_t)ipaddr_fw_state);
 618
 619	switch (ip_idx) {
 620	case 0:
 621		ha->ip_config.ipv4_addr_state = ipaddr_state;
 622		break;
 623	case 1:
 624		ha->ip_config.ipv6_link_local_state = ipaddr_state;
 625		break;
 626	case 2:
 627		ha->ip_config.ipv6_addr0_state = ipaddr_state;
 628		break;
 629	case 3:
 630		ha->ip_config.ipv6_addr1_state = ipaddr_state;
 631		break;
 632	default:
 633		ql4_printk(KERN_INFO, ha, "%s: Invalid IPADDR index %d\n",
 634			   __func__, ip_idx);
 635	}
 636}
 637
 638static void qla4xxx_default_router_changed(struct scsi_qla_host *ha,
 639					   uint32_t *mbox_sts)
 640{
 641	memcpy(&ha->ip_config.ipv6_default_router_addr.s6_addr32[0],
 642	       &mbox_sts[2], sizeof(uint32_t));
 643	memcpy(&ha->ip_config.ipv6_default_router_addr.s6_addr32[1],
 644	       &mbox_sts[3], sizeof(uint32_t));
 645	memcpy(&ha->ip_config.ipv6_default_router_addr.s6_addr32[2],
 646	       &mbox_sts[4], sizeof(uint32_t));
 647	memcpy(&ha->ip_config.ipv6_default_router_addr.s6_addr32[3],
 648	       &mbox_sts[5], sizeof(uint32_t));
 649}
 650
 651/**
 652 * qla4xxx_isr_decode_mailbox - decodes mailbox status
 653 * @ha: Pointer to host adapter structure.
 654 * @mailbox_status: Mailbox status.
 655 *
 656 * This routine decodes the mailbox status during the ISR.
 657 * Hardware_lock locked upon entry. runs in interrupt context.
 658 **/
 659static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
 660				       uint32_t mbox_status)
 661{
 662	int i;
 663	uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
 664	__le32 __iomem *mailbox_out;
 665	uint32_t opcode = 0;
 666
 667	if (is_qla8032(ha) || is_qla8042(ha))
 668		mailbox_out = &ha->qla4_83xx_reg->mailbox_out[0];
 669	else if (is_qla8022(ha))
 670		mailbox_out = &ha->qla4_82xx_reg->mailbox_out[0];
 671	else
 672		mailbox_out = &ha->reg->mailbox[0];
 673
 674	if ((mbox_status == MBOX_STS_BUSY) ||
 675	    (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) ||
 676	    (mbox_status >> 12 == MBOX_COMPLETION_STATUS)) {
 677		ha->mbox_status[0] = mbox_status;
 678
 679		if (test_bit(AF_MBOX_COMMAND, &ha->flags)) {
 680			/*
 681			 * Copy all mailbox registers to a temporary
 682			 * location and set mailbox command done flag
 683			 */
 684			for (i = 0; i < ha->mbox_status_count; i++)
 685				ha->mbox_status[i] = readl(&mailbox_out[i]);
 686
 687			set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
 688
 689			if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags))
 690				complete(&ha->mbx_intr_comp);
 691		}
 692	} else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
 693		for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
 694			mbox_sts[i] = readl(&mailbox_out[i]);
 695
 696		/* Immediately process the AENs that don't require much work.
 697		 * Only queue the database_changed AENs */
 698		if (ha->aen_log.count < MAX_AEN_ENTRIES) {
 699			for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
 700				ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] =
 701				    mbox_sts[i];
 702			ha->aen_log.count++;
 703		}
 704		switch (mbox_status) {
 705		case MBOX_ASTS_SYSTEM_ERROR:
 706			/* Log Mailbox registers */
 707			ql4_printk(KERN_INFO, ha, "%s: System Err\n", __func__);
 708			qla4xxx_dump_registers(ha);
 709
 710			if ((is_qla8022(ha) && ql4xdontresethba) ||
 711			    ((is_qla8032(ha) || is_qla8042(ha)) &&
 712			     qla4_83xx_idc_dontreset(ha))) {
 713				DEBUG2(printk("scsi%ld: %s:Don't Reset HBA\n",
 714				    ha->host_no, __func__));
 715			} else {
 716				set_bit(AF_GET_CRASH_RECORD, &ha->flags);
 717				set_bit(DPC_RESET_HA, &ha->dpc_flags);
 718			}
 719			break;
 720
 721		case MBOX_ASTS_REQUEST_TRANSFER_ERROR:
 722		case MBOX_ASTS_RESPONSE_TRANSFER_ERROR:
 723		case MBOX_ASTS_NVRAM_INVALID:
 724		case MBOX_ASTS_IP_ADDRESS_CHANGED:
 725		case MBOX_ASTS_DHCP_LEASE_EXPIRED:
 726			DEBUG2(printk("scsi%ld: AEN %04x, ERROR Status, "
 727				      "Reset HA\n", ha->host_no, mbox_status));
 728			if (is_qla80XX(ha))
 729				set_bit(DPC_RESET_HA_FW_CONTEXT,
 730					&ha->dpc_flags);
 731			else
 732				set_bit(DPC_RESET_HA, &ha->dpc_flags);
 733			break;
 734
 735		case MBOX_ASTS_LINK_UP:
 736			set_bit(AF_LINK_UP, &ha->flags);
 737			if (test_bit(AF_INIT_DONE, &ha->flags))
 738				set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
 739
 740			ql4_printk(KERN_INFO, ha, "%s: LINK UP\n", __func__);
 741			qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKUP,
 742					      sizeof(mbox_sts),
 743					      (uint8_t *) mbox_sts);
 744
 745			if ((is_qla8032(ha) || is_qla8042(ha)) &&
 746			    ha->notify_link_up_comp)
 747				complete(&ha->link_up_comp);
 748
 749			break;
 750
 751		case MBOX_ASTS_LINK_DOWN:
 752			clear_bit(AF_LINK_UP, &ha->flags);
 753			if (test_bit(AF_INIT_DONE, &ha->flags)) {
 754				set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
 755				qla4xxx_wake_dpc(ha);
 756			}
 757
 758			ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__);
 759			qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKDOWN,
 760					      sizeof(mbox_sts),
 761					      (uint8_t *) mbox_sts);
 762			break;
 763
 764		case MBOX_ASTS_HEARTBEAT:
 765			ha->seconds_since_last_heartbeat = 0;
 766			break;
 767
 768		case MBOX_ASTS_DHCP_LEASE_ACQUIRED:
 769			DEBUG2(printk("scsi%ld: AEN %04x DHCP LEASE "
 770				      "ACQUIRED\n", ha->host_no, mbox_status));
 771			set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
 772			break;
 773
 774		case MBOX_ASTS_PROTOCOL_STATISTIC_ALARM:
 775		case MBOX_ASTS_SCSI_COMMAND_PDU_REJECTED: /* Target
 776							   * mode
 777							   * only */
 778		case MBOX_ASTS_UNSOLICITED_PDU_RECEIVED:  /* Connection mode */
 779		case MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR:
 780		case MBOX_ASTS_SUBNET_STATE_CHANGE:
 781		case MBOX_ASTS_DUPLICATE_IP:
 782			/* No action */
 783			DEBUG2(printk("scsi%ld: AEN %04x\n", ha->host_no,
 784				      mbox_status));
 785			break;
 786
 787		case MBOX_ASTS_IP_ADDR_STATE_CHANGED:
 788			printk("scsi%ld: AEN %04x, mbox_sts[2]=%04x, "
 789			    "mbox_sts[3]=%04x\n", ha->host_no, mbox_sts[0],
 790			    mbox_sts[2], mbox_sts[3]);
 791
 792			qla4xxx_update_ipaddr_state(ha, mbox_sts[5],
 793						    mbox_sts[3]);
 794			/* mbox_sts[2] = Old ACB state
 795			 * mbox_sts[3] = new ACB state */
 796			if ((mbox_sts[3] == IP_ADDRSTATE_PREFERRED) &&
 797			    ((mbox_sts[2] == IP_ADDRSTATE_TENTATIVE) ||
 798			     (mbox_sts[2] == IP_ADDRSTATE_ACQUIRING))) {
 799				set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
 800			} else if ((mbox_sts[3] == IP_ADDRSTATE_ACQUIRING) &&
 801				   (mbox_sts[2] == IP_ADDRSTATE_PREFERRED)) {
 802				if (is_qla80XX(ha))
 803					set_bit(DPC_RESET_HA_FW_CONTEXT,
 804						&ha->dpc_flags);
 805				else
 806					set_bit(DPC_RESET_HA, &ha->dpc_flags);
 807			} else if (mbox_sts[3] == IP_ADDRSTATE_DISABLING) {
 808				ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ACB in disabling state\n",
 809					   ha->host_no, __func__);
 810			} else if (mbox_sts[3] == IP_ADDRSTATE_UNCONFIGURED) {
 811				complete(&ha->disable_acb_comp);
 812				ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ACB state unconfigured\n",
 813					   ha->host_no, __func__);
 814			}
 815			break;
 816
 817		case MBOX_ASTS_IPV6_LINK_MTU_CHANGE:
 818		case MBOX_ASTS_IPV6_AUTO_PREFIX_IGNORED:
 819		case MBOX_ASTS_IPV6_ND_LOCAL_PREFIX_IGNORED:
 820			/* No action */
 821			DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: AEN %04x\n",
 822					  ha->host_no, mbox_status));
 823			break;
 824
 825		case MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD:
 826			DEBUG2(ql4_printk(KERN_INFO, ha,
 827					  "scsi%ld: AEN %04x, IPv6 ERROR, "
 828					  "mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3}=%08x, mbox_sts[4]=%08x mbox_sts[5]=%08x\n",
 829					  ha->host_no, mbox_sts[0], mbox_sts[1],
 830					  mbox_sts[2], mbox_sts[3], mbox_sts[4],
 831					  mbox_sts[5]));
 832			break;
 833
 834		case MBOX_ASTS_MAC_ADDRESS_CHANGED:
 835		case MBOX_ASTS_DNS:
 836			/* No action */
 837			DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x, "
 838				      "mbox_sts[1]=%04x, mbox_sts[2]=%04x\n",
 839				      ha->host_no, mbox_sts[0],
 840				      mbox_sts[1], mbox_sts[2]));
 841			break;
 842
 843		case MBOX_ASTS_SELF_TEST_FAILED:
 844		case MBOX_ASTS_LOGIN_FAILED:
 845			/* No action */
 846			DEBUG2(printk("scsi%ld: AEN %04x, mbox_sts[1]=%04x, "
 847				      "mbox_sts[2]=%04x, mbox_sts[3]=%04x\n",
 848				      ha->host_no, mbox_sts[0], mbox_sts[1],
 849				      mbox_sts[2], mbox_sts[3]));
 850			break;
 851
 852		case MBOX_ASTS_DATABASE_CHANGED:
 853			/* Queue AEN information and process it in the DPC
 854			 * routine */
 855			if (ha->aen_q_count > 0) {
 856
 857				/* decrement available counter */
 858				ha->aen_q_count--;
 859
 860				for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
 861					ha->aen_q[ha->aen_in].mbox_sts[i] =
 862					    mbox_sts[i];
 863
 864				/* print debug message */
 865				DEBUG2(printk("scsi%ld: AEN[%d] %04x queued "
 866					      "mb1:0x%x mb2:0x%x mb3:0x%x "
 867					      "mb4:0x%x mb5:0x%x\n",
 868					      ha->host_no, ha->aen_in,
 869					      mbox_sts[0], mbox_sts[1],
 870					      mbox_sts[2], mbox_sts[3],
 871					      mbox_sts[4], mbox_sts[5]));
 872
 873				/* advance pointer */
 874				ha->aen_in++;
 875				if (ha->aen_in == MAX_AEN_ENTRIES)
 876					ha->aen_in = 0;
 877
 878				/* The DPC routine will process the aen */
 879				set_bit(DPC_AEN, &ha->dpc_flags);
 880			} else {
 881				DEBUG2(printk("scsi%ld: %s: aen %04x, queue "
 882					      "overflowed!  AEN LOST!!\n",
 883					      ha->host_no, __func__,
 884					      mbox_sts[0]));
 885
 886				DEBUG2(printk("scsi%ld: DUMP AEN QUEUE\n",
 887					      ha->host_no));
 888
 889				for (i = 0; i < MAX_AEN_ENTRIES; i++) {
 890					DEBUG2(printk("AEN[%d] %04x %04x %04x "
 891						      "%04x\n", i, mbox_sts[0],
 892						      mbox_sts[1], mbox_sts[2],
 893						      mbox_sts[3]));
 894				}
 895			}
 896			break;
 897
 898		case MBOX_ASTS_TXSCVR_INSERTED:
 899			DEBUG2(printk(KERN_WARNING
 900			    "scsi%ld: AEN %04x Transceiver"
 901			    " inserted\n",  ha->host_no, mbox_sts[0]));
 902			break;
 903
 904		case MBOX_ASTS_TXSCVR_REMOVED:
 905			DEBUG2(printk(KERN_WARNING
 906			    "scsi%ld: AEN %04x Transceiver"
 907			    " removed\n",  ha->host_no, mbox_sts[0]));
 908			break;
 909
 910		case MBOX_ASTS_IDC_REQUEST_NOTIFICATION:
 911			if (is_qla8032(ha) || is_qla8042(ha)) {
 912				DEBUG2(ql4_printk(KERN_INFO, ha,
 913						  "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x\n",
 914						  ha->host_no, mbox_sts[0],
 915						  mbox_sts[1], mbox_sts[2],
 916						  mbox_sts[3], mbox_sts[4]));
 917				opcode = mbox_sts[1] >> 16;
 918				if ((opcode == MBOX_CMD_SET_PORT_CONFIG) ||
 919				    (opcode == MBOX_CMD_PORT_RESET)) {
 920					set_bit(DPC_POST_IDC_ACK,
 921						&ha->dpc_flags);
 922					ha->idc_info.request_desc = mbox_sts[1];
 923					ha->idc_info.info1 = mbox_sts[2];
 924					ha->idc_info.info2 = mbox_sts[3];
 925					ha->idc_info.info3 = mbox_sts[4];
 926					qla4xxx_wake_dpc(ha);
 927				}
 928			}
 929			break;
 930
 931		case MBOX_ASTS_IDC_COMPLETE:
 932			if (is_qla8032(ha) || is_qla8042(ha)) {
 933				DEBUG2(ql4_printk(KERN_INFO, ha,
 934						  "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x\n",
 935						  ha->host_no, mbox_sts[0],
 936						  mbox_sts[1], mbox_sts[2],
 937						  mbox_sts[3], mbox_sts[4]));
 938				DEBUG2(ql4_printk(KERN_INFO, ha,
 939						  "scsi:%ld: AEN %04x IDC Complete notification\n",
 940						  ha->host_no, mbox_sts[0]));
 941
 942				opcode = mbox_sts[1] >> 16;
 943				if (ha->notify_idc_comp)
 944					complete(&ha->idc_comp);
 945
 946				if ((opcode == MBOX_CMD_SET_PORT_CONFIG) ||
 947				    (opcode == MBOX_CMD_PORT_RESET))
 948					ha->idc_info.info2 = mbox_sts[3];
 949
 950				if (qla4_83xx_loopback_in_progress(ha)) {
 951					set_bit(AF_LOOPBACK, &ha->flags);
 952				} else {
 953					clear_bit(AF_LOOPBACK, &ha->flags);
 954					if (ha->saved_acb)
 955						set_bit(DPC_RESTORE_ACB,
 956							&ha->dpc_flags);
 957				}
 958				qla4xxx_wake_dpc(ha);
 959			}
 960			break;
 961
 962		case MBOX_ASTS_IPV6_DEFAULT_ROUTER_CHANGED:
 963			DEBUG2(ql4_printk(KERN_INFO, ha,
 964					  "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x mbox_sts[5]=%08x\n",
 965					  ha->host_no, mbox_sts[0], mbox_sts[1],
 966					  mbox_sts[2], mbox_sts[3], mbox_sts[4],
 967					  mbox_sts[5]));
 968			DEBUG2(ql4_printk(KERN_INFO, ha,
 969					  "scsi%ld: AEN %04x Received IPv6 default router changed notification\n",
 970					  ha->host_no, mbox_sts[0]));
 971			qla4xxx_default_router_changed(ha, mbox_sts);
 972			break;
 973
 974		case MBOX_ASTS_IDC_TIME_EXTEND_NOTIFICATION:
 975			DEBUG2(ql4_printk(KERN_INFO, ha,
 976					  "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x mbox_sts[5]=%08x\n",
 977					  ha->host_no, mbox_sts[0], mbox_sts[1],
 978					  mbox_sts[2], mbox_sts[3], mbox_sts[4],
 979					  mbox_sts[5]));
 980			DEBUG2(ql4_printk(KERN_INFO, ha,
 981					  "scsi%ld: AEN %04x Received IDC Extend Timeout notification\n",
 982					  ha->host_no, mbox_sts[0]));
 983			/* new IDC timeout */
 984			ha->idc_extend_tmo = mbox_sts[1];
 985			break;
 986
 987		case MBOX_ASTS_INITIALIZATION_FAILED:
 988			DEBUG2(ql4_printk(KERN_INFO, ha,
 989					  "scsi%ld: AEN %04x, mbox_sts[3]=%08x\n",
 990					  ha->host_no, mbox_sts[0],
 991					  mbox_sts[3]));
 992			break;
 993
 994		case MBOX_ASTS_SYSTEM_WARNING_EVENT:
 995			DEBUG2(ql4_printk(KERN_WARNING, ha,
 996					  "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x mbox_sts[5]=%08x\n",
 997					  ha->host_no, mbox_sts[0], mbox_sts[1],
 998					  mbox_sts[2], mbox_sts[3], mbox_sts[4],
 999					  mbox_sts[5]));
1000			break;
1001
1002		case MBOX_ASTS_DCBX_CONF_CHANGE:
1003			DEBUG2(ql4_printk(KERN_INFO, ha,
1004					  "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x mbox_sts[5]=%08x\n",
1005					  ha->host_no, mbox_sts[0], mbox_sts[1],
1006					  mbox_sts[2], mbox_sts[3], mbox_sts[4],
1007					  mbox_sts[5]));
1008			DEBUG2(ql4_printk(KERN_INFO, ha,
1009					  "scsi%ld: AEN %04x Received DCBX configuration changed notification\n",
1010					  ha->host_no, mbox_sts[0]));
1011			break;
1012
1013		default:
1014			DEBUG2(printk(KERN_WARNING
1015				      "scsi%ld: AEN %04x UNKNOWN\n",
1016				      ha->host_no, mbox_sts[0]));
1017			break;
1018		}
1019	} else {
1020		DEBUG2(printk("scsi%ld: Unknown mailbox status %08X\n",
1021			      ha->host_no, mbox_status));
1022
1023		ha->mbox_status[0] = mbox_status;
1024	}
1025}
1026
1027void qla4_83xx_interrupt_service_routine(struct scsi_qla_host *ha,
1028					 uint32_t intr_status)
1029{
1030	/* Process mailbox/asynch event interrupt.*/
1031	if (intr_status) {
1032		qla4xxx_isr_decode_mailbox(ha,
1033				readl(&ha->qla4_83xx_reg->mailbox_out[0]));
1034		/* clear the interrupt */
1035		writel(0, &ha->qla4_83xx_reg->risc_intr);
1036	} else {
1037		qla4xxx_process_response_queue(ha);
1038	}
1039
1040	/* clear the interrupt */
1041	writel(0, &ha->qla4_83xx_reg->mb_int_mask);
1042}
1043
1044/**
1045 * qla4_82xx_interrupt_service_routine - isr
1046 * @ha: pointer to host adapter structure.
1047 *
1048 * This is the main interrupt service routine.
1049 * hardware_lock locked upon entry. runs in interrupt context.
1050 **/
1051void qla4_82xx_interrupt_service_routine(struct scsi_qla_host *ha,
1052    uint32_t intr_status)
1053{
1054	/* Process response queue interrupt. */
1055	if ((intr_status & HSRX_RISC_IOCB_INT) &&
1056	    test_bit(AF_INIT_DONE, &ha->flags))
1057		qla4xxx_process_response_queue(ha);
1058
1059	/* Process mailbox/asynch event interrupt.*/
1060	if (intr_status & HSRX_RISC_MB_INT)
1061		qla4xxx_isr_decode_mailbox(ha,
1062		    readl(&ha->qla4_82xx_reg->mailbox_out[0]));
1063
1064	/* clear the interrupt */
1065	writel(0, &ha->qla4_82xx_reg->host_int);
1066	readl(&ha->qla4_82xx_reg->host_int);
1067}
1068
1069/**
1070 * qla4xxx_interrupt_service_routine - isr
1071 * @ha: pointer to host adapter structure.
1072 *
1073 * This is the main interrupt service routine.
1074 * hardware_lock locked upon entry. runs in interrupt context.
1075 **/
1076void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
1077				       uint32_t intr_status)
1078{
1079	/* Process response queue interrupt. */
1080	if (intr_status & CSR_SCSI_COMPLETION_INTR)
1081		qla4xxx_process_response_queue(ha);
1082
1083	/* Process mailbox/asynch event	 interrupt.*/
1084	if (intr_status & CSR_SCSI_PROCESSOR_INTR) {
1085		qla4xxx_isr_decode_mailbox(ha,
1086					   readl(&ha->reg->mailbox[0]));
1087
1088		/* Clear Mailbox Interrupt */
1089		writel(set_rmask(CSR_SCSI_PROCESSOR_INTR),
1090		       &ha->reg->ctrl_status);
1091		readl(&ha->reg->ctrl_status);
1092	}
1093}
1094
1095/**
1096 * qla4_82xx_spurious_interrupt - processes spurious interrupt
1097 * @ha: pointer to host adapter structure.
1098 * @reqs_count: .
1099 *
1100 **/
1101static void qla4_82xx_spurious_interrupt(struct scsi_qla_host *ha,
1102    uint8_t reqs_count)
1103{
1104	if (reqs_count)
1105		return;
1106
1107	DEBUG2(ql4_printk(KERN_INFO, ha, "Spurious Interrupt\n"));
1108	if (is_qla8022(ha)) {
1109		writel(0, &ha->qla4_82xx_reg->host_int);
1110		if (!ha->pdev->msi_enabled && !ha->pdev->msix_enabled)
1111			qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg,
1112			    0xfbff);
1113	}
1114	ha->spurious_int_count++;
1115}
1116
1117/**
1118 * qla4xxx_intr_handler - hardware interrupt handler.
1119 * @irq: Unused
1120 * @dev_id: Pointer to host adapter structure
1121 **/
1122irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id)
1123{
1124	struct scsi_qla_host *ha;
1125	uint32_t intr_status;
1126	unsigned long flags = 0;
1127	uint8_t reqs_count = 0;
1128
1129	ha = (struct scsi_qla_host *) dev_id;
1130	if (!ha) {
1131		DEBUG2(printk(KERN_INFO
1132			      "qla4xxx: Interrupt with NULL host ptr\n"));
1133		return IRQ_NONE;
1134	}
1135
1136	spin_lock_irqsave(&ha->hardware_lock, flags);
1137
1138	ha->isr_count++;
1139	/*
1140	 * Repeatedly service interrupts up to a maximum of
1141	 * MAX_REQS_SERVICED_PER_INTR
1142	 */
1143	while (1) {
1144		/*
1145		 * Read interrupt status
1146		 */
1147		if (ha->isp_ops->rd_shdw_rsp_q_in(ha) !=
1148		    ha->response_out)
1149			intr_status = CSR_SCSI_COMPLETION_INTR;
1150		else
1151			intr_status = readl(&ha->reg->ctrl_status);
1152
1153		if ((intr_status &
1154		    (CSR_SCSI_RESET_INTR|CSR_FATAL_ERROR|INTR_PENDING)) == 0) {
1155			if (reqs_count == 0)
1156				ha->spurious_int_count++;
1157			break;
1158		}
1159
1160		if (intr_status & CSR_FATAL_ERROR) {
1161			DEBUG2(printk(KERN_INFO "scsi%ld: Fatal Error, "
1162				      "Status 0x%04x\n", ha->host_no,
1163				      readl(isp_port_error_status (ha))));
1164
1165			/* Issue Soft Reset to clear this error condition.
1166			 * This will prevent the RISC from repeatedly
1167			 * interrupting the driver; thus, allowing the DPC to
1168			 * get scheduled to continue error recovery.
1169			 * NOTE: Disabling RISC interrupts does not work in
1170			 * this case, as CSR_FATAL_ERROR overrides
1171			 * CSR_SCSI_INTR_ENABLE */
1172			if ((readl(&ha->reg->ctrl_status) &
1173			     CSR_SCSI_RESET_INTR) == 0) {
1174				writel(set_rmask(CSR_SOFT_RESET),
1175				       &ha->reg->ctrl_status);
1176				readl(&ha->reg->ctrl_status);
1177			}
1178
1179			writel(set_rmask(CSR_FATAL_ERROR),
1180			       &ha->reg->ctrl_status);
1181			readl(&ha->reg->ctrl_status);
1182
1183			__qla4xxx_disable_intrs(ha);
1184
1185			set_bit(DPC_RESET_HA, &ha->dpc_flags);
1186
1187			break;
1188		} else if (intr_status & CSR_SCSI_RESET_INTR) {
1189			clear_bit(AF_ONLINE, &ha->flags);
1190			__qla4xxx_disable_intrs(ha);
1191
1192			writel(set_rmask(CSR_SCSI_RESET_INTR),
1193			       &ha->reg->ctrl_status);
1194			readl(&ha->reg->ctrl_status);
1195
1196			if (!test_bit(AF_HA_REMOVAL, &ha->flags))
1197				set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
1198
1199			break;
1200		} else if (intr_status & INTR_PENDING) {
1201			ha->isp_ops->interrupt_service_routine(ha, intr_status);
1202			ha->total_io_count++;
1203			if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
1204				break;
1205		}
1206	}
1207
1208	spin_unlock_irqrestore(&ha->hardware_lock, flags);
1209
1210	return IRQ_HANDLED;
1211}
1212
1213/**
1214 * qla4_82xx_intr_handler - hardware interrupt handler.
1215 * @irq: Unused
1216 * @dev_id: Pointer to host adapter structure
1217 **/
1218irqreturn_t qla4_82xx_intr_handler(int irq, void *dev_id)
1219{
1220	struct scsi_qla_host *ha = dev_id;
1221	uint32_t intr_status;
1222	uint32_t status;
1223	unsigned long flags = 0;
1224	uint8_t reqs_count = 0;
1225
1226	if (unlikely(pci_channel_offline(ha->pdev)))
1227		return IRQ_HANDLED;
1228
1229	ha->isr_count++;
1230	status = qla4_82xx_rd_32(ha, ISR_INT_VECTOR);
1231	if (!(status & ha->nx_legacy_intr.int_vec_bit))
1232		return IRQ_NONE;
1233
1234	status = qla4_82xx_rd_32(ha, ISR_INT_STATE_REG);
1235	if (!ISR_IS_LEGACY_INTR_TRIGGERED(status)) {
1236		DEBUG7(ql4_printk(KERN_INFO, ha,
1237				  "%s legacy Int not triggered\n", __func__));
1238		return IRQ_NONE;
1239	}
1240
1241	/* clear the interrupt */
1242	qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff);
1243
1244	/* read twice to ensure write is flushed */
1245	qla4_82xx_rd_32(ha, ISR_INT_VECTOR);
1246	qla4_82xx_rd_32(ha, ISR_INT_VECTOR);
1247
1248	spin_lock_irqsave(&ha->hardware_lock, flags);
1249	while (1) {
1250		if (!(readl(&ha->qla4_82xx_reg->host_int) &
1251		    ISRX_82XX_RISC_INT)) {
1252			qla4_82xx_spurious_interrupt(ha, reqs_count);
1253			break;
1254		}
1255		intr_status =  readl(&ha->qla4_82xx_reg->host_status);
1256		if ((intr_status &
1257		    (HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0)  {
1258			qla4_82xx_spurious_interrupt(ha, reqs_count);
1259			break;
1260		}
1261
1262		ha->isp_ops->interrupt_service_routine(ha, intr_status);
1263
1264		/* Enable Interrupt */
1265		qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff);
1266
1267		if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
1268			break;
1269	}
1270
1271	spin_unlock_irqrestore(&ha->hardware_lock, flags);
1272	return IRQ_HANDLED;
1273}
1274
1275#define LEG_INT_PTR_B31		(1 << 31)
1276#define LEG_INT_PTR_B30		(1 << 30)
1277#define PF_BITS_MASK		(0xF << 16)
1278
1279/**
1280 * qla4_83xx_intr_handler - hardware interrupt handler.
1281 * @irq: Unused
1282 * @dev_id: Pointer to host adapter structure
1283 **/
1284irqreturn_t qla4_83xx_intr_handler(int irq, void *dev_id)
1285{
1286	struct scsi_qla_host *ha = dev_id;
1287	uint32_t leg_int_ptr = 0;
1288	unsigned long flags = 0;
1289
1290	ha->isr_count++;
1291	leg_int_ptr = readl(&ha->qla4_83xx_reg->leg_int_ptr);
1292
1293	/* Legacy interrupt is valid if bit31 of leg_int_ptr is set */
1294	if (!(leg_int_ptr & LEG_INT_PTR_B31)) {
1295		DEBUG7(ql4_printk(KERN_ERR, ha,
1296				  "%s: Legacy Interrupt Bit 31 not set, spurious interrupt!\n",
1297				  __func__));
1298		return IRQ_NONE;
1299	}
1300
1301	/* Validate the PCIE function ID set in leg_int_ptr bits [19..16] */
1302	if ((leg_int_ptr & PF_BITS_MASK) != ha->pf_bit) {
1303		DEBUG7(ql4_printk(KERN_ERR, ha,
1304				  "%s: Incorrect function ID 0x%x in legacy interrupt register, ha->pf_bit = 0x%x\n",
1305				  __func__, (leg_int_ptr & PF_BITS_MASK),
1306				  ha->pf_bit));
1307		return IRQ_NONE;
1308	}
1309
1310	/* To de-assert legacy interrupt, write 0 to Legacy Interrupt Trigger
1311	 * Control register and poll till Legacy Interrupt Pointer register
1312	 * bit30 is 0.
1313	 */
1314	writel(0, &ha->qla4_83xx_reg->leg_int_trig);
1315	do {
1316		leg_int_ptr = readl(&ha->qla4_83xx_reg->leg_int_ptr);
1317		if ((leg_int_ptr & PF_BITS_MASK) != ha->pf_bit)
1318			break;
1319	} while (leg_int_ptr & LEG_INT_PTR_B30);
1320
1321	spin_lock_irqsave(&ha->hardware_lock, flags);
1322	leg_int_ptr = readl(&ha->qla4_83xx_reg->risc_intr);
1323	ha->isp_ops->interrupt_service_routine(ha, leg_int_ptr);
1324	spin_unlock_irqrestore(&ha->hardware_lock, flags);
1325
1326	return IRQ_HANDLED;
1327}
1328
1329irqreturn_t
1330qla4_8xxx_msi_handler(int irq, void *dev_id)
1331{
1332	struct scsi_qla_host *ha;
1333
1334	ha = (struct scsi_qla_host *) dev_id;
1335	if (!ha) {
1336		DEBUG2(printk(KERN_INFO
1337		    "qla4xxx: MSIX: Interrupt with NULL host ptr\n"));
1338		return IRQ_NONE;
1339	}
1340
1341	ha->isr_count++;
1342	/* clear the interrupt */
1343	qla4_82xx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff);
1344
1345	/* read twice to ensure write is flushed */
1346	qla4_82xx_rd_32(ha, ISR_INT_VECTOR);
1347	qla4_82xx_rd_32(ha, ISR_INT_VECTOR);
1348
1349	return qla4_8xxx_default_intr_handler(irq, dev_id);
1350}
1351
1352static irqreturn_t qla4_83xx_mailbox_intr_handler(int irq, void *dev_id)
1353{
1354	struct scsi_qla_host *ha = dev_id;
1355	unsigned long flags;
1356	uint32_t ival = 0;
1357
1358	spin_lock_irqsave(&ha->hardware_lock, flags);
1359
1360	ival = readl(&ha->qla4_83xx_reg->risc_intr);
1361	if (ival == 0) {
1362		ql4_printk(KERN_INFO, ha,
1363			   "%s: It is a spurious mailbox interrupt!\n",
1364			   __func__);
1365		ival = readl(&ha->qla4_83xx_reg->mb_int_mask);
1366		ival &= ~INT_MASK_FW_MB;
1367		writel(ival, &ha->qla4_83xx_reg->mb_int_mask);
1368		goto exit;
1369	}
1370
1371	qla4xxx_isr_decode_mailbox(ha,
1372				   readl(&ha->qla4_83xx_reg->mailbox_out[0]));
1373	writel(0, &ha->qla4_83xx_reg->risc_intr);
1374	ival = readl(&ha->qla4_83xx_reg->mb_int_mask);
1375	ival &= ~INT_MASK_FW_MB;
1376	writel(ival, &ha->qla4_83xx_reg->mb_int_mask);
1377	ha->isr_count++;
1378exit:
1379	spin_unlock_irqrestore(&ha->hardware_lock, flags);
1380	return IRQ_HANDLED;
1381}
1382
1383/**
1384 * qla4_8xxx_default_intr_handler - hardware interrupt handler.
1385 * @irq: Unused
1386 * @dev_id: Pointer to host adapter structure
1387 *
1388 * This interrupt handler is called directly for MSI-X, and
1389 * called indirectly for MSI.
1390 **/
1391irqreturn_t
1392qla4_8xxx_default_intr_handler(int irq, void *dev_id)
1393{
1394	struct scsi_qla_host *ha = dev_id;
1395	unsigned long   flags;
1396	uint32_t intr_status;
1397	uint8_t reqs_count = 0;
1398
1399	if (is_qla8032(ha) || is_qla8042(ha)) {
1400		qla4_83xx_mailbox_intr_handler(irq, dev_id);
1401	} else {
1402		spin_lock_irqsave(&ha->hardware_lock, flags);
1403		while (1) {
1404			if (!(readl(&ha->qla4_82xx_reg->host_int) &
1405			    ISRX_82XX_RISC_INT)) {
1406				qla4_82xx_spurious_interrupt(ha, reqs_count);
1407				break;
1408			}
1409
1410			intr_status =  readl(&ha->qla4_82xx_reg->host_status);
1411			if ((intr_status &
1412			    (HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) {
1413				qla4_82xx_spurious_interrupt(ha, reqs_count);
1414				break;
1415			}
1416
1417			ha->isp_ops->interrupt_service_routine(ha, intr_status);
1418
1419			if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
1420				break;
1421		}
1422		ha->isr_count++;
1423		spin_unlock_irqrestore(&ha->hardware_lock, flags);
1424	}
1425	return IRQ_HANDLED;
1426}
1427
1428irqreturn_t
1429qla4_8xxx_msix_rsp_q(int irq, void *dev_id)
1430{
1431	struct scsi_qla_host *ha = dev_id;
1432	unsigned long flags;
1433	int intr_status;
1434	uint32_t ival = 0;
1435
1436	spin_lock_irqsave(&ha->hardware_lock, flags);
1437	if (is_qla8032(ha) || is_qla8042(ha)) {
1438		ival = readl(&ha->qla4_83xx_reg->iocb_int_mask);
1439		if (ival == 0) {
1440			ql4_printk(KERN_INFO, ha, "%s: It is a spurious iocb interrupt!\n",
1441				   __func__);
1442			goto exit_msix_rsp_q;
1443		}
1444		qla4xxx_process_response_queue(ha);
1445		writel(0, &ha->qla4_83xx_reg->iocb_int_mask);
1446	} else {
1447		intr_status = readl(&ha->qla4_82xx_reg->host_status);
1448		if (intr_status & HSRX_RISC_IOCB_INT) {
1449			qla4xxx_process_response_queue(ha);
1450			writel(0, &ha->qla4_82xx_reg->host_int);
1451		} else {
1452			ql4_printk(KERN_INFO, ha, "%s: spurious iocb interrupt...\n",
1453				   __func__);
1454			goto exit_msix_rsp_q;
1455		}
1456	}
1457	ha->isr_count++;
1458exit_msix_rsp_q:
1459	spin_unlock_irqrestore(&ha->hardware_lock, flags);
1460	return IRQ_HANDLED;
1461}
1462
1463/**
1464 * qla4xxx_process_aen - processes AENs generated by firmware
1465 * @ha: pointer to host adapter structure.
1466 * @process_aen: type of AENs to process
1467 *
1468 * Processes specific types of Asynchronous Events generated by firmware.
1469 * The type of AENs to process is specified by process_aen and can be
1470 *	PROCESS_ALL_AENS	 0
1471 *	FLUSH_DDB_CHANGED_AENS	 1
1472 *	RELOGIN_DDB_CHANGED_AENS 2
1473 **/
1474void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
1475{
1476	uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
1477	struct aen *aen;
1478	int i;
1479	unsigned long flags;
1480
1481	spin_lock_irqsave(&ha->hardware_lock, flags);
1482	while (ha->aen_out != ha->aen_in) {
1483		aen = &ha->aen_q[ha->aen_out];
1484		/* copy aen information to local structure */
1485		for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
1486			mbox_sts[i] = aen->mbox_sts[i];
1487
1488		ha->aen_q_count++;
1489		ha->aen_out++;
1490
1491		if (ha->aen_out == MAX_AEN_ENTRIES)
1492			ha->aen_out = 0;
1493
1494		spin_unlock_irqrestore(&ha->hardware_lock, flags);
1495
1496		DEBUG2(printk("qla4xxx(%ld): AEN[%d]=0x%08x, mbx1=0x%08x mbx2=0x%08x"
1497			" mbx3=0x%08x mbx4=0x%08x\n", ha->host_no,
1498			(ha->aen_out ? (ha->aen_out-1): (MAX_AEN_ENTRIES-1)),
1499			mbox_sts[0], mbox_sts[1], mbox_sts[2],
1500			mbox_sts[3], mbox_sts[4]));
1501
1502		switch (mbox_sts[0]) {
1503		case MBOX_ASTS_DATABASE_CHANGED:
1504			switch (process_aen) {
1505			case FLUSH_DDB_CHANGED_AENS:
1506				DEBUG2(printk("scsi%ld: AEN[%d] %04x, index "
1507					      "[%d] state=%04x FLUSHED!\n",
1508					      ha->host_no, ha->aen_out,
1509					      mbox_sts[0], mbox_sts[2],
1510					      mbox_sts[3]));
1511				break;
1512			case PROCESS_ALL_AENS:
1513			default:
1514				/* Specific device. */
1515				if (mbox_sts[1] == 1)
1516					qla4xxx_process_ddb_changed(ha,
1517						mbox_sts[2], mbox_sts[3],
1518						mbox_sts[4]);
1519				break;
1520			}
1521		}
1522		spin_lock_irqsave(&ha->hardware_lock, flags);
1523	}
1524	spin_unlock_irqrestore(&ha->hardware_lock, flags);
1525}
1526
1527int qla4xxx_request_irqs(struct scsi_qla_host *ha)
1528{
1529	int ret = 0;
1530	int rval = QLA_ERROR;
1531
1532	if (is_qla40XX(ha))
1533		goto try_intx;
1534
1535	if (ql4xenablemsix == 2) {
1536		/* Note: MSI Interrupts not supported for ISP8324 and ISP8042 */
1537		if (is_qla8032(ha) || is_qla8042(ha)) {
1538			ql4_printk(KERN_INFO, ha, "%s: MSI Interrupts not supported for ISP%04x, Falling back-to INTx mode\n",
1539				   __func__, ha->pdev->device);
1540			goto try_intx;
1541		}
1542		goto try_msi;
1543	}
1544
1545	if (ql4xenablemsix == 0 || ql4xenablemsix != 1)
1546		goto try_intx;
1547
1548	/* Trying MSI-X */
1549	ret = qla4_8xxx_enable_msix(ha);
1550	if (!ret) {
1551		DEBUG2(ql4_printk(KERN_INFO, ha,
1552		    "MSI-X: Enabled (0x%X).\n", ha->revision_id));
1553		goto irq_attached;
1554	} else {
1555		if (is_qla8032(ha) || is_qla8042(ha)) {
1556			ql4_printk(KERN_INFO, ha, "%s: ISP%04x: MSI-X: Falling back-to INTx mode. ret = %d\n",
1557				   __func__, ha->pdev->device, ret);
1558			goto try_intx;
1559		}
1560	}
1561
1562	ql4_printk(KERN_WARNING, ha,
1563	    "MSI-X: Falling back-to MSI mode -- %d.\n", ret);
1564
1565try_msi:
1566	/* Trying MSI */
1567	ret = pci_alloc_irq_vectors(ha->pdev, 1, 1, PCI_IRQ_MSI);
1568	if (ret > 0) {
1569		ret = request_irq(ha->pdev->irq, qla4_8xxx_msi_handler,
1570			0, DRIVER_NAME, ha);
1571		if (!ret) {
1572			DEBUG2(ql4_printk(KERN_INFO, ha, "MSI: Enabled.\n"));
1573			goto irq_attached;
1574		} else {
1575			ql4_printk(KERN_WARNING, ha,
1576			    "MSI: Failed to reserve interrupt %d "
1577			    "already in use.\n", ha->pdev->irq);
1578			pci_free_irq_vectors(ha->pdev);
1579		}
1580	}
1581
1582try_intx:
1583	if (is_qla8022(ha)) {
1584		ql4_printk(KERN_WARNING, ha, "%s: ISP82xx Legacy interrupt not supported\n",
1585			   __func__);
1586		goto irq_not_attached;
1587	}
1588
1589	/* Trying INTx */
1590	ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
1591	    IRQF_SHARED, DRIVER_NAME, ha);
1592	if (!ret) {
1593		DEBUG2(ql4_printk(KERN_INFO, ha, "INTx: Enabled.\n"));
1594		goto irq_attached;
1595
1596	} else {
1597		ql4_printk(KERN_WARNING, ha,
1598		    "INTx: Failed to reserve interrupt %d already in"
1599		    " use.\n", ha->pdev->irq);
1600		goto irq_not_attached;
1601	}
1602
1603irq_attached:
1604	set_bit(AF_IRQ_ATTACHED, &ha->flags);
1605	ha->host->irq = ha->pdev->irq;
1606	ql4_printk(KERN_INFO, ha, "%s: irq %d attached\n",
1607		   __func__, ha->pdev->irq);
1608	rval = QLA_SUCCESS;
1609irq_not_attached:
1610	return rval;
1611}
1612
1613void qla4xxx_free_irqs(struct scsi_qla_host *ha)
1614{
1615	if (!test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags))
1616		return;
1617
1618	if (ha->pdev->msix_enabled)
1619		free_irq(pci_irq_vector(ha->pdev, 1), ha);
1620	free_irq(pci_irq_vector(ha->pdev, 0), ha);
1621	pci_free_irq_vectors(ha->pdev);
1622}