aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_transport_sas.c73
-rw-r--r--include/scsi/scsi_transport_sas.h6
2 files changed, 73 insertions, 6 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index d518c1207fb4..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) \
@@ -326,9 +373,9 @@ sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
326//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int); 373//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int);
327sas_phy_linkspeed_attr(negotiated_linkrate); 374sas_phy_linkspeed_attr(negotiated_linkrate);
328sas_phy_linkspeed_attr(minimum_linkrate_hw); 375sas_phy_linkspeed_attr(minimum_linkrate_hw);
329sas_phy_linkspeed_attr(minimum_linkrate); 376sas_phy_linkspeed_rw_attr(minimum_linkrate);
330sas_phy_linkspeed_attr(maximum_linkrate_hw); 377sas_phy_linkspeed_attr(maximum_linkrate_hw);
331sas_phy_linkspeed_attr(maximum_linkrate); 378sas_phy_linkspeed_rw_attr(maximum_linkrate);
332sas_phy_linkerror_attr(invalid_dword_count); 379sas_phy_linkerror_attr(invalid_dword_count);
333sas_phy_linkerror_attr(running_disparity_error_count); 380sas_phy_linkerror_attr(running_disparity_error_count);
334sas_phy_linkerror_attr(loss_of_dword_sync_count); 381sas_phy_linkerror_attr(loss_of_dword_sync_count);
@@ -1310,13 +1357,23 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
1310 * Setup / Teardown code 1357 * Setup / Teardown code
1311 */ 1358 */
1312 1359
1313#define SETUP_TEMPLATE(attrb, field, perm, test) \ 1360#define SETUP_TEMPLATE(attrb, field, perm, test) \
1314 i->private_##attrb[count] = class_device_attr_##field; \ 1361 i->private_##attrb[count] = class_device_attr_##field; \
1315 i->private_##attrb[count].attr.mode = perm; \ 1362 i->private_##attrb[count].attr.mode = perm; \
1316 i->attrb[count] = &i->private_##attrb[count]; \ 1363 i->attrb[count] = &i->private_##attrb[count]; \
1317 if (test) \ 1364 if (test) \
1318 count++ 1365 count++
1319 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++
1320 1377
1321#define SETUP_RPORT_ATTRIBUTE(field) \ 1378#define SETUP_RPORT_ATTRIBUTE(field) \
1322 SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) 1379 SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1)
@@ -1327,6 +1384,10 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
1327#define SETUP_PHY_ATTRIBUTE(field) \ 1384#define SETUP_PHY_ATTRIBUTE(field) \
1328 SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) 1385 SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1)
1329 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
1330#define SETUP_PORT_ATTRIBUTE(field) \ 1391#define SETUP_PORT_ATTRIBUTE(field) \
1331 SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1) 1392 SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
1332 1393
@@ -1407,9 +1468,9 @@ sas_attach_transport(struct sas_function_template *ft)
1407 //SETUP_PHY_ATTRIBUTE(port_identifier); 1468 //SETUP_PHY_ATTRIBUTE(port_identifier);
1408 SETUP_PHY_ATTRIBUTE(negotiated_linkrate); 1469 SETUP_PHY_ATTRIBUTE(negotiated_linkrate);
1409 SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw); 1470 SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw);
1410 SETUP_PHY_ATTRIBUTE(minimum_linkrate); 1471 SETUP_PHY_ATTRIBUTE_RW(minimum_linkrate);
1411 SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw); 1472 SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw);
1412 SETUP_PHY_ATTRIBUTE(maximum_linkrate); 1473 SETUP_PHY_ATTRIBUTE_RW(maximum_linkrate);
1413 1474
1414 SETUP_PHY_ATTRIBUTE(invalid_dword_count); 1475 SETUP_PHY_ATTRIBUTE(invalid_dword_count);
1415 SETUP_PHY_ATTRIBUTE(running_disparity_error_count); 1476 SETUP_PHY_ATTRIBUTE(running_disparity_error_count);
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
index 87de518960c1..53024377f3b8 100644
--- a/include/scsi/scsi_transport_sas.h
+++ b/include/scsi/scsi_transport_sas.h
@@ -150,12 +150,18 @@ struct sas_port {
150#define transport_class_to_sas_port(cdev) \ 150#define transport_class_to_sas_port(cdev) \
151 dev_to_sas_port((cdev)->dev) 151 dev_to_sas_port((cdev)->dev)
152 152
153struct sas_phy_linkrates {
154 enum sas_linkrate maximum_linkrate;
155 enum sas_linkrate minimum_linkrate;
156};
157
153/* The functions by which the transport class and the driver communicate */ 158/* The functions by which the transport class and the driver communicate */
154struct sas_function_template { 159struct sas_function_template {
155 int (*get_linkerrors)(struct sas_phy *); 160 int (*get_linkerrors)(struct sas_phy *);
156 int (*get_enclosure_identifier)(struct sas_rphy *, u64 *); 161 int (*get_enclosure_identifier)(struct sas_rphy *, u64 *);
157 int (*get_bay_identifier)(struct sas_rphy *); 162 int (*get_bay_identifier)(struct sas_rphy *);
158 int (*phy_reset)(struct sas_phy *, int); 163 int (*phy_reset)(struct sas_phy *, int);
164 int (*set_phy_speed)(struct sas_phy *, struct sas_phy_linkrates *);
159}; 165};
160 166
161 167