aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_transport_fc.c124
-rw-r--r--include/scsi/scsi_transport_fc.h7
2 files changed, 91 insertions, 40 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 78486d540652..998c01be3234 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -53,6 +53,25 @@ static void fc_bsg_remove(struct request_queue *);
53static void fc_bsg_goose_queue(struct fc_rport *); 53static void fc_bsg_goose_queue(struct fc_rport *);
54 54
55/* 55/*
56 * Module Parameters
57 */
58
59/*
60 * dev_loss_tmo: the default number of seconds that the FC transport
61 * should insulate the loss of a remote port.
62 * The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
63 */
64static unsigned int fc_dev_loss_tmo = 60; /* seconds */
65
66module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR);
67MODULE_PARM_DESC(dev_loss_tmo,
68 "Maximum number of seconds that the FC transport should"
69 " insulate the loss of a remote port. Once this value is"
70 " exceeded, the scsi target is removed. Value should be"
71 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT if"
72 " fast_io_fail_tmo is not set.");
73
74/*
56 * Redefine so that we can have same named attributes in the 75 * Redefine so that we can have same named attributes in the
57 * sdev/starget/host objects. 76 * sdev/starget/host objects.
58 */ 77 */
@@ -408,6 +427,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
408 if (!fc_host->work_q) 427 if (!fc_host->work_q)
409 return -ENOMEM; 428 return -ENOMEM;
410 429
430 fc_host->dev_loss_tmo = fc_dev_loss_tmo;
411 snprintf(fc_host->devloss_work_q_name, 431 snprintf(fc_host->devloss_work_q_name,
412 sizeof(fc_host->devloss_work_q_name), 432 sizeof(fc_host->devloss_work_q_name),
413 "fc_dl_%d", shost->host_no); 433 "fc_dl_%d", shost->host_no);
@@ -462,25 +482,6 @@ static DECLARE_TRANSPORT_CLASS(fc_vport_class,
462 NULL); 482 NULL);
463 483
464/* 484/*
465 * Module Parameters
466 */
467
468/*
469 * dev_loss_tmo: the default number of seconds that the FC transport
470 * should insulate the loss of a remote port.
471 * The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
472 */
473static unsigned int fc_dev_loss_tmo = 60; /* seconds */
474
475module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR);
476MODULE_PARM_DESC(dev_loss_tmo,
477 "Maximum number of seconds that the FC transport should"
478 " insulate the loss of a remote port. Once this value is"
479 " exceeded, the scsi target is removed. Value should be"
480 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT if"
481 " fast_io_fail_tmo is not set.");
482
483/*
484 * Netlink Infrastructure 485 * Netlink Infrastructure
485 */ 486 */
486 487
@@ -830,24 +831,32 @@ static FC_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
830/* 831/*
831 * dev_loss_tmo attribute 832 * dev_loss_tmo attribute
832 */ 833 */
833fc_rport_show_function(dev_loss_tmo, "%d\n", 20, ) 834static int fc_str_to_dev_loss(const char *buf, unsigned long *val)
834static ssize_t 835{
835store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr, 836 char *cp;
836 const char *buf, size_t count) 837
838 *val = simple_strtoul(buf, &cp, 0);
839 if ((*cp && (*cp != '\n')) || (*val < 0))
840 return -EINVAL;
841 /*
842 * Check for overflow; dev_loss_tmo is u32
843 */
844 if (*val > UINT_MAX)
845 return -EINVAL;
846
847 return 0;
848}
849
850static int fc_rport_set_dev_loss_tmo(struct fc_rport *rport,
851 unsigned long val)
837{ 852{
838 unsigned long val;
839 struct fc_rport *rport = transport_class_to_rport(dev);
840 struct Scsi_Host *shost = rport_to_shost(rport); 853 struct Scsi_Host *shost = rport_to_shost(rport);
841 struct fc_internal *i = to_fc_internal(shost->transportt); 854 struct fc_internal *i = to_fc_internal(shost->transportt);
842 char *cp; 855
843 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || 856 if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
844 (rport->port_state == FC_PORTSTATE_DELETED) || 857 (rport->port_state == FC_PORTSTATE_DELETED) ||
845 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) 858 (rport->port_state == FC_PORTSTATE_NOTPRESENT))
846 return -EBUSY; 859 return -EBUSY;
847 val = simple_strtoul(buf, &cp, 0);
848 if ((*cp && (*cp != '\n')) || (val < 0))
849 return -EINVAL;
850
851 /* 860 /*
852 * Check for overflow; dev_loss_tmo is u32 861 * Check for overflow; dev_loss_tmo is u32
853 */ 862 */
@@ -863,6 +872,25 @@ store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
863 return -EINVAL; 872 return -EINVAL;
864 873
865 i->f->set_rport_dev_loss_tmo(rport, val); 874 i->f->set_rport_dev_loss_tmo(rport, val);
875 return 0;
876}
877
878fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
879static ssize_t
880store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
881 const char *buf, size_t count)
882{
883 struct fc_rport *rport = transport_class_to_rport(dev);
884 unsigned long val;
885 int rc;
886
887 rc = fc_str_to_dev_loss(buf, &val);
888 if (rc)
889 return rc;
890
891 rc = fc_rport_set_dev_loss_tmo(rport, val);
892 if (rc)
893 return rc;
866 return count; 894 return count;
867} 895}
868static FC_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR, 896static FC_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,
@@ -1608,8 +1636,35 @@ store_fc_private_host_issue_lip(struct device *dev,
1608static FC_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL, 1636static FC_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
1609 store_fc_private_host_issue_lip); 1637 store_fc_private_host_issue_lip);
1610 1638
1611fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20); 1639static ssize_t
1640store_fc_private_host_dev_loss_tmo(struct device *dev,
1641 struct device_attribute *attr,
1642 const char *buf, size_t count)
1643{
1644 struct Scsi_Host *shost = transport_class_to_shost(dev);
1645 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
1646 struct fc_rport *rport;
1647 unsigned long val, flags;
1648 int rc;
1649
1650 rc = fc_str_to_dev_loss(buf, &val);
1651 if (rc)
1652 return rc;
1653
1654 fc_host_dev_loss_tmo(shost) = val;
1655 spin_lock_irqsave(shost->host_lock, flags);
1656 list_for_each_entry(rport, &fc_host->rports, peers)
1657 fc_rport_set_dev_loss_tmo(rport, val);
1658 spin_unlock_irqrestore(shost->host_lock, flags);
1659 return count;
1660}
1612 1661
1662fc_private_host_show_function(dev_loss_tmo, "%d\n", 20, );
1663static FC_DEVICE_ATTR(host, dev_loss_tmo, S_IRUGO | S_IWUSR,
1664 show_fc_host_dev_loss_tmo,
1665 store_fc_private_host_dev_loss_tmo);
1666
1667fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
1613 1668
1614/* 1669/*
1615 * Host Statistics Management 1670 * Host Statistics Management
@@ -2165,6 +2220,7 @@ fc_attach_transport(struct fc_function_template *ft)
2165 SETUP_HOST_ATTRIBUTE_RW(system_hostname); 2220 SETUP_HOST_ATTRIBUTE_RW(system_hostname);
2166 2221
2167 /* Transport-managed attributes */ 2222 /* Transport-managed attributes */
2223 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(dev_loss_tmo);
2168 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type); 2224 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
2169 if (ft->issue_fc_host_lip) 2225 if (ft->issue_fc_host_lip)
2170 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip); 2226 SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip);
@@ -2525,11 +2581,7 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
2525 2581
2526 rport->maxframe_size = -1; 2582 rport->maxframe_size = -1;
2527 rport->supported_classes = FC_COS_UNSPECIFIED; 2583 rport->supported_classes = FC_COS_UNSPECIFIED;
2528 if (fci->f->get_host_def_dev_loss_tmo) { 2584 rport->dev_loss_tmo = fc_host->dev_loss_tmo;
2529 fci->f->get_host_def_dev_loss_tmo(shost);
2530 rport->dev_loss_tmo = fc_host_def_dev_loss_tmo(shost);
2531 } else
2532 rport->dev_loss_tmo = fc_dev_loss_tmo;
2533 memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name)); 2585 memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name));
2534 memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name)); 2586 memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name));
2535 rport->port_id = ids->port_id; 2587 rport->port_id = ids->port_id;
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 9f98fca9b763..59816fe31e68 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -496,7 +496,7 @@ struct fc_host_attrs {
496 u64 fabric_name; 496 u64 fabric_name;
497 char symbolic_name[FC_SYMBOLIC_NAME_SIZE]; 497 char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
498 char system_hostname[FC_SYMBOLIC_NAME_SIZE]; 498 char system_hostname[FC_SYMBOLIC_NAME_SIZE];
499 u32 def_dev_loss_tmo; 499 u32 dev_loss_tmo;
500 500
501 /* Private (Transport-managed) Attributes */ 501 /* Private (Transport-managed) Attributes */
502 enum fc_tgtid_binding_type tgtid_bind_type; 502 enum fc_tgtid_binding_type tgtid_bind_type;
@@ -581,8 +581,8 @@ struct fc_host_attrs {
581 (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name) 581 (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name)
582#define fc_host_devloss_work_q(x) \ 582#define fc_host_devloss_work_q(x) \
583 (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q) 583 (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
584#define fc_host_def_dev_loss_tmo(x) \ 584#define fc_host_dev_loss_tmo(x) \
585 (((struct fc_host_attrs *)(x)->shost_data)->def_dev_loss_tmo) 585 (((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo)
586 586
587 587
588struct fc_bsg_buffer { 588struct fc_bsg_buffer {
@@ -643,7 +643,6 @@ struct fc_function_template {
643 void (*get_host_fabric_name)(struct Scsi_Host *); 643 void (*get_host_fabric_name)(struct Scsi_Host *);
644 void (*get_host_symbolic_name)(struct Scsi_Host *); 644 void (*get_host_symbolic_name)(struct Scsi_Host *);
645 void (*set_host_system_hostname)(struct Scsi_Host *); 645 void (*set_host_system_hostname)(struct Scsi_Host *);
646 void (*get_host_def_dev_loss_tmo)(struct Scsi_Host *);
647 646
648 struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *); 647 struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *);
649 void (*reset_fc_host_stats)(struct Scsi_Host *); 648 void (*reset_fc_host_stats)(struct Scsi_Host *);