]> www.infradead.org Git - linux.git/commitdiff
ata: libata: Introduce ata_dev_free_resources
authorDamien Le Moal <dlemoal@kernel.org>
Thu, 5 Sep 2024 01:51:19 +0000 (10:51 +0900)
committerDamien Le Moal <dlemoal@kernel.org>
Sat, 7 Sep 2024 01:16:55 +0000 (10:16 +0900)
Introduce the function ata_dev_free_resources() to free the resources
allocated to support a device features. For now, this function is
reduced to calling zpodd_exit() for devices that have this feature
enabled.

ata_dev_free_resources() is called from ata_eh_dev_disable() as this
function is always called for all devices attached to a port that is
being detached and for devices that are being disabled due to being
removed (detached) from the system or due to errors.

With this change, the call to zpodd_exit() done in ata_port_detach()
and ata_scsi_handle_link_detach() are removed as these functions
remove all devices attached to the link or port using libata EH, thus
resulting in ata_eh_dev_disable() being called and the zpodd_exit()
function being executed.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/libata.h

index 32325a1c07afa3f28e3d6c9207b0d9328b580a58..bfd452b0d46d02a911ec28374a065a1196894b83 100644 (file)
@@ -5976,6 +5976,21 @@ int ata_host_activate(struct ata_host *host, int irq,
 }
 EXPORT_SYMBOL_GPL(ata_host_activate);
 
+/**
+ *     ata_dev_free_resources - Free a device resources
+ *     @dev: Target ATA device
+ *
+ *     Free resources allocated to support a device features.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+void ata_dev_free_resources(struct ata_device *dev)
+{
+       if (zpodd_dev_enabled(dev))
+               zpodd_exit(dev);
+}
+
 /**
  *     ata_port_detach - Detach ATA port in preparation of device removal
  *     @ap: ATA port to be detached
@@ -6030,19 +6045,15 @@ static void ata_port_detach(struct ata_port *ap)
        cancel_delayed_work_sync(&ap->hotplug_task);
        cancel_delayed_work_sync(&ap->scsi_rescan_task);
 
-       /* clean up zpodd on port removal */
-       ata_for_each_link(link, ap, HOST_FIRST) {
-               ata_for_each_dev(dev, link, ALL) {
-                       if (zpodd_dev_enabled(dev))
-                               zpodd_exit(dev);
-               }
-       }
+       /* Delete port multiplier link transport devices */
        if (ap->pmp_link) {
                int i;
+
                for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
                        ata_tlink_delete(&ap->pmp_link[i]);
        }
-       /* remove the associated SCSI host */
+
+       /* Remove the associated SCSI host */
        scsi_remove_host(ap->scsi_host);
        ata_tport_delete(ap);
 }
index ed535e1b4225e27b8adbe7b66f1add70c0ba11c5..364828b8a22d6f811f7754491f01940986e01d71 100644 (file)
@@ -500,10 +500,13 @@ static void ata_eh_dev_disable(struct ata_device *dev)
        ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);
        dev->class++;
 
-       /* From now till the next successful probe, ering is used to
+       /*
+        * From now till the next successful probe, ering is used to
         * track probe failures.  Clear accumulated device error info.
         */
        ata_ering_clear(&dev->ering);
+
+       ata_dev_free_resources(dev);
 }
 
 static void ata_eh_unload(struct ata_port *ap)
index 6bd7ab27fcbb2e498c9874eeb4dfaa65a53ec66c..4fb45565c142d4fbb125b56a6fbe224817500672 100644 (file)
@@ -4614,9 +4614,6 @@ static void ata_scsi_handle_link_detach(struct ata_link *link)
                dev->flags &= ~ATA_DFLAG_DETACHED;
                spin_unlock_irqrestore(ap->lock, flags);
 
-               if (zpodd_dev_enabled(dev))
-                       zpodd_exit(dev);
-
                ata_scsi_remove_dev(dev);
        }
 }
index 2a9d1bbf2482d62b71b641c0f049b3630a68de69..927d77bde7ef67fad5a7c5625b815141898d96e2 100644 (file)
@@ -71,6 +71,7 @@ extern bool ata_dev_power_init_tf(struct ata_device *dev,
                                  struct ata_taskfile *tf, bool set_active);
 extern void ata_dev_power_set_standby(struct ata_device *dev);
 extern void ata_dev_power_set_active(struct ata_device *dev);
+void ata_dev_free_resources(struct ata_device *dev);
 extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
 extern unsigned int ata_dev_set_feature(struct ata_device *dev,
                                        u8 subcmd, u8 action);