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

Commit 821d6e54 authored by Vikas Chaudhary's avatar Vikas Chaudhary Committed by James Bottomley
Browse files

[SCSI] qla4xxx: do not retry login to CHAP auth failed targets



Per RFC 3720, Login Response Status Code 0x02 should not be retried.
Condensed connection error checking code to a single routine, and
added check for status class 0x02.

Signed-off-by: default avatarKaren Higgins <karen.higgins@qlogic.com>
Signed-off-by: default avatarVikas Chaudhary <vikas.chaudhary@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 c301b026
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -67,11 +67,12 @@ struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
					uint32_t index);
					uint32_t index);
void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb);
void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb);
int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
				uint32_t fw_ddb_index, uint32_t state);
		uint32_t state, uint32_t conn_error);
void qla4xxx_dump_buffer(void *b, uint32_t size);
void qla4xxx_dump_buffer(void *b, uint32_t size);
int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
	struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
	struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err);


extern int ql4xextended_error_logging;
extern int ql4xextended_error_logging;
extern int ql4xdiscoverywait;
extern int ql4xdiscoverywait;
+90 −40
Original line number Original line Diff line number Diff line
@@ -505,6 +505,7 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
	struct dev_db_entry *fw_ddb_entry = NULL;
	struct dev_db_entry *fw_ddb_entry = NULL;
	dma_addr_t fw_ddb_entry_dma;
	dma_addr_t fw_ddb_entry_dma;
	int status = QLA_ERROR;
	int status = QLA_ERROR;
	uint32_t conn_err;


	if (ddb_entry == NULL) {
	if (ddb_entry == NULL) {
		DEBUG2(printk("scsi%ld: %s: ddb_entry is NULL\n", ha->host_no,
		DEBUG2(printk("scsi%ld: %s: ddb_entry is NULL\n", ha->host_no,
@@ -525,7 +526,7 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,


	if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
	if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
				    fw_ddb_entry_dma, NULL, NULL,
				    fw_ddb_entry_dma, NULL, NULL,
				    &ddb_entry->fw_ddb_device_state, NULL,
				    &ddb_entry->fw_ddb_device_state, &conn_err,
				    &ddb_entry->tcp_source_port_num,
				    &ddb_entry->tcp_source_port_num,
				    &ddb_entry->connection_id) ==
				    &ddb_entry->connection_id) ==
	    QLA_ERROR) {
	    QLA_ERROR) {
@@ -578,12 +579,26 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
			fw_ddb_entry->link_local_ipv6_addr,
			fw_ddb_entry->link_local_ipv6_addr,
			min(sizeof(ddb_entry->link_local_ipv6_addr),
			min(sizeof(ddb_entry->link_local_ipv6_addr),
			sizeof(fw_ddb_entry->link_local_ipv6_addr)));
			sizeof(fw_ddb_entry->link_local_ipv6_addr)));
	}

	DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n",
			ha->host_no, __func__, fw_ddb_index,
			ddb_entry->fw_ddb_device_state, status));


		DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d "
					"State %04x ConnErr %08x IP %pI6 "
					":%04d \"%s\"\n",
					__func__, fw_ddb_index,
					ddb_entry->os_target_id,
					ddb_entry->fw_ddb_device_state,
					conn_err, fw_ddb_entry->ip_addr,
					le16_to_cpu(fw_ddb_entry->port),
					fw_ddb_entry->iscsi_name));
	} else
		DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d "
					"State %04x ConnErr %08x IP %pI4 "
					":%04d \"%s\"\n",
					__func__, fw_ddb_index,
					ddb_entry->os_target_id,
					ddb_entry->fw_ddb_device_state,
					conn_err, fw_ddb_entry->ip_addr,
					le16_to_cpu(fw_ddb_entry->port),
					fw_ddb_entry->iscsi_name));
exit_update_ddb:
exit_update_ddb:
	if (fw_ddb_entry)
	if (fw_ddb_entry)
		dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
		dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
@@ -629,6 +644,40 @@ static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
	return ddb_entry;
	return ddb_entry;
}
}


/**
 * qla4_is_relogin_allowed - Are we allowed to login?
 * @ha: Pointer to host adapter structure.
 * @conn_err: Last connection error associated with the ddb
 *
 * This routine tests the given connection error to determine if
 * we are allowed to login.
 **/
