Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 065aa1b4 authored by Vikas Chaudhary's avatar Vikas Chaudhary Committed by James Bottomley
Browse files

[SCSI] qla4xxx: set device state as per Link UP and LINK DOWN



Link Down -> Mark all devices missing
 Previously, the driver took no action on a Link Down,
 and waited for the I/O on a dead connection to timeout
 in the firmware before marking the DDB missing.

Link Up -> Mark all devices online
 F/W will do auto login to all the devices only once.
 After that its the responsibility of the driver to
 relogin to devices whenever there is :
        * Any sort of connection failure or
        * KATO expires indicating target has logged out or
        * I/O times out etc.

Signed-off-by: default avatarVikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: default avatarKaren Higgins <karen.higgins@qlogic.com>
Signed-off-by: default avatarRavi Anand <ravi.anand@qlogic.com>
Reviewed-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 2a49a78e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -310,6 +310,7 @@ struct scsi_qla_host {
#define DPC_ISNS_RESTART		7 /* 0x00000080 */
#define DPC_AEN				9 /* 0x00000200 */
#define DPC_GET_DHCP_IP_ADDR		15 /* 0x00008000 */
#define DPC_LINK_CHANGED		18 /* 0x00040000 */

	struct Scsi_Host *host; /* pointer to host data */
	uint32_t tot_ddbs;
+9 −3
Original line number Diff line number Diff line
@@ -1279,6 +1279,7 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
	int status = QLA_ERROR;
	int8_t ip_address[IP_ADDR_LEN] = {0} ;

	clear_bit(AF_ONLINE, &ha->flags);
	ha->eeprom_cmd_data = 0;

	qla4x00_pci_config(ha);
@@ -1456,10 +1457,15 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
		 * the device came back.
		 */
	} else {
		/* Device went away, try to relogin. */
		/* Mark device missing */
		if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
		/* Device went away, mark device missing */
		if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) {
			DEBUG2(dev_info(&ha->pdev->dev, "%s mark missing "
					"ddb_entry 0x%p sess 0x%p conn 0x%p\n",
					__func__, ddb_entry,
					ddb_entry->sess, ddb_entry->conn));
			qla4xxx_mark_device_missing(ha, ddb_entry);
		}

		/*
		 * Relogin if device state changed to a not active state.
		 * However, do not relogin if this aen is a result of an IOCTL
+11 −4
Original line number Diff line number Diff line
@@ -498,15 +498,22 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
			break;

		case MBOX_ASTS_LINK_UP:
			DEBUG2(printk("scsi%ld: AEN %04x Adapter LINK UP\n",
				      ha->host_no, mbox_status));
			set_bit(AF_LINK_UP, &ha->flags);
			if (test_bit(AF_INIT_DONE, &ha->flags))
				set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);

			DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter"
					" LINK UP\n", ha->host_no,
					mbox_status));
			break;

		case MBOX_ASTS_LINK_DOWN:
			DEBUG2(printk("scsi%ld: AEN %04x Adapter LINK DOWN\n",
				      ha->host_no, mbox_status));
			clear_bit(AF_LINK_UP, &ha->flags);
			set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);

			DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter"
					" LINK DOWN\n", ha->host_no,
					mbox_status));
			break;

		case MBOX_ASTS_HEARTBEAT:
+49 −0
Original line number Diff line number Diff line
@@ -685,6 +685,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
	     test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) ||
	     test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
	     test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||
	     test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) ||
	     test_bit(DPC_AEN, &ha->dpc_flags)) &&
	     ha->dpc_thread) {
		DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"
@@ -1069,6 +1070,54 @@ static void qla4xxx_do_dpc(struct work_struct *work)
	if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
		qla4xxx_get_dhcp_ip_address(ha);

	/* ---- link change? --- */
	if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
		if (!test_bit(AF_LINK_UP, &ha->flags)) {
			/* ---- link down? --- */
			list_for_each_entry_safe(ddb_entry, dtemp,
						 &ha->ddb_list, list) {
				if (atomic_read(&ddb_entry->state) ==
						DDB_STATE_ONLINE)
					qla4xxx_mark_device_missing(ha,
							ddb_entry);
			}
		} else {
			/* ---- link up? --- *
			 * F/W will auto login to all devices ONLY ONCE after
			 * link up during driver initialization and runtime
			 * fatal error recovery.  Therefore, the driver must
			 * manually relogin to devices when recovering from
			 * connection failures, logouts, expired KATO, etc. */

			list_for_each_entry_safe(ddb_entry, dtemp,
							&ha->ddb_list, list) {
				if ((atomic_read(&ddb_entry->state) ==
						 DDB_STATE_MISSING) ||
				    (atomic_read(&ddb_entry->state) ==
						 DDB_STATE_DEAD)) {
					if (ddb_entry->fw_ddb_device_state ==
					    DDB_DS_SESSION_ACTIVE) {
						atomic_set(&ddb_entry->state,
							   DDB_STATE_ONLINE);
						dev_info(&ha->pdev->dev,
						    "scsi%ld: %s: ddb[%d]"
						    " os[%d] marked"
						    " ONLINE\n",
						    ha->host_no, __func__,
						    ddb_entry->fw_ddb_index,
						    ddb_entry->os_target_id);

						iscsi_unblock_session(
						    ddb_entry->sess);
					} else
						qla4xxx_relogin_device(
						    ha, ddb_entry);
				}

			}
		}
	}

	/* ---- relogin device? --- */
	if (adapter_up(ha) &&
	    test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {