diff options
| author | Shaun Tancheff <shaun@tancheff.com> | 2016-08-24 14:08:14 -0400 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2016-08-25 11:26:48 -0400 |
| commit | ef2d7392c4ece5c3cd12a6c7ca9366cd8f189aff (patch) | |
| tree | 0f627a1746582b8443f3377718c58d426ef3871c /drivers | |
| parent | 7b20309428598df00ffeb0b01f5948dea6aaf1f7 (diff) | |
libata: SCT Write Same / DSM Trim
Correct handling of devices with sector_size other that 512 bytes.
In the case of a 4Kn device sector_size it is possible to describe a much
larger DSM Trim than the current fixed default of 512 bytes.
This patch assumes the minimum descriptor is sector_size and fills out
the descriptor accordingly.
The ACS-2 specification is quite clear that the DSM command payload is
sized as number of 512 byte transfers so a 4Kn device will operate
correctly without this patch.
Signed-off-by: Shaun Tancheff <shaun.tancheff@seagate.com>
Acked-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/ata/libata-scsi.c | 85 |
1 files changed, 57 insertions, 28 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 08d9c8e731b3..35b1f9e475cc 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
| @@ -3283,7 +3283,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) | |||
| 3283 | /** | 3283 | /** |
| 3284 | * ata_format_dsm_trim_descr() - SATL Write Same to DSM Trim | 3284 | * ata_format_dsm_trim_descr() - SATL Write Same to DSM Trim |
| 3285 | * @cmd: SCSI command being translated | 3285 | * @cmd: SCSI command being translated |
| 3286 | * @num: Maximum number of entries (nominally 64). | 3286 | * @trmax: Maximum number of entries that will fit in sector_size bytes. |
| 3287 | * @sector: Starting sector | 3287 | * @sector: Starting sector |
| 3288 | * @count: Total Range of request in logical sectors | 3288 | * @count: Total Range of request in logical sectors |
| 3289 | * | 3289 | * |
| @@ -3298,63 +3298,80 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) | |||
| 3298 | * LBA's should be sorted order and not overlap. | 3298 | * LBA's should be sorted order and not overlap. |
| 3299 | * | 3299 | * |
| 3300 | * NOTE: this is the same format as ADD LBA(S) TO NV CACHE PINNED SET | 3300 | * NOTE: this is the same format as ADD LBA(S) TO NV CACHE PINNED SET |
| 3301 | * | ||
| 3302 | * Return: Number of bytes copied into sglist. | ||
| 3301 | */ | 3303 | */ |
| 3302 | static unsigned int ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 num, | 3304 | static size_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax, |
| 3303 | u64 sector, u32 count) | 3305 | u64 sector, u32 count) |
| 3304 | { | 3306 | { |
| 3305 | __le64 *buffer; | 3307 | struct scsi_device *sdp = cmd->device; |
| 3306 | u32 i = 0, used_bytes; | 3308 | size_t len = sdp->sector_size; |
| 3309 | size_t r; | ||
| 3310 | __le64 *buf; | ||
| 3311 | u32 i = 0; | ||
| 3307 | unsigned long flags; | 3312 | unsigned long flags; |
| 3308 | 3313 | ||
| 3309 | BUILD_BUG_ON(512 > ATA_SCSI_RBUF_SIZE); | 3314 | WARN_ON(len > ATA_SCSI_RBUF_SIZE); |
| 3315 | |||
| 3316 | if (len > ATA_SCSI_RBUF_SIZE) | ||
| 3317 | len = ATA_SCSI_RBUF_SIZE; | ||
| 3310 | 3318 | ||
| 3311 | spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); | 3319 | spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); |
| 3312 | buffer = ((void *)ata_scsi_rbuf); | 3320 | buf = ((void *)ata_scsi_rbuf); |
| 3313 | while (i < num) { | 3321 | memset(buf, 0, len); |
| 3322 | while (i < trmax) { | ||
| 3314 | u64 entry = sector | | 3323 | u64 entry = sector | |
| 3315 | ((u64)(count > 0xffff ? 0xffff : count) << 48); | 3324 | ((u64)(count > 0xffff ? 0xffff : count) << 48); |
| 3316 | buffer[i++] = __cpu_to_le64(entry); | 3325 | buf[i++] = __cpu_to_le64(entry); |
| 3317 | if (count <= 0xffff) | 3326 | if (count <= 0xffff) |
| 3318 | break; | 3327 | break; |
| 3319 | count -= 0xffff; | 3328 | count -= 0xffff; |
| 3320 | sector += 0xffff; | 3329 | sector += 0xffff; |
| 3321 | } | 3330 | } |
| 3322 | 3331 | r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, len); | |
| 3323 | used_bytes = ALIGN(i * 8, 512); | ||
| 3324 | memset(buffer + i, 0, used_bytes - i * 8); | ||
| 3325 | sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buffer, 512); | ||
| 3326 | spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); | 3332 | spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); |
| 3327 | 3333 | ||
| 3328 | return used_bytes; | 3334 | return r; |
| 3329 | } | 3335 | } |
| 3330 | 3336 | ||
| 3331 | /** | 3337 | /** |
| 3332 | * ata_format_dsm_trim_descr() - SATL Write Same to ATA SCT Write Same | 3338 | * ata_format_dsm_trim_descr() - SATL Write Same to ATA SCT Write Same |
| 3333 | * @cmd: SCSI command being translated | 3339 | * @cmd: SCSI command being translated |
| 3334 | * @lba: Starting sector | 3340 | * @lba: Starting sector |
| 3335 | * @num: Number of logical sectors to be zero'd. | 3341 | * @num: Number of sectors to be zero'd. |
| 3336 | * | 3342 | * |
| 3337 | * Rewrite the WRITE SAME descriptor to be an SCT Write Same formatted | 3343 | * Rewrite the WRITE SAME payload to be an SCT Write Same formatted |
| 3338 | * descriptor. | 3344 | * descriptor. |
| 3339 | * NOTE: Writes a pattern (0's) in the foreground. | 3345 | * NOTE: Writes a pattern (0's) in the foreground. |
| 3340 | * Large write-same requents can timeout. | 3346 | * |
| 3347 | * Return: Number of bytes copied into sglist. | ||
| 3341 | */ | 3348 | */ |
| 3342 | static void ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, u64 num) | 3349 | static size_t ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, u64 num) |
| 3343 | { | 3350 | { |
| 3344 | u16 *sctpg; | 3351 | struct scsi_device *sdp = cmd->device; |
| 3352 | size_t len = sdp->sector_size; | ||
| 3353 | size_t r; | ||
| 3354 | u16 *buf; | ||
| 3345 | unsigned long flags; | 3355 | unsigned long flags; |
| 3346 | 3356 | ||
| 3347 | spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); | 3357 | spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); |
| 3348 | sctpg = ((void *)ata_scsi_rbuf); | 3358 | buf = ((void *)ata_scsi_rbuf); |
| 3359 | |||
| 3360 | put_unaligned_le16(0x0002, &buf[0]); /* SCT_ACT_WRITE_SAME */ | ||
| 3361 | put_unaligned_le16(0x0101, &buf[1]); /* WRITE PTRN FG */ | ||
| 3362 | put_unaligned_le64(lba, &buf[2]); | ||
| 3363 | put_unaligned_le64(num, &buf[6]); | ||
| 3364 | put_unaligned_le32(0u, &buf[10]); /* pattern */ | ||
| 3365 | |||
| 3366 | WARN_ON(len > ATA_SCSI_RBUF_SIZE); | ||
| 3349 | 3367 | ||
| 3350 | put_unaligned_le16(0x0002, &sctpg[0]); /* SCT_ACT_WRITE_SAME */ | 3368 | if (len > ATA_SCSI_RBUF_SIZE) |
| 3351 | put_unaligned_le16(0x0101, &sctpg[1]); /* WRITE PTRN FG */ | 3369 | len = ATA_SCSI_RBUF_SIZE; |
| 3352 | put_unaligned_le64(lba, &sctpg[2]); | ||
| 3353 | put_unaligned_le64(num, &sctpg[6]); | ||
| 3354 | put_unaligned_le32(0u, &sctpg[10]); | ||
| 3355 | 3370 | ||
| 3356 | sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), sctpg, 512); | 3371 | r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, len); |
| 3357 | spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); | 3372 | spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); |
| 3373 | |||
| 3374 | return r; | ||
| 3358 | } | 3375 | } |
| 3359 | 3376 | ||
| 3360 | /** | 3377 | /** |
| @@ -3371,11 +3388,13 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) | |||
| 3371 | { | 3388 | { |
| 3372 | struct ata_taskfile *tf = &qc->tf; | 3389 | struct ata_taskfile *tf = &qc->tf; |
| 3373 | struct scsi_cmnd *scmd = qc->scsicmd; | 3390 | struct scsi_cmnd *scmd = qc->scsicmd; |
| 3391 | struct scsi_device *sdp = scmd->device; | ||
| 3392 | size_t len = sdp->sector_size; | ||
| 3374 | struct ata_device *dev = qc->dev; | 3393 | struct ata_device *dev = qc->dev; |
| 3375 | const u8 *cdb = scmd->cmnd; | 3394 | const u8 *cdb = scmd->cmnd; |
| 3376 | u64 block; | 3395 | u64 block; |
| 3377 | u32 n_block; | 3396 | u32 n_block; |
| 3378 | const u32 trmax = ATA_MAX_TRIM_RNUM; | 3397 | const u32 trmax = len >> 3; |
| 3379 | u32 size; | 3398 | u32 size; |
| 3380 | u16 fp; | 3399 | u16 fp; |
| 3381 | u8 bp = 0xff; | 3400 | u8 bp = 0xff; |
| @@ -3420,8 +3439,16 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) | |||
| 3420 | if (!scsi_sg_count(scmd)) | 3439 | if (!scsi_sg_count(scmd)) |
| 3421 | goto invalid_param_len; | 3440 | goto invalid_param_len; |
| 3422 | 3441 | ||
| 3442 | /* | ||
| 3443 | * size must match sector size in bytes | ||
| 3444 | * For DATA SET MANAGEMENT TRIM in ACS-2 nsect (aka count) | ||
| 3445 | * is defined as number of 512 byte blocks to be transferred. | ||
| 3446 | */ | ||
| 3423 | if (unmap) { | 3447 | if (unmap) { |
| 3424 | size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block); | 3448 | size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block); |
| 3449 | if (size != len) | ||
| 3450 | goto invalid_param_len; | ||
| 3451 | |||
| 3425 | if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { | 3452 | if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { |
| 3426 | /* Newer devices support queued TRIM commands */ | 3453 | /* Newer devices support queued TRIM commands */ |
| 3427 | tf->protocol = ATA_PROT_NCQ; | 3454 | tf->protocol = ATA_PROT_NCQ; |
| @@ -3441,7 +3468,9 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) | |||
| 3441 | tf->command = ATA_CMD_DSM; | 3468 | tf->command = ATA_CMD_DSM; |
| 3442 | } | 3469 | } |
| 3443 | } else { | 3470 | } else { |
| 3444 | ata_format_sct_write_same(scmd, block, n_block); | 3471 | size = ata_format_sct_write_same(scmd, block, n_block); |
| 3472 | if (size != len) | ||
| 3473 | goto invalid_param_len; | ||
| 3445 | 3474 | ||
| 3446 | tf->hob_feature = 0; | 3475 | tf->hob_feature = 0; |
| 3447 | tf->feature = 0; | 3476 | tf->feature = 0; |
