Skip to content

Commit

Permalink
libata: update libata LLDs to use devres
Browse files Browse the repository at this point in the history
Update libata LLDs to use devres.  Core layer is already converted to
support managed LLDs.  This patch simplifies initialization and fixes
many resource related bugs in init failure and detach path.  For
example, all converted drivers now handle ata_device_add() failure
gracefully without excessive resource rollback code.

As most resources are released automatically on driver detach, many
drivers don't need or can do with much simpler ->{port|host}_stop().
In general, stop callbacks are need iff port or host needs to be given
commands to shut it down.  Note that freezing is enough in many cases
and ports are automatically frozen before being detached.

Signed-off-by: Tejun Heo <[email protected]>
Signed-off-by: Jeff Garzik <[email protected]>
  • Loading branch information
htejun authored and Jeff Garzik committed Feb 9, 2007
1 parent f0d36ef commit 24dc5f3
Show file tree
Hide file tree
Showing 59 changed files with 355 additions and 1,245 deletions.
125 changes: 27 additions & 98 deletions drivers/ata/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <linux/libata.h>
#include <asm/io.h>

#define DRV_NAME "ahci"
#define DRV_VERSION "2.0"
Expand Down Expand Up @@ -166,9 +165,6 @@ enum {
PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */

/* hpriv->flags bits */
AHCI_FLAG_MSI = (1 << 0),

/* ap->flags bits */
AHCI_FLAG_NO_NCQ = (1 << 24),
AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */
Expand All @@ -191,7 +187,6 @@ struct ahci_sg {
};

struct ahci_host_priv {
unsigned long flags;
u32 cap; /* cache of HOST_CAP register */
u32 port_map; /* cache of HOST_PORTS_IMPL reg */
};
Expand Down Expand Up @@ -229,7 +224,6 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
static int ahci_port_resume(struct ata_port *ap);
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 void ahci_remove_one (struct pci_dev *pdev);

static struct scsi_host_template ahci_sht = {
.module = THIS_MODULE,
Expand Down Expand Up @@ -441,9 +435,9 @@ static struct pci_driver ahci_pci_driver = {
.name = DRV_NAME,
.id_table = ahci_pci_tbl,
.probe = ahci_init_one,
.remove = ata_pci_remove_one,
.suspend = ahci_pci_device_suspend,
.resume = ahci_pci_device_resume,
.remove = ahci_remove_one,
};


Expand Down Expand Up @@ -1426,23 +1420,18 @@ static int ahci_port_start(struct ata_port *ap)
dma_addr_t mem_dma;
int rc;

pp = kmalloc(sizeof(*pp), GFP_KERNEL);
pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
if (!pp)
return -ENOMEM;
memset(pp, 0, sizeof(*pp));

rc = ata_pad_alloc(ap, dev);
if (rc) {
kfree(pp);
if (rc)
return rc;
}

mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
if (!mem) {
ata_pad_free(ap, dev);
kfree(pp);
mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma,
GFP_KERNEL);
if (!mem)
return -ENOMEM;
}
memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);

/*
Expand Down Expand Up @@ -1484,9 +1473,7 @@ static int ahci_port_start(struct ata_port *ap)

static void ahci_port_stop(struct ata_port *ap)
{
struct device *dev = ap->host->dev;
struct ahci_host_priv *hpriv = ap->host->private_data;
struct ahci_port_priv *pp = ap->private_data;
void __iomem *mmio = ap->host->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
const char *emsg = NULL;
Expand All @@ -1496,12 +1483,6 @@ static void ahci_port_stop(struct ata_port *ap)
rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
if (rc)
ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);

ap->private_data = NULL;
dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
pp->cmd_slot, pp->cmd_slot_dma);
ata_pad_free(ap, dev);
kfree(pp);
}

static void ahci_setup_port(struct ata_ioports *port, unsigned long base,
Expand Down Expand Up @@ -1669,15 +1650,15 @@ static void ahci_print_info(struct ata_probe_ent *probe_ent)
);
}

static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
unsigned int board_idx = (unsigned int) ent->driver_data;
struct device *dev = &pdev->dev;
struct ata_probe_ent *probe_ent;
struct ahci_host_priv *hpriv;
unsigned long base;
void __iomem *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data;
int have_msi, pci_dev_busy = 0;
int rc;

VPRINTK("ENTER\n");
Expand All @@ -1694,46 +1675,34 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENODEV;
}

rc = pci_enable_device(pdev);
rc = pcim_enable_device(pdev);
if (rc)
return rc;

rc = pci_request_regions(pdev, DRV_NAME);
if (rc) {
pci_dev_busy = 1;
goto err_out;
pcim_pin_device(pdev);
return rc;
}

if (pci_enable_msi(pdev) == 0)
have_msi = 1;
else {
if (pci_enable_msi(pdev))
pci_intx(pdev, 1);
have_msi = 0;
}

probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
if (probe_ent == NULL) {
rc = -ENOMEM;
goto err_out_msi;
}
probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
if (probe_ent == NULL)
return -ENOMEM;

memset(probe_ent, 0, sizeof(*probe_ent));
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);

mmio_base = pci_iomap(pdev, AHCI_PCI_BAR, 0);
if (mmio_base == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
}
mmio_base = pcim_iomap(pdev, AHCI_PCI_BAR, 0);
if (mmio_base == NULL)
return -ENOMEM;
base = (unsigned long) mmio_base;

hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
if (!hpriv) {
rc = -ENOMEM;
goto err_out_iounmap;
}
memset(hpriv, 0, sizeof(*hpriv));
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
if (!hpriv)
return -ENOMEM;

probe_ent->sht = ahci_port_info[board_idx].sht;
probe_ent->port_flags = ahci_port_info[board_idx].flags;
Expand All @@ -1746,62 +1715,22 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->mmio_base = mmio_base;
probe_ent->private_data = hpriv;

if (have_msi)
hpriv->flags |= AHCI_FLAG_MSI;

/* initialize adapter */
rc = ahci_host_init(probe_ent);
if (rc)
goto err_out_hpriv;
return rc;

