* [PATCH] ata: libata-scsi: Use correct device no in ata_find_dev()
@ 2023-05-22 11:27 Damien Le Moal
2023-05-22 11:48 ` John Garry
2023-05-22 13:09 ` Jason Yan
0 siblings, 2 replies; 4+ messages in thread
From: Damien Le Moal @ 2023-05-22 11:27 UTC (permalink / raw)
To: linux-ide; +Cc: John Garry, Jason Yan, Xingui Yang
For non-pmp attached devices managed directly by libata, the device
number is always 0 or 1 and lower to the maximum number of devices
returned by ata_link_max_devices(). However, for libsas managed devices,
devices are numbered up to the number of device scanned on an HBA port,
while each device has a regular ata/link setup supporting at most 1
device per link. This results in ata_find_dev() always returning NULL
except for the first device with device number 0.
Fix this by rewriting ata_find_dev() to ignore the device number for
non-pmp attached devices with a link with at most 1 device. For these,
device number 0 is always used to return the correct ata_device struct
of the port link. This change excludes IDE master/slave setups (maximum
number of devices per link is 2) and port-multiplier attached devices.
Reported-by: Xingui Yang <yangxingui@huawei.com>
Fixes: 41bda9c98035 ("libata-link: update hotplug to handle PMP links")
Cc: stable@vger.kernel.org
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
drivers/ata/libata-scsi.c | 31 ++++++++++++++++++++++++-------
1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 7bb12deab70c..3ba9cb258394 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2696,16 +2696,33 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
{
- if (!sata_pmp_attached(ap)) {
- if (likely(devno >= 0 &&
- devno < ata_link_max_devices(&ap->link)))
+ if (unlikely(devno < 0))
+ return NULL;
+
+ if (likely(!sata_pmp_attached(ap))) {
+ /*
+ * For the non PMP case, the maximum number of devices per link
+ * is 1 (e.g. SATA case), or 2 (IDE master + slave). The former
+ * case includes libsas hosted devices which are numbered up to
+ * the number of devices scanned on an HBA port, but with each
+ * ata device having its own ata port and link. To accommodate
+ * these, ignore devno and always use device number 0.
+ */
+ switch (ata_link_max_devices(&ap->link)) {
+ case 1:
+ return &ap->link.device[0];
+ case 2:
+ if (devno >= 2)
+ return NULL;
return &ap->link.device[devno];
- } else {
- if (likely(devno >= 0 &&
- devno < ap->nr_pmp_links))
- return &ap->pmp_link[devno].device[0];
+ default:
+ return NULL;
+ }
}
+ if (devno < ap->nr_pmp_links)
+ return &ap->pmp_link[devno].device[0];
+
return NULL;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] ata: libata-scsi: Use correct device no in ata_find_dev()
2023-05-22 11:27 [PATCH] ata: libata-scsi: Use correct device no in ata_find_dev() Damien Le Moal
@ 2023-05-22 11:48 ` John Garry
2023-05-22 12:05 ` Damien Le Moal
2023-05-22 13:09 ` Jason Yan
1 sibling, 1 reply; 4+ messages in thread
From: John Garry @ 2023-05-22 11:48 UTC (permalink / raw)
To: Damien Le Moal, linux-ide; +Cc: Jason Yan, Xingui Yang
On 22/05/2023 12:27, Damien Le Moal wrote:
Hi Damien,
Our mails just crossed...
> For non-pmp attached devices managed directly by libata, the device
> number is always 0 or 1 and lower to the maximum number of devices
> returned by ata_link_max_devices(). However, for libsas managed devices,
> devices are numbered up to the number of device scanned on an HBA port,
It's not really clear to me which number you mean. For libsas and lib
ata, ata_device->devno is configured the same, it's just that the sdev
per ata_device does not have the same numbering scheme for libsas. For
libsas - or scsi_transport_sas, to be more exact - the sdev id is per shost.
> while each device has a regular ata/link setup supporting at most 1
> device per link. This results in ata_find_dev() always returning NULL
> except for the first device with device number 0.
>
> Fix this by rewriting ata_find_dev() to ignore the device number for
> non-pmp attached devices with a link with at most 1 device. For these,
> device number 0 is always used to return the correct ata_device struct
> of the port link. This change excludes IDE master/slave setups (maximum
> number of devices per link is 2) and port-multiplier attached devices.
>
> Reported-by: Xingui Yang <yangxingui@huawei.com>
> Fixes: 41bda9c98035 ("libata-link: update hotplug to handle PMP links")
> Cc: stable@vger.kernel.org
> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
> ---
> drivers/ata/libata-scsi.c | 31 ++++++++++++++++++++++++-------
> 1 file changed, 24 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 7bb12deab70c..3ba9cb258394 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -2696,16 +2696,33 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
>
> static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
> {
> - if (!sata_pmp_attached(ap)) {
> - if (likely(devno >= 0 &&
> - devno < ata_link_max_devices(&ap->link)))
> + if (unlikely(devno < 0))
> + return NULL;
> +
> + if (likely(!sata_pmp_attached(ap))) {
> + /*
> + * For the non PMP case, the maximum number of devices per link
> + * is 1 (e.g. SATA case), or 2 (IDE master + slave). The former
> + * case includes libsas hosted devices which are numbered up to
> + * the number of devices scanned on an HBA port, but with each
> + * ata device having its own ata port and link. To accommodate
> + * these, ignore devno and always use device number 0.
> + */
> + switch (ata_link_max_devices(&ap->link)) {
> + case 1:
> + return &ap->link.device[0];
> + case 2:
> + if (devno >= 2)
How about ATA_MAX_DEVICES?
> + return NULL;
> return &ap->link.device[devno];
> - } else {
> - if (likely(devno >= 0 &&
> - devno < ap->nr_pmp_links))
> - return &ap->pmp_link[devno].device[0];
> + default:
> + return NULL;
> + }
> }
>
> + if (devno < ap->nr_pmp_links)
> + return &ap->pmp_link[devno].device[0];
> +
> return NULL;
> }
This looks ok to me, since we have a big comment about what we're doing.
I did send another suggestion, so I'll leave it to you.
BTW, I think that we can follow-up to this and remove the add ata_device
arg that we added to sas_change_queue_depth()
Thanks,
John
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] ata: libata-scsi: Use correct device no in ata_find_dev()
2023-05-22 11:48 ` John Garry
@ 2023-05-22 12:05 ` Damien Le Moal
0 siblings, 0 replies; 4+ messages in thread
From: Damien Le Moal @ 2023-05-22 12:05 UTC (permalink / raw)
To: John Garry, linux-ide; +Cc: Jason Yan, Xingui Yang
On 5/22/23 20:48, John Garry wrote:
> On 22/05/2023 12:27, Damien Le Moal wrote:
>
> Hi Damien,
>
> Our mails just crossed...
>
>> For non-pmp attached devices managed directly by libata, the device
>> number is always 0 or 1 and lower to the maximum number of devices
>> returned by ata_link_max_devices(). However, for libsas managed devices,
>> devices are numbered up to the number of device scanned on an HBA port,
>
> It's not really clear to me which number you mean. For libsas and lib
> ata, ata_device->devno is configured the same, it's just that the sdev
devno used in ata_find_dev() is scsidev->id, which is always 0 for a non-pmp
SATA drive (and can be 1 for an IDE slave drive). But with libsas, that number
is 0, 1, 2, 3... numbering the devices found on the HBA port. Hence
ata_find_dev() return NULL always because the ata_link_max_devices() is always 1
for any libsas ata device as they all have their own ata_port & ata_link.
> per ata_device does not have the same numbering scheme for libsas. For
> libsas - or scsi_transport_sas, to be more exact - the sdev id is per shost.
Yes. So the sdev->id goes beyond 0 and cannot be used as the devno for the
devices as they each have their own port & link.
>
>> while each device has a regular ata/link setup supporting at most 1
>> device per link. This results in ata_find_dev() always returning NULL
>> except for the first device with device number 0.
>>
>> Fix this by rewriting ata_find_dev() to ignore the device number for
>> non-pmp attached devices with a link with at most 1 device. For these,
>> device number 0 is always used to return the correct ata_device struct
>> of the port link. This change excludes IDE master/slave setups (maximum
>> number of devices per link is 2) and port-multiplier attached devices.
>>
>> Reported-by: Xingui Yang <yangxingui@huawei.com>
>> Fixes: 41bda9c98035 ("libata-link: update hotplug to handle PMP links")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
>> ---
>> drivers/ata/libata-scsi.c | 31 ++++++++++++++++++++++++-------
>> 1 file changed, 24 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
>> index 7bb12deab70c..3ba9cb258394 100644
>> --- a/drivers/ata/libata-scsi.c
>> +++ b/drivers/ata/libata-scsi.c
>> @@ -2696,16 +2696,33 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
>>
>> static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
>> {
>> - if (!sata_pmp_attached(ap)) {
>> - if (likely(devno >= 0 &&
>> - devno < ata_link_max_devices(&ap->link)))
>> + if (unlikely(devno < 0))
>> + return NULL;
>> +
>> + if (likely(!sata_pmp_attached(ap))) {
>> + /*
>> + * For the non PMP case, the maximum number of devices per link
>> + * is 1 (e.g. SATA case), or 2 (IDE master + slave). The former
>> + * case includes libsas hosted devices which are numbered up to
>> + * the number of devices scanned on an HBA port, but with each
>> + * ata device having its own ata port and link. To accommodate
>> + * these, ignore devno and always use device number 0.
>> + */
>> + switch (ata_link_max_devices(&ap->link)) {
>> + case 1:
>> + return &ap->link.device[0];
>> + case 2:
>> + if (devno >= 2)
>
> How about ATA_MAX_DEVICES?
Indeed. That would be nicer. And ata_link_max_devices() could use that as well.
>
>> + return NULL;
>> return &ap->link.device[devno];
>> - } else {
>> - if (likely(devno >= 0 &&
>> - devno < ap->nr_pmp_links))
>> - return &ap->pmp_link[devno].device[0];
>> + default:
>> + return NULL;
>> + }
>> }
>>
>> + if (devno < ap->nr_pmp_links)
>> + return &ap->pmp_link[devno].device[0];
>> +
>> return NULL;
>> }
>
> This looks ok to me, since we have a big comment about what we're doing.
I am not super happy about the wording of the comment. Suggestions welcome :)
I will at least reword to mention the counting of devices per shost.
> I did send another suggestion, so I'll leave it to you.
I kind of like the loop as it does not need a devno but it also implies that we
do have a scsi dev already while ata_find_dev() currently does not assume that.
Given that this function is also used in ata_scsi_user_scan() where we do not
have a sdev, it would not work for all cases.
>
> BTW, I think that we can follow-up to this and remove the add ata_device
> arg that we added to sas_change_queue_depth()
Yes. I will clean that up after sending this fix for this cycle. The cleanup
will be for 6.5.
>
> Thanks,
> John
>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] ata: libata-scsi: Use correct device no in ata_find_dev()
2023-05-22 11:27 [PATCH] ata: libata-scsi: Use correct device no in ata_find_dev() Damien Le Moal
2023-05-22 11:48 ` John Garry
@ 2023-05-22 13:09 ` Jason Yan
1 sibling, 0 replies; 4+ messages in thread
From: Jason Yan @ 2023-05-22 13:09 UTC (permalink / raw)
To: Damien Le Moal, linux-ide; +Cc: John Garry, Xingui Yang
On 2023/5/22 19:27, Damien Le Moal wrote:
> For non-pmp attached devices managed directly by libata, the device
> number is always 0 or 1 and lower to the maximum number of devices
> returned by ata_link_max_devices(). However, for libsas managed devices,
> devices are numbered up to the number of device scanned on an HBA port,
> while each device has a regular ata/link setup supporting at most 1
> device per link. This results in ata_find_dev() always returning NULL
> except for the first device with device number 0.
>
> Fix this by rewriting ata_find_dev() to ignore the device number for
> non-pmp attached devices with a link with at most 1 device. For these,
> device number 0 is always used to return the correct ata_device struct
> of the port link. This change excludes IDE master/slave setups (maximum
> number of devices per link is 2) and port-multiplier attached devices.
>
> Reported-by: Xingui Yang <yangxingui@huawei.com>
> Fixes: 41bda9c98035 ("libata-link: update hotplug to handle PMP links")
> Cc: stable@vger.kernel.org
> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
> ---
> drivers/ata/libata-scsi.c | 31 ++++++++++++++++++++++++-------
> 1 file changed, 24 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 7bb12deab70c..3ba9cb258394 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -2696,16 +2696,33 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
>
> static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
> {
> - if (!sata_pmp_attached(ap)) {
> - if (likely(devno >= 0 &&
> - devno < ata_link_max_devices(&ap->link)))
> + if (unlikely(devno < 0))
> + return NULL;
devno is either scsidev->id or scsidev->channel, which will never < 0.
Actually it is unsigned int. So I doubt if we need this check here.
> +
> + if (likely(!sata_pmp_attached(ap))) {
> + /*
> + * For the non PMP case, the maximum number of devices per link
> + * is 1 (e.g. SATA case), or 2 (IDE master + slave). The former
> + * case includes libsas hosted devices which are numbered up to
> + * the number of devices scanned on an HBA port, but with each
> + * ata device having its own ata port and link. To accommodate
> + * these, ignore devno and always use device number 0.
> + */
> + switch (ata_link_max_devices(&ap->link)) {
> + case 1:
> + return &ap->link.device[0];
> + case 2:
> + if (devno >= 2)
> + return NULL;
> return &ap->link.device[devno];
> - } else {
> - if (likely(devno >= 0 &&
> - devno < ap->nr_pmp_links))
> - return &ap->pmp_link[devno].device[0];
> + default:
> + return NULL;
> + }
> }
>
> + if (devno < ap->nr_pmp_links)
> + return &ap->pmp_link[devno].device[0];
> +
> return NULL;
> }
This change looks good to me.
Thanks,
Jason
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-05-22 13:09 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-05-22 11:27 [PATCH] ata: libata-scsi: Use correct device no in ata_find_dev() Damien Le Moal
2023-05-22 11:48 ` John Garry
2023-05-22 12:05 ` Damien Le Moal
2023-05-22 13:09 ` Jason Yan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox