diff options
author | Vikas Chaudhary <vikas.chaudhary@qlogic.com> | 2011-07-25 14:48:41 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-08-27 10:36:02 -0400 |
commit | ed1086e041b4870313dd0c0755f4bbc3b62d0d08 (patch) | |
tree | 255b9e0a5dc611246dbbc4322b1b571533f4d8b6 /drivers/scsi/qla4xxx | |
parent | 8d07913dbe79568eafe5bb73806a08aac294d4e6 (diff) |
[SCSI] qla4xxx: added support to show multiple iface in sysfs
Add support for default ipv4 and ipv6 ifaces in qla4xxx.
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Reviewed-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Reviewed-by: Harish Zunjarrao <harish.zunjarrao@qlogic.com>
[make iface creation dynamic]
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla4xxx')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 3 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 177 |
2 files changed, 176 insertions, 4 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 015d0a18bf8a..12db99280e04 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -588,6 +588,9 @@ struct scsi_qla_host { | |||
588 | struct completion mbx_intr_comp; | 588 | struct completion mbx_intr_comp; |
589 | 589 | ||
590 | struct ipaddress_config ip_config; | 590 | struct ipaddress_config ip_config; |
591 | struct iscsi_iface *iface_ipv4; | ||
592 | struct iscsi_iface *iface_ipv6_0; | ||
593 | struct iscsi_iface *iface_ipv6_1; | ||
591 | 594 | ||
592 | /* --- From About Firmware --- */ | 595 | /* --- From About Firmware --- */ |
593 | uint16_t iscsi_major; | 596 | uint16_t iscsi_major; |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 21e4f858d72b..32df0c5fc9cc 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -82,6 +82,9 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost, | |||
82 | enum iscsi_host_param param, char *buf); | 82 | enum iscsi_host_param param, char *buf); |
83 | static int qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data, | 83 | static int qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data, |
84 | int count); | 84 | int count); |
85 | static int qla4xxx_get_iface_param(struct iscsi_iface *iface, | ||
86 | enum iscsi_param_type param_type, | ||
87 | int param, char *buf); | ||
85 | static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session); | 88 | static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session); |
86 | static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc); | 89 | static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc); |
87 | 90 | ||
@@ -140,16 +143,99 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { | |||
140 | .host_param_mask = ISCSI_HOST_HWADDRESS | | 143 | .host_param_mask = ISCSI_HOST_HWADDRESS | |
141 | ISCSI_HOST_IPADDRESS | | 144 | ISCSI_HOST_IPADDRESS | |
142 | ISCSI_HOST_INITIATOR_NAME, | 145 | ISCSI_HOST_INITIATOR_NAME, |
146 | .iface_param_mask = ISCSI_NET_IPV4_ADDR | | ||
147 | ISCSI_NET_IPV4_SUBNET | | ||
148 | ISCSI_NET_IPV4_GW | | ||
149 | ISCSI_NET_IPV4_BOOTPROTO | | ||
150 | ISCSI_NET_IFACE_ENABLE | | ||
151 | ISCSI_NET_IPV6_LINKLOCAL | | ||
152 | ISCSI_NET_IPV6_ADDR | | ||
153 | ISCSI_NET_IPV6_ROUTER | | ||
154 | ISCSI_NET_IPV6_ADDR_AUTOCFG | | ||
155 | ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG | | ||
156 | ISCSI_NET_IFACE_ENABLE, | ||
143 | .tgt_dscvr = qla4xxx_tgt_dscvr, | 157 | .tgt_dscvr = qla4xxx_tgt_dscvr, |
144 | .get_conn_param = qla4xxx_conn_get_param, | 158 | .get_conn_param = qla4xxx_conn_get_param, |
145 | .get_session_param = qla4xxx_sess_get_param, | 159 | .get_session_param = qla4xxx_sess_get_param, |
146 | .get_host_param = qla4xxx_host_get_param, | 160 | .get_host_param = qla4xxx_host_get_param, |
147 | .set_iface_param = qla4xxx_iface_set_param, | 161 | .set_iface_param = qla4xxx_iface_set_param, |
148 | .session_recovery_timedout = qla4xxx_recovery_timedout, | 162 | .session_recovery_timedout = qla4xxx_recovery_timedout, |
163 | .get_iface_param = qla4xxx_get_iface_param, | ||
149 | }; | 164 | }; |
150 | 165 | ||
151 | static struct scsi_transport_template *qla4xxx_scsi_transport; | 166 | static struct scsi_transport_template *qla4xxx_scsi_transport; |
152 | 167 | ||
168 | static int qla4xxx_get_iface_param(struct iscsi_iface *iface, | ||
169 | enum iscsi_param_type param_type, | ||
170 | int param, char *buf) | ||
171 | { | ||
172 | struct Scsi_Host *shost = iscsi_iface_to_shost(iface); | ||
173 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
174 | int len = -ENOSYS; | ||
175 | |||
176 | if (param_type != ISCSI_NET_PARAM) | ||
177 | return -ENOSYS; | ||
178 | |||
179 | switch (param) { | ||
180 | case ISCSI_NET_PARAM_IPV4_ADDR: | ||
181 | len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address); | ||
182 | break; | ||
183 | case ISCSI_NET_PARAM_IPV4_SUBNET: | ||
184 | len = sprintf(buf, "%pI4\n", &ha->ip_config.subnet_mask); | ||
185 | break; | ||
186 | case ISCSI_NET_PARAM_IPV4_GW: | ||
187 | len = sprintf(buf, "%pI4\n", &ha->ip_config.gateway); | ||
188 | break; | ||
189 | case ISCSI_NET_PARAM_IFACE_ENABLE: | ||
190 | if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) | ||
191 | len = sprintf(buf, "%s\n", | ||
192 | (ha->ip_config.ipv4_options & | ||
193 | IPOPT_IPV4_PROTOCOL_ENABLE) ? | ||
194 | "enabled" : "disabled"); | ||
195 | else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) | ||
196 | len = sprintf(buf, "%s\n", | ||
197 | (ha->ip_config.ipv6_options & | ||
198 | IPV6_OPT_IPV6_PROTOCOL_ENABLE) ? | ||
199 | "enabled" : "disabled"); | ||
200 | break; | ||
201 | case ISCSI_NET_PARAM_IPV4_BOOTPROTO: | ||
202 | len = sprintf(buf, "%s\n", | ||
203 | (ha->ip_config.tcp_options & TCPOPT_DHCP_ENABLE) ? | ||
204 | "dhcp" : "static"); | ||
205 | break; | ||
206 | case ISCSI_NET_PARAM_IPV6_ADDR: | ||
207 | if (iface->iface_num == 0) | ||
208 | len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr0); | ||
209 | if (iface->iface_num == 1) | ||
210 | len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr1); | ||
211 | break; | ||
212 | case ISCSI_NET_PARAM_IPV6_LINKLOCAL: | ||
213 | len = sprintf(buf, "%pI6\n", | ||
214 | &ha->ip_config.ipv6_link_local_addr); | ||
215 | break; | ||
216 | case ISCSI_NET_PARAM_IPV6_ROUTER: | ||
217 | len = sprintf(buf, "%pI6\n", | ||
218 | &ha->ip_config.ipv6_default_router_addr); | ||
219 | break; | ||
220 | case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG: | ||
221 | len = sprintf(buf, "%s\n", | ||
222 | (ha->ip_config.ipv6_addl_options & | ||
223 | IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) ? | ||
224 | "nd" : "static"); | ||
225 | break; | ||
226 | case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG: | ||
227 | len = sprintf(buf, "%s\n", | ||
228 | (ha->ip_config.ipv6_addl_options & | ||
229 | IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR) ? | ||
230 | "auto" : "static"); | ||
231 | break; | ||
232 | default: | ||
233 | len = -ENOSYS; | ||
234 | } | ||
235 | |||
236 | return len; | ||
237 | } | ||
238 | |||
153 | static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc) | 239 | static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc) |
154 | { | 240 | { |
155 | struct iscsi_cls_session *session; | 241 | struct iscsi_cls_session *session; |
@@ -203,6 +289,78 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost, | |||
203 | return len; | 289 | return len; |
204 | } | 290 | } |
205 | 291 | ||
292 | static void qla4xxx_create_ipv4_iface(struct scsi_qla_host *ha) | ||
293 | { | ||
294 | if (ha->iface_ipv4) | ||
295 | return; | ||
296 | |||
297 | /* IPv4 */ | ||
298 | ha->iface_ipv4 = iscsi_create_iface(ha->host, | ||
299 | &qla4xxx_iscsi_transport, | ||
300 | ISCSI_IFACE_TYPE_IPV4, 0, 0); | ||
301 | if (!ha->iface_ipv4) | ||
302 | ql4_printk(KERN_ERR, ha, "Could not create IPv4 iSCSI " | ||
303 | "iface0.\n"); | ||
304 | } | ||
305 | |||
306 | static void qla4xxx_create_ipv6_iface(struct scsi_qla_host *ha) | ||
307 | { | ||
308 | if (!ha->iface_ipv6_0) | ||
309 | /* IPv6 iface-0 */ | ||
310 | ha->iface_ipv6_0 = iscsi_create_iface(ha->host, | ||
311 | &qla4xxx_iscsi_transport, | ||
312 | ISCSI_IFACE_TYPE_IPV6, 0, | ||
313 | 0); | ||
314 | if (!ha->iface_ipv6_0) | ||
315 | ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI " | ||
316 | "iface0.\n"); | ||
317 | |||
318 | if (!ha->iface_ipv6_1) | ||
319 | /* IPv6 iface-1 */ | ||
320 | ha->iface_ipv6_1 = iscsi_create_iface(ha->host, | ||
321 | &qla4xxx_iscsi_transport, | ||
322 | ISCSI_IFACE_TYPE_IPV6, 1, | ||
323 | 0); | ||
324 | if (!ha->iface_ipv6_1) | ||
325 | ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI " | ||
326 | "iface1.\n"); | ||
327 | } | ||
328 | |||
329 | static void qla4xxx_create_ifaces(struct scsi_qla_host *ha) | ||
330 | { | ||
331 | if (ha->ip_config.ipv4_options & IPOPT_IPV4_PROTOCOL_ENABLE) | ||
332 | qla4xxx_create_ipv4_iface(ha); | ||
333 | |||
334 | if (ha->ip_config.ipv6_options & IPV6_OPT_IPV6_PROTOCOL_ENABLE) | ||
335 | qla4xxx_create_ipv6_iface(ha); | ||
336 | } | ||
337 | |||
338 | static void qla4xxx_destroy_ipv4_iface(struct scsi_qla_host *ha) | ||
339 | { | ||
340 | if (ha->iface_ipv4) { | ||
341 | iscsi_destroy_iface(ha->iface_ipv4); | ||
342 | ha->iface_ipv4 = NULL; | ||
343 | } | ||
344 | } | ||
345 | |||
346 | static void qla4xxx_destroy_ipv6_iface(struct scsi_qla_host *ha) | ||
347 | { | ||
348 | if (ha->iface_ipv6_0) { | ||
349 | iscsi_destroy_iface(ha->iface_ipv6_0); | ||
350 | ha->iface_ipv6_0 = NULL; | ||
351 | } | ||
352 | if (ha->iface_ipv6_1) { | ||
353 | iscsi_destroy_iface(ha->iface_ipv6_1); | ||
354 | ha->iface_ipv6_1 = NULL; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | static void qla4xxx_destroy_ifaces(struct scsi_qla_host *ha) | ||
359 | { | ||
360 | qla4xxx_destroy_ipv4_iface(ha); | ||
361 | qla4xxx_destroy_ipv6_iface(ha); | ||
362 | } | ||
363 | |||
206 | static void qla4xxx_set_ipv6(struct scsi_qla_host *ha, | 364 | static void qla4xxx_set_ipv6(struct scsi_qla_host *ha, |
207 | struct iscsi_iface_param_info *iface_param, | 365 | struct iscsi_iface_param_info *iface_param, |
208 | struct addr_ctrl_blk *init_fw_cb) | 366 | struct addr_ctrl_blk *init_fw_cb) |
@@ -278,13 +436,16 @@ static void qla4xxx_set_ipv6(struct scsi_qla_host *ha, | |||
278 | sizeof(init_fw_cb->ipv6_dflt_rtr_addr)); | 436 | sizeof(init_fw_cb->ipv6_dflt_rtr_addr)); |
279 | break; | 437 | break; |
280 | case ISCSI_NET_PARAM_IFACE_ENABLE: | 438 | case ISCSI_NET_PARAM_IFACE_ENABLE: |
281 | if (iface_param->value[0] == ISCSI_IFACE_ENABLE) | 439 | if (iface_param->value[0] == ISCSI_IFACE_ENABLE) { |
282 | init_fw_cb->ipv6_opts |= | 440 | init_fw_cb->ipv6_opts |= |
283 | cpu_to_le16(IPV6_OPT_IPV6_PROTOCOL_ENABLE); | 441 | cpu_to_le16(IPV6_OPT_IPV6_PROTOCOL_ENABLE); |
284 | else | 442 | qla4xxx_create_ipv6_iface(ha); |
443 | } else { | ||
285 | init_fw_cb->ipv6_opts &= | 444 | init_fw_cb->ipv6_opts &= |
286 | cpu_to_le16(~IPV6_OPT_IPV6_PROTOCOL_ENABLE & | 445 | cpu_to_le16(~IPV6_OPT_IPV6_PROTOCOL_ENABLE & |
287 | 0xFFFF); | 446 | 0xFFFF); |
447 | qla4xxx_destroy_ipv6_iface(ha); | ||
448 | } | ||
288 | break; | 449 | break; |
289 | case ISCSI_NET_PARAM_VLAN_ID: | 450 | case ISCSI_NET_PARAM_VLAN_ID: |
290 | if (iface_param->len != sizeof(init_fw_cb->ipv6_vlan_tag)) | 451 | if (iface_param->len != sizeof(init_fw_cb->ipv6_vlan_tag)) |
@@ -326,13 +487,16 @@ static void qla4xxx_set_ipv4(struct scsi_qla_host *ha, | |||
326 | ql4_printk(KERN_ERR, ha, "Invalid IPv4 bootproto\n"); | 487 | ql4_printk(KERN_ERR, ha, "Invalid IPv4 bootproto\n"); |
327 | break; | 488 | break; |
328 | case ISCSI_NET_PARAM_IFACE_ENABLE: | 489 | case ISCSI_NET_PARAM_IFACE_ENABLE: |
329 | if (iface_param->value[0] == ISCSI_IFACE_ENABLE) | 490 | if (iface_param->value[0] == ISCSI_IFACE_ENABLE) { |
330 | init_fw_cb->ipv4_ip_opts |= | 491 | init_fw_cb->ipv4_ip_opts |= |
331 | cpu_to_le16(IPOPT_IPV4_PROTOCOL_ENABLE); | 492 | cpu_to_le16(IPOPT_IPV4_PROTOCOL_ENABLE); |
332 | else | 493 | qla4xxx_create_ipv4_iface(ha); |
494 | } else { | ||
333 | init_fw_cb->ipv4_ip_opts &= | 495 | init_fw_cb->ipv4_ip_opts &= |
334 | cpu_to_le16(~IPOPT_IPV4_PROTOCOL_ENABLE & | 496 | cpu_to_le16(~IPOPT_IPV4_PROTOCOL_ENABLE & |
335 | 0xFFFF); | 497 | 0xFFFF); |
498 | qla4xxx_destroy_ipv4_iface(ha); | ||
499 | } | ||
336 | break; | 500 | break; |
337 | case ISCSI_NET_PARAM_VLAN_ID: | 501 | case ISCSI_NET_PARAM_VLAN_ID: |
338 | if (iface_param->len != sizeof(init_fw_cb->ipv4_vlan_tag)) | 502 | if (iface_param->len != sizeof(init_fw_cb->ipv4_vlan_tag)) |
@@ -2081,6 +2245,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
2081 | ha->host_no, ha->firmware_version[0], ha->firmware_version[1], | 2245 | ha->host_no, ha->firmware_version[0], ha->firmware_version[1], |
2082 | ha->patch_number, ha->build_number); | 2246 | ha->patch_number, ha->build_number); |
2083 | scsi_scan_host(host); | 2247 | scsi_scan_host(host); |
2248 | |||
2249 | qla4xxx_create_ifaces(ha); | ||
2084 | return 0; | 2250 | return 0; |
2085 | 2251 | ||
2086 | probe_failed: | 2252 | probe_failed: |
@@ -2150,6 +2316,9 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
2150 | /* remove devs from iscsi_sessions to scsi_devices */ | 2316 | /* remove devs from iscsi_sessions to scsi_devices */ |
2151 | qla4xxx_free_ddb_list(ha); | 2317 | qla4xxx_free_ddb_list(ha); |
2152 | 2318 | ||
2319 | /* destroy iface from sysfs */ | ||
2320 | qla4xxx_destroy_ifaces(ha); | ||
2321 | |||
2153 | scsi_remove_host(ha->host); | 2322 | scsi_remove_host(ha->host); |
2154 | 2323 | ||
2155 | qla4xxx_free_adapter(ha); | 2324 | qla4xxx_free_adapter(ha); |