int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err)
{
	uint32_t err_code, login_rsp_sts_class;
	int relogin = 1;

	err_code = ((conn_err & 0x00ff0000) >> 16);
	login_rsp_sts_class = ((conn_err & 0x0000ff00) >> 8);
	if (err_code == 0x1c || err_code == 0x06) {
		DEBUG2(dev_info(&ha->pdev->dev,
				": conn_err=0x%08x, send target completed"
				" or access denied failure\n", conn_err));
		relogin = 0;
	}
	if ((err_code == 0x08) && (login_rsp_sts_class == 0x02)) {
		/* Login Response PDU returned an error.
		   Login Response Status in Error Code Detail
		   indicates login should not be retried.*/
		DEBUG2(dev_info(&ha->pdev->dev,
				": conn_err=0x%08x, do not retry relogin\n",
				conn_err));
		relogin = 0;
	}

	return relogin;
}

/**
/**
 * qla4xxx_configure_ddbs - builds driver ddb list
 * qla4xxx_configure_ddbs - builds driver ddb list
 * @ha: Pointer to host adapter structure.
 * @ha: Pointer to host adapter structure.
@@ -643,17 +692,29 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
	uint32_t fw_ddb_index = 0;
	uint32_t fw_ddb_index = 0;
	uint32_t next_fw_ddb_index = 0;
	uint32_t next_fw_ddb_index = 0;
	uint32_t ddb_state;
	uint32_t ddb_state;
	uint32_t conn_err, err_code;
	uint32_t conn_err;
	struct ddb_entry *ddb_entry;
	struct ddb_entry *ddb_entry;
	struct dev_db_entry *fw_ddb_entry = NULL;
	dma_addr_t fw_ddb_entry_dma;
	uint32_t ipv6_device;
	uint32_t new_tgt;
	uint32_t new_tgt;


	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
			&fw_ddb_entry_dma, GFP_KERNEL);
	if (fw_ddb_entry == NULL) {
		DEBUG2(dev_info(&ha->pdev->dev, "%s: DMA alloc failed\n",
				__func__));
		return QLA_ERROR;
	}

	dev_info(&ha->pdev->dev, "Initializing DDBs ...\n");
	dev_info(&ha->pdev->dev, "Initializing DDBs ...\n");
	for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES;
	for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES;
	     fw_ddb_index = next_fw_ddb_index) {
	     fw_ddb_index = next_fw_ddb_index) {
		/* First, let's see if a device exists here */
		/* First, let's see if a device exists here */
		if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, NULL, 0, NULL,
		if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
					    &next_fw_ddb_index, &ddb_state,
					    0, NULL, &next_fw_ddb_index,
					    &conn_err, NULL, NULL) ==
					    &ddb_state, &conn_err,
					    NULL, NULL) ==
					    QLA_ERROR) {
					    QLA_ERROR) {
			DEBUG2(printk("scsi%ld: %s: get_ddb_entry, "
			DEBUG2(printk("scsi%ld: %s: get_ddb_entry, "
				      "fw_ddb_index %d failed", ha->host_no,
				      "fw_ddb_index %d failed", ha->host_no,
@@ -671,17 +732,18 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
			/* Try and login to device */
			/* Try and login to device */
			DEBUG2(printk("scsi%ld: %s: Login to DDB[%d]\n",
			DEBUG2(printk("scsi%ld: %s: Login to DDB[%d]\n",
				      ha->host_no, __func__, fw_ddb_index));
				      ha->host_no, __func__, fw_ddb_index));
			err_code = ((conn_err & 0x00ff0000) >> 16);
			ipv6_device = le16_to_cpu(fw_ddb_entry->options) &
			if (err_code == 0x1c || err_code == 0x06) {
					DDB_OPT_IPV6_DEVICE;
				DEBUG2(printk("scsi%ld: %s send target "
			if (qla4_is_relogin_allowed(ha, conn_err) &&
					      "completed "
					((!ipv6_device &&
					      "or access denied failure\n",
					  *((uint32_t *)fw_ddb_entry->ip_addr))
					      ha->host_no, __func__));
					 || ipv6_device)) {
			} else {
				qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0);
				qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0);
				if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index,
				if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index,
					NULL, 0, NULL, &next_fw_ddb_index,
							NULL, 0, NULL,
					&ddb_state, &conn_err, NULL, NULL)
							&next_fw_ddb_index,
							&ddb_state, &conn_err,
							NULL, NULL)
						== QLA_ERROR) {
						== QLA_ERROR) {
					DEBUG2(printk("scsi%ld: %s:"
					DEBUG2(printk("scsi%ld: %s:"
						"get_ddb_entry %d failed\n",
						"get_ddb_entry %d failed\n",
@@ -737,7 +799,6 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
struct qla4_relog_scan {
struct qla4_relog_scan {
	int halt_wait;
	int halt_wait;
	uint32_t conn_err;
	uint32_t conn_err;
	uint32_t err_code;
	uint32_t fw_ddb_index;
	uint32_t fw_ddb_index;
	uint32_t next_fw_ddb_index;
	uint32_t next_fw_ddb_index;
	uint32_t fw_ddb_device_state;
	uint32_t fw_ddb_device_state;
@@ -747,18 +808,7 @@ static int qla4_test_rdy(struct scsi_qla_host *ha, struct qla4_relog_scan *rs)
{
{
	struct ddb_entry *ddb_entry;
	struct ddb_entry *ddb_entry;


	/*
	if (qla4_is_relogin_allowed(ha, rs->conn_err)) {
	 * Don't want to do a relogin if connection
	 * error is 0x1c.
	 */
	rs->err_code = ((rs->conn_err & 0x00ff0000) >> 16);
	if (rs->err_code == 0x1c || rs->err_code == 0x06) {
		DEBUG2(printk(
			       "scsi%ld: %s send target"
			       " completed or "
			       "access denied failure\n",
			       ha->host_no, __func__));
	} else {
		/* We either have a device that is in
		/* We either have a device that is in
		 * the process of relogging in or a
		 * the process of relogging in or a
		 * device that is waiting to be
		 * device that is waiting to be
@@ -1411,8 +1461,8 @@ static void qla4xxx_add_device_dynamically(struct scsi_qla_host *ha,
 *
 *
 * This routine processes a Decive Database Changed AEN Event.
 * This routine processes a Decive Database Changed AEN Event.
 **/
 **/
int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
				uint32_t fw_ddb_index, uint32_t state)
		uint32_t state, uint32_t conn_err)
{
{
	struct ddb_entry * ddb_entry;
	struct ddb_entry * ddb_entry;
	uint32_t old_fw_ddb_device_state;
	uint32_t old_fw_ddb_device_state;
@@ -1470,13 +1520,13 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,


		/*
		/*
		 * Relogin if device state changed to a not active state.
		 * Relogin if device state changed to a not active state.
		 * However, do not relogin if this aen is a result of an IOCTL
		 * However, do not relogin if a RELOGIN is in process, or
		 * logout (DF_NO_RELOGIN) or if this is a discovered device.
		 * we are not allowed to relogin to this DDB.
		 */
		 */
		if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED &&
		if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED &&
		    !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
		    !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
		    !test_bit(DF_NO_RELOGIN, &ddb_entry->flags) &&
		    !test_bit(DF_NO_RELOGIN, &ddb_entry->flags) &&
		    !test_bit(DF_ISNS_DISCOVERED, &ddb_entry->flags)) {
		    qla4_is_relogin_allowed(ha, conn_err)) {
			/*
			/*
			 * This triggers a relogin.  After the relogin_timer
			 * This triggers a relogin.  After the relogin_timer
			 * expires, the relogin gets scheduled.	 We must wait a
			 * expires, the relogin gets scheduled.	 We must wait a
@@ -1484,7 +1534,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
			 * with failed device_state or a logout response before
			 * with failed device_state or a logout response before
			 * we can issue another relogin.
			 * we can issue another relogin.
			 */
			 */
			/* Firmware padds this timeout: (time2wait +1).
			/* Firmware pads this timeout: (time2wait +1).
			 * Driver retry to login should be longer than F/W.
			 * Driver retry to login should be longer than F/W.
			 * Otherwise F/W will fail
			 * Otherwise F/W will fail
			 * set_ddb() mbx cmd with 0x4005 since it still
			 * set_ddb() mbx cmd with 0x4005 since it still
+1 −1
Original line number Original line Diff line number Diff line
@@ -838,7 +838,7 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
				qla4xxx_reinitialize_ddb_list(ha);
				qla4xxx_reinitialize_ddb_list(ha);
			} else if (mbox_sts[1] == 1) {	/* Specific device. */
			} else if (mbox_sts[1] == 1) {	/* Specific device. */
				qla4xxx_process_ddb_changed(ha, mbox_sts[2],
				qla4xxx_process_ddb_changed(ha, mbox_sts[2],
							    mbox_sts[3]);
						mbox_sts[3], mbox_sts[4]);
			}
			}
			break;
			break;
		}
		}