diff options
author | Sarang Radke <sarang.radke@qlogic.com> | 2010-03-19 20:03:59 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-04-11 10:45:50 -0400 |
commit | 09ff701a177b116c6c15b6e501e58fbfb306b424 (patch) | |
tree | fd99933ea29dbc36fc6636f5278d237dbee89b96 /drivers | |
parent | 6e98016ca077c5c751167bfdb1a3a2a3bee581cf (diff) |
[SCSI] qla2xxx: Add APEX support.
Allows priority setting for FCP_CMNDs.
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.c | 163 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 7 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 59 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 9 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 168 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 47 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 69 |
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 | ||
38 | int | ||
39 | qla24xx_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 | |||
69 | static int | ||
70 | qla24xx_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 | } | ||
194 | exit_fcp_prio_cfg: | ||
195 | bsg_job->job_done(bsg_job); | ||
196 | return ret; | ||
197 | } | ||
38 | static int | 198 | static int |
39 | qla2x00_process_els(struct fc_bsg_job *bsg_job) | 199 | qla2x00_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 | ||
1278 | struct qla_flt_region { | 1282 | struct 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 | |||
1764 | struct 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 | |||
1789 | struct 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 | |||
328 | qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t); | 328 | qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t); |
329 | 329 | ||
330 | extern int qla2x00_get_data_rate(scsi_qla_host_t *); | 330 | extern int qla2x00_get_data_rate(scsi_qla_host_t *); |
331 | extern 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 *); | |||
384 | extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); | 387 | extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); |
385 | 388 | ||
386 | extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *); | 389 | extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *); |
390 | extern 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 *); | |||
430 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); | 434 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); |
431 | extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); | 435 | extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); |
432 | extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *); | 436 | extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *); |
433 | extern int qla2x00_echo_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *); | 437 | extern int qla2x00_echo_test(scsi_qla_host_t *, |
438 | struct msg_echo_lb *, uint16_t *); | ||
439 | extern int qla24xx_update_all_fcp_prio(scsi_qla_host_t *); | ||
440 | extern 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 | */ | ||
4933 | uint8_t | ||
4934 | qla24xx_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 | */ | ||
5026 | int | ||
5027 | qla24xx_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 | */ | ||
5063 | int | ||
5064 | qla24xx_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 | |||
3900 | int | ||
3901 | qla24xx_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]; | ||
759 | done: | 775 | done: |
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 | |||
2742 | int | ||
2743 | qla24xx_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; | ||
2783 | fail: | ||
2784 | vfree(ha->fcp_prio_cfg); | ||
2785 | ha->fcp_prio_cfg = NULL; | ||
2786 | return QLA_FUNCTION_FAILED; | ||
2787 | } | ||