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.c103
1 files changed, 97 insertions, 6 deletions
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index f27e52d963d..927e99cb722 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;