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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ata-6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux

Pull ata fixes from Damien Le Moal:

- Fix the incorrect return type of ata_mselect_control_ata_feature()

- Several fixes for the control of the Command Duration Limits feature
to avoid unnecessary enable and disable actions. Avoiding the
unnecessary enable action also avoids unwanted resets of the CDL
statistics log page as that is implied for any enable action.

- Fix the translation for sensing the control mode page to correctly
return the last enable or disable action performed, as defined in
SAT-6. This correct mode sense information is used to fix the
behavior of the scsi layer to avoid unnecessary mode select command
issuing.

* tag 'ata-6.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
scsi: Improve CDL control
ata: libata-scsi: Improve CDL control
ata: libata-scsi: Fix ata_msense_control_ata_feature()
ata: libata-scsi: Fix ata_mselect_control_ata_feature() return type

+41 -20
+17 -8
drivers/ata/libata-scsi.c
··· 2453 2453 */ 2454 2454 put_unaligned_be16(ATA_FEATURE_SUB_MPAGE_LEN - 4, &buf[2]); 2455 2455 2456 - if (dev->flags & ATA_DFLAG_CDL) 2457 - buf[4] = 0x02; /* Support T2A and T2B pages */ 2456 + if (dev->flags & ATA_DFLAG_CDL_ENABLED) 2457 + buf[4] = 0x02; /* T2A and T2B pages enabled */ 2458 2458 else 2459 2459 buf[4] = 0; 2460 2460 ··· 3886 3886 } 3887 3887 3888 3888 /* 3889 - * Translate MODE SELECT control mode page, sub-pages f2h (ATA feature mode 3889 + * Translate MODE SELECT control mode page, sub-page f2h (ATA feature mode 3890 3890 * page) into a SET FEATURES command. 3891 3891 */ 3892 - static unsigned int ata_mselect_control_ata_feature(struct ata_queued_cmd *qc, 3893 - const u8 *buf, int len, 3894 - u16 *fp) 3892 + static int ata_mselect_control_ata_feature(struct ata_queued_cmd *qc, 3893 + const u8 *buf, int len, u16 *fp) 3895 3894 { 3896 3895 struct ata_device *dev = qc->dev; 3897 3896 struct ata_taskfile *tf = &qc->tf; ··· 3908 3909 /* Check cdl_ctrl */ 3909 3910 switch (buf[0] & 0x03) { 3910 3911 case 0: 3911 - /* Disable CDL */ 3912 + /* Disable CDL if it is enabled */ 3913 + if (!(dev->flags & ATA_DFLAG_CDL_ENABLED)) 3914 + return 0; 3915 + ata_dev_dbg(dev, "Disabling CDL\n"); 3912 3916 cdl_action = 0; 3913 3917 dev->flags &= ~ATA_DFLAG_CDL_ENABLED; 3914 3918 break; 3915 3919 case 0x02: 3916 - /* Enable CDL T2A/T2B: NCQ priority must be disabled */ 3920 + /* 3921 + * Enable CDL if not already enabled. Since this is mutually 3922 + * exclusive with NCQ priority, allow this only if NCQ priority 3923 + * is disabled. 3924 + */ 3925 + if (dev->flags & ATA_DFLAG_CDL_ENABLED) 3926 + return 0; 3917 3927 if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED) { 3918 3928 ata_dev_err(dev, 3919 3929 "NCQ priority must be disabled to enable CDL\n"); 3920 3930 return -EINVAL; 3921 3931 } 3932 + ata_dev_dbg(dev, "Enabling CDL\n"); 3922 3933 cdl_action = 1; 3923 3934 dev->flags |= ATA_DFLAG_CDL_ENABLED; 3924 3935 break;
+24 -12
drivers/scsi/scsi.c
··· 707 707 */ 708 708 int scsi_cdl_enable(struct scsi_device *sdev, bool enable) 709 709 { 710 - struct scsi_mode_data data; 711 - struct scsi_sense_hdr sshdr; 712 - struct scsi_vpd *vpd; 713 - bool is_ata = false; 714 710 char buf[64]; 711 + bool is_ata; 715 712 int ret; 716 713 717 714 if (!sdev->cdl_supported) 718 715 return -EOPNOTSUPP; 719 716 720 717 rcu_read_lock(); 721 - vpd = rcu_dereference(sdev->vpd_pg89); 722 - if (vpd) 723 - is_ata = true; 718 + is_ata = rcu_dereference(sdev->vpd_pg89); 724 719 rcu_read_unlock(); 725 720 726 721 /* 727 722 * For ATA devices, CDL needs to be enabled with a SET FEATURES command. 728 723 */ 729 724 if (is_ata) { 725 + struct scsi_mode_data data; 726 + struct scsi_sense_hdr sshdr; 730 727 char *buf_data; 731 728 int len; 732 729 ··· 732 735 if (ret) 733 736 return -EINVAL; 734 737 735 - /* Enable CDL using the ATA feature page */ 738 + /* Enable or disable CDL using the ATA feature page */ 736 739 len = min_t(size_t, sizeof(buf), 737 740 data.length - data.header_length - 738 741 data.block_descriptor_length); 739 742 buf_data = buf + data.header_length + 740 743 data.block_descriptor_length; 741 - if (enable) 742 - buf_data[4] = 0x02; 743 - else 744 - buf_data[4] = 0; 744 + 745 + /* 746 + * If we want to enable CDL and CDL is already enabled on the 747 + * device, do nothing. This avoids needlessly resetting the CDL 748 + * statistics on the device as that is implied by the CDL enable 749 + * action. Similar to this, there is no need to do anything if 750 + * we want to disable CDL and CDL is already disabled. 751 + */ 752 + if (enable) { 753 + if ((buf_data[4] & 0x03) == 0x02) 754 + goto out; 755 + buf_data[4] &= ~0x03; 756 + buf_data[4] |= 0x02; 757 + } else { 758 + if ((buf_data[4] & 0x03) == 0x00) 759 + goto out; 760 + buf_data[4] &= ~0x03; 761 + } 745 762 746 763 ret = scsi_mode_select(sdev, 1, 0, buf_data, len, 5 * HZ, 3, 747 764 &data, &sshdr); ··· 767 756 } 768 757 } 769 758 759 + out: 770 760 sdev->cdl_enable = enable; 771 761 772 762 return 0;