From: Niklas Cassel <Niklas.Cassel@wdc.com>
To: Damien Le Moal <dlemoal@kernel.org>
Cc: "linux-ide@vger.kernel.org" <linux-ide@vger.kernel.org>,
"linux-scsi@vger.kernel.org" <linux-scsi@vger.kernel.org>,
"Martin K . Petersen" <martin.petersen@oracle.com>,
John Garry <john.g.garry@oracle.com>,
Rodrigo Vivi <rodrigo.vivi@intel.com>,
Paul Ausbeck <paula@soe.ucsc.edu>,
Kai-Heng Feng <kai.heng.feng@canonical.com>,
Joe Breuer <linux-kernel@jmbreuer.net>,
Geert Uytterhoeven <geert@linux-m68k.org>,
Chia-Lin Kao <acelan.kao@canonical.com>
Subject: Re: [PATCH v3 03/23] ata: libata-scsi: link ata port and scsi device
Date: Tue, 19 Sep 2023 13:21:31 +0000 [thread overview]
Message-ID: <ZQmgU/j8OD8t4KLs@x1-carbon> (raw)
In-Reply-To: <20230915081507.761711-4-dlemoal@kernel.org>
On Fri, Sep 15, 2023 at 05:14:47PM +0900, Damien Le Moal wrote:
> There is no direct device ancestry defined between an ata_device and
> its scsi device which prevents the power management code from correctly
> ordering suspend and resume operations. Create such ancestry with the
> ata device as the parent to ensure that the scsi device (child) is
> suspended before the ata device and that resume handles the ata device
> before the scsi device.
>
> The parent-child (supplier-consumer) relationship is established between
> the ata_port (parent) and the scsi device (child) with the function
> device_add_link(). The parent used is not the ata_device as the PM
> operations are defined per port and the status of all devices connected
> through that port is controlled from the port operations.
>
> The device link is established with the new function
> ata_scsi_dev_alloc(). This function is used to define the ->slave_alloc
> callback of the scsi host template of most drivers.
>
> Fixes: a19a93e4c6a9 ("scsi: core: pm: Rely on the device driver core for async power management")
> Cc: stable@vger.kernel.org
> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> ---
> drivers/ata/ahci.h | 1 +
> drivers/ata/libata-scsi.c | 49 +++++++++++++++++++++++++++++++++++----
> drivers/ata/libata.h | 1 +
> drivers/ata/pata_macio.c | 1 +
> drivers/ata/sata_mv.c | 1 +
> drivers/ata/sata_nv.c | 2 ++
> drivers/ata/sata_sil24.c | 1 +
> include/linux/libata.h | 3 +++
> 8 files changed, 54 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> index 4bae95b06ae3..72085756f4ba 100644
> --- a/drivers/ata/ahci.h
> +++ b/drivers/ata/ahci.h
> @@ -398,6 +398,7 @@ extern const struct attribute_group *ahci_sdev_groups[];
> .sdev_groups = ahci_sdev_groups, \
> .change_queue_depth = ata_scsi_change_queue_depth, \
> .tag_alloc_policy = BLK_TAG_ALLOC_RR, \
> + .slave_alloc = ata_scsi_slave_alloc, \
> .slave_configure = ata_scsi_slave_config
>
> extern struct ata_port_operations ahci_ops;
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index d3f28b82c97b..eef76af1af90 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -1089,6 +1089,46 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev)
> return 0;
> }
>
> +int ata_scsi_dev_alloc(struct scsi_device *sdev, struct ata_port *ap)
> +{
> + struct device_link *link;
> +
> + ata_scsi_sdev_config(sdev);
> +
> + /*
> + * Create a link from the ata_port device to the scsi device to ensure
> + * that PM does suspend/resume in the correct order: the scsi device is
> + * consumer (child) and the ata port the supplier (parent).
> + */
> + link = device_link_add(&sdev->sdev_gendev, &ap->tdev,
> + DL_FLAG_STATELESS |
> + DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
> + if (!link) {
> + ata_port_err(ap, "Failed to create link to scsi device %s\n",
> + dev_name(&sdev->sdev_gendev));
> + return -ENODEV;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * ata_scsi_slave_alloc - Early setup of SCSI device
> + * @sdev: SCSI device to examine
> + *
> + * This is called from scsi_alloc_sdev() when the scsi device
> + * associated with an ATA device is scanned on a port.
> + *
> + * LOCKING:
> + * Defined by SCSI layer. We don't really care.
> + */
> +
> +int ata_scsi_slave_alloc(struct scsi_device *sdev)
> +{
> + return ata_scsi_dev_alloc(sdev, ata_shost_to_port(sdev->host));
> +}
> +EXPORT_SYMBOL_GPL(ata_scsi_slave_alloc);
> +
> /**
> * ata_scsi_slave_config - Set SCSI device attributes
> * @sdev: SCSI device to examine
> @@ -1105,14 +1145,11 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
> {
> struct ata_port *ap = ata_shost_to_port(sdev->host);
> struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
> - int rc = 0;
> -
> - ata_scsi_sdev_config(sdev);
>
> if (dev)
> - rc = ata_scsi_dev_config(sdev, dev);
> + return ata_scsi_dev_config(sdev, dev);
>
> - return rc;
> + return 0;
> }
> EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
>
> @@ -1136,6 +1173,8 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
> unsigned long flags;
> struct ata_device *dev;
>
> + device_link_remove(&sdev->sdev_gendev, &ap->tdev);
> +
> spin_lock_irqsave(ap->lock, flags);
> dev = __ata_scsi_find_dev(ap, sdev);
> if (dev && dev->sdev) {
> diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
> index 6e7d352803bd..079981e7156a 100644
> --- a/drivers/ata/libata.h
> +++ b/drivers/ata/libata.h
> @@ -111,6 +111,7 @@ extern struct ata_device *ata_scsi_find_dev(struct ata_port *ap,
> extern int ata_scsi_add_hosts(struct ata_host *host,
> const struct scsi_host_template *sht);
> extern void ata_scsi_scan_host(struct ata_port *ap, int sync);
> +extern int ata_scsi_dev_alloc(struct scsi_device *sdev, struct ata_port *ap);
> extern int ata_scsi_offline_dev(struct ata_device *dev);
> extern bool ata_scsi_sense_is_valid(u8 sk, u8 asc, u8 ascq);
> extern void ata_scsi_set_sense(struct ata_device *dev,
> diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c
> index 17f6ccee53c7..32968b4cf8e4 100644
> --- a/drivers/ata/pata_macio.c
> +++ b/drivers/ata/pata_macio.c
> @@ -918,6 +918,7 @@ static const struct scsi_host_template pata_macio_sht = {
> * use 64K minus 256
> */
> .max_segment_size = MAX_DBDMA_SEG,
> + .slave_alloc = ata_scsi_slave_alloc,
> .slave_configure = pata_macio_slave_config,
> .sdev_groups = ata_common_sdev_groups,
> .can_queue = ATA_DEF_QUEUE,
> diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
> index d105db5c7d81..353ac7b2f14a 100644
> --- a/drivers/ata/sata_mv.c
> +++ b/drivers/ata/sata_mv.c
> @@ -673,6 +673,7 @@ static const struct scsi_host_template mv6_sht = {
> .sdev_groups = ata_ncq_sdev_groups,
> .change_queue_depth = ata_scsi_change_queue_depth,
> .tag_alloc_policy = BLK_TAG_ALLOC_RR,
> + .slave_alloc = ata_scsi_slave_alloc,
It seems wrong to add .slave_alloc to all different ata_port_operations structs.
The .slave_configure is added on all different ata_port_operations structs,
because the callback can be different for different drivers.
However, adding the device link is done in .ata_scsi_slave_alloc,
removing the device link is done in .ata_scsi_slave_destroy.
Thus, I suggest that we only add the
.slave_alloc = ata_scsi_slave_alloc,
to __ATA_BASE_SHT() in libata.h, which is currently the only
place which has .slave_destroy defined.
All the other port operations inherit from __ATA_BASE_SHT().
> .slave_configure = ata_scsi_slave_config
> };
>
> diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
> index 0a0cee755bde..5428dc2ec5e3 100644
> --- a/drivers/ata/sata_nv.c
> +++ b/drivers/ata/sata_nv.c
> @@ -380,6 +380,7 @@ static const struct scsi_host_template nv_adma_sht = {
> .can_queue = NV_ADMA_MAX_CPBS,
> .sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN,
> .dma_boundary = NV_ADMA_DMA_BOUNDARY,
> + .slave_alloc = ata_scsi_slave_alloc,
> .slave_configure = nv_adma_slave_config,
> .sdev_groups = ata_ncq_sdev_groups,
> .change_queue_depth = ata_scsi_change_queue_depth,
> @@ -391,6 +392,7 @@ static const struct scsi_host_template nv_swncq_sht = {
> .can_queue = ATA_MAX_QUEUE - 1,
> .sg_tablesize = LIBATA_MAX_PRD,
> .dma_boundary = ATA_DMA_BOUNDARY,
> + .slave_alloc = ata_scsi_slave_alloc,
> .slave_configure = nv_swncq_slave_config,
> .sdev_groups = ata_ncq_sdev_groups,
> .change_queue_depth = ata_scsi_change_queue_depth,
> diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
> index 142e70bfc498..e0b1b3625031 100644
> --- a/drivers/ata/sata_sil24.c
> +++ b/drivers/ata/sata_sil24.c
> @@ -381,6 +381,7 @@ static const struct scsi_host_template sil24_sht = {
> .tag_alloc_policy = BLK_TAG_ALLOC_FIFO,
> .sdev_groups = ata_ncq_sdev_groups,
> .change_queue_depth = ata_scsi_change_queue_depth,
> + .slave_alloc = ata_scsi_slave_alloc,
> .slave_configure = ata_scsi_slave_config
> };
>
> diff --git a/include/linux/libata.h b/include/linux/libata.h
> index 52d58b13e5ee..c8cfea386c16 100644
> --- a/include/linux/libata.h
> +++ b/include/linux/libata.h
> @@ -1144,6 +1144,7 @@ extern int ata_std_bios_param(struct scsi_device *sdev,
> struct block_device *bdev,
> sector_t capacity, int geom[]);
> extern void ata_scsi_unlock_native_capacity(struct scsi_device *sdev);
> +extern int ata_scsi_slave_alloc(struct scsi_device *sdev);
> extern int ata_scsi_slave_config(struct scsi_device *sdev);
> extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
> extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
> @@ -1401,12 +1402,14 @@ extern const struct attribute_group *ata_common_sdev_groups[];
> __ATA_BASE_SHT(drv_name), \
> .can_queue = ATA_DEF_QUEUE, \
> .tag_alloc_policy = BLK_TAG_ALLOC_RR, \
> + .slave_alloc = ata_scsi_slave_alloc, \
> .slave_configure = ata_scsi_slave_config
>
> #define ATA_SUBBASE_SHT_QD(drv_name, drv_qd) \
> __ATA_BASE_SHT(drv_name), \
> .can_queue = drv_qd, \
> .tag_alloc_policy = BLK_TAG_ALLOC_RR, \
> + .slave_alloc = ata_scsi_slave_alloc, \
> .slave_configure = ata_scsi_slave_config
>
> #define ATA_BASE_SHT(drv_name) \
> --
> 2.41.0
>
next prev parent reply other threads:[~2023-09-19 13:21 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-15 8:14 [PATCH v3 00/23] Fix libata suspend/resume handling and code cleanup Damien Le Moal
2023-09-15 8:14 ` [PATCH v3 01/23] ata: libata-core: Fix ata_port_request_pm() locking Damien Le Moal
2023-09-19 13:21 ` Niklas Cassel
2023-09-19 16:31 ` Damien Le Moal
2023-09-20 7:21 ` Niklas Cassel
2023-09-20 7:30 ` Niklas Cassel
2023-09-20 10:22 ` Damien Le Moal
2023-09-20 10:20 ` Damien Le Moal
2023-09-15 8:14 ` [PATCH v3 02/23] ata: libata-core: Fix port and device removal Damien Le Moal
2023-09-19 13:21 ` Niklas Cassel
2023-09-19 17:42 ` Damien Le Moal
2023-09-15 8:14 ` [PATCH v3 03/23] ata: libata-scsi: link ata port and scsi device Damien Le Moal
2023-09-19 13:21 ` Niklas Cassel [this message]
2023-09-19 16:27 ` Damien Le Moal
2023-09-15 8:14 ` [PATCH v3 04/23] scsi: sd: Differentiate system and runtime start/stop management Damien Le Moal
2023-09-15 12:26 ` Hannes Reinecke
2023-09-15 8:14 ` [PATCH v3 05/23] ata: libata-scsi: Disable scsi device manage_system_start_stop Damien Le Moal
2023-09-15 12:27 ` Hannes Reinecke
2023-09-15 8:14 ` [PATCH v3 06/23] scsi: Do not attempt to rescan suspended devices Damien Le Moal
2023-09-15 12:29 ` Hannes Reinecke
2023-09-19 13:59 ` Niklas Cassel
2023-09-15 8:14 ` [PATCH v3 07/23] ata: libata-scsi: Fix delayed scsi_rescan_device() execution Damien Le Moal
2023-09-15 12:29 ` Hannes Reinecke
2023-09-19 14:00 ` Niklas Cassel
2023-09-15 8:14 ` [PATCH v3 08/23] ata: libata-core: Do not register PM operations for SAS ports Damien Le Moal
2023-09-15 8:14 ` [PATCH v3 09/23] scsi: sd: Do not issue commands to suspended disks on shutdown Damien Le Moal
2023-09-15 12:30 ` Hannes Reinecke
2023-09-15 14:31 ` Bart Van Assche
2023-09-15 8:14 ` [PATCH v3 10/23] ata: libata-core: Fix compilation warning in ata_dev_config_ncq() Damien Le Moal
2023-09-15 8:14 ` [PATCH v3 11/23] ata: libata-eh: Fix compilation warning in ata_eh_link_report() Damien Le Moal
2023-09-15 8:14 ` [PATCH v3 12/23] scsi: Remove scsi device no_start_on_resume flag Damien Le Moal
2023-09-15 8:14 ` [PATCH v3 13/23] ata: libata-scsi: Cleanup ata_scsi_start_stop_xlat() Damien Le Moal
2023-09-15 8:14 ` [PATCH v3 14/23] ata: libata-core: Synchronize ata_port_detach() with hotplug Damien Le Moal
2023-09-15 8:14 ` [PATCH v3 15/23] ata: libata-core: Detach a port devices on shutdown Damien Le Moal
2023-09-15 8:15 ` [PATCH v3 16/23] ata: libata-core: Remove ata_port_suspend_async() Damien Le Moal
2023-09-15 8:15 ` [PATCH v3 17/23] ata: libata-core: Remove ata_port_resume_async() Damien Le Moal
2023-09-15 8:15 ` [PATCH v3 18/23] ata: libata-core: Do not poweroff runtime suspended ports Damien Le Moal
2023-09-15 8:15 ` [PATCH v3 19/23] ata: libata-core: Do not resume " Damien Le Moal
2023-09-15 8:15 ` [PATCH v3 20/23] ata: libata-sata: Improve ata_sas_slave_configure() Damien Le Moal
2023-09-15 8:15 ` [PATCH v3 21/23] ata: libata-eh: Improve reset error messages Damien Le Moal
2023-09-15 8:15 ` [PATCH v3 22/23] ata: libata-eh: Reduce "disable device" message verbosity Damien Le Moal
2023-09-15 8:15 ` [PATCH v3 23/23] ata: libata: Cleanup inline DMA helper functions Damien Le Moal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZQmgU/j8OD8t4KLs@x1-carbon \
--to=niklas.cassel@wdc.com \
--cc=acelan.kao@canonical.com \
--cc=dlemoal@kernel.org \
--cc=geert@linux-m68k.org \
--cc=john.g.garry@oracle.com \
--cc=kai.heng.feng@canonical.com \
--cc=linux-ide@vger.kernel.org \
--cc=linux-kernel@jmbreuer.net \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=paula@soe.ucsc.edu \
--cc=rodrigo.vivi@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox