diff options
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r-- | drivers/ata/libata-scsi.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 9e92107691f2..3c4c5ae277ba 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/libata.h> | 46 | #include <linux/libata.h> |
47 | #include <linux/hdreg.h> | 47 | #include <linux/hdreg.h> |
48 | #include <linux/uaccess.h> | 48 | #include <linux/uaccess.h> |
49 | #include <linux/suspend.h> | ||
49 | 50 | ||
50 | #include "libata.h" | 51 | #include "libata.h" |
51 | 52 | ||
@@ -423,9 +424,9 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, | |||
423 | * RETURNS: | 424 | * RETURNS: |
424 | * Zero on success, negative errno on error. | 425 | * Zero on success, negative errno on error. |
425 | */ | 426 | */ |
426 | static int ata_get_identity(struct scsi_device *sdev, void __user *arg) | 427 | static int ata_get_identity(struct ata_port *ap, struct scsi_device *sdev, |
428 | void __user *arg) | ||
427 | { | 429 | { |
428 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
429 | struct ata_device *dev = ata_scsi_find_dev(ap, sdev); | 430 | struct ata_device *dev = ata_scsi_find_dev(ap, sdev); |
430 | u16 __user *dst = arg; | 431 | u16 __user *dst = arg; |
431 | char buf[40]; | 432 | char buf[40]; |
@@ -645,7 +646,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) | |||
645 | return rc; | 646 | return rc; |
646 | } | 647 | } |
647 | 648 | ||
648 | int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) | 649 | int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev, |
650 | int cmd, void __user *arg) | ||
649 | { | 651 | { |
650 | int val = -EINVAL, rc = -EINVAL; | 652 | int val = -EINVAL, rc = -EINVAL; |
651 | 653 | ||
@@ -663,7 +665,7 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) | |||
663 | return 0; | 665 | return 0; |
664 | 666 | ||
665 | case HDIO_GET_IDENTITY: | 667 | case HDIO_GET_IDENTITY: |
666 | return ata_get_identity(scsidev, arg); | 668 | return ata_get_identity(ap, scsidev, arg); |
667 | 669 | ||
668 | case HDIO_DRIVE_CMD: | 670 | case HDIO_DRIVE_CMD: |
669 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) | 671 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) |
@@ -682,6 +684,14 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) | |||
682 | 684 | ||
683 | return rc; | 685 | return rc; |
684 | } | 686 | } |
687 | EXPORT_SYMBOL_GPL(ata_sas_scsi_ioctl); | ||
688 | |||
689 | int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) | ||
690 | { | ||
691 | return ata_sas_scsi_ioctl(ata_shost_to_port(scsidev->host), | ||
692 | scsidev, cmd, arg); | ||
693 | } | ||
694 | EXPORT_SYMBOL_GPL(ata_scsi_ioctl); | ||
685 | 695 | ||
686 | /** | 696 | /** |
687 | * ata_scsi_qc_new - acquire new ata_queued_cmd reference | 697 | * ata_scsi_qc_new - acquire new ata_queued_cmd reference |
@@ -1294,6 +1304,17 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) | |||
1294 | 1304 | ||
1295 | tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ | 1305 | tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ |
1296 | } else { | 1306 | } else { |
1307 | /* Some odd clown BIOSen issue spindown on power off (ACPI S4 | ||
1308 | * or S5) causing some drives to spin up and down again. | ||
1309 | */ | ||
1310 | if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) && | ||
1311 | system_state == SYSTEM_POWER_OFF) | ||
1312 | goto skip; | ||
1313 | |||
1314 | if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) && | ||
1315 | system_entering_hibernation()) | ||
1316 | goto skip; | ||
1317 | |||
1297 | /* XXX: This is for backward compatibility, will be | 1318 | /* XXX: This is for backward compatibility, will be |
1298 | * removed. Read Documentation/feature-removal-schedule.txt | 1319 | * removed. Read Documentation/feature-removal-schedule.txt |
1299 | * for more info. | 1320 | * for more info. |
@@ -1317,8 +1338,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) | |||
1317 | scmd->scsi_done = qc->scsidone; | 1338 | scmd->scsi_done = qc->scsidone; |
1318 | qc->scsidone = ata_delayed_done; | 1339 | qc->scsidone = ata_delayed_done; |
1319 | } | 1340 | } |
1320 | scmd->result = SAM_STAT_GOOD; | 1341 | goto skip; |
1321 | return 1; | ||
1322 | } | 1342 | } |
1323 | 1343 | ||
1324 | /* Issue ATA STANDBY IMMEDIATE command */ | 1344 | /* Issue ATA STANDBY IMMEDIATE command */ |
@@ -1334,10 +1354,13 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) | |||
1334 | 1354 | ||
1335 | return 0; | 1355 | return 0; |
1336 | 1356 | ||
1337 | invalid_fld: | 1357 | invalid_fld: |
1338 | ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); | 1358 | ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); |
1339 | /* "Invalid field in cbd" */ | 1359 | /* "Invalid field in cbd" */ |
1340 | return 1; | 1360 | return 1; |
1361 | skip: | ||
1362 | scmd->result = SAM_STAT_GOOD; | ||
1363 | return 1; | ||
1341 | } | 1364 | } |
1342 | 1365 | ||
1343 | 1366 | ||