diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_sas.c')
-rw-r--r-- | drivers/scsi/scsi_transport_sas.c | 103 |
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 { | |||
155 | sas_bitfield_name_search(linkspeed, sas_linkspeed_names) | 155 | sas_bitfield_name_search(linkspeed, sas_linkspeed_names) |
156 | sas_bitfield_name_set(linkspeed, sas_linkspeed_names) | 156 | sas_bitfield_name_set(linkspeed, sas_linkspeed_names) |
157 | 157 | ||
158 | static 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 | |||
158 | static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost, | 169 | static 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 | } |
359 | EXPORT_SYMBOL(sas_remove_host); | 370 | EXPORT_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 | */ | ||
380 | unsigned int | ||
381 | sas_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 | } | ||
405 | EXPORT_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 | */ | ||
414 | void | ||
415 | sas_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 | } | ||
421 | EXPORT_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 | */ | ||
430 | void 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 | } | ||
443 | EXPORT_SYMBOL_GPL(sas_enable_tlr); | ||
444 | |||
445 | unsigned 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 | } | ||
450 | EXPORT_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); | |||
1146 | int sas_read_port_mode_page(struct scsi_device *sdev) | 1236 | int 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); |
1208 | sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, | 1293 | sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, |
1209 | "%d\n", int); | 1294 | "%d\n", int); |
1295 | sas_end_dev_simple_attr(tlr_supported, tlr_supported, | ||
1296 | "%d\n", int); | ||
1297 | sas_end_dev_simple_attr(tlr_enabled, tlr_enabled, | ||
1298 | "%d\n", int); | ||
1210 | 1299 | ||
1211 | static DECLARE_TRANSPORT_CLASS(sas_expander_class, | 1300 | static 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; |