aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_sas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_transport_sas.c')
-rw-r--r--drivers/scsi/scsi_transport_sas.c83
1 files changed, 69 insertions, 14 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 5a625c3fddae..b5b0c2cba96b 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -77,6 +77,24 @@ get_sas_##title##_names(u32 table_key, char *buf) \
77 return len; \ 77 return len; \
78} 78}
79 79
80#define sas_bitfield_name_set(title, table) \
81static ssize_t \
82set_sas_##title##_names(u32 *table_key, const char *buf) \
83{ \
84 ssize_t len = 0; \
85 int i; \
86 \
87 for (i = 0; i < ARRAY_SIZE(table); i++) { \
88 len = strlen(table[i].name); \
89 if (strncmp(buf, table[i].name, len) == 0 && \
90 (buf[len] == '\n' || buf[len] == '\0')) { \
91 *table_key = table[i].value; \
92 return 0; \
93 } \
94 } \
95 return -EINVAL; \
96}
97
80#define sas_bitfield_name_search(title, table) \ 98#define sas_bitfield_name_search(title, table) \
81static ssize_t \ 99static ssize_t \
82get_sas_##title##_names(u32 table_key, char *buf) \ 100get_sas_##title##_names(u32 table_key, char *buf) \
@@ -131,7 +149,7 @@ static struct {
131 { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, 149 { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" },
132}; 150};
133sas_bitfield_name_search(linkspeed, sas_linkspeed_names) 151sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
134 152sas_bitfield_name_set(linkspeed, sas_linkspeed_names)
135 153
136/* 154/*
137 * SAS host attributes 155 * SAS host attributes
@@ -253,10 +271,39 @@ show_sas_phy_##field(struct class_device *cdev, char *buf) \
253 return get_sas_linkspeed_names(phy->field, buf); \ 271 return get_sas_linkspeed_names(phy->field, buf); \
254} 272}
255 273
274/* Fudge to tell if we're minimum or maximum */
275#define sas_phy_store_linkspeed(field) \
276static ssize_t \
277store_sas_phy_##field(struct class_device *cdev, const char *buf, \
278 size_t count) \
279{ \
280 struct sas_phy *phy = transport_class_to_phy(cdev); \
281 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \
282 struct sas_internal *i = to_sas_internal(shost->transportt); \
283 u32 value; \
284 struct sas_phy_linkrates rates = {0}; \
285 int error; \
286 \
287 error = set_sas_linkspeed_names(&value, buf); \
288 if (error) \
289 return error; \
290 rates.field = value; \
291 error = i->f->set_phy_speed(phy, &rates); \
292 \
293 return error ? error : count; \
294}
295
296#define sas_phy_linkspeed_rw_attr(field) \
297 sas_phy_show_linkspeed(field) \
298 sas_phy_store_linkspeed(field) \
299static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, \
300 store_sas_phy_##field)
301
256#define sas_phy_linkspeed_attr(field) \ 302#define sas_phy_linkspeed_attr(field) \
257 sas_phy_show_linkspeed(field) \ 303 sas_phy_show_linkspeed(field) \
258static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 304static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
259 305
306
260#define sas_phy_show_linkerror(field) \ 307#define sas_phy_show_linkerror(field) \
261static ssize_t \ 308static ssize_t \
262show_sas_phy_##field(struct class_device *cdev, char *buf) \ 309show_sas_phy_##field(struct class_device *cdev, char *buf) \
@@ -266,9 +313,6 @@ show_sas_phy_##field(struct class_device *cdev, char *buf) \
266 struct sas_internal *i = to_sas_internal(shost->transportt); \ 313 struct sas_internal *i = to_sas_internal(shost->transportt); \
267 int error; \ 314 int error; \
268 \ 315 \
269 if (!phy->local_attached) \
270 return -EINVAL; \
271 \
272 error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0; \ 316 error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0; \
273 if (error) \ 317 if (error) \
274 return error; \ 318 return error; \
@@ -299,9 +343,6 @@ static ssize_t do_sas_phy_reset(struct class_device *cdev,
299 struct sas_internal *i = to_sas_internal(shost->transportt); 343 struct sas_internal *i = to_sas_internal(shost->transportt);
300 int error; 344 int error;
301 345
302 if (!phy->local_attached)
303 return -EINVAL;
304
305 error = i->f->phy_reset(phy, hard_reset); 346 error = i->f->phy_reset(phy, hard_reset);
306 if (error) 347 if (error)
307 return error; 348 return error;
@@ -332,9 +373,9 @@ sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
332//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int); 373//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int);
333sas_phy_linkspeed_attr(negotiated_linkrate); 374sas_phy_linkspeed_attr(negotiated_linkrate);
334sas_phy_linkspeed_attr(minimum_linkrate_hw); 375sas_phy_linkspeed_attr(minimum_linkrate_hw);
335sas_phy_linkspeed_attr(minimum_linkrate); 376sas_phy_linkspeed_rw_attr(minimum_linkrate);
336sas_phy_linkspeed_attr(maximum_linkrate_hw); 377sas_phy_linkspeed_attr(maximum_linkrate_hw);
337sas_phy_linkspeed_attr(maximum_linkrate); 378sas_phy_linkspeed_rw_attr(maximum_linkrate);
338sas_phy_linkerror_attr(invalid_dword_count); 379sas_phy_linkerror_attr(invalid_dword_count);
339sas_phy_linkerror_attr(running_disparity_error_count); 380sas_phy_linkerror_attr(running_disparity_error_count);
340sas_phy_linkerror_attr(loss_of_dword_sync_count); 381sas_phy_linkerror_attr(loss_of_dword_sync_count);
@@ -849,7 +890,7 @@ show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf)
849 * Only devices behind an expander are supported, because the 890 * Only devices behind an expander are supported, because the
850 * enclosure identifier is a SMP feature. 891 * enclosure identifier is a SMP feature.
851 */ 892 */
852 if (phy->local_attached) 893 if (scsi_is_sas_phy_local(phy))
853 return -EINVAL; 894 return -EINVAL;
854 895
855 error = i->f->get_enclosure_identifier(rphy, &identifier); 896 error = i->f->get_enclosure_identifier(rphy, &identifier);
@@ -870,7 +911,7 @@ show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf)
870 struct sas_internal *i = to_sas_internal(shost->transportt); 911 struct sas_internal *i = to_sas_internal(shost->transportt);
871 int val; 912 int val;
872 913
873 if (phy->local_attached) 914 if (scsi_is_sas_phy_local(phy))
874 return -EINVAL; 915 return -EINVAL;
875 916
876 val = i->f->get_bay_identifier(rphy); 917 val = i->f->get_bay_identifier(rphy);
@@ -1316,13 +1357,23 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
1316 * Setup / Teardown code 1357 * Setup / Teardown code
1317 */ 1358 */
1318 1359
1319#define SETUP_TEMPLATE(attrb, field, perm, test) \ 1360#define SETUP_TEMPLATE(attrb, field, perm, test) \
1320 i->private_##attrb[count] = class_device_attr_##field; \ 1361 i->private_##attrb[count] = class_device_attr_##field; \
1321 i->private_##attrb[count].attr.mode = perm; \ 1362 i->private_##attrb[count].attr.mode = perm; \
1322 i->attrb[count] = &i->private_##attrb[count]; \ 1363 i->attrb[count] = &i->private_##attrb[count]; \
1323 if (test) \ 1364 if (test) \
1324 count++ 1365 count++
1325 1366
1367#define SETUP_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm) \
1368 i->private_##attrb[count] = class_device_attr_##field; \
1369 i->private_##attrb[count].attr.mode = perm; \
1370 if (ro_test) { \
1371 i->private_##attrb[count].attr.mode = ro_perm; \
1372 i->private_##attrb[count].store = NULL; \
1373 } \
1374 i->attrb[count] = &i->private_##attrb[count]; \
1375 if (test) \
1376 count++
1326 1377
1327#define SETUP_RPORT_ATTRIBUTE(field) \ 1378#define SETUP_RPORT_ATTRIBUTE(field) \
1328 SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) 1379 SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1)
@@ -1333,6 +1384,10 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
1333#define SETUP_PHY_ATTRIBUTE(field) \ 1384#define SETUP_PHY_ATTRIBUTE(field) \
1334 SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) 1385 SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1)
1335 1386
1387#define SETUP_PHY_ATTRIBUTE_RW(field) \
1388 SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \
1389 !i->f->set_phy_speed, S_IRUGO)
1390
1336#define SETUP_PORT_ATTRIBUTE(field) \ 1391#define SETUP_PORT_ATTRIBUTE(field) \
1337 SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1) 1392 SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
1338 1393
@@ -1413,9 +1468,9 @@ sas_attach_transport(struct sas_function_template *ft)
1413 //SETUP_PHY_ATTRIBUTE(port_identifier); 1468 //SETUP_PHY_ATTRIBUTE(port_identifier);
1414 SETUP_PHY_ATTRIBUTE(negotiated_linkrate); 1469 SETUP_PHY_ATTRIBUTE(negotiated_linkrate);
1415 SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw); 1470 SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw);
1416 SETUP_PHY_ATTRIBUTE(minimum_linkrate); 1471 SETUP_PHY_ATTRIBUTE_RW(minimum_linkrate);
1417 SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw); 1472 SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw);
1418 SETUP_PHY_ATTRIBUTE(maximum_linkrate); 1473 SETUP_PHY_ATTRIBUTE_RW(maximum_linkrate);
1419 1474
1420 SETUP_PHY_ATTRIBUTE(invalid_dword_count); 1475 SETUP_PHY_ATTRIBUTE(invalid_dword_count);
1421 SETUP_PHY_ATTRIBUTE(running_disparity_error_count); 1476 SETUP_PHY_ATTRIBUTE(running_disparity_error_count);