aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c163
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h7
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h59
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h9
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c168
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c47
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c69
7 files changed, 518 insertions, 4 deletions
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index c20292fde720..3c3a86ca6cbd 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -35,6 +35,166 @@ done:
35 return sp; 35 return sp;
36} 36}
37 37
38int
39qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
40{
41 int i, ret, num_valid;
42 uint8_t *bcode;
43 struct qla_fcp_prio_entry *pri_entry;
44
45 ret = 1;
46 num_valid = 0;
47 bcode = (uint8_t *)pri_cfg;
48
49 if (bcode[0x0] != 'H' || bcode[0x1] != 'Q' || bcode[0x2] != 'O' ||
50 bcode[0x3] != 'S') {
51 return 0;
52 }
53 if (flag != 1)
54 return ret;
55
56 pri_entry = &pri_cfg->entry[0];
57 for (i = 0; i < pri_cfg->num_entries; i++) {
58 if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
59 num_valid++;
60 pri_entry++;
61 }
62
63 if (num_valid == 0)
64 ret = 0;
65
66 return ret;
67}
68
69static int
70qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
71{
72 struct Scsi_Host *host = bsg_job->shost;
73 scsi_qla_host_t *vha = shost_priv(host);
74 struct qla_hw_data *ha = vha->hw;
75 int ret = 0;
76 uint32_t len;
77 uint32_t oper;
78
79 bsg_job->reply->reply_payload_rcv_len = 0;
80
81 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
82 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
83 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
84 ret = -EBUSY;
85 goto exit_fcp_prio_cfg;
86 }
87
88 /* Get the sub command */
89 oper = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
90
91 /* Only set config is allowed if config memory is not allocated */
92 if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) {
93 ret = -EINVAL;
94 goto exit_fcp_prio_cfg;
95 }
96 switch (oper) {
97 case QLFC_FCP_PRIO_DISABLE:
98 if (ha->flags.fcp_prio_enabled) {
99 ha->flags.fcp_prio_enabled = 0;
100 ha->fcp_prio_cfg->attributes &=
101 ~FCP_PRIO_ATTR_ENABLE;
102 qla24xx_update_all_fcp_prio(vha);
103 bsg_job->reply->result = DID_OK;
104 } else {
105 ret = -EINVAL;
106 bsg_job->reply->result = (DID_ERROR << 16);
107 goto exit_fcp_prio_cfg;
108 }
109 break;
110
111 case QLFC_FCP_PRIO_ENABLE:
112 if (!ha->flags.fcp_prio_enabled) {
113 if (ha->fcp_prio_cfg) {
114 ha->flags.fcp_prio_enabled = 1;
115 ha->fcp_prio_cfg->attributes |=
116 FCP_PRIO_ATTR_ENABLE;
117 qla24xx_update_all_fcp_prio(vha);
118 bsg_job->reply->result = DID_OK;
119 } else {
120 ret = -EINVAL;
121 bsg_job->reply->result = (DID_ERROR << 16);
122 goto exit_fcp_prio_cfg;
123 }
124 }
125 break;
126
127 case QLFC_FCP_PRIO_GET_CONFIG:
128 len = bsg_job->reply_payload.payload_len;
129 if (!len || len > FCP_PRIO_CFG_SIZE) {
130 ret = -EINVAL;
131 bsg_job->reply->result = (DID_ERROR << 16);
132 goto exit_fcp_prio_cfg;
133 }
134
135 bsg_job->reply->result = DID_OK;
136 bsg_job->reply->reply_payload_rcv_len =
137 sg_copy_from_buffer(
138 bsg_job->reply_payload.sg_list,
139 bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg,
140 len);
141
142 break;
143
144 case QLFC_FCP_PRIO_SET_CONFIG:
145 len = bsg_job->request_payload.payload_len;
146 if (!len || len > FCP_PRIO_CFG_SIZE) {
147 bsg_job->reply->result = (DID_ERROR << 16);
148 ret = -EINVAL;
149 goto exit_fcp_prio_cfg;
150 }
151
152 if (!ha->fcp_prio_cfg) {
153 ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
154 if (!ha->fcp_prio_cfg) {
155 qla_printk(KERN_WARNING, ha,
156 "Unable to allocate memory "
157 "for fcp prio config data (%x).\n",
158 FCP_PRIO_CFG_SIZE);
159 bsg_job->reply->result = (DID_ERROR << 16);
160 ret = -ENOMEM;
161 goto exit_fcp_prio_cfg;
162 }
163 }
164
165 memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
166 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
167 bsg_job->request_payload.sg_cnt, ha->fcp_prio_cfg,
168 FCP_PRIO_CFG_SIZE);
169
170 /* validate fcp priority data */
171 if (!qla24xx_fcp_prio_cfg_valid(
172 (struct qla_fcp_prio_cfg *)
173 ha->fcp_prio_cfg, 1)) {
174 bsg_job->reply->result = (DID_ERROR << 16);
175 ret = -EINVAL;
176 /* If buffer was invalidatic int
177 * fcp_prio_cfg is of no use
178 */
179 vfree(ha->fcp_prio_cfg);
180 ha->fcp_prio_cfg = NULL;
181 goto exit_fcp_prio_cfg;
182 }
183
184 ha->flags.fcp_prio_enabled = 0;
185 if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE)
186 ha->flags.fcp_prio_enabled = 1;
187 qla24xx_update_all_fcp_prio(vha);
188 bsg_job->reply->result = DID_OK;
189 break;
190 default:
191 ret = -EINVAL;
192 break;
193 }
194exit_fcp_prio_cfg:
195 bsg_job->job_done(bsg_job);
196 return ret;
197}
38static int 198static int
39qla2x00_process_els(struct fc_bsg_job *bsg_job) 199qla2x00_process_els(struct fc_bsg_job *bsg_job)
40{ 200{
@@ -948,6 +1108,9 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
948 case QL_VND_IIDMA: 1108 case QL_VND_IIDMA:
949 return qla24xx_iidma(bsg_job); 1109 return qla24xx_iidma(bsg_job);
950 1110
1111 case QL_VND_FCP_PRIO_CFG_CMD:
1112 return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job);
1113
951 default: 1114 default:
952 bsg_job->reply->result = (DID_ERROR << 16); 1115 bsg_job->reply->result = (DID_ERROR << 16);
953 bsg_job->job_done(bsg_job); 1116 bsg_job->job_done(bsg_job);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 608397bf7e0a..c51bd4e5fb44 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1580,6 +1580,8 @@ typedef struct fc_port {
1580 uint16_t loop_id; 1580 uint16_t loop_id;
1581 uint16_t old_loop_id; 1581 uint16_t old_loop_id;
1582 1582
1583 uint8_t fcp_prio;
1584
1583 uint8_t fabric_port_name[WWN_SIZE]; 1585 uint8_t fabric_port_name[WWN_SIZE];
1584 uint16_t fp_speed; 1586 uint16_t fp_speed;
1585 1587
@@ -2296,6 +2298,7 @@ struct qla_hw_data {
2296 uint32_t eeh_busy :1; 2298 uint32_t eeh_busy :1;
2297 uint32_t cpu_affinity_enabled :1; 2299 uint32_t cpu_affinity_enabled :1;
2298 uint32_t disable_msix_handshake :1; 2300 uint32_t disable_msix_handshake :1;
2301 uint32_t fcp_prio_enabled :1;
2299 } flags; 2302 } flags;
2300 2303
2301 /* This spinlock is used to protect "io transactions", you must 2304 /* This spinlock is used to protect "io transactions", you must
@@ -2599,6 +2602,7 @@ struct qla_hw_data {
2599 uint32_t flt_region_nvram; 2602 uint32_t flt_region_nvram;
2600 uint32_t flt_region_npiv_conf; 2603 uint32_t flt_region_npiv_conf;
2601 uint32_t flt_region_gold_fw; 2604 uint32_t flt_region_gold_fw;
2605 uint32_t flt_region_fcp_prio;
2602 2606
2603 /* Needed for BEACON */ 2607 /* Needed for BEACON */
2604 uint16_t beacon_blink_led; 2608 uint16_t beacon_blink_led;
@@ -2627,6 +2631,9 @@ struct qla_hw_data {
2627 struct isp_operations *isp_ops; 2631 struct isp_operations *isp_ops;
2628 struct workqueue_struct *wq; 2632 struct workqueue_struct *wq;
2629 struct qlfc_fw fw_buf; 2633 struct qlfc_fw fw_buf;
2634
2635 /* FCP_CMND priority support */
2636 struct qla_fcp_prio_cfg *fcp_prio_cfg;
2630}; 2637};
2631 2638
2632/* 2639/*
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 42c5587cc50c..a77a2471eaff 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -841,6 +841,8 @@ struct device_reg_24xx {
841#define FA_HW_EVENT_ENTRY_SIZE 4 841#define FA_HW_EVENT_ENTRY_SIZE 4
842#define FA_NPIV_CONF0_ADDR 0x5C000 842#define FA_NPIV_CONF0_ADDR 0x5C000
843#define FA_NPIV_CONF1_ADDR 0x5D000 843#define FA_NPIV_CONF1_ADDR 0x5D000
844#define FA_FCP_PRIO0_ADDR 0x10000
845#define FA_FCP_PRIO1_ADDR 0x12000
844 846
845/* 847/*
846 * Flash Error Log Event Codes. 848 * Flash Error Log Event Codes.
@@ -1274,6 +1276,8 @@ struct qla_flt_header {
1274#define FLT_REG_NPIV_CONF_0 0x29 1276#define FLT_REG_NPIV_CONF_0 0x29
1275#define FLT_REG_NPIV_CONF_1 0x2a 1277#define FLT_REG_NPIV_CONF_1 0x2a
1276#define FLT_REG_GOLD_FW 0x2f 1278#define FLT_REG_GOLD_FW 0x2f
1279#define FLT_REG_FCP_PRIO_0 0x87
1280#define FLT_REG_FCP_PRIO_1 0x88
1277 1281
1278struct qla_flt_region { 1282struct qla_flt_region {
1279 uint32_t code; 1283 uint32_t code;
@@ -1750,6 +1754,61 @@ struct ex_init_cb_81xx {
1750#define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000 1754#define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000
1751#define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000 1755#define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000
1752 1756
1757/* FCP priority config defines *************************************/
1758/* operations */
1759#define QLFC_FCP_PRIO_DISABLE 0x0
1760#define QLFC_FCP_PRIO_ENABLE 0x1
1761#define QLFC_FCP_PRIO_GET_CONFIG 0x2
1762#define QLFC_FCP_PRIO_SET_CONFIG 0x3
1763
1764struct qla_fcp_prio_entry {
1765 uint16_t flags; /* Describes parameter(s) in FCP */
1766 /* priority entry that are valid */
1767#define FCP_PRIO_ENTRY_VALID 0x1
1768#define FCP_PRIO_ENTRY_TAG_VALID 0x2
1769#define FCP_PRIO_ENTRY_SPID_VALID 0x4
1770#define FCP_PRIO_ENTRY_DPID_VALID 0x8
1771#define FCP_PRIO_ENTRY_LUNB_VALID 0x10
1772#define FCP_PRIO_ENTRY_LUNE_VALID 0x20
1773#define FCP_PRIO_ENTRY_SWWN_VALID 0x40
1774#define FCP_PRIO_ENTRY_DWWN_VALID 0x80
1775 uint8_t tag; /* Priority value */
1776 uint8_t reserved; /* Reserved for future use */
1777 uint32_t src_pid; /* Src port id. high order byte */
1778 /* unused; -1 (wild card) */
1779 uint32_t dst_pid; /* Src port id. high order byte */
1780 /* unused; -1 (wild card) */
1781 uint16_t lun_beg; /* 1st lun num of lun range. */
1782 /* -1 (wild card) */
1783 uint16_t lun_end; /* 2nd lun num of lun range. */
1784 /* -1 (wild card) */
1785 uint8_t src_wwpn[8]; /* Source WWPN: -1 (wild card) */
1786 uint8_t dst_wwpn[8]; /* Destination WWPN: -1 (wild card) */
1787};
1788
1789struct qla_fcp_prio_cfg {
1790 uint8_t signature[4]; /* "HQOS" signature of config data */
1791 uint16_t version; /* 1: Initial version */
1792 uint16_t length; /* config data size in num bytes */
1793 uint16_t checksum; /* config data bytes checksum */
1794 uint16_t num_entries; /* Number of entries */
1795 uint16_t size_of_entry; /* Size of each entry in num bytes */
1796 uint8_t attributes; /* enable/disable, persistence */
1797#define FCP_PRIO_ATTR_DISABLE 0x0
1798#define FCP_PRIO_ATTR_ENABLE 0x1
1799#define FCP_PRIO_ATTR_PERSIST 0x2
1800 uint8_t reserved; /* Reserved for future use */
1801#define FCP_PRIO_CFG_HDR_SIZE 0x10
1802 struct qla_fcp_prio_entry entry[1]; /* fcp priority entries */
1803#define FCP_PRIO_CFG_ENTRY_SIZE 0x20
1804};
1805
1806#define FCP_PRIO_CFG_SIZE (32*1024) /* fcp prio data per port*/
1807
1808/* 25XX Support ****************************************************/
1809#define FA_FCP_PRIO0_ADDR_25 0x3C000
1810#define FA_FCP_PRIO1_ADDR_25 0x3E000
1811
1753/* 81XX Flash locations -- occupies second 2MB region. */ 1812/* 81XX Flash locations -- occupies second 2MB region. */
1754#define FA_BOOT_CODE_ADDR_81 0x80000 1813#define FA_BOOT_CODE_ADDR_81 0x80000
1755#define FA_RISC_CODE_ADDR_81 0xA0000 1814#define FA_RISC_CODE_ADDR_81 0xA0000
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index c1f1736dcdad..5efd4c05c79b 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -328,6 +328,9 @@ extern int
328qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t); 328qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t);
329 329
330extern int qla2x00_get_data_rate(scsi_qla_host_t *); 330extern int qla2x00_get_data_rate(scsi_qla_host_t *);
331extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
332 uint16_t *);
333
331/* 334/*
332 * Global Function Prototypes in qla_isr.c source file. 335 * Global Function Prototypes in qla_isr.c source file.
333 */ 336 */
@@ -384,6 +387,7 @@ extern int qla2xxx_get_flash_info(scsi_qla_host_t *);
384extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); 387extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
385 388
386extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *); 389extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *);
390extern int qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *);
387 391
388/* 392/*
389 * Global Function Prototypes in qla_dbg.c source file. 393 * Global Function Prototypes in qla_dbg.c source file.
@@ -430,7 +434,10 @@ extern void qla2x00_init_host_attr(scsi_qla_host_t *);
430extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); 434extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
431extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); 435extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
432extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *); 436extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *);
433extern int qla2x00_echo_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *); 437extern int qla2x00_echo_test(scsi_qla_host_t *,
438 struct msg_echo_lb *, uint16_t *);
439extern int qla24xx_update_all_fcp_prio(scsi_qla_host_t *);
440extern int qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *, uint8_t);
434 441
435/* 442/*
436 * Global Function Prototypes in qla_dfs.c source file. 443 * Global Function Prototypes in qla_dfs.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 4229bb483c5e..e7fe11486bb8 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -349,6 +349,12 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
349 } 349 }
350 } 350 }
351 351
352 if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)) {
353 if (qla24xx_read_fcp_prio_cfg(vha))
354 qla_printk(KERN_ERR, ha,
355 "Unable to read FCP priority data.\n");
356 }
357
352 return (rval); 358 return (rval);
353} 359}
354 360
@@ -4905,3 +4911,165 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha)
4905 ha->fw_options[2] |= BIT_9; 4911 ha->fw_options[2] |= BIT_9;
4906 qla2x00_set_fw_options(vha, ha->fw_options); 4912 qla2x00_set_fw_options(vha, ha->fw_options);
4907} 4913}
4914
4915/*
4916 * qla24xx_get_fcp_prio
4917 * Gets the fcp cmd priority value for the logged in port.
4918 * Looks for a match of the port descriptors within
4919 * each of the fcp prio config entries. If a match is found,
4920 * the tag (priority) value is returned.
4921 *
4922 * Input:
4923 * ha = adapter block po
4924 * fcport = port structure pointer.
4925 *
4926 * Return:
4927 * non-zero (if found)
4928 * 0 (if not found)
4929 *
4930 * Context:
4931 * Kernel context
4932 */
4933uint8_t
4934qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
4935{
4936 int i, entries;
4937 uint8_t pid_match, wwn_match;
4938 uint8_t priority;
4939 uint32_t pid1, pid2;
4940 uint64_t wwn1, wwn2;
4941 struct qla_fcp_prio_entry *pri_entry;
4942 struct qla_hw_data *ha = vha->hw;
4943
4944 if (!ha->fcp_prio_cfg || !ha->flags.fcp_prio_enabled)
4945 return 0;
4946
4947 priority = 0;
4948 entries = ha->fcp_prio_cfg->num_entries;
4949 pri_entry = &ha->fcp_prio_cfg->entry[0];
4950
4951 for (i = 0; i < entries; i++) {
4952 pid_match = wwn_match = 0;
4953
4954 if (!(pri_entry->flags & FCP_PRIO_ENTRY_VALID)) {
4955 pri_entry++;
4956 continue;
4957 }
4958
4959 /* check source pid for a match */
4960 if (pri_entry->flags & FCP_PRIO_ENTRY_SPID_VALID) {
4961 pid1 = pri_entry->src_pid & INVALID_PORT_ID;
4962 pid2 = vha->d_id.b24 & INVALID_PORT_ID;
4963 if (pid1 == INVALID_PORT_ID)
4964 pid_match++;
4965 else if (pid1 == pid2)
4966 pid_match++;
4967 }
4968
4969 /* check destination pid for a match */
4970 if (pri_entry->flags & FCP_PRIO_ENTRY_DPID_VALID) {
4971 pid1 = pri_entry->dst_pid & INVALID_PORT_ID;
4972 pid2 = fcport->d_id.b24 & INVALID_PORT_ID;
4973 if (pid1 == INVALID_PORT_ID)
4974 pid_match++;
4975 else if (pid1 == pid2)
4976 pid_match++;
4977 }
4978
4979 /* check source WWN for a match */
4980 if (pri_entry->flags & FCP_PRIO_ENTRY_SWWN_VALID) {
4981 wwn1 = wwn_to_u64(vha->port_name);
4982 wwn2 = wwn_to_u64(pri_entry->src_wwpn);
4983 if (wwn2 == (uint64_t)-1)
4984 wwn_match++;
4985 else if (wwn1 == wwn2)
4986 wwn_match++;
4987 }
4988
4989 /* check destination WWN for a match */
4990 if (pri_entry->flags & FCP_PRIO_ENTRY_DWWN_VALID) {
4991 wwn1 = wwn_to_u64(fcport->port_name);
4992 wwn2 = wwn_to_u64(pri_entry->dst_wwpn);
4993 if (wwn2 == (uint64_t)-1)
4994 wwn_match++;
4995 else if (wwn1 == wwn2)
4996 wwn_match++;
4997 }
4998
4999 if (pid_match == 2 || wwn_match == 2) {
5000 /* Found a matching entry */
5001 if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
5002 priority = pri_entry->tag;
5003 break;
5004 }
5005
5006 pri_entry++;
5007 }
5008
5009 return priority;
5010}
5011
5012/*
5013 * qla24xx_update_fcport_fcp_prio
5014 * Activates fcp priority for the logged in fc port
5015 *
5016 * Input:
5017 * ha = adapter block pointer.
5018 * fcp = port structure pointer.
5019 *
5020 * Return:
5021 * QLA_SUCCESS or QLA_FUNCTION_FAILED
5022 *
5023 * Context:
5024 * Kernel context.
5025 */
5026int
5027qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *ha, fc_port_t *fcport)
5028{
5029 int ret;
5030 uint8_t priority;
5031 uint16_t mb[5];
5032
5033 if (atomic_read(&fcport->state) == FCS_UNCONFIGURED ||
5034 fcport->port_type != FCT_TARGET ||
5035 fcport->loop_id == FC_NO_LOOP_ID)
5036 return QLA_FUNCTION_FAILED;
5037
5038 priority = qla24xx_get_fcp_prio(ha, fcport);
5039 ret = qla24xx_set_fcp_prio(ha, fcport->loop_id, priority, mb);
5040 if (ret == QLA_SUCCESS)
5041 fcport->fcp_prio = priority;
5042 else
5043 DEBUG2(printk(KERN_WARNING
5044 "scsi(%ld): Unable to activate fcp priority, "
5045 " ret=0x%x\n", ha->host_no, ret));
5046
5047 return ret;
5048}
5049
5050/*
5051 * qla24xx_update_all_fcp_prio
5052 * Activates fcp priority for all the logged in ports
5053 *
5054 * Input:
5055 * ha = adapter block pointer.
5056 *
5057 * Return:
5058 * QLA_SUCCESS or QLA_FUNCTION_FAILED
5059 *
5060 * Context:
5061 * Kernel context.
5062 */
5063int
5064qla24xx_update_all_fcp_prio(scsi_qla_host_t *vha)
5065{
5066 int ret;
5067 fc_port_t *fcport;
5068
5069 ret = QLA_FUNCTION_FAILED;
5070 /* We need to set priority for all logged in ports */
5071 list_for_each_entry(fcport, &vha->vp_fcports, list)
5072 ret = qla24xx_update_fcport_fcp_prio(vha, fcport);
5073
5074 return ret;
5075}
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 7f3bc45d2e20..e9c9f82c1d87 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3896,3 +3896,50 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
3896 3896
3897 return rval; 3897 return rval;
3898} 3898}
3899
3900int
3901qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
3902 uint16_t *mb)
3903{
3904 int rval;
3905 mbx_cmd_t mc;
3906 mbx_cmd_t *mcp = &mc;
3907 struct qla_hw_data *ha = vha->hw;
3908
3909 if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
3910 return QLA_FUNCTION_FAILED;
3911
3912 DEBUG11(printk(KERN_INFO
3913 "%s(%ld): entered.\n", __func__, ha->host_no));
3914
3915 mcp->mb[0] = MBC_PORT_PARAMS;
3916 mcp->mb[1] = loop_id;
3917 if (ha->flags.fcp_prio_enabled)
3918 mcp->mb[2] = BIT_1;
3919 else
3920 mcp->mb[2] = BIT_2;
3921 mcp->mb[4] = priority & 0xf;
3922 mcp->mb[9] = vha->vp_idx;
3923 mcp->out_mb = MBX_9|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3924 mcp->in_mb = MBX_4|MBX_3|MBX_1|MBX_0;
3925 mcp->tov = 30;
3926 mcp->flags = 0;
3927 rval = qla2x00_mailbox_command(vha, mcp);
3928 if (mb != NULL) {
3929 mb[0] = mcp->mb[0];
3930 mb[1] = mcp->mb[1];
3931 mb[3] = mcp->mb[3];
3932 mb[4] = mcp->mb[4];
3933 }
3934
3935 if (rval != QLA_SUCCESS) {
3936 DEBUG2_3_11(printk(KERN_WARNING
3937 "%s(%ld): failed=%x.\n", __func__,
3938 vha->host_no, rval));
3939 } else {
3940 DEBUG11(printk(KERN_INFO
3941 "%s(%ld): done.\n", __func__, vha->host_no));
3942 }
3943
3944 return rval;
3945}
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 8b3de4e54c28..f32a4b032967 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -648,6 +648,12 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
648 const uint32_t def_npiv_conf1[] = 648 const uint32_t def_npiv_conf1[] =
649 { FA_NPIV_CONF1_ADDR_24, FA_NPIV_CONF1_ADDR, 649 { FA_NPIV_CONF1_ADDR_24, FA_NPIV_CONF1_ADDR,
650 FA_NPIV_CONF1_ADDR_81 }; 650 FA_NPIV_CONF1_ADDR_81 };
651 const uint32_t fcp_prio_cfg0[] =
652 { FA_FCP_PRIO0_ADDR, FA_FCP_PRIO0_ADDR_25,
653 0 };
654 const uint32_t fcp_prio_cfg1[] =
655 { FA_FCP_PRIO1_ADDR, FA_FCP_PRIO1_ADDR_25,
656 0 };
651 uint32_t def; 657 uint32_t def;
652 uint16_t *wptr; 658 uint16_t *wptr;
653 uint16_t cnt, chksum; 659 uint16_t cnt, chksum;
@@ -732,6 +738,14 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
732 case FLT_REG_GOLD_FW: 738 case FLT_REG_GOLD_FW:
733 ha->flt_region_gold_fw = start; 739 ha->flt_region_gold_fw = start;
734 break; 740 break;
741 case FLT_REG_FCP_PRIO_0:
742 if (!(PCI_FUNC(ha->pdev->devfn) & 1))
743 ha->flt_region_fcp_prio = start;
744 break;
745 case FLT_REG_FCP_PRIO_1:
746 if (PCI_FUNC(ha->pdev->devfn) & 1)
747 ha->flt_region_fcp_prio = start;
748 break;
735 } 749 }
736 } 750 }
737 goto done; 751 goto done;
@@ -750,12 +764,14 @@ no_flash_data:
750 ha->flt_region_boot = def_boot[def]; 764 ha->flt_region_boot = def_boot[def];
751 ha->flt_region_vpd_nvram = def_vpd_nvram[def]; 765 ha->flt_region_vpd_nvram = def_vpd_nvram[def];
752 ha->flt_region_vpd = ha->flags.port0 ? 766 ha->flt_region_vpd = ha->flags.port0 ?
753 def_vpd0[def]: def_vpd1[def]; 767 def_vpd0[def] : def_vpd1[def];
754 ha->flt_region_nvram = ha->flags.port0 ? 768 ha->flt_region_nvram = ha->flags.port0 ?
755 def_nvram0[def]: def_nvram1[def]; 769 def_nvram0[def] : def_nvram1[def];
756 ha->flt_region_fdt = def_fdt[def]; 770 ha->flt_region_fdt = def_fdt[def];
757 ha->flt_region_npiv_conf = ha->flags.port0 ? 771 ha->flt_region_npiv_conf = ha->flags.port0 ?
758 def_npiv_conf0[def]: def_npiv_conf1[def]; 772 def_npiv_conf0[def] : def_npiv_conf1[def];
773 ha->flt_region_fcp_prio = ha->flags.port0 ?
774 fcp_prio_cfg0[def] : fcp_prio_cfg1[def];
759done: 775done:
760 DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x " 776 DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
761 "vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x " 777 "vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x "
@@ -2722,3 +2738,50 @@ qla2xxx_get_vpd_field(scsi_qla_host_t *vha, char *key, char *str, size_t size)
2722 2738
2723 return 0; 2739 return 0;
2724} 2740}
2741
2742int
2743qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
2744{
2745 int len, max_len;
2746 uint32_t fcp_prio_addr;
2747 struct qla_hw_data *ha = vha->hw;
2748
2749 if (!ha->fcp_prio_cfg) {
2750 ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
2751 if (!ha->fcp_prio_cfg) {
2752 qla_printk(KERN_WARNING, ha,
2753 "Unable to allocate memory for fcp priority data "
2754 "(%x).\n", FCP_PRIO_CFG_SIZE);
2755 return QLA_FUNCTION_FAILED;
2756 }
2757 }
2758 memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
2759
2760 fcp_prio_addr = ha->flt_region_fcp_prio;
2761
2762 /* first read the fcp priority data header from flash */
2763 ha->isp_ops->read_optrom(vha, (uint8_t *)ha->fcp_prio_cfg,
2764 fcp_prio_addr << 2, FCP_PRIO_CFG_HDR_SIZE);
2765
2766 if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 0))
2767 goto fail;
2768
2769 /* read remaining FCP CMD config data from flash */
2770 fcp_prio_addr += (FCP_PRIO_CFG_HDR_SIZE >> 2);
2771 len = ha->fcp_prio_cfg->num_entries * FCP_PRIO_CFG_ENTRY_SIZE;
2772 max_len = FCP_PRIO_CFG_SIZE - FCP_PRIO_CFG_HDR_SIZE;
2773
2774 ha->isp_ops->read_optrom(vha, (uint8_t *)&ha->fcp_prio_cfg->entry[0],
2775 fcp_prio_addr << 2, (len < max_len ? len : max_len));
2776
2777 /* revalidate the entire FCP priority config data, including entries */
2778 if (!qla24xx_fcp_prio_cfg_valid(ha->fcp_prio_cfg, 1))
2779 goto fail;
2780
2781 ha->flags.fcp_prio_enabled = 1;
2782 return QLA_SUCCESS;
2783fail:
2784 vfree(ha->fcp_prio_cfg);
2785 ha->fcp_prio_cfg = NULL;
2786 return QLA_FUNCTION_FAILED;
2787}