if (!(probe_ent->port_flags & AHCI_FLAG_NO_NCQ) &&
(hpriv->cap & HOST_CAP_NCQ))
probe_ent->port_flags |= ATA_FLAG_NCQ;

ahci_print_info(probe_ent);

/* FIXME: check ata_device_add return value */
ata_device_add(probe_ent);
kfree(probe_ent);
if (!ata_device_add(probe_ent))
return -ENODEV;

devm_kfree(dev, probe_ent);
return 0;

err_out_hpriv:
kfree(hpriv);
err_out_iounmap:
pci_iounmap(pdev, mmio_base);
err_out_free_ent:
kfree(probe_ent);
err_out_msi:
if (have_msi)
pci_disable_msi(pdev);
else
pci_intx(pdev, 0);
pci_release_regions(pdev);
err_out:
if (!pci_dev_busy)
pci_disable_device(pdev);
return rc;
}

static void ahci_remove_one(struct pci_dev *pdev)
{
struct device *dev = pci_dev_to_dev(pdev);
struct ata_host *host = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = host->private_data;

ata_host_remove(host);

pci_iounmap(pdev, host->mmio_base);

if (hpriv->flags & AHCI_FLAG_MSI)
pci_disable_msi(pdev);
else
pci_intx(pdev, 0);
pci_release_regions(pdev);
pci_disable_device(pdev);
dev_set_drvdata(dev, NULL);
kfree(hpriv);
}

static int __init ahci_init(void)
Expand Down
2 changes: 0 additions & 2 deletions drivers/ata/ata_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,6 @@ static struct ata_port_operations generic_port_ops = {
.irq_clear = ata_bmdma_irq_clear,

.port_start = ata_port_start,
.port_stop = ata_port_stop,
.host_stop = ata_host_stop
};

static int all_generic_ide; /* Set to claim all devices */
Expand Down
19 changes: 2 additions & 17 deletions drivers/ata/ata_piix.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ struct piix_host_priv {

static int piix_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent);
static void piix_host_stop(struct ata_host *host);
static void piix_pata_error_handler(struct ata_port *ap);
static void ich_pata_error_handler(struct ata_port *ap);
static void piix_sata_error_handler(struct ata_port *ap);
Expand Down Expand Up @@ -311,8 +310,6 @@ static const struct ata_port_operations piix_pata_ops = {
.irq_clear = ata_bmdma_irq_clear,

.port_start = ata_port_start,
.port_stop = ata_port_stop,
.host_stop = piix_host_stop,
};

static const struct ata_port_operations ich_pata_ops = {
Expand Down Expand Up @@ -344,8 +341,6 @@ static const struct ata_port_operations ich_pata_ops = {
.irq_clear = ata_bmdma_irq_clear,

.port_start = ata_port_start,
.port_stop = ata_port_stop,
.host_stop = piix_host_stop,
};

static const struct ata_port_operations piix_sata_ops = {
Expand Down Expand Up @@ -374,8 +369,6 @@ static const struct ata_port_operations piix_sata_ops = {
.irq_clear = ata_bmdma_irq_clear,

.port_start = ata_port_start,
.port_stop = ata_port_stop,
.host_stop = piix_host_stop,
};

static const struct piix_map_db ich5_map_db = {
Expand Down Expand Up @@ -1072,6 +1065,7 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
struct device *dev = &pdev->dev;
struct ata_port_info port_info[2];
struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] };
struct piix_host_priv *hpriv;
Expand All @@ -1085,7 +1079,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (!in_module_init)
return -ENODEV;

hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
if (!hpriv)
return -ENOMEM;

Expand Down Expand Up @@ -1135,15 +1129,6 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return ata_pci_init_one(pdev, ppinfo, 2);
}

static void piix_host_stop(struct ata_host *host)
{
struct piix_host_priv *hpriv = host->private_data;

ata_host_stop(host);

kfree(hpriv);
}

static int __init piix_init(void)
{
int rc;
Expand Down
8 changes: 0 additions & 8 deletions drivers/ata/pata_ali.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,6 @@ static struct ata_port_operations ali_early_port_ops = {
.irq_clear = ata_bmdma_irq_clear,

.port_start = ata_port_start,
.port_stop = ata_port_stop,
.host_stop = ata_host_stop
};

/*
Expand Down Expand Up @@ -417,8 +415,6 @@ static struct ata_port_operations ali_20_port_ops = {
.irq_clear = ata_bmdma_irq_clear,

.port_start = ata_port_start,
.port_stop = ata_port_stop,
.host_stop = ata_host_stop
};

/*
Expand Down Expand Up @@ -455,8 +451,6 @@ static struct ata_port_operations ali_c2_port_ops = {
.irq_clear = ata_bmdma_irq_clear,

.port_start = ata_port_start,
.port_stop = ata_port_stop,
.host_stop = ata_host_stop
};

/*
Expand Down Expand Up @@ -492,8 +486,6 @@ static struct ata_port_operations ali_c5_port_ops = {
.irq_clear = ata_bmdma_irq_clear,

.port_start = ata_port_start,
.port_stop = ata_port_stop,
.host_stop = ata_host_stop
};


Expand Down
Loading

0 comments on commit 24dc5f3

Please sign in to comment.