diff options
author | Vikas Chaudhary <vikas.chaudhary@qlogic.com> | 2010-04-28 02:11:21 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-05-02 15:39:49 -0400 |
commit | 821d6e5413481a57bbe1c2722dbe1fee4ff675c4 (patch) | |
tree | 8e0ddfabf4fda472a06b104d809c5e2078040720 /drivers/scsi | |
parent | c301b0266c65c8781361ca152981cff4fac05498 (diff) |
[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: Karen Higgins <karen.higgins@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: Ravi Anand <ravi.anand@qlogic.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 5 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_init.c | 130 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 2 |
3 files changed, 94 insertions, 43 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 96ebfb021f6c..987658f5bc13 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -67,11 +67,12 @@ struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, | |||
67 | uint32_t index); | 67 | uint32_t index); |
68 | void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb); | 68 | void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb); |
69 | int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha); | 69 | int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha); |
70 | int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha, | 70 | int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, |
71 | uint32_t fw_ddb_index, uint32_t state); | 71 | uint32_t state, uint32_t conn_error); |
72 | void qla4xxx_dump_buffer(void *b, uint32_t size); | 72 | void qla4xxx_dump_buffer(void *b, uint32_t size); |
73 | int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, | 73 | int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, |
74 | struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod); | 74 | struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod); |
75 | int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err); | ||
75 | 76 | ||
76 | extern int ql4xextended_error_logging; | 77 | extern int ql4xextended_error_logging; |
77 | extern int ql4xdiscoverywait; | 78 | extern int ql4xdiscoverywait; |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index beaeb18a66ab..5510df8a7fa6 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
@@ -505,6 +505,7 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, | |||
505 | struct dev_db_entry *fw_ddb_entry = NULL; | 505 | struct dev_db_entry *fw_ddb_entry = NULL; |
506 | dma_addr_t fw_ddb_entry_dma; | 506 | dma_addr_t fw_ddb_entry_dma; |
507 | int status = QLA_ERROR; | 507 | int status = QLA_ERROR; |
508 | uint32_t conn_err; | ||
508 | 509 | ||
509 | if (ddb_entry == NULL) { | 510 | if (ddb_entry == NULL) { |
510 | DEBUG2(printk("scsi%ld: %s: ddb_entry is NULL\n", ha->host_no, | 511 | 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 | 526 | ||
526 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry, | 527 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry, |
527 | fw_ddb_entry_dma, NULL, NULL, | 528 | fw_ddb_entry_dma, NULL, NULL, |
528 | &ddb_entry->fw_ddb_device_state, NULL, | 529 | &ddb_entry->fw_ddb_device_state, &conn_err, |
529 | &ddb_entry->tcp_source_port_num, | 530 | &ddb_entry->tcp_source_port_num, |
530 | &ddb_entry->connection_id) == | 531 | &ddb_entry->connection_id) == |
531 | QLA_ERROR) { | 532 | QLA_ERROR) { |
@@ -578,12 +579,26 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, | |||
578 | fw_ddb_entry->link_local_ipv6_addr, | 579 | fw_ddb_entry->link_local_ipv6_addr, |
579 | min(sizeof(ddb_entry->link_local_ipv6_addr), | 580 | min(sizeof(ddb_entry->link_local_ipv6_addr), |
580 | sizeof(fw_ddb_entry->link_local_ipv6_addr))); | 581 | sizeof(fw_ddb_entry->link_local_ipv6_addr))); |
581 | } | ||
582 | |||
583 | DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n", | ||
584 | ha->host_no, __func__, fw_ddb_index, | ||
585 | ddb_entry->fw_ddb_device_state, status)); | ||
586 | 582 | ||
583 | DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d " | ||
584 | "State %04x ConnErr %08x IP %pI6 " | ||
585 | ":%04d \"%s\"\n", | ||
586 | __func__, fw_ddb_index, | ||
587 | ddb_entry->os_target_id, | ||
588 | ddb_entry->fw_ddb_device_state, | ||
589 | conn_err, fw_ddb_entry->ip_addr, | ||
590 | le16_to_cpu(fw_ddb_entry->port), | ||
591 | fw_ddb_entry->iscsi_name)); | ||
592 | } else | ||
593 | DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d " | ||
594 | "State %04x ConnErr %08x IP %pI4 " | ||
595 | ":%04d \"%s\"\n", | ||
596 | __func__, fw_ddb_index, | ||
597 | ddb_entry->os_target_id, | ||
598 | ddb_entry->fw_ddb_device_state, | ||
599 | conn_err, fw_ddb_entry->ip_addr, | ||
600 | le16_to_cpu(fw_ddb_entry->port), | ||
601 | fw_ddb_entry->iscsi_name)); | ||
587 | exit_update_ddb: | 602 | exit_update_ddb: |
588 | if (fw_ddb_entry) | 603 | if (fw_ddb_entry) |
589 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | 604 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), |
@@ -630,6 +645,40 @@ static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, | |||
630 | } | 645 | } |
631 | 646 | ||
632 | /** | 647 | /** |
648 | * qla4_is_relogin_allowed - Are we allowed to login? | ||
649 | * @ha: Pointer to host adapter structure. | ||
650 | * @conn_err: Last connection error associated with the ddb | ||
651 | * | ||
652 | * This routine tests the given connection error to determine if | ||
653 | * we are allowed to login. | ||
654 | **/ | ||
655 | int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err) | ||
656 | { | ||
657 | uint32_t err_code, login_rsp_sts_class; | ||
658 | int relogin = 1; | ||
659 | |||
660 | err_code = ((conn_err & 0x00ff0000) >> 16); | ||
661 | login_rsp_sts_class = ((conn_err & 0x0000ff00) >> 8); | ||
662 | if (err_code == 0x1c || err_code == 0x06) { | ||
663 | DEBUG2(dev_info(&ha->pdev->dev, | ||
664 | ": conn_err=0x%08x, send target completed" | ||
665 | " or access denied failure\n", conn_err)); | ||
666 | relogin = 0; | ||
667 | } | ||
668 | if ((err_code == 0x08) && (login_rsp_sts_class == 0x02)) { | ||
669 | /* Login Response PDU returned an error. | ||
670 | Login Response Status in Error Code Detail | ||
671 | indicates login should not be retried.*/ | ||
672 | DEBUG2(dev_info(&ha->pdev->dev, | ||
673 | ": conn_err=0x%08x, do not retry relogin\n", | ||
674 | conn_err)); | ||
675 | relogin = 0; | ||
676 | } | ||
677 | |||
678 | return relogin; | ||
679 | } | ||
680 | |||
681 | /** | ||
633 | * qla4xxx_configure_ddbs - builds driver ddb list | 682 | * qla4xxx_configure_ddbs - builds driver ddb list |
634 | * @ha: Pointer to host adapter structure. | 683 | * @ha: Pointer to host adapter structure. |
635 | * | 684 | * |
@@ -643,18 +692,30 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) | |||
643 | uint32_t fw_ddb_index = 0; | 692 | uint32_t fw_ddb_index = 0; |
644 | uint32_t next_fw_ddb_index = 0; | 693 | uint32_t next_fw_ddb_index = 0; |
645 | uint32_t ddb_state; | 694 | uint32_t ddb_state; |
646 | uint32_t conn_err, err_code; | 695 | uint32_t conn_err; |
647 | struct ddb_entry *ddb_entry; | 696 | struct ddb_entry *ddb_entry; |
697 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
698 | dma_addr_t fw_ddb_entry_dma; | ||
699 | uint32_t ipv6_device; | ||
648 | uint32_t new_tgt; | 700 | uint32_t new_tgt; |
649 | 701 | ||
702 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
703 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
704 | if (fw_ddb_entry == NULL) { | ||
705 | DEBUG2(dev_info(&ha->pdev->dev, "%s: DMA alloc failed\n", | ||
706 | __func__)); | ||
707 | return QLA_ERROR; | ||
708 | } | ||
709 | |||
650 | dev_info(&ha->pdev->dev, "Initializing DDBs ...\n"); | 710 | dev_info(&ha->pdev->dev, "Initializing DDBs ...\n"); |
651 | for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; | 711 | for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; |
652 | fw_ddb_index = next_fw_ddb_index) { | 712 | fw_ddb_index = next_fw_ddb_index) { |
653 | /* First, let's see if a device exists here */ | 713 | /* First, let's see if a device exists here */ |
654 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, NULL, 0, NULL, | 714 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry, |
655 | &next_fw_ddb_index, &ddb_state, | 715 | 0, NULL, &next_fw_ddb_index, |
656 | &conn_err, NULL, NULL) == | 716 | &ddb_state, &conn_err, |
657 | QLA_ERROR) { | 717 | NULL, NULL) == |
718 | QLA_ERROR) { | ||
658 | DEBUG2(printk("scsi%ld: %s: get_ddb_entry, " | 719 | DEBUG2(printk("scsi%ld: %s: get_ddb_entry, " |
659 | "fw_ddb_index %d failed", ha->host_no, | 720 | "fw_ddb_index %d failed", ha->host_no, |
660 | __func__, fw_ddb_index)); | 721 | __func__, fw_ddb_index)); |
@@ -671,18 +732,19 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) | |||
671 | /* Try and login to device */ | 732 | /* Try and login to device */ |
672 | DEBUG2(printk("scsi%ld: %s: Login to DDB[%d]\n", | 733 | DEBUG2(printk("scsi%ld: %s: Login to DDB[%d]\n", |
673 | ha->host_no, __func__, fw_ddb_index)); | 734 | ha->host_no, __func__, fw_ddb_index)); |
674 | err_code = ((conn_err & 0x00ff0000) >> 16); | 735 | ipv6_device = le16_to_cpu(fw_ddb_entry->options) & |
675 | if (err_code == 0x1c || err_code == 0x06) { | 736 | DDB_OPT_IPV6_DEVICE; |
676 | DEBUG2(printk("scsi%ld: %s send target " | 737 | if (qla4_is_relogin_allowed(ha, conn_err) && |
677 | "completed " | 738 | ((!ipv6_device && |
678 | "or access denied failure\n", | 739 | *((uint32_t *)fw_ddb_entry->ip_addr)) |
679 | ha->host_no, __func__)); | 740 | || ipv6_device)) { |
680 | } else { | ||
681 | qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0); | 741 | qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0); |
682 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, | 742 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, |
683 | NULL, 0, NULL, &next_fw_ddb_index, | 743 | NULL, 0, NULL, |
684 | &ddb_state, &conn_err, NULL, NULL) | 744 | &next_fw_ddb_index, |
685 | == QLA_ERROR) { | 745 | &ddb_state, &conn_err, |
746 | NULL, NULL) | ||
747 | == QLA_ERROR) { | ||
686 | DEBUG2(printk("scsi%ld: %s:" | 748 | DEBUG2(printk("scsi%ld: %s:" |
687 | "get_ddb_entry %d failed\n", | 749 | "get_ddb_entry %d failed\n", |
688 | ha->host_no, | 750 | ha->host_no, |
@@ -737,7 +799,6 @@ next_one: | |||
737 | struct qla4_relog_scan { | 799 | struct qla4_relog_scan { |
738 | int halt_wait; | 800 | int halt_wait; |
739 | uint32_t conn_err; | 801 | uint32_t conn_err; |
740 | uint32_t err_code; | ||
741 | uint32_t fw_ddb_index; | 802 | uint32_t fw_ddb_index; |
742 | uint32_t next_fw_ddb_index; | 803 | uint32_t next_fw_ddb_index; |
743 | uint32_t fw_ddb_device_state; | 804 | 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 | { | 808 | { |
748 | struct ddb_entry *ddb_entry; | 809 | struct ddb_entry *ddb_entry; |
749 | 810 | ||
750 | /* | 811 | if (qla4_is_relogin_allowed(ha, rs->conn_err)) { |
751 | * Don't want to do a relogin if connection | ||
752 | * error is 0x1c. | ||
753 | */ | ||
754 | rs->err_code = ((rs->conn_err & 0x00ff0000) >> 16); | ||
755 | if (rs->err_code == 0x1c || rs->err_code == 0x06) { | ||
756 | DEBUG2(printk( | ||
757 | "scsi%ld: %s send target" | ||
758 | " completed or " | ||
759 | "access denied failure\n", | ||
760 | ha->host_no, __func__)); | ||
761 | } else { | ||
762 | /* We either have a device that is in | 812 | /* We either have a device that is in |
763 | * the process of relogging in or a | 813 | * the process of relogging in or a |
764 | * device that is waiting to be | 814 | * device that is waiting to be |
@@ -1411,8 +1461,8 @@ static void qla4xxx_add_device_dynamically(struct scsi_qla_host *ha, | |||
1411 | * | 1461 | * |
1412 | * This routine processes a Decive Database Changed AEN Event. | 1462 | * This routine processes a Decive Database Changed AEN Event. |
1413 | **/ | 1463 | **/ |
1414 | int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, | 1464 | int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, |
1415 | uint32_t fw_ddb_index, uint32_t state) | 1465 | uint32_t state, uint32_t conn_err) |
1416 | { | 1466 | { |
1417 | struct ddb_entry * ddb_entry; | 1467 | struct ddb_entry * ddb_entry; |
1418 | uint32_t old_fw_ddb_device_state; | 1468 | uint32_t old_fw_ddb_device_state; |
@@ -1470,13 +1520,13 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, | |||
1470 | 1520 | ||
1471 | /* | 1521 | /* |
1472 | * Relogin if device state changed to a not active state. | 1522 | * Relogin if device state changed to a not active state. |
1473 | * However, do not relogin if this aen is a result of an IOCTL | 1523 | * However, do not relogin if a RELOGIN is in process, or |
1474 | * logout (DF_NO_RELOGIN) or if this is a discovered device. | 1524 | * we are not allowed to relogin to this DDB. |
1475 | */ | 1525 | */ |
1476 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED && | 1526 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED && |
1477 | !test_bit(DF_RELOGIN, &ddb_entry->flags) && | 1527 | !test_bit(DF_RELOGIN, &ddb_entry->flags) && |
1478 | !test_bit(DF_NO_RELOGIN, &ddb_entry->flags) && | 1528 | !test_bit(DF_NO_RELOGIN, &ddb_entry->flags) && |
1479 | !test_bit(DF_ISNS_DISCOVERED, &ddb_entry->flags)) { | 1529 | qla4_is_relogin_allowed(ha, conn_err)) { |
1480 | /* | 1530 | /* |
1481 | * This triggers a relogin. After the relogin_timer | 1531 | * This triggers a relogin. After the relogin_timer |
1482 | * expires, the relogin gets scheduled. We must wait a | 1532 | * expires, the relogin gets scheduled. We must wait a |
@@ -1484,7 +1534,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, | |||
1484 | * with failed device_state or a logout response before | 1534 | * with failed device_state or a logout response before |
1485 | * we can issue another relogin. | 1535 | * we can issue another relogin. |
1486 | */ | 1536 | */ |
1487 | /* Firmware padds this timeout: (time2wait +1). | 1537 | /* Firmware pads this timeout: (time2wait +1). |
1488 | * Driver retry to login should be longer than F/W. | 1538 | * Driver retry to login should be longer than F/W. |
1489 | * Otherwise F/W will fail | 1539 | * Otherwise F/W will fail |
1490 | * set_ddb() mbx cmd with 0x4005 since it still | 1540 | * set_ddb() mbx cmd with 0x4005 since it still |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 9db286df7ca0..ce5838eb685e 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -838,7 +838,7 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen) | |||
838 | qla4xxx_reinitialize_ddb_list(ha); | 838 | qla4xxx_reinitialize_ddb_list(ha); |
839 | } else if (mbox_sts[1] == 1) { /* Specific device. */ | 839 | } else if (mbox_sts[1] == 1) { /* Specific device. */ |
840 | qla4xxx_process_ddb_changed(ha, mbox_sts[2], | 840 | qla4xxx_process_ddb_changed(ha, mbox_sts[2], |
841 | mbox_sts[3]); | 841 | mbox_sts[3], mbox_sts[4]); |
842 | } | 842 | } |
843 | break; | 843 | break; |
844 | } | 844 | } |