aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c189
-rw-r--r--include/scsi/iscsi_if.h21
-rw-r--r--include/scsi/scsi_transport_iscsi.h26
3 files changed, 233 insertions, 3 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 212a8d84674..4d5e64f429e 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -270,6 +270,185 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
270} 270}
271EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint); 271EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
272 272
273/*
274 * Interface to display network param to sysfs
275 */
276
277static void iscsi_iface_release(struct device *dev)
278{
279 struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
280 struct device *parent = iface->dev.parent;
281
282 kfree(iface);
283 put_device(parent);
284}
285
286
287static struct class iscsi_iface_class = {
288 .name = "iscsi_iface",
289 .dev_release = iscsi_iface_release,
290};
291
292#define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store) \
293struct device_attribute dev_attr_##_prefix##_##_name = \
294 __ATTR(_name, _mode, _show, _store)
295
296/* iface attrs show */
297#define iscsi_iface_attr_show(type, name, param_type, param) \
298static ssize_t \
299show_##type##_##name(struct device *dev, struct device_attribute *attr, \
300 char *buf) \
301{ \
302 struct iscsi_iface *iface = iscsi_dev_to_iface(dev); \
303 struct iscsi_transport *t = iface->transport; \
304 return t->get_iface_param(iface, param_type, param, buf); \
305} \
306
307#define iscsi_iface_net_attr(type, name, param) \
308 iscsi_iface_attr_show(type, name, ISCSI_NET_PARAM, param) \
309static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
310
311/* generic read only ipvi4 attribute */
312iscsi_iface_net_attr(ipv4_iface, ipaddress, ISCSI_NET_PARAM_IPV4_ADDR);
313iscsi_iface_net_attr(ipv4_iface, gateway, ISCSI_NET_PARAM_IPV4_GW);
314iscsi_iface_net_attr(ipv4_iface, subnet, ISCSI_NET_PARAM_IPV4_SUBNET);
315iscsi_iface_net_attr(ipv4_iface, bootproto, ISCSI_NET_PARAM_IPV4_BOOTPROTO);
316
317/* generic read only ipv6 attribute */
318iscsi_iface_net_attr(ipv6_iface, ipaddress, ISCSI_NET_PARAM_IPV6_ADDR);
319iscsi_iface_net_attr(ipv6_iface, link_local_addr, ISCSI_NET_PARAM_IPV6_LINKLOCAL);
320iscsi_iface_net_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER);
321iscsi_iface_net_attr(ipv6_iface, ipaddr_autocfg,
322 ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG);
323iscsi_iface_net_attr(ipv6_iface, linklocal_autocfg,
324 ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG);
325
326/* common read only iface attribute */
327iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE);
328iscsi_iface_net_attr(iface, vlan, ISCSI_NET_PARAM_VLAN_ID);
329
330static mode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
331 struct attribute *attr, int i)
332{
333 struct device *dev = container_of(kobj, struct device, kobj);
334 struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
335 struct iscsi_transport *t = iface->transport;
336
337 if (attr == &dev_attr_iface_enabled.attr)
338 return (t->iface_param_mask & ISCSI_NET_IFACE_ENABLE) ?
339 S_IRUGO : 0;
340 else if (attr == &dev_attr_iface_vlan.attr)
341 return (t->iface_param_mask & ISCSI_NET_VLAN_ID) ? S_IRUGO : 0;
342
343 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
344 if (attr == &dev_attr_ipv4_iface_ipaddress.attr)
345 return (t->iface_param_mask & ISCSI_NET_IPV4_ADDR) ?
346 S_IRUGO : 0;
347 else if (attr == &dev_attr_ipv4_iface_gateway.attr)
348 return (t->iface_param_mask & ISCSI_NET_IPV4_GW) ?
349 S_IRUGO : 0;
350 else if (attr == &dev_attr_ipv4_iface_subnet.attr)
351 return (t->iface_param_mask & ISCSI_NET_IPV4_SUBNET) ?
352 S_IRUGO : 0;
353 else if (attr == &dev_attr_ipv4_iface_bootproto.attr)
354 return (t->iface_param_mask & ISCSI_NET_IPV4_BOOTPROTO) ?
355 S_IRUGO : 0;
356 } else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) {
357 if (attr == &dev_attr_ipv6_iface_ipaddress.attr)
358 return (t->iface_param_mask & ISCSI_NET_IPV6_ADDR) ?
359 S_IRUGO : 0;
360 else if (attr == &dev_attr_ipv6_iface_link_local_addr.attr)
361 return (t->iface_param_mask & ISCSI_NET_IPV6_LINKLOCAL) ?
362 S_IRUGO : 0;
363 else if (attr == &dev_attr_ipv6_iface_router_addr.attr)
364 return (t->iface_param_mask & ISCSI_NET_IPV6_ROUTER) ?
365 S_IRUGO : 0;
366 else if (attr == &dev_attr_ipv6_iface_ipaddr_autocfg.attr)
367 return (t->iface_param_mask & ISCSI_NET_IPV6_ADDR_AUTOCFG) ?
368 S_IRUGO : 0;
369 else if (attr == &dev_attr_ipv6_iface_linklocal_autocfg.attr)
370 return (t->iface_param_mask & ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG) ?
371 S_IRUGO : 0;
372 }
373
374 return 0;
375}
376
377static struct attribute *iscsi_iface_attrs[] = {
378 &dev_attr_iface_enabled.attr,
379 &dev_attr_iface_vlan.attr,
380 &dev_attr_ipv4_iface_ipaddress.attr,
381 &dev_attr_ipv4_iface_gateway.attr,
382 &dev_attr_ipv4_iface_subnet.attr,
383 &dev_attr_ipv4_iface_bootproto.attr,
384 &dev_attr_ipv6_iface_ipaddress.attr,
385 &dev_attr_ipv6_iface_link_local_addr.attr,
386 &dev_attr_ipv6_iface_router_addr.attr,
387 &dev_attr_ipv6_iface_ipaddr_autocfg.attr,
388 &dev_attr_ipv6_iface_linklocal_autocfg.attr,
389 NULL,
390};
391
392static struct attribute_group iscsi_iface_group = {
393 .attrs = iscsi_iface_attrs,
394 .is_visible = iscsi_iface_attr_is_visible,
395};
396
397struct iscsi_iface *
398iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
399 uint32_t iface_type, uint32_t iface_num, int dd_size)
400{
401 struct iscsi_iface *iface;
402 int err;
403
404 iface = kzalloc(sizeof(*iface) + dd_size, GFP_KERNEL);
405 if (!iface)
406 return NULL;
407
408 iface->transport = transport;
409 iface->iface_type = iface_type;
410 iface->iface_num = iface_num;
411 iface->dev.release = iscsi_iface_release;
412 iface->dev.class = &iscsi_iface_class;
413 /* parent reference released in iscsi_iface_release */
414 iface->dev.parent = get_device(&shost->shost_gendev);
415 if (iface_type == ISCSI_IFACE_TYPE_IPV4)
416 dev_set_name(&iface->dev, "ipv4-iface-%u-%u", shost->host_no,
417 iface_num);
418 else
419 dev_set_name(&iface->dev, "ipv6-iface-%u-%u", shost->host_no,
420 iface_num);
421
422 err = device_register(&iface->dev);
423 if (err)
424 goto free_iface;
425
426 err = sysfs_create_group(&iface->dev.kobj, &iscsi_iface_group);
427 if (err)
428 goto unreg_iface;
429
430 if (dd_size)
431 iface->dd_data = &iface[1];
432 return iface;
433
434unreg_iface:
435 device_unregister(&iface->dev);
436 return NULL;
437
438free_iface:
439 put_device(iface->dev.parent);
440 kfree(iface);
441 return NULL;
442}
443EXPORT_SYMBOL_GPL(iscsi_create_iface);
444
445void iscsi_destroy_iface(struct iscsi_iface *iface)
446{
447 sysfs_remove_group(&iface->dev.kobj, &iscsi_iface_group);
448 device_unregister(&iface->dev);
449}
450EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
451
273static int iscsi_setup_host(struct transport_container *tc, struct device *dev, 452static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
274 struct device *cdev) 453 struct device *cdev)
275{ 454{
@@ -2175,6 +2354,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
2175 2354
2176 BUG_ON(count > ISCSI_SESSION_ATTRS); 2355 BUG_ON(count > ISCSI_SESSION_ATTRS);
2177 priv->session_attrs[count] = NULL; 2356 priv->session_attrs[count] = NULL;
2357 count = 0;
2178 2358
2179 spin_lock_irqsave(&iscsi_transport_lock, flags); 2359 spin_lock_irqsave(&iscsi_transport_lock, flags);
2180 list_add(&priv->list, &iscsi_transports); 2360 list_add(&priv->list, &iscsi_transports);
@@ -2237,10 +2417,14 @@ static __init int iscsi_transport_init(void)
2237 if (err) 2417 if (err)
2238 goto unregister_transport_class; 2418 goto unregister_transport_class;
2239 2419
2240 err = transport_class_register(&iscsi_host_class); 2420 err = class_register(&iscsi_iface_class);
2241 if (err) 2421 if (err)
2242 goto unregister_endpoint_class; 2422 goto unregister_endpoint_class;
2243 2423
2424 err = transport_class_register(&iscsi_host_class);
2425 if (err)
2426 goto unregister_iface_class;
2427
2244 err = transport_class_register(&iscsi_connection_class); 2428 err = transport_class_register(&iscsi_connection_class);
2245 if (err) 2429 if (err)
2246 goto unregister_host_class; 2430 goto unregister_host_class;
@@ -2270,6 +2454,8 @@ unregister_conn_class:
2270 transport_class_unregister(&iscsi_connection_class); 2454 transport_class_unregister(&iscsi_connection_class);
2271unregister_host_class: 2455unregister_host_class:
2272 transport_class_unregister(&iscsi_host_class); 2456 transport_class_unregister(&iscsi_host_class);
2457unregister_iface_class:
2458 class_unregister(&iscsi_iface_class);
2273unregister_endpoint_class: 2459unregister_endpoint_class:
2274 class_unregister(&iscsi_endpoint_class); 2460 class_unregister(&iscsi_endpoint_class);
2275unregister_transport_class: 2461unregister_transport_class:
@@ -2285,6 +2471,7 @@ static void __exit iscsi_transport_exit(void)
2285 transport_class_unregister(&iscsi_session_class); 2471 transport_class_unregister(&iscsi_session_class);
2286 transport_class_unregister(&iscsi_host_class); 2472 transport_class_unregister(&iscsi_host_class);
2287 class_unregister(&iscsi_endpoint_class); 2473 class_unregister(&iscsi_endpoint_class);
2474 class_unregister(&iscsi_iface_class);
2288 class_unregister(&iscsi_transport_class); 2475 class_unregister(&iscsi_transport_class);
2289} 2476}
2290 2477
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index e93831e8787..a563753d578 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -296,10 +296,27 @@ enum iscsi_net_param {
296 ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG = 11, 296 ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG = 11,
297 ISCSI_NET_PARAM_IFACE_ENABLE = 12, 297 ISCSI_NET_PARAM_IFACE_ENABLE = 12,
298 ISCSI_NET_PARAM_VLAN_ID = 13, 298 ISCSI_NET_PARAM_VLAN_ID = 13,
299 ISCSI_NET_IFACE_TYPE = 14, 299 ISCSI_NET_PARAM_IFACE_TYPE = 14,
300 ISCSI_NET_IFACE_NAME = 15, 300 ISCSI_NET_PARAM_IFACE_NAME = 15,
301}; 301};
302 302
303#define ISCSI_NET_IPV4_ADDR (1ULL << ISCSI_NET_PARAM_IPV4_ADDR)
304#define ISCSI_NET_IPV4_SUBNET (1ULL << ISCSI_NET_PARAM_IPV4_SUBNET)
305#define ISCSI_NET_IPV4_GW (1ULL << ISCSI_NET_PARAM_IPV4_GW)
306#define ISCSI_NET_IPV4_BOOTPROTO (1ULL << ISCSI_NET_PARAM_IPV4_BOOTPROTO)
307#define ISCSI_NET_MAC (1ULL << ISCSI_NET_PARAM_MAC)
308#define ISCSI_NET_IPV6_LINKLOCAL (1ULL << ISCSI_NET_PARAM_IPV6_LINKLOCAL)
309#define ISCSI_NET_IPV6_ADDR (1ULL << ISCSI_NET_PARAM_IPV6_ADDR)
310#define ISCSI_NET_IPV6_ROUTER (1ULL << ISCSI_NET_PARAM_IPV6_ROUTER)
311#define ISCSI_NET_IPV6_ADDR_AUTOCFG \
312 (1ULL << ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG)
313#define ISCSI_NET_IPV6_LINKLOCAL_AUTOCFG \
314 (1ULL << ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG)
315#define ISCSI_NET_IPV6_ROUTER_AUTOCFG \
316 (1ULL << ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG)
317#define ISCSI_NET_IFACE_ENABLE (1ULL << ISCSI_NET_PARAM_IFACE_ENABLE)
318#define ISCSI_NET_VLAN_ID (1ULL << ISCSI_NET_PARAM_VLAN_ID)
319
303/* 320/*
304 * Common error codes 321 * Common error codes
305 */ 322 */
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 9fcce7cd367..e1f210a173a 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -37,6 +37,7 @@ struct iscsi_cls_conn;
37struct iscsi_conn; 37struct iscsi_conn;
38struct iscsi_task; 38struct iscsi_task;
39struct sockaddr; 39struct sockaddr;
40struct iscsi_iface;
40 41
41/** 42/**
42 * struct iscsi_transport - iSCSI Transport template 43 * struct iscsi_transport - iSCSI Transport template
@@ -87,6 +88,8 @@ struct iscsi_transport {
87 /* LLD sets this to indicate what values it can export to sysfs */ 88 /* LLD sets this to indicate what values it can export to sysfs */
88 uint64_t param_mask; 89 uint64_t param_mask;
89 uint64_t host_param_mask; 90 uint64_t host_param_mask;
91 uint64_t iface_param_mask;
92
90 struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep, 93 struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep,
91 uint16_t cmds_max, uint16_t qdepth, 94 uint16_t cmds_max, uint16_t qdepth,
92 uint32_t sn); 95 uint32_t sn);
@@ -138,6 +141,9 @@ struct iscsi_transport {
138 uint32_t enable, struct sockaddr *dst_addr); 141 uint32_t enable, struct sockaddr *dst_addr);
139 int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params); 142 int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
140 int (*set_iface_param) (struct Scsi_Host *shost, char *data, int count); 143 int (*set_iface_param) (struct Scsi_Host *shost, char *data, int count);
144 int (*get_iface_param) (struct iscsi_iface *iface,
145 enum iscsi_param_type param_type,
146 int param, char *buf);
141}; 147};
142 148
143/* 149/*
@@ -229,6 +235,20 @@ struct iscsi_endpoint {
229 struct iscsi_cls_conn *conn; 235 struct iscsi_cls_conn *conn;
230}; 236};
231 237
238struct iscsi_iface {
239 struct device dev;
240 struct iscsi_transport *transport;
241 uint32_t iface_type; /* IPv4 or IPv6 */
242 uint32_t iface_num; /* iface number, 0 - n */
243 void *dd_data; /* LLD private data */
244};
245
246#define iscsi_dev_to_iface(_dev) \
247 container_of(_dev, struct iscsi_iface, dev)
248
249#define iscsi_iface_to_shost(_iface) \
250 dev_to_shost(_iface->dev.parent)
251
232/* 252/*
233 * session and connection functions that can be used by HW iSCSI LLDs 253 * session and connection functions that can be used by HW iSCSI LLDs
234 */ 254 */
@@ -262,5 +282,11 @@ extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size);
262extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep); 282extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep);
263extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle); 283extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle);
264extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd); 284extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd);
285extern struct iscsi_iface *iscsi_create_iface(struct Scsi_Host *shost,
286 struct iscsi_transport *t,
287 uint32_t iface_type,
288 uint32_t iface_num, int dd_size);
289extern void iscsi_destroy_iface(struct iscsi_iface *iface);
290extern struct iscsi_iface *iscsi_lookup_iface(int handle);
265 291
266#endif 292#endif