aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_sas_internal.h2
-rw-r--r--drivers/scsi/scsi_transport_sas.c103
-rw-r--r--include/scsi/scsi_transport_sas.h7
3 files changed, 105 insertions, 7 deletions
diff --git a/drivers/scsi/scsi_sas_internal.h b/drivers/scsi/scsi_sas_internal.h
index 998cb5be6833..6266a5d73d0f 100644
--- a/drivers/scsi/scsi_sas_internal.h
+++ b/drivers/scsi/scsi_sas_internal.h
@@ -5,7 +5,7 @@
5#define SAS_PHY_ATTRS 17 5#define SAS_PHY_ATTRS 17
6#define SAS_PORT_ATTRS 1 6#define SAS_PORT_ATTRS 1
7#define SAS_RPORT_ATTRS 7 7#define SAS_RPORT_ATTRS 7
8#define SAS_END_DEV_ATTRS 3 8#define SAS_END_DEV_ATTRS 5
9#define SAS_EXPANDER_ATTRS 7 9#define SAS_EXPANDER_ATTRS 7
10 10
11struct sas_internal { 11struct sas_internal {
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index f27e52d963d3..927e99cb7225 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -155,6 +155,17 @@ static struct {
155sas_bitfield_name_search(linkspeed, sas_linkspeed_names) 155sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
156sas_bitfield_name_set(linkspeed, sas_linkspeed_names) 156sas_bitfield_name_set(linkspeed, sas_linkspeed_names)
157 157
158static struct sas_end_device *sas_sdev_to_rdev(struct scsi_device *sdev)
159{
160 struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target);
161 struct sas_end_device *rdev;
162
163 BUG_ON(rphy->identify.device_type != SAS_END_DEVICE);
164
165 rdev = rphy_to_end_device(rphy);
166 return rdev;
167}
168
158static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost, 169static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
159 struct sas_rphy *rphy) 170 struct sas_rphy *rphy)
160{ 171{
@@ -358,6 +369,85 @@ void sas_remove_host(struct Scsi_Host *shost)
358} 369}
359EXPORT_SYMBOL(sas_remove_host); 370EXPORT_SYMBOL(sas_remove_host);
360 371
372/**
373 * sas_tlr_supported - checking TLR bit in vpd 0x90
374 * @sdev: scsi device struct
375 *
376 * Check Transport Layer Retries are supported or not.
377 * If vpd page 0x90 is present, TRL is supported.
378 *
379 */
380unsigned int
381sas_tlr_supported(struct scsi_device *sdev)
382{
383 const int vpd_len = 32;
384 struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
385 char *buffer = kzalloc(vpd_len, GFP_KERNEL);
386 int ret = 0;
387
388 if (scsi_get_vpd_page(sdev, 0x90, buffer, vpd_len))
389 goto out;
390
391 /*
392 * Magic numbers: the VPD Protocol page (0x90)
393 * has a 4 byte header and then one entry per device port
394 * the TLR bit is at offset 8 on each port entry
395 * if we take the first port, that's at total offset 12
396 */
397 ret = buffer[12] & 0x01;
398
399 out:
400 kfree(buffer);
401 rdev->tlr_supported = ret;
402 return ret;
403
404}
405EXPORT_SYMBOL_GPL(sas_tlr_supported);
406
407/**
408 * sas_disable_tlr - setting TLR flags
409 * @sdev: scsi device struct
410 *
411 * Seting tlr_enabled flag to 0.
412 *
413 */
414void
415sas_disable_tlr(struct scsi_device *sdev)
416{
417 struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
418
419 rdev->tlr_enabled = 0;
420}
421EXPORT_SYMBOL_GPL(sas_disable_tlr);
422
423/**
424 * sas_enable_tlr - setting TLR flags
425 * @sdev: scsi device struct
426 *
427 * Seting tlr_enabled flag 1.
428 *
429 */
430void sas_enable_tlr(struct scsi_device *sdev)
431{
432 unsigned int tlr_supported = 0;
433 tlr_supported = sas_tlr_supported(sdev);
434
435 if (tlr_supported) {
436 struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
437
438 rdev->tlr_enabled = 1;
439 }
440
441 return;
442}
443EXPORT_SYMBOL_GPL(sas_enable_tlr);
444
445unsigned int sas_is_tlr_enabled(struct scsi_device *sdev)
446{
447 struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
448 return rdev->tlr_enabled;
449}
450EXPORT_SYMBOL_GPL(sas_is_tlr_enabled);
361 451
362/* 452/*
363 * SAS Phy attributes 453 * SAS Phy attributes
@@ -1146,15 +1236,10 @@ sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
1146int sas_read_port_mode_page(struct scsi_device *sdev) 1236int sas_read_port_mode_page(struct scsi_device *sdev)
1147{ 1237{
1148 char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; 1238 char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata;
1149 struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target); 1239 struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
1150 struct sas_end_device *rdev;
1151 struct scsi_mode_data mode_data; 1240 struct scsi_mode_data mode_data;
1152 int res, error; 1241 int res, error;
1153 1242
1154 BUG_ON(rphy->identify.device_type != SAS_END_DEVICE);
1155
1156 rdev = rphy_to_end_device(rphy);
1157
1158 if (!buffer) 1243 if (!buffer)
1159 return -ENOMEM; 1244 return -ENOMEM;
1160 1245
@@ -1207,6 +1292,10 @@ sas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout,
1207 "%d\n", int); 1292 "%d\n", int);
1208sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, 1293sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout,
1209 "%d\n", int); 1294 "%d\n", int);
1295sas_end_dev_simple_attr(tlr_supported, tlr_supported,
1296 "%d\n", int);
1297sas_end_dev_simple_attr(tlr_enabled, tlr_enabled,
1298 "%d\n", int);
1210 1299
1211static DECLARE_TRANSPORT_CLASS(sas_expander_class, 1300static DECLARE_TRANSPORT_CLASS(sas_expander_class,
1212 "sas_expander", NULL, NULL, NULL); 1301 "sas_expander", NULL, NULL, NULL);
@@ -1733,6 +1822,8 @@ sas_attach_transport(struct sas_function_template *ft)
1733 SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning); 1822 SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning);
1734 SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout); 1823 SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout);
1735 SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); 1824 SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout);
1825 SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_supported);
1826 SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_enabled);
1736 i->end_dev_attrs[count] = NULL; 1827 i->end_dev_attrs[count] = NULL;
1737 1828
1738 count = 0; 1829 count = 0;
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
index 61ad3594aad6..ffeebc34a4f7 100644
--- a/include/scsi/scsi_transport_sas.h
+++ b/include/scsi/scsi_transport_sas.h
@@ -107,6 +107,8 @@ struct sas_end_device {
107 struct sas_rphy rphy; 107 struct sas_rphy rphy;
108 /* flags */ 108 /* flags */
109 unsigned ready_led_meaning:1; 109 unsigned ready_led_meaning:1;
110 unsigned tlr_supported:1;
111 unsigned tlr_enabled:1;
110 /* parameters */ 112 /* parameters */
111 u16 I_T_nexus_loss_timeout; 113 u16 I_T_nexus_loss_timeout;
112 u16 initiator_response_timeout; 114 u16 initiator_response_timeout;
@@ -181,6 +183,11 @@ extern int sas_phy_add(struct sas_phy *);
181extern void sas_phy_delete(struct sas_phy *); 183extern void sas_phy_delete(struct sas_phy *);
182extern int scsi_is_sas_phy(const struct device *); 184extern int scsi_is_sas_phy(const struct device *);
183 185
186unsigned int sas_tlr_supported(struct scsi_device *);
187unsigned int sas_is_tlr_enabled(struct scsi_device *);
188void sas_disable_tlr(struct scsi_device *);
189void sas_enable_tlr(struct scsi_device *);
190
184extern struct sas_rphy *sas_end_device_alloc(struct sas_port *); 191extern struct sas_rphy *sas_end_device_alloc(struct sas_port *);
185extern struct sas_rphy *sas_expander_alloc(struct sas_port *, enum sas_device_type); 192extern struct sas_rphy *sas_expander_alloc(struct sas_port *, enum sas_device_type);
186void sas_rphy_free(struct sas_rphy *); 193void sas_rphy_free(struct sas_rphy *);