* [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