diff options
-rw-r--r-- | drivers/scsi/scsi_transport_sas.c | 43 | ||||
-rw-r--r-- | include/scsi/scsi_transport_sas.h | 1 |
2 files changed, 42 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index f5618c1116f4..0cc766a9aa65 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c | |||
@@ -34,7 +34,7 @@ | |||
34 | 34 | ||
35 | 35 | ||
36 | #define SAS_HOST_ATTRS 0 | 36 | #define SAS_HOST_ATTRS 0 |
37 | #define SAS_PORT_ATTRS 15 | 37 | #define SAS_PORT_ATTRS 17 |
38 | #define SAS_RPORT_ATTRS 5 | 38 | #define SAS_RPORT_ATTRS 5 |
39 | 39 | ||
40 | struct sas_internal { | 40 | struct sas_internal { |
@@ -289,9 +289,39 @@ show_sas_device_type(struct class_device *cdev, char *buf) | |||
289 | return snprintf(buf, 20, "none\n"); | 289 | return snprintf(buf, 20, "none\n"); |
290 | return get_sas_device_type_names(phy->identify.device_type, buf); | 290 | return get_sas_device_type_names(phy->identify.device_type, buf); |
291 | } | 291 | } |
292 | |||
293 | static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); | 292 | static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); |
294 | 293 | ||
294 | static ssize_t do_sas_phy_reset(struct class_device *cdev, | ||
295 | size_t count, int hard_reset) | ||
296 | { | ||
297 | struct sas_phy *phy = transport_class_to_phy(cdev); | ||
298 | struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); | ||
299 | struct sas_internal *i = to_sas_internal(shost->transportt); | ||
300 | int error; | ||
301 | |||
302 | if (!phy->local_attached) | ||
303 | return -EINVAL; | ||
304 | |||
305 | error = i->f->phy_reset(phy, hard_reset); | ||
306 | if (error) | ||
307 | return error; | ||
308 | return count; | ||
309 | }; | ||
310 | |||
311 | static ssize_t store_sas_link_reset(struct class_device *cdev, | ||
312 | const char *buf, size_t count) | ||
313 | { | ||
314 | return do_sas_phy_reset(cdev, count, 0); | ||
315 | } | ||
316 | static CLASS_DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset); | ||
317 | |||
318 | static ssize_t store_sas_hard_reset(struct class_device *cdev, | ||
319 | const char *buf, size_t count) | ||
320 | { | ||
321 | return do_sas_phy_reset(cdev, count, 1); | ||
322 | } | ||
323 | static CLASS_DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset); | ||
324 | |||
295 | sas_phy_protocol_attr(identify.initiator_port_protocols, | 325 | sas_phy_protocol_attr(identify.initiator_port_protocols, |
296 | initiator_port_protocols); | 326 | initiator_port_protocols); |
297 | sas_phy_protocol_attr(identify.target_port_protocols, | 327 | sas_phy_protocol_attr(identify.target_port_protocols, |
@@ -725,6 +755,13 @@ static struct device *sas_target_parent(struct Scsi_Host *shost, | |||
725 | i->phy_attrs[count] = &i->private_phy_attrs[count]; \ | 755 | i->phy_attrs[count] = &i->private_phy_attrs[count]; \ |
726 | count++ | 756 | count++ |
727 | 757 | ||
758 | #define SETUP_PORT_ATTRIBUTE_WRONLY(field) \ | ||
759 | i->private_phy_attrs[count] = class_device_attr_##field; \ | ||
760 | i->private_phy_attrs[count].attr.mode = S_IWUGO; \ | ||
761 | i->private_phy_attrs[count].show = NULL; \ | ||
762 | i->phy_attrs[count] = &i->private_phy_attrs[count]; \ | ||
763 | count++ | ||
764 | |||
728 | 765 | ||
729 | /** | 766 | /** |
730 | * sas_attach_transport -- instantiate SAS transport template | 767 | * sas_attach_transport -- instantiate SAS transport template |
@@ -781,6 +818,8 @@ sas_attach_transport(struct sas_function_template *ft) | |||
781 | SETUP_PORT_ATTRIBUTE(running_disparity_error_count); | 818 | SETUP_PORT_ATTRIBUTE(running_disparity_error_count); |
782 | SETUP_PORT_ATTRIBUTE(loss_of_dword_sync_count); | 819 | SETUP_PORT_ATTRIBUTE(loss_of_dword_sync_count); |
783 | SETUP_PORT_ATTRIBUTE(phy_reset_problem_count); | 820 | SETUP_PORT_ATTRIBUTE(phy_reset_problem_count); |
821 | SETUP_PORT_ATTRIBUTE_WRONLY(link_reset); | ||
822 | SETUP_PORT_ATTRIBUTE_WRONLY(hard_reset); | ||
784 | i->phy_attrs[count] = NULL; | 823 | i->phy_attrs[count] = NULL; |
785 | 824 | ||
786 | count = 0; | 825 | count = 0; |
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 57eb68c6e9a7..b91400bfb02a 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h | |||
@@ -94,6 +94,7 @@ struct sas_rphy { | |||
94 | /* The functions by which the transport class and the driver communicate */ | 94 | /* The functions by which the transport class and the driver communicate */ |
95 | struct sas_function_template { | 95 | struct sas_function_template { |
96 | int (*get_linkerrors)(struct sas_phy *); | 96 | int (*get_linkerrors)(struct sas_phy *); |
97 | int (*phy_reset)(struct sas_phy *, int); | ||
97 | }; | 98 | }; |
98 | 99 | ||
99 | 100 | ||