diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 22:25:38 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 22:25:38 -0500 |
commit | 0d522ee7499e4abe7189b2f1728e838959b8ddde (patch) | |
tree | 094f60e8bdb0083b58a43a0decbca59443a66e39 /drivers/scsi/qla4xxx/ql4_os.c | |
parent | 5eea9be8b2478dbc2f9fb1cd6228a90e8dba804e (diff) | |
parent | 323f6226a816f0b01514d25fba5529e0e68636c3 (diff) |
Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull first round of SCSI updates from James Bottomley:
"This patch set is driver updates for qla4xxx, scsi_debug, pm80xx,
fcoe/libfc, eas2r, lpfc, be2iscsi and megaraid_sas plus some assorted
bug fixes and cleanups"
* tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (106 commits)
[SCSI] scsi_error: Escalate to LUN reset if abort fails
[SCSI] Add 'eh_deadline' to limit SCSI EH runtime
[SCSI] remove check for 'resetting'
[SCSI] dc395: Move 'last_reset' into internal host structure
[SCSI] tmscsim: Move 'last_reset' into host structure
[SCSI] advansys: Remove 'last_reset' references
[SCSI] dpt_i2o: return SCSI_MLQUEUE_HOST_BUSY when in reset
[SCSI] dpt_i2o: Remove DPTI_STATE_IOCTL
[SCSI] megaraid_sas: Fix synchronization problem between sysPD IO path and AEN path
[SCSI] lpfc: Fix typo on NULL assignment
[SCSI] scsi_dh_alua: ALUA handler attach should succeed while TPG is transitioning
[SCSI] scsi_dh_alua: ALUA check sense should retry device internal reset unit attention
[SCSI] esas2r: Cleanup snprinf formatting of firmware version
[SCSI] esas2r: Remove superfluous mask of pcie_cap_reg
[SCSI] esas2r: Fixes for big-endian platforms
[SCSI] esas2r: Directly call kernel functions for atomic bit operations
[SCSI] lpfc 8.3.43: Update lpfc version to driver version 8.3.43
[SCSI] lpfc 8.3.43: Fixed not processing task management IOCB response status
[SCSI] lpfc 8.3.43: Fixed spinlock hang.
[SCSI] lpfc 8.3.43: Fixed invalid Total_Data_Placed value received for els and ct command responses
...
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_os.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 471 |
1 files changed, 449 insertions, 22 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index f8a0a26a3cd4..6dc3e99b7f9c 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -149,6 +149,8 @@ static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num, | |||
149 | static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, | 149 | static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, |
150 | uint32_t *num_entries, char *buf); | 150 | uint32_t *num_entries, char *buf); |
151 | static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx); | 151 | static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx); |
152 | static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, | ||
153 | int len); | ||
152 | 154 | ||
153 | /* | 155 | /* |
154 | * SCSI host template entry points | 156 | * SCSI host template entry points |
@@ -252,6 +254,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { | |||
252 | .send_ping = qla4xxx_send_ping, | 254 | .send_ping = qla4xxx_send_ping, |
253 | .get_chap = qla4xxx_get_chap_list, | 255 | .get_chap = qla4xxx_get_chap_list, |
254 | .delete_chap = qla4xxx_delete_chap, | 256 | .delete_chap = qla4xxx_delete_chap, |
257 | .set_chap = qla4xxx_set_chap_entry, | ||
255 | .get_flashnode_param = qla4xxx_sysfs_ddb_get_param, | 258 | .get_flashnode_param = qla4xxx_sysfs_ddb_get_param, |
256 | .set_flashnode_param = qla4xxx_sysfs_ddb_set_param, | 259 | .set_flashnode_param = qla4xxx_sysfs_ddb_set_param, |
257 | .new_flashnode = qla4xxx_sysfs_ddb_add, | 260 | .new_flashnode = qla4xxx_sysfs_ddb_add, |
@@ -508,6 +511,95 @@ static umode_t qla4_attr_is_visible(int param_type, int param) | |||
508 | return 0; | 511 | return 0; |
509 | } | 512 | } |
510 | 513 | ||
514 | static int qla4xxx_get_chap_by_index(struct scsi_qla_host *ha, | ||
515 | int16_t chap_index, | ||
516 | struct ql4_chap_table **chap_entry) | ||
517 | { | ||
518 | int rval = QLA_ERROR; | ||
519 | int max_chap_entries; | ||
520 | |||
521 | if (!ha->chap_list) { | ||
522 | ql4_printk(KERN_ERR, ha, "CHAP table cache is empty!\n"); | ||
523 | rval = QLA_ERROR; | ||
524 | goto exit_get_chap; | ||
525 | } | ||
526 | |||
527 | if (is_qla80XX(ha)) | ||
528 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | ||
529 | sizeof(struct ql4_chap_table); | ||
530 | else | ||
531 | max_chap_entries = MAX_CHAP_ENTRIES_40XX; | ||
532 | |||
533 | if (chap_index > max_chap_entries) { | ||
534 | ql4_printk(KERN_ERR, ha, "Invalid Chap index\n"); | ||
535 | rval = QLA_ERROR; | ||
536 | goto exit_get_chap; | ||
537 | } | ||
538 | |||
539 | *chap_entry = (struct ql4_chap_table *)ha->chap_list + chap_index; | ||
540 | if ((*chap_entry)->cookie != | ||
541 | __constant_cpu_to_le16(CHAP_VALID_COOKIE)) { | ||
542 | rval = QLA_ERROR; | ||
543 | *chap_entry = NULL; | ||
544 | } else { | ||
545 | rval = QLA_SUCCESS; | ||
546 | } | ||
547 | |||
548 | exit_get_chap: | ||
549 | return rval; | ||
550 | } | ||
551 | |||
552 | /** | ||
553 | * qla4xxx_find_free_chap_index - Find the first free chap index | ||
554 | * @ha: pointer to adapter structure | ||
555 | * @chap_index: CHAP index to be returned | ||
556 | * | ||
557 | * Find the first free chap index available in the chap table | ||
558 | * | ||
559 | * Note: Caller should acquire the chap lock before getting here. | ||
560 | **/ | ||
561 | static int qla4xxx_find_free_chap_index(struct scsi_qla_host *ha, | ||
562 | uint16_t *chap_index) | ||
563 | { | ||
564 | int i, rval; | ||
565 | int free_index = -1; | ||
566 | int max_chap_entries = 0; | ||
567 | struct ql4_chap_table *chap_table; | ||
568 | |||
569 | if (is_qla80XX(ha)) | ||
570 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | ||
571 | sizeof(struct ql4_chap_table); | ||
572 | else | ||
573 | max_chap_entries = MAX_CHAP_ENTRIES_40XX; | ||
574 | |||
575 | if (!ha->chap_list) { | ||
576 | ql4_printk(KERN_ERR, ha, "CHAP table cache is empty!\n"); | ||
577 | rval = QLA_ERROR; | ||
578 | goto exit_find_chap; | ||
579 | } | ||
580 | |||
581 | for (i = 0; i < max_chap_entries; i++) { | ||
582 | chap_table = (struct ql4_chap_table *)ha->chap_list + i; | ||
583 | |||
584 | if ((chap_table->cookie != | ||
585 | __constant_cpu_to_le16(CHAP_VALID_COOKIE)) && | ||
586 | (i > MAX_RESRV_CHAP_IDX)) { | ||
587 | free_index = i; | ||
588 | break; | ||
589 | } | ||
590 | } | ||
591 | |||
592 | if (free_index != -1) { | ||
593 | *chap_index = free_index; | ||
594 | rval = QLA_SUCCESS; | ||
595 | } else { | ||
596 | rval = QLA_ERROR; | ||
597 | } | ||
598 | |||
599 | exit_find_chap: | ||
600 | return rval; | ||
601 | } | ||
602 | |||
511 | static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, | 603 | static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, |
512 | uint32_t *num_entries, char *buf) | 604 | uint32_t *num_entries, char *buf) |
513 | { | 605 | { |
@@ -691,6 +783,111 @@ exit_delete_chap: | |||
691 | return ret; | 783 | return ret; |
692 | } | 784 | } |
693 | 785 | ||
786 | /** | ||
787 | * qla4xxx_set_chap_entry - Make chap entry with given information | ||
788 | * @shost: pointer to host | ||
789 | * @data: chap info - credentials, index and type to make chap entry | ||
790 | * @len: length of data | ||
791 | * | ||
792 | * Add or update chap entry with the given information | ||
793 | **/ | ||
794 | static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, int len) | ||
795 | { | ||
796 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
797 | struct iscsi_chap_rec chap_rec; | ||
798 | struct ql4_chap_table *chap_entry = NULL; | ||
799 | struct iscsi_param_info *param_info; | ||
800 | struct nlattr *attr; | ||
801 | int max_chap_entries = 0; | ||
802 | int type; | ||
803 | int rem = len; | ||
804 | int rc = 0; | ||
805 | |||
806 | memset(&chap_rec, 0, sizeof(chap_rec)); | ||
807 | |||
808 | nla_for_each_attr(attr, data, len, rem) { | ||
809 | param_info = nla_data(attr); | ||
810 | |||
811 | switch (param_info->param) { | ||
812 | case ISCSI_CHAP_PARAM_INDEX: | ||
813 | chap_rec.chap_tbl_idx = *(uint16_t *)param_info->value; | ||
814 | break; | ||
815 | case ISCSI_CHAP_PARAM_CHAP_TYPE: | ||
816 | chap_rec.chap_type = param_info->value[0]; | ||
817 | break; | ||
818 | case ISCSI_CHAP_PARAM_USERNAME: | ||
819 | memcpy(chap_rec.username, param_info->value, | ||
820 | param_info->len); | ||
821 | break; | ||
822 | case ISCSI_CHAP_PARAM_PASSWORD: | ||
823 | memcpy(chap_rec.password, param_info->value, | ||
824 | param_info->len); | ||
825 | break; | ||
826 | case ISCSI_CHAP_PARAM_PASSWORD_LEN: | ||
827 | chap_rec.password_length = param_info->value[0]; | ||
828 | break; | ||
829 | default: | ||
830 | ql4_printk(KERN_ERR, ha, | ||
831 | "%s: No such sysfs attribute\n", __func__); | ||
832 | rc = -ENOSYS; | ||
833 | goto exit_set_chap; | ||
834 | }; | ||
835 | } | ||
836 | |||
837 | if (chap_rec.chap_type == CHAP_TYPE_IN) | ||
838 | type = BIDI_CHAP; | ||
839 | else | ||
840 | type = LOCAL_CHAP; | ||
841 | |||
842 | if (is_qla80XX(ha)) | ||
843 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | ||
844 | sizeof(struct ql4_chap_table); | ||
845 | else | ||
846 | max_chap_entries = MAX_CHAP_ENTRIES_40XX; | ||
847 | |||
848 | mutex_lock(&ha->chap_sem); | ||
849 | if (chap_rec.chap_tbl_idx < max_chap_entries) { | ||
850 | rc = qla4xxx_get_chap_by_index(ha, chap_rec.chap_tbl_idx, | ||
851 | &chap_entry); | ||
852 | if (!rc) { | ||
853 | if (!(type == qla4xxx_get_chap_type(chap_entry))) { | ||
854 | ql4_printk(KERN_INFO, ha, | ||
855 | "Type mismatch for CHAP entry %d\n", | ||
856 | chap_rec.chap_tbl_idx); | ||
857 | rc = -EINVAL; | ||
858 | goto exit_unlock_chap; | ||
859 | } | ||
860 | |||
861 | /* If chap index is in use then don't modify it */ | ||
862 | rc = qla4xxx_is_chap_active(shost, | ||
863 | chap_rec.chap_tbl_idx); | ||
864 | if (rc) { | ||
865 | ql4_printk(KERN_INFO, ha, | ||
866 | "CHAP entry %d is in use\n", | ||
867 | chap_rec.chap_tbl_idx); | ||
868 | rc = -EBUSY; | ||
869 | goto exit_unlock_chap; | ||
870 | } | ||
871 | } | ||
872 | } else { | ||
873 | rc = qla4xxx_find_free_chap_index(ha, &chap_rec.chap_tbl_idx); | ||
874 | if (rc) { | ||
875 | ql4_printk(KERN_INFO, ha, "CHAP entry not available\n"); | ||
876 | rc = -EBUSY; | ||
877 | goto exit_unlock_chap; | ||
878 | } | ||
879 | } | ||
880 | |||
881 | rc = qla4xxx_set_chap(ha, chap_rec.username, chap_rec.password, | ||
882 | chap_rec.chap_tbl_idx, type); | ||
883 | |||
884 | exit_unlock_chap: | ||
885 | mutex_unlock(&ha->chap_sem); | ||
886 | |||
887 | exit_set_chap: | ||
888 | return rc; | ||
889 | } | ||
890 | |||
694 | static int qla4xxx_get_iface_param(struct iscsi_iface *iface, | 891 | static int qla4xxx_get_iface_param(struct iscsi_iface *iface, |
695 | enum iscsi_param_type param_type, | 892 | enum iscsi_param_type param_type, |
696 | int param, char *buf) | 893 | int param, char *buf) |
@@ -1455,9 +1652,12 @@ static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess, | |||
1455 | struct iscsi_session *sess = cls_sess->dd_data; | 1652 | struct iscsi_session *sess = cls_sess->dd_data; |
1456 | struct ddb_entry *ddb_entry = sess->dd_data; | 1653 | struct ddb_entry *ddb_entry = sess->dd_data; |
1457 | struct scsi_qla_host *ha = ddb_entry->ha; | 1654 | struct scsi_qla_host *ha = ddb_entry->ha; |
1655 | struct iscsi_cls_conn *cls_conn = ddb_entry->conn; | ||
1656 | struct ql4_chap_table chap_tbl; | ||
1458 | int rval, len; | 1657 | int rval, len; |
1459 | uint16_t idx; | 1658 | uint16_t idx; |
1460 | 1659 | ||
1660 | memset(&chap_tbl, 0, sizeof(chap_tbl)); | ||
1461 | switch (param) { | 1661 | switch (param) { |
1462 | case ISCSI_PARAM_CHAP_IN_IDX: | 1662 | case ISCSI_PARAM_CHAP_IN_IDX: |
1463 | rval = qla4xxx_get_chap_index(ha, sess->username_in, | 1663 | rval = qla4xxx_get_chap_index(ha, sess->username_in, |
@@ -1469,14 +1669,46 @@ static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess, | |||
1469 | len = sprintf(buf, "%hu\n", idx); | 1669 | len = sprintf(buf, "%hu\n", idx); |
1470 | break; | 1670 | break; |
1471 | case ISCSI_PARAM_CHAP_OUT_IDX: | 1671 | case ISCSI_PARAM_CHAP_OUT_IDX: |
1472 | rval = qla4xxx_get_chap_index(ha, sess->username, | 1672 | if (ddb_entry->ddb_type == FLASH_DDB) { |
1473 | sess->password, LOCAL_CHAP, | 1673 | if (ddb_entry->chap_tbl_idx != INVALID_ENTRY) { |
1474 | &idx); | 1674 | idx = ddb_entry->chap_tbl_idx; |
1675 | rval = QLA_SUCCESS; | ||
1676 | } else { | ||
1677 | rval = QLA_ERROR; | ||
1678 | } | ||
1679 | } else { | ||
1680 | rval = qla4xxx_get_chap_index(ha, sess->username, | ||
1681 | sess->password, | ||
1682 | LOCAL_CHAP, &idx); | ||
1683 | } | ||
1475 | if (rval) | 1684 | if (rval) |
1476 | len = sprintf(buf, "\n"); | 1685 | len = sprintf(buf, "\n"); |
1477 | else | 1686 | else |
1478 | len = sprintf(buf, "%hu\n", idx); | 1687 | len = sprintf(buf, "%hu\n", idx); |
1479 | break; | 1688 | break; |
1689 | case ISCSI_PARAM_USERNAME: | ||
1690 | case ISCSI_PARAM_PASSWORD: | ||
1691 | /* First, populate session username and password for FLASH DDB, | ||
1692 | * if not already done. This happens when session login fails | ||
1693 | * for a FLASH DDB. | ||
1694 | */ | ||
1695 | if (ddb_entry->ddb_type == FLASH_DDB && | ||
1696 | ddb_entry->chap_tbl_idx != INVALID_ENTRY && | ||
1697 | !sess->username && !sess->password) { | ||
1698 | idx = ddb_entry->chap_tbl_idx; | ||
1699 | rval = qla4xxx_get_uni_chap_at_index(ha, chap_tbl.name, | ||
1700 | chap_tbl.secret, | ||
1701 | idx); | ||
1702 | if (!rval) { | ||
1703 | iscsi_set_param(cls_conn, ISCSI_PARAM_USERNAME, | ||
1704 | (char *)chap_tbl.name, | ||
1705 | strlen((char *)chap_tbl.name)); | ||
1706 | iscsi_set_param(cls_conn, ISCSI_PARAM_PASSWORD, | ||
1707 | (char *)chap_tbl.secret, | ||
1708 | chap_tbl.secret_len); | ||
1709 | } | ||
1710 | } | ||
1711 | /* allow fall-through */ | ||
1480 | default: | 1712 | default: |
1481 | return iscsi_session_get_param(cls_sess, param, buf); | 1713 | return iscsi_session_get_param(cls_sess, param, buf); |
1482 | } | 1714 | } |
@@ -2373,11 +2605,6 @@ static void qla4xxx_copy_to_sess_conn_params(struct iscsi_conn *conn, | |||
2373 | COPY_ISID(sess->isid, fw_ddb_entry->isid); | 2605 | COPY_ISID(sess->isid, fw_ddb_entry->isid); |
2374 | 2606 | ||
2375 | ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); | 2607 | ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); |
2376 | if (ddb_link < MAX_DDB_ENTRIES) | ||
2377 | sess->discovery_parent_idx = ddb_link; | ||
2378 | else | ||
2379 | sess->discovery_parent_idx = DDB_NO_LINK; | ||
2380 | |||
2381 | if (ddb_link == DDB_ISNS) | 2608 | if (ddb_link == DDB_ISNS) |
2382 | disc_parent = ISCSI_DISC_PARENT_ISNS; | 2609 | disc_parent = ISCSI_DISC_PARENT_ISNS; |
2383 | else if (ddb_link == DDB_NO_LINK) | 2610 | else if (ddb_link == DDB_NO_LINK) |
@@ -2402,6 +2629,7 @@ static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, | |||
2402 | int buflen = 0; | 2629 | int buflen = 0; |
2403 | struct iscsi_session *sess; | 2630 | struct iscsi_session *sess; |
2404 | struct ddb_entry *ddb_entry; | 2631 | struct ddb_entry *ddb_entry; |
2632 | struct ql4_chap_table chap_tbl; | ||
2405 | struct iscsi_conn *conn; | 2633 | struct iscsi_conn *conn; |
2406 | char ip_addr[DDB_IPADDR_LEN]; | 2634 | char ip_addr[DDB_IPADDR_LEN]; |
2407 | uint16_t options = 0; | 2635 | uint16_t options = 0; |
@@ -2409,6 +2637,7 @@ static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, | |||
2409 | sess = cls_sess->dd_data; | 2637 | sess = cls_sess->dd_data; |
2410 | ddb_entry = sess->dd_data; | 2638 | ddb_entry = sess->dd_data; |
2411 | conn = cls_conn->dd_data; | 2639 | conn = cls_conn->dd_data; |
2640 | memset(&chap_tbl, 0, sizeof(chap_tbl)); | ||
2412 | 2641 | ||
2413 | ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx); | 2642 | ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx); |
2414 | 2643 | ||
@@ -2435,6 +2664,19 @@ static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, | |||
2435 | (char *)fw_ddb_entry->iscsi_name, buflen); | 2664 | (char *)fw_ddb_entry->iscsi_name, buflen); |
2436 | iscsi_set_param(cls_conn, ISCSI_PARAM_INITIATOR_NAME, | 2665 | iscsi_set_param(cls_conn, ISCSI_PARAM_INITIATOR_NAME, |
2437 | (char *)ha->name_string, buflen); | 2666 | (char *)ha->name_string, buflen); |
2667 | |||
2668 | if (ddb_entry->chap_tbl_idx != INVALID_ENTRY) { | ||
2669 | if (!qla4xxx_get_uni_chap_at_index(ha, chap_tbl.name, | ||
2670 | chap_tbl.secret, | ||
2671 | ddb_entry->chap_tbl_idx)) { | ||
2672 | iscsi_set_param(cls_conn, ISCSI_PARAM_USERNAME, | ||
2673 | (char *)chap_tbl.name, | ||
2674 | strlen((char *)chap_tbl.name)); | ||
2675 | iscsi_set_param(cls_conn, ISCSI_PARAM_PASSWORD, | ||
2676 | (char *)chap_tbl.secret, | ||
2677 | chap_tbl.secret_len); | ||
2678 | } | ||
2679 | } | ||
2438 | } | 2680 | } |
2439 | 2681 | ||
2440 | void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha, | 2682 | void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha, |
@@ -4937,7 +5179,8 @@ static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha, | |||
4937 | } | 5179 | } |
4938 | 5180 | ||
4939 | static int qla4xxx_is_session_exists(struct scsi_qla_host *ha, | 5181 | static int qla4xxx_is_session_exists(struct scsi_qla_host *ha, |
4940 | struct dev_db_entry *fw_ddb_entry) | 5182 | struct dev_db_entry *fw_ddb_entry, |
5183 | uint32_t *index) | ||
4941 | { | 5184 | { |
4942 | struct ddb_entry *ddb_entry; | 5185 | struct ddb_entry *ddb_entry; |
4943 | struct ql4_tuple_ddb *fw_tddb = NULL; | 5186 | struct ql4_tuple_ddb *fw_tddb = NULL; |
@@ -4971,6 +5214,8 @@ static int qla4xxx_is_session_exists(struct scsi_qla_host *ha, | |||
4971 | qla4xxx_get_param_ddb(ddb_entry, tmp_tddb); | 5214 | qla4xxx_get_param_ddb(ddb_entry, tmp_tddb); |
4972 | if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, false)) { | 5215 | if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, false)) { |
4973 | ret = QLA_SUCCESS; /* found */ | 5216 | ret = QLA_SUCCESS; /* found */ |
5217 | if (index != NULL) | ||
5218 | *index = idx; | ||
4974 | goto exit_check; | 5219 | goto exit_check; |
4975 | } | 5220 | } |
4976 | } | 5221 | } |
@@ -5206,6 +5451,7 @@ static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha, | |||
5206 | ddb_entry->ha = ha; | 5451 | ddb_entry->ha = ha; |
5207 | ddb_entry->unblock_sess = qla4xxx_unblock_flash_ddb; | 5452 | ddb_entry->unblock_sess = qla4xxx_unblock_flash_ddb; |
5208 | ddb_entry->ddb_change = qla4xxx_flash_ddb_change; | 5453 | ddb_entry->ddb_change = qla4xxx_flash_ddb_change; |
5454 | ddb_entry->chap_tbl_idx = INVALID_ENTRY; | ||
5209 | 5455 | ||
5210 | atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); | 5456 | atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); |
5211 | atomic_set(&ddb_entry->relogin_timer, 0); | 5457 | atomic_set(&ddb_entry->relogin_timer, 0); |
@@ -5267,6 +5513,87 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha) | |||
5267 | } while (time_after(wtime, jiffies)); | 5513 | } while (time_after(wtime, jiffies)); |
5268 | } | 5514 | } |
5269 | 5515 | ||
5516 | static int qla4xxx_cmp_fw_stentry(struct dev_db_entry *fw_ddb_entry, | ||
5517 | struct dev_db_entry *flash_ddb_entry) | ||
5518 | { | ||
5519 | uint16_t options = 0; | ||
5520 | size_t ip_len = IP_ADDR_LEN; | ||
5521 | |||
5522 | options = le16_to_cpu(fw_ddb_entry->options); | ||
5523 | if (options & DDB_OPT_IPV6_DEVICE) | ||
5524 | ip_len = IPv6_ADDR_LEN; | ||
5525 | |||
5526 | if (memcmp(fw_ddb_entry->ip_addr, flash_ddb_entry->ip_addr, ip_len)) | ||
5527 | return QLA_ERROR; | ||
5528 | |||
5529 | if (memcmp(&fw_ddb_entry->isid[0], &flash_ddb_entry->isid[0], | ||
5530 | sizeof(fw_ddb_entry->isid))) | ||
5531 | return QLA_ERROR; | ||
5532 | |||
5533 | if (memcmp(&fw_ddb_entry->port, &flash_ddb_entry->port, | ||
5534 | sizeof(fw_ddb_entry->port))) | ||
5535 | return QLA_ERROR; | ||
5536 | |||
5537 | return QLA_SUCCESS; | ||
5538 | } | ||
5539 | |||
5540 | static int qla4xxx_find_flash_st_idx(struct scsi_qla_host *ha, | ||
5541 | struct dev_db_entry *fw_ddb_entry, | ||
5542 | uint32_t fw_idx, uint32_t *flash_index) | ||
5543 | { | ||
5544 | struct dev_db_entry *flash_ddb_entry; | ||
5545 | dma_addr_t flash_ddb_entry_dma; | ||
5546 | uint32_t idx = 0; | ||
5547 | int max_ddbs; | ||
5548 | int ret = QLA_ERROR, status; | ||
5549 | |||
5550 | max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : | ||
5551 | MAX_DEV_DB_ENTRIES; | ||
5552 | |||
5553 | flash_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | ||
5554 | &flash_ddb_entry_dma); | ||
5555 | if (flash_ddb_entry == NULL || fw_ddb_entry == NULL) { | ||
5556 | ql4_printk(KERN_ERR, ha, "Out of memory\n"); | ||
5557 | goto exit_find_st_idx; | ||
5558 | } | ||
5559 | |||
5560 | status = qla4xxx_flashdb_by_index(ha, flash_ddb_entry, | ||
5561 | flash_ddb_entry_dma, fw_idx); | ||
5562 | if (status == QLA_SUCCESS) { | ||
5563 | status = qla4xxx_cmp_fw_stentry(fw_ddb_entry, flash_ddb_entry); | ||
5564 | if (status == QLA_SUCCESS) { | ||
5565 | *flash_index = fw_idx; | ||
5566 | ret = QLA_SUCCESS; | ||
5567 | goto exit_find_st_idx; | ||
5568 | } | ||
5569 | } | ||
5570 | |||
5571 | for (idx = 0; idx < max_ddbs; idx++) { | ||
5572 | status = qla4xxx_flashdb_by_index(ha, flash_ddb_entry, | ||
5573 | flash_ddb_entry_dma, idx); | ||
5574 | if (status == QLA_ERROR) | ||
5575 | continue; | ||
5576 | |||
5577 | status = qla4xxx_cmp_fw_stentry(fw_ddb_entry, flash_ddb_entry); | ||
5578 | if (status == QLA_SUCCESS) { | ||
5579 | *flash_index = idx; | ||
5580 | ret = QLA_SUCCESS; | ||
5581 | goto exit_find_st_idx; | ||
5582 | } | ||
5583 | } | ||
5584 | |||
5585 | if (idx == max_ddbs) | ||
5586 | ql4_printk(KERN_ERR, ha, "Failed to find ST [%d] in flash\n", | ||
5587 | fw_idx); | ||
5588 | |||
5589 | exit_find_st_idx: | ||
5590 | if (flash_ddb_entry) | ||
5591 | dma_pool_free(ha->fw_ddb_dma_pool, flash_ddb_entry, | ||
5592 | flash_ddb_entry_dma); | ||
5593 | |||
5594 | return ret; | ||
5595 | } | ||
5596 | |||
5270 | static void qla4xxx_build_st_list(struct scsi_qla_host *ha, | 5597 | static void qla4xxx_build_st_list(struct scsi_qla_host *ha, |
5271 | struct list_head *list_st) | 5598 | struct list_head *list_st) |
5272 | { | 5599 | { |
@@ -5278,6 +5605,7 @@ static void qla4xxx_build_st_list(struct scsi_qla_host *ha, | |||
5278 | int ret; | 5605 | int ret; |
5279 | uint32_t idx = 0, next_idx = 0; | 5606 | uint32_t idx = 0, next_idx = 0; |
5280 | uint32_t state = 0, conn_err = 0; | 5607 | uint32_t state = 0, conn_err = 0; |
5608 | uint32_t flash_index = -1; | ||
5281 | uint16_t conn_id = 0; | 5609 | uint16_t conn_id = 0; |
5282 | 5610 | ||
5283 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | 5611 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, |
@@ -5310,6 +5638,19 @@ static void qla4xxx_build_st_list(struct scsi_qla_host *ha, | |||
5310 | if (!st_ddb_idx) | 5638 | if (!st_ddb_idx) |
5311 | break; | 5639 | break; |
5312 | 5640 | ||
5641 | ret = qla4xxx_find_flash_st_idx(ha, fw_ddb_entry, idx, | ||
5642 | &flash_index); | ||
5643 | if (ret == QLA_ERROR) { | ||
5644 | ql4_printk(KERN_ERR, ha, | ||
5645 | "No flash entry for ST at idx [%d]\n", idx); | ||
5646 | st_ddb_idx->flash_ddb_idx = idx; | ||
5647 | } else { | ||
5648 | ql4_printk(KERN_INFO, ha, | ||
5649 | "ST at idx [%d] is stored at flash [%d]\n", | ||
5650 | idx, flash_index); | ||
5651 | st_ddb_idx->flash_ddb_idx = flash_index; | ||
5652 | } | ||
5653 | |||
5313 | st_ddb_idx->fw_ddb_idx = idx; | 5654 | st_ddb_idx->fw_ddb_idx = idx; |
5314 | 5655 | ||
5315 | list_add_tail(&st_ddb_idx->list, list_st); | 5656 | list_add_tail(&st_ddb_idx->list, list_st); |
@@ -5354,6 +5695,28 @@ static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha, | |||
5354 | } | 5695 | } |
5355 | } | 5696 | } |
5356 | 5697 | ||
5698 | static void qla4xxx_update_sess_disc_idx(struct scsi_qla_host *ha, | ||
5699 | struct ddb_entry *ddb_entry, | ||
5700 | struct dev_db_entry *fw_ddb_entry) | ||
5701 | { | ||
5702 | struct iscsi_cls_session *cls_sess; | ||
5703 | struct iscsi_session *sess; | ||
5704 | uint32_t max_ddbs = 0; | ||
5705 | uint16_t ddb_link = -1; | ||
5706 | |||
5707 | max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : | ||
5708 | MAX_DEV_DB_ENTRIES; | ||
5709 | |||
5710 | cls_sess = ddb_entry->sess; | ||
5711 | sess = cls_sess->dd_data; | ||
5712 | |||
5713 | ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); | ||
5714 | if (ddb_link < max_ddbs) | ||
5715 | sess->discovery_parent_idx = ddb_link; | ||
5716 | else | ||
5717 | sess->discovery_parent_idx = DDB_NO_LINK; | ||
5718 | } | ||
5719 | |||
5357 | static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha, | 5720 | static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha, |
5358 | struct dev_db_entry *fw_ddb_entry, | 5721 | struct dev_db_entry *fw_ddb_entry, |
5359 | int is_reset, uint16_t idx) | 5722 | int is_reset, uint16_t idx) |
@@ -5418,6 +5781,7 @@ static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha, | |||
5418 | 5781 | ||
5419 | /* Update sess/conn params */ | 5782 | /* Update sess/conn params */ |
5420 | qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn); | 5783 | qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn); |
5784 | qla4xxx_update_sess_disc_idx(ha, ddb_entry, fw_ddb_entry); | ||
5421 | 5785 | ||
5422 | if (is_reset == RESET_ADAPTER) { | 5786 | if (is_reset == RESET_ADAPTER) { |
5423 | iscsi_block_session(cls_sess); | 5787 | iscsi_block_session(cls_sess); |
@@ -5434,17 +5798,43 @@ exit_setup: | |||
5434 | return ret; | 5798 | return ret; |
5435 | } | 5799 | } |
5436 | 5800 | ||
5801 | static void qla4xxx_update_fw_ddb_link(struct scsi_qla_host *ha, | ||
5802 | struct list_head *list_ddb, | ||
5803 | struct dev_db_entry *fw_ddb_entry) | ||
5804 | { | ||
5805 | struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; | ||
5806 | uint16_t ddb_link; | ||
5807 | |||
5808 | ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); | ||
5809 | |||
5810 | list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) { | ||
5811 | if (ddb_idx->fw_ddb_idx == ddb_link) { | ||
5812 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
5813 | "Updating NT parent idx from [%d] to [%d]\n", | ||
5814 | ddb_link, ddb_idx->flash_ddb_idx)); | ||
5815 | fw_ddb_entry->ddb_link = | ||
5816 | cpu_to_le16(ddb_idx->flash_ddb_idx); | ||
5817 | return; | ||
5818 | } | ||
5819 | } | ||
5820 | } | ||
5821 | |||
5437 | static void qla4xxx_build_nt_list(struct scsi_qla_host *ha, | 5822 | static void qla4xxx_build_nt_list(struct scsi_qla_host *ha, |
5438 | struct list_head *list_nt, int is_reset) | 5823 | struct list_head *list_nt, |
5824 | struct list_head *list_st, | ||
5825 | int is_reset) | ||
5439 | { | 5826 | { |
5440 | struct dev_db_entry *fw_ddb_entry; | 5827 | struct dev_db_entry *fw_ddb_entry; |
5828 | struct ddb_entry *ddb_entry = NULL; | ||
5441 | dma_addr_t fw_ddb_dma; | 5829 | dma_addr_t fw_ddb_dma; |
5442 | int max_ddbs; | 5830 | int max_ddbs; |
5443 | int fw_idx_size; | 5831 | int fw_idx_size; |
5444 | int ret; | 5832 | int ret; |
5445 | uint32_t idx = 0, next_idx = 0; | 5833 | uint32_t idx = 0, next_idx = 0; |
5446 | uint32_t state = 0, conn_err = 0; | 5834 | uint32_t state = 0, conn_err = 0; |
5835 | uint32_t ddb_idx = -1; | ||
5447 | uint16_t conn_id = 0; | 5836 | uint16_t conn_id = 0; |
5837 | uint16_t ddb_link = -1; | ||
5448 | struct qla_ddb_index *nt_ddb_idx; | 5838 | struct qla_ddb_index *nt_ddb_idx; |
5449 | 5839 | ||
5450 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | 5840 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, |
@@ -5471,12 +5861,18 @@ static void qla4xxx_build_nt_list(struct scsi_qla_host *ha, | |||
5471 | if (strlen((char *) fw_ddb_entry->iscsi_name) == 0) | 5861 | if (strlen((char *) fw_ddb_entry->iscsi_name) == 0) |
5472 | goto continue_next_nt; | 5862 | goto continue_next_nt; |
5473 | 5863 | ||
5864 | ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); | ||
5865 | if (ddb_link < max_ddbs) | ||
5866 | qla4xxx_update_fw_ddb_link(ha, list_st, fw_ddb_entry); | ||
5867 | |||
5474 | if (!(state == DDB_DS_NO_CONNECTION_ACTIVE || | 5868 | if (!(state == DDB_DS_NO_CONNECTION_ACTIVE || |
5475 | state == DDB_DS_SESSION_FAILED)) | 5869 | state == DDB_DS_SESSION_FAILED) && |
5870 | (is_reset == INIT_ADAPTER)) | ||
5476 | goto continue_next_nt; | 5871 | goto continue_next_nt; |
5477 | 5872 | ||
5478 | DEBUG2(ql4_printk(KERN_INFO, ha, | 5873 | DEBUG2(ql4_printk(KERN_INFO, ha, |
5479 | "Adding DDB to session = 0x%x\n", idx)); | 5874 | "Adding DDB to session = 0x%x\n", idx)); |
5875 | |||
5480 | if (is_reset == INIT_ADAPTER) { | 5876 | if (is_reset == INIT_ADAPTER) { |
5481 | nt_ddb_idx = vmalloc(fw_idx_size); | 5877 | nt_ddb_idx = vmalloc(fw_idx_size); |
5482 | if (!nt_ddb_idx) | 5878 | if (!nt_ddb_idx) |
@@ -5506,9 +5902,17 @@ static void qla4xxx_build_nt_list(struct scsi_qla_host *ha, | |||
5506 | 5902 | ||
5507 | list_add_tail(&nt_ddb_idx->list, list_nt); | 5903 | list_add_tail(&nt_ddb_idx->list, list_nt); |
5508 | } else if (is_reset == RESET_ADAPTER) { | 5904 | } else if (is_reset == RESET_ADAPTER) { |
5509 | if (qla4xxx_is_session_exists(ha, fw_ddb_entry) == | 5905 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry, |
5510 | QLA_SUCCESS) | 5906 | &ddb_idx); |
5907 | if (ret == QLA_SUCCESS) { | ||
5908 | ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, | ||
5909 | ddb_idx); | ||
5910 | if (ddb_entry != NULL) | ||
5911 | qla4xxx_update_sess_disc_idx(ha, | ||
5912 | ddb_entry, | ||
5913 | fw_ddb_entry); | ||
5511 | goto continue_next_nt; | 5914 | goto continue_next_nt; |
5915 | } | ||
5512 | } | 5916 | } |
5513 | 5917 | ||
5514 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset, idx); | 5918 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset, idx); |
@@ -5526,7 +5930,8 @@ exit_nt_list: | |||
5526 | } | 5930 | } |
5527 | 5931 | ||
5528 | static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha, | 5932 | static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha, |
5529 | struct list_head *list_nt) | 5933 | struct list_head *list_nt, |
5934 | uint16_t target_id) | ||
5530 | { | 5935 | { |
5531 | struct dev_db_entry *fw_ddb_entry; | 5936 | struct dev_db_entry *fw_ddb_entry; |
5532 | dma_addr_t fw_ddb_dma; | 5937 | dma_addr_t fw_ddb_dma; |
@@ -5571,13 +5976,16 @@ static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha, | |||
5571 | 5976 | ||
5572 | nt_ddb_idx->fw_ddb_idx = idx; | 5977 | nt_ddb_idx->fw_ddb_idx = idx; |
5573 | 5978 | ||
5574 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry); | 5979 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry, NULL); |
5575 | if (ret == QLA_SUCCESS) { | 5980 | if (ret == QLA_SUCCESS) { |
5576 | /* free nt_ddb_idx and do not add to list_nt */ | 5981 | /* free nt_ddb_idx and do not add to list_nt */ |
5577 | vfree(nt_ddb_idx); | 5982 | vfree(nt_ddb_idx); |
5578 | goto continue_next_new_nt; | 5983 | goto continue_next_new_nt; |
5579 | } | 5984 | } |
5580 | 5985 | ||
5986 | if (target_id < max_ddbs) | ||
5987 | fw_ddb_entry->ddb_link = cpu_to_le16(target_id); | ||
5988 | |||
5581 | list_add_tail(&nt_ddb_idx->list, list_nt); | 5989 | list_add_tail(&nt_ddb_idx->list, list_nt); |
5582 | 5990 | ||
5583 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, | 5991 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, |
@@ -5894,7 +6302,8 @@ exit_ddb_conn_open: | |||
5894 | } | 6302 | } |
5895 | 6303 | ||
5896 | static int qla4xxx_ddb_login_st(struct scsi_qla_host *ha, | 6304 | static int qla4xxx_ddb_login_st(struct scsi_qla_host *ha, |
5897 | struct dev_db_entry *fw_ddb_entry) | 6305 | struct dev_db_entry *fw_ddb_entry, |
6306 | uint16_t target_id) | ||
5898 | { | 6307 | { |
5899 | struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; | 6308 | struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; |
5900 | struct list_head list_nt; | 6309 | struct list_head list_nt; |
@@ -5919,7 +6328,7 @@ static int qla4xxx_ddb_login_st(struct scsi_qla_host *ha, | |||
5919 | if (ret == QLA_ERROR) | 6328 | if (ret == QLA_ERROR) |
5920 | goto exit_login_st; | 6329 | goto exit_login_st; |
5921 | 6330 | ||
5922 | qla4xxx_build_new_nt_list(ha, &list_nt); | 6331 | qla4xxx_build_new_nt_list(ha, &list_nt, target_id); |
5923 | 6332 | ||
5924 | list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, &list_nt, list) { | 6333 | list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, &list_nt, list) { |
5925 | list_del_init(&ddb_idx->list); | 6334 | list_del_init(&ddb_idx->list); |
@@ -5946,7 +6355,7 @@ static int qla4xxx_ddb_login_nt(struct scsi_qla_host *ha, | |||
5946 | { | 6355 | { |
5947 | int ret = QLA_ERROR; | 6356 | int ret = QLA_ERROR; |
5948 | 6357 | ||
5949 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry); | 6358 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry, NULL); |
5950 | if (ret != QLA_SUCCESS) | 6359 | if (ret != QLA_SUCCESS) |
5951 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, | 6360 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, |
5952 | idx); | 6361 | idx); |
@@ -6001,7 +6410,8 @@ static int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess, | |||
6001 | fw_ddb_entry->cookie = DDB_VALID_COOKIE; | 6410 | fw_ddb_entry->cookie = DDB_VALID_COOKIE; |
6002 | 6411 | ||
6003 | if (strlen((char *)fw_ddb_entry->iscsi_name) == 0) | 6412 | if (strlen((char *)fw_ddb_entry->iscsi_name) == 0) |
6004 | ret = qla4xxx_ddb_login_st(ha, fw_ddb_entry); | 6413 | ret = qla4xxx_ddb_login_st(ha, fw_ddb_entry, |
6414 | fnode_sess->target_id); | ||
6005 | else | 6415 | else |
6006 | ret = qla4xxx_ddb_login_nt(ha, fw_ddb_entry, | 6416 | ret = qla4xxx_ddb_login_nt(ha, fw_ddb_entry, |
6007 | fnode_sess->target_id); | 6417 | fnode_sess->target_id); |
@@ -6522,10 +6932,13 @@ qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, | |||
6522 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | 6932 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); |
6523 | struct scsi_qla_host *ha = to_qla_host(shost); | 6933 | struct scsi_qla_host *ha = to_qla_host(shost); |
6524 | struct iscsi_flashnode_param_info *fnode_param; | 6934 | struct iscsi_flashnode_param_info *fnode_param; |
6935 | struct ql4_chap_table chap_tbl; | ||
6525 | struct nlattr *attr; | 6936 | struct nlattr *attr; |
6937 | uint16_t chap_out_idx = INVALID_ENTRY; | ||
6526 | int rc = QLA_ERROR; | 6938 | int rc = QLA_ERROR; |
6527 | uint32_t rem = len; | 6939 | uint32_t rem = len; |
6528 | 6940 | ||
6941 | memset((void *)&chap_tbl, 0, sizeof(chap_tbl)); | ||
6529 | nla_for_each_attr(attr, data, len, rem) { | 6942 | nla_for_each_attr(attr, data, len, rem) { |
6530 | fnode_param = nla_data(attr); | 6943 | fnode_param = nla_data(attr); |
6531 | 6944 | ||
@@ -6567,6 +6980,10 @@ qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, | |||
6567 | break; | 6980 | break; |
6568 | case ISCSI_FLASHNODE_CHAP_AUTH_EN: | 6981 | case ISCSI_FLASHNODE_CHAP_AUTH_EN: |
6569 | fnode_sess->chap_auth_en = fnode_param->value[0]; | 6982 | fnode_sess->chap_auth_en = fnode_param->value[0]; |
6983 | /* Invalidate chap index if chap auth is disabled */ | ||
6984 | if (!fnode_sess->chap_auth_en) | ||
6985 | fnode_sess->chap_out_idx = INVALID_ENTRY; | ||
6986 | |||
6570 | break; | 6987 | break; |
6571 | case ISCSI_FLASHNODE_SNACK_REQ_EN: | 6988 | case ISCSI_FLASHNODE_SNACK_REQ_EN: |
6572 | fnode_conn->snack_req_en = fnode_param->value[0]; | 6989 | fnode_conn->snack_req_en = fnode_param->value[0]; |
@@ -6705,6 +7122,17 @@ qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, | |||
6705 | fnode_conn->exp_statsn = | 7122 | fnode_conn->exp_statsn = |
6706 | *(uint32_t *)fnode_param->value; | 7123 | *(uint32_t *)fnode_param->value; |
6707 | break; | 7124 | break; |
7125 | case ISCSI_FLASHNODE_CHAP_OUT_IDX: | ||
7126 | chap_out_idx = *(uint16_t *)fnode_param->value; | ||
7127 | if (!qla4xxx_get_uni_chap_at_index(ha, | ||
7128 | chap_tbl.name, | ||
7129 | chap_tbl.secret, | ||
7130 | chap_out_idx)) { | ||
7131 | fnode_sess->chap_out_idx = chap_out_idx; | ||
7132 | /* Enable chap auth if chap index is valid */ | ||
7133 | fnode_sess->chap_auth_en = QL4_PARAM_ENABLE; | ||
7134 | } | ||
7135 | break; | ||
6708 | default: | 7136 | default: |
6709 | ql4_printk(KERN_ERR, ha, | 7137 | ql4_printk(KERN_ERR, ha, |
6710 | "%s: No such sysfs attribute\n", __func__); | 7138 | "%s: No such sysfs attribute\n", __func__); |
@@ -6926,11 +7354,10 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset) | |||
6926 | schedule_timeout_uninterruptible(HZ / 10); | 7354 | schedule_timeout_uninterruptible(HZ / 10); |
6927 | } while (time_after(wtime, jiffies)); | 7355 | } while (time_after(wtime, jiffies)); |
6928 | 7356 | ||
6929 | /* Free up the sendtargets list */ | ||
6930 | qla4xxx_free_ddb_list(&list_st); | ||
6931 | 7357 | ||
6932 | qla4xxx_build_nt_list(ha, &list_nt, is_reset); | 7358 | qla4xxx_build_nt_list(ha, &list_nt, &list_st, is_reset); |
6933 | 7359 | ||
7360 | qla4xxx_free_ddb_list(&list_st); | ||
6934 | qla4xxx_free_ddb_list(&list_nt); | 7361 | qla4xxx_free_ddb_list(&list_nt); |
6935 | 7362 | ||
6936 | qla4xxx_free_ddb_index(ha); | 7363 | qla4xxx_free_ddb_index(ha); |