aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_fc.c
diff options
context:
space:
mode:
authorJames Bottomley <jejb@sparkweed.localdomain>2006-09-23 16:33:43 -0400
committerJames Bottomley <jejb@sparkweed.localdomain>2006-09-23 16:33:43 -0400
commitc9802cd9574a80444e689c7525627b40d7dc3a06 (patch)
tree5954e2ac7e97023b51d36127963a1e9262fbcfe0 /drivers/scsi/scsi_transport_fc.c
parent3eeab61aa3ddd3c0bedb7449ada1599de22fdb5a (diff)
parent2d2f8d59b14bec6c745e219a350ac51d9e00673f (diff)
Merge mulgrave-w:git/scsi-misc-2.6
Conflicts: drivers/scsi/iscsi_tcp.c drivers/scsi/iscsi_tcp.h Pretty horrible merge between crypto hash consolidation and crypto_digest_...->crypto_hash_... conversion Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_transport_fc.c')
-rw-r--r--drivers/scsi/scsi_transport_fc.c368
1 files changed, 352 insertions, 16 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index b03aa85108e5..4ab176ed480d 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -32,6 +32,9 @@
32#include <scsi/scsi_transport.h> 32#include <scsi/scsi_transport.h>
33#include <scsi/scsi_transport_fc.h> 33#include <scsi/scsi_transport_fc.h>
34#include <scsi/scsi_cmnd.h> 34#include <scsi/scsi_cmnd.h>
35#include <linux/netlink.h>
36#include <net/netlink.h>
37#include <scsi/scsi_netlink_fc.h>
35#include "scsi_priv.h" 38#include "scsi_priv.h"
36 39
37static int fc_queue_work(struct Scsi_Host *, struct work_struct *); 40static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
@@ -93,6 +96,29 @@ fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)
93#define FC_PORTTYPE_MAX_NAMELEN 50 96#define FC_PORTTYPE_MAX_NAMELEN 50
94 97
95 98
99/* Convert fc_host_event_code values to ascii string name */
100static const struct {
101 enum fc_host_event_code value;
102 char *name;
103} fc_host_event_code_names[] = {
104 { FCH_EVT_LIP, "lip" },
105 { FCH_EVT_LINKUP, "link_up" },
106 { FCH_EVT_LINKDOWN, "link_down" },
107 { FCH_EVT_LIPRESET, "lip_reset" },
108 { FCH_EVT_RSCN, "rscn" },
109 { FCH_EVT_ADAPTER_CHANGE, "adapter_chg" },
110 { FCH_EVT_PORT_UNKNOWN, "port_unknown" },
111 { FCH_EVT_PORT_ONLINE, "port_online" },
112 { FCH_EVT_PORT_OFFLINE, "port_offline" },
113 { FCH_EVT_PORT_FABRIC, "port_fabric" },
114 { FCH_EVT_LINK_UNKNOWN, "link_unknown" },
115 { FCH_EVT_VENDOR_UNIQUE, "vendor_unique" },
116};
117fc_enum_name_search(host_event_code, fc_host_event_code,
118 fc_host_event_code_names)
119#define FC_HOST_EVENT_CODE_MAX_NAMELEN 30
120
121
96/* Convert fc_port_state values to ascii string name */ 122/* Convert fc_port_state values to ascii string name */
97static struct { 123static struct {
98 enum fc_port_state value; 124 enum fc_port_state value;
@@ -216,6 +242,7 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
216 242
217 243
218static void fc_timeout_deleted_rport(void *data); 244static void fc_timeout_deleted_rport(void *data);
245static void fc_timeout_fail_rport_io(void *data);
219static void fc_scsi_scan_rport(void *data); 246static void fc_scsi_scan_rport(void *data);
220 247
221/* 248/*
@@ -223,7 +250,7 @@ static void fc_scsi_scan_rport(void *data);
223 * Increase these values if you add attributes 250 * Increase these values if you add attributes
224 */ 251 */
225#define FC_STARGET_NUM_ATTRS 3 252#define FC_STARGET_NUM_ATTRS 3
226#define FC_RPORT_NUM_ATTRS 9 253#define FC_RPORT_NUM_ATTRS 10
227#define FC_HOST_NUM_ATTRS 17 254#define FC_HOST_NUM_ATTRS 17
228 255
229struct fc_internal { 256struct fc_internal {
@@ -301,8 +328,6 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
301 fc_host->supported_classes = FC_COS_UNSPECIFIED; 328 fc_host->supported_classes = FC_COS_UNSPECIFIED;
302 memset(fc_host->supported_fc4s, 0, 329 memset(fc_host->supported_fc4s, 0,
303 sizeof(fc_host->supported_fc4s)); 330 sizeof(fc_host->supported_fc4s));
304 memset(fc_host->symbolic_name, 0,
305 sizeof(fc_host->symbolic_name));
306 fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN; 331 fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN;
307 fc_host->maxframe_size = -1; 332 fc_host->maxframe_size = -1;
308 memset(fc_host->serial_number, 0, 333 memset(fc_host->serial_number, 0,
@@ -315,6 +340,8 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
315 sizeof(fc_host->active_fc4s)); 340 sizeof(fc_host->active_fc4s));
316 fc_host->speed = FC_PORTSPEED_UNKNOWN; 341 fc_host->speed = FC_PORTSPEED_UNKNOWN;
317 fc_host->fabric_name = -1; 342 fc_host->fabric_name = -1;
343 memset(fc_host->symbolic_name, 0, sizeof(fc_host->symbolic_name));
344 memset(fc_host->system_hostname, 0, sizeof(fc_host->system_hostname));
318 345
319 fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN; 346 fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN;
320 347
@@ -377,10 +404,182 @@ MODULE_PARM_DESC(dev_loss_tmo,
377 " exceeded, the scsi target is removed. Value should be" 404 " exceeded, the scsi target is removed. Value should be"
378 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT."); 405 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT.");
379 406
407/**
408 * Netlink Infrastructure
409 **/
410
411static atomic_t fc_event_seq;
412
413/**
414 * fc_get_event_number - Obtain the next sequential FC event number
415 *
416 * Notes:
417 * We could have inline'd this, but it would have required fc_event_seq to
418 * be exposed. For now, live with the subroutine call.
419 * Atomic used to avoid lock/unlock...
420 **/
421u32
422fc_get_event_number(void)
423{
424 return atomic_add_return(1, &fc_event_seq);
425}
426EXPORT_SYMBOL(fc_get_event_number);
427
428
429/**
430 * fc_host_post_event - called to post an even on an fc_host.
431 *
432 * @shost: host the event occurred on
433 * @event_number: fc event number obtained from get_fc_event_number()
434 * @event_code: fc_host event being posted
435 * @event_data: 32bits of data for the event being posted
436 *
437 * Notes:
438 * This routine assumes no locks are held on entry.
439 **/
440void
441fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
442 enum fc_host_event_code event_code, u32 event_data)
443{
444 struct sk_buff *skb;
445 struct nlmsghdr *nlh;
446 struct fc_nl_event *event;
447 const char *name;
448 u32 len, skblen;
449 int err;
450
451 if (!scsi_nl_sock) {
452 err = -ENOENT;
453 goto send_fail;
454 }
455
456 len = FC_NL_MSGALIGN(sizeof(*event));
457 skblen = NLMSG_SPACE(len);
458
459 skb = alloc_skb(skblen, GFP_KERNEL);
460 if (!skb) {
461 err = -ENOBUFS;
462 goto send_fail;
463 }
464
465 nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
466 skblen - sizeof(*nlh), 0);
467 if (!nlh) {
468 err = -ENOBUFS;
469 goto send_fail_skb;
470 }
471 event = NLMSG_DATA(nlh);
472
473 INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
474 FC_NL_ASYNC_EVENT, len);
475 event->seconds = get_seconds();
476 event->vendor_id = 0;
477 event->host_no = shost->host_no;
478 event->event_datalen = sizeof(u32); /* bytes */
479 event->event_num = event_number;
480 event->event_code = event_code;
481 event->event_data = event_data;
482
483 err = nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS);
484 if (err && (err != -ESRCH)) /* filter no recipient errors */
485 /* nlmsg_multicast already kfree_skb'd */
486 goto send_fail;
487
488 return;
489
490send_fail_skb:
491 kfree_skb(skb);
492send_fail:
493 name = get_fc_host_event_code_name(event_code);
494 printk(KERN_WARNING
495 "%s: Dropped Event : host %d %s data 0x%08x - err %d\n",
496 __FUNCTION__, shost->host_no,
497 (name) ? name : "<unknown>", event_data, err);
498 return;
499}
500EXPORT_SYMBOL(fc_host_post_event);
501
502
503/**
504 * fc_host_post_vendor_event - called to post a vendor unique event on
505 * a fc_host
506 *
507 * @shost: host the event occurred on
508 * @event_number: fc event number obtained from get_fc_event_number()
509 * @data_len: amount, in bytes, of vendor unique data
510 * @data_buf: pointer to vendor unique data
511 *
512 * Notes:
513 * This routine assumes no locks are held on entry.
514 **/
515void
516fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
517 u32 data_len, char * data_buf, u64 vendor_id)
518{
519 struct sk_buff *skb;
520 struct nlmsghdr *nlh;
521 struct fc_nl_event *event;
522 u32 len, skblen;
523 int err;
524
525 if (!scsi_nl_sock) {
526 err = -ENOENT;
527 goto send_vendor_fail;
528 }
529
530 len = FC_NL_MSGALIGN(sizeof(*event) + data_len);
531 skblen = NLMSG_SPACE(len);
532
533 skb = alloc_skb(skblen, GFP_KERNEL);
534 if (!skb) {
535 err = -ENOBUFS;
536 goto send_vendor_fail;
537 }
538
539 nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
540 skblen - sizeof(*nlh), 0);
541 if (!nlh) {
542 err = -ENOBUFS;
543 goto send_vendor_fail_skb;
544 }
545 event = NLMSG_DATA(nlh);
546
547 INIT_SCSI_NL_HDR(&event->snlh, SCSI_NL_TRANSPORT_FC,
548 FC_NL_ASYNC_EVENT, len);
549 event->seconds = get_seconds();
550 event->vendor_id = vendor_id;
551 event->host_no = shost->host_no;
552 event->event_datalen = data_len; /* bytes */
553 event->event_num = event_number;
554 event->event_code = FCH_EVT_VENDOR_UNIQUE;
555 memcpy(&event->event_data, data_buf, data_len);
556
557 err = nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS);
558 if (err && (err != -ESRCH)) /* filter no recipient errors */
559 /* nlmsg_multicast already kfree_skb'd */
560 goto send_vendor_fail;
561
562 return;
563
564send_vendor_fail_skb:
565 kfree_skb(skb);
566send_vendor_fail:
567 printk(KERN_WARNING
568 "%s: Dropped Event : host %d vendor_unique - err %d\n",
569 __FUNCTION__, shost->host_no, err);
570 return;
571}
572EXPORT_SYMBOL(fc_host_post_vendor_event);
573
574
380 575
381static __init int fc_transport_init(void) 576static __init int fc_transport_init(void)
382{ 577{
383 int error = transport_class_register(&fc_host_class); 578 int error;
579
580 atomic_set(&fc_event_seq, 0);
581
582 error = transport_class_register(&fc_host_class);
384 if (error) 583 if (error)
385 return error; 584 return error;
386 error = transport_class_register(&fc_rport_class); 585 error = transport_class_register(&fc_rport_class);
@@ -424,11 +623,14 @@ store_fc_rport_##field(struct class_device *cdev, const char *buf, \
424 struct fc_rport *rport = transport_class_to_rport(cdev); \ 623 struct fc_rport *rport = transport_class_to_rport(cdev); \
425 struct Scsi_Host *shost = rport_to_shost(rport); \ 624 struct Scsi_Host *shost = rport_to_shost(rport); \
426 struct fc_internal *i = to_fc_internal(shost->transportt); \ 625 struct fc_internal *i = to_fc_internal(shost->transportt); \
626 char *cp; \
427 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || \ 627 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || \
428 (rport->port_state == FC_PORTSTATE_DELETED) || \ 628 (rport->port_state == FC_PORTSTATE_DELETED) || \
429 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) \ 629 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) \
430 return -EBUSY; \ 630 return -EBUSY; \
431 val = simple_strtoul(buf, NULL, 0); \ 631 val = simple_strtoul(buf, &cp, 0); \
632 if (*cp && (*cp != '\n')) \
633 return -EINVAL; \
432 i->f->set_rport_##field(rport, val); \ 634 i->f->set_rport_##field(rport, val); \
433 return count; \ 635 return count; \
434} 636}
@@ -510,6 +712,13 @@ static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO, \
510 if (i->f->show_rport_##field) \ 712 if (i->f->show_rport_##field) \
511 count++ 713 count++
512 714
715#define SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(field) \
716{ \
717 i->private_rport_attrs[count] = class_device_attr_rport_##field; \
718 i->rport_attrs[count] = &i->private_rport_attrs[count]; \
719 count++; \
720}
721
513 722
514/* The FC Transport Remote Port Attributes: */ 723/* The FC Transport Remote Port Attributes: */
515 724
@@ -542,12 +751,14 @@ store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf,
542 struct fc_rport *rport = transport_class_to_rport(cdev); 751 struct fc_rport *rport = transport_class_to_rport(cdev);
543 struct Scsi_Host *shost = rport_to_shost(rport); 752 struct Scsi_Host *shost = rport_to_shost(rport);
544 struct fc_internal *i = to_fc_internal(shost->transportt); 753 struct fc_internal *i = to_fc_internal(shost->transportt);
754 char *cp;
545 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || 755 if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
546 (rport->port_state == FC_PORTSTATE_DELETED) || 756 (rport->port_state == FC_PORTSTATE_DELETED) ||
547 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) 757 (rport->port_state == FC_PORTSTATE_NOTPRESENT))
548 return -EBUSY; 758 return -EBUSY;
549 val = simple_strtoul(buf, NULL, 0); 759 val = simple_strtoul(buf, &cp, 0);
550 if ((val < 0) || (val > SCSI_DEVICE_BLOCK_MAX_TIMEOUT)) 760 if ((*cp && (*cp != '\n')) ||
761 (val < 0) || (val > SCSI_DEVICE_BLOCK_MAX_TIMEOUT))
551 return -EINVAL; 762 return -EINVAL;
552 i->f->set_rport_dev_loss_tmo(rport, val); 763 i->f->set_rport_dev_loss_tmo(rport, val);
553 return count; 764 return count;
@@ -597,6 +808,44 @@ static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO,
597fc_private_rport_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN); 808fc_private_rport_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);
598fc_private_rport_rd_attr(scsi_target_id, "%d\n", 20); 809fc_private_rport_rd_attr(scsi_target_id, "%d\n", 20);
599 810
811/*
812 * fast_io_fail_tmo attribute
813 */
814static ssize_t
815show_fc_rport_fast_io_fail_tmo (struct class_device *cdev, char *buf)
816{
817 struct fc_rport *rport = transport_class_to_rport(cdev);
818
819 if (rport->fast_io_fail_tmo == -1)
820 return snprintf(buf, 5, "off\n");
821 return snprintf(buf, 20, "%d\n", rport->fast_io_fail_tmo);
822}
823
824static ssize_t
825store_fc_rport_fast_io_fail_tmo(struct class_device *cdev, const char *buf,
826 size_t count)
827{
828 int val;
829 char *cp;
830 struct fc_rport *rport = transport_class_to_rport(cdev);
831
832 if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
833 (rport->port_state == FC_PORTSTATE_DELETED) ||
834 (rport->port_state == FC_PORTSTATE_NOTPRESENT))
835 return -EBUSY;
836 if (strncmp(buf, "off", 3) == 0)
837 rport->fast_io_fail_tmo = -1;
838 else {
839 val = simple_strtoul(buf, &cp, 0);
840 if ((*cp && (*cp != '\n')) ||
841 (val < 0) || (val >= rport->dev_loss_tmo))
842 return -EINVAL;
843 rport->fast_io_fail_tmo = val;
844 }
845 return count;
846}
847static FC_CLASS_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
848 show_fc_rport_fast_io_fail_tmo, store_fc_rport_fast_io_fail_tmo);
600 849
601 850
602/* 851/*
@@ -682,12 +931,34 @@ store_fc_host_##field(struct class_device *cdev, const char *buf, \
682 int val; \ 931 int val; \
683 struct Scsi_Host *shost = transport_class_to_shost(cdev); \ 932 struct Scsi_Host *shost = transport_class_to_shost(cdev); \
684 struct fc_internal *i = to_fc_internal(shost->transportt); \ 933 struct fc_internal *i = to_fc_internal(shost->transportt); \
934 char *cp; \
685 \ 935 \
686 val = simple_strtoul(buf, NULL, 0); \ 936 val = simple_strtoul(buf, &cp, 0); \
937 if (*cp && (*cp != '\n')) \
938 return -EINVAL; \
687 i->f->set_host_##field(shost, val); \ 939 i->f->set_host_##field(shost, val); \
688 return count; \ 940 return count; \
689} 941}
690 942
943#define fc_host_store_str_function(field, slen) \
944static ssize_t \
945store_fc_host_##field(struct class_device *cdev, const char *buf, \
946 size_t count) \
947{ \
948 struct Scsi_Host *shost = transport_class_to_shost(cdev); \
949 struct fc_internal *i = to_fc_internal(shost->transportt); \
950 unsigned int cnt=count; \
951 \
952 /* count may include a LF at end of string */ \
953 if (buf[cnt-1] == '\n') \
954 cnt--; \
955 if (cnt > ((slen) - 1)) \
956 return -EINVAL; \
957 memcpy(fc_host_##field(shost), buf, cnt); \
958 i->f->set_host_##field(shost); \
959 return count; \
960}
961
691#define fc_host_rd_attr(field, format_string, sz) \ 962#define fc_host_rd_attr(field, format_string, sz) \
692 fc_host_show_function(field, format_string, sz, ) \ 963 fc_host_show_function(field, format_string, sz, ) \
693static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \ 964static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
@@ -815,7 +1086,6 @@ fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
815fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); 1086fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
816fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20, 1087fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,
817 unsigned long long); 1088 unsigned long long);
818fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1));
819fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); 1089fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
820fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); 1090fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
821 1091
@@ -858,6 +1128,13 @@ fc_host_rd_attr(port_id, "0x%06x\n", 20);
858fc_host_rd_enum_attr(port_type, FC_PORTTYPE_MAX_NAMELEN); 1128fc_host_rd_enum_attr(port_type, FC_PORTTYPE_MAX_NAMELEN);
859fc_host_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN); 1129fc_host_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);
860fc_host_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long); 1130fc_host_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long);
1131fc_host_rd_attr(symbolic_name, "%s\n", FC_SYMBOLIC_NAME_SIZE + 1);
1132
1133fc_private_host_show_function(system_hostname, "%s\n",
1134 FC_SYMBOLIC_NAME_SIZE + 1, )
1135fc_host_store_str_function(system_hostname, FC_SYMBOLIC_NAME_SIZE)
1136static FC_CLASS_DEVICE_ATTR(host, system_hostname, S_IRUGO | S_IWUSR,
1137 show_fc_host_system_hostname, store_fc_host_system_hostname);
861 1138
862 1139
863/* Private Host Attributes */ 1140/* Private Host Attributes */
@@ -1223,7 +1500,6 @@ fc_attach_transport(struct fc_function_template *ft)
1223 SETUP_HOST_ATTRIBUTE_RD(permanent_port_name); 1500 SETUP_HOST_ATTRIBUTE_RD(permanent_port_name);
1224 SETUP_HOST_ATTRIBUTE_RD(supported_classes); 1501 SETUP_HOST_ATTRIBUTE_RD(supported_classes);
1225 SETUP_HOST_ATTRIBUTE_RD(supported_fc4s); 1502 SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);
1226 SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
1227 SETUP_HOST_ATTRIBUTE_RD(supported_speeds); 1503 SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
1228 SETUP_HOST_ATTRIBUTE_RD(maxframe_size); 1504 SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
1229 SETUP_HOST_ATTRIBUTE_RD(serial_number); 1505 SETUP_HOST_ATTRIBUTE_RD(serial_number);
@@ -1234,6 +1510,8 @@ fc_attach_transport(struct fc_function_template *ft)
1234 SETUP_HOST_ATTRIBUTE_RD(active_fc4s); 1510 SETUP_HOST_ATTRIBUTE_RD(active_fc4s);
1235 SETUP_HOST_ATTRIBUTE_RD(speed); 1511 SETUP_HOST_ATTRIBUTE_RD(speed);
1236 SETUP_HOST_ATTRIBUTE_RD(fabric_name); 1512 SETUP_HOST_ATTRIBUTE_RD(fabric_name);
1513 SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
1514 SETUP_HOST_ATTRIBUTE_RW(system_hostname);
1237 1515
1238 /* Transport-managed attributes */ 1516 /* Transport-managed attributes */
1239 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type); 1517 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
@@ -1257,6 +1535,8 @@ fc_attach_transport(struct fc_function_template *ft)
1257 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(roles); 1535 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(roles);
1258 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_state); 1536 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_state);
1259 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(scsi_target_id); 1537 SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(scsi_target_id);
1538 if (ft->terminate_rport_io)
1539 SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(fast_io_fail_tmo);
1260 1540
1261 BUG_ON(count > FC_RPORT_NUM_ATTRS); 1541 BUG_ON(count > FC_RPORT_NUM_ATTRS);
1262 1542
@@ -1328,7 +1608,7 @@ fc_flush_work(struct Scsi_Host *shost)
1328 * @delay: jiffies to delay the work queuing 1608 * @delay: jiffies to delay the work queuing
1329 * 1609 *
1330 * Return value: 1610 * Return value:
1331 * 0 on success / != 0 for error 1611 * 1 on success / 0 already queued / < 0 for error
1332 **/ 1612 **/
1333static int 1613static int
1334fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work, 1614fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work,
@@ -1343,6 +1623,9 @@ fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work,
1343 return -EINVAL; 1623 return -EINVAL;
1344 } 1624 }
1345 1625
1626 if (delay == 0)
1627 return queue_work(fc_host_devloss_work_q(shost), work);
1628
1346 return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay); 1629 return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay);
1347} 1630}
1348 1631
@@ -1435,10 +1718,23 @@ fc_starget_delete(void *data)
1435 struct fc_rport *rport = (struct fc_rport *)data; 1718 struct fc_rport *rport = (struct fc_rport *)data;
1436 struct Scsi_Host *shost = rport_to_shost(rport); 1719 struct Scsi_Host *shost = rport_to_shost(rport);
1437 unsigned long flags; 1720 unsigned long flags;
1721 struct fc_internal *i = to_fc_internal(shost->transportt);
1722
1723 /*
1724 * Involve the LLDD if possible. All io on the rport is to
1725 * be terminated, either as part of the dev_loss_tmo callback
1726 * processing, or via the terminate_rport_io function.
1727 */
1728 if (i->f->dev_loss_tmo_callbk)
1729 i->f->dev_loss_tmo_callbk(rport);
1730 else if (i->f->terminate_rport_io)
1731 i->f->terminate_rport_io(rport);
1438 1732
1439 spin_lock_irqsave(shost->host_lock, flags); 1733 spin_lock_irqsave(shost->host_lock, flags);
1440 if (rport->flags & FC_RPORT_DEVLOSS_PENDING) { 1734 if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
1441 spin_unlock_irqrestore(shost->host_lock, flags); 1735 spin_unlock_irqrestore(shost->host_lock, flags);
1736 if (!cancel_delayed_work(&rport->fail_io_work))
1737 fc_flush_devloss(shost);
1442 if (!cancel_delayed_work(&rport->dev_loss_work)) 1738 if (!cancel_delayed_work(&rport->dev_loss_work))
1443 fc_flush_devloss(shost); 1739 fc_flush_devloss(shost);
1444 spin_lock_irqsave(shost->host_lock, flags); 1740 spin_lock_irqsave(shost->host_lock, flags);
@@ -1461,10 +1757,7 @@ fc_rport_final_delete(void *data)
1461 struct fc_rport *rport = (struct fc_rport *)data; 1757 struct fc_rport *rport = (struct fc_rport *)data;
1462 struct device *dev = &rport->dev; 1758 struct device *dev = &rport->dev;
1463 struct Scsi_Host *shost = rport_to_shost(rport); 1759 struct Scsi_Host *shost = rport_to_shost(rport);
1464 1760 struct fc_internal *i = to_fc_internal(shost->transportt);
1465 /* Delete SCSI target and sdevs */
1466 if (rport->scsi_target_id != -1)
1467 fc_starget_delete(data);
1468 1761
1469 /* 1762 /*
1470 * if a scan is pending, flush the SCSI Host work_q so that 1763 * if a scan is pending, flush the SCSI Host work_q so that
@@ -1473,6 +1766,14 @@ fc_rport_final_delete(void *data)
1473 if (rport->flags & FC_RPORT_SCAN_PENDING) 1766 if (rport->flags & FC_RPORT_SCAN_PENDING)
1474 scsi_flush_work(shost); 1767 scsi_flush_work(shost);
1475 1768
1769 /* Delete SCSI target and sdevs */
1770 if (rport->scsi_target_id != -1)
1771 fc_starget_delete(data);
1772 else if (i->f->dev_loss_tmo_callbk)
1773 i->f->dev_loss_tmo_callbk(rport);
1774 else if (i->f->terminate_rport_io)
1775 i->f->terminate_rport_io(rport);
1776
1476 transport_remove_device(dev); 1777 transport_remove_device(dev);
1477 device_del(dev); 1778 device_del(dev);
1478 transport_destroy_device(dev); 1779 transport_destroy_device(dev);
@@ -1524,8 +1825,10 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
1524 if (fci->f->dd_fcrport_size) 1825 if (fci->f->dd_fcrport_size)
1525 rport->dd_data = &rport[1]; 1826 rport->dd_data = &rport[1];
1526 rport->channel = channel; 1827 rport->channel = channel;
1828 rport->fast_io_fail_tmo = -1;
1527 1829
1528 INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport); 1830 INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport);
1831 INIT_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io, rport);
1529 INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport); 1832 INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport);
1530 INIT_WORK(&rport->stgt_delete_work, fc_starget_delete, rport); 1833 INIT_WORK(&rport->stgt_delete_work, fc_starget_delete, rport);
1531 INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete, rport); 1834 INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete, rport);
@@ -1689,11 +1992,13 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
1689 /* restart the target */ 1992 /* restart the target */
1690 1993
1691 /* 1994 /*
1692 * Stop the target timer first. Take no action 1995 * Stop the target timers first. Take no action
1693 * on the del_timer failure as the state 1996 * on the del_timer failure as the state
1694 * machine state change will validate the 1997 * machine state change will validate the
1695 * transaction. 1998 * transaction.
1696 */ 1999 */
2000 if (!cancel_delayed_work(&rport->fail_io_work))
2001 fc_flush_devloss(shost);
1697 if (!cancel_delayed_work(work)) 2002 if (!cancel_delayed_work(work))
1698 fc_flush_devloss(shost); 2003 fc_flush_devloss(shost);
1699 2004
@@ -1837,6 +2142,7 @@ void
1837fc_remote_port_delete(struct fc_rport *rport) 2142fc_remote_port_delete(struct fc_rport *rport)
1838{ 2143{
1839 struct Scsi_Host *shost = rport_to_shost(rport); 2144 struct Scsi_Host *shost = rport_to_shost(rport);
2145 struct fc_internal *i = to_fc_internal(shost->transportt);
1840 int timeout = rport->dev_loss_tmo; 2146 int timeout = rport->dev_loss_tmo;
1841 unsigned long flags; 2147 unsigned long flags;
1842 2148
@@ -1867,6 +2173,12 @@ fc_remote_port_delete(struct fc_rport *rport)
1867 2173
1868 scsi_target_block(&rport->dev); 2174 scsi_target_block(&rport->dev);
1869 2175
2176 /* see if we need to kill io faster than waiting for device loss */
2177 if ((rport->fast_io_fail_tmo != -1) &&
2178 (rport->fast_io_fail_tmo < timeout) && (i->f->terminate_rport_io))
2179 fc_queue_devloss_work(shost, &rport->fail_io_work,
2180 rport->fast_io_fail_tmo * HZ);
2181
1870 /* cap the length the devices can be blocked until they are deleted */ 2182 /* cap the length the devices can be blocked until they are deleted */
1871 fc_queue_devloss_work(shost, &rport->dev_loss_work, timeout * HZ); 2183 fc_queue_devloss_work(shost, &rport->dev_loss_work, timeout * HZ);
1872} 2184}
@@ -1926,6 +2238,8 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
1926 * machine state change will validate the 2238 * machine state change will validate the
1927 * transaction. 2239 * transaction.
1928 */ 2240 */
2241 if (!cancel_delayed_work(&rport->fail_io_work))
2242 fc_flush_devloss(shost);
1929 if (!cancel_delayed_work(&rport->dev_loss_work)) 2243 if (!cancel_delayed_work(&rport->dev_loss_work))
1930 fc_flush_devloss(shost); 2244 fc_flush_devloss(shost);
1931 2245
@@ -2047,6 +2361,28 @@ fc_timeout_deleted_rport(void *data)
2047} 2361}
2048 2362
2049/** 2363/**
2364 * fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a
2365 * disconnected SCSI target.
2366 *
2367 * @data: rport to terminate io on.
2368 *
2369 * Notes: Only requests the failure of the io, not that all are flushed
2370 * prior to returning.
2371 **/
2372static void
2373fc_timeout_fail_rport_io(void *data)
2374{
2375 struct fc_rport *rport = (struct fc_rport *)data;
2376 struct Scsi_Host *shost = rport_to_shost(rport);
2377 struct fc_internal *i = to_fc_internal(shost->transportt);
2378
2379 if (rport->port_state != FC_PORTSTATE_BLOCKED)
2380 return;
2381
2382 i->f->terminate_rport_io(rport);
2383}
2384
2385/**
2050 * fc_scsi_scan_rport - called to perform a scsi scan on a remote port. 2386 * fc_scsi_scan_rport - called to perform a scsi scan on a remote port.
2051 * 2387 *
2052 * @data: remote port to be scanned. 2388 * @data: remote port to be scanned.