diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_sas.c')
-rw-r--r-- | drivers/scsi/scsi_transport_sas.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 1d145d2f9a38..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 11 | 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 { |
@@ -257,6 +257,29 @@ show_sas_phy_##field(struct class_device *cdev, char *buf) \ | |||
257 | sas_phy_show_linkspeed(field) \ | 257 | sas_phy_show_linkspeed(field) \ |
258 | static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) | 258 | static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) |
259 | 259 | ||
260 | #define sas_phy_show_linkerror(field) \ | ||
261 | static ssize_t \ | ||
262 | show_sas_phy_##field(struct class_device *cdev, char *buf) \ | ||
263 | { \ | ||
264 | struct sas_phy *phy = transport_class_to_phy(cdev); \ | ||
265 | struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \ | ||
266 | struct sas_internal *i = to_sas_internal(shost->transportt); \ | ||
267 | int error; \ | ||
268 | \ | ||
269 | if (!phy->local_attached) \ | ||
270 | return -EINVAL; \ | ||
271 | \ | ||
272 | error = i->f->get_linkerrors(phy); \ | ||
273 | if (error) \ | ||
274 | return error; \ | ||
275 | return snprintf(buf, 20, "%u\n", phy->field); \ | ||
276 | } | ||
277 | |||
278 | #define sas_phy_linkerror_attr(field) \ | ||
279 | sas_phy_show_linkerror(field) \ | ||
280 | static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) | ||
281 | |||
282 | |||
260 | static ssize_t | 283 | static ssize_t |
261 | show_sas_device_type(struct class_device *cdev, char *buf) | 284 | show_sas_device_type(struct class_device *cdev, char *buf) |
262 | { | 285 | { |
@@ -266,9 +289,39 @@ show_sas_device_type(struct class_device *cdev, char *buf) | |||
266 | return snprintf(buf, 20, "none\n"); | 289 | return snprintf(buf, 20, "none\n"); |
267 | return get_sas_device_type_names(phy->identify.device_type, buf); | 290 | return get_sas_device_type_names(phy->identify.device_type, buf); |
268 | } | 291 | } |
269 | |||
270 | 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); |
271 | 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 | |||
272 | sas_phy_protocol_attr(identify.initiator_port_protocols, | 325 | sas_phy_protocol_attr(identify.initiator_port_protocols, |
273 | initiator_port_protocols); | 326 | initiator_port_protocols); |
274 | sas_phy_protocol_attr(identify.target_port_protocols, | 327 | sas_phy_protocol_attr(identify.target_port_protocols, |
@@ -282,6 +335,10 @@ sas_phy_linkspeed_attr(minimum_linkrate_hw); | |||
282 | sas_phy_linkspeed_attr(minimum_linkrate); | 335 | sas_phy_linkspeed_attr(minimum_linkrate); |
283 | sas_phy_linkspeed_attr(maximum_linkrate_hw); | 336 | sas_phy_linkspeed_attr(maximum_linkrate_hw); |
284 | sas_phy_linkspeed_attr(maximum_linkrate); | 337 | sas_phy_linkspeed_attr(maximum_linkrate); |
338 | sas_phy_linkerror_attr(invalid_dword_count); | ||
339 | sas_phy_linkerror_attr(running_disparity_error_count); | ||
340 | sas_phy_linkerror_attr(loss_of_dword_sync_count); | ||
341 | sas_phy_linkerror_attr(phy_reset_problem_count); | ||
285 | 342 | ||
286 | 343 | ||
287 | static DECLARE_TRANSPORT_CLASS(sas_phy_class, | 344 | static DECLARE_TRANSPORT_CLASS(sas_phy_class, |
@@ -698,6 +755,13 @@ static struct device *sas_target_parent(struct Scsi_Host *shost, | |||
698 | i->phy_attrs[count] = &i->private_phy_attrs[count]; \ | 755 | i->phy_attrs[count] = &i->private_phy_attrs[count]; \ |
699 | count++ | 756 | count++ |
700 | 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 | |||
701 | 765 | ||
702 | /** | 766 | /** |
703 | * sas_attach_transport -- instantiate SAS transport template | 767 | * sas_attach_transport -- instantiate SAS transport template |
@@ -749,6 +813,13 @@ sas_attach_transport(struct sas_function_template *ft) | |||
749 | SETUP_PORT_ATTRIBUTE(minimum_linkrate); | 813 | SETUP_PORT_ATTRIBUTE(minimum_linkrate); |
750 | SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw); | 814 | SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw); |
751 | SETUP_PORT_ATTRIBUTE(maximum_linkrate); | 815 | SETUP_PORT_ATTRIBUTE(maximum_linkrate); |
816 | |||
817 | SETUP_PORT_ATTRIBUTE(invalid_dword_count); | ||
818 | SETUP_PORT_ATTRIBUTE(running_disparity_error_count); | ||
819 | SETUP_PORT_ATTRIBUTE(loss_of_dword_sync_count); | ||
820 | SETUP_PORT_ATTRIBUTE(phy_reset_problem_count); | ||
821 | SETUP_PORT_ATTRIBUTE_WRONLY(link_reset); | ||
822 | SETUP_PORT_ATTRIBUTE_WRONLY(hard_reset); | ||
752 | i->phy_attrs[count] = NULL; | 823 | i->phy_attrs[count] = NULL; |
753 | 824 | ||
754 | count = 0; | 825 | count = 0; |