diff options
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_inline.h | 12 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 16 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 197 |
4 files changed, 225 insertions, 2 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index e6f2a2669dbd..5cef2527180a 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -83,6 +83,8 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
83 | uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts); | 83 | uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts); |
84 | int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username, | 84 | int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username, |
85 | char *password, int bidi, uint16_t *chap_index); | 85 | char *password, int bidi, uint16_t *chap_index); |
86 | int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password, | ||
87 | uint16_t idx, int bidi); | ||
86 | 88 | ||
87 | void qla4xxx_queue_iocb(struct scsi_qla_host *ha); | 89 | void qla4xxx_queue_iocb(struct scsi_qla_host *ha); |
88 | void qla4xxx_complete_iocb(struct scsi_qla_host *ha); | 90 | void qla4xxx_complete_iocb(struct scsi_qla_host *ha); |
diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h index 8503ad643bdd..655b7bb644d9 100644 --- a/drivers/scsi/qla4xxx/ql4_inline.h +++ b/drivers/scsi/qla4xxx/ql4_inline.h | |||
@@ -82,3 +82,15 @@ qla4xxx_disable_intrs(struct scsi_qla_host *ha) | |||
82 | __qla4xxx_disable_intrs(ha); | 82 | __qla4xxx_disable_intrs(ha); |
83 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 83 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
84 | } | 84 | } |
85 | |||
86 | static inline int qla4xxx_get_chap_type(struct ql4_chap_table *chap_entry) | ||
87 | { | ||
88 | int type; | ||
89 | |||
90 | if (chap_entry->flags & BIT_7) | ||
91 | type = LOCAL_CHAP; | ||
92 | else | ||
93 | type = BIDI_CHAP; | ||
94 | |||
95 | return type; | ||
96 | } | ||
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 121be4298d4c..22cbd005bdf4 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -1530,8 +1530,20 @@ exit_get_chap: | |||
1530 | return ret; | 1530 | return ret; |
1531 | } | 1531 | } |
1532 | 1532 | ||
1533 | static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, | 1533 | /** |
1534 | char *password, uint16_t idx, int bidi) | 1534 | * qla4xxx_set_chap - Make a chap entry at the given index |
1535 | * @ha: pointer to adapter structure | ||
1536 | * @username: CHAP username to set | ||
1537 | * @password: CHAP password to set | ||
1538 | * @idx: CHAP index at which to make the entry | ||
1539 | * @bidi: type of chap entry (chap_in or chap_out) | ||
1540 | * | ||
1541 | * Create chap entry at the given index with the information provided. | ||
1542 | * | ||
1543 | * Note: Caller should acquire the chap lock before getting here. | ||
1544 | **/ | ||
1545 | int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password, | ||
1546 | uint16_t idx, int bidi) | ||
1535 | { | 1547 | { |
1536 | int ret = 0; | 1548 | int ret = 0; |
1537 | int rval = QLA_ERROR; | 1549 | int rval = QLA_ERROR; |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 45478807dabb..933c7668531b 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) |