From: Damien Le Moal <hidden> Date: 2021-08-10 05:49:44
The first three patches of this series fix sparse and kernel bot
warnings (potential NULL pointer dereference and locking imbalance).
The following three patches cleanup libata-core code in the area of
device configuration (ata_dev_configure() function).
Patch 7 improves ata_read_log_page() to avoid unnecessary warning
messages and patch 8 adds an informational message on device scan to
advertize the features supported by a device.
Path 9 adds the new sysfs ahci device attribute ncq_prio_supported to
indicate that a disk supports NCQ priority.
Changes from v4:
* Fixed patch 1 to avoid an out-of-bounds array access
* Changed title of patch 3 to describe the change (as opposed to only
mentioning the tool that found the problem)
* Removed patch 10 from this series as Martin took it through the scsi
tree
* Added reviewed-by tags
Changes from v3:
* Reworked patch 1
* Added patch 3 to fix a sparse warning discovered while checking
patch 1 & 2
* Added reviewed-by tags
Changes from v2:
* Reworked patch 4 to avoid the need for an additional on-stack string
for device information messages
* Added reviewed-by tags
Changes from v1:
* Added patch 1 and 2 to fix problems reported by the kernel test robot
* Use strscpy() instead of strcpy in patch 4
* Use sysfs_emit in patch 8 and 9 as suggested by Bart
* Fix typos in comments of the new sas_ncq_prio_supported attribute in
patch 9
Damien Le Moal (9):
libata: fix ata_host_alloc_pinfo()
libata: fix ata_host_start()
libata: simplify ata_scsi_rbuf_fill()
libata: cleanup device sleep capability detection
libata: cleanup ata_dev_configure()
libata: cleanup NCQ priority handling
libata: fix ata_read_log_page() warning
libata: print feature list on device scan
libahci: Introduce ncq_prio_supported sysfs sttribute
drivers/ata/libahci.c | 1 +
drivers/ata/libata-core.c | 290 +++++++++++++++++++++-----------------
drivers/ata/libata-sata.c | 61 ++++----
drivers/ata/libata-scsi.c | 60 ++------
include/linux/libata.h | 5 +
5 files changed, 211 insertions(+), 206 deletions(-)
--
2.31.1
From: Damien Le Moal <hidden> Date: 2021-08-10 05:49:46
Avoid static checkers warnings about a potential NULL pointer
dereference for the port info variable pi. To do so, test that at least
one port info is available on entry to ata_host_alloc_pinfo() and start
the ata port initialization for() loop with pi initialized to the first
port info passed as argument (which is already checked to be non NULL).
Within the for() loop, get the next port info, if it is not NULL,
after initializing the ata port using the previous port info.
Reported-by: kernel test robot <redacted>
Signed-off-by: Damien Le Moal <redacted>
---
drivers/ata/libata-core.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
@@ -5441,16 +5441,17 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,structata_host*host;inti,j;+/* We must have at least one port info */+if(!ppi[0])+returnNULL;+host=ata_host_alloc(dev,n_ports);if(!host)returnNULL;-for(i=0,j=0,pi=NULL;i<host->n_ports;i++){+for(i=0,j=0,pi=ppi[0];i<host->n_ports;i++){structata_port*ap=host->ports[i];-if(ppi[j])-pi=ppi[j++];-ap->pio_mask=pi->pio_mask;ap->mwdma_mask=pi->mwdma_mask;ap->udma_mask=pi->udma_mask;
From: Damien Le Moal <hidden> Date: 2021-08-10 05:49:49
The loop on entry of ata_host_start() may not initialize host->ops to a
non NULL value. The test on the host_stop field of host->ops must then
be preceded by a check that host->ops is not NULL.
Reported-by: kernel test robot <redacted>
Signed-off-by: Damien Le Moal <redacted>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/ata/libata-core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Damien Le Moal <hidden> Date: 2021-08-10 05:49:50
Sparse complains about context imbalance in ata_scsi_rbuf_get() and
ata_scsi_rbuf_put() due to these functions respectively only taking
and releasing the ata_scsi_rbuf_lock spinlock. Since these functions are
only called from ata_scsi_rbuf_fill() with ata_scsi_rbuf_get() being
called with a copy_in argument always false, the code can be simplified
and ata_scsi_rbuf_{get|put} removed. This change both simplifies the
code and fixes the sparse warning.
Signed-off-by: Damien Le Moal <redacted>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/ata/libata-scsi.c | 60 ++++++---------------------------------
1 file changed, 9 insertions(+), 51 deletions(-)
From: Damien Le Moal <hidden> Date: 2021-08-10 05:49:56
Move the code to retrieve the device sleep capability and timings out of
ata_dev_configure() into the helper function ata_dev_config_devslp().
While at it, mark the device as supporting the device sleep capability
only if the sata settings page was retrieved successfully to ensure that
the timing information is correctly initialized.
Signed-off-by: Damien Le Moal <redacted>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/ata/libata-core.c | 55 +++++++++++++++++++++++----------------
1 file changed, 32 insertions(+), 23 deletions(-)
@@ -2363,6 +2363,37 @@ static void ata_dev_config_trusted(struct ata_device *dev)dev->flags|=ATA_DFLAG_TRUSTED;}+staticvoidata_dev_config_devslp(structata_device*dev)+{+u8*sata_setting=dev->link->ap->sector_buf;+unsignedinterr_mask;+inti,j;++/*+*Checkdevicesleepcapability.GetDevSlptimingvariables+*fromSATASettingspageofIdentifyDeviceDataLog.+*/+if(!ata_id_has_devslp(dev->id))+return;++err_mask=ata_read_log_page(dev,+ATA_LOG_IDENTIFY_DEVICE,+ATA_LOG_SATA_SETTINGS,+sata_setting,1);+if(err_mask){+ata_dev_dbg(dev,+"failed to get SATA Settings Log, Emask 0x%x\n",+err_mask);+return;+}++dev->flags|=ATA_DFLAG_DEVSLP;+for(i=0;i<ATA_LOG_DEVSLP_SIZE;i++){+j=ATA_LOG_DEVSLP_OFFSET+i;+dev->devslp_timing[i]=sata_setting[j];+}+}+/***ata_dev_configure-ConfigurethespecifiedATA/ATAPIdevice*@dev:Targetdevicetoconfigure
@@ -2565,29 +2596,7 @@ int ata_dev_configure(struct ata_device *dev)}}-/* Check and mark DevSlp capability. Get DevSlp timing variables-*fromSATASettingspageofIdentifyDeviceDataLog.-*/-if(ata_id_has_devslp(dev->id)){-u8*sata_setting=ap->sector_buf;-inti,j;--dev->flags|=ATA_DFLAG_DEVSLP;-err_mask=ata_read_log_page(dev,-ATA_LOG_IDENTIFY_DEVICE,-ATA_LOG_SATA_SETTINGS,-sata_setting,-1);-if(err_mask)-ata_dev_dbg(dev,-"failed to get Identify Device Data, Emask 0x%x\n",-err_mask);-else-for(i=0;i<ATA_LOG_DEVSLP_SIZE;i++){-j=ATA_LOG_DEVSLP_OFFSET+i;-dev->devslp_timing[i]=sata_setting[j];-}-}+ata_dev_config_devslp(dev);ata_dev_config_sense_reporting(dev);ata_dev_config_zac(dev);ata_dev_config_trusted(dev);
From: Damien Le Moal <hidden> Date: 2021-08-10 05:49:56
Introduce the helper functions ata_dev_config_lba() and
ata_dev_config_chs() to configure the addressing capabilities of a
device. To control message printing in these new helpers, as well as
in ata_dev_configure() and in ata_hpa_resize(), add the helper function
ata_dev_print_info() to avoid open coding for the eh context
ATA_EHI_PRINTINFO flag in multiple functions.
Signed-off-by: Damien Le Moal <redacted>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/ata/libata-core.c | 131 ++++++++++++++++++++++----------------
1 file changed, 75 insertions(+), 56 deletions(-)
@@ -159,6 +159,12 @@ MODULE_DESCRIPTION("Library module for ATA devices");MODULE_LICENSE("GPL");MODULE_VERSION(DRV_VERSION);+staticinlineboolata_dev_print_info(structata_device*dev)+{+structata_eh_context*ehc=&dev->link->eh_context;++returnehc->i.flags&ATA_EHI_PRINTINFO;+}staticboolata_sstatus_online(u32sstatus){
@@ -2538,62 +2601,18 @@ int ata_dev_configure(struct ata_device *dev)dev->multi_count=cnt;}-if(ata_id_has_lba(id)){-constchar*lba_desc;-charncq_desc[24];--lba_desc="LBA";-dev->flags|=ATA_DFLAG_LBA;-if(ata_id_has_lba48(id)){-dev->flags|=ATA_DFLAG_LBA48;-lba_desc="LBA48";--if(dev->n_sectors>=(1UL<<28)&&-ata_id_has_flush_ext(id))-dev->flags|=ATA_DFLAG_FLUSH_EXT;-}+/* print device info to dmesg */+if(ata_msg_drv(ap)&&print_info)+ata_dev_info(dev,"%s: %s, %s, max %s\n",+revbuf,modelbuf,fwrevbuf,+ata_mode_string(xfer_mask));-/* config NCQ */-rc=ata_dev_config_ncq(dev,ncq_desc,sizeof(ncq_desc));+if(ata_id_has_lba(id)){+rc=ata_dev_config_lba(dev);if(rc)returnrc;--/* print device info to dmesg */-if(ata_msg_drv(ap)&&print_info){-ata_dev_info(dev,"%s: %s, %s, max %s\n",-revbuf,modelbuf,fwrevbuf,-ata_mode_string(xfer_mask));-ata_dev_info(dev,-"%llu sectors, multi %u: %s %s\n",-(unsignedlonglong)dev->n_sectors,-dev->multi_count,lba_desc,ncq_desc);-}}else{-/* CHS */--/* Default translation */-dev->cylinders=id[1];-dev->heads=id[3];-dev->sectors=id[6];--if(ata_id_current_chs_valid(id)){-/* Current CHS translation is valid. */-dev->cylinders=id[54];-dev->heads=id[55];-dev->sectors=id[56];-}--/* print device info to dmesg */-if(ata_msg_drv(ap)&&print_info){-ata_dev_info(dev,"%s: %s, %s, max %s\n",-revbuf,modelbuf,fwrevbuf,-ata_mode_string(xfer_mask));-ata_dev_info(dev,-"%llu sectors, multi %u, CHS %u/%u/%u\n",-(unsignedlonglong)dev->n_sectors,-dev->multi_count,dev->cylinders,-dev->heads,dev->sectors);-}+ata_dev_config_chs(dev);}ata_dev_config_devslp(dev);
From: Damien Le Moal <hidden> Date: 2021-08-10 05:49:58
The ata device flag ATA_DFLAG_NCQ_PRIO indicates if a device supports
the NCQ Priority feature while the ATA_DFLAG_NCQ_PRIO_ENABLE device
flag indicates if the feature is enabled. Enabling NCQ priority use is
controlled by the user through the device sysfs attribute
ncq_prio_enable. As a result, the ATA_DFLAG_NCQ_PRIO flag should not be
cleared when ATA_DFLAG_NCQ_PRIO_ENABLE is not set as the device still
supports the feature even after the user disables it. This leads to the
following cleanups:
- In ata_build_rw_tf(), set a command high priority bit based on the
ATA_DFLAG_NCQ_PRIO_ENABLE flag, not on the ATA_DFLAG_NCQ flag. That
is, set a command high priority only if the user enabled NCQ priority
use.
- In ata_dev_config_ncq_prio(), ATA_DFLAG_NCQ_PRIO should not be cleared
if ATA_DFLAG_NCQ_PRIO_ENABLE is not set. If the device does not
support NCQ priority, both ATA_DFLAG_NCQ_PRIO and
ATA_DFLAG_NCQ_PRIO_ENABLE must be cleared.
With the above ata_dev_config_ncq_prio() change, ATA_DFLAG_NCQ_PRIO flag
is set on device scan and revalidation. There is no need to trigger a
device revalidation in ata_ncq_prio_enable_store() when the user enables
the use of NCQ priority. Remove the revalidation code from that funciton
to simplify it. Also change the return value from -EIO to -EINVAL when a
user tries to enable NCQ priority for a device that does not support
this feature. While at it, also simplify ata_ncq_prio_enable_show().
Overall, there is no functional change introduced by this patch.
Signed-off-by: Damien Le Moal <redacted>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/ata/libata-core.c | 32 ++++++++++++++------------------
drivers/ata/libata-sata.c | 37 ++++++++++++-------------------------
2 files changed, 26 insertions(+), 43 deletions(-)
@@ -2190,18 +2183,21 @@ static void ata_dev_config_ncq_prio(struct ata_device *dev)1);if(err_mask){ata_dev_dbg(dev,-"failed to get Identify Device data, Emask 0x%x\n",+"failed to get SATA settings log, Emask 0x%x\n",err_mask);-return;+gotonot_supported;}-if(ap->sector_buf[ATA_LOG_NCQ_PRIO_OFFSET]&BIT(3)){-dev->flags|=ATA_DFLAG_NCQ_PRIO;-}else{-dev->flags&=~ATA_DFLAG_NCQ_PRIO;-ata_dev_dbg(dev,"SATA page does not support priority\n");-}+if(!(ap->sector_buf[ATA_LOG_NCQ_PRIO_OFFSET]&BIT(3)))+gotonot_supported;++dev->flags|=ATA_DFLAG_NCQ_PRIO;++return;+not_supported:+dev->flags&=~ATA_DFLAG_NCQ_PRIO_ENABLE;+dev->flags&=~ATA_DFLAG_NCQ_PRIO;}staticintata_dev_config_ncq(structata_device*dev,
From: Damien Le Moal <hidden> Date: 2021-08-10 05:50:01
Support for the READ LOG PAGE DMA EXT command is indicated by words 119
and 120 of a device identify data. This is tested in
ata_read_log_page() with ata_id_has_read_log_dma_ext() and the
READ LOG PAGE DMA command used if the device reports supports for it.
However, some devices lie about this support and using the DMA version
of the command fails, generating the warning message "READ LOG DMA EXT
failed, trying PIO". Since READ LOG PAGE DMA EXT is an optional command,
this warning is not at all important but may be scary for the user.
Change ata_read_log_page() to suppres this warning and to print an
error message if both DMA and PIO attempts failed.
With this change, there is no need to print again an error message when
ata_read_log_page() returns an error. So simplify the users of this
function.
Signed-off-by: Damien Le Moal <redacted>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/ata/libata-core.c | 47 +++++++++++----------------------------
1 file changed, 13 insertions(+), 34 deletions(-)
From: Damien Le Moal <hidden> Date: 2021-08-10 05:50:02
Print a list of features supported by a drive when it is configured in
ata_dev_configure() using the new function ata_dev_print_features().
The features printed are not already advertized and are: trusted
send-recev support, device attention support, device sleep support,
NCQ send-recv support and NCQ priority support.
Signed-off-by: Damien Le Moal <redacted>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/ata/libata-core.c | 17 +++++++++++++++++
include/linux/libata.h | 4 ++++
2 files changed, 21 insertions(+)
From: Damien Le Moal <hidden> Date: 2021-08-10 05:51:44
Currently, the only way a user can determine if a SATA device supports
NCQ priority is to try to enable the use of this feature using the
ncq_prio_enable sysfs device attribute. If enabling the feature fails,
it is because the device does not support NCQ priority. Otherwise, the
feature is enabled and indicates that the device supports NCQ priority.
Improve this odd interface by introducing the read-only
ncq_prio_supported sysfs device attribute to indicate if a SATA device
supports NCQ priority. The value of this attribute reflects if the
device flag ATA_DFLAG_NCQ_PRIO is set or cleared.
Signed-off-by: Damien Le Moal <redacted>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/ata/libahci.c | 1 +
drivers/ata/libata-sata.c | 24 ++++++++++++++++++++++++
include/linux/libata.h | 1 +
3 files changed, 26 insertions(+)
From: Hannes Reinecke <hare@suse.de> Date: 2021-08-10 06:06:28
On 8/10/21 7:49 AM, Damien Le Moal wrote:
Avoid static checkers warnings about a potential NULL pointer
dereference for the port info variable pi. To do so, test that at least
one port info is available on entry to ata_host_alloc_pinfo() and start
the ata port initialization for() loop with pi initialized to the first
port info passed as argument (which is already checked to be non NULL).
Within the for() loop, get the next port info, if it is not NULL,
after initializing the ata port using the previous port info.
Reported-by: kernel test robot <redacted>
Signed-off-by: Damien Le Moal <redacted>
---
drivers/ata/libata-core.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
On Tue, Aug 10, 2021 at 02:49:39PM +0900, Damien Le Moal wrote:
quoted hunk
Currently, the only way a user can determine if a SATA device supports
NCQ priority is to try to enable the use of this feature using the
ncq_prio_enable sysfs device attribute. If enabling the feature fails,
it is because the device does not support NCQ priority. Otherwise, the
feature is enabled and indicates that the device supports NCQ priority.
Improve this odd interface by introducing the read-only
ncq_prio_supported sysfs device attribute to indicate if a SATA device
supports NCQ priority. The value of this attribute reflects if the
device flag ATA_DFLAG_NCQ_PRIO is set or cleared.
Signed-off-by: Damien Le Moal <redacted>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/ata/libahci.c | 1 +
drivers/ata/libata-sata.c | 24 ++++++++++++++++++++++++
include/linux/libata.h | 1 +
3 files changed, 26 insertions(+)
Hello Damien,
I do not fully understand if NCQ is only supported for AHCI controllers,
or if vanilla SATA controllers (without AHCI) can support it as well
(since NCQ is part of the ATA Command Set - 5).
However, I do think that you might have missed adding the
dev_attr_ncq_prio_supported
attribute for the ata_ncq_sdev_attrs struct in libata-sata.c
(The ata_ncq_sdev_attrs struct already has the dev_attr_ncq_prio_enable
attribute, so it makes sense that it should have the new supported
attribute as well.)
Kind regards,
Niklas
From: Damien Le Moal <hidden> Date: 2021-08-11 23:30:57
On 2021/08/12 4:07, Niklas Cassel wrote:
On Tue, Aug 10, 2021 at 02:49:39PM +0900, Damien Le Moal wrote:
quoted
Currently, the only way a user can determine if a SATA device supports
NCQ priority is to try to enable the use of this feature using the
ncq_prio_enable sysfs device attribute. If enabling the feature fails,
it is because the device does not support NCQ priority. Otherwise, the
feature is enabled and indicates that the device supports NCQ priority.
Improve this odd interface by introducing the read-only
ncq_prio_supported sysfs device attribute to indicate if a SATA device
supports NCQ priority. The value of this attribute reflects if the
device flag ATA_DFLAG_NCQ_PRIO is set or cleared.
Signed-off-by: Damien Le Moal <redacted>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/ata/libahci.c | 1 +
drivers/ata/libata-sata.c | 24 ++++++++++++++++++++++++
include/linux/libata.h | 1 +
3 files changed, 26 insertions(+)
Hello Damien,
I do not fully understand if NCQ is only supported for AHCI controllers,
or if vanilla SATA controllers (without AHCI) can support it as well
(since NCQ is part of the ATA Command Set - 5).
However, I do think that you might have missed adding the
dev_attr_ncq_prio_supported
attribute for the ata_ncq_sdev_attrs struct in libata-sata.c
(The ata_ncq_sdev_attrs struct already has the dev_attr_ncq_prio_enable
attribute, so it makes sense that it should have the new supported
attribute as well.)
Good catch. I indeed forgot that one. Will add it.
On Wed, Aug 11, 2021 at 11:30:52PM +0000, Damien Le Moal wrote:
On 2021/08/12 4:07, Niklas Cassel wrote:
quoted
On Tue, Aug 10, 2021 at 02:49:39PM +0900, Damien Le Moal wrote:
quoted
Currently, the only way a user can determine if a SATA device supports
NCQ priority is to try to enable the use of this feature using the
ncq_prio_enable sysfs device attribute. If enabling the feature fails,
it is because the device does not support NCQ priority. Otherwise, the
feature is enabled and indicates that the device supports NCQ priority.
Improve this odd interface by introducing the read-only
ncq_prio_supported sysfs device attribute to indicate if a SATA device
supports NCQ priority. The value of this attribute reflects if the
device flag ATA_DFLAG_NCQ_PRIO is set or cleared.
Signed-off-by: Damien Le Moal <redacted>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/ata/libahci.c | 1 +
drivers/ata/libata-sata.c | 24 ++++++++++++++++++++++++
include/linux/libata.h | 1 +
3 files changed, 26 insertions(+)
Hello Damien,
I do not fully understand if NCQ is only supported for AHCI controllers,
or if vanilla SATA controllers (without AHCI) can support it as well
(since NCQ is part of the ATA Command Set - 5).
However, I do think that you might have missed adding the
dev_attr_ncq_prio_supported
attribute for the ata_ncq_sdev_attrs struct in libata-sata.c
(The ata_ncq_sdev_attrs struct already has the dev_attr_ncq_prio_enable
attribute, so it makes sense that it should have the new supported
attribute as well.)
Good catch. I indeed forgot that one. Will add it.
When respinning this patch, we should document this new attribute in:
Documentation/ABI/testing/sysfs-block-device
as well. (ncq_prio_enable is already documented there.)
Kind regards,
Niklas