diff options
-rw-r--r-- | drivers/scsi/scsi_transport_sas.c | 31 | ||||
-rw-r--r-- | include/scsi/scsi_transport_sas.h | 23 |
2 files changed, 49 insertions, 5 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 1d145d2f9a38..63445f90097e 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 15 |
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,26 @@ 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 | error = i->f->get_linkerrors(phy); \ | ||
270 | if (error) \ | ||
271 | return error; \ | ||
272 | return snprintf(buf, 20, "%u\n", phy->field); \ | ||
273 | } | ||
274 | |||
275 | #define sas_phy_linkerror_attr(field) \ | ||
276 | sas_phy_show_linkerror(field) \ | ||
277 | static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) | ||
278 | |||
279 | |||
260 | static ssize_t | 280 | static ssize_t |
261 | show_sas_device_type(struct class_device *cdev, char *buf) | 281 | show_sas_device_type(struct class_device *cdev, char *buf) |
262 | { | 282 | { |
@@ -282,6 +302,10 @@ sas_phy_linkspeed_attr(minimum_linkrate_hw); | |||
282 | sas_phy_linkspeed_attr(minimum_linkrate); | 302 | sas_phy_linkspeed_attr(minimum_linkrate); |
283 | sas_phy_linkspeed_attr(maximum_linkrate_hw); | 303 | sas_phy_linkspeed_attr(maximum_linkrate_hw); |
284 | sas_phy_linkspeed_attr(maximum_linkrate); | 304 | sas_phy_linkspeed_attr(maximum_linkrate); |
305 | sas_phy_linkerror_attr(invalid_dword_count); | ||
306 | sas_phy_linkerror_attr(running_disparity_error_count); | ||
307 | sas_phy_linkerror_attr(loss_of_dword_sync_count); | ||
308 | sas_phy_linkerror_attr(phy_reset_problem_count); | ||
285 | 309 | ||
286 | 310 | ||
287 | static DECLARE_TRANSPORT_CLASS(sas_phy_class, | 311 | static DECLARE_TRANSPORT_CLASS(sas_phy_class, |
@@ -749,6 +773,11 @@ sas_attach_transport(struct sas_function_template *ft) | |||
749 | SETUP_PORT_ATTRIBUTE(minimum_linkrate); | 773 | SETUP_PORT_ATTRIBUTE(minimum_linkrate); |
750 | SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw); | 774 | SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw); |
751 | SETUP_PORT_ATTRIBUTE(maximum_linkrate); | 775 | SETUP_PORT_ATTRIBUTE(maximum_linkrate); |
776 | |||
777 | SETUP_PORT_ATTRIBUTE(invalid_dword_count); | ||
778 | SETUP_PORT_ATTRIBUTE(running_disparity_error_count); | ||
779 | SETUP_PORT_ATTRIBUTE(loss_of_dword_sync_count); | ||
780 | SETUP_PORT_ATTRIBUTE(phy_reset_problem_count); | ||
752 | i->phy_attrs[count] = NULL; | 781 | i->phy_attrs[count] = NULL; |
753 | 782 | ||
754 | count = 0; | 783 | count = 0; |
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index bc4aeb660dd3..38389d8dd56e 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h | |||
@@ -41,20 +41,28 @@ struct sas_identify { | |||
41 | u8 phy_identifier; | 41 | u8 phy_identifier; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | /* The functions by which the transport class and the driver communicate */ | ||
45 | struct sas_function_template { | ||
46 | }; | ||
47 | |||
48 | struct sas_phy { | 44 | struct sas_phy { |
49 | struct device dev; | 45 | struct device dev; |
50 | int number; | 46 | int number; |
47 | |||
48 | /* phy identification */ | ||
51 | struct sas_identify identify; | 49 | struct sas_identify identify; |
50 | |||
51 | /* phy attributes */ | ||
52 | enum sas_linkrate negotiated_linkrate; | 52 | enum sas_linkrate negotiated_linkrate; |
53 | enum sas_linkrate minimum_linkrate_hw; | 53 | enum sas_linkrate minimum_linkrate_hw; |
54 | enum sas_linkrate minimum_linkrate; | 54 | enum sas_linkrate minimum_linkrate; |
55 | enum sas_linkrate maximum_linkrate_hw; | 55 | enum sas_linkrate maximum_linkrate_hw; |
56 | enum sas_linkrate maximum_linkrate; | 56 | enum sas_linkrate maximum_linkrate; |
57 | u8 port_identifier; | 57 | u8 port_identifier; |
58 | |||
59 | /* link error statistics */ | ||
60 | u32 invalid_dword_count; | ||
61 | u32 running_disparity_error_count; | ||
62 | u32 loss_of_dword_sync_count; | ||
63 | u32 phy_reset_problem_count; | ||
64 | |||
65 | /* the other end of the link */ | ||
58 | struct sas_rphy *rphy; | 66 | struct sas_rphy *rphy; |
59 | }; | 67 | }; |
60 | 68 | ||
@@ -79,6 +87,13 @@ struct sas_rphy { | |||
79 | #define rphy_to_shost(rphy) \ | 87 | #define rphy_to_shost(rphy) \ |
80 | dev_to_shost((rphy)->dev.parent) | 88 | dev_to_shost((rphy)->dev.parent) |
81 | 89 | ||
90 | |||
91 | /* The functions by which the transport class and the driver communicate */ | ||
92 | struct sas_function_template { | ||
93 | int (*get_linkerrors)(struct sas_phy *); | ||
94 | }; | ||
95 | |||
96 | |||
82 | extern void sas_remove_host(struct Scsi_Host *); | 97 | extern void sas_remove_host(struct Scsi_Host *); |
83 | 98 | ||
84 | extern struct sas_phy *sas_phy_alloc(struct device *, int); | 99 | extern struct sas_phy *sas_phy_alloc(struct device *, int); |