]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
[PATCH] libata: add host_set->next for legacy two host_sets case, take #3
authorTejun Heo <htejun@gmail.com>
Mon, 12 Jun 2006 14:05:38 +0000 (23:05 +0900)
committerJeff Garzik <jeff@garzik.org>
Mon, 12 Jun 2006 14:23:21 +0000 (10:23 -0400)
For a legacy ATA controller, libata registers two separate host sets.
There was no connection between the two hosts making it impossible to
traverse all ports related to the controller.  This patch adds
host_set->next which points to the second host_set and makes
ata_pci_remove_one() remove all associated host_sets.

* On device removal, all ports hanging off the device are properly
  detached.  Prior to this patch, ports on the first host_set weren't
  detached casuing oops on driver unloading.

* On device removal, both host_sets are properly freed

This will also be used by new power management code to suspend and
resume all ports of a controller.  host_set/port representation will
be improved to handle legacy controllers better and this host_set
linking will go away with it.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/scsi/libata-bmdma.c
drivers/scsi/libata-core.c
include/linux/libata.h

index 4bc05371737ccfc40cc7f39c49c91f63585fbaf8..13fab97c840e1f0f5e5244372a481cd971b7f209 100644 (file)
@@ -1076,10 +1076,21 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
 
        /* FIXME: check ata_device_add return */
        if (legacy_mode) {
-               if (legacy_mode & (1 << 0))
+               struct device *dev = &pdev->dev;
+               struct ata_host_set *host_set = NULL;
+
+               if (legacy_mode & (1 << 0)) {
                        ata_device_add(probe_ent);
-               if (legacy_mode & (1 << 1))
+                       host_set = dev_get_drvdata(dev);
+               }
+
+               if (legacy_mode & (1 << 1)) {
                        ata_device_add(probe_ent2);
+                       if (host_set) {
+                               host_set->next = dev_get_drvdata(dev);
+                               dev_set_drvdata(dev, host_set);
+                       }
+               }
        } else
                ata_device_add(probe_ent);
 
index 014855e5a43ac514bff8b06c79fee9191b06d536..d73cb3672d6a3a6d7b84ed11b9b743834a83131a 100644 (file)
@@ -5621,8 +5621,12 @@ void ata_pci_remove_one (struct pci_dev *pdev)
 {
        struct device *dev = pci_dev_to_dev(pdev);
        struct ata_host_set *host_set = dev_get_drvdata(dev);
+       struct ata_host_set *host_set2 = host_set->next;
 
        ata_host_set_remove(host_set);
+       if (host_set2)
+               ata_host_set_remove(host_set2);
+
        pci_release_regions(pdev);
        pci_disable_device(pdev);
        dev_set_drvdata(dev, NULL);
index 61eea5795d5a7380718a7fa5e533f95d209d49bc..f03b8664af1164b7f0ce797e04f0ada5ffab392f 100644 (file)
@@ -356,7 +356,8 @@ struct ata_host_set {
        unsigned long           flags;
        int                     simplex_claimed;        /* Keep seperate in case we
                                                           ever need to do this locked */
-       struct ata_port *       ports[0];
+       struct ata_host_set     *next;          /* for legacy mode */
+       struct ata_port         *ports[0];
 };
 
 struct ata_queued_cmd {