diff options
| -rw-r--r-- | drivers/ata/libata-scsi.c | 122 |
1 files changed, 86 insertions, 36 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 4de273b77abc..395c8591980f 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
| @@ -57,6 +57,9 @@ | |||
| 57 | 57 | ||
| 58 | #define ATA_SCSI_RBUF_SIZE 4096 | 58 | #define ATA_SCSI_RBUF_SIZE 4096 |
| 59 | 59 | ||
| 60 | static DEFINE_SPINLOCK(ata_scsi_rbuf_lock); | ||
| 61 | static u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE]; | ||
| 62 | |||
| 60 | typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc); | 63 | typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc); |
| 61 | 64 | ||
| 62 | static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, | 65 | static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, |
| @@ -2054,6 +2057,53 @@ struct ata_scsi_args { | |||
| 2054 | }; | 2057 | }; |
| 2055 | 2058 | ||
| 2056 | /** | 2059 | /** |
| 2060 | * ata_scsi_rbuf_get - Map response buffer. | ||
| 2061 | * @cmd: SCSI command containing buffer to be mapped. | ||
| 2062 | * @flags: unsigned long variable to store irq enable status | ||
| 2063 | * @copy_in: copy in from user buffer | ||
| 2064 | * | ||
| 2065 | * Prepare buffer for simulated SCSI commands. | ||
| 2066 | * | ||
| 2067 | * LOCKING: | ||
| 2068 | * spin_lock_irqsave(ata_scsi_rbuf_lock) on success | ||
| 2069 | * | ||
| 2070 | * RETURNS: | ||
| 2071 | * Pointer to response buffer. | ||
| 2072 | */ | ||
| 2073 | static void *ata_scsi_rbuf_get(struct scsi_cmnd *cmd, bool copy_in, | ||
| 2074 | unsigned long *flags) | ||
| 2075 | { | ||
| 2076 | spin_lock_irqsave(&ata_scsi_rbuf_lock, *flags); | ||
| 2077 | |||
| 2078 | memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE); | ||
| 2079 | if (copy_in) | ||
| 2080 | sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), | ||
| 2081 | ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE); | ||
| 2082 | return ata_scsi_rbuf; | ||
| 2083 | } | ||
| 2084 | |||
| 2085 | /** | ||
| 2086 | * ata_scsi_rbuf_put - Unmap response buffer. | ||
| 2087 | * @cmd: SCSI command containing buffer to be unmapped. | ||
| 2088 | * @copy_out: copy out result | ||
| 2089 | * @flags: @flags passed to ata_scsi_rbuf_get() | ||
| 2090 | * | ||
| 2091 | * Returns rbuf buffer. The result is copied to @cmd's buffer if | ||
| 2092 | * @copy_back is true. | ||
| 2093 | * | ||
| 2094 | * LOCKING: | ||
| 2095 | * Unlocks ata_scsi_rbuf_lock. | ||
| 2096 | */ | ||
| 2097 | static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, bool copy_out, | ||
| 2098 | unsigned long *flags) | ||
| 2099 | { | ||
| 2100 | if (copy_out) | ||
| 2101 | sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), | ||
| 2102 | ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE); | ||
| 2103 | spin_unlock_irqrestore(&ata_scsi_rbuf_lock, *flags); | ||
| 2104 | } | ||
| 2105 | |||
| 2106 | /** | ||
| 2057 | * ata_scsi_rbuf_fill - wrapper for SCSI command simulators | 2107 | * ata_scsi_rbuf_fill - wrapper for SCSI command simulators |
| 2058 | * @args: device IDENTIFY data / SCSI command of interest. | 2108 | * @args: device IDENTIFY data / SCSI command of interest. |
| 2059 | * @actor: Callback hook for desired SCSI command simulator | 2109 | * @actor: Callback hook for desired SCSI command simulator |
| @@ -2071,22 +2121,17 @@ struct ata_scsi_args { | |||
| 2071 | static void ata_scsi_rbuf_fill(struct ata_scsi_args *args, | 2121 | static void ata_scsi_rbuf_fill(struct ata_scsi_args *args, |
| 2072 | unsigned int (*actor)(struct ata_scsi_args *args, u8 *rbuf)) | 2122 | unsigned int (*actor)(struct ata_scsi_args *args, u8 *rbuf)) |
| 2073 | { | 2123 | { |
| 2124 | u8 *rbuf; | ||
| 2125 | unsigned int rc; | ||
| 2074 | struct scsi_cmnd *cmd = args->cmd; | 2126 | struct scsi_cmnd *cmd = args->cmd; |
| 2075 | u8 *buf; | 2127 | unsigned long flags; |
| 2076 | 2128 | ||
| 2077 | buf = kzalloc(ATA_SCSI_RBUF_SIZE, GFP_NOIO); | 2129 | rbuf = ata_scsi_rbuf_get(cmd, false, &flags); |
| 2078 | if (!buf) { | 2130 | rc = actor(args, rbuf); |
| 2079 | ata_scsi_set_sense(args->dev, cmd, NOT_READY, 0x08, 0); | 2131 | ata_scsi_rbuf_put(cmd, rc == 0, &flags); |
| 2080 | return; | ||
| 2081 | } | ||
| 2082 | 2132 | ||
| 2083 | if (actor(args, buf) == 0) { | 2133 | if (rc == 0) |
| 2084 | sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), | ||
| 2085 | buf, ATA_SCSI_RBUF_SIZE); | ||
| 2086 | cmd->result = SAM_STAT_GOOD; | 2134 | cmd->result = SAM_STAT_GOOD; |
| 2087 | } | ||
| 2088 | |||
| 2089 | kfree(buf); | ||
| 2090 | } | 2135 | } |
| 2091 | 2136 | ||
| 2092 | /** | 2137 | /** |
| @@ -3318,17 +3363,24 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) | |||
| 3318 | * | 3363 | * |
| 3319 | * Return: Number of bytes copied into sglist. | 3364 | * Return: Number of bytes copied into sglist. |
| 3320 | */ | 3365 | */ |
| 3321 | static ssize_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax, | 3366 | static size_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax, |
| 3322 | u64 sector, u32 count) | 3367 | u64 sector, u32 count) |
| 3323 | { | 3368 | { |
| 3369 | struct scsi_device *sdp = cmd->device; | ||
| 3370 | size_t len = sdp->sector_size; | ||
| 3324 | size_t r; | 3371 | size_t r; |
| 3325 | __le64 *buf; | 3372 | __le64 *buf; |
| 3326 | u32 i = 0; | 3373 | u32 i = 0; |
| 3374 | unsigned long flags; | ||
| 3327 | 3375 | ||
| 3328 | buf = kzalloc(cmd->device->sector_size, GFP_NOFS); | 3376 | WARN_ON(len > ATA_SCSI_RBUF_SIZE); |
| 3329 | if (!buf) | ||
| 3330 | return -ENOMEM; | ||
| 3331 | 3377 | ||
| 3378 | if (len > ATA_SCSI_RBUF_SIZE) | ||
| 3379 | len = ATA_SCSI_RBUF_SIZE; | ||
| 3380 | |||
| 3381 | spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); | ||
| 3382 | buf = ((void *)ata_scsi_rbuf); | ||
| 3383 | memset(buf, 0, len); | ||
| 3332 | while (i < trmax) { | 3384 | while (i < trmax) { |
| 3333 | u64 entry = sector | | 3385 | u64 entry = sector | |
| 3334 | ((u64)(count > 0xffff ? 0xffff : count) << 48); | 3386 | ((u64)(count > 0xffff ? 0xffff : count) << 48); |
| @@ -3338,9 +3390,9 @@ static ssize_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax, | |||
| 3338 | count -= 0xffff; | 3390 | count -= 0xffff; |
| 3339 | sector += 0xffff; | 3391 | sector += 0xffff; |
| 3340 | } | 3392 | } |
| 3341 | r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, | 3393 | r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, len); |
| 3342 | cmd->device->sector_size); | 3394 | spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); |
| 3343 | kfree(buf); | 3395 | |
| 3344 | return r; | 3396 | return r; |
| 3345 | } | 3397 | } |
| 3346 | 3398 | ||
| @@ -3356,15 +3408,16 @@ static ssize_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax, | |||
| 3356 | * | 3408 | * |
| 3357 | * Return: Number of bytes copied into sglist. | 3409 | * Return: Number of bytes copied into sglist. |
| 3358 | */ | 3410 | */ |
| 3359 | static ssize_t ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, | 3411 | static size_t ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, u64 num) |
| 3360 | u64 num) | ||
| 3361 | { | 3412 | { |
| 3413 | struct scsi_device *sdp = cmd->device; | ||
| 3414 | size_t len = sdp->sector_size; | ||
| 3362 | size_t r; | 3415 | size_t r; |
| 3363 | u16 *buf; | 3416 | u16 *buf; |
| 3417 | unsigned long flags; | ||
| 3364 | 3418 | ||
| 3365 | buf = kzalloc(cmd->device->sector_size, GFP_NOIO); | 3419 | spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); |
| 3366 | if (!buf) | 3420 | buf = ((void *)ata_scsi_rbuf); |
| 3367 | return -ENOMEM; | ||
| 3368 | 3421 | ||
| 3369 | put_unaligned_le16(0x0002, &buf[0]); /* SCT_ACT_WRITE_SAME */ | 3422 | put_unaligned_le16(0x0002, &buf[0]); /* SCT_ACT_WRITE_SAME */ |
| 3370 | put_unaligned_le16(0x0101, &buf[1]); /* WRITE PTRN FG */ | 3423 | put_unaligned_le16(0x0101, &buf[1]); /* WRITE PTRN FG */ |
| @@ -3372,9 +3425,14 @@ static ssize_t ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, | |||
| 3372 | put_unaligned_le64(num, &buf[6]); | 3425 | put_unaligned_le64(num, &buf[6]); |
| 3373 | put_unaligned_le32(0u, &buf[10]); /* pattern */ | 3426 | put_unaligned_le32(0u, &buf[10]); /* pattern */ |
| 3374 | 3427 | ||
| 3375 | r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, | 3428 | WARN_ON(len > ATA_SCSI_RBUF_SIZE); |
| 3376 | cmd->device->sector_size); | 3429 | |
| 3377 | kfree(buf); | 3430 | if (len > ATA_SCSI_RBUF_SIZE) |
| 3431 | len = ATA_SCSI_RBUF_SIZE; | ||
| 3432 | |||
| 3433 | r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, len); | ||
| 3434 | spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); | ||
| 3435 | |||
| 3378 | return r; | 3436 | return r; |
| 3379 | } | 3437 | } |
| 3380 | 3438 | ||
| @@ -3399,7 +3457,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) | |||
| 3399 | u64 block; | 3457 | u64 block; |
| 3400 | u32 n_block; | 3458 | u32 n_block; |
| 3401 | const u32 trmax = len >> 3; | 3459 | const u32 trmax = len >> 3; |
| 3402 | ssize_t size; | 3460 | u32 size; |
| 3403 | u16 fp; | 3461 | u16 fp; |
| 3404 | u8 bp = 0xff; | 3462 | u8 bp = 0xff; |
| 3405 | u8 unmap = cdb[1] & 0x8; | 3463 | u8 unmap = cdb[1] & 0x8; |
| @@ -3450,8 +3508,6 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) | |||
| 3450 | */ | 3508 | */ |
| 3451 | if (unmap) { | 3509 | if (unmap) { |
| 3452 | size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block); | 3510 | size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block); |
| 3453 | if (size < 0) | ||
| 3454 | goto comm_fail; | ||
| 3455 | if (size != len) | 3511 | if (size != len) |
| 3456 | goto invalid_param_len; | 3512 | goto invalid_param_len; |
| 3457 | 3513 | ||
| @@ -3475,8 +3531,6 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) | |||
| 3475 | } | 3531 | } |
| 3476 | } else { | 3532 | } else { |
| 3477 | size = ata_format_sct_write_same(scmd, block, n_block); | 3533 | size = ata_format_sct_write_same(scmd, block, n_block); |
| 3478 | if (size < 0) | ||
| 3479 | goto comm_fail; | ||
| 3480 | if (size != len) | 3534 | if (size != len) |
| 3481 | goto invalid_param_len; | 3535 | goto invalid_param_len; |
| 3482 | 3536 | ||
| @@ -3515,10 +3569,6 @@ invalid_opcode: | |||
| 3515 | /* "Invalid command operation code" */ | 3569 | /* "Invalid command operation code" */ |
| 3516 | ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0); | 3570 | ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0); |
| 3517 | return 1; | 3571 | return 1; |
| 3518 | comm_fail: | ||
| 3519 | /* "Logical unit communication failure" */ | ||
| 3520 | ata_scsi_set_sense(dev, scmd, NOT_READY, 0x08, 0); | ||
| 3521 | return 1; | ||
| 3522 | } | 3572 | } |
| 3523 | 3573 | ||
| 3524 | /** | 3574 | /** |
