Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libata: Add support for SCT Write Same

SATA drives may support write same via SCT. This is useful
for setting the drive contents to a specific pattern (0's).

Translate a SCSI WRITE SAME 16 command to be either a DSM TRIM
command or an SCT Write Same command.

Based on the UNMAP flag:
- When set translate to DSM TRIM
- When not set translate to SCT Write Same

Signed-off-by: Shaun Tancheff <shaun.tancheff@seagate.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Acked-by: Tejun Heo <tj@kernel.org>

authored by

Shaun Tancheff and committed by
Tejun Heo
7b203094 9379e6b8

+213 -29
+170 -29
drivers/ata/libata-scsi.c
··· 1159 1159 { 1160 1160 sdev->use_10_for_rw = 1; 1161 1161 sdev->use_10_for_ms = 1; 1162 - sdev->no_report_opcodes = 1; 1163 - sdev->no_write_same = 1; 1164 1162 1165 1163 /* Schedule policy is determined by ->qc_defer() callback and 1166 1164 * it needs to see every deferred qc. Set dev_blocked to 1 to ··· 3285 3287 * @cmd: SCSI command being translated 3286 3288 * @num: Maximum number of entries (nominally 64). 3287 3289 * @sector: Starting sector 3288 - * @count: Total Range of request 3290 + * @count: Total Range of request in logical sectors 3289 3291 * 3290 3292 * Rewrite the WRITE SAME descriptor to be a DSM TRIM little-endian formatted 3291 3293 * descriptor. ··· 3328 3330 return used_bytes; 3329 3331 } 3330 3332 3333 + /** 3334 + * ata_format_dsm_trim_descr() - SATL Write Same to ATA SCT Write Same 3335 + * @cmd: SCSI command being translated 3336 + * @lba: Starting sector 3337 + * @num: Number of logical sectors to be zero'd. 3338 + * 3339 + * Rewrite the WRITE SAME descriptor to be an SCT Write Same formatted 3340 + * descriptor. 3341 + * NOTE: Writes a pattern (0's) in the foreground. 3342 + * Large write-same requents can timeout. 3343 + */ 3344 + static void ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, u64 num) 3345 + { 3346 + u16 *sctpg; 3347 + unsigned long flags; 3348 + 3349 + spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); 3350 + sctpg = ((void *)ata_scsi_rbuf); 3351 + 3352 + put_unaligned_le16(0x0002, &sctpg[0]); /* SCT_ACT_WRITE_SAME */ 3353 + put_unaligned_le16(0x0101, &sctpg[1]); /* WRITE PTRN FG */ 3354 + put_unaligned_le64(lba, &sctpg[2]); 3355 + put_unaligned_le64(num, &sctpg[6]); 3356 + put_unaligned_le32(0u, &sctpg[10]); 3357 + 3358 + sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), sctpg, 512); 3359 + spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); 3360 + } 3361 + 3362 + /** 3363 + * ata_scsi_write_same_xlat() - SATL Write Same to ATA SCT Write Same 3364 + * @qc: Command to be translated 3365 + * 3366 + * Translate a SCSI WRITE SAME command to be either a DSM TRIM command or 3367 + * an SCT Write Same command. 3368 + * Based on WRITE SAME has the UNMAP flag 3369 + * When set translate to DSM TRIM 3370 + * When clear translate to SCT Write Same 3371 + */ 3331 3372 static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) 3332 3373 { 3333 3374 struct ata_taskfile *tf = &qc->tf; ··· 3379 3342 u32 size; 3380 3343 u16 fp; 3381 3344 u8 bp = 0xff; 3345 + u8 unmap = cdb[1] & 0x8; 3382 3346 3383 3347 /* we may not issue DMA commands if no DMA mode is set */ 3384 3348 if (unlikely(!dev->dma_mode)) ··· 3391 3353 } 3392 3354 scsi_16_lba_len(cdb, &block, &n_block); 3393 3355 3394 - /* for now we only support WRITE SAME with the unmap bit set */ 3395 - if (unlikely(!(cdb[1] & 0x8))) { 3396 - fp = 1; 3397 - bp = 3; 3398 - goto invalid_fld; 3356 + if (unmap) { 3357 + /* If trim is not enabled the cmd is invalid. */ 3358 + if ((dev->horkage & ATA_HORKAGE_NOTRIM) || 3359 + !ata_id_has_trim(dev->id)) { 3360 + fp = 1; 3361 + bp = 3; 3362 + goto invalid_fld; 3363 + } 3364 + /* If the request is too large the cmd is invalid */ 3365 + if (n_block > 0xffff * trmax) { 3366 + fp = 2; 3367 + goto invalid_fld; 3368 + } 3369 + } else { 3370 + /* If write same is not available the cmd is invalid */ 3371 + if (!ata_id_sct_write_same(dev->id)) { 3372 + fp = 1; 3373 + bp = 3; 3374 + goto invalid_fld; 3375 + } 3399 3376 } 3400 3377 3401 3378 /* ··· 3420 3367 if (!scsi_sg_count(scmd)) 3421 3368 goto invalid_param_len; 3422 3369 3423 - if (n_block <= 0xffff * trmax) { 3370 + if (unmap) { 3424 3371 size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block); 3425 - } else { 3426 - fp = 2; 3427 - goto invalid_fld; 3428 - } 3372 + if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { 3373 + /* Newer devices support queued TRIM commands */ 3374 + tf->protocol = ATA_PROT_NCQ; 3375 + tf->command = ATA_CMD_FPDMA_SEND; 3376 + tf->hob_nsect = ATA_SUBCMD_FPDMA_SEND_DSM & 0x1f; 3377 + tf->nsect = qc->tag << 3; 3378 + tf->hob_feature = (size / 512) >> 8; 3379 + tf->feature = size / 512; 3429 3380 3430 - if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { 3431 - /* Newer devices support queued TRIM commands */ 3432 - tf->protocol = ATA_PROT_NCQ; 3433 - tf->command = ATA_CMD_FPDMA_SEND; 3434 - tf->hob_nsect = ATA_SUBCMD_FPDMA_SEND_DSM & 0x1f; 3435 - tf->nsect = qc->tag << 3; 3436 - tf->hob_feature = (size / 512) >> 8; 3437 - tf->feature = size / 512; 3438 - 3439 - tf->auxiliary = 1; 3381 + tf->auxiliary = 1; 3382 + } else { 3383 + tf->protocol = ATA_PROT_DMA; 3384 + tf->hob_feature = 0; 3385 + tf->feature = ATA_DSM_TRIM; 3386 + tf->hob_nsect = (size / 512) >> 8; 3387 + tf->nsect = size / 512; 3388 + tf->command = ATA_CMD_DSM; 3389 + } 3440 3390 } else { 3441 - tf->protocol = ATA_PROT_DMA; 3391 + ata_format_sct_write_same(scmd, block, n_block); 3392 + 3442 3393 tf->hob_feature = 0; 3443 - tf->feature = ATA_DSM_TRIM; 3444 - tf->hob_nsect = (size / 512) >> 8; 3445 - tf->nsect = size / 512; 3446 - tf->command = ATA_CMD_DSM; 3394 + tf->feature = 0; 3395 + tf->hob_nsect = 0; 3396 + tf->nsect = 1; 3397 + tf->lbah = 0; 3398 + tf->lbam = 0; 3399 + tf->lbal = ATA_CMD_STANDBYNOW1; 3400 + tf->hob_lbah = 0; 3401 + tf->hob_lbam = 0; 3402 + tf->hob_lbal = 0; 3403 + tf->device = ATA_CMD_STANDBYNOW1; 3404 + tf->protocol = ATA_PROT_DMA; 3405 + tf->command = ATA_CMD_WRITE_LOG_DMA_EXT; 3447 3406 } 3448 3407 3449 3408 tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 | ··· 3476 3411 /* "Invalid command operation code" */ 3477 3412 ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0); 3478 3413 return 1; 3414 + } 3415 + 3416 + /** 3417 + * ata_scsiop_maint_in - Simulate a subset of MAINTENANCE_IN 3418 + * @args: device MAINTENANCE_IN data / SCSI command of interest. 3419 + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. 3420 + * 3421 + * Yields a subset to satisfy scsi_report_opcode() 3422 + * 3423 + * LOCKING: 3424 + * spin_lock_irqsave(host lock) 3425 + */ 3426 + static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) 3427 + { 3428 + struct ata_device *dev = args->dev; 3429 + u8 *cdb = args->cmd->cmnd; 3430 + u8 supported = 0; 3431 + unsigned int err = 0; 3432 + 3433 + if (cdb[2] != 1) { 3434 + ata_dev_warn(dev, "invalid command format %d\n", cdb[2]); 3435 + err = 2; 3436 + goto out; 3437 + } 3438 + switch (cdb[3]) { 3439 + case INQUIRY: 3440 + case MODE_SENSE: 3441 + case MODE_SENSE_10: 3442 + case READ_CAPACITY: 3443 + case SERVICE_ACTION_IN_16: 3444 + case REPORT_LUNS: 3445 + case REQUEST_SENSE: 3446 + case SYNCHRONIZE_CACHE: 3447 + case REZERO_UNIT: 3448 + case SEEK_6: 3449 + case SEEK_10: 3450 + case TEST_UNIT_READY: 3451 + case SEND_DIAGNOSTIC: 3452 + case MAINTENANCE_IN: 3453 + case READ_6: 3454 + case READ_10: 3455 + case READ_16: 3456 + case WRITE_6: 3457 + case WRITE_10: 3458 + case WRITE_16: 3459 + case ATA_12: 3460 + case ATA_16: 3461 + case VERIFY: 3462 + case VERIFY_16: 3463 + case MODE_SELECT: 3464 + case MODE_SELECT_10: 3465 + case START_STOP: 3466 + supported = 3; 3467 + break; 3468 + case WRITE_SAME_16: 3469 + if (ata_id_sct_write_same(dev->id)) 3470 + supported = 3; 3471 + break; 3472 + case ZBC_IN: 3473 + case ZBC_OUT: 3474 + if (ata_id_zoned_cap(dev->id) || 3475 + dev->class == ATA_DEV_ZAC) 3476 + supported = 3; 3477 + break; 3478 + default: 3479 + break; 3480 + } 3481 + out: 3482 + rbuf[1] = supported; /* supported */ 3483 + return err; 3479 3484 } 3480 3485 3481 3486 /** ··· 4328 4193 ata_scsi_invalid_field(dev, cmd, 1); 4329 4194 break; 4330 4195 4196 + case MAINTENANCE_IN: 4197 + if (scsicmd[1] == MI_REPORT_SUPPORTED_OPERATION_CODES) 4198 + ata_scsi_rbuf_fill(&args, ata_scsiop_maint_in); 4199 + else 4200 + ata_scsi_invalid_field(dev, cmd, 1); 4201 + break; 4202 + 4331 4203 /* all other commands */ 4332 4204 default: 4333 4205 ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x20, 0x0); ··· 4367 4225 shost->max_lun = 1; 4368 4226 shost->max_channel = 1; 4369 4227 shost->max_cmd_len = 16; 4370 - shost->no_write_same = 1; 4371 4228 4372 4229 /* Schedule policy is determined by ->qc_defer() 4373 4230 * callback and it needs to see every deferred qc.
+43
include/linux/ata.h
··· 105 105 ATA_ID_CFA_KEY_MGMT = 162, 106 106 ATA_ID_CFA_MODES = 163, 107 107 ATA_ID_DATA_SET_MGMT = 169, 108 + ATA_ID_SCT_CMD_XPORT = 206, 108 109 ATA_ID_ROT_SPEED = 217, 109 110 ATA_ID_PIO4 = (1 << 1), 110 111 ··· 787 786 if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15))) 788 787 return false; 789 788 return id[ATA_ID_COMMAND_SET_4] & (1 << 6); 789 + } 790 + 791 + /** 792 + * 793 + * Word: 206 - SCT Command Transport 794 + * 15:12 - Vendor Specific 795 + * 11:6 - Reserved 796 + * 5 - SCT Command Transport Data Tables supported 797 + * 4 - SCT Command Transport Features Control supported 798 + * 3 - SCT Command Transport Error Recovery Control supported 799 + * 2 - SCT Command Transport Write Same supported 800 + * 1 - SCT Command Transport Long Sector Access supported 801 + * 0 - SCT Command Transport supported 802 + */ 803 + static inline bool ata_id_sct_data_tables(const u16 *id) 804 + { 805 + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 5) ? true : false; 806 + } 807 + 808 + static inline bool ata_id_sct_features_ctrl(const u16 *id) 809 + { 810 + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 4) ? true : false; 811 + } 812 + 813 + static inline bool ata_id_sct_error_recovery_ctrl(const u16 *id) 814 + { 815 + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 3) ? true : false; 816 + } 817 + 818 + static inline bool ata_id_sct_write_same(const u16 *id) 819 + { 820 + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 2) ? true : false; 821 + } 822 + 823 + static inline bool ata_id_sct_long_sector_access(const u16 *id) 824 + { 825 + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 1) ? true : false; 826 + } 827 + 828 + static inline bool ata_id_sct_supported(const u16 *id) 829 + { 830 + return id[ATA_ID_SCT_CMD_XPORT] & (1 << 0) ? true : false; 790 831 } 791 832 792 833 /**