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

libata: remove SCT WRITE SAME support

This was already disabled a while ago because it caused I/O errors,
and it's severly getting into the way of the discard / write zeroes
rework.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

Christoph Hellwig and committed by
Tejun Heo
63ccc191 c6ade20f

+29 -108
+29 -103
drivers/ata/libata-scsi.c
··· 3393 3393 } 3394 3394 3395 3395 /** 3396 - * ata_format_dsm_trim_descr() - SATL Write Same to ATA SCT Write Same 3397 - * @cmd: SCSI command being translated 3398 - * @lba: Starting sector 3399 - * @num: Number of sectors to be zero'd. 3400 - * 3401 - * Rewrite the WRITE SAME payload to be an SCT Write Same formatted 3402 - * descriptor. 3403 - * NOTE: Writes a pattern (0's) in the foreground. 3404 - * 3405 - * Return: Number of bytes copied into sglist. 3406 - */ 3407 - static size_t ata_format_sct_write_same(struct scsi_cmnd *cmd, u64 lba, u64 num) 3408 - { 3409 - struct scsi_device *sdp = cmd->device; 3410 - size_t len = sdp->sector_size; 3411 - size_t r; 3412 - u16 *buf; 3413 - unsigned long flags; 3414 - 3415 - spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); 3416 - buf = ((void *)ata_scsi_rbuf); 3417 - 3418 - put_unaligned_le16(0x0002, &buf[0]); /* SCT_ACT_WRITE_SAME */ 3419 - put_unaligned_le16(0x0101, &buf[1]); /* WRITE PTRN FG */ 3420 - put_unaligned_le64(lba, &buf[2]); 3421 - put_unaligned_le64(num, &buf[6]); 3422 - put_unaligned_le32(0u, &buf[10]); /* pattern */ 3423 - 3424 - WARN_ON(len > ATA_SCSI_RBUF_SIZE); 3425 - 3426 - if (len > ATA_SCSI_RBUF_SIZE) 3427 - len = ATA_SCSI_RBUF_SIZE; 3428 - 3429 - r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, len); 3430 - spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); 3431 - 3432 - return r; 3433 - } 3434 - 3435 - /** 3436 3396 * ata_scsi_write_same_xlat() - SATL Write Same to ATA SCT Write Same 3437 3397 * @qc: Command to be translated 3438 3398 * ··· 3436 3476 } 3437 3477 scsi_16_lba_len(cdb, &block, &n_block); 3438 3478 3439 - if (unmap) { 3440 - /* If trim is not enabled the cmd is invalid. */ 3441 - if ((dev->horkage & ATA_HORKAGE_NOTRIM) || 3442 - !ata_id_has_trim(dev->id)) { 3443 - fp = 1; 3444 - bp = 3; 3445 - goto invalid_fld; 3446 - } 3447 - /* If the request is too large the cmd is invalid */ 3448 - if (n_block > 0xffff * trmax) { 3449 - fp = 2; 3450 - goto invalid_fld; 3451 - } 3452 - } else { 3453 - /* If write same is not available the cmd is invalid */ 3454 - if (!ata_id_sct_write_same(dev->id)) { 3455 - fp = 1; 3456 - bp = 3; 3457 - goto invalid_fld; 3458 - } 3479 + if (!unmap || 3480 + (dev->horkage & ATA_HORKAGE_NOTRIM) || 3481 + !ata_id_has_trim(dev->id)) { 3482 + fp = 1; 3483 + bp = 3; 3484 + goto invalid_fld; 3485 + } 3486 + /* If the request is too large the cmd is invalid */ 3487 + if (n_block > 0xffff * trmax) { 3488 + fp = 2; 3489 + goto invalid_fld; 3459 3490 } 3460 3491 3461 3492 /* ··· 3461 3510 * For DATA SET MANAGEMENT TRIM in ACS-2 nsect (aka count) 3462 3511 * is defined as number of 512 byte blocks to be transferred. 3463 3512 */ 3464 - if (unmap) { 3465 - size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block); 3466 - if (size != len) 3467 - goto invalid_param_len; 3468 3513 3469 - if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { 3470 - /* Newer devices support queued TRIM commands */ 3471 - tf->protocol = ATA_PROT_NCQ; 3472 - tf->command = ATA_CMD_FPDMA_SEND; 3473 - tf->hob_nsect = ATA_SUBCMD_FPDMA_SEND_DSM & 0x1f; 3474 - tf->nsect = qc->tag << 3; 3475 - tf->hob_feature = (size / 512) >> 8; 3476 - tf->feature = size / 512; 3514 + size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block); 3515 + if (size != len) 3516 + goto invalid_param_len; 3477 3517 3478 - tf->auxiliary = 1; 3479 - } else { 3480 - tf->protocol = ATA_PROT_DMA; 3481 - tf->hob_feature = 0; 3482 - tf->feature = ATA_DSM_TRIM; 3483 - tf->hob_nsect = (size / 512) >> 8; 3484 - tf->nsect = size / 512; 3485 - tf->command = ATA_CMD_DSM; 3486 - } 3518 + if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { 3519 + /* Newer devices support queued TRIM commands */ 3520 + tf->protocol = ATA_PROT_NCQ; 3521 + tf->command = ATA_CMD_FPDMA_SEND; 3522 + tf->hob_nsect = ATA_SUBCMD_FPDMA_SEND_DSM & 0x1f; 3523 + tf->nsect = qc->tag << 3; 3524 + tf->hob_feature = (size / 512) >> 8; 3525 + tf->feature = size / 512; 3526 + 3527 + tf->auxiliary = 1; 3487 3528 } else { 3488 - size = ata_format_sct_write_same(scmd, block, n_block); 3489 - if (size != len) 3490 - goto invalid_param_len; 3491 - 3492 - tf->hob_feature = 0; 3493 - tf->feature = 0; 3494 - tf->hob_nsect = 0; 3495 - tf->nsect = 1; 3496 - tf->lbah = 0; 3497 - tf->lbam = 0; 3498 - tf->lbal = ATA_CMD_STANDBYNOW1; 3499 - tf->hob_lbah = 0; 3500 - tf->hob_lbam = 0; 3501 - tf->hob_lbal = 0; 3502 - tf->device = ATA_CMD_STANDBYNOW1; 3503 3529 tf->protocol = ATA_PROT_DMA; 3504 - tf->command = ATA_CMD_WRITE_LOG_DMA_EXT; 3505 - if (unlikely(dev->flags & ATA_DFLAG_PIO)) 3506 - tf->command = ATA_CMD_WRITE_LOG_EXT; 3530 + tf->hob_feature = 0; 3531 + tf->feature = ATA_DSM_TRIM; 3532 + tf->hob_nsect = (size / 512) >> 8; 3533 + tf->nsect = size / 512; 3534 + tf->command = ATA_CMD_DSM; 3507 3535 } 3508 3536 3509 3537 tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 | ··· 3557 3627 case START_STOP: 3558 3628 supported = 3; 3559 3629 break; 3560 - case WRITE_SAME_16: 3561 - if (!ata_id_sct_write_same(dev->id)) 3562 - break; 3563 - /* fallthrough: if SCT ... only enable for ZBC */ 3564 3630 case ZBC_IN: 3565 3631 case ZBC_OUT: 3566 3632 if (ata_id_zoned_cap(dev->id) ||
-5
include/linux/ata.h
··· 817 817 return id[ATA_ID_SCT_CMD_XPORT] & (1 << 3) ? true : false; 818 818 } 819 819 820 - static inline bool ata_id_sct_write_same(const u16 *id) 821 - { 822 - return id[ATA_ID_SCT_CMD_XPORT] & (1 << 2) ? true : false; 823 - } 824 - 825 820 static inline bool ata_id_sct_long_sector_access(const u16 *id) 826 821 { 827 822 return id[ATA_ID_SCT_CMD_XPORT] & (1 << 1) ? true : false;