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