From 86dcc5dea79ab7dc2517174aa784a2844096857e Mon Sep 17 00:00:00 2001 From: Lee Duncan <lduncan@suse.com> Date: Jun 02 2025 19:53:20 +0000 Subject: scsi: Improve CDL control (git-fixes). --- diff --git a/patches.suse/scsi-Improve-CDL-control.patch b/patches.suse/scsi-Improve-CDL-control.patch new file mode 100644 index 0000000..1f1b4b4 --- /dev/null +++ b/patches.suse/scsi-Improve-CDL-control.patch @@ -0,0 +1,122 @@ +From: Damien Le Moal <dlemoal@kernel.org> +Date: Sun, 13 Apr 2025 11:24:47 +0900 +Subject: scsi: Improve CDL control +Git-commit: 14a3cc755825ef7b34c986aa2786ea815023e9c5 +Patch-mainline: v6.15-rc4 +References: git-fixes + +With ATA devices supporting the CDL feature, using CDL requires that the +feature be enabled with a SET FEATURES command. This command is issued +as the translated command for the MODE SELECT command issued by +scsi_cdl_enable() when the user enables CDL through the device +cdl_enable sysfs attribute. + +However, the implementation of scsi_cdl_enable() always issues a MODE +SELECT command for ATA devices when the enable argument is true, even if +CDL is already enabled on the device. While this does not cause any +issue with using CDL descriptors with read/write commands (the CDL +feature will be enabled on the drive), issuing the MODE SELECT command +even when the device CDL feature is already enabled will cause a reset +of the ATA device CDL statistics log page (as defined in ACS, any CDL +enable action must reset the device statistics). + +Avoid this needless actions (and the implied statistics log page reset) +by modifying scsi_cdl_enable() to issue the MODE SELECT command to +enable CDL if and only if CDL is not reported as already enabled on the +device. + +And while at it, simplify the initialization of the is_ata boolean +variable and move the declaration of the scsi mode data and sense header +variables to within the scope of ATA device handling. + +Fixes: 1b22cfb14142 ("scsi: core: Allow enabling and disabling command duration limits") +Cc: stable@vger.kernel.org +Signed-off-by: Damien Le Moal <dlemoal@kernel.org> +Reviewed-by: Niklas Cassel <cassel@kernel.org> +Reviewed-by: Igor Pylypiv <ipylypiv@google.com> +Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> +Acked-by: Lee Duncan <lduncan@suse.com> +--- + drivers/scsi/scsi.c | 36 ++++++++++++++++++++++++------------ + 1 file changed, 24 insertions(+), 12 deletions(-) + +diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c +index 53daf923ad8e..518a252eb6aa 100644 +--- a/drivers/scsi/scsi.c ++++ b/drivers/scsi/scsi.c +@@ -707,26 +707,23 @@ void scsi_cdl_check(struct scsi_device *sdev) + */ + int scsi_cdl_enable(struct scsi_device *sdev, bool enable) + { +- struct scsi_mode_data data; +- struct scsi_sense_hdr sshdr; +- struct scsi_vpd *vpd; +- bool is_ata = false; + char buf[64]; ++ bool is_ata; + int ret; + + if (!sdev->cdl_supported) + return -EOPNOTSUPP; + + rcu_read_lock(); +- vpd = rcu_dereference(sdev->vpd_pg89); +- if (vpd) +- is_ata = true; ++ is_ata = rcu_dereference(sdev->vpd_pg89); + rcu_read_unlock(); + + /* + * For ATA devices, CDL needs to be enabled with a SET FEATURES command. + */ + if (is_ata) { ++ struct scsi_mode_data data; ++ struct scsi_sense_hdr sshdr; + char *buf_data; + int len; + +@@ -735,16 +732,30 @@ int scsi_cdl_enable(struct scsi_device *sdev, bool enable) + if (ret) + return -EINVAL; + +- /* Enable CDL using the ATA feature page */ ++ /* Enable or disable CDL using the ATA feature page */ + len = min_t(size_t, sizeof(buf), + data.length - data.header_length - + data.block_descriptor_length); + buf_data = buf + data.header_length + + data.block_descriptor_length; +- if (enable) +- buf_data[4] = 0x02; +- else +- buf_data[4] = 0; ++ ++ /* ++ * If we want to enable CDL and CDL is already enabled on the ++ * device, do nothing. This avoids needlessly resetting the CDL ++ * statistics on the device as that is implied by the CDL enable ++ * action. Similar to this, there is no need to do anything if ++ * we want to disable CDL and CDL is already disabled. ++ */ ++ if (enable) { ++ if ((buf_data[4] & 0x03) == 0x02) ++ goto out; ++ buf_data[4] &= ~0x03; ++ buf_data[4] |= 0x02; ++ } else { ++ if ((buf_data[4] & 0x03) == 0x00) ++ goto out; ++ buf_data[4] &= ~0x03; ++ } + + ret = scsi_mode_select(sdev, 1, 0, buf_data, len, 5 * HZ, 3, + &data, &sshdr); +@@ -756,6 +767,7 @@ int scsi_cdl_enable(struct scsi_device *sdev, bool enable) + } + } + ++out: + sdev->cdl_enable = enable; + + return 0; + diff --git a/series.conf b/series.conf index 0c6ddac..d62e6b7 100644 --- a/series.conf +++ b/series.conf @@ -31720,6 +31720,7 @@ patches.suse/ata-libata-scsi-Fix-ata_mselect_control_ata_feature-.patch patches.suse/ata-libata-scsi-Fix-ata_msense_control_ata_feature.patch patches.suse/ata-libata-scsi-Improve-CDL-control.patch + patches.suse/scsi-Improve-CDL-control.patch patches.suse/Revert-drm-meson-vclk-fix-calculation-of-59.94-fract.patch patches.suse/drm-amd-display-Fix-gpu-reset-in-multidisplay-config.patch patches.suse/drm-amd-display-Force-full-update-in-gpu-reset.patch