Commit fad16e7a authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik

ahci: fix module refcount breakage introduced by libahci split

libata depends on scsi_host_template for module reference counting and
sht's should be owned by each low level driver.  During libahci split,
the sht was left with libahci.ko leaving the actual low level drivers
not reference counted.  This made ahci and ahci_platform always
unloadable even while they're being actively used.

Fix it by defining AHCI_SHT() macro in ahci.h and defining a sht for
each low level ahci driver.

stable: only applicable to 2.6.35.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Reported-by: default avatarPedro Francisco <pedrogfrancisco@gmail.com>
Tested-by: default avatarMichael Tokarev <mjt@tls.msk.ru>
Cc: stable@kernel.org
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 050026fe
...@@ -90,6 +90,10 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); ...@@ -90,6 +90,10 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int ahci_pci_device_resume(struct pci_dev *pdev); static int ahci_pci_device_resume(struct pci_dev *pdev);
#endif #endif
static struct scsi_host_template ahci_sht = {
AHCI_SHT("ahci"),
};
static struct ata_port_operations ahci_vt8251_ops = { static struct ata_port_operations ahci_vt8251_ops = {
.inherits = &ahci_ops, .inherits = &ahci_ops,
.hardreset = ahci_vt8251_hardreset, .hardreset = ahci_vt8251_hardreset,
......
...@@ -298,7 +298,17 @@ struct ahci_host_priv { ...@@ -298,7 +298,17 @@ struct ahci_host_priv {
extern int ahci_ignore_sss; extern int ahci_ignore_sss;
extern struct scsi_host_template ahci_sht; extern struct device_attribute *ahci_shost_attrs[];
extern struct device_attribute *ahci_sdev_attrs[];
#define AHCI_SHT(drv_name) \
ATA_NCQ_SHT(drv_name), \
.can_queue = AHCI_MAX_CMDS - 1, \
.sg_tablesize = AHCI_MAX_SG, \
.dma_boundary = AHCI_DMA_BOUNDARY, \
.shost_attrs = ahci_shost_attrs, \
.sdev_attrs = ahci_sdev_attrs
extern struct ata_port_operations ahci_ops; extern struct ata_port_operations ahci_ops;
void ahci_save_initial_config(struct device *dev, void ahci_save_initial_config(struct device *dev,
......
...@@ -23,6 +23,10 @@ ...@@ -23,6 +23,10 @@
#include <linux/ahci_platform.h> #include <linux/ahci_platform.h>
#include "ahci.h" #include "ahci.h"
static struct scsi_host_template ahci_platform_sht = {
AHCI_SHT("ahci_platform"),
};
static int __init ahci_probe(struct platform_device *pdev) static int __init ahci_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -145,7 +149,7 @@ static int __init ahci_probe(struct platform_device *pdev) ...@@ -145,7 +149,7 @@ static int __init ahci_probe(struct platform_device *pdev)
ahci_print_info(host, "platform"); ahci_print_info(host, "platform");
rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
&ahci_sht); &ahci_platform_sht);
if (rc) if (rc)
goto err0; goto err0;
......
...@@ -121,7 +121,7 @@ static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); ...@@ -121,7 +121,7 @@ static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO, static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
ahci_read_em_buffer, ahci_store_em_buffer); ahci_read_em_buffer, ahci_store_em_buffer);
static struct device_attribute *ahci_shost_attrs[] = { struct device_attribute *ahci_shost_attrs[] = {
&dev_attr_link_power_management_policy, &dev_attr_link_power_management_policy,
&dev_attr_em_message_type, &dev_attr_em_message_type,
&dev_attr_em_message, &dev_attr_em_message,
...@@ -132,22 +132,14 @@ static struct device_attribute *ahci_shost_attrs[] = { ...@@ -132,22 +132,14 @@ static struct device_attribute *ahci_shost_attrs[] = {
&dev_attr_em_buffer, &dev_attr_em_buffer,
NULL NULL
}; };
EXPORT_SYMBOL_GPL(ahci_shost_attrs);
static struct device_attribute *ahci_sdev_attrs[] = { struct device_attribute *ahci_sdev_attrs[] = {
&dev_attr_sw_activity, &dev_attr_sw_activity,
&dev_attr_unload_heads, &dev_attr_unload_heads,
NULL NULL
}; };
EXPORT_SYMBOL_GPL(ahci_sdev_attrs);
struct scsi_host_template ahci_sht = {
ATA_NCQ_SHT("ahci"),
.can_queue = AHCI_MAX_CMDS - 1,
.sg_tablesize = AHCI_MAX_SG,
.dma_boundary = AHCI_DMA_BOUNDARY,
.shost_attrs = ahci_shost_attrs,
.sdev_attrs = ahci_sdev_attrs,
};
EXPORT_SYMBOL_GPL(ahci_sht);
struct ata_port_operations ahci_ops = { struct ata_port_operations ahci_ops = {
.inherits = &sata_pmp_port_ops, .inherits = &sata_pmp_port_ops,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment