aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx/ql4_os.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-13 22:25:38 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-13 22:25:38 -0500
commit0d522ee7499e4abe7189b2f1728e838959b8ddde (patch)
tree094f60e8bdb0083b58a43a0decbca59443a66e39 /drivers/scsi/qla4xxx/ql4_os.c
parent5eea9be8b2478dbc2f9fb1cd6228a90e8dba804e (diff)
parent323f6226a816f0b01514d25fba5529e0e68636c3 (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.c471
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,
149static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, 149static 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);
151static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx); 151static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx);
152static 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
514static 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
548exit_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 **/
561static 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
599exit_find_chap:
600 return rval;
601}
602
511static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, 603static 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 **/
794static 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
884exit_unlock_chap:
885 mutex_unlock(&ha->chap_sem);
886
887exit_set_chap:
888 return rc;
889}
890
694static int qla4xxx_get_iface_param(struct iscsi_iface *iface, 891static 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
2440void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha, 2682void 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
4939static int qla4xxx_is_session_exists(struct scsi_qla_host *ha, 5181static 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
5516static 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
5540static 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
5589exit_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
5270static void qla4xxx_build_st_list(struct scsi_qla_host *ha, 5597static 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
5698static 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
5357static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha, 5720static 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
5801static 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
5437static void qla4xxx_build_nt_list(struct scsi_qla_host *ha, 5822static 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
5528static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha, 5932static 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
5896static int qla4xxx_ddb_login_st(struct scsi_qla_host *ha, 6304static 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);