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

[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
...@@ -67,11 +67,12 @@ struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, ...@@ -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;
......
...@@ -505,6 +505,7 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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,18 +692,30 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) ...@@ -643,18 +692,30 @@ 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,
QLA_ERROR) { NULL, NULL) ==
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,
__func__, fw_ddb_index)); __func__, fw_ddb_index));
...@@ -671,18 +732,19 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) ...@@ -671,18 +732,19 @@ 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,
== QLA_ERROR) { &ddb_state, &conn_err,
NULL, NULL)
== QLA_ERROR) {
DEBUG2(printk("scsi%ld: %s:" DEBUG2(printk("scsi%ld: %s:"
"get_ddb_entry %d failed\n", "get_ddb_entry %d failed\n",
ha->host_no, ha->host_no,
...@@ -737,7 +799,6 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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
......
...@@ -838,7 +838,7 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen) ...@@ -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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment