aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_inline.h12
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c16
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c197
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);
84int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username, 84int 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);
86int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password,
87 uint16_t idx, int bidi);
86 88
87void qla4xxx_queue_iocb(struct scsi_qla_host *ha); 89void qla4xxx_queue_iocb(struct scsi_qla_host *ha);
88void qla4xxx_complete_iocb(struct scsi_qla_host *ha); 90void 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
86static 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
1533static 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 **/
1545int 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,
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)