* [PATCH 04/12] libata: implement ata_host_alloc_pinfo() and ata_host_attach()
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
2007-03-09 16:08 ` Jeff Garzik
2007-03-09 11:15 ` [PATCH 02/12] libata: separate out ata_host_start() Tejun Heo
` (10 subsequent siblings)
11 siblings, 1 reply; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
Implement ata_host_alloc_pinfo() and ata_host_attach(). These helpers
will be used in the following patches to adopt new init model.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/libata-core.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/libata.h | 5 ++
2 files changed, 98 insertions(+), 0 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b95618d..97e7d9c 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5684,6 +5684,55 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
}
/**
+ * ata_host_alloc_pinfo - alloc host and init with port_info array
+ * @dev: generic device this host is associated with
+ * @ppi: array of ATA port_info to initialize host with
+ * @n_ports: number of ATA ports attached to this host
+ *
+ * Allocate ATA host and initialize with info from @ppi. If NULL
+ * terminated, @ppi may contain fewer entries than @n_ports. The
+ * last entry will be used for the remaining ports.
+ *
+ * RETURNS:
+ * Allocate ATA host on success, NULL on failure.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ */
+struct ata_host *ata_host_alloc_pinfo(struct device *dev,
+ const struct ata_port_info * const * ppi,
+ int n_ports)
+{
+ const struct ata_port_info *pi;
+ struct ata_host *host;
+ int i, j;
+
+ host = ata_host_alloc(dev, n_ports);
+ if (!host)
+ return NULL;
+
+ for (i = 0, j = 0, pi = NULL; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ if (ppi[j])
+ pi = ppi[j++];
+
+ ap->pio_mask = pi->pio_mask;
+ ap->mwdma_mask = pi->mwdma_mask;
+ ap->udma_mask = pi->udma_mask;
+ ap->flags |= pi->flags;
+ ap->ops = pi->port_ops;
+
+ if (!host->ops && (pi->port_ops != &ata_dummy_port_ops))
+ host->ops = pi->port_ops;
+ if (!host->private_data && pi->private_data)
+ host->private_data = pi->private_data;
+ }
+
+ return host;
+}
+
+/**
* ata_host_start - start and freeze ports of an ATA host
* @host: ATA host to start ports for
*
@@ -5896,6 +5945,48 @@ int ata_host_attach(struct ata_host *host, struct scsi_host_template *sht)
}
/**
+ * ata_host_activate - start host, request IRQ and attach it
+ * @host: target ATA host
+ * @irq: IRQ to request
+ * @irq_handler: irq_handler used when requesting IRQ
+ * @irq_flags: irq_flags used when requesting IRQ
+ * @sht: scsi_host_template to use when attaching the host
+ *
+ * After allocating an ATA host and initializing it, most libata
+ * LLDs perform three steps to activate the host - start host,
+ * request IRQ and attach it. This helper takes necessasry
+ * arguments and performs the three steps in one go.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+int ata_host_activate(struct ata_host *host, int irq,
+ irq_handler_t irq_handler, unsigned long irq_flags,
+ struct scsi_host_template *sht)
+{
+ int rc;
+
+ rc = ata_host_start(host);
+ if (rc)
+ return rc;
+
+ rc = devm_request_irq(host->dev, irq, irq_handler, irq_flags,
+ dev_driver_string(host->dev), host);
+ if (rc)
+ return rc;
+
+ rc = ata_host_attach(host, sht);
+ /* if failed, just free the IRQ and leave ports alone */
+ if (rc)
+ devm_free_irq(host->dev, irq, host);
+
+ return rc;
+}
+
+/**
* ata_device_add - Register hardware device with ATA and SCSI layers
* @ent: Probe information describing hardware device to be registered
*
@@ -6470,8 +6561,10 @@ EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_std_ports);
EXPORT_SYMBOL_GPL(ata_host_init);
EXPORT_SYMBOL_GPL(ata_host_alloc);
+EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo);
EXPORT_SYMBOL_GPL(ata_host_start);
EXPORT_SYMBOL_GPL(ata_host_attach);
+EXPORT_SYMBOL_GPL(ata_host_activate);
EXPORT_SYMBOL_GPL(ata_device_add);
EXPORT_SYMBOL_GPL(ata_host_detach);
EXPORT_SYMBOL_GPL(ata_sg_init);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 9edb7c7..202ed7a 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -729,9 +729,14 @@ extern int ata_pci_device_resume(struct pci_dev *pdev);
extern int ata_pci_clear_simplex(struct pci_dev *pdev);
#endif /* CONFIG_PCI */
extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports);
+extern struct ata_host *ata_host_alloc_pinfo(struct device *dev,
+ const struct ata_port_info * const * ppi, int n_ports);
extern int ata_host_start(struct ata_host *host);
extern int ata_host_attach(struct ata_host *host,
struct scsi_host_template *sht);
+extern int ata_host_activate(struct ata_host *host, int irq,
+ irq_handler_t irq_handler, unsigned long irq_flags,
+ struct scsi_host_template *sht);
extern int ata_device_add(const struct ata_probe_ent *ent);
extern void ata_host_detach(struct ata_host *host);
extern void ata_host_init(struct ata_host *, struct device *,
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 02/12] libata: separate out ata_host_start()
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
2007-03-09 11:15 ` [PATCH 04/12] libata: implement ata_host_alloc_pinfo() and ata_host_attach() Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
2007-03-09 11:15 ` [PATCH 05/12] libata: convert legacy PCI host handling to new init model Tejun Heo
` (9 subsequent siblings)
11 siblings, 0 replies; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
Separate out ata_host_start() from ata_device_add(). ata_host_start()
calls ->port_start on each port if available and freezes the port.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/libata-core.c | 74 +++++++++++++++++++++++++++++++++++++--------
include/linux/libata.h | 2 +
2 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index fab488c..6a4e7a4 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5671,11 +5671,14 @@ static void ata_host_release(struct device *gendev, void *res)
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
- if (ap && ap->ops->port_stop)
+ if (!ap)
+ continue;
+
+ if ((host->flags & ATA_HOST_STARTED) && ap->ops->port_stop)
ap->ops->port_stop(ap);
}
- if (host->ops->host_stop)
+ if ((host->flags & ATA_HOST_STARTED) && host->ops->host_stop)
host->ops->host_stop(host);
for (i = 0; i < host->n_ports; i++) {
@@ -5695,6 +5698,56 @@ static void ata_host_release(struct device *gendev, void *res)
}
/**
+ * ata_host_start - start and freeze ports of an ATA host
+ * @host: ATA host to start ports for
+ *
+ * Start and then freeze ports of @host. Started status is
+ * recorded in host->flags, so this function can be called
+ * multiple times. Ports are guaranteed to get started only
+ * once.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ *
+ * RETURNS:
+ * 0 if all ports are started successfully, -errno otherwise.
+ */
+int ata_host_start(struct ata_host *host)
+{
+ int i, rc;
+
+ if (host->flags & ATA_HOST_STARTED)
+ return 0;
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ if (ap->ops->port_start) {
+ rc = ap->ops->port_start(ap);
+ if (rc) {
+ ata_port_printk(ap, KERN_ERR, "failed to "
+ "start port (errno=%d)\n", rc);
+ goto err_out;
+ }
+ }
+
+ ata_eh_freeze_port(ap);
+ }
+
+ host->flags |= ATA_HOST_STARTED;
+ return 0;
+
+ err_out:
+ while (--i >= 0) {
+ struct ata_port *ap = host->ports[i];
+
+ if (ap->ops->port_stop)
+ ap->ops->port_stop(ap);
+ }
+ return rc;
+}
+
+/**
* ata_sas_host_init - Initialize a host struct
* @host: host to initialize
* @dev: device host is attached to
@@ -5783,14 +5836,6 @@ int ata_device_add(const struct ata_probe_ent *ent)
continue;
}
- /* start port */
- rc = ap->ops->port_start(ap);
- if (rc) {
- host->ports[i] = NULL;
- scsi_host_put(ap->scsi_host);
- goto err_out;
- }
-
/* Report the secondary IRQ for second channel legacy */
if (i == 1 && ent->irq2)
irq_line = ent->irq2;
@@ -5808,11 +5853,13 @@ int ata_device_add(const struct ata_probe_ent *ent)
ap->ioaddr.ctl_addr,
ap->ioaddr.bmdma_addr,
irq_line);
-
- /* freeze port before requesting IRQ */
- ata_eh_freeze_port(ap);
}
+ /* start ports */
+ rc = ata_host_start(host);
+ if (rc)
+ goto err_out;
+
/* obtain irq, that may be shared between channels */
rc = devm_request_irq(dev, ent->irq, ent->port_ops->irq_handler,
ent->irq_flags, DRV_NAME, host);
@@ -6367,6 +6414,7 @@ EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_std_ports);
EXPORT_SYMBOL_GPL(ata_host_init);
+EXPORT_SYMBOL_GPL(ata_host_start);
EXPORT_SYMBOL_GPL(ata_device_add);
EXPORT_SYMBOL_GPL(ata_host_detach);
EXPORT_SYMBOL_GPL(ata_sg_init);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index cfdc617..296c9ef 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -210,6 +210,7 @@ enum {
/* host set flags */
ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host only */
+ ATA_HOST_STARTED = (1 << 1), /* Host started */
/* various lengths of time */
ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */
@@ -727,6 +728,7 @@ extern int ata_pci_device_resume(struct pci_dev *pdev);
#endif
extern int ata_pci_clear_simplex(struct pci_dev *pdev);
#endif /* CONFIG_PCI */
+extern int ata_host_start(struct ata_host *host);
extern int ata_device_add(const struct ata_probe_ent *ent);
extern void ata_host_detach(struct ata_host *host);
extern void ata_host_init(struct ata_host *, struct device *,
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 05/12] libata: convert legacy PCI host handling to new init model
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
2007-03-09 11:15 ` [PATCH 04/12] libata: implement ata_host_alloc_pinfo() and ata_host_attach() Tejun Heo
2007-03-09 11:15 ` [PATCH 02/12] libata: separate out ata_host_start() Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
2007-03-09 17:46 ` Jeff Garzik
2007-03-09 11:15 ` [PATCH 03/12] libata: separate out ata_host_alloc() and ata_host_attach() Tejun Heo
` (8 subsequent siblings)
11 siblings, 1 reply; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
Convert legacy PCI host handling to alloc-init-attach model.
ata_init_legacy_host(), ata_request_legacy_irqs() and
ata_pci_init_bmdma() are separated out and follow the new init model.
The two legacy handling functions use separate ata_legacy_devres
instead of generic devm_* resources. This reduces devres overhead for
legacy hosts which was a bit high because it didn't use PCI/iomap
merged resoruces.
ata_pci_init_one() is rewritten in terms of the aboved functions but
native mode handling is still using the old method. Conversion will
be completed when native mode handling is updated.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/libata-sff.c | 436 +++++++++++++++++++++++++++++++++-------------
1 files changed, 312 insertions(+), 124 deletions(-)
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index dfd906c..8287df5 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -627,75 +627,278 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
return probe_ent;
}
-static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
- struct ata_port_info **port, int port_mask)
+/**
+ * ata_pci_init_bmdma - acquire PCI BMDMA resources and init ATA host
+ * @host: target ATA host
+ *
+ * Acquire PCI BMDMA resources and initialize @host accordingly.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+static int ata_pci_init_bmdma(struct ata_host *host)
{
- struct ata_probe_ent *probe_ent;
- void __iomem *iomap[5] = { }, *bmdma;
+ struct device *gdev = host->dev;
+ struct pci_dev *pdev = to_pci_dev(gdev);
+ int i, rc;
- if (port_mask & ATA_PORT_PRIMARY) {
- iomap[0] = devm_ioport_map(&pdev->dev, ATA_PRIMARY_CMD, 8);
- iomap[1] = devm_ioport_map(&pdev->dev, ATA_PRIMARY_CTL, 1);
- if (!iomap[0] || !iomap[1])
- return NULL;
+ /* TODO: If we get no DMA mask we should fall back to PIO */
+ rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
+ if (rc)
+ return rc;
+
+ /* request and iomap DMA region */
+ rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME);
+ if (rc) {
+ dev_printk(KERN_ERR, gdev, "failed to request/iomap BAR4\n");
+ return -ENOMEM;
}
+ host->iomap = pcim_iomap_table(pdev);
- if (port_mask & ATA_PORT_SECONDARY) {
- iomap[2] = devm_ioport_map(&pdev->dev, ATA_SECONDARY_CMD, 8);
- iomap[3] = devm_ioport_map(&pdev->dev, ATA_SECONDARY_CTL, 1);
- if (!iomap[2] || !iomap[3])
- return NULL;
+ for (i = 0; i < 2; i++) {
+ struct ata_port *ap = host->ports[i];
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ void __iomem *bmdma = host->iomap[4] + 8 * i;
+
+ if (ata_port_is_dummy(ap))
+ continue;
+
+ ioaddr->bmdma_addr = bmdma;
+ if ((!(ap->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+ (ioread8(bmdma + 2) & 0x80))
+ host->flags |= ATA_HOST_SIMPLEX;
}
- bmdma = pcim_iomap(pdev, 4, 16); /* may fail */
+ return 0;
+}
+
+struct ata_legacy_devres {
+ unsigned int mask;
+ unsigned long cmd_port[2];
+ void __iomem * cmd_addr[2];
+ void __iomem * ctl_addr[2];
+ unsigned int irq[2];
+ void * irq_dev_id[2];
+};
- /* alloc and init probe_ent */
- probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
- if (!probe_ent)
- return NULL;
+static void ata_legacy_free_irqs(struct ata_legacy_devres *legacy_dr)
+{
+ int i;
- probe_ent->n_ports = 2;
- probe_ent->irq_flags = IRQF_SHARED;
+ for (i = 0; i < 2; i++) {
+ if (!legacy_dr->irq[i])
+ continue;
- if (port_mask & ATA_PORT_PRIMARY) {
- probe_ent->irq = ATA_PRIMARY_IRQ(pdev);
- probe_ent->port[0].cmd_addr = iomap[0];
- probe_ent->port[0].altstatus_addr =
- probe_ent->port[0].ctl_addr = iomap[1];
- if (bmdma) {
- probe_ent->port[0].bmdma_addr = bmdma;
- if ((!(port[0]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
- (ioread8(bmdma + 2) & 0x80))
- probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
+ free_irq(legacy_dr->irq[i], legacy_dr->irq_dev_id[i]);
+ legacy_dr->irq[i] = 0;
+ legacy_dr->irq_dev_id[i] = NULL;
+ }
+}
+
+static void ata_legacy_release(struct device *gdev, void *res)
+{
+ struct ata_legacy_devres *this = res;
+ int i;
+
+ ata_legacy_free_irqs(this);
+
+ for (i = 0; i < 2; i++) {
+ if (this->cmd_addr[i])
+ ioport_unmap(this->cmd_addr[i]);
+ if (this->ctl_addr[i])
+ ioport_unmap(this->ctl_addr[i]);
+ if (this->cmd_port[i])
+ release_region(this->cmd_port[i], 8);
+ }
+}
+
+static int ata_init_legacy_port(struct ata_port *ap,
+ struct ata_legacy_devres *legacy_dr)
+{
+ struct ata_host *host = ap->host;
+ int port_no = ap->port_no;
+ unsigned long cmd_port, ctl_port;
+
+ if (port_no == 0) {
+ cmd_port = ATA_PRIMARY_CMD;
+ ctl_port = ATA_PRIMARY_CTL;
+ } else {
+ cmd_port = ATA_SECONDARY_CMD;
+ ctl_port = ATA_SECONDARY_CTL;
+ }
+
+ /* request cmd_port */
+ if (request_region(cmd_port, 8, "libata"))
+ legacy_dr->cmd_port[port_no] = cmd_port;
+ else {
+ struct resource *conflict, res;
+
+ /* Deal with combined mode hack. This side of the
+ * logic all goes away once the combined mode hack is
+ * killed in 2.6.21.
+ */
+ res.start = cmd_port;
+ res.end = cmd_port + 8 - 1;
+ conflict = ____request_resource(&ioport_resource, &res);
+ while (conflict->child)
+ conflict = ____request_resource(conflict, &res);
+ if (strcmp(conflict->name, "libata")) {
+ dev_printk(KERN_WARNING, host->dev,
+ "0x%0lX IDE port busy\n", cmd_port);
+ return -EBUSY;
}
- ata_std_ports(&probe_ent->port[0]);
- } else
- probe_ent->dummy_port_mask |= ATA_PORT_PRIMARY;
+ dev_printk(KERN_INFO, host->dev,
+ "0x%0lX IDE port preallocated\n", cmd_port);
+ }
+
+ /* iomap cmd and ctl ports */
+ legacy_dr->cmd_addr[port_no] = ioport_map(cmd_port, 8);
+ legacy_dr->ctl_addr[port_no] = ioport_map(ctl_port, 1);
+ if (!legacy_dr->cmd_addr[port_no] || !legacy_dr->ctl_addr[port_no])
+ return -ENOMEM;
+
+ /* init IO addresses */
+ ap->ioaddr.cmd_addr = legacy_dr->cmd_addr[port_no];
+ ap->ioaddr.altstatus_addr = legacy_dr->ctl_addr[port_no];
+ ap->ioaddr.ctl_addr = legacy_dr->ctl_addr[port_no];
+ ata_std_ports(&ap->ioaddr);
+
+ return 0;
+}
+
+/**
+ * ata_init_legacy_host - acquire legacy ATA resources and init ATA host
+ * @host: target ATA host
+ * @legacy_mask: out parameter, mask indicating ports is in legacy mode
+ * @was_busy: out parameter, indicates whether any port was busy
+ *
+ * Acquire legacy ATA resources for ports.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+static int ata_init_legacy_host(struct ata_host *host,
+ unsigned int *legacy_mask, int *was_busy)
+{
+ struct device *gdev = host->dev;
+ struct ata_legacy_devres *legacy_dr;
+ int i, rc;
+
+ if (!devres_open_group(gdev, NULL, GFP_KERNEL))
+ return -ENOMEM;
+
+ rc = -ENOMEM;
+ legacy_dr = devres_alloc(ata_legacy_release, sizeof(*legacy_dr),
+ GFP_KERNEL);
+ if (!legacy_dr)
+ goto err_out;
+ devres_add(gdev, legacy_dr);
+
+ for (i = 0; i < 2; i++) {
+ *legacy_mask &= ~(1 << i);
+ rc = ata_init_legacy_port(host->ports[i], legacy_dr);
+ if (rc == 0)
+ legacy_dr->mask |= 1 << i;
+ else if (rc == -EBUSY)
+ (*was_busy)++;
+ }
+
+ if (!legacy_dr->mask)
+ return -EBUSY;
- if (port_mask & ATA_PORT_SECONDARY) {
- if (probe_ent->irq)
- probe_ent->irq2 = ATA_SECONDARY_IRQ(pdev);
+ for (i = 0; i < 2; i++)
+ if (!(legacy_dr->mask & (1 << i)))
+ host->ports[i]->ops = &ata_dummy_port_ops;
+
+ *legacy_mask |= legacy_dr->mask;
+
+ devres_remove_group(gdev, NULL);
+ return 0;
+
+ err_out:
+ devres_release_group(gdev, NULL);
+ return rc;
+}
+
+/**
+ * ata_request_legacy_irqs - request legacy ATA IRQs
+ * @host: target ATA host
+ * @handler: array of IRQ handlers
+ * @irq_flags: array of IRQ flags
+ * @dev_id: array of IRQ dev_ids
+ *
+ * Request legacy IRQs for non-dummy legacy ports in @host. All
+ * IRQ parameters are passed as array to allow ports to have
+ * separate IRQ handlers.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+static int ata_request_legacy_irqs(struct ata_host *host,
+ irq_handler_t const *handler,
+ const unsigned int *irq_flags,
+ void * const *dev_id)
+{
+ struct device *gdev = host->dev;
+ struct ata_legacy_devres *legacy_dr;
+ int i, rc;
+
+ legacy_dr = devres_find(host->dev, ata_legacy_release, NULL, NULL);
+ BUG_ON(!legacy_dr);
+
+ for (i = 0; i < 2; i++) {
+ unsigned int irq;
+
+ /* FIXME: ATA_*_IRQ() should take generic device not pci_dev */
+ if (i == 0)
+ irq = ATA_PRIMARY_IRQ(to_pci_dev(gdev));
else
- probe_ent->irq = ATA_SECONDARY_IRQ(pdev);
- probe_ent->port[1].cmd_addr = iomap[2];
- probe_ent->port[1].altstatus_addr =
- probe_ent->port[1].ctl_addr = iomap[3];
- if (bmdma) {
- probe_ent->port[1].bmdma_addr = bmdma + 8;
- if ((!(port[1]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
- (ioread8(bmdma + 10) & 0x80))
- probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
+ irq = ATA_SECONDARY_IRQ(to_pci_dev(gdev));
+
+ if (!(legacy_dr->mask & (1 << i)))
+ continue;
+
+ if (!handler[i]) {
+ dev_printk(KERN_ERR, gdev,
+ "NULL handler specified for port %d\n", i);
+ rc = -EINVAL;
+ goto err_out;
}
- ata_std_ports(&probe_ent->port[1]);
- /* FIXME: could be pointing to stack area; must copy */
- probe_ent->pinfo2 = port[1];
- } else
- probe_ent->dummy_port_mask |= ATA_PORT_SECONDARY;
+ rc = request_irq(irq, handler[i], irq_flags[i], DRV_NAME,
+ dev_id[i]);
+ if (rc) {
+ dev_printk(KERN_ERR, gdev,
+ "irq %u request failed (errno=%d)\n", irq, rc);
+ goto err_out;
+ }
- return probe_ent;
-}
+ /* record irq allocation in legacy_dr */
+ legacy_dr->irq[i] = irq;
+ legacy_dr->irq_dev_id[i] = dev_id[i];
+
+ /* only used to print info */
+ if (i == 0)
+ host->irq = irq;
+ else
+ host->irq2 = irq;
+ }
+ return 0;
+
+ err_out:
+ ata_legacy_free_irqs(legacy_dr);
+ return rc;
+}
/**
* ata_pci_init_one - Initialize/register PCI IDE host controller
@@ -727,7 +930,8 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
{
struct device *dev = &pdev->dev;
struct ata_probe_ent *probe_ent = NULL;
- struct ata_port_info *port[2];
+ struct ata_host *host = NULL;
+ const struct ata_port_info *port[2];
u8 mask;
unsigned int legacy_mode = 0;
int rc;
@@ -783,87 +987,71 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
pcim_pin_device(pdev);
goto err_out;
}
+
+ /* TODO: If we get no DMA mask we should fall back to PIO */
+ rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
+ if (rc)
+ goto err_out;
+
+ pci_set_master(pdev);
} else {
- /* Deal with combined mode hack. This side of the logic all
- goes away once the combined mode hack is killed in 2.6.21 */
- if (!devm_request_region(dev, ATA_PRIMARY_CMD, 8, "libata")) {
- struct resource *conflict, res;
- res.start = ATA_PRIMARY_CMD;
- res.end = ATA_PRIMARY_CMD + 8 - 1;
- conflict = ____request_resource(&ioport_resource, &res);
- while (conflict->child)
- conflict = ____request_resource(conflict, &res);
- if (!strcmp(conflict->name, "libata"))
- legacy_mode |= ATA_PORT_PRIMARY;
- else {
- pcim_pin_device(pdev);
- printk(KERN_WARNING "ata: 0x%0X IDE port busy\n" \
- "ata: conflict with %s\n",
- ATA_PRIMARY_CMD,
- conflict->name);
- }
- } else
- legacy_mode |= ATA_PORT_PRIMARY;
-
- if (!devm_request_region(dev, ATA_SECONDARY_CMD, 8, "libata")) {
- struct resource *conflict, res;
- res.start = ATA_SECONDARY_CMD;
- res.end = ATA_SECONDARY_CMD + 8 - 1;
- conflict = ____request_resource(&ioport_resource, &res);
- while (conflict->child)
- conflict = ____request_resource(conflict, &res);
- if (!strcmp(conflict->name, "libata"))
- legacy_mode |= ATA_PORT_SECONDARY;
- else {
- pcim_pin_device(pdev);
- printk(KERN_WARNING "ata: 0x%X IDE port busy\n" \
- "ata: conflict with %s\n",
- ATA_SECONDARY_CMD,
- conflict->name);
- }
- } else
- legacy_mode |= ATA_PORT_SECONDARY;
-
- if (legacy_mode & ATA_PORT_PRIMARY)
- pci_request_region(pdev, 1, DRV_NAME);
- if (legacy_mode & ATA_PORT_SECONDARY)
- pci_request_region(pdev, 3, DRV_NAME);
- /* If there is a DMA resource, allocate it */
- pci_request_region(pdev, 4, DRV_NAME);
- }
+ int was_busy = 0;
- /* we have legacy mode, but all ports are unavailable */
- if (legacy_mode == (1 << 3)) {
- rc = -EBUSY;
- goto err_out;
- }
+ rc = -ENOMEM;
+ host = ata_host_alloc_pinfo(dev, port, 2);
+ if (!host)
+ goto err_out;
- /* TODO: If we get no DMA mask we should fall back to PIO */
- rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
- if (rc)
- goto err_out;
+ rc = ata_init_legacy_host(host, &legacy_mode, &was_busy);
+ if (was_busy)
+ pcim_pin_device(pdev);
+ if (rc)
+ goto err_out;
+
+ /* request respective PCI regions, may fail */
+ rc = pci_request_region(pdev, 1, DRV_NAME);
+ rc = pci_request_region(pdev, 3, DRV_NAME);
+
+ /* init bmdma */
+ ata_pci_init_bmdma(host);
+ pci_set_master(pdev);
+ }
if (legacy_mode) {
- probe_ent = ata_pci_init_legacy_port(pdev, port, legacy_mode);
+ irq_handler_t handler[2] = { host->ops->irq_handler,
+ host->ops->irq_handler };
+ unsigned int irq_flags[2] = { IRQF_SHARED, IRQF_SHARED };
+ void *dev_id[2] = { host, host };
+
+ rc = ata_host_start(host);
+ if (rc)
+ goto err_out;
+
+ rc = ata_request_legacy_irqs(host, handler, irq_flags, dev_id);
+ if (rc)
+ goto err_out;
+
+ rc = ata_host_attach(host, port_info[0]->sht);
+ if (rc)
+ goto err_out;
} else {
if (n_ports == 2)
- probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
+ probe_ent = ata_pci_init_native_mode(pdev, (struct ata_port_info **)port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
else
- probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
- }
- if (!probe_ent) {
- rc = -ENOMEM;
- goto err_out;
- }
+ probe_ent = ata_pci_init_native_mode(pdev, (struct ata_port_info **)port, ATA_PORT_PRIMARY);
- pci_set_master(pdev);
+ if (!probe_ent) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
- if (!ata_device_add(probe_ent)) {
- rc = -ENODEV;
- goto err_out;
- }
+ if (!ata_device_add(probe_ent)) {
+ rc = -ENODEV;
+ goto err_out;
+ }
- devm_kfree(dev, probe_ent);
+ devm_kfree(dev, probe_ent);
+ }
devres_remove_group(dev, NULL);
return 0;
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH 05/12] libata: convert legacy PCI host handling to new init model
2007-03-09 11:15 ` [PATCH 05/12] libata: convert legacy PCI host handling to new init model Tejun Heo
@ 2007-03-09 17:46 ` Jeff Garzik
0 siblings, 0 replies; 27+ messages in thread
From: Jeff Garzik @ 2007-03-09 17:46 UTC (permalink / raw)
To: Tejun Heo; +Cc: alan, linux-ide
Tejun Heo wrote:
> Convert legacy PCI host handling to alloc-init-attach model.
> ata_init_legacy_host(), ata_request_legacy_irqs() and
> ata_pci_init_bmdma() are separated out and follow the new init model.
>
> The two legacy handling functions use separate ata_legacy_devres
> instead of generic devm_* resources. This reduces devres overhead for
> legacy hosts which was a bit high because it didn't use PCI/iomap
> merged resoruces.
>
> ata_pci_init_one() is rewritten in terms of the aboved functions but
> native mode handling is still using the old method. Conversion will
> be completed when native mode handling is updated.
>
> Signed-off-by: Tejun Heo <htejun@gmail.com>
> ---
> drivers/ata/libata-sff.c | 436 +++++++++++++++++++++++++++++++++-------------
> 1 files changed, 312 insertions(+), 124 deletions(-)
ACK patches 5-12
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 03/12] libata: separate out ata_host_alloc() and ata_host_attach()
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
` (2 preceding siblings ...)
2007-03-09 11:15 ` [PATCH 05/12] libata: convert legacy PCI host handling to new init model Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
2007-03-09 15:34 ` Jeff Garzik
2007-03-12 22:25 ` Brian King
2007-03-09 11:15 ` [PATCH 01/12] libata: allocate ap separately from shost Tejun Heo
` (7 subsequent siblings)
11 siblings, 2 replies; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
Reorganize ata_host_alloc() and its subroutines into the following
three functions.
* ata_host_alloc() : allocates host and its attached ports. shost is
not attached automatically.
* ata_scsi_add_hosts() : allocates and adds shosts associated with an
ATA host. Used by ata_host_attach().
* ata_host_attach() : takes a fully initialized ata_host structure and
registers it to libata layer and probes it.
Only ata_host_alloc() and ata_host_attach() are exported.
ata_device_add() is rewritten using the above functions. This patch
does not introduce any observable behavior change. Things worth
mentioning.
* print_id is assigned at attach time and LLDs are allowed to
overallocate ports and reduce host->n_ports during initialization.
ata_host_attach() will throw away unused ports automatically.
* All SCSI host initialization stuff now resides in
ata_scsi_add_hosts() in libata-scsi.c, where it should be.
* ipr is now the only user of ata_host_init(). Either kill it by
converting ipr to use ata_host_alloc() and friends or rename and
move it to libata-scsi.c
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/libata-core.c | 469 +++++++++++++++++++++++++--------------------
drivers/ata/libata-scsi.c | 68 ++++++--
drivers/ata/libata.h | 8 +-
include/linux/libata.h | 3 +
4 files changed, 326 insertions(+), 222 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 6a4e7a4..b95618d 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -72,7 +72,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
static void ata_dev_xfermask(struct ata_device *dev);
-static unsigned int ata_print_id = 1;
+unsigned int ata_print_id = 1;
static struct workqueue_struct *ata_wq;
struct workqueue_struct *ata_aux_wq;
@@ -5520,42 +5520,35 @@ void ata_dev_init(struct ata_device *dev)
}
/**
- * ata_port_init - Initialize an ata_port structure
- * @ap: Structure to initialize
- * @host: Collection of hosts to which @ap belongs
- * @ent: Probe information provided by low-level driver
- * @port_no: Port number associated with this ata_port
+ * ata_port_alloc - allocate and initialize basic ATA port resources
+ * @host: ATA host this allocated port belongs to
*
- * Initialize a new ata_port structure.
+ * Allocate and initialize basic ATA port resources.
+ *
+ * RETURNS:
+ * Allocate ATA port on success, NULL on failure.
*
* LOCKING:
- * Inherited from caller.
+ * Inherited from calling layer (may sleep).
*/
-void ata_port_init(struct ata_port *ap, struct ata_host *host,
- const struct ata_probe_ent *ent, unsigned int port_no)
+struct ata_port *ata_port_alloc(struct ata_host *host)
{
+ struct ata_port *ap;
unsigned int i;
+ DPRINTK("ENTER\n");
+
+ ap = kzalloc(sizeof(*ap), GFP_KERNEL);
+ if (!ap)
+ return NULL;
+
ap->lock = &host->lock;
ap->flags = ATA_FLAG_DISABLED;
- ap->print_id = ata_print_id++;
+ ap->print_id = -1;
ap->ctl = ATA_DEVCTL_OBS;
ap->host = host;
- ap->dev = ent->dev;
- ap->port_no = port_no;
- if (port_no == 1 && ent->pinfo2) {
- ap->pio_mask = ent->pinfo2->pio_mask;
- ap->mwdma_mask = ent->pinfo2->mwdma_mask;
- ap->udma_mask = ent->pinfo2->udma_mask;
- ap->flags |= ent->pinfo2->flags;
- ap->ops = ent->pinfo2->port_ops;
- } else {
- ap->pio_mask = ent->pio_mask;
- ap->mwdma_mask = ent->mwdma_mask;
- ap->udma_mask = ent->udma_mask;
- ap->flags |= ent->port_flags;
- ap->ops = ent->port_ops;
- }
+ ap->dev = host->dev;
+
ap->hw_sata_spd_limit = UINT_MAX;
ap->active_tag = ATA_TAG_POISON;
ap->last_ctl = 0xFF;
@@ -5575,10 +5568,7 @@ void ata_port_init(struct ata_port *ap, struct ata_host *host,
INIT_LIST_HEAD(&ap->eh_done_q);
init_waitqueue_head(&ap->eh_wait_q);
- /* set cable type */
ap->cbl = ATA_CBL_NONE;
- if (ap->flags & ATA_FLAG_SATA)
- ap->cbl = ATA_CBL_SATA;
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
@@ -5591,75 +5581,6 @@ void ata_port_init(struct ata_port *ap, struct ata_host *host,
ap->stats.unhandled_irq = 1;
ap->stats.idle_irq = 1;
#endif
-
- memcpy(&ap->ioaddr, &ent->port[port_no], sizeof(struct ata_ioports));
-}
-
-/**
- * ata_port_init_shost - Initialize SCSI host associated with ATA port
- * @ap: ATA port to initialize SCSI host for
- * @shost: SCSI host associated with @ap
- *
- * Initialize SCSI host @shost associated with ATA port @ap.
- *
- * LOCKING:
- * Inherited from caller.
- */
-static void ata_port_init_shost(struct ata_port *ap, struct Scsi_Host *shost)
-{
- ap->scsi_host = shost;
-
- shost->unique_id = ap->print_id;
- shost->max_id = 16;
- shost->max_lun = 1;
- shost->max_channel = 1;
- shost->max_cmd_len = 16;
-}
-
-/**
- * ata_port_add - Attach low-level ATA driver to system
- * @ent: Information provided by low-level driver
- * @host: Collections of ports to which we add
- * @port_no: Port number associated with this host
- *
- * Attach low-level ATA driver to system.
- *
- * LOCKING:
- * PCI/etc. bus probe sem.
- *
- * RETURNS:
- * New ata_port on success, for NULL on error.
- */
-static struct ata_port * ata_port_add(const struct ata_probe_ent *ent,
- struct ata_host *host,
- unsigned int port_no)
-{
- struct Scsi_Host *shost;
- struct ata_port *ap;
-
- DPRINTK("ENTER\n");
-
- if (!ent->port_ops->error_handler &&
- !(ent->port_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) {
- printk(KERN_ERR "ata%u: no reset mechanism available\n",
- port_no);
- return NULL;
- }
-
- ap = kzalloc(sizeof(struct ata_port), GFP_KERNEL);
- if (!ap)
- return NULL;
-
- shost = scsi_host_alloc(ent->sht, sizeof(struct ata_port *));
- if (!shost)
- return NULL;
-
- *(struct ata_port **)&shost->hostdata[0] = ap;
- shost->transportt = &ata_scsi_transport_template;
-
- ata_port_init(ap, host, ent, port_no);
- ata_port_init_shost(ap, shost);
-
return ap;
}
@@ -5698,13 +5619,79 @@ static void ata_host_release(struct device *gendev, void *res)
}
/**
+ * ata_host_alloc - allocate and init basic ATA host resources
+ * @dev: generic device this host is associated with
+ * @max_ports: maximum number of ATA ports associated with this host
+ *
+ * Allocate and initialize basic ATA host resources. LLD calls
+ * this function to allocate a host, initializes it fully and
+ * attaches it using ata_host_attach().
+ *
+ * @max_ports ports are allocated and host->n_ports is
+ * initialized to @max_ports. The caller is allowed to decrease
+ * host->n_ports before calling ata_host_attach(). The unused
+ * ports will be automatically freed on attach.
+ *
+ * RETURNS:
+ * Allocate ATA host on success, NULL on failure.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ */
+struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
+{
+ struct ata_host *host;
+ size_t sz;
+ int i;
+
+ DPRINTK("ENTER\n");
+
+ if (!devres_open_group(dev, NULL, GFP_KERNEL))
+ return NULL;
+
+ /* alloc a container for our list of ATA ports (buses) */
+ sz = sizeof(struct ata_host) + (max_ports + 1) * sizeof(void *);
+ /* alloc a container for our list of ATA ports (buses) */
+ host = devres_alloc(ata_host_release, sz, GFP_KERNEL);
+ if (!host)
+ goto err_out;
+
+ devres_add(dev, host);
+ dev_set_drvdata(dev, host);
+
+ spin_lock_init(&host->lock);
+ host->dev = dev;
+ host->n_ports = max_ports;
+
+ /* allocate ports bound to this host */
+ for (i = 0; i < max_ports; i++) {
+ struct ata_port *ap;
+
+ ap = ata_port_alloc(host);
+ if (!ap)
+ goto err_out;
+
+ ap->port_no = i;
+ host->ports[i] = ap;
+ }
+
+ devres_remove_group(dev, NULL);
+ return host;
+
+ err_out:
+ devres_release_group(dev, NULL);
+ return NULL;
+}
+
+/**
* ata_host_start - start and freeze ports of an ATA host
* @host: ATA host to start ports for
*
* Start and then freeze ports of @host. Started status is
* recorded in host->flags, so this function can be called
* multiple times. Ports are guaranteed to get started only
- * once.
+ * once. If host->ops isn't initialized yet, its set to the
+ * first non-dummy port ops.
*
* LOCKING:
* Inherited from calling layer (may sleep).
@@ -5722,6 +5709,9 @@ int ata_host_start(struct ata_host *host)
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
+ if (!host->ops && !ata_port_is_dummy(ap))
+ host->ops = ap->ops;
+
if (ap->ops->port_start) {
rc = ap->ops->port_start(ap);
if (rc) {
@@ -5758,7 +5748,7 @@ int ata_host_start(struct ata_host *host)
* PCI/etc. bus probe sem.
*
*/
-
+/* KILLME - the only user left is ipr */
void ata_host_init(struct ata_host *host, struct device *dev,
unsigned long flags, const struct ata_port_operations *ops)
{
@@ -5769,6 +5759,143 @@ void ata_host_init(struct ata_host *host, struct device *dev,
}
/**
+ * ata_host_attach - attach initialized ATA host
+ * @host: ATA host to attach
+ * @sht: template for SCSI host
+ *
+ * Attach initialized ATA host. @host is allocated using
+ * ata_host_alloc() and fully initialized by LLD. This function
+ * starts ports, registers @host with ATA and SCSI layers and
+ * probe attached devices.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+int ata_host_attach(struct ata_host *host, struct scsi_host_template *sht)
+{
+ int i, rc;
+
+ /* host must have been started */
+ if (!(host->flags & ATA_HOST_STARTED)) {
+ dev_printk(KERN_ERR, host->dev,
+ "BUG: trying to attach unstarted host\n");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ /* Blow away unused ports. This happens when LLD can't
+ * determine the exact number of ports to allocate at
+ * allocation time.
+ */
+ for (i = host->n_ports; host->ports[i]; i++)
+ kfree(host->ports[i]);
+
+ /* give ports names and add SCSI hosts */
+ for (i = 0; i < host->n_ports; i++)
+ host->ports[i]->print_id = ata_print_id++;
+
+ rc = ata_scsi_add_hosts(host, sht);
+ if (rc)
+ return rc;
+
+ /* set cable, sata_spd_limit and report */
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+ int irq_line;
+ u32 scontrol;
+ unsigned long xfer_mask;
+
+ /* set SATA cable type if still unset */
+ if (ap->cbl == ATA_CBL_NONE && (ap->flags & ATA_FLAG_SATA))
+ ap->cbl = ATA_CBL_SATA;
+
+ /* init sata_spd_limit to the current value */
+ if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
+ int spd = (scontrol >> 4) & 0xf;
+ ap->hw_sata_spd_limit &= (1 << spd) - 1;
+ }
+ ap->sata_spd_limit = ap->hw_sata_spd_limit;
+
+ /* report the secondary IRQ for second channel legacy */
+ irq_line = host->irq;
+ if (i == 1 && host->irq2)
+ irq_line = host->irq2;
+
+ xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
+ ap->udma_mask);
+
+ /* print per-port info to dmesg */
+ if (!ata_port_is_dummy(ap))
+ ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%p "
+ "ctl 0x%p bmdma 0x%p irq %d\n",
+ ap->cbl == ATA_CBL_SATA ? 'S' : 'P',
+ ata_mode_string(xfer_mask),
+ ap->ioaddr.cmd_addr,
+ ap->ioaddr.ctl_addr,
+ ap->ioaddr.bmdma_addr,
+ irq_line);
+ else
+ ata_port_printk(ap, KERN_INFO, "DUMMY\n");
+ }
+
+ /* perform each probe synchronously */
+ DPRINTK("probe begin\n");
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+ int rc;
+
+ /* probe */
+ if (ap->ops->error_handler) {
+ struct ata_eh_info *ehi = &ap->eh_info;
+ unsigned long flags;
+
+ ata_port_probe(ap);
+
+ /* kick EH for boot probing */
+ spin_lock_irqsave(ap->lock, flags);
+
+ ehi->probe_mask = (1 << ATA_MAX_DEVICES) - 1;
+ ehi->action |= ATA_EH_SOFTRESET;
+ ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
+
+ ap->pflags |= ATA_PFLAG_LOADING;
+ ata_port_schedule_eh(ap);
+
+ spin_unlock_irqrestore(ap->lock, flags);
+
+ /* wait for EH to finish */
+ ata_port_wait_eh(ap);
+ } else {
+ DPRINTK("ata%u: bus probe begin\n", ap->print_id);
+ rc = ata_bus_probe(ap);
+ DPRINTK("ata%u: bus probe end\n", ap->print_id);
+
+ if (rc) {
+ /* FIXME: do something useful here?
+ * Current libata behavior will
+ * tear down everything when
+ * the module is removed
+ * or the h/w is unplugged.
+ */
+ }
+ }
+ }
+
+ /* probes are done, now scan each port's disk(s) */
+ DPRINTK("host probe begin\n");
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ ata_scsi_scan_host(ap);
+ }
+
+ return 0;
+}
+
+/**
* ata_device_add - Register hardware device with ATA and SCSI layers
* @ent: Probe information describing hardware device to be registered
*
@@ -5800,62 +5927,53 @@ int ata_device_add(const struct ata_probe_ent *ent)
return 0;
}
+ if (!ent->port_ops->error_handler &&
+ !(ent->port_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) {
+ dev_printk(KERN_ERR, dev, "no reset mechanism available\n");
+ return 0;
+ }
+
if (!devres_open_group(dev, ata_device_add, GFP_KERNEL))
return 0;
- /* alloc a container for our list of ATA ports (buses) */
- host = devres_alloc(ata_host_release, sizeof(struct ata_host) +
- (ent->n_ports * sizeof(void *)), GFP_KERNEL);
- if (!host)
- goto err_out;
- devres_add(dev, host);
- dev_set_drvdata(dev, host);
+ /* allocate host */
+ host = ata_host_alloc(dev, ent->n_ports);
- ata_host_init(host, dev, ent->_host_flags, ent->port_ops);
- host->n_ports = ent->n_ports;
host->irq = ent->irq;
host->irq2 = ent->irq2;
host->iomap = ent->iomap;
host->private_data = ent->private_data;
+ host->ops = ent->port_ops;
+ host->flags = ent->_host_flags;
- /* register each port bound to this device */
for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap;
- unsigned long xfer_mode_mask;
- int irq_line = ent->irq;
-
- ap = ata_port_add(ent, host, i);
- host->ports[i] = ap;
- if (!ap)
- goto err_out;
+ struct ata_port *ap = host->ports[i];
/* dummy? */
if (ent->dummy_port_mask & (1 << i)) {
- ata_port_printk(ap, KERN_INFO, "DUMMY\n");
ap->ops = &ata_dummy_port_ops;
continue;
}
- /* Report the secondary IRQ for second channel legacy */
- if (i == 1 && ent->irq2)
- irq_line = ent->irq2;
-
- xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
- (ap->mwdma_mask << ATA_SHIFT_MWDMA) |
- (ap->pio_mask << ATA_SHIFT_PIO);
+ if (ap->port_no == 1 && ent->pinfo2) {
+ ap->pio_mask = ent->pinfo2->pio_mask;
+ ap->mwdma_mask = ent->pinfo2->mwdma_mask;
+ ap->udma_mask = ent->pinfo2->udma_mask;
+ ap->flags |= ent->pinfo2->flags;
+ ap->ops = ent->pinfo2->port_ops;
+ } else {
+ ap->pio_mask = ent->pio_mask;
+ ap->mwdma_mask = ent->mwdma_mask;
+ ap->udma_mask = ent->udma_mask;
+ ap->flags |= ent->port_flags;
+ ap->ops = ent->port_ops;
+ }
- /* print per-port info to dmesg */
- ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%p "
- "ctl 0x%p bmdma 0x%p irq %d\n",
- ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
- ata_mode_string(xfer_mode_mask),
- ap->ioaddr.cmd_addr,
- ap->ioaddr.ctl_addr,
- ap->ioaddr.bmdma_addr,
- irq_line);
+ memcpy(&ap->ioaddr, &ent->port[ap->port_no],
+ sizeof(struct ata_ioports));
}
- /* start ports */
+ /* start and freeze ports before requesting IRQ */
rc = ata_host_start(host);
if (rc)
goto err_out;
@@ -5888,80 +6006,17 @@ int ata_device_add(const struct ata_probe_ent *ent)
/* resource acquisition complete */
devres_remove_group(dev, ata_device_add);
- /* perform each probe synchronously */
- DPRINTK("probe begin\n");
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
- u32 scontrol;
- int rc;
-
- /* init sata_spd_limit to the current value */
- if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
- int spd = (scontrol >> 4) & 0xf;
- ap->hw_sata_spd_limit &= (1 << spd) - 1;
- }
- ap->sata_spd_limit = ap->hw_sata_spd_limit;
-
- rc = scsi_add_host(ap->scsi_host, dev);
- if (rc) {
- ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n");
- /* FIXME: do something useful here */
- /* FIXME: handle unconditional calls to
- * scsi_scan_host and ata_host_remove, below,
- * at the very least
- */
- }
-
- if (ap->ops->error_handler) {
- struct ata_eh_info *ehi = &ap->eh_info;
- unsigned long flags;
-
- ata_port_probe(ap);
-
- /* kick EH for boot probing */
- spin_lock_irqsave(ap->lock, flags);
-
- ehi->probe_mask = (1 << ATA_MAX_DEVICES) - 1;
- ehi->action |= ATA_EH_SOFTRESET;
- ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
-
- ap->pflags |= ATA_PFLAG_LOADING;
- ata_port_schedule_eh(ap);
-
- spin_unlock_irqrestore(ap->lock, flags);
-
- /* wait for EH to finish */
- ata_port_wait_eh(ap);
- } else {
- DPRINTK("ata%u: bus probe begin\n", ap->print_id);
- rc = ata_bus_probe(ap);
- DPRINTK("ata%u: bus probe end\n", ap->print_id);
-
- if (rc) {
- /* FIXME: do something useful here?
- * Current libata behavior will
- * tear down everything when
- * the module is removed
- * or the h/w is unplugged.
- */
- }
- }
- }
-
- /* probes are done, now scan each port's disk(s) */
- DPRINTK("host probe begin\n");
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
-
- ata_scsi_scan_host(ap);
- }
+ /* attach */
+ rc = ata_host_attach(host, ent->sht);
+ if (rc)
+ goto err_out;
- VPRINTK("EXIT, returning %u\n", ent->n_ports);
- return ent->n_ports; /* success */
+ VPRINTK("EXIT, returning %u\n", host->n_ports);
+ return host->n_ports; /* success */
err_out:
devres_release_group(dev, ata_device_add);
- VPRINTK("EXIT, returning %d\n", rc);
+ VPRINTK("EXIT, returning 0\n");
return 0;
}
@@ -6414,7 +6469,9 @@ EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_std_ports);
EXPORT_SYMBOL_GPL(ata_host_init);
+EXPORT_SYMBOL_GPL(ata_host_alloc);
EXPORT_SYMBOL_GPL(ata_host_start);
+EXPORT_SYMBOL_GPL(ata_host_attach);
EXPORT_SYMBOL_GPL(ata_device_add);
EXPORT_SYMBOL_GPL(ata_host_detach);
EXPORT_SYMBOL_GPL(ata_sg_init);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 684528e..77e6124 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -104,7 +104,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
* libata transport template. libata doesn't do real transport stuff.
* It just needs the eh_timed_out hook.
*/
-struct scsi_transport_template ata_scsi_transport_template = {
+static struct scsi_transport_template ata_scsi_transport_template = {
.eh_strategy_handler = ata_scsi_error,
.eh_timed_out = ata_scsi_timed_out,
.user_scan = ata_scsi_user_scan,
@@ -2949,6 +2949,48 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
}
}
+int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
+{
+ int i, rc;
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+ struct Scsi_Host *shost;
+
+ rc = -ENOMEM;
+ shost = scsi_host_alloc(sht, sizeof(struct ata_port *));
+ if (!shost)
+ goto err_alloc;
+
+ *(struct ata_port **)&shost->hostdata[0] = ap;
+ ap->scsi_host = shost;
+
+ shost->transportt = &ata_scsi_transport_template;
+ shost->unique_id = ap->print_id;
+ shost->max_id = 16;
+ shost->max_lun = 1;
+ shost->max_channel = 1;
+ shost->max_cmd_len = 16;
+
+ rc = scsi_add_host(ap->scsi_host, ap->host->dev);
+ if (rc)
+ goto err_add;
+ }
+
+ return 0;
+
+ err_add:
+ scsi_host_put(host->ports[i]->scsi_host);
+ err_alloc:
+ while (--i >= 0) {
+ struct Scsi_Host *shost = host->ports[i]->scsi_host;
+
+ scsi_remove_host(shost);
+ scsi_host_put(shost);
+ }
+ return rc;
+}
+
void ata_scsi_scan_host(struct ata_port *ap)
{
unsigned int i;
@@ -3225,21 +3267,21 @@ struct ata_port *ata_sas_port_alloc(struct ata_host *host,
struct ata_port_info *port_info,
struct Scsi_Host *shost)
{
- struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL);
- struct ata_probe_ent *ent;
+ struct ata_port *ap;
+ ap = ata_port_alloc(host);
if (!ap)
return NULL;
- ent = ata_probe_ent_alloc(host->dev, port_info);
- if (!ent) {
- kfree(ap);
- return NULL;
- }
-
- ata_port_init(ap, host, ent, 0);
+ ap->port_no = 0;
ap->lock = shost->host_lock;
- devm_kfree(host->dev, ent);
+ ap->pio_mask = port_info->pio_mask;
+ ap->mwdma_mask = port_info->mwdma_mask;
+ ap->udma_mask = port_info->udma_mask;
+ ap->flags |= port_info->flags;
+ ap->ops = port_info->port_ops;
+ ap->cbl = ATA_CBL_SATA;
+
return ap;
}
EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
@@ -3295,8 +3337,10 @@ int ata_sas_port_init(struct ata_port *ap)
{
int rc = ap->ops->port_start(ap);
- if (!rc)
+ if (!rc) {
+ ap->print_id = ata_print_id++;
rc = ata_bus_probe(ap);
+ }
return rc;
}
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index c426714..38949a2 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -52,6 +52,7 @@ enum {
ATA_DNXFER_QUIET = (1 << 31),
};
+extern unsigned int ata_print_id;
extern struct workqueue_struct *ata_aux_wq;
extern int atapi_enabled;
extern int atapi_dmadir;
@@ -92,10 +93,9 @@ extern int ata_flush_cache(struct ata_device *dev);
extern void ata_dev_init(struct ata_device *dev);
extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
-extern void ata_port_init(struct ata_port *ap, struct ata_host *host,
- const struct ata_probe_ent *ent, unsigned int port_no);
extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev,
const struct ata_port_info *port);
+extern struct ata_port *ata_port_alloc(struct ata_host *host);
/* libata-acpi.c */
#ifdef CONFIG_SATA_ACPI
@@ -113,8 +113,8 @@ static inline int ata_acpi_push_id(struct ata_port *ap, unsigned int ix)
#endif
/* libata-scsi.c */
-extern struct scsi_transport_template ata_scsi_transport_template;
-
+extern int ata_scsi_add_hosts(struct ata_host *host,
+ struct scsi_host_template *sht);
extern void ata_scsi_scan_host(struct ata_port *ap);
extern int ata_scsi_offline_dev(struct ata_device *dev);
extern void ata_scsi_hotplug(struct work_struct *work);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 296c9ef..9edb7c7 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -728,7 +728,10 @@ extern int ata_pci_device_resume(struct pci_dev *pdev);
#endif
extern int ata_pci_clear_simplex(struct pci_dev *pdev);
#endif /* CONFIG_PCI */
+extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports);
extern int ata_host_start(struct ata_host *host);
+extern int ata_host_attach(struct ata_host *host,
+ struct scsi_host_template *sht);
extern int ata_device_add(const struct ata_probe_ent *ent);
extern void ata_host_detach(struct ata_host *host);
extern void ata_host_init(struct ata_host *, struct device *,
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH 03/12] libata: separate out ata_host_alloc() and ata_host_attach()
2007-03-09 11:15 ` [PATCH 03/12] libata: separate out ata_host_alloc() and ata_host_attach() Tejun Heo
@ 2007-03-09 15:34 ` Jeff Garzik
2007-03-12 22:25 ` Brian King
1 sibling, 0 replies; 27+ messages in thread
From: Jeff Garzik @ 2007-03-09 15:34 UTC (permalink / raw)
To: Tejun Heo; +Cc: alan, linux-ide
Tejun Heo wrote:
> Reorganize ata_host_alloc() and its subroutines into the following
> three functions.
>
> * ata_host_alloc() : allocates host and its attached ports. shost is
> not attached automatically.
>
> * ata_scsi_add_hosts() : allocates and adds shosts associated with an
> ATA host. Used by ata_host_attach().
>
> * ata_host_attach() : takes a fully initialized ata_host structure and
> registers it to libata layer and probes it.
I think it's more common in Linux to use foo_register than foo_attach.
attach is more a BSD-ism :)
ACK patches 2-3, modulo the naming comment
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 03/12] libata: separate out ata_host_alloc() and ata_host_attach()
2007-03-09 11:15 ` [PATCH 03/12] libata: separate out ata_host_alloc() and ata_host_attach() Tejun Heo
2007-03-09 15:34 ` Jeff Garzik
@ 2007-03-12 22:25 ` Brian King
2007-03-13 6:06 ` Tejun Heo
1 sibling, 1 reply; 27+ messages in thread
From: Brian King @ 2007-03-12 22:25 UTC (permalink / raw)
To: Tejun Heo; +Cc: jeff, alan, linux-ide
Tejun Heo wrote:
> * ipr is now the only user of ata_host_init(). Either kill it by
> converting ipr to use ata_host_alloc() and friends or rename and
> move it to libata-scsi.c
One of the problems with converting ipr to use ata_host_alloc and
friends is that it then forces ipr to tell libata how many "SATA ports"
are possible. On SAS, this number can't really be calculated, since
the maximum number of SATA devices which can possibly be cabled to a
SAS adapter, particularly with SAS expanders, is a very large number
and is not practical for how this is being used in the current
implementation. My guess is that aic94xx will have similar issues/concerns.
Brian
--
Brian King
eServer Storage I/O
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 03/12] libata: separate out ata_host_alloc() and ata_host_attach()
2007-03-12 22:25 ` Brian King
@ 2007-03-13 6:06 ` Tejun Heo
2007-03-13 22:34 ` Brian King
0 siblings, 1 reply; 27+ messages in thread
From: Tejun Heo @ 2007-03-13 6:06 UTC (permalink / raw)
To: brking; +Cc: jeff, alan, linux-ide
Hello, Brian.
Brian King wrote:
> Tejun Heo wrote:
>> * ipr is now the only user of ata_host_init(). Either kill it by
>> converting ipr to use ata_host_alloc() and friends or rename and
>> move it to libata-scsi.c
>
> One of the problems with converting ipr to use ata_host_alloc and
> friends is that it then forces ipr to tell libata how many "SATA ports"
> are possible. On SAS, this number can't really be calculated, since
> the maximum number of SATA devices which can possibly be cabled to a
> SAS adapter, particularly with SAS expanders, is a very large number
> and is not practical for how this is being used in the current
> implementation. My guess is that aic94xx will have similar issues/concerns.
I dunno much about SAS integration, so I intentionally left it alone, so
this patchset shouldn't change behavior from SAS's point of view.
Making host->ports dynamic isn't difficult at all. We can just separate
out the ports[] array and make it rcu and supply a few access helpers so
that we can adjust its size dynamically.
Association to SCSI host is done via pointer now even for native ATA
case, so this should be easier for SAS. What I'm worried about is how
EH gets invoked. libata depends on EH to do a lot of things including
probing, requesting sense data, etc. How should this work? SAS
attached libata port shares EH with the SAS SCSI host, right? How can
we connect SAS EH with libata EH and would it be okay for libata EH hold
the SCSI EH (thus holding all command execution on the host) to handle
ATA exceptions?
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 03/12] libata: separate out ata_host_alloc() and ata_host_attach()
2007-03-13 6:06 ` Tejun Heo
@ 2007-03-13 22:34 ` Brian King
2007-03-14 4:48 ` Tejun Heo
0 siblings, 1 reply; 27+ messages in thread
From: Brian King @ 2007-03-13 22:34 UTC (permalink / raw)
To: Tejun Heo; +Cc: jeff, alan, linux-ide
Tejun Heo wrote:
> Association to SCSI host is done via pointer now even for native ATA
> case, so this should be easier for SAS. What I'm worried about is how
> EH gets invoked. libata depends on EH to do a lot of things including
> probing, requesting sense data, etc. How should this work?
For SAS, the scsi_host pointer in the ata port is NULL today, since libata
is really not managing the scsi host, the LLDD is. I think the initialization
model we want for SAS is a little different than the one you are heading
towards on SATA. For SAS, I think we just want to be able to alloc/init
and delete/destroy a SATA device a they show up on the transport,
without tying it to initialization of the ata host. And this set of
patches doesn't necessarily prevent that...
> SAS attached libata port shares EH with the SAS SCSI host, right? How can
Right.
> we connect SAS EH with libata EH and would it be okay for libata EH hold
> the SCSI EH (thus holding all command execution on the host) to handle
> ATA exceptions?
Currently, ipr calls ata_do_eh from its eh_device_reset_handler function.
This seems to work well enough with the testing that I've done, but it
would certainly be nice to get to a more layered EH approach, where we
could possibly have pluggable error handlers for different device types.
Regarding holding all command execution on the host while performing eh,
that doesn't seem to be a huge issue from my perspective, not sure if
this would have a larger negative impact on others... Generally speaking,
we shouldn't be entering eh very often, and it should only be happening
if something went wrong. The biggest issue here might be ATAPI devices,
since they tend to report more errors during normal running. The request
sense for these devices for SAS is done without entering eh today. Would
you want to move this into eh as well?
Brian
--
Brian King
eServer Storage I/O
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 03/12] libata: separate out ata_host_alloc() and ata_host_attach()
2007-03-13 22:34 ` Brian King
@ 2007-03-14 4:48 ` Tejun Heo
2007-03-14 15:25 ` Brian King
0 siblings, 1 reply; 27+ messages in thread
From: Tejun Heo @ 2007-03-14 4:48 UTC (permalink / raw)
To: brking; +Cc: jeff, alan, linux-ide
Hello, Brian.
Brian King wrote:
> Tejun Heo wrote:
>> Association to SCSI host is done via pointer now even for native ATA
>> case, so this should be easier for SAS. What I'm worried about is how
>> EH gets invoked. libata depends on EH to do a lot of things including
>> probing, requesting sense data, etc. How should this work?
>
> For SAS, the scsi_host pointer in the ata port is NULL today, since libata
> is really not managing the scsi host, the LLDD is. I think the initialization
> model we want for SAS is a little different than the one you are heading
> towards on SATA. For SAS, I think we just want to be able to alloc/init
> and delete/destroy a SATA device a they show up on the transport,
> without tying it to initialization of the ata host. And this set of
> patches doesn't necessarily prevent that...
Yeap, I tried to keep SAS bridge functions working. If SAS doesn't need
the host abstraction and wanna do stuff per-port basis, ata_port_alloc()
can be directly exported and separating out per-port register routine
shouldn't be too difficult, but I do think it would still be beneficial
to have ata_host structure in SAS case too for code simplicity if not
for anything else.
>> SAS attached libata port shares EH with the SAS SCSI host, right? How can
>
> Right.
>
>> we connect SAS EH with libata EH and would it be okay for libata EH hold
>> the SCSI EH (thus holding all command execution on the host) to handle
>> ATA exceptions?
>
> Currently, ipr calls ata_do_eh from its eh_device_reset_handler function.
> This seems to work well enough with the testing that I've done, but it
> would certainly be nice to get to a more layered EH approach, where we
> could possibly have pluggable error handlers for different device types.
That's an unexpected usage of ata_do_eh() but I can see how that works
and using ata_do_eh() for that purpose actually makes sense. Most SCSI
related dancing is done before and after ata_do_eh() and ata_do_eh()
only deals with ATA qc's (except for scsi_eh_finish_cmd() called to
finish failed qc's but these are still for only scmds associated with qcs).
In the future, we might need to separate those direct
scsi_eh_finish_cmd() calls out of ata_do_eh() so that ata_do_eh() really
deals with libata qc proper but that change shouldn't be too difficult
for SAS.
> Regarding holding all command execution on the host while performing eh,
> that doesn't seem to be a huge issue from my perspective, not sure if
> this would have a larger negative impact on others... Generally speaking,
> we shouldn't be entering eh very often, and it should only be happening
> if something went wrong. The biggest issue here might be ATAPI devices,
> since they tend to report more errors during normal running. The request
> sense for these devices for SAS is done without entering eh today. Would
> you want to move this into eh as well?
No, not for SAS. The reasons why I put sense requesting to EH were...
1. to make fast path code straight forward (no qc reusing dance)
2. in native ATA, we have per-port EH thread so sharing is not a problem.
As #2 is not true in SAS case, I think keeping sense requesting out of
EH is the right thing to do here. I still think that it's much
simpler/reliable to handle any exception case in a separate thread. I
think this in the long term should be solved by making EH per-request
queue (we of course will need mechanism to synchronize several EHs so
that we can take host-wide EH actions).
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 03/12] libata: separate out ata_host_alloc() and ata_host_attach()
2007-03-14 4:48 ` Tejun Heo
@ 2007-03-14 15:25 ` Brian King
0 siblings, 0 replies; 27+ messages in thread
From: Brian King @ 2007-03-14 15:25 UTC (permalink / raw)
To: Tejun Heo; +Cc: jeff, alan, linux-ide
Tejun Heo wrote:
> Brian King wrote:
>> For SAS, the scsi_host pointer in the ata port is NULL today, since libata
>> is really not managing the scsi host, the LLDD is. I think the initialization
>> model we want for SAS is a little different than the one you are heading
>> towards on SATA. For SAS, I think we just want to be able to alloc/init
>> and delete/destroy a SATA device a they show up on the transport,
>> without tying it to initialization of the ata host. And this set of
>> patches doesn't necessarily prevent that...
>
> Yeap, I tried to keep SAS bridge functions working. If SAS doesn't need
> the host abstraction and wanna do stuff per-port basis, ata_port_alloc()
> can be directly exported and separating out per-port register routine
> shouldn't be too difficult, but I do think it would still be beneficial
> to have ata_host structure in SAS case too for code simplicity if not
> for anything else.
I think having the ata_host structure for SAS is fine. It's just a matter
of how much of what ends up in it actually gets used for SAS.
>> Regarding holding all command execution on the host while performing eh,
>> that doesn't seem to be a huge issue from my perspective, not sure if
>> this would have a larger negative impact on others... Generally speaking,
>> we shouldn't be entering eh very often, and it should only be happening
>> if something went wrong. The biggest issue here might be ATAPI devices,
>> since they tend to report more errors during normal running. The request
>> sense for these devices for SAS is done without entering eh today. Would
>> you want to move this into eh as well?
>
> No, not for SAS. The reasons why I put sense requesting to EH were...
>
> 1. to make fast path code straight forward (no qc reusing dance)
>
> 2. in native ATA, we have per-port EH thread so sharing is not a problem.
>
> As #2 is not true in SAS case, I think keeping sense requesting out of
> EH is the right thing to do here. I still think that it's much
> simpler/reliable to handle any exception case in a separate thread. I
> think this in the long term should be solved by making EH per-request
> queue (we of course will need mechanism to synchronize several EHs so
> that we can take host-wide EH actions).
Agreed.
Brian
--
Brian King
eServer Storage I/O
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 01/12] libata: allocate ap separately from shost
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
` (3 preceding siblings ...)
2007-03-09 11:15 ` [PATCH 03/12] libata: separate out ata_host_alloc() and ata_host_attach() Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
2007-03-09 15:00 ` Jeff Garzik
2007-03-09 11:15 ` [PATCH 09/12] libata: convert ata_pci_init_native_mode() users to new init model Tejun Heo
` (6 subsequent siblings)
11 siblings, 1 reply; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
Don't embed ap inside shost. Allocate it separately and point it back
from shosts's hostdata. This makes port allocation more flexible and
allows regular ATA and SAS share host alloc/init paths.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/libata-core.c | 15 +++++++++++----
include/linux/libata.h | 2 +-
2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 6e124bd..fab488c 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5646,14 +5646,17 @@ static struct ata_port * ata_port_add(const struct ata_probe_ent *ent,
return NULL;
}
- shost = scsi_host_alloc(ent->sht, sizeof(struct ata_port));
+ ap = kzalloc(sizeof(struct ata_port), GFP_KERNEL);
+ if (!ap)
+ return NULL;
+
+ shost = scsi_host_alloc(ent->sht, sizeof(struct ata_port *));
if (!shost)
return NULL;
+ *(struct ata_port **)&shost->hostdata[0] = ap;
shost->transportt = &ata_scsi_transport_template;
- ap = ata_shost_to_port(shost);
-
ata_port_init(ap, host, ent, port_no);
ata_port_init_shost(ap, shost);
@@ -5678,9 +5681,13 @@ static void ata_host_release(struct device *gendev, void *res)
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
- if (ap)
+ if (!ap)
+ continue;
+
+ if (ap->scsi_host)
scsi_host_put(ap->scsi_host);
+ kfree(ap);
host->ports[i] = NULL;
}
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 911ac4e..cfdc617 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -1221,7 +1221,7 @@ static inline void ata_pad_free(struct ata_port *ap, struct device *dev)
static inline struct ata_port *ata_shost_to_port(struct Scsi_Host *host)
{
- return (struct ata_port *) &host->hostdata[0];
+ return *(struct ata_port **)&host->hostdata[0];
}
#endif /* __LINUX_LIBATA_H__ */
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH 01/12] libata: allocate ap separately from shost
2007-03-09 11:15 ` [PATCH 01/12] libata: allocate ap separately from shost Tejun Heo
@ 2007-03-09 15:00 ` Jeff Garzik
0 siblings, 0 replies; 27+ messages in thread
From: Jeff Garzik @ 2007-03-09 15:00 UTC (permalink / raw)
To: Tejun Heo; +Cc: alan, linux-ide
Tejun Heo wrote:
> Don't embed ap inside shost. Allocate it separately and point it back
> from shosts's hostdata. This makes port allocation more flexible and
> allows regular ATA and SAS share host alloc/init paths.
>
> Signed-off-by: Tejun Heo <htejun@gmail.com>
> ---
> drivers/ata/libata-core.c | 15 +++++++++++----
> include/linux/libata.h | 2 +-
> 2 files changed, 12 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
> index 6e124bd..fab488c 100644
> --- a/drivers/ata/libata-core.c
> +++ b/drivers/ata/libata-core.c
> @@ -5646,14 +5646,17 @@ static struct ata_port * ata_port_add(const struct ata_probe_ent *ent,
> return NULL;
> }
>
> - shost = scsi_host_alloc(ent->sht, sizeof(struct ata_port));
> + ap = kzalloc(sizeof(struct ata_port), GFP_KERNEL);
> + if (!ap)
> + return NULL;
> +
> + shost = scsi_host_alloc(ent->sht, sizeof(struct ata_port *));
> if (!shost)
> return NULL;
memory leak on error
otherwise OK
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 09/12] libata: convert ata_pci_init_native_mode() users to new init model
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
` (4 preceding siblings ...)
2007-03-09 11:15 ` [PATCH 01/12] libata: allocate ap separately from shost Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
2007-03-09 11:15 ` [PATCH 11/12] libata: convert the remaining PATA drivers " Tejun Heo
` (5 subsequent siblings)
11 siblings, 0 replies; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
Convert drivers which use ata_pci_init_native_mode() to new init
model. ata_pci_init_native_host() is used instead. sata_nv, sata_uli
and sata_sis are in this category.
Tested on nVidia Corporation CK804 Serial ATA Controller [10de:0054]
in both BMDMA and ADMA mode.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/sata_nv.c | 86 +++++++++++++++++++++--------------------------
drivers/ata/sata_sis.c | 49 +++++++++------------------
drivers/ata/sata_uli.c | 62 +++++++++++++---------------------
3 files changed, 79 insertions(+), 118 deletions(-)
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index eb0f877..37cbea5 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -368,7 +368,6 @@ static const struct ata_port_operations nv_generic_ops = {
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.data_xfer = ata_data_xfer,
- .irq_handler = nv_generic_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -395,7 +394,6 @@ static const struct ata_port_operations nv_nf2_ops = {
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.data_xfer = ata_data_xfer,
- .irq_handler = nv_nf2_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -422,7 +420,6 @@ static const struct ata_port_operations nv_ck804_ops = {
.error_handler = nv_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.data_xfer = ata_data_xfer,
- .irq_handler = nv_ck804_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -451,7 +448,6 @@ static const struct ata_port_operations nv_adma_ops = {
.error_handler = nv_adma_error_handler,
.post_internal_cmd = nv_adma_post_internal_cmd,
.data_xfer = ata_data_xfer,
- .irq_handler = nv_adma_interrupt,
.irq_clear = nv_adma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -476,6 +472,7 @@ static struct ata_port_info nv_port_info[] = {
.mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK,
.port_ops = &nv_generic_ops,
+ .irq_handler = nv_generic_interrupt,
},
/* nforce2/3 */
{
@@ -486,6 +483,7 @@ static struct ata_port_info nv_port_info[] = {
.mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK,
.port_ops = &nv_nf2_ops,
+ .irq_handler = nv_nf2_interrupt,
},
/* ck804 */
{
@@ -496,6 +494,7 @@ static struct ata_port_info nv_port_info[] = {
.mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK,
.port_ops = &nv_ck804_ops,
+ .irq_handler = nv_ck804_interrupt,
},
/* ADMA */
{
@@ -507,6 +506,7 @@ static struct ata_port_info nv_port_info[] = {
.mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK,
.port_ops = &nv_adma_ops,
+ .irq_handler = nv_adma_interrupt,
},
};
@@ -1068,14 +1068,14 @@ static int nv_adma_port_resume(struct ata_port *ap)
}
#endif
-static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int port)
+static void nv_adma_setup_port(struct ata_port *ap)
{
- void __iomem *mmio = probe_ent->iomap[NV_MMIO_BAR];
- struct ata_ioports *ioport = &probe_ent->port[port];
+ void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR];
+ struct ata_ioports *ioport = &ap->ioaddr;
VPRINTK("ENTER\n");
- mmio += NV_ADMA_PORT + port * NV_ADMA_PORT_SIZE;
+ mmio += NV_ADMA_PORT + ap->port_no * NV_ADMA_PORT_SIZE;
ioport->cmd_addr = mmio;
ioport->data_addr = mmio + (ATA_REG_DATA * 4);
@@ -1092,9 +1092,9 @@ static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int por
ioport->ctl_addr = mmio + 0x20;
}
-static int nv_adma_host_init(struct ata_probe_ent *probe_ent)
+static int nv_adma_host_init(struct ata_host *host)
{
- struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+ struct pci_dev *pdev = to_pci_dev(host->dev);
unsigned int i;
u32 tmp32;
@@ -1109,8 +1109,8 @@ static int nv_adma_host_init(struct ata_probe_ent *probe_ent)
pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
- for (i = 0; i < probe_ent->n_ports; i++)
- nv_adma_setup_port(probe_ent, i);
+ for (i = 0; i < host->n_ports; i++)
+ nv_adma_setup_port(host->ports[i]);
return 0;
}
@@ -1467,14 +1467,13 @@ static void nv_adma_error_handler(struct ata_port *ap)
static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version = 0;
- struct ata_port_info *ppi[2];
- struct ata_probe_ent *probe_ent;
+ const struct ata_port_info *ppi[2];
+ struct ata_host *host;
struct nv_host_priv *hpriv;
int rc;
u32 bar;
void __iomem *base;
unsigned long type = ent->driver_data;
- u64 dma_mask = ATA_DMA_MASK;
// Make sure this is a SATA controller by counting the number of bars
// (NVIDIA SATA controllers will always have six bars). Otherwise,
@@ -1490,43 +1489,38 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
return rc;
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc) {
- pcim_pin_device(pdev);
- return rc;
- }
-
- if(type >= CK804 && adma_enabled) {
+ /* determine type and allocate host */
+ if (type >= CK804 && adma_enabled) {
dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");
type = ADMA;
- dma_mask = DMA_64BIT_MASK;
}
- rc = pci_configure_dma_masks(pdev, dma_mask, NULL);
+ ppi[0] = ppi[1] = &nv_port_info[type];
+ rc = ata_pci_prepare_native_host(pdev, ppi, 2, &host);
if (rc)
return rc;
- rc = -ENOMEM;
-
hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
if (!hpriv)
return -ENOMEM;
+ hpriv->type = type;
+ host->private_data = hpriv;
- ppi[0] = ppi[1] = &nv_port_info[type];
- probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
- if (!probe_ent)
- return -ENOMEM;
-
- if (!pcim_iomap(pdev, NV_MMIO_BAR, 0))
- return -EIO;
- probe_ent->iomap = pcim_iomap_table(pdev);
+ if (type == ADMA) {
+ rc = pci_configure_dma_masks(pdev, DMA_64BIT_MASK, NULL);
+ if (rc)
+ return rc;
+ }
- probe_ent->private_data = hpriv;
- hpriv->type = type;
+ /* request and iomap NV_MMIO_BAR */
+ rc = pcim_iomap_regions(pdev, 1 << NV_MMIO_BAR, DRV_NAME);
+ if (rc)
+ return rc;
- base = probe_ent->iomap[NV_MMIO_BAR];
- probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
- probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
+ /* configure SCR access */
+ base = host->iomap[NV_MMIO_BAR];
+ host->ports[0]->ioaddr.scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
+ host->ports[1]->ioaddr.scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
/* enable SATA space for CK804 */
if (type >= CK804) {
@@ -1537,20 +1531,16 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
}
- pci_set_master(pdev);
-
+ /* init ADMA */
if (type == ADMA) {
- rc = nv_adma_host_init(probe_ent);
+ rc = nv_adma_host_init(host);
if (rc)
return rc;
}
- rc = ata_device_add(probe_ent);
- if (rc != NV_PORTS)
- return -ENODEV;
-
- devm_kfree(&pdev->dev, probe_ent);
- return 0;
+ pci_set_master(pdev);
+ return ata_host_activate(host, pdev->irq, ppi[0]->irq_handler,
+ IRQF_SHARED, ppi[0]->sht);
}
static void nv_remove_one (struct pci_dev *pdev)
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 75c5683..d8ee062 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -121,7 +121,6 @@ static const struct ata_port_operations sis_ops = {
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -131,7 +130,6 @@ static const struct ata_port_operations sis_ops = {
};
static struct ata_port_info sis_port_info = {
- .sht = &sis_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x7,
@@ -256,12 +254,13 @@ static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
- struct ata_probe_ent *probe_ent = NULL;
- int rc;
+ struct ata_port_info pi = sis_port_info;
+ const struct ata_port_info *ppi[2] = { &pi, &pi };
+ struct ata_host *host;
u32 genctl, val;
- struct ata_port_info pi = sis_port_info, *ppi[2] = { &pi, &pi };
u8 pmr;
u8 port2_start = 0x20;
+ int rc;
if (!printed_version++)
dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
@@ -270,16 +269,6 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
return rc;
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc) {
- pcim_pin_device(pdev);
- return rc;
- }
-
- rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
- if (rc)
- return rc;
-
/* check and see if the SCRs are in IO space or PCI cfg space */
pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
@@ -346,30 +335,26 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
- probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
- if (!probe_ent)
- return -ENOMEM;
+ rc = ata_pci_prepare_native_host(pdev, ppi, 2, &host);
+ if (rc)
+ return rc;
- if (!(probe_ent->port_flags & SIS_FLAG_CFGSCR)) {
- void *mmio;
+ if (!(pi.flags & SIS_FLAG_CFGSCR)) {
+ void __iomem *mmio;
- mmio = pcim_iomap(pdev, SIS_SCR_PCI_BAR, 0);
- if (!mmio)
- return -ENOMEM;
+ rc = pcim_iomap_regions(pdev, 1 << SIS_SCR_PCI_BAR, DRV_NAME);
+ if (rc)
+ return rc;
+ mmio = host->iomap[SIS_SCR_PCI_BAR];
- probe_ent->port[0].scr_addr = mmio;
- probe_ent->port[1].scr_addr = mmio + port2_start;
+ host->ports[0]->ioaddr.scr_addr = mmio;
+ host->ports[1]->ioaddr.scr_addr = mmio + port2_start;
}
pci_set_master(pdev);
pci_intx(pdev, 1);
-
- if (!ata_device_add(probe_ent))
- return -EIO;
-
- devm_kfree(&pdev->dev, probe_ent);
- return 0;
-
+ return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+ &sis_sht);
}
static int __init sis_init(void)
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index bfdb73e..f74e383 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -115,7 +115,6 @@ static const struct ata_port_operations uli_ops = {
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -127,7 +126,6 @@ static const struct ata_port_operations uli_ops = {
};
static struct ata_port_info uli_port_info = {
- .sht = &uli_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_IGN_SIMPLEX,
.pio_mask = 0x1f, /* pio0-4 */
@@ -185,12 +183,13 @@ static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
- struct ata_probe_ent *probe_ent;
- struct ata_port_info *ppi[2];
- int rc;
+ const struct ata_port_info *ppi[] = { &uli_port_info, NULL };
unsigned int board_idx = (unsigned int) ent->driver_data;
+ struct ata_host *host;
struct uli_priv *hpriv;
void __iomem * const *iomap;
+ struct ata_ioports *ioaddr;
+ int n_ports, rc;
if (!printed_version++)
dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
@@ -199,51 +198,42 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
return rc;
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc) {
- pcim_pin_device(pdev);
- return rc;
- }
-
- rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
+ n_ports = 2;
+ if (board_idx == uli_5287)
+ n_ports = 4;
+ rc = ata_pci_prepare_native_host(pdev, ppi, n_ports, &host);
if (rc)
return rc;
- ppi[0] = ppi[1] = &uli_port_info;
- probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
- if (!probe_ent)
- return -ENOMEM;
-
hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
if (!hpriv)
return -ENOMEM;
+ host->private_data = hpriv;
- probe_ent->private_data = hpriv;
-
- iomap = pcim_iomap_table(pdev);
+ iomap = host->iomap;
switch (board_idx) {
case uli_5287:
hpriv->scr_cfg_addr[0] = ULI5287_BASE;
hpriv->scr_cfg_addr[1] = ULI5287_BASE + ULI5287_OFFS;
- probe_ent->n_ports = 4;
- probe_ent->port[2].cmd_addr = iomap[0] + 8;
- probe_ent->port[2].altstatus_addr =
- probe_ent->port[2].ctl_addr = (void __iomem *)
+ ioaddr = &host->ports[2]->ioaddr;
+ ioaddr->cmd_addr = iomap[0] + 8;
+ ioaddr->altstatus_addr =
+ ioaddr->ctl_addr = (void __iomem *)
((unsigned long)iomap[1] | ATA_PCI_CTL_OFS) + 4;
- probe_ent->port[2].bmdma_addr = iomap[4] + 16;
+ ioaddr->bmdma_addr = iomap[4] + 16;
hpriv->scr_cfg_addr[2] = ULI5287_BASE + ULI5287_OFFS*4;
+ ata_std_ports(ioaddr);
- probe_ent->port[3].cmd_addr = iomap[2] + 8;
- probe_ent->port[3].altstatus_addr =
- probe_ent->port[3].ctl_addr = (void __iomem *)
+ ioaddr = &host->ports[3]->ioaddr;
+ ioaddr->cmd_addr = iomap[2] + 8;
+ ioaddr->altstatus_addr =
+ ioaddr->ctl_addr = (void __iomem *)
((unsigned long)iomap[3] | ATA_PCI_CTL_OFS) + 4;
- probe_ent->port[3].bmdma_addr = iomap[4] + 24;
+ ioaddr->bmdma_addr = iomap[4] + 24;
hpriv->scr_cfg_addr[3] = ULI5287_BASE + ULI5287_OFFS*5;
-
- ata_std_ports(&probe_ent->port[2]);
- ata_std_ports(&probe_ent->port[3]);
+ ata_std_ports(ioaddr);
break;
case uli_5289:
@@ -263,12 +253,8 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_master(pdev);
pci_intx(pdev, 1);
-
- if (!ata_device_add(probe_ent))
- return -ENODEV;
-
- devm_kfree(&pdev->dev, probe_ent);
- return 0;
+ return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+ &uli_sht);
}
static int __init uli_init(void)
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 11/12] libata: convert the remaining PATA drivers to new init model
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
` (5 preceding siblings ...)
2007-03-09 11:15 ` [PATCH 09/12] libata: convert ata_pci_init_native_mode() users to new init model Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
2007-03-09 12:49 ` Alan Cox
2007-03-09 11:15 ` [PATCH 12/12] libata: kill probe_ent and related helpers Tejun Heo
` (4 subsequent siblings)
11 siblings, 1 reply; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
Convert pdc_adma, pata_cs5520, pata_isapnp, pata_ixp4xx_cf,
pata_legacy, pata_mpc52xx, pata_mpiix, pata_pcmcia, pata_pdc2027x,
pata_platform, pata_qdi, pata_scc and pata_winbond to new init model.
* init_one()'s now follow more consistent init order
* cs5520 now registers one host with two ports, not two hosts. If any
of the two ports are disabled, it's made dummy as other drivers do.
Tested pdc_adma and pata_legacy. Both are as broken as before. The
rest are compile tested only.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/pata_cs5520.c | 127 +++++++++++++++++++++++-------------------
drivers/ata/pata_isapnp.c | 43 ++++++++-------
drivers/ata/pata_ixp4xx_cf.c | 39 ++++++-------
drivers/ata/pata_legacy.c | 38 ++++++------
drivers/ata/pata_mpc52xx.c | 46 +++++++--------
drivers/ata/pata_mpiix.c | 36 ++++++------
drivers/ata/pata_pcmcia.c | 40 +++++++-------
drivers/ata/pata_pdc2027x.c | 98 +++++++++++++--------------------
drivers/ata/pata_platform.c | 43 +++++++--------
drivers/ata/pata_qdi.c | 45 +++++++--------
drivers/ata/pata_scc.c | 51 +++++------------
drivers/ata/pata_winbond.c | 97 +++++++++++++++-----------------
drivers/ata/pdc_adma.c | 85 +++++++++++-----------------
13 files changed, 360 insertions(+), 428 deletions(-)
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 6bddae5..0546748 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -197,7 +197,6 @@ static struct ata_port_operations cs5520_port_ops = {
.qc_issue = ata_qc_issue_prot,
.data_xfer = ata_data_xfer,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -205,87 +204,99 @@ static struct ata_port_operations cs5520_port_ops = {
.port_start = ata_port_start,
};
-static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ struct ata_port_info pi = {
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .port_ops = &cs5520_port_ops,
+ };
+ const struct ata_port_info *ppi[2];
u8 pcicfg;
void *iomap[5];
- static struct ata_probe_ent probe[2];
- int ports = 0, rc;
+ struct ata_host *host;
+ struct ata_ioports *ioaddr;
+ int i, rc;
/* IDE port enable bits */
- pci_read_config_byte(dev, 0x60, &pcicfg);
+ pci_read_config_byte(pdev, 0x60, &pcicfg);
/* Check if the ATA ports are enabled */
- if ((pcicfg & 3) == 0)
+ if (!(pcicfg & 3))
return -ENODEV;
+ ppi[0] = ppi[1] = &ata_dummy_port_info;
+ if (pcicfg & 1)
+ ppi[0] = π
+ if (pcicfg & 2)
+ ppi[1] = π
+
if ((pcicfg & 0x40) == 0) {
- printk(KERN_WARNING DRV_NAME ": DMA mode disabled. Enabling.\n");
- pci_write_config_byte(dev, 0x60, pcicfg | 0x40);
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "DMA mode disabled. Enabling.\n");
+ pci_write_config_byte(pdev, 0x60, pcicfg | 0x40);
}
+ pi.mwdma_mask = id->driver_data;
+
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
+ if (!host)
+ return -ENOMEM;
+
/* Perform set up for DMA */
- if (pci_enable_device_bars(dev, 1<<2)) {
+ if (pci_enable_device_bars(pdev, 1<<2)) {
printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n");
return -ENODEV;
}
- pci_set_master(dev);
- rc = pci_configure_dma_masks(dev, DMA_32BIT_MASK, NULL);
+ rc = pci_configure_dma_masks(pdev, DMA_32BIT_MASK, NULL);
if (rc)
return rc;
- /* Map IO ports */
- iomap[0] = devm_ioport_map(&dev->dev, 0x1F0, 8);
- iomap[1] = devm_ioport_map(&dev->dev, 0x3F6, 1);
- iomap[2] = devm_ioport_map(&dev->dev, 0x170, 8);
- iomap[3] = devm_ioport_map(&dev->dev, 0x376, 1);
- iomap[4] = pcim_iomap(dev, 2, 0);
+ /* Map IO ports and initialize host accordingly */
+ iomap[0] = devm_ioport_map(&pdev->dev, 0x1F0, 8);
+ iomap[1] = devm_ioport_map(&pdev->dev, 0x3F6, 1);
+ iomap[2] = devm_ioport_map(&pdev->dev, 0x170, 8);
+ iomap[3] = devm_ioport_map(&pdev->dev, 0x376, 1);
+ iomap[4] = pcim_iomap(pdev, 2, 0);
if (!iomap[0] || !iomap[1] || !iomap[2] || !iomap[3] || !iomap[4])
return -ENOMEM;
- /* We have to do our own plumbing as the PCI setup for this
- chipset is non-standard so we can't punt to the libata code */
-
- INIT_LIST_HEAD(&probe[0].node);
- probe[0].dev = pci_dev_to_dev(dev);
- probe[0].port_ops = &cs5520_port_ops;
- probe[0].sht = &cs5520_sht;
- probe[0].pio_mask = 0x1F;
- probe[0].mwdma_mask = id->driver_data;
- probe[0].irq = 14;
- probe[0].irq_flags = 0;
- probe[0].port_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST;
- probe[0].n_ports = 1;
- probe[0].port[0].cmd_addr = iomap[0];
- probe[0].port[0].ctl_addr = iomap[1];
- probe[0].port[0].altstatus_addr = iomap[1];
- probe[0].port[0].bmdma_addr = iomap[4];
-
- /* The secondary lurks at different addresses but is otherwise
- the same beastie */
-
- probe[1] = probe[0];
- INIT_LIST_HEAD(&probe[1].node);
- probe[1].irq = 15;
- probe[1].port[0].cmd_addr = iomap[2];
- probe[1].port[0].ctl_addr = iomap[3];
- probe[1].port[0].altstatus_addr = iomap[3];
- probe[1].port[0].bmdma_addr = iomap[4] + 8;
-
- /* Let libata fill in the port details */
- ata_std_ports(&probe[0].port[0]);
- ata_std_ports(&probe[1].port[0]);
-
- /* Now add the ports that are active */
- if (pcicfg & 1)
- ports += ata_device_add(&probe[0]);
- if (pcicfg & 2)
- ports += ata_device_add(&probe[1]);
- if (ports)
- return 0;
- return -ENODEV;
+ ioaddr = &host->ports[0]->ioaddr;
+ ioaddr->cmd_addr = iomap[0];
+ ioaddr->ctl_addr = iomap[1];
+ ioaddr->altstatus_addr = iomap[1];
+ ioaddr->bmdma_addr = iomap[4];
+ ata_std_ports(ioaddr);
+
+ ioaddr = &host->ports[1]->ioaddr;
+ ioaddr->cmd_addr = iomap[2];
+ ioaddr->ctl_addr = iomap[3];
+ ioaddr->altstatus_addr = iomap[3];
+ ioaddr->bmdma_addr = iomap[4] + 8;
+ ata_std_ports(ioaddr);
+
+ /* activate the host */
+ pci_set_master(pdev);
+ rc = ata_host_start(host);
+ if (rc)
+ return rc;
+
+ for (i = 0; i < 2; i++) {
+ static const int irq[] = { 14, 15 };
+ struct ata_port *ap = host->ports[0];
+
+ if (ata_port_is_dummy(ap))
+ continue;
+
+ rc = devm_request_irq(&pdev->dev, irq[ap->port_no],
+ ata_interrupt, 0, DRV_NAME, host);
+ if (rc)
+ return rc;
+ }
+
+ return ata_host_attach(host, &cs5520_sht);
}
/**
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 1a61cc8..46e0d70 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -55,7 +55,6 @@ static struct ata_port_operations isapnp_port_ops = {
.data_xfer = ata_data_xfer,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -74,8 +73,10 @@ static struct ata_port_operations isapnp_port_ops = {
static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev_id)
{
- struct ata_probe_ent ae;
+ struct ata_host *host;
+ struct ata_port *ap;
void __iomem *cmd_addr, *ctl_addr;
+ int rc;
if (pnp_port_valid(idev, 0) == 0)
return -ENODEV;
@@ -84,34 +85,36 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
if (pnp_irq_valid(idev, 0) == 0)
return -ENODEV;
+ /* allocate host */
+ host = ata_host_alloc(&idev->dev, 1);
+ if (!host)
+ return -ENOMEM;
+
+ /* acquire resources and fill host */
cmd_addr = devm_ioport_map(&idev->dev, pnp_port_start(idev, 0), 8);
if (!cmd_addr)
return -ENOMEM;
- memset(&ae, 0, sizeof(struct ata_probe_ent));
- INIT_LIST_HEAD(&ae.node);
- ae.dev = &idev->dev;
- ae.port_ops = &isapnp_port_ops;
- ae.sht = &isapnp_sht;
- ae.n_ports = 1;
- ae.pio_mask = 1; /* ISA so PIO 0 cycles */
- ae.irq = pnp_irq(idev, 0);
- ae.irq_flags = 0;
- ae.port_flags = ATA_FLAG_SLAVE_POSS;
- ae.port[0].cmd_addr = cmd_addr;
+ ap = host->ports[0];
+
+ ap->ops = &isapnp_port_ops;
+ ap->pio_mask = 1;
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
+
+ ap->ioaddr.cmd_addr = cmd_addr;
if (pnp_port_valid(idev, 1) == 0) {
ctl_addr = devm_ioport_map(&idev->dev,
pnp_port_start(idev, 1), 1);
- ae.port[0].altstatus_addr = ctl_addr;
- ae.port[0].ctl_addr = ctl_addr;
- ae.port_flags |= ATA_FLAG_SRST;
+ ap->ioaddr.altstatus_addr = ctl_addr;
+ ap->ioaddr.ctl_addr = ctl_addr;
}
- ata_std_ports(&ae.port[0]);
- if (ata_device_add(&ae) == 0)
- return -ENODEV;
- return 0;
+ ata_std_ports(&ap->ioaddr);
+
+ /* activate */
+ return ata_host_activate(host, pnp_irq(idev, 0), ata_interrupt, 0,
+ &isapnp_sht);
}
/**
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index 9a0523b..1afcdf4 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -130,7 +130,6 @@ static struct ata_port_operations ixp4xx_port_ops = {
.eng_timeout = ata_eng_timeout,
.data_xfer = ixp4xx_mmio_data_xfer,
- .irq_handler = ata_interrupt,
.irq_clear = ixp4xx_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -173,12 +172,12 @@ static void ixp4xx_setup_port(struct ata_ioports *ioaddr,
static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
{
- int ret;
unsigned int irq;
struct resource *cs0, *cs1;
- struct ata_probe_ent ae;
-
+ struct ata_host *host;
+ struct ata_port *ap;
struct ixp4xx_pata_data *data = pdev->dev.platform_data;
+ int rc;
cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -186,6 +185,12 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
if (!cs0 || !cs1)
return -EINVAL;
+ /* allocate host */
+ host = ata_host_alloc(&pdev->dev, 1);
+ if (!host)
+ return -ENOMEM;
+
+ /* acquire resources and fill host */
pdev->dev.coherent_dma_mask = DMA_32BIT_MASK;
data->cs0 = devm_ioremap(&pdev->dev, cs0->start, 0x1000);
@@ -199,32 +204,22 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
*data->cs0_cfg = data->cs0_bits;
*data->cs1_cfg = data->cs1_bits;
- memset(&ae, 0, sizeof(struct ata_probe_ent));
- INIT_LIST_HEAD(&ae.node);
+ ap = host->ports[0];
- ae.dev = &pdev->dev;
- ae.port_ops = &ixp4xx_port_ops;
- ae.sht = &ixp4xx_sht;
- ae.n_ports = 1;
- ae.pio_mask = 0x1f; /* PIO4 */
- ae.irq = irq;
- ae.irq_flags = 0;
- ae.port_flags = ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY
- | ATA_FLAG_NO_ATAPI | ATA_FLAG_SRST;
+ ap->ops = &ixp4xx_port_ops;
+ ap->pio_mask = 0x1f; /* PIO4 */
+ ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI;
/* run in polling mode if no irq has been assigned */
if (!irq)
- ae.port_flags |= ATA_FLAG_PIO_POLLING;
+ ap->flags |= ATA_FLAG_PIO_POLLING;
- ixp4xx_setup_port(&ae.port[0], data);
+ ixp4xx_setup_port(&ap->ioaddr, data);
dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
- ret = ata_device_add(&ae);
- if (ret == 0)
- return -ENODEV;
-
- return 0;
+ /* activate host */
+ return ata_host_activate(host, irq, ata_interrupt, 0, &ixp4xx_sht);
}
static __devexit int ixp4xx_pata_remove(struct platform_device *dev)
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index fc5b73d..1fef86a 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -709,7 +709,8 @@ static struct ata_port_operations opti82c46x_port_ops = {
static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl, int irq)
{
struct legacy_data *ld = &legacy_data[nr_legacy_host];
- struct ata_probe_ent ae;
+ struct ata_host *host;
+ struct ata_port *ap;
struct platform_device *pdev;
struct ata_port_operations *ops = &legacy_port_ops;
void __iomem *io_addr, *ctrl_addr;
@@ -791,24 +792,23 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
if (ops == &legacy_port_ops && (autospeed & mask))
ops = &simple_port_ops;
- memset(&ae, 0, sizeof(struct ata_probe_ent));
- INIT_LIST_HEAD(&ae.node);
- ae.dev = &pdev->dev;
- ae.port_ops = ops;
- ae.sht = &legacy_sht;
- ae.n_ports = 1;
- ae.pio_mask = pio_modes;
- ae.irq = irq;
- ae.irq_flags = 0;
- ae.port_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST|iordy;
- ae.port[0].cmd_addr = io_addr;
- ae.port[0].altstatus_addr = ctrl_addr;
- ae.port[0].ctl_addr = ctrl_addr;
- ata_std_ports(&ae.port[0]);
- ae.private_data = ld;
-
- ret = -ENODEV;
- if (!ata_device_add(&ae))
+ ret = -ENOMEM;
+ host = ata_host_alloc(&pdev->dev, 1);
+ if (!host)
+ goto fail;
+ ap = host->ports[0];
+
+ ap->ops = ops;
+ ap->pio_mask = pio_modes;
+ ap->flags |= ATA_FLAG_SLAVE_POSS | iordy;
+ ap->ioaddr.cmd_addr = io_addr;
+ ap->ioaddr.altstatus_addr = ctrl_addr;
+ ap->ioaddr.ctl_addr = ctrl_addr;
+ ata_std_ports(&ap->ioaddr);
+ ap->private_data = ld;
+
+ ret = ata_host_activate(host, irq, ata_interrupt, 0, &legacy_sht);
+ if (ret)
goto fail;
legacy_host[nr_legacy_host++] = dev_get_drvdata(&pdev->dev);
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index f5d8872..9733e48 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -300,35 +300,33 @@ static struct ata_port_operations mpc52xx_ata_port_ops = {
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.data_xfer = ata_data_xfer,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start,
};
-static struct ata_probe_ent mpc52xx_ata_probe_ent = {
- .port_ops = &mpc52xx_ata_port_ops,
- .sht = &mpc52xx_ata_sht,
- .n_ports = 1,
- .pio_mask = 0x1f, /* Up to PIO4 */
- .mwdma_mask = 0x00, /* No MWDMA */
- .udma_mask = 0x00, /* No UDMA */
- .port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
- .irq_flags = 0,
-};
-
static int __devinit
mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv)
{
- struct ata_probe_ent *ae = &mpc52xx_ata_probe_ent;
- struct ata_ioports *aio = &ae->port[0];
- int rv;
-
- INIT_LIST_HEAD(&ae->node);
- ae->dev = dev;
- ae->irq = priv->ata_irq;
-
+ struct ata_host *host;
+ struct ata_port *ap;
+ struct ata_ioports *aio;
+ int rc;
+
+ host = ata_host_alloc(dev, 1);
+ if (!host)
+ return -ENOMEM;
+
+ ap = host->ports[0];
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
+ ap->pio_mask = 0x1f; /* Up to PIO4 */
+ ap->mwdma_mask = 0x00; /* No MWDMA */
+ ap->udma_mask = 0x00; /* No UDMA */
+ ap->ops = &mpc52xx_ata_port_ops;
+ host->private_data = priv;
+
+ aio = &ap->ioaddr;
aio->cmd_addr = 0; /* Don't have a classic reg block */
aio->altstatus_addr = &priv->ata_regs->tf_control;
aio->ctl_addr = &priv->ata_regs->tf_control;
@@ -343,11 +341,9 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv)
aio->status_addr = &priv->ata_regs->tf_command;
aio->command_addr = &priv->ata_regs->tf_command;
- ae->private_data = priv;
-
- rv = ata_device_add(ae);
-
- return rv ? 0 : -EINVAL;
+ /* activate host */
+ return ata_host_activate(host, priv->ata_irq, ata_interrupt, 0,
+ &mpc52xx_ata_sht);
}
static struct mpc52xx_ata_priv *
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index 4abe45a..ba4db4c 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -190,7 +190,6 @@ static struct ata_port_operations mpiix_port_ops = {
.qc_issue = mpiix_qc_issue_prot,
.data_xfer = ata_data_xfer,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -201,8 +200,9 @@ static struct ata_port_operations mpiix_port_ops = {
static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
/* Single threaded by the PCI probe logic */
- static struct ata_probe_ent probe;
static int printed_version;
+ struct ata_host *host;
+ struct ata_port *ap;
void __iomem *cmd_addr, *ctl_addr;
u16 idetim;
int irq;
@@ -210,6 +210,10 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
if (!printed_version++)
dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+ host = ata_host_alloc(&dev->dev, 1);
+ if (!host)
+ return -ENOMEM;
+
/* MPIIX has many functions which can be turned on or off according
to other devices present. Make sure IDE is enabled before we try
and use it */
@@ -238,27 +242,21 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
without BARs set fools the setup. #2 If you pci_disable_device
the MPIIX your box goes castors up */
- INIT_LIST_HEAD(&probe.node);
- probe.dev = pci_dev_to_dev(dev);
- probe.port_ops = &mpiix_port_ops;
- probe.sht = &mpiix_sht;
- probe.pio_mask = 0x1F;
- probe.irq_flags = IRQF_SHARED;
- probe.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
- probe.n_ports = 1;
+ ap = host->ports[0];
+ ap->ops = &mpiix_port_ops;
+ ap->pio_mask = 0x1F;
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
- probe.irq = irq;
- probe.port[0].cmd_addr = cmd_addr;
- probe.port[0].ctl_addr = ctl_addr;
- probe.port[0].altstatus_addr = ctl_addr;
+ ap->ioaddr.cmd_addr = cmd_addr;
+ ap->ioaddr.ctl_addr = ctl_addr;
+ ap->ioaddr.altstatus_addr = ctl_addr;
/* Let libata fill in the port details */
- ata_std_ports(&probe.port[0]);
+ ata_std_ports(&ap->ioaddr);
- /* Now add the port that is active */
- if (ata_device_add(&probe))
- return 0;
- return -ENODEV;
+ /* activate host */
+ return ata_host_activate(host, irq, ata_interrupt, IRQF_SHARED,
+ &mpiix_sht);
}
static const struct pci_device_id mpiix[] = {
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 103720f..85719a2 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -90,7 +90,6 @@ static struct ata_port_operations pcmcia_port_ops = {
.data_xfer = ata_data_xfer_noirq,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -111,7 +110,8 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static int pcmcia_init_one(struct pcmcia_device *pdev)
{
- struct ata_probe_ent ae;
+ struct ata_host *host;
+ struct ata_port *ap;
struct ata_pcmcia_info *info;
tuple_t tuple;
struct {
@@ -255,24 +255,24 @@ next_entry:
* Having done the PCMCIA plumbing the ATA side is relatively
* sane.
*/
-
- memset(&ae, 0, sizeof(struct ata_probe_ent));
- INIT_LIST_HEAD(&ae.node);
- ae.dev = &pdev->dev;
- ae.port_ops = &pcmcia_port_ops;
- ae.sht = &pcmcia_sht;
- ae.n_ports = 1;
- ae.pio_mask = 1; /* ISA so PIO 0 cycles */
- ae.irq = pdev->irq.AssignedIRQ;
- ae.irq_flags = IRQF_SHARED;
- ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
- ae.port[0].cmd_addr = io_addr;
- ae.port[0].altstatus_addr = ctl_addr;
- ae.port[0].ctl_addr = ctl_addr;
- ata_std_ports(&ae.port[0]);
-
- ret = -ENODEV;
- if (ata_device_add(&ae) == 0)
+ ret = -ENOMEM;
+ host = ata_host_alloc(&pdev->dev, 1);
+ if (!host)
+ goto failed;
+ ap = host->ports[0];
+
+ ap->ops = &pcmcia_port_ops;
+ ap->pio_mask = 1; /* ISA so PIO 0 cycles */
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
+ ap->ioaddr.cmd_addr = io_addr;
+ ap->ioaddr.altstatus_addr = ctl_addr;
+ ap->ioaddr.ctl_addr = ctl_addr;
+ ata_std_ports(&ap->ioaddr);
+
+ /* activate */
+ ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt,
+ IRQF_SHARED, &pcmcia_sht);
+ if (ret)
goto failed;
info->ndev = 1;
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index 3ab66fd..69fec16 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -167,7 +167,6 @@ static struct ata_port_operations pdc2027x_pata100_ops = {
.error_handler = pdc2027x_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -201,7 +200,6 @@ static struct ata_port_operations pdc2027x_pata133_ops = {
.error_handler = pdc2027x_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -212,7 +210,6 @@ static struct ata_port_operations pdc2027x_pata133_ops = {
static struct ata_port_info pdc2027x_port_info[] = {
/* PDC_UDMA_100 */
{
- .sht = &pdc2027x_sht,
.flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
ATA_FLAG_MMIO,
.pio_mask = 0x1f, /* pio0-4 */
@@ -222,7 +219,6 @@ static struct ata_port_info pdc2027x_port_info[] = {
},
/* PDC_UDMA_133 */
{
- .sht = &pdc2027x_sht,
.flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
ATA_FLAG_MMIO,
.pio_mask = 0x1f, /* pio0-4 */
@@ -521,12 +517,12 @@ static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc)
/**
* pdc_read_counter - Read the ctr counter
- * @probe_ent: for the port address
+ * @host: target ATA host
*/
-static long pdc_read_counter(struct ata_probe_ent *probe_ent)
+static long pdc_read_counter(struct ata_host *host)
{
- void __iomem *mmio_base = probe_ent->iomap[PDC_MMIO_BAR];
+ void __iomem *mmio_base = host->iomap[PDC_MMIO_BAR];
long counter;
int retry = 1;
u32 bccrl, bccrh, bccrlv, bccrhv;
@@ -564,12 +560,12 @@ retry:
* adjust_pll - Adjust the PLL input clock in Hz.
*
* @pdc_controller: controller specific information
- * @probe_ent: For the port address
+ * @host: target ATA host
* @pll_clock: The input of PLL in HZ
*/
-static void pdc_adjust_pll(struct ata_probe_ent *probe_ent, long pll_clock, unsigned int board_idx)
+static void pdc_adjust_pll(struct ata_host *host, long pll_clock, unsigned int board_idx)
{
- void __iomem *mmio_base = probe_ent->iomap[PDC_MMIO_BAR];
+ void __iomem *mmio_base = host->iomap[PDC_MMIO_BAR];
u16 pll_ctl;
long pll_clock_khz = pll_clock / 1000;
long pout_required = board_idx? PDC_133_MHZ:PDC_100_MHZ;
@@ -649,19 +645,19 @@ static void pdc_adjust_pll(struct ata_probe_ent *probe_ent, long pll_clock, unsi
/**
* detect_pll_input_clock - Detect the PLL input clock in Hz.
- * @probe_ent: for the port address
+ * @host: target ATA host
* Ex. 16949000 on 33MHz PCI bus for pdc20275.
* Half of the PCI clock.
*/
-static long pdc_detect_pll_input_clock(struct ata_probe_ent *probe_ent)
+static long pdc_detect_pll_input_clock(struct ata_host *host)
{
- void __iomem *mmio_base = probe_ent->iomap[PDC_MMIO_BAR];
+ void __iomem *mmio_base = host->iomap[PDC_MMIO_BAR];
u32 scr;
long start_count, end_count;
long pll_clock;
/* Read current counter value */
- start_count = pdc_read_counter(probe_ent);
+ start_count = pdc_read_counter(host);
/* Start the test mode */
scr = readl(mmio_base + PDC_SYS_CTL);
@@ -673,7 +669,7 @@ static long pdc_detect_pll_input_clock(struct ata_probe_ent *probe_ent)
mdelay(100);
/* Read the counter values again */
- end_count = pdc_read_counter(probe_ent);
+ end_count = pdc_read_counter(host);
/* Stop the test mode */
scr = readl(mmio_base + PDC_SYS_CTL);
@@ -692,11 +688,10 @@ static long pdc_detect_pll_input_clock(struct ata_probe_ent *probe_ent)
/**
* pdc_hardware_init - Initialize the hardware.
- * @pdev: instance of pci_dev found
- * @pdc_controller: controller specific information
- * @pe: for the port address
+ * @host: target ATA host
+ * @board_idx: board identifier
*/
-static int pdc_hardware_init(struct pci_dev *pdev, struct ata_probe_ent *pe, unsigned int board_idx)
+static int pdc_hardware_init(struct ata_host *host, unsigned int board_idx)
{
long pll_clock;
@@ -706,15 +701,15 @@ static int pdc_hardware_init(struct pci_dev *pdev, struct ata_probe_ent *pe, uns
* Ex. 25MHz or 40MHz, we have to adjust the cycle_time.
* The pdc20275 controller employs PLL circuit to help correct timing registers setting.
*/
- pll_clock = pdc_detect_pll_input_clock(pe);
+ pll_clock = pdc_detect_pll_input_clock(host);
if (pll_clock < 0) /* counter overflow? Try again. */
- pll_clock = pdc_detect_pll_input_clock(pe);
+ pll_clock = pdc_detect_pll_input_clock(host);
- dev_printk(KERN_INFO, &pdev->dev, "PLL input clock %ld kHz\n", pll_clock/1000);
+ dev_printk(KERN_INFO, host->dev, "PLL input clock %ld kHz\n", pll_clock/1000);
/* Adjust PLL control register */
- pdc_adjust_pll(pe, pll_clock, board_idx);
+ pdc_adjust_pll(host, pll_clock, board_idx);
return 0;
}
@@ -746,8 +741,7 @@ static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base)
* Called when an instance of PCI adapter is inserted.
* This function checks whether the hardware is supported,
* initialize hardware and register an instance of ata_host to
- * libata by providing struct ata_probe_ent and ata_device_add().
- * (implements struct pci_driver.probe() )
+ * libata. (implements struct pci_driver.probe() )
*
* @pdev: instance of pci_dev found
* @ent: matching entry in the id_tbl[]
@@ -756,14 +750,21 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
{
static int printed_version;
unsigned int board_idx = (unsigned int) ent->driver_data;
-
- struct ata_probe_ent *probe_ent;
+ const struct ata_port_info *ppi[] =
+ { &pdc2027x_port_info[board_idx], NULL };
+ struct ata_host *host;
void __iomem *mmio_base;
int rc;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ /* alloc host */
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
+ if (!host)
+ return -ENOMEM;
+
+ /* acquire resources and fill host */
rc = pcim_enable_device(pdev);
if (rc)
return rc;
@@ -771,51 +772,28 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
rc = pcim_iomap_regions(pdev, 1 << PDC_MMIO_BAR, DRV_NAME);
if (rc)
return rc;
+ host->iomap = pcim_iomap_table(pdev);
rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
if (rc)
return rc;
- /* Prepare the probe entry */
- probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
- if (probe_ent == NULL)
- return -ENOMEM;
-
- probe_ent->dev = pci_dev_to_dev(pdev);
- INIT_LIST_HEAD(&probe_ent->node);
-
- probe_ent->sht = pdc2027x_port_info[board_idx].sht;
- probe_ent->port_flags = pdc2027x_port_info[board_idx].flags;
- probe_ent->pio_mask = pdc2027x_port_info[board_idx].pio_mask;
- probe_ent->mwdma_mask = pdc2027x_port_info[board_idx].mwdma_mask;
- probe_ent->udma_mask = pdc2027x_port_info[board_idx].udma_mask;
- probe_ent->port_ops = pdc2027x_port_info[board_idx].port_ops;
+ mmio_base = host->iomap[PDC_MMIO_BAR];
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->iomap = pcim_iomap_table(pdev);
+ pdc_ata_setup_port(&host->ports[0]->ioaddr, mmio_base + 0x17c0);
+ host->ports[0]->ioaddr.bmdma_addr = mmio_base + 0x1000;
+ pdc_ata_setup_port(&host->ports[1]->ioaddr, mmio_base + 0x15c0);
+ host->ports[1]->ioaddr.bmdma_addr = mmio_base + 0x1008;
- mmio_base = probe_ent->iomap[PDC_MMIO_BAR];
-
- pdc_ata_setup_port(&probe_ent->port[0], mmio_base + 0x17c0);
- probe_ent->port[0].bmdma_addr = mmio_base + 0x1000;
- pdc_ata_setup_port(&probe_ent->port[1], mmio_base + 0x15c0);
- probe_ent->port[1].bmdma_addr = mmio_base + 0x1008;
-
- probe_ent->n_ports = 2;
-
- pci_set_master(pdev);
//pci_enable_intx(pdev);
/* initialize adapter */
- if (pdc_hardware_init(pdev, probe_ent, board_idx) != 0)
+ if (pdc_hardware_init(host, board_idx) != 0)
return -EIO;
- if (!ata_device_add(probe_ent))
- return -ENODEV;
-
- devm_kfree(&pdev->dev, probe_ent);
- return 0;
+ pci_set_master(pdev);
+ return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+ &pdc2027x_sht);
}
/**
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 4b82a54..d8c242b 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -86,7 +86,6 @@ static struct ata_port_operations pata_platform_port_ops = {
.data_xfer = ata_data_xfer_noirq,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -135,7 +134,8 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
static int __devinit pata_platform_probe(struct platform_device *pdev)
{
struct resource *io_res, *ctl_res;
- struct ata_probe_ent ae;
+ struct ata_host *host;
+ struct ata_port *ap;
unsigned int mmio;
/*
@@ -175,44 +175,41 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
/*
* Now that that's out of the way, wire up the port..
*/
- memset(&ae, 0, sizeof(struct ata_probe_ent));
- INIT_LIST_HEAD(&ae.node);
- ae.dev = &pdev->dev;
- ae.port_ops = &pata_platform_port_ops;
- ae.sht = &pata_platform_sht;
- ae.n_ports = 1;
- ae.pio_mask = pio_mask;
- ae.irq = platform_get_irq(pdev, 0);
- ae.irq_flags = 0;
- ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
+ host = ata_host_alloc(&pdev->dev, 1);
+ if (!host)
+ return -ENOMEM;
+ ap = host->ports[0];
+
+ ap->ops = &pata_platform_port_ops;
+ ap->pio_mask = pio_mask;
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
/*
* Handle the MMIO case
*/
if (mmio) {
- ae.port[0].cmd_addr = devm_ioremap(&pdev->dev, io_res->start,
+ ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, io_res->start,
io_res->end - io_res->start + 1);
- ae.port[0].ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start,
+ ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start,
ctl_res->end - ctl_res->start + 1);
} else {
- ae.port[0].cmd_addr = devm_ioport_map(&pdev->dev, io_res->start,
+ ap->ioaddr.cmd_addr = devm_ioport_map(&pdev->dev, io_res->start,
io_res->end - io_res->start + 1);
- ae.port[0].ctl_addr = devm_ioport_map(&pdev->dev, ctl_res->start,
+ ap->ioaddr.ctl_addr = devm_ioport_map(&pdev->dev, ctl_res->start,
ctl_res->end - ctl_res->start + 1);
}
- if (!ae.port[0].cmd_addr || !ae.port[0].ctl_addr) {
+ if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) {
dev_err(&pdev->dev, "failed to map IO/CTL base\n");
return -ENOMEM;
}
- ae.port[0].altstatus_addr = ae.port[0].ctl_addr;
+ ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
- pata_platform_setup_port(&ae.port[0], pdev->dev.platform_data);
+ pata_platform_setup_port(&ap->ioaddr, pdev->dev.platform_data);
- if (unlikely(ata_device_add(&ae) == 0))
- return -ENODEV;
-
- return 0;
+ /* activate */
+ return ata_host_activate(host, platform_get_irq(pdev, 0), ata_interrupt,
+ 0, &pata_platform_sht);
}
/**
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index c381001..103f444 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -189,7 +189,6 @@ static struct ata_port_operations qdi6500_port_ops = {
.data_xfer = qdi_data_xfer,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -217,7 +216,6 @@ static struct ata_port_operations qdi6580_port_ops = {
.data_xfer = qdi_data_xfer,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -238,8 +236,9 @@ static struct ata_port_operations qdi6580_port_ops = {
static __init int qdi_init_one(unsigned long port, int type, unsigned long io, int irq, int fast)
{
- struct ata_probe_ent ae;
struct platform_device *pdev;
+ struct ata_host *host;
+ struct ata_port *ap;
void __iomem *io_addr, *ctl_addr;
int ret;
@@ -257,34 +256,31 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
if (!io_addr || !ctl_addr)
goto fail;
- memset(&ae, 0, sizeof(struct ata_probe_ent));
- INIT_LIST_HEAD(&ae.node);
- ae.dev = &pdev->dev;
+ ret = -ENOMEM;
+ host = ata_host_alloc(&pdev->dev, 1);
+ if (!host)
+ goto fail;
+ ap = host->ports[0];
if (type == 6580) {
- ae.port_ops = &qdi6580_port_ops;
- ae.pio_mask = 0x1F;
- ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
+ ap->ops = &qdi6580_port_ops;
+ ap->pio_mask = 0x1F;
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
} else {
- ae.port_ops = &qdi6500_port_ops;
- ae.pio_mask = 0x07; /* Actually PIO3 !IORDY is possible */
- ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
- ATA_FLAG_NO_IORDY;
+ ap->ops = &qdi6500_port_ops;
+ ap->pio_mask = 0x07; /* Actually PIO3 !IORDY is possible */
+ ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY;
}
- ae.sht = &qdi_sht;
- ae.n_ports = 1;
- ae.irq = irq;
- ae.irq_flags = 0;
- ae.port[0].cmd_addr = io_addr;
- ae.port[0].altstatus_addr = ctl_addr;
- ae.port[0].ctl_addr = ctl_addr;
- ata_std_ports(&ae.port[0]);
+ ap->ioaddr.cmd_addr = io_addr;
+ ap->ioaddr.altstatus_addr = ctl_addr;
+ ap->ioaddr.ctl_addr = ctl_addr;
+ ata_std_ports(&ap->ioaddr);
/*
* Hook in a private data structure per channel
*/
- ae.private_data = &qdi_data[nr_qdi_host];
+ ap->private_data = &qdi_data[nr_qdi_host];
qdi_data[nr_qdi_host].timing = port;
qdi_data[nr_qdi_host].fast = fast;
@@ -292,8 +288,9 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
printk(KERN_INFO DRV_NAME": qd%d at 0x%lx.\n", type, io);
- ret = -ENODEV;
- if (!ata_device_add(&ae))
+ /* activate */
+ ret = ata_host_activate(host, irq, ata_interrupt, 0, &qdi_sht);
+ if (ret)
goto fail;
qdi_host[nr_qdi_host++] = dev_get_drvdata(&pdev->dev);
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index ee0c533..de90d36 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -1016,7 +1016,6 @@ static const struct ata_port_operations scc_pata_ops = {
.error_handler = scc_error_handler,
.post_internal_cmd = scc_bmdma_stop,
- .irq_handler = ata_interrupt,
.irq_clear = scc_bmdma_irq_clear,
.irq_on = scc_irq_on,
.irq_ack = scc_irq_ack,
@@ -1027,7 +1026,6 @@ static const struct ata_port_operations scc_pata_ops = {
static struct ata_port_info scc_port_info[] = {
{
- .sht = &scc_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x00,
@@ -1040,10 +1038,10 @@ static struct ata_port_info scc_port_info[] = {
* scc_reset_controller - initialize SCC PATA controller.
*/
-static int scc_reset_controller(struct ata_probe_ent *probe_ent)
+static int scc_reset_controller(struct ata_host *host)
{
- void __iomem *ctrl_base = probe_ent->iomap[SCC_CTRL_BAR];
- void __iomem *bmid_base = probe_ent->iomap[SCC_BMID_BAR];
+ void __iomem *ctrl_base = host->iomap[SCC_CTRL_BAR];
+ void __iomem *bmid_base = host->iomap[SCC_BMID_BAR];
void __iomem *cckctrl_port = ctrl_base + SCC_CTL_CCKCTRL;
void __iomem *mode_port = ctrl_base + SCC_CTL_MODEREG;
void __iomem *ecmode_port = ctrl_base + SCC_CTL_ECMODE;
@@ -1104,22 +1102,20 @@ static void scc_setup_ports (struct ata_ioports *ioaddr, void __iomem *base)
ioaddr->command_addr = ioaddr->cmd_addr + SCC_REG_CMD;
}
-static int scc_host_init(struct ata_probe_ent *probe_ent)
+static int scc_host_init(struct ata_host *host)
{
- struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+ struct pci_dev *pdev = to_pci_dev(host->dev);
int rc;
- rc = scc_reset_controller(probe_ent);
+ rc = scc_reset_controller(host);
if (rc)
return rc;
- probe_ent->n_ports = 1;
-
rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
if (rc)
return rc;
- scc_setup_ports(&probe_ent->port[0], probe_ent->iomap[SCC_BMID_BAR]);
+ scc_setup_ports(&host->ports[0]->ioaddr, host->iomap[SCC_BMID_BAR]);
pci_set_master(pdev);
@@ -1142,14 +1138,18 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
unsigned int board_idx = (unsigned int) ent->driver_data;
+ const struct ata_port_info *ppi[] = { &scc_port_info[board_idx], NULL };
struct device *dev = &pdev->dev;
- struct ata_probe_ent *probe_ent;
int rc;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev,
"version " DRV_VERSION "\n");
+ host = ata_port_alloc_pinfo(&pdev->dev, ppi, 1);
+ if (!host)
+ return -ENOMEM;
+
rc = pcim_enable_device(pdev);
if (rc)
return rc;
@@ -1159,33 +1159,14 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
pcim_pin_device(pdev);
if (rc)
return rc;
+ host->iomap = pcim_iomap_table(pdev);
- probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
- if (!probe_ent)
- return -ENOMEM;
-
- probe_ent->dev = dev;
- INIT_LIST_HEAD(&probe_ent->node);
-
- probe_ent->sht = scc_port_info[board_idx].sht;
- probe_ent->port_flags = scc_port_info[board_idx].flags;
- probe_ent->pio_mask = scc_port_info[board_idx].pio_mask;
- probe_ent->udma_mask = scc_port_info[board_idx].udma_mask;
- probe_ent->port_ops = scc_port_info[board_idx].port_ops;
-
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->iomap = pcim_iomap_table(pdev);
-
- rc = scc_host_init(probe_ent);
+ rc = scc_host_init(host);
if (rc)
return rc;
- if (!ata_device_add(probe_ent))
- return -ENODEV;
-
- devm_kfree(dev, probe_ent);
- return 0;
+ return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+ &scc_sht);
}
static struct pci_driver scc_pci_driver = {
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
index 6c11103..5422120 100644
--- a/drivers/ata/pata_winbond.c
+++ b/drivers/ata/pata_winbond.c
@@ -158,7 +158,6 @@ static struct ata_port_operations winbond_port_ops = {
.data_xfer = winbond_data_xfer,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -179,11 +178,9 @@ static struct ata_port_operations winbond_port_ops = {
static __init int winbond_init_one(unsigned long port)
{
- struct ata_probe_ent ae;
struct platform_device *pdev;
- int ret;
u8 reg;
- int i;
+ int i, rc;
reg = winbond_readcfg(port, 0x81);
reg |= 0x80; /* jumpered mode off */
@@ -202,58 +199,56 @@ static __init int winbond_init_one(unsigned long port)
for (i = 0; i < 2 ; i ++) {
unsigned long cmd_port = 0x1F0 - (0x80 * i);
+ struct ata_host *host;
+ struct ata_port *ap;
void __iomem *cmd_addr, *ctl_addr;
- if (reg & (1 << i)) {
- /*
- * Fill in a probe structure first of all
- */
-
- pdev = platform_device_register_simple(DRV_NAME, nr_winbond_host, NULL, 0);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
-
- cmd_addr = devm_ioport_map(&pdev->dev, cmd_port, 8);
- ctl_addr = devm_ioport_map(&pdev->dev, cmd_port + 0x0206, 1);
- if (!cmd_addr || !ctl_addr) {
- platform_device_unregister(pdev);
- return -ENOMEM;
- }
-
- memset(&ae, 0, sizeof(struct ata_probe_ent));
- INIT_LIST_HEAD(&ae.node);
- ae.dev = &pdev->dev;
-
- ae.port_ops = &winbond_port_ops;
- ae.pio_mask = 0x1F;
-
- ae.sht = &winbond_sht;
-
- ae.n_ports = 1;
- ae.irq = 14 + i;
- ae.irq_flags = 0;
- ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
- ae.port[0].cmd_addr = cmd_addr;
- ae.port[0].altstatus_addr = ctl_addr;
- ae.port[0].ctl_addr = ctl_addr;
- ata_std_ports(&ae.port[0]);
- /*
- * Hook in a private data structure per channel
- */
- ae.private_data = &winbond_data[nr_winbond_host];
- winbond_data[nr_winbond_host].config = port;
- winbond_data[nr_winbond_host].platform_dev = pdev;
-
- ret = ata_device_add(&ae);
- if (ret == 0) {
- platform_device_unregister(pdev);
- return -ENODEV;
- }
- winbond_host[nr_winbond_host++] = dev_get_drvdata(&pdev->dev);
- }
+ if (!(reg & (1 << i)))
+ continue;
+
+ pdev = platform_device_register_simple(DRV_NAME, nr_winbond_host, NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ rc = -ENOMEM;
+ host = ata_host_alloc(&pdev->dev, 1);
+ if (!host)
+ goto err_unregister;
+
+ rc = -ENOMEM;
+ cmd_addr = devm_ioport_map(&pdev->dev, cmd_port, 8);
+ ctl_addr = devm_ioport_map(&pdev->dev, cmd_port + 0x0206, 1);
+ if (!cmd_addr || !ctl_addr)
+ goto err_unregister;
+
+ ap = host->ports[0];
+ ap->ops = &winbond_port_ops;
+ ap->pio_mask = 0x1F;
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
+ ap->ioaddr.cmd_addr = cmd_addr;
+ ap->ioaddr.altstatus_addr = ctl_addr;
+ ap->ioaddr.ctl_addr = ctl_addr;
+ ata_std_ports(&ap->ioaddr);
+
+ /* hook in a private data structure per channel */
+ host->private_data = &winbond_data[nr_winbond_host];
+ winbond_data[nr_winbond_host].config = port;
+ winbond_data[nr_winbond_host].platform_dev = pdev;
+
+ /* activate */
+ rc = ata_host_activate(host, 14 + i, ata_interrupt, 0,
+ &winbond_sht);
+ if (rc)
+ goto err_unregister;
+
+ winbond_host[nr_winbond_host++] = dev_get_drvdata(&pdev->dev);
}
return 0;
+
+ err_unregister:
+ platform_device_unregister(pdev);
+ return rc;
}
/**
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 9448aab..4df1e17 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -52,9 +52,9 @@
/* macro to calculate base address for ADMA regs */
#define ADMA_REGS(base,port_no) ((base) + 0x80 + ((port_no) * 0x20))
-/* macro to obtain addresses from ata_host */
-#define ADMA_HOST_REGS(host,port_no) \
- ADMA_REGS((host)->iomap[ADMA_MMIO_BAR], port_no)
+/* macro to obtain addresses from ata_port */
+#define ADMA_PORT_REGS(ap) \
+ ADMA_REGS((ap)->host->iomap[ADMA_MMIO_BAR], ap->port_no)
enum {
ADMA_MMIO_BAR = 4,
@@ -128,7 +128,6 @@ struct adma_port_priv {
static int adma_ata_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent);
-static irqreturn_t adma_intr (int irq, void *dev_instance);
static int adma_port_start(struct ata_port *ap);
static void adma_host_stop(struct ata_host *host);
static void adma_port_stop(struct ata_port *ap);
@@ -172,7 +171,6 @@ static const struct ata_port_operations adma_ata_ops = {
.qc_issue = adma_qc_issue,
.eng_timeout = adma_eng_timeout,
.data_xfer = ata_data_xfer,
- .irq_handler = adma_intr,
.irq_clear = adma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -186,7 +184,6 @@ static const struct ata_port_operations adma_ata_ops = {
static struct ata_port_info adma_port_info[] = {
/* board_1841_idx */
{
- .sht = &adma_ata_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
ATA_FLAG_PIO_POLLING,
@@ -229,8 +226,10 @@ static void adma_irq_clear(struct ata_port *ap)
/* nothing */
}
-static void adma_reset_engine(void __iomem *chan)
+static void adma_reset_engine(struct ata_port *ap)
{
+ void __iomem *chan = ADMA_PORT_REGS(ap);
+
/* reset ADMA to idle state */
writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
udelay(2);
@@ -241,14 +240,14 @@ static void adma_reset_engine(void __iomem *chan)
static void adma_reinit_engine(struct ata_port *ap)
{
struct adma_port_priv *pp = ap->private_data;
- void __iomem *chan = ADMA_HOST_REGS(ap->host, ap->port_no);
+ void __iomem *chan = ADMA_PORT_REGS(ap);
/* mask/clear ATA interrupts */
writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
ata_check_status(ap);
/* reset the ADMA engine */
- adma_reset_engine(chan);
+ adma_reset_engine(ap);
/* set in-FIFO threshold to 0x100 */
writew(0x100, chan + ADMA_FIFO_IN);
@@ -268,7 +267,7 @@ static void adma_reinit_engine(struct ata_port *ap)
static inline void adma_enter_reg_mode(struct ata_port *ap)
{
- void __iomem *chan = ADMA_HOST_REGS(ap->host, ap->port_no);
+ void __iomem *chan = ADMA_PORT_REGS(ap);
writew(aPIOMD4, chan + ADMA_CONTROL);
readb(chan + ADMA_STATUS); /* flush */
@@ -415,7 +414,7 @@ static void adma_qc_prep(struct ata_queued_cmd *qc)
static inline void adma_packet_start(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- void __iomem *chan = ADMA_HOST_REGS(ap->host, ap->port_no);
+ void __iomem *chan = ADMA_PORT_REGS(ap);
VPRINTK("ENTER, ap %p\n", ap);
@@ -453,7 +452,7 @@ static inline unsigned int adma_intr_pkt(struct ata_host *host)
struct ata_port *ap = host->ports[port_no];
struct adma_port_priv *pp;
struct ata_queued_cmd *qc;
- void __iomem *chan = ADMA_HOST_REGS(host, port_no);
+ void __iomem *chan = ADMA_PORT_REGS(ap);
u8 status = readb(chan + ADMA_STATUS);
if (status == 0)
@@ -575,7 +574,7 @@ static int adma_port_start(struct ata_port *ap)
static void adma_port_stop(struct ata_port *ap)
{
- adma_reset_engine(ADMA_HOST_REGS(ap->host, ap->port_no));
+ adma_reset_engine(ap);
}
static void adma_host_stop(struct ata_host *host)
@@ -583,35 +582,40 @@ static void adma_host_stop(struct ata_host *host)
unsigned int port_no;
for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
- adma_reset_engine(ADMA_HOST_REGS(host, port_no));
+ adma_reset_engine(host->ports[port_no]);
}
-static void adma_host_init(unsigned int chip_id,
- struct ata_probe_ent *probe_ent)
+static void adma_host_init(struct ata_host *host, unsigned int chip_id)
{
unsigned int port_no;
- void __iomem *mmio_base = probe_ent->iomap[ADMA_MMIO_BAR];
/* enable/lock aGO operation */
- writeb(7, mmio_base + ADMA_MODE_LOCK);
+ writeb(7, host->iomap[ADMA_MMIO_BAR] + ADMA_MODE_LOCK);
/* reset the ADMA logic */
for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
- adma_reset_engine(ADMA_REGS(mmio_base, port_no));
+ adma_reset_engine(host->ports[port_no]);
}
static int adma_ata_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
static int printed_version;
- struct ata_probe_ent *probe_ent = NULL;
- void __iomem *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data;
+ const struct ata_port_info *ppi[] = { &adma_port_info[board_idx], NULL };
+ struct ata_host *host;
+ void __iomem *mmio_base;
int rc, port_no;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ /* alloc host */
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, ADMA_PORTS);
+ if (!host)
+ return -ENOMEM;
+
+ /* acquire resources and fill host */
rc = pcim_enable_device(pdev);
if (rc)
return rc;
@@ -622,46 +626,23 @@ static int adma_ata_init_one(struct pci_dev *pdev,
rc = pcim_iomap_regions(pdev, 1 << ADMA_MMIO_BAR, DRV_NAME);
if (rc)
return rc;
- mmio_base = pcim_iomap_table(pdev)[ADMA_MMIO_BAR];
+ host->iomap = pcim_iomap_table(pdev);
+ mmio_base = host->iomap[ADMA_MMIO_BAR];
rc = pci_configure_dma_masks(pdev, DMA_32BIT_MASK, NULL);
if (rc)
return rc;
- probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
- if (probe_ent == NULL)
- return -ENOMEM;
-
- probe_ent->dev = pci_dev_to_dev(pdev);
- INIT_LIST_HEAD(&probe_ent->node);
-
- probe_ent->sht = adma_port_info[board_idx].sht;
- probe_ent->port_flags = adma_port_info[board_idx].flags;
- probe_ent->pio_mask = adma_port_info[board_idx].pio_mask;
- probe_ent->mwdma_mask = adma_port_info[board_idx].mwdma_mask;
- probe_ent->udma_mask = adma_port_info[board_idx].udma_mask;
- probe_ent->port_ops = adma_port_info[board_idx].port_ops;
-
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->n_ports = ADMA_PORTS;
- probe_ent->iomap = pcim_iomap_table(pdev);
-
- for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
- adma_ata_setup_port(&probe_ent->port[port_no],
+ for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+ adma_ata_setup_port(&host->ports[port_no]->ioaddr,
ADMA_ATA_REGS(mmio_base, port_no));
- }
-
- pci_set_master(pdev);
/* initialize adapter */
- adma_host_init(board_idx, probe_ent);
+ adma_host_init(host, board_idx);
- if (!ata_device_add(probe_ent))
- return -ENODEV;
-
- devm_kfree(&pdev->dev, probe_ent);
- return 0;
+ pci_set_master(pdev);
+ return ata_host_activate(host, pdev->irq, adma_intr, IRQF_SHARED,
+ &adma_ata_sht);
}
static int __init adma_ata_init(void)
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH 11/12] libata: convert the remaining PATA drivers to new init model
2007-03-09 11:15 ` [PATCH 11/12] libata: convert the remaining PATA drivers " Tejun Heo
@ 2007-03-09 12:49 ` Alan Cox
0 siblings, 0 replies; 27+ messages in thread
From: Alan Cox @ 2007-03-09 12:49 UTC (permalink / raw)
To: Tejun Heo; +Cc: jeff, linux-ide
> Tested pdc_adma and pata_legacy. Both are as broken as before. The
> rest are compile tested only.
pata_legacy should be working. If you are using the Jeff/Linus tree
you'll need to remove the buggy crap for ACPI and then test.
It does still leave ports around and I need to find a sane way to probe
for an ATA port presence before using libata (or have a 'no drives go
away' action)
Other than the one noted NAK point the rest of the core changes look good
to me and the PATA ones sane, as well as good cleanups.
Acked-by: Alan Cox <alan@redhat.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 12/12] libata: kill probe_ent and related helpers
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
` (6 preceding siblings ...)
2007-03-09 11:15 ` [PATCH 11/12] libata: convert the remaining PATA drivers " Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
2007-03-09 11:15 ` [PATCH 06/12] libata: convert native PCI host handling to new init model Tejun Heo
` (3 subsequent siblings)
11 siblings, 0 replies; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
All drivers are converted to new init model. Kill probe_ent,
ata_device_add() and ata_pci_init_native_mode().
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/libata-core.c | 153 ---------------------------------------------
drivers/ata/libata-sff.c | 95 ----------------------------
drivers/ata/libata.h | 2 -
include/linux/libata.h | 31 ---------
4 files changed, 0 insertions(+), 281 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 4d371fb..5722026 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5987,131 +5987,6 @@ int ata_host_activate(struct ata_host *host, int irq,
}
/**
- * ata_device_add - Register hardware device with ATA and SCSI layers
- * @ent: Probe information describing hardware device to be registered
- *
- * This function processes the information provided in the probe
- * information struct @ent, allocates the necessary ATA and SCSI
- * host information structures, initializes them, and registers
- * everything with requisite kernel subsystems.
- *
- * This function requests irqs, probes the ATA bus, and probes
- * the SCSI bus.
- *
- * LOCKING:
- * PCI/etc. bus probe sem.
- *
- * RETURNS:
- * Number of ports registered. Zero on error (no ports registered).
- */
-int ata_device_add(const struct ata_probe_ent *ent)
-{
- unsigned int i;
- struct device *dev = ent->dev;
- struct ata_host *host;
- int rc;
-
- DPRINTK("ENTER\n");
-
- if (ent->irq == 0) {
- dev_printk(KERN_ERR, dev, "is not available: No interrupt assigned.\n");
- return 0;
- }
-
- if (!ent->port_ops->error_handler &&
- !(ent->port_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) {
- dev_printk(KERN_ERR, dev, "no reset mechanism available\n");
- return 0;
- }
-
- if (!devres_open_group(dev, ata_device_add, GFP_KERNEL))
- return 0;
-
- /* allocate host */
- host = ata_host_alloc(dev, ent->n_ports);
-
- host->irq = ent->irq;
- host->irq2 = ent->irq2;
- host->iomap = ent->iomap;
- host->private_data = ent->private_data;
- host->ops = ent->port_ops;
- host->flags = ent->_host_flags;
-
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
-
- /* dummy? */
- if (ent->dummy_port_mask & (1 << i)) {
- ap->ops = &ata_dummy_port_ops;
- continue;
- }
-
- if (ap->port_no == 1 && ent->pinfo2) {
- ap->pio_mask = ent->pinfo2->pio_mask;
- ap->mwdma_mask = ent->pinfo2->mwdma_mask;
- ap->udma_mask = ent->pinfo2->udma_mask;
- ap->flags |= ent->pinfo2->flags;
- ap->ops = ent->pinfo2->port_ops;
- } else {
- ap->pio_mask = ent->pio_mask;
- ap->mwdma_mask = ent->mwdma_mask;
- ap->udma_mask = ent->udma_mask;
- ap->flags |= ent->port_flags;
- ap->ops = ent->port_ops;
- }
-
- memcpy(&ap->ioaddr, &ent->port[ap->port_no],
- sizeof(struct ata_ioports));
- }
-
- /* start and freeze ports before requesting IRQ */
- rc = ata_host_start(host);
- if (rc)
- goto err_out;
-
- /* obtain irq, that may be shared between channels */
- rc = devm_request_irq(dev, ent->irq, ent->port_ops->irq_handler,
- ent->irq_flags, DRV_NAME, host);
- if (rc) {
- dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
- ent->irq, rc);
- goto err_out;
- }
-
- /* do we have a second IRQ for the other channel, eg legacy mode */
- if (ent->irq2) {
- /* We will get weird core code crashes later if this is true
- so trap it now */
- BUG_ON(ent->irq == ent->irq2);
-
- rc = devm_request_irq(dev, ent->irq2,
- ent->port_ops->irq_handler, ent->irq_flags,
- DRV_NAME, host);
- if (rc) {
- dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
- ent->irq2, rc);
- goto err_out;
- }
- }
-
- /* resource acquisition complete */
- devres_remove_group(dev, ata_device_add);
-
- /* attach */
- rc = ata_host_attach(host, ent->sht);
- if (rc)
- goto err_out;
-
- VPRINTK("EXIT, returning %u\n", host->n_ports);
- return host->n_ports; /* success */
-
- err_out:
- devres_release_group(dev, ata_device_add);
- VPRINTK("EXIT, returning 0\n");
- return 0;
-}
-
-/**
* ata_port_detach - Detach ATA port in prepration of device removal
* @ap: ATA port to be detached
*
@@ -6186,32 +6061,6 @@ void ata_host_detach(struct ata_host *host)
ata_port_detach(host->ports[i]);
}
-struct ata_probe_ent *
-ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
-{
- struct ata_probe_ent *probe_ent;
-
- probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
- if (!probe_ent) {
- printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
- kobject_name(&(dev->kobj)));
- return NULL;
- }
-
- INIT_LIST_HEAD(&probe_ent->node);
- probe_ent->dev = dev;
-
- probe_ent->sht = port->sht;
- probe_ent->port_flags = port->flags;
- probe_ent->pio_mask = port->pio_mask;
- probe_ent->mwdma_mask = port->mwdma_mask;
- probe_ent->udma_mask = port->udma_mask;
- probe_ent->port_ops = port->port_ops;
- probe_ent->private_data = port->private_data;
-
- return probe_ent;
-}
-
/**
* ata_std_ports - initialize ioaddr with standard port offsets.
* @ioaddr: IO address structure to be initialized
@@ -6570,7 +6419,6 @@ EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo);
EXPORT_SYMBOL_GPL(ata_host_start);
EXPORT_SYMBOL_GPL(ata_host_attach);
EXPORT_SYMBOL_GPL(ata_host_activate);
-EXPORT_SYMBOL_GPL(ata_device_add);
EXPORT_SYMBOL_GPL(ata_host_detach);
EXPORT_SYMBOL_GPL(ata_sg_init);
EXPORT_SYMBOL_GPL(ata_sg_init_one);
@@ -6653,7 +6501,6 @@ EXPORT_SYMBOL_GPL(ata_timing_merge);
#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
EXPORT_SYMBOL_GPL(pci_configure_dma_masks);
-EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_native_host);
EXPORT_SYMBOL_GPL(ata_pci_prepare_native_host);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index d53b181..c29bdd5 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -533,101 +533,6 @@ static int ata_resources_present(struct pci_dev *pdev, int port)
}
/**
- * ata_pci_init_native_mode - Initialize native-mode driver
- * @pdev: pci device to be initialized
- * @port: array[2] of pointers to port info structures.
- * @ports: bitmap of ports present
- *
- * Utility function which allocates and initializes an
- * ata_probe_ent structure for a standard dual-port
- * PIO-based IDE controller. The returned ata_probe_ent
- * structure can be passed to ata_device_add(). The returned
- * ata_probe_ent structure should then be freed with kfree().
- *
- * The caller need only pass the address of the primary port, the
- * secondary will be deduced automatically. If the device has non
- * standard secondary port mappings this function can be called twice,
- * once for each interface.
- */
-
-struct ata_probe_ent *
-ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports)
-{
- struct ata_probe_ent *probe_ent;
- int i;
- void __iomem * const *iomap;
-
- /* Discard disabled ports. Some controllers show their unused
- * channels this way. Disabled ports will be made dummy.
- */
- if (ata_resources_present(pdev, 0) == 0)
- ports &= ~ATA_PORT_PRIMARY;
- if (ata_resources_present(pdev, 1) == 0)
- ports &= ~ATA_PORT_SECONDARY;
-
- if (!ports) {
- dev_printk(KERN_ERR, &pdev->dev, "no available port\n");
- return NULL;
- }
-
- /* iomap BARs */
- for (i = 0; i < 4; i++) {
- if (!(ports & (1 << (i / 2))))
- continue;
- if (pcim_iomap(pdev, i, 0) == NULL) {
- dev_printk(KERN_ERR, &pdev->dev,
- "failed to iomap PCI BAR %d\n", i);
- return NULL;
- }
- }
-
- pcim_iomap(pdev, 4, 0); /* may fail */
- iomap = pcim_iomap_table(pdev);
-
- /* alloc and init probe_ent */
- probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
- if (!probe_ent)
- return NULL;
-
- probe_ent->n_ports = 2;
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
-
- if (ports & ATA_PORT_PRIMARY) {
- probe_ent->port[0].cmd_addr = iomap[0];
- probe_ent->port[0].altstatus_addr =
- probe_ent->port[0].ctl_addr = (void __iomem *)
- ((unsigned long)iomap[1] | ATA_PCI_CTL_OFS);
- if (iomap[4]) {
- if ((!(port[0]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
- (ioread8(iomap[4] + 2) & 0x80))
- probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
- probe_ent->port[0].bmdma_addr = iomap[4];
- }
- ata_std_ports(&probe_ent->port[0]);
- } else
- probe_ent->dummy_port_mask |= ATA_PORT_PRIMARY;
-
- if (ports & ATA_PORT_SECONDARY) {
- probe_ent->port[1].cmd_addr = iomap[2];
- probe_ent->port[1].altstatus_addr =
- probe_ent->port[1].ctl_addr = (void __iomem *)
- ((unsigned long)iomap[3] | ATA_PCI_CTL_OFS);
- if (iomap[4]) {
- if ((!(port[1]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
- (ioread8(iomap[4] + 10) & 0x80))
- probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
- probe_ent->port[1].bmdma_addr = iomap[4] + 8;
- }
- ata_std_ports(&probe_ent->port[1]);
- probe_ent->pinfo2 = port[1];
- } else
- probe_ent->dummy_port_mask |= ATA_PORT_SECONDARY;
-
- return probe_ent;
-}
-
-/**
* ata_pci_init_bmdma - acquire PCI BMDMA resources and init ATA host
* @host: target ATA host
*
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 38949a2..242cc7f 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -93,8 +93,6 @@ extern int ata_flush_cache(struct ata_device *dev);
extern void ata_dev_init(struct ata_device *dev);
extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
-extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev,
- const struct ata_port_info *port);
extern struct ata_port *ata_port_alloc(struct ata_host *host);
/* libata-acpi.c */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 43d9356..1126184 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -366,34 +366,6 @@ struct ata_ioports {
void __iomem *scr_addr;
};
-struct ata_probe_ent {
- struct list_head node;
- struct device *dev;
- const struct ata_port_operations *port_ops;
- struct scsi_host_template *sht;
- struct ata_ioports port[ATA_MAX_PORTS];
- unsigned int n_ports;
- unsigned int dummy_port_mask;
- unsigned int pio_mask;
- unsigned int mwdma_mask;
- unsigned int udma_mask;
- unsigned long irq;
- unsigned long irq2;
- unsigned int irq_flags;
- unsigned long port_flags;
- unsigned long _host_flags;
- void __iomem * const *iomap;
- void *private_data;
-
- /* port_info for the secondary port. Together with irq2, it's
- * used to implement non-uniform secondary port. Currently,
- * the only user is ata_piix combined mode. This workaround
- * will be removed together with ata_probe_ent when init model
- * is updated.
- */
- const struct ata_port_info *pinfo2;
-};
-
struct ata_host {
spinlock_t lock;
struct device *dev;
@@ -739,7 +711,6 @@ extern int ata_host_attach(struct ata_host *host,
extern int ata_host_activate(struct ata_host *host, int irq,
irq_handler_t irq_handler, unsigned long irq_flags,
struct scsi_host_template *sht);
-extern int ata_device_add(const struct ata_probe_ent *ent);
extern void ata_host_detach(struct ata_host *host);
extern void ata_host_init(struct ata_host *, struct device *,
unsigned long, const struct ata_port_operations *);
@@ -881,8 +852,6 @@ struct pci_bits {
unsigned long val;
};
-extern struct ata_probe_ent *
-ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int portmask);
extern int ata_pci_init_native_host(struct ata_host *host,
unsigned int port_mask);
extern int ata_pci_prepare_native_host(struct pci_dev *pdev,
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 06/12] libata: convert native PCI host handling to new init model
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
` (7 preceding siblings ...)
2007-03-09 11:15 ` [PATCH 12/12] libata: kill probe_ent and related helpers Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
2007-03-09 15:45 ` Jeff Garzik
2007-03-09 11:15 ` [PATCH 08/12] libata: convert drivers with combined SATA/PATA ports " Tejun Heo
` (2 subsequent siblings)
11 siblings, 1 reply; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
Convert native PCI host handling to alloc-init-attach model. New
function ata_pci_init_native_host() follows the new init model and
replaces ata_pci_init_native_mode(). As there are remaining LLD
users, the old function isn't removed yet.
ata_pci_init_one() is reimplemented using the new function and now
fully converted to new init model.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/libata-core.c | 1 +
drivers/ata/libata-sff.c | 148 ++++++++++++++++++++++++++++++--------------
include/linux/libata.h | 2 +
3 files changed, 104 insertions(+), 47 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 97e7d9c..cf63651 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6649,6 +6649,7 @@ EXPORT_SYMBOL_GPL(ata_timing_merge);
EXPORT_SYMBOL_GPL(pci_test_config_bits);
EXPORT_SYMBOL_GPL(pci_configure_dma_masks);
EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
+EXPORT_SYMBOL_GPL(ata_pci_init_native_host);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
#ifdef CONFIG_PM
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 8287df5..f033e79 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -675,6 +675,70 @@ static int ata_pci_init_bmdma(struct ata_host *host)
return 0;
}
+/**
+ * ata_pci_init_native_host - acquire native ATA resources and init host
+ * @host: target ATA host
+ * @port_mask: ports to consider
+ *
+ * Acquire native PCI ATA resources for @host and initialize
+ * @host accordoingly.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask)
+{
+ struct device *gdev = host->dev;
+ struct pci_dev *pdev = to_pci_dev(gdev);
+ int i, rc;
+
+ /* Discard disabled ports. Some controllers show their unused
+ * channels this way. Disabled ports are made dummy.
+ */
+ for (i = 0; i < 2; i++) {
+ if ((port_mask & (1 << i)) && !ata_resources_present(pdev, i)) {
+ host->ports[i]->ops = &ata_dummy_port_ops;
+ port_mask &= ~(1 << i);
+ }
+ }
+
+ if (!port_mask) {
+ dev_printk(KERN_ERR, gdev, "no available port\n");
+ return -ENODEV;
+ }
+
+ /* request, iomap BARs and init port addresses accordingly */
+ for (i = 0; i < 2; i++) {
+ struct ata_port *ap = host->ports[i];
+ int base = i * 2;
+ void __iomem * const *iomap;
+
+ if (!(port_mask & (1 << i)))
+ continue;
+
+ rc = pcim_iomap_regions(pdev, 0x3 << base, DRV_NAME);
+ if (rc) {
+ dev_printk(KERN_ERR, gdev, "failed to request/iomap "
+ "BARs for port %d (errno=%d)\n", i, rc);
+ if (rc == -EBUSY)
+ pcim_pin_device(pdev);
+ return rc;
+ }
+ host->iomap = iomap = pcim_iomap_table(pdev);
+
+ ap->ioaddr.cmd_addr = iomap[base];
+ ap->ioaddr.altstatus_addr =
+ ap->ioaddr.ctl_addr = (void __iomem *)
+ ((unsigned long)iomap[base + 1] | ATA_PCI_CTL_OFS);
+ ata_std_ports(&ap->ioaddr);
+ }
+
+ return 0;
+}
+
struct ata_legacy_devres {
unsigned int mask;
unsigned long cmd_port[2];
@@ -929,7 +993,6 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
unsigned int n_ports)
{
struct device *dev = &pdev->dev;
- struct ata_probe_ent *probe_ent = NULL;
struct ata_host *host = NULL;
const struct ata_port_info *port[2];
u8 mask;
@@ -955,7 +1018,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
Checking dev->is_enabled is insufficient as this is not set at
boot for the primary video which is BIOS enabled
- */
+ */
rc = pcim_enable_device(pdev);
if (rc)
@@ -981,27 +1044,28 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
#endif
}
+ /* alloc and init host */
+ host = ata_host_alloc_pinfo(dev, port, 2);
+ if (!host) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "failed to allocate ATA host\n");
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
if (!legacy_mode) {
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc) {
- pcim_pin_device(pdev);
- goto err_out;
- }
+ unsigned int port_mask;
+
+ port_mask = ATA_PORT_PRIMARY;
+ if (n_ports > 1)
+ port_mask |= ATA_PORT_SECONDARY;
- /* TODO: If we get no DMA mask we should fall back to PIO */
- rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
+ rc = ata_pci_init_native_host(host, port_mask);
if (rc)
goto err_out;
-
- pci_set_master(pdev);
} else {
int was_busy = 0;
- rc = -ENOMEM;
- host = ata_host_alloc_pinfo(dev, port, 2);
- if (!host)
- goto err_out;
-
rc = ata_init_legacy_host(host, &legacy_mode, &was_busy);
if (was_busy)
pcim_pin_device(pdev);
@@ -1011,47 +1075,37 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
/* request respective PCI regions, may fail */
rc = pci_request_region(pdev, 1, DRV_NAME);
rc = pci_request_region(pdev, 3, DRV_NAME);
-
- /* init bmdma */
- ata_pci_init_bmdma(host);
- pci_set_master(pdev);
}
- if (legacy_mode) {
+ /* init BMDMA, may fail */
+ ata_pci_init_bmdma(host);
+ pci_set_master(pdev);
+
+ /* start host and request IRQ */
+ rc = ata_host_start(host);
+ if (rc)
+ goto err_out;
+
+ if (!legacy_mode)
+ rc = devm_request_irq(dev, pdev->irq,
+ port_info[0]->port_ops->irq_handler,
+ IRQF_SHARED, DRV_NAME, host);
+ else {
irq_handler_t handler[2] = { host->ops->irq_handler,
host->ops->irq_handler };
unsigned int irq_flags[2] = { IRQF_SHARED, IRQF_SHARED };
void *dev_id[2] = { host, host };
- rc = ata_host_start(host);
- if (rc)
- goto err_out;
-
rc = ata_request_legacy_irqs(host, handler, irq_flags, dev_id);
- if (rc)
- goto err_out;
-
- rc = ata_host_attach(host, port_info[0]->sht);
- if (rc)
- goto err_out;
- } else {
- if (n_ports == 2)
- probe_ent = ata_pci_init_native_mode(pdev, (struct ata_port_info **)port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
- else
- probe_ent = ata_pci_init_native_mode(pdev, (struct ata_port_info **)port, ATA_PORT_PRIMARY);
-
- if (!probe_ent) {
- rc = -ENOMEM;
- goto err_out;
- }
+ }
+ if (rc)
+ goto err_out;
- if (!ata_device_add(probe_ent)) {
- rc = -ENODEV;
- goto err_out;
- }
+ /* attach */
+ rc = ata_host_attach(host, port_info[0]->sht);
+ if (rc)
+ goto err_out;
- devm_kfree(dev, probe_ent);
- }
devres_remove_group(dev, NULL);
return 0;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 202ed7a..7aa6085 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -881,6 +881,8 @@ struct pci_bits {
extern struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int portmask);
+extern int ata_pci_init_native_host(struct ata_host *host,
+ unsigned int port_mask);
extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
extern int pci_configure_dma_masks(struct pci_dev *pdev, u64 dma_mask,
u64 *configured_mask);
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 08/12] libata: convert drivers with combined SATA/PATA ports to new init model
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
` (8 preceding siblings ...)
2007-03-09 11:15 ` [PATCH 06/12] libata: convert native PCI host handling to new init model Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
2007-03-09 12:46 ` Alan Cox
2007-03-09 11:15 ` [PATCH 07/12] libata: add init helpers including ata_pci_prepare_native_host() Tejun Heo
2007-03-09 11:15 ` [PATCH 10/12] libata: convert the remaining SATA drivers to new init model Tejun Heo
11 siblings, 1 reply; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
Convert sata_via and sata_promise to nwe init model. Both controllers
can have combined configuration (SATA + PATA) and used twisted
initialization method (modifying port in ->port_start) to overcome
probe_ent limitations.
This patch converts both drivers to new init model in which such
configuration is natively supported.
* promise: Combined pata port now uses separate port_info entry right
after the sata counterpart entry.
* promise: Controller configuration is discerned using ap->flags.
This simplifies init path and makes it look more like other LLDs.
* promise: SATA/PATA branches are converted into separate ops.
Remaining ones are converted to more standard ap->cbl ==
ATA_CBL_SATA check.
* via: Both SATA and PATA ports in vt6421 are represented int their
own port_info structure.
Tested on PDC20375 (SATA150 TX2plus) [105a:3375] and PDC40775 (SATA
300 TX2plus) [105a:3d73]. Couldn't test via cuz my c3 won't boot the
current kernel.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/sata_promise.c | 278 +++++++++++++++++++------------------------
drivers/ata/sata_via.c | 172 ++++++++++++----------------
2 files changed, 196 insertions(+), 254 deletions(-)
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 71a05ad..2ca2e1c 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -49,6 +49,7 @@
enum {
+ PDC_MAX_PORTS = 4,
PDC_MMIO_BAR = 3,
/* register offsets */
@@ -74,10 +75,12 @@ enum {
(1<<8) | (1<<9) | (1<<10),
board_2037x = 0, /* FastTrak S150 TX2plus */
- board_20319 = 1, /* FastTrak S150 TX4 */
- board_20619 = 2, /* FastTrak TX4000 */
- board_2057x = 3, /* SATAII150 Tx2plus */
- board_40518 = 4, /* SATAII150 Tx4 */
+ board_2037x_pata = 1, /* FastTrak S150 TX2plus PATA port */
+ board_20319 = 2, /* FastTrak S150 TX4 */
+ board_20619 = 3, /* FastTrak TX4000 */
+ board_2057x = 4, /* SATAII150 Tx2plus */
+ board_2057x_pata = 5, /* SATAII150 Tx2plus */
+ board_40518 = 6, /* SATAII150 Tx4 */
PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */
@@ -100,8 +103,10 @@ enum {
ATA_FLAG_MMIO |
ATA_FLAG_PIO_POLLING,
- /* hp->flags bits */
- PDC_FLAG_GEN_II = (1 << 0),
+ /* ap->flags bits */
+ PDC_FLAG_GEN_II = (1 << 24),
+ PDC_FLAG_SATA_PATA = (1 << 25), /* supports SATA + PATA */
+ PDC_FLAG_4_PORTS = (1 << 26), /* 4 ports */
};
@@ -110,26 +115,21 @@ struct pdc_port_priv {
dma_addr_t pkt_dma;
};
-struct pdc_host_priv {
- unsigned long flags;
- unsigned long port_flags[ATA_MAX_PORTS];
-};
-
static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static irqreturn_t pdc_interrupt (int irq, void *dev_instance);
static int pdc_port_start(struct ata_port *ap);
static void pdc_qc_prep(struct ata_queued_cmd *qc);
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
static int pdc_check_atapi_dma(struct ata_queued_cmd *qc);
-static int pdc_old_check_atapi_dma(struct ata_queued_cmd *qc);
+static int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc);
static void pdc_irq_clear(struct ata_port *ap);
static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
static void pdc_freeze(struct ata_port *ap);
static void pdc_thaw(struct ata_port *ap);
-static void pdc_error_handler(struct ata_port *ap);
+static void pdc_sata_error_handler(struct ata_port *ap);
+static void pdc_pata_error_handler(struct ata_port *ap);
static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
@@ -164,10 +164,9 @@ static const struct ata_port_operations pdc_sata_ops = {
.qc_issue = pdc_qc_issue_prot,
.freeze = pdc_freeze,
.thaw = pdc_thaw,
- .error_handler = pdc_error_handler,
+ .error_handler = pdc_sata_error_handler,
.post_internal_cmd = pdc_post_internal_cmd,
.data_xfer = ata_data_xfer,
- .irq_handler = pdc_interrupt,
.irq_clear = pdc_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -185,16 +184,15 @@ static const struct ata_port_operations pdc_old_sata_ops = {
.check_status = ata_check_status,
.exec_command = pdc_exec_command_mmio,
.dev_select = ata_std_dev_select,
- .check_atapi_dma = pdc_old_check_atapi_dma,
+ .check_atapi_dma = pdc_old_sata_check_atapi_dma,
.qc_prep = pdc_qc_prep,
.qc_issue = pdc_qc_issue_prot,
.freeze = pdc_freeze,
.thaw = pdc_thaw,
- .error_handler = pdc_error_handler,
+ .error_handler = pdc_sata_error_handler,
.post_internal_cmd = pdc_post_internal_cmd,
.data_xfer = ata_data_xfer,
- .irq_handler = pdc_interrupt,
.irq_clear = pdc_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -217,10 +215,9 @@ static const struct ata_port_operations pdc_pata_ops = {
.qc_issue = pdc_qc_issue_prot,
.freeze = pdc_freeze,
.thaw = pdc_thaw,
- .error_handler = pdc_error_handler,
+ .error_handler = pdc_pata_error_handler,
.post_internal_cmd = pdc_post_internal_cmd,
.data_xfer = ata_data_xfer,
- .irq_handler = pdc_interrupt,
.irq_clear = pdc_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -231,18 +228,27 @@ static const struct ata_port_operations pdc_pata_ops = {
static const struct ata_port_info pdc_port_info[] = {
/* board_2037x */
{
- .sht = &pdc_ata_sht,
- .flags = PDC_COMMON_FLAGS,
+ .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
+ PDC_FLAG_SATA_PATA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_old_sata_ops,
},
+ /* board_2037x_pata */
+ {
+ .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .port_ops = &pdc_pata_ops,
+ },
+
/* board_20319 */
{
- .sht = &pdc_ata_sht,
- .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+ .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
+ PDC_FLAG_4_PORTS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
@@ -251,8 +257,8 @@ static const struct ata_port_info pdc_port_info[] = {
/* board_20619 */
{
- .sht = &pdc_ata_sht,
- .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
+ .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS |
+ PDC_FLAG_4_PORTS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
@@ -261,18 +267,28 @@ static const struct ata_port_info pdc_port_info[] = {
/* board_2057x */
{
- .sht = &pdc_ata_sht,
- .flags = PDC_COMMON_FLAGS,
+ .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
+ PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_sata_ops,
},
+ /* board_2057x_pata */
+ {
+ .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
+ PDC_FLAG_GEN_II,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .port_ops = &pdc_pata_ops,
+ },
+
/* board_40518 */
{
- .sht = &pdc_ata_sht,
- .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+ .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA |
+ PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
@@ -316,15 +332,10 @@ static struct pci_driver pdc_ata_pci_driver = {
static int pdc_port_start(struct ata_port *ap)
{
struct device *dev = ap->host->dev;
- struct pdc_host_priv *hp = ap->host->private_data;
struct pdc_port_priv *pp;
int rc;
/* fix up port flags and cable type for SATA+PATA chips */
- ap->flags |= hp->port_flags[ap->port_no];
- if (ap->flags & ATA_FLAG_SATA)
- ap->cbl = ATA_CBL_SATA;
-
rc = ata_port_start(ap);
if (rc)
return rc;
@@ -340,7 +351,7 @@ static int pdc_port_start(struct ata_port *ap)
ap->private_data = pp;
/* fix up PHYMODE4 align timing */
- if ((hp->flags & PDC_FLAG_GEN_II) && sata_scr_valid(ap)) {
+ if ((ap->flags & PDC_FLAG_GEN_II) && (ap->cbl == ATA_CBL_SATA)) {
void __iomem *mmio = (void __iomem *) ap->ioaddr.scr_addr;
unsigned int tmp;
@@ -390,7 +401,7 @@ static void pdc_pata_cbl_detect(struct ata_port *ap)
static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
- if (sc_reg > SCR_CONTROL || ap->cbl != ATA_CBL_SATA)
+ if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -399,7 +410,7 @@ static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
u32 val)
{
- if (sc_reg > SCR_CONTROL || ap->cbl != ATA_CBL_SATA)
+ if (sc_reg > SCR_CONTROL)
return;
writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -436,7 +447,7 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
buf32[2] = 0; /* no next-packet */
/* select drive */
- if (sata_scr_valid(ap)) {
+ if (ap->cbl == ATA_CBL_SATA) {
dev_sel = PDC_DEVICE_SATA;
} else {
dev_sel = ATA_DEVICE_OBS;
@@ -555,26 +566,27 @@ static void pdc_thaw(struct ata_port *ap)
readl(mmio + PDC_CTLSTAT); /* flush */
}
-static int pdc_pre_reset(struct ata_port *ap)
+static void pdc_sata_error_handler(struct ata_port *ap)
{
- if (!sata_scr_valid(ap))
- pdc_pata_cbl_detect(ap);
- return ata_std_prereset(ap);
+ if (!(ap->pflags & ATA_PFLAG_FROZEN))
+ pdc_reset_port(ap);
+
+ ata_bmdma_error_handler(ap);
}
-static void pdc_error_handler(struct ata_port *ap)
+static int pdc_pata_prereset(struct ata_port *ap)
{
- ata_reset_fn_t hardreset;
+ pdc_pata_cbl_detect(ap);
+ return ata_std_prereset(ap);
+}
+
+static void pdc_pata_error_handler(struct ata_port *ap)
+{
if (!(ap->pflags & ATA_PFLAG_FROZEN))
pdc_reset_port(ap);
- hardreset = NULL;
- if (sata_scr_valid(ap))
- hardreset = sata_std_hardreset;
-
- /* perform recovery */
- ata_do_eh(ap, pdc_pre_reset, ata_std_softreset, hardreset,
+ ata_do_eh(ap, pdc_pata_prereset, ata_std_softreset, NULL,
ata_std_postreset);
}
@@ -767,44 +779,40 @@ static int pdc_check_atapi_dma(struct ata_queued_cmd *qc)
return pio;
}
-static int pdc_old_check_atapi_dma(struct ata_queued_cmd *qc)
+static int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc)
{
- struct ata_port *ap = qc->ap;
-
/* First generation chips cannot use ATAPI DMA on SATA ports */
- if (sata_scr_valid(ap))
- return 1;
- return pdc_check_atapi_dma(qc);
+ return 1;
}
-static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base,
- void __iomem *scr_addr)
+static void pdc_ata_setup_port(struct ata_port *ap,
+ void __iomem *base, void __iomem *scr_addr)
{
- port->cmd_addr = base;
- port->data_addr = base;
- port->feature_addr =
- port->error_addr = base + 0x4;
- port->nsect_addr = base + 0x8;
- port->lbal_addr = base + 0xc;
- port->lbam_addr = base + 0x10;
- port->lbah_addr = base + 0x14;
- port->device_addr = base + 0x18;
- port->command_addr =
- port->status_addr = base + 0x1c;
- port->altstatus_addr =
- port->ctl_addr = base + 0x38;
- port->scr_addr = scr_addr;
+ ap->ioaddr.cmd_addr = base;
+ ap->ioaddr.data_addr = base;
+ ap->ioaddr.feature_addr =
+ ap->ioaddr.error_addr = base + 0x4;
+ ap->ioaddr.nsect_addr = base + 0x8;
+ ap->ioaddr.lbal_addr = base + 0xc;
+ ap->ioaddr.lbam_addr = base + 0x10;
+ ap->ioaddr.lbah_addr = base + 0x14;
+ ap->ioaddr.device_addr = base + 0x18;
+ ap->ioaddr.command_addr =
+ ap->ioaddr.status_addr = base + 0x1c;
+ ap->ioaddr.altstatus_addr =
+ ap->ioaddr.ctl_addr = base + 0x38;
+ ap->ioaddr.scr_addr = scr_addr;
}
-static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
+static void pdc_host_init(struct ata_host *host)
{
- void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
- struct pdc_host_priv *hp = pe->private_data;
+ void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
+ int is_gen2 = host->ports[0]->flags & PDC_FLAG_GEN_II;
int hotplug_offset;
u32 tmp;
- if (hp->flags & PDC_FLAG_GEN_II)
+ if (is_gen2)
hotplug_offset = PDC2_SATA_PLUG_CSR;
else
hotplug_offset = PDC_SATA_PLUG_CSR;
@@ -818,7 +826,7 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
/* enable BMR_BURST, maybe change FIFO_SHD to 8 dwords */
tmp = readl(mmio + PDC_FLASH_CTL);
tmp |= 0x02000; /* bit 13 (enable bmr burst) */
- if (!(hp->flags & PDC_FLAG_GEN_II))
+ if (!is_gen2)
tmp |= 0x10000; /* bit 16 (fifo threshold at 8 dw) */
writel(tmp, mmio + PDC_FLASH_CTL);
@@ -831,7 +839,7 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
writel(tmp | 0xff0000, mmio + hotplug_offset);
/* don't initialise TBG or SLEW on 2nd generation chips */
- if (hp->flags & PDC_FLAG_GEN_II)
+ if (is_gen2)
return;
/* reduce TBG clock to 133 Mhz. */
@@ -853,16 +861,16 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
- struct ata_probe_ent *probe_ent;
- struct pdc_host_priv *hp;
+ const struct ata_port_info *pi = &pdc_port_info[ent->driver_data];
+ const struct ata_port_info *ppi[PDC_MAX_PORTS];
+ struct ata_host *host;
void __iomem *base;
- unsigned int board_idx = (unsigned int) ent->driver_data;
- int rc;
- u8 tmp;
+ int n_ports, i, rc;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ /* enable and acquire resources */
rc = pcim_enable_device(pdev);
if (rc)
return rc;
@@ -872,86 +880,46 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
pcim_pin_device(pdev);
if (rc)
return rc;
+ base = pcim_iomap_table(pdev)[PDC_MMIO_BAR];
- rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
- if (rc)
- return rc;
-
- probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
- if (probe_ent == NULL)
- return -ENOMEM;
+ /* determine port configuration and setup host */
+ n_ports = 2;
+ if (pi->flags & PDC_FLAG_4_PORTS)
+ n_ports = 4;
+ for (i = 0; i < n_ports; i++)
+ ppi[i] = pi;
- probe_ent->dev = pci_dev_to_dev(pdev);
- INIT_LIST_HEAD(&probe_ent->node);
+ if (pi->flags & PDC_FLAG_SATA_PATA) {
+ u8 tmp = readb(base + PDC_FLASH_CTL+1);
+ if (!(tmp & 0x80)) {
+ ppi[n_ports++] = pi + 1;
+ dev_printk(KERN_INFO, &pdev->dev, "PATA port found\n");
+ }
+ }
- hp = devm_kzalloc(&pdev->dev, sizeof(*hp), GFP_KERNEL);
- if (hp == NULL)
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
+ if (!host) {
+ dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host\n");
return -ENOMEM;
-
- probe_ent->private_data = hp;
-
- probe_ent->sht = pdc_port_info[board_idx].sht;
- probe_ent->port_flags = pdc_port_info[board_idx].flags;
- probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask;
- probe_ent->mwdma_mask = pdc_port_info[board_idx].mwdma_mask;
- probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask;
- probe_ent->port_ops = pdc_port_info[board_idx].port_ops;
-
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->iomap = pcim_iomap_table(pdev);
-
- base = probe_ent->iomap[PDC_MMIO_BAR];
-
- pdc_ata_setup_port(&probe_ent->port[0], base + 0x200, base + 0x400);
- pdc_ata_setup_port(&probe_ent->port[1], base + 0x280, base + 0x500);
-
- /* notice 4-port boards */
- switch (board_idx) {
- case board_40518:
- hp->flags |= PDC_FLAG_GEN_II;
- /* Fall through */
- case board_20319:
- probe_ent->n_ports = 4;
- pdc_ata_setup_port(&probe_ent->port[2], base + 0x300, base + 0x600);
- pdc_ata_setup_port(&probe_ent->port[3], base + 0x380, base + 0x700);
- break;
- case board_2057x:
- hp->flags |= PDC_FLAG_GEN_II;
- /* Fall through */
- case board_2037x:
- /* TX2plus boards also have a PATA port */
- tmp = readb(base + PDC_FLASH_CTL+1);
- if (!(tmp & 0x80)) {
- probe_ent->n_ports = 3;
- pdc_ata_setup_port(&probe_ent->port[2], base + 0x300, NULL);
- hp->port_flags[2] = ATA_FLAG_SLAVE_POSS;
- printk(KERN_INFO DRV_NAME " PATA port found\n");
- } else
- probe_ent->n_ports = 2;
- hp->port_flags[0] = ATA_FLAG_SATA;
- hp->port_flags[1] = ATA_FLAG_SATA;
- break;
- case board_20619:
- probe_ent->n_ports = 4;
- pdc_ata_setup_port(&probe_ent->port[2], base + 0x300, NULL);
- pdc_ata_setup_port(&probe_ent->port[3], base + 0x380, NULL);
- break;
- default:
- BUG();
- break;
}
+ host->iomap = pcim_iomap_table(pdev);
- pci_set_master(pdev);
+ for (i = 0; i < host->n_ports; i++)
+ pdc_ata_setup_port(host->ports[i],
+ base + 0x200 + i * 0x80,
+ base + 0x400 + i * 0x100);
/* initialize adapter */
- pdc_host_init(board_idx, probe_ent);
+ pdc_host_init(host);
- if (!ata_device_add(probe_ent))
- return -ENODEV;
+ rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
+ if (rc)
+ return rc;
- devm_kfree(&pdev->dev, probe_ent);
- return 0;
+ /* start host, request IRQ and attach */
+ pci_set_master(pdev);
+ return ata_host_activate(host, pdev->irq, pdc_interrupt, IRQF_SHARED,
+ &pdc_ata_sht);
}
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 1b43062..267193d 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -64,8 +64,6 @@ enum {
PORT0 = (1 << 1),
PORT1 = (1 << 0),
ALL_PORTS = PORT0 | PORT1,
- PATA_PORT = 2, /* PATA is port 2 */
- N_PORTS = 3,
NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
@@ -82,7 +80,6 @@ static void vt6421_sata_error_handler(struct ata_port *ap);
static void vt6421_pata_error_handler(struct ata_port *ap);
static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev);
static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev);
-static int vt6421_port_start(struct ata_port *ap);
static const struct pci_device_id svia_pci_tbl[] = {
{ PCI_VDEVICE(VIA, 0x5337), vt6420 },
@@ -141,7 +138,6 @@ static const struct ata_port_operations vt6420_sata_ops = {
.error_handler = vt6420_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -175,12 +171,11 @@ static const struct ata_port_operations vt6421_pata_ops = {
.error_handler = vt6421_pata_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
- .port_start = vt6421_port_start,
+ .port_start = ata_port_start,
};
static const struct ata_port_operations vt6421_sata_ops = {
@@ -206,7 +201,6 @@ static const struct ata_port_operations vt6421_sata_ops = {
.error_handler = vt6421_sata_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -214,11 +208,10 @@ static const struct ata_port_operations vt6421_sata_ops = {
.scr_read = svia_scr_read,
.scr_write = svia_scr_write,
- .port_start = vt6421_port_start,
+ .port_start = ata_port_start,
};
-static struct ata_port_info vt6420_port_info = {
- .sht = &svia_sht,
+static const struct ata_port_info vt6420_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
@@ -226,6 +219,22 @@ static struct ata_port_info vt6420_port_info = {
.port_ops = &vt6420_sata_ops,
};
+static struct ata_port_info vt6421_sport_info = {
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f,
+ .port_ops = &vt6421_sata_ops,
+};
+
+static struct ata_port_info vt6421_pport_info = {
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0,
+ .udma_mask = 0x7f,
+ .port_ops = &vt6421_pata_ops,
+};
+
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
MODULE_LICENSE("GPL");
@@ -375,16 +384,6 @@ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev)
pci_write_config_byte(pdev, PATA_UDMA_TIMING, udma_bits[adev->pio_mode - XFER_UDMA_0]);
}
-static int vt6421_port_start(struct ata_port *ap)
-{
- if (ap->port_no == PATA_PORT) {
- ap->ops = &vt6421_pata_ops;
- ap->mwdma_mask = 0;
- ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST;
- }
- return ata_port_start(ap);
-}
-
static const unsigned int svia_bar_sizes[] = {
8, 4, 8, 4, 16, 256
};
@@ -403,79 +402,71 @@ static void __iomem * vt6421_scr_addr(void __iomem *addr, unsigned int port)
return addr + (port * 64);
}
-static void vt6421_init_addrs(struct ata_probe_ent *probe_ent,
- void __iomem * const *iomap, unsigned int port)
+static void vt6421_init_addrs(struct ata_port *ap)
{
- void __iomem *reg_addr = iomap[port];
- void __iomem *bmdma_addr = iomap[4] + (port * 8);
-
- probe_ent->port[port].cmd_addr = reg_addr;
- probe_ent->port[port].altstatus_addr =
- probe_ent->port[port].ctl_addr = (void __iomem *)
+ void __iomem * const * iomap = ap->host->iomap;
+ void __iomem *reg_addr = iomap[ap->port_no];
+ void __iomem *bmdma_addr = iomap[4] + (ap->port_no * 8);
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+
+ ioaddr->cmd_addr = reg_addr;
+ ioaddr->altstatus_addr =
+ ioaddr->ctl_addr = (void __iomem *)
((unsigned long)(reg_addr + 8) | ATA_PCI_CTL_OFS);
- probe_ent->port[port].bmdma_addr = bmdma_addr;
- probe_ent->port[port].scr_addr = vt6421_scr_addr(iomap[5], port);
+ ioaddr->bmdma_addr = bmdma_addr;
+ ioaddr->scr_addr = vt6421_scr_addr(iomap[5], ap->port_no);
- ata_std_ports(&probe_ent->port[port]);
+ ata_std_ports(ioaddr);
}
-static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
+static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
{
- struct ata_probe_ent *probe_ent;
- struct ata_port_info *ppi[2];
- void __iomem *bar5;
+ const struct ata_port_info *ppi[] = { &vt6420_port_info, NULL };
+ struct ata_host *host;
+ int rc;
- ppi[0] = ppi[1] = &vt6420_port_info;
- probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
- if (!probe_ent)
- return NULL;
+ rc = ata_pci_prepare_native_host(pdev, ppi, 2, &host);
+ if (rc)
+ return rc;
+ *r_host = host;
- bar5 = pcim_iomap(pdev, 5, 0);
- if (!bar5) {
+ rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
+ if (rc) {
dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n");
- return NULL;
+ return rc;
}
- probe_ent->port[0].scr_addr = svia_scr_addr(bar5, 0);
- probe_ent->port[1].scr_addr = svia_scr_addr(bar5, 1);
+ host->ports[0]->ioaddr.scr_addr = svia_scr_addr(host->iomap[5], 0);
+ host->ports[1]->ioaddr.scr_addr = svia_scr_addr(host->iomap[5], 1);
- return probe_ent;
+ return 0;
}
-static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
+static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
{
- struct ata_probe_ent *probe_ent;
- unsigned int i;
+ const struct ata_port_info *ppi[] =
+ { &vt6421_sport_info, &vt6421_sport_info, &vt6421_pport_info };
+ struct ata_host *host;
+ int i, rc;
+
+ *r_host = host = ata_host_alloc_pinfo(&pdev->dev, ppi, ARRAY_SIZE(ppi));
+ if (!host) {
+ dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host\n");
+ return -ENOMEM;
+ }
- probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
- if (!probe_ent)
- return NULL;
-
- memset(probe_ent, 0, sizeof(*probe_ent));
- probe_ent->dev = pci_dev_to_dev(pdev);
- INIT_LIST_HEAD(&probe_ent->node);
-
- probe_ent->sht = &svia_sht;
- probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY;
- probe_ent->port_ops = &vt6421_sata_ops;
- probe_ent->n_ports = N_PORTS;
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->pio_mask = 0x1f;
- probe_ent->mwdma_mask = 0x07;
- probe_ent->udma_mask = 0x7f;
-
- for (i = 0; i < 6; i++)
- if (!pcim_iomap(pdev, i, 0)) {
- dev_printk(KERN_ERR, &pdev->dev,
- "failed to iomap PCI BAR %d\n", i);
- return NULL;
- }
+ rc = pcim_iomap_regions(pdev, 0x1f, DRV_NAME);
+ if (rc) {
+ dev_printk(KERN_ERR, &pdev->dev, "failed to request/iomap "
+ "PCI BARs (errno=%d)\n", rc);
+ return rc;
+ }
+ host->iomap = pcim_iomap_table(pdev);
- for (i = 0; i < N_PORTS; i++)
- vt6421_init_addrs(probe_ent, pcim_iomap_table(pdev), i);
+ for (i = 0; i < host->n_ports; i++)
+ vt6421_init_addrs(host->ports[i]);
- return probe_ent;
+ return pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
}
static void svia_configure(struct pci_dev *pdev)
@@ -522,7 +513,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static int printed_version;
unsigned int i;
int rc;
- struct ata_probe_ent *probe_ent;
+ struct ata_host *host;
int board_id = (int) ent->driver_data;
const int *bar_sizes;
u8 tmp8;
@@ -534,12 +525,6 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
return rc;
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc) {
- pcim_pin_device(pdev);
- return rc;
- }
-
if (board_id == vt6420) {
pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
if (tmp8 & SATA_2DEV) {
@@ -565,29 +550,18 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENODEV;
}
- rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
- if (rc)
- return rc;
-
if (board_id == vt6420)
- probe_ent = vt6420_init_probe_ent(pdev);
+ rc = vt6420_prepare_host(pdev, &host);
else
- probe_ent = vt6421_init_probe_ent(pdev);
-
- if (!probe_ent) {
- dev_printk(KERN_ERR, &pdev->dev, "out of memory\n");
- return -ENOMEM;
- }
+ rc = vt6421_prepare_host(pdev, &host);
+ if (rc)
+ return rc;
svia_configure(pdev);
pci_set_master(pdev);
-
- if (!ata_device_add(probe_ent))
- return -ENODEV;
-
- devm_kfree(&pdev->dev, probe_ent);
- return 0;
+ return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+ &svia_sht);
}
static int __init svia_init(void)
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH 08/12] libata: convert drivers with combined SATA/PATA ports to new init model
2007-03-09 11:15 ` [PATCH 08/12] libata: convert drivers with combined SATA/PATA ports " Tejun Heo
@ 2007-03-09 12:46 ` Alan Cox
2007-03-09 11:55 ` Jeff Garzik
0 siblings, 1 reply; 27+ messages in thread
From: Alan Cox @ 2007-03-09 12:46 UTC (permalink / raw)
To: Tejun Heo; +Cc: jeff, linux-ide
> * promise: SATA/PATA branches are converted into separate ops.
> Remaining ones are converted to more standard ap->cbl ==
> ATA_CBL_SATA check.
NAK this specifically
I've got some pending and needed patches to spot where drives report SATA
and the host is doing PATA cables. This is needed for various warped PATA
controller and glue variants and means that the PATA port probe may end
up returning with ap->cbl == ATA_CBL_SATA if it finds SATA devices on a
supposedly PATA port.
Alan
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 08/12] libata: convert drivers with combined SATA/PATA ports to new init model
2007-03-09 12:46 ` Alan Cox
@ 2007-03-09 11:55 ` Jeff Garzik
2007-03-09 13:04 ` Tejun Heo
0 siblings, 1 reply; 27+ messages in thread
From: Jeff Garzik @ 2007-03-09 11:55 UTC (permalink / raw)
To: Alan Cox, Tejun Heo; +Cc: linux-ide
Alan Cox wrote:
>> * promise: SATA/PATA branches are converted into separate ops.
>> Remaining ones are converted to more standard ap->cbl ==
>> ATA_CBL_SATA check.
>
> NAK this specifically
>
> I've got some pending and needed patches to spot where drives report SATA
> and the host is doing PATA cables. This is needed for various warped PATA
> controller and glue variants and means that the PATA port probe may end
> up returning with ap->cbl == ATA_CBL_SATA if it finds SATA devices on a
> supposedly PATA port.
Indeed.
With the new init model, testing for ATA_FLAG_SATA should be the
preferred test, as it makes all the mixed PATA/SATA ->port_start hackery
and tests go away.
With the new init model, the LLDD and core should now /always/ know
whether the port is PATA or SATA. The LLDD will set it up that way.
Now that different ->ops for PATA and SATA is supported (with Tejun's
patches), I would expect the number of "is this port SATA?" tests to
drop dramatically, for reasons mentioned in the previous paragraph and
also because you can create separate hooks for PATA and SATA that
permits the killing of "is this SATA?" or "is this PATA?" tests.
Jeff
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 08/12] libata: convert drivers with combined SATA/PATA ports to new init model
2007-03-09 11:55 ` Jeff Garzik
@ 2007-03-09 13:04 ` Tejun Heo
0 siblings, 0 replies; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 13:04 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Alan Cox, linux-ide
Jeff Garzik wrote:
> Alan Cox wrote:
>>> * promise: SATA/PATA branches are converted into separate ops.
>>> Remaining ones are converted to more standard ap->cbl ==
>>> ATA_CBL_SATA check.
>>
>> NAK this specifically
>>
>> I've got some pending and needed patches to spot where drives report SATA
>> and the host is doing PATA cables. This is needed for various warped PATA
>> controller and glue variants and means that the PATA port probe may end
>> up returning with ap->cbl == ATA_CBL_SATA if it finds SATA devices on a
>> supposedly PATA port.
>
> Indeed.
>
> With the new init model, testing for ATA_FLAG_SATA should be the
> preferred test, as it makes all the mixed PATA/SATA ->port_start hackery
> and tests go away.
>
> With the new init model, the LLDD and core should now /always/ know
> whether the port is PATA or SATA. The LLDD will set it up that way.
>
> Now that different ->ops for PATA and SATA is supported (with Tejun's
> patches), I would expect the number of "is this port SATA?" tests to
> drop dramatically, for reasons mentioned in the previous paragraph and
> also because you can create separate hooks for PATA and SATA that
> permits the killing of "is this SATA?" or "is this PATA?" tests.
I see. I'll drop that part.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 07/12] libata: add init helpers including ata_pci_prepare_native_host()
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
` (9 preceding siblings ...)
2007-03-09 11:15 ` [PATCH 08/12] libata: convert drivers with combined SATA/PATA ports " Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
2007-03-09 11:15 ` [PATCH 10/12] libata: convert the remaining SATA drivers to new init model Tejun Heo
11 siblings, 0 replies; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
These will be used to convert LLDs to new init model.
* Add irq_handler field to port_info. In new init model, requesting
IRQ is LLD's responsibility and libata doesn't need to know about
irq_handler. Most LLDs can simply register their irq_handler but
some need different irq_handler depending on specific chip. The
added port_info->irq_handler field can be used by LLDs to select
the matching IRQ handler in such cases.
* Add ata_dummy_port_info.
* Implement ata_pci_prepare_native_host(), a helper to alloc ATA host,
acquire all resources and init the host in one go.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/libata-core.c | 6 ++++
drivers/ata/libata-sff.c | 67 +++++++++++++++++++++++++++++++++++++++++++-
include/linux/libata.h | 5 +++
3 files changed, 76 insertions(+), 2 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index cf63651..4d371fb 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6546,6 +6546,10 @@ const struct ata_port_operations ata_dummy_port_ops = {
.port_stop = ata_dummy_noret,
};
+const struct ata_port_info ata_dummy_port_info = {
+ .port_ops = &ata_dummy_port_ops,
+};
+
/*
* libata is essentially a library of internal helper functions for
* low-level ATA host controller drivers. As such, the API/ABI is
@@ -6557,6 +6561,7 @@ EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
EXPORT_SYMBOL_GPL(sata_deb_timing_long);
EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
+EXPORT_SYMBOL_GPL(ata_dummy_port_info);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_std_ports);
EXPORT_SYMBOL_GPL(ata_host_init);
@@ -6650,6 +6655,7 @@ EXPORT_SYMBOL_GPL(pci_test_config_bits);
EXPORT_SYMBOL_GPL(pci_configure_dma_masks);
EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_native_host);
+EXPORT_SYMBOL_GPL(ata_pci_prepare_native_host);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
#ifdef CONFIG_PM
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index f033e79..d53b181 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -660,13 +660,12 @@ static int ata_pci_init_bmdma(struct ata_host *host)
for (i = 0; i < 2; i++) {
struct ata_port *ap = host->ports[i];
- struct ata_ioports *ioaddr = &ap->ioaddr;
void __iomem *bmdma = host->iomap[4] + 8 * i;
if (ata_port_is_dummy(ap))
continue;
- ioaddr->bmdma_addr = bmdma;
+ ap->ioaddr.bmdma_addr = bmdma;
if ((!(ap->flags & ATA_FLAG_IGN_SIMPLEX)) &&
(ioread8(bmdma + 2) & 0x80))
host->flags |= ATA_HOST_SIMPLEX;
@@ -739,6 +738,70 @@ int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask)
return 0;
}
+/**
+ * ata_pci_prepare_native_host - helper to prepare native PCI ATA host
+ * @pdev: target PCI device
+ * @ppi: array of port_info
+ * @n_ports: number of ports to allocate
+ * @r_host: out argument for the initialized ATA host
+ *
+ * Helper to allocate ATA host for @pdev, acquire all native PCI
+ * resources and initialize it accordingly in one go.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+int ata_pci_prepare_native_host(struct pci_dev *pdev,
+ const struct ata_port_info * const * ppi,
+ int n_ports, struct ata_host **r_host)
+{
+ struct ata_host *host;
+ unsigned int port_mask;
+ int rc;
+
+ if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL))
+ return -ENOMEM;
+
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
+ if (!host) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "failed to allocate ATA host\n");
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ port_mask = ATA_PORT_PRIMARY;
+ if (n_ports > 1)
+ port_mask |= ATA_PORT_SECONDARY;
+
+ rc = ata_pci_init_native_host(host, port_mask);
+ if (rc)
+ goto err_out;
+
+ /* init DMA related stuff */
+ rc = ata_pci_init_bmdma(host);
+ if (rc)
+ goto err_bmdma;
+
+ devres_remove_group(&pdev->dev, NULL);
+ *r_host = host;
+ return 0;
+
+ err_bmdma:
+ /* This is necessary because PCI and iomap resources are
+ * merged and releasing the top group won't release the
+ * acquired resources if some of those have been acquired
+ * before entering this function.
+ */
+ pcim_iounmap_regions(pdev, 0xf);
+ err_out:
+ devres_release_group(&pdev->dev, NULL);
+ return rc;
+}
+
struct ata_legacy_devres {
unsigned int mask;
unsigned long cmd_port[2];
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 7aa6085..43d9356 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -663,6 +663,7 @@ struct ata_port_info {
unsigned long mwdma_mask;
unsigned long udma_mask;
const struct ata_port_operations *port_ops;
+ irq_handler_t irq_handler;
void *private_data;
};
@@ -685,6 +686,7 @@ extern const unsigned long sata_deb_timing_hotplug[];
extern const unsigned long sata_deb_timing_long[];
extern const struct ata_port_operations ata_dummy_port_ops;
+extern const struct ata_port_info ata_dummy_port_info;
static inline const unsigned long *
sata_ehc_deb_timing(struct ata_eh_context *ehc)
@@ -883,6 +885,9 @@ extern struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int portmask);
extern int ata_pci_init_native_host(struct ata_host *host,
unsigned int port_mask);
+extern int ata_pci_prepare_native_host(struct pci_dev *pdev,
+ const struct ata_port_info * const * ppi,
+ int n_ports, struct ata_host **r_host);
extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
extern int pci_configure_dma_masks(struct pci_dev *pdev, u64 dma_mask,
u64 *configured_mask);
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH 10/12] libata: convert the remaining SATA drivers to new init model
2007-03-09 11:15 [PATCHSET] libata: implement new initialization model, take #3 Tejun Heo
` (10 preceding siblings ...)
2007-03-09 11:15 ` [PATCH 07/12] libata: add init helpers including ata_pci_prepare_native_host() Tejun Heo
@ 2007-03-09 11:15 ` Tejun Heo
11 siblings, 0 replies; 27+ messages in thread
From: Tejun Heo @ 2007-03-09 11:15 UTC (permalink / raw)
To: jeff, alan, linux-ide; +Cc: Tejun Heo
Convert ahci, sata_sil, sata_sil24, sata_svw, sata_qstor, sata_mv,
sata_sx4, sata_vsc and sata_inic162x to new init model.
Now that host and ap are available during intialization, functions are
converted to take either host or ap instead of low level parameters
which were inevitable for functions shared between init and other
paths. This simplifies code quite a bit.
* init_one()'s now follow more consistent init order
* ahci_setup_port() and ahci_host_init() collapsed into
ahci_init_one() for init order consistency
* sata_vsc uses port_info instead of setting fields manually
* in sata_svw, k2_board_info converted to port_info (info is now in
port flags). port number is honored now.
Tested on ICH7/8 AHCI, jmb360, sil3112, 3114, 3124 and 3132.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/ahci.c | 310 +++++++++++++++++--------------------------
drivers/ata/sata_inic162x.c | 64 +++------
drivers/ata/sata_mv.c | 105 ++++++---------
drivers/ata/sata_qstor.c | 62 +++------
drivers/ata/sata_sil.c | 89 +++++-------
drivers/ata/sata_sil24.c | 107 ++++++----------
drivers/ata/sata_svw.c | 105 +++++++--------
drivers/ata/sata_sx4.c | 150 +++++++++------------
drivers/ata/sata_vsc.c | 72 ++++------
9 files changed, 419 insertions(+), 645 deletions(-)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index fd9acf3..0895e23 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -207,7 +207,6 @@ static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
-static irqreturn_t ahci_interrupt (int irq, void *dev_instance);
static void ahci_irq_clear(struct ata_port *ap);
static int ahci_port_start(struct ata_port *ap);
static void ahci_port_stop(struct ata_port *ap);
@@ -261,7 +260,6 @@ static const struct ata_port_operations ahci_ops = {
.qc_prep = ahci_qc_prep,
.qc_issue = ahci_qc_issue,
- .irq_handler = ahci_interrupt,
.irq_clear = ahci_irq_clear,
.irq_on = ata_dummy_irq_on,
.irq_ack = ata_dummy_irq_ack,
@@ -296,7 +294,6 @@ static const struct ata_port_operations ahci_vt8251_ops = {
.qc_prep = ahci_qc_prep,
.qc_issue = ahci_qc_issue,
- .irq_handler = ahci_interrupt,
.irq_clear = ahci_irq_clear,
.irq_on = ata_dummy_irq_on,
.irq_ack = ata_dummy_irq_ack,
@@ -322,7 +319,6 @@ static const struct ata_port_operations ahci_vt8251_ops = {
static const struct ata_port_info ahci_port_info[] = {
/* board_ahci */
{
- .sht = &ahci_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_SKIP_D2H_BSY,
@@ -332,7 +328,6 @@ static const struct ata_port_info ahci_port_info[] = {
},
/* board_ahci_pi */
{
- .sht = &ahci_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI,
@@ -342,7 +337,6 @@ static const struct ata_port_info ahci_port_info[] = {
},
/* board_ahci_vt8251 */
{
- .sht = &ahci_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_SKIP_D2H_BSY |
@@ -353,7 +347,6 @@ static const struct ata_port_info ahci_port_info[] = {
},
/* board_ahci_ign_iferr */
{
- .sht = &ahci_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_SKIP_D2H_BSY |
@@ -456,10 +449,11 @@ static inline int ahci_nr_ports(u32 cap)
return (cap & 0x1f) + 1;
}
-static inline void __iomem *ahci_port_base(void __iomem *base,
- unsigned int port)
+static inline void __iomem *ahci_port_base(struct ata_port *ap)
{
- return base + 0x100 + (port * 0x80);
+ void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
+
+ return mmio + 0x100 + (ap->port_no * 0x80);
}
static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
@@ -496,8 +490,9 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
}
-static void ahci_start_engine(void __iomem *port_mmio)
+static void ahci_start_engine(struct ata_port *ap)
{
+ void __iomem *port_mmio = ahci_port_base(ap);
u32 tmp;
/* start DMA */
@@ -507,8 +502,9 @@ static void ahci_start_engine(void __iomem *port_mmio)
readl(port_mmio + PORT_CMD); /* flush */
}
-static int ahci_stop_engine(void __iomem *port_mmio)
+static int ahci_stop_engine(struct ata_port *ap)
{
+ void __iomem *port_mmio = ahci_port_base(ap);
u32 tmp;
tmp = readl(port_mmio + PORT_CMD);
@@ -530,19 +526,23 @@ static int ahci_stop_engine(void __iomem *port_mmio)
return 0;
}
-static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap,
- dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
+static void ahci_start_fis_rx(struct ata_port *ap)
{
+ void __iomem *port_mmio = ahci_port_base(ap);
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ struct ahci_port_priv *pp = ap->private_data;
u32 tmp;
/* set FIS registers */
- if (cap & HOST_CAP_64)
- writel((cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
- writel(cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
+ if (hpriv->cap & HOST_CAP_64)
+ writel((pp->cmd_slot_dma >> 16) >> 16,
+ port_mmio + PORT_LST_ADDR_HI);
+ writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
- if (cap & HOST_CAP_64)
- writel((rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
- writel(rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
+ if (hpriv->cap & HOST_CAP_64)
+ writel((pp->rx_fis_dma >> 16) >> 16,
+ port_mmio + PORT_FIS_ADDR_HI);
+ writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
/* enable FIS reception */
tmp = readl(port_mmio + PORT_CMD);
@@ -553,8 +553,9 @@ static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap,
readl(port_mmio + PORT_CMD);
}
-static int ahci_stop_fis_rx(void __iomem *port_mmio)
+static int ahci_stop_fis_rx(struct ata_port *ap)
{
+ void __iomem *port_mmio = ahci_port_base(ap);
u32 tmp;
/* disable FIS reception */
@@ -571,14 +572,16 @@ static int ahci_stop_fis_rx(void __iomem *port_mmio)
return 0;
}
-static void ahci_power_up(void __iomem *port_mmio, u32 cap)
+static void ahci_power_up(struct ata_port *ap)
{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ void __iomem *port_mmio = ahci_port_base(ap);
u32 cmd;
cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
/* spin up device */
- if (cap & HOST_CAP_SSS) {
+ if (hpriv->cap & HOST_CAP_SSS) {
cmd |= PORT_CMD_SPIN_UP;
writel(cmd, port_mmio + PORT_CMD);
}
@@ -588,11 +591,13 @@ static void ahci_power_up(void __iomem *port_mmio, u32 cap)
}
#ifdef CONFIG_PM
-static void ahci_power_down(void __iomem *port_mmio, u32 cap)
+static void ahci_power_down(struct ata_port *ap)
{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ void __iomem *port_mmio = ahci_port_base(ap);
u32 cmd, scontrol;
- if (!(cap & HOST_CAP_SSS))
+ if (!(hpriv->cap & HOST_CAP_SSS))
return;
/* put device into listen mode, first set PxSCTL.DET to 0 */
@@ -607,29 +612,28 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap)
}
#endif
-static void ahci_init_port(void __iomem *port_mmio, u32 cap,
- dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
+static void ahci_init_port(struct ata_port *ap)
{
/* enable FIS reception */
- ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma);
+ ahci_start_fis_rx(ap);
/* enable DMA */
- ahci_start_engine(port_mmio);
+ ahci_start_engine(ap);
}
-static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
+static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
{
int rc;
/* disable DMA */
- rc = ahci_stop_engine(port_mmio);
+ rc = ahci_stop_engine(ap);
if (rc) {
*emsg = "failed to stop engine";
return rc;
}
/* disable FIS reception */
- rc = ahci_stop_fis_rx(port_mmio);
+ rc = ahci_stop_fis_rx(ap);
if (rc) {
*emsg = "failed stop FIS RX";
return rc;
@@ -638,8 +642,10 @@ static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
return 0;
}
-static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
+static int ahci_reset_controller(struct ata_host *host)
{
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
u32 cap_save, impl_save, tmp;
cap_save = readl(mmio + HOST_CAP);
@@ -659,7 +665,7 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
tmp = readl(mmio + HOST_CTL);
if (tmp & HOST_RESET) {
- dev_printk(KERN_ERR, &pdev->dev,
+ dev_printk(KERN_ERR, host->dev,
"controller reset failed (0x%x)\n", tmp);
return -EIO;
}
@@ -688,23 +694,23 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
return 0;
}
-static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
- int n_ports, unsigned int port_flags,
- struct ahci_host_priv *hpriv)
+static void ahci_init_controller(struct ata_host *host)
{
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
int i, rc;
u32 tmp;
- for (i = 0; i < n_ports; i++) {
- void __iomem *port_mmio = ahci_port_base(mmio, i);
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+ void __iomem *port_mmio = ahci_port_base(ap);
const char *emsg = NULL;
- if ((port_flags & AHCI_FLAG_HONOR_PI) &&
- !(hpriv->port_map & (1 << i)))
+ if (ata_port_is_dummy(ap))
continue;
/* make sure port is not active */
- rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
+ rc = ahci_deinit_port(ap, &emsg);
if (rc)
dev_printk(KERN_WARNING, &pdev->dev,
"%s (%d)\n", emsg, rc);
@@ -732,7 +738,7 @@ static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
static unsigned int ahci_dev_classify(struct ata_port *ap)
{
- void __iomem *port_mmio = ap->ioaddr.cmd_addr;
+ void __iomem *port_mmio = ahci_port_base(ap);
struct ata_taskfile tf;
u32 tmp;
@@ -782,8 +788,7 @@ static int ahci_clo(struct ata_port *ap)
static int ahci_softreset(struct ata_port *ap, unsigned int *class)
{
struct ahci_port_priv *pp = ap->private_data;
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *port_mmio = ahci_port_base(ap);
const u32 cmd_fis_len = 5; /* five dwords */
const char *reason = NULL;
struct ata_taskfile tf;
@@ -800,7 +805,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
}
/* prepare for SRST (AHCI-1.1 10.4.1) */
- rc = ahci_stop_engine(port_mmio);
+ rc = ahci_stop_engine(ap);
if (rc) {
reason = "failed to stop engine";
goto fail_restart;
@@ -820,7 +825,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
}
/* restart engine */
- ahci_start_engine(port_mmio);
+ ahci_start_engine(ap);
ata_tf_init(ap->device, &tf);
fis = pp->cmd_tbl;
@@ -879,7 +884,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
return 0;
fail_restart:
- ahci_start_engine(port_mmio);
+ ahci_start_engine(ap);
fail:
ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
return rc;
@@ -890,13 +895,11 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
struct ahci_port_priv *pp = ap->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
struct ata_taskfile tf;
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
int rc;
DPRINTK("ENTER\n");
- ahci_stop_engine(port_mmio);
+ ahci_stop_engine(ap);
/* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(ap->device, &tf);
@@ -905,7 +908,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
rc = sata_std_hardreset(ap, class);
- ahci_start_engine(port_mmio);
+ ahci_start_engine(ap);
if (rc == 0 && ata_port_online(ap))
*class = ahci_dev_classify(ap);
@@ -918,20 +921,18 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
{
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
int rc;
DPRINTK("ENTER\n");
- ahci_stop_engine(port_mmio);
+ ahci_stop_engine(ap);
rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context));
/* vt8251 needs SError cleared for the port to operate */
ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR));
- ahci_start_engine(port_mmio);
+ ahci_start_engine(ap);
DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
@@ -943,7 +944,7 @@ static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
static void ahci_postreset(struct ata_port *ap, unsigned int *class)
{
- void __iomem *port_mmio = ap->ioaddr.cmd_addr;
+ void __iomem *port_mmio = ahci_port_base(ap);
u32 new_tmp, tmp;
ata_std_postreset(ap, class);
@@ -1108,8 +1109,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
static void ahci_host_intr(struct ata_port *ap)
{
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *port_mmio = ap->ioaddr.cmd_addr;
struct ata_eh_info *ehi = &ap->eh_info;
struct ahci_port_priv *pp = ap->private_data;
u32 status, qc_active;
@@ -1260,7 +1260,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- void __iomem *port_mmio = ap->ioaddr.cmd_addr;
+ void __iomem *port_mmio = ahci_port_base(ap);
if (qc->tf.protocol == ATA_PROT_NCQ)
writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
@@ -1272,8 +1272,7 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
static void ahci_freeze(struct ata_port *ap)
{
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *port_mmio = ahci_port_base(ap);
/* turn IRQ off */
writel(0, port_mmio + PORT_IRQ_MASK);
@@ -1282,7 +1281,7 @@ static void ahci_freeze(struct ata_port *ap)
static void ahci_thaw(struct ata_port *ap)
{
void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void __iomem *port_mmio = ahci_port_base(ap);
u32 tmp;
/* clear IRQ */
@@ -1296,13 +1295,10 @@ static void ahci_thaw(struct ata_port *ap)
static void ahci_error_handler(struct ata_port *ap)
{
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
/* restart engine */
- ahci_stop_engine(port_mmio);
- ahci_start_engine(port_mmio);
+ ahci_stop_engine(ap);
+ ahci_start_engine(ap);
}
/* perform recovery */
@@ -1312,13 +1308,10 @@ static void ahci_error_handler(struct ata_port *ap)
static void ahci_vt8251_error_handler(struct ata_port *ap)
{
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
/* restart engine */
- ahci_stop_engine(port_mmio);
- ahci_start_engine(port_mmio);
+ ahci_stop_engine(ap);
+ ahci_start_engine(ap);
}
/* perform recovery */
@@ -1329,36 +1322,29 @@ static void ahci_vt8251_error_handler(struct ata_port *ap)
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
if (qc->flags & ATA_QCFLAG_FAILED)
qc->err_mask |= AC_ERR_OTHER;
if (qc->err_mask) {
/* make DMA engine forget about the failed command */
- ahci_stop_engine(port_mmio);
- ahci_start_engine(port_mmio);
+ ahci_stop_engine(ap);
+ ahci_start_engine(ap);
}
}
#ifdef CONFIG_PM
static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
{
- struct ahci_host_priv *hpriv = ap->host->private_data;
- struct ahci_port_priv *pp = ap->private_data;
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
const char *emsg = NULL;
int rc;
- rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
+ rc = ahci_deinit_port(ap, &emsg);
if (rc == 0)
- ahci_power_down(port_mmio, hpriv->cap);
+ ahci_power_down(ap);
else {
ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
- ahci_init_port(port_mmio, hpriv->cap,
- pp->cmd_slot_dma, pp->rx_fis_dma);
+ ahci_init_port(ap);
}
return rc;
@@ -1366,13 +1352,8 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
static int ahci_port_resume(struct ata_port *ap)
{
- struct ahci_port_priv *pp = ap->private_data;
- struct ahci_host_priv *hpriv = ap->host->private_data;
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
- ahci_power_up(port_mmio, hpriv->cap);
- ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
+ ahci_power_up(ap);
+ ahci_init_port(ap);
return 0;
}
@@ -1400,8 +1381,6 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
static int ahci_pci_device_resume(struct pci_dev *pdev)
{
struct ata_host *host = dev_get_drvdata(&pdev->dev);
- struct ahci_host_priv *hpriv = host->private_data;
- void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
int rc;
rc = ata_pci_device_do_resume(pdev);
@@ -1409,12 +1388,11 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
return rc;
if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
- rc = ahci_reset_controller(mmio, pdev);
+ rc = ahci_reset_controller(host);
if (rc)
return rc;
- ahci_init_controller(mmio, pdev, host->n_ports,
- host->ports[0]->flags, hpriv);
+ ahci_init_controller(host);
}
ata_host_resume(host);
@@ -1426,10 +1404,7 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
static int ahci_port_start(struct ata_port *ap)
{
struct device *dev = ap->host->dev;
- struct ahci_host_priv *hpriv = ap->host->private_data;
struct ahci_port_priv *pp;
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
void *mem;
dma_addr_t mem_dma;
int rc;
@@ -1477,41 +1452,25 @@ static int ahci_port_start(struct ata_port *ap)
ap->private_data = pp;
/* power up port */
- ahci_power_up(port_mmio, hpriv->cap);
+ ahci_power_up(ap);
/* initialize port */
- ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
+ ahci_init_port(ap);
return 0;
}
static void ahci_port_stop(struct ata_port *ap)
{
- struct ahci_host_priv *hpriv = ap->host->private_data;
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
const char *emsg = NULL;
int rc;
/* de-initialize port */
- rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
+ rc = ahci_deinit_port(ap, &emsg);
if (rc)
ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
}
-static void ahci_setup_port(struct ata_ioports *port, void __iomem *base,
- unsigned int port_idx)
-{
- VPRINTK("ENTER, base==0x%lx, port_idx %u\n", base, port_idx);
- base = ahci_port_base(base, port_idx);
- VPRINTK("base now==0x%lx\n", base);
-
- port->cmd_addr = base;
- port->scr_addr = base + PORT_SCR;
-
- VPRINTK("EXIT\n");
-}
-
static int ahci_determine_nr_ports(struct pci_dev *pdev,
struct ata_port_info *pi,
struct ahci_host_priv *hpriv,
@@ -1554,43 +1513,11 @@ static int ahci_determine_nr_ports(struct pci_dev *pdev,
return max_port + 1;
}
-static int ahci_host_init(struct ata_probe_ent *probe_ent)
+static void ahci_print_info(struct ata_host *host)
{
- struct ahci_host_priv *hpriv = probe_ent->private_data;
- struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
- void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
- unsigned int i;
- u64 dma_mask;
- int rc;
-
- rc = ahci_reset_controller(mmio, pdev);
- if (rc)
- return rc;
-
- dma_mask = DMA_32BIT_MASK;
- if (hpriv->cap & HOST_CAP_64)
- dma_mask = DMA_64BIT_MASK;
-
- rc = pci_configure_dma_masks(pdev, dma_mask, NULL);
- if (rc)
- return rc;
-
- for (i = 0; i < probe_ent->n_ports; i++)
- ahci_setup_port(&probe_ent->port[i], mmio, i);
-
- ahci_init_controller(mmio, pdev, probe_ent->n_ports,
- probe_ent->port_flags, hpriv);
-
- pci_set_master(pdev);
-
- return 0;
-}
-
-static void ahci_print_info(struct ata_probe_ent *probe_ent)
-{
- struct ahci_host_priv *hpriv = probe_ent->private_data;
- struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
- void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
+ struct ahci_host_priv *hpriv = host->private_data;
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
u32 vers, cap, impl, speed;
const char *speed_s;
u16 cc;
@@ -1660,13 +1587,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 printed_version;
- unsigned int board_idx = (unsigned int) ent->driver_data;
- struct ata_port_info pi = ahci_port_info[board_idx];
+ struct ata_port_info pi = ahci_port_info[ent->driver_data];
+ const struct ata_port_info *ppi[] = { &pi, NULL };
struct device *dev = &pdev->dev;
+ unsigned int dummy_mask = 0;
void __iomem *mmio;
- struct ata_probe_ent *probe_ent;
struct ahci_host_priv *hpriv;
- int rc;
+ struct ata_host *host;
+ u64 dma_mask;
+ int n_ports, i, rc;
VPRINTK("ENTER\n");
@@ -1675,6 +1604,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ /* acquire resources */
rc = pcim_enable_device(pdev);
if (rc)
return rc;
@@ -1689,51 +1619,55 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_enable_msi(pdev))
pci_intx(pdev, 1);
- probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
- if (probe_ent == NULL)
- return -ENOMEM;
-
- probe_ent->dev = pci_dev_to_dev(pdev);
- INIT_LIST_HEAD(&probe_ent->node);
-
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
if (!hpriv)
return -ENOMEM;
- /* determine number of ports and fill probe_ent */
+ /* determine number of ports */
hpriv->cap = readl(mmio + HOST_CAP);
hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
+ n_ports = ahci_determine_nr_ports(pdev, &pi, hpriv, &dummy_mask);
+
+ /* prepare host */
+ if (!(pi.flags & AHCI_FLAG_NO_NCQ) && (hpriv->cap & HOST_CAP_NCQ))
+ pi.flags |= ATA_FLAG_NCQ;
- probe_ent->n_ports = ahci_determine_nr_ports(pdev, &pi, hpriv,
- &probe_ent->dummy_port_mask);
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
+ if (!host)
+ return -ENOMEM;
+ host->iomap = pcim_iomap_table(pdev);
+ host->private_data = hpriv;
- probe_ent->sht = pi.sht;
- probe_ent->port_flags = pi.flags;
- probe_ent->pio_mask = pi.pio_mask;
- probe_ent->udma_mask = pi.udma_mask;
- probe_ent->port_ops = pi.port_ops;
+ for (i = 0; i < host->n_ports; i++) {
+ if (!(dummy_mask & (1 << i))) {
+ struct ata_port *ap = host->ports[i];
+ void __iomem *port_mmio = ahci_port_base(ap);
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->iomap = pcim_iomap_table(pdev);
- probe_ent->private_data = hpriv;
+ ap->ioaddr.cmd_addr = port_mmio;
+ ap->ioaddr.scr_addr = port_mmio + PORT_SCR;
+ } else
+ host->ports[i]->ops = &ata_dummy_port_ops;
+ }
/* initialize adapter */
- rc = ahci_host_init(probe_ent);
+ dma_mask = DMA_32BIT_MASK;
+ if (hpriv->cap & HOST_CAP_64)
+ dma_mask = DMA_64BIT_MASK;
+
+ rc = pci_configure_dma_masks(pdev, dma_mask, NULL);
if (rc)
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);
+ rc = ahci_reset_controller(host);
+ if (rc)
+ return rc;
- if (!ata_device_add(probe_ent))
- return -ENODEV;
+ ahci_init_controller(host);
+ ahci_print_info(host);
- devm_kfree(dev, probe_ent);
- return 0;
+ pci_set_master(pdev);
+ return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
+ &ahci_sht);
}
static int __init ahci_init(void)
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index 733d1f4..935cd0a 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -559,7 +559,6 @@ static struct ata_port_operations inic_port_ops = {
.bmdma_stop = inic_bmdma_stop,
.bmdma_status = inic_bmdma_status,
- .irq_handler = inic_interrupt,
.irq_clear = inic_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -580,7 +579,6 @@ static struct ata_port_operations inic_port_ops = {
};
static struct ata_port_info inic_port_info = {
- .sht = &inic_sht,
/* For some reason, ATA_PROT_ATAPI is broken on this
* controller, and no, PIO_POLLING does't fix it. It somehow
* manages to report the wrong ireason and ignoring ireason
@@ -659,8 +657,8 @@ static int inic_pci_device_resume(struct pci_dev *pdev)
static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
- struct ata_port_info *pinfo = &inic_port_info;
- struct ata_probe_ent *probe_ent;
+ const struct ata_port_info *ppi[] = { &inic_port_info, NULL };
+ struct ata_host *host;
struct inic_host_priv *hpriv;
void __iomem * const *iomap;
int i, rc;
@@ -668,47 +666,26 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
- rc = pcim_enable_device(pdev);
- if (rc)
- return rc;
+ /* alloc host */
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, NR_PORTS);
+ hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
+ if (!host || !hpriv)
+ return -ENOMEM;
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
- return rc;
+ host->private_data = hpriv;
- rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);
+ /* acquire resources and fill host */
+ rc = pcim_enable_device(pdev);
if (rc)
return rc;
- iomap = pcim_iomap_table(pdev);
- /* Set dma_mask. This devices doesn't support 64bit addressing. */
- rc = pci_configure_dma_masks(pdev, DMA_32BIT_MASK, NULL);
+ rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);
if (rc)
return rc;
-
- probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
- hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
- if (!probe_ent || !hpriv)
- return -ENOMEM;
-
- probe_ent->dev = &pdev->dev;
- INIT_LIST_HEAD(&probe_ent->node);
-
- probe_ent->sht = pinfo->sht;
- probe_ent->port_flags = pinfo->flags;
- probe_ent->pio_mask = pinfo->pio_mask;
- probe_ent->mwdma_mask = pinfo->mwdma_mask;
- probe_ent->udma_mask = pinfo->udma_mask;
- probe_ent->port_ops = pinfo->port_ops;
- probe_ent->n_ports = NR_PORTS;
-
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
-
- probe_ent->iomap = iomap;
+ host->iomap = iomap = pcim_iomap_table(pdev);
for (i = 0; i < NR_PORTS; i++) {
- struct ata_ioports *port = &probe_ent->port[i];
+ struct ata_ioports *port = &host->ports[i]->ioaddr;
void __iomem *port_base = iomap[MMIO_BAR] + i * PORT_SIZE;
port->cmd_addr = iomap[2 * i];
@@ -720,9 +697,13 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
ata_std_ports(port);
}
- probe_ent->private_data = hpriv;
hpriv->cached_hctl = readw(iomap[MMIO_BAR] + HOST_CTL);
+ /* Set dma_mask. This devices doesn't support 64bit addressing. */
+ rc = pci_configure_dma_masks(pdev, DMA_32BIT_MASK, NULL);
+ if (rc)
+ return rc;
+
rc = init_controller(iomap[MMIO_BAR], hpriv->cached_hctl);
if (rc) {
dev_printk(KERN_ERR, &pdev->dev,
@@ -731,13 +712,8 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
pci_set_master(pdev);
-
- if (!ata_device_add(probe_ent))
- return -ENODEV;
-
- devm_kfree(&pdev->dev, probe_ent);
-
- return 0;
+ return ata_host_activate(host, pdev->irq, inic_interrupt, IRQF_SHARED,
+ &inic_sht);
}
static const struct pci_device_id inic_pci_tbl[] = {
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index ed07f7a..0283c0b 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -347,7 +347,6 @@ static void mv_port_stop(struct ata_port *ap);
static void mv_qc_prep(struct ata_queued_cmd *qc);
static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
-static irqreturn_t mv_interrupt(int irq, void *dev_instance);
static void mv_eng_timeout(struct ata_port *ap);
static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
@@ -409,7 +408,6 @@ static const struct ata_port_operations mv5_ops = {
.eng_timeout = mv_eng_timeout,
- .irq_handler = mv_interrupt,
.irq_clear = mv_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -438,7 +436,6 @@ static const struct ata_port_operations mv6_ops = {
.eng_timeout = mv_eng_timeout,
- .irq_handler = mv_interrupt,
.irq_clear = mv_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -467,7 +464,6 @@ static const struct ata_port_operations mv_iie_ops = {
.eng_timeout = mv_eng_timeout,
- .irq_handler = mv_interrupt,
.irq_clear = mv_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -481,35 +477,30 @@ static const struct ata_port_operations mv_iie_ops = {
static const struct ata_port_info mv_port_info[] = {
{ /* chip_504x */
- .sht = &mv_sht,
.flags = MV_COMMON_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &mv5_ops,
},
{ /* chip_508x */
- .sht = &mv_sht,
.flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &mv5_ops,
},
{ /* chip_5080 */
- .sht = &mv_sht,
.flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &mv5_ops,
},
{ /* chip_604x */
- .sht = &mv_sht,
.flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &mv6_ops,
},
{ /* chip_608x */
- .sht = &mv_sht,
.flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
MV_FLAG_DUAL_HC),
.pio_mask = 0x1f, /* pio0-4 */
@@ -517,14 +508,12 @@ static const struct ata_port_info mv_port_info[] = {
.port_ops = &mv6_ops,
},
{ /* chip_6042 */
- .sht = &mv_sht,
.flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &mv_iie_ops,
},
{ /* chip_7042 */
- .sht = &mv_sht,
.flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */
@@ -2060,9 +2049,10 @@ static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio)
readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
}
-static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv,
- unsigned int board_idx)
+static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
{
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+ struct mv_host_priv *hpriv = host->private_data;
u8 rev_id;
u32 hp_flags = hpriv->hp_flags;
@@ -2160,8 +2150,8 @@ static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv,
/**
* mv_init_host - Perform some early initialization of the host.
- * @pdev: host PCI device
- * @probe_ent: early data struct representing the host
+ * @host: ATA host to initialize
+ * @board_idx: controller index
*
* If possible, do an early global reset of the host. Then do
* our port init and clear/unmask all/relevant host interrupts.
@@ -2169,24 +2159,23 @@ static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv,
* LOCKING:
* Inherited from caller.
*/
-static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
- unsigned int board_idx)
+static int mv_init_host(struct ata_host *host, unsigned int board_idx)
{
int rc = 0, n_hc, port, hc;
- void __iomem *mmio = probe_ent->iomap[MV_PRIMARY_BAR];
- struct mv_host_priv *hpriv = probe_ent->private_data;
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+ void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
+ struct mv_host_priv *hpriv = host->private_data;
/* global interrupt mask */
writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
- rc = mv_chip_id(pdev, hpriv, board_idx);
+ rc = mv_chip_id(host, board_idx);
if (rc)
goto done;
- n_hc = mv_get_hc_count(probe_ent->port_flags);
- probe_ent->n_ports = MV_PORTS_PER_HC * n_hc;
+ n_hc = mv_get_hc_count(host->ports[0]->flags);
- for (port = 0; port < probe_ent->n_ports; port++)
+ for (port = 0; port < host->n_ports; port++)
hpriv->ops->read_preamp(hpriv, port, mmio);
rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc);
@@ -2197,7 +2186,7 @@ static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
hpriv->ops->reset_bus(pdev, mmio);
hpriv->ops->enable_leds(hpriv, mmio);
- for (port = 0; port < probe_ent->n_ports; port++) {
+ for (port = 0; port < host->n_ports; port++) {
if (IS_60XX(hpriv)) {
void __iomem *port_mmio = mv_port_base(mmio, port);
@@ -2210,9 +2199,9 @@ static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
hpriv->ops->phy_errata(hpriv, mmio, port);
}
- for (port = 0; port < probe_ent->n_ports; port++) {
+ for (port = 0; port < host->n_ports; port++) {
void __iomem *port_mmio = mv_port_base(mmio, port);
- mv_port_init(&probe_ent->port[port], port_mmio);
+ mv_port_init(&host->ports[port]->ioaddr, port_mmio);
}
for (hc = 0; hc < n_hc; hc++) {
@@ -2251,17 +2240,17 @@ done:
/**
* mv_print_info - Dump key info to kernel log for perusal.
- * @probe_ent: early data struct representing the host
+ * @host: ATA host to print info about
*
* FIXME: complete this.
*
* LOCKING:
* Inherited from caller.
*/
-static void mv_print_info(struct ata_probe_ent *probe_ent)
+static void mv_print_info(struct ata_host *host)
{
- struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
- struct mv_host_priv *hpriv = probe_ent->private_data;
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+ struct mv_host_priv *hpriv = host->private_data;
u8 rev_id, scc;
const char *scc_s;
@@ -2280,7 +2269,7 @@ static void mv_print_info(struct ata_probe_ent *probe_ent)
dev_printk(KERN_INFO, &pdev->dev,
"%u slots %u ports %s mode IRQ via %s\n",
- (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports,
+ (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
}
@@ -2295,54 +2284,42 @@ static void mv_print_info(struct ata_probe_ent *probe_ent)
static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version = 0;
- struct device *dev = &pdev->dev;
- struct ata_probe_ent *probe_ent;
- struct mv_host_priv *hpriv;
unsigned int board_idx = (unsigned int)ent->driver_data;
- int rc;
+ const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
+ struct ata_host *host;
+ struct mv_host_priv *hpriv;
+ int n_ports, rc;
if (!printed_version++)
dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+ /* allocate host */
+ n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC;
+
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
+ hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
+ if (!host || !hpriv)
+ return -ENOMEM;
+ host->private_data = hpriv;
+
+ /* acquire resources */
rc = pcim_enable_device(pdev);
if (rc)
return rc;
- pci_set_master(pdev);
rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME);
if (rc == -EBUSY)
pcim_pin_device(pdev);
if (rc)
return rc;
+ host->iomap = pcim_iomap_table(pdev);
rc = pci_configure_dma_masks(pdev, DMA_64BIT_MASK, NULL);
if (rc)
return rc;
- probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
- if (probe_ent == NULL)
- return -ENOMEM;
-
- probe_ent->dev = pci_dev_to_dev(pdev);
- INIT_LIST_HEAD(&probe_ent->node);
-
- hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
- if (!hpriv)
- return -ENOMEM;
-
- probe_ent->sht = mv_port_info[board_idx].sht;
- probe_ent->port_flags = mv_port_info[board_idx].flags;
- probe_ent->pio_mask = mv_port_info[board_idx].pio_mask;
- probe_ent->udma_mask = mv_port_info[board_idx].udma_mask;
- probe_ent->port_ops = mv_port_info[board_idx].port_ops;
-
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->iomap = pcim_iomap_table(pdev);
- probe_ent->private_data = hpriv;
-
/* initialize adapter */
- rc = mv_init_host(pdev, probe_ent, board_idx);
+ rc = mv_init_host(host, board_idx);
if (rc)
return rc;
@@ -2351,13 +2328,11 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_intx(pdev, 1);
mv_dump_pci_cfg(pdev, 0x68);
- mv_print_info(probe_ent);
-
- if (ata_device_add(probe_ent) == 0)
- return -ENODEV;
+ mv_print_info(host);
- devm_kfree(dev, probe_ent);
- return 0;
+ pci_set_master(pdev);
+ return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
+ &mv_sht);
}
static int __init mv_init(void)
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index b1faaaf..38069ea 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -114,7 +114,6 @@ struct qs_port_priv {
static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static int qs_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static irqreturn_t qs_intr (int irq, void *dev_instance);
static int qs_port_start(struct ata_port *ap);
static void qs_host_stop(struct ata_host *host);
static void qs_phy_reset(struct ata_port *ap);
@@ -158,7 +157,6 @@ static const struct ata_port_operations qs_ata_ops = {
.qc_issue = qs_qc_issue,
.data_xfer = ata_data_xfer,
.eng_timeout = qs_eng_timeout,
- .irq_handler = qs_intr,
.irq_clear = qs_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -173,7 +171,6 @@ static const struct ata_port_operations qs_ata_ops = {
static const struct ata_port_info qs_port_info[] = {
/* board_2068_idx */
{
- .sht = &qs_ata_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET |
//FIXME ATA_FLAG_SRST |
@@ -530,16 +527,16 @@ static void qs_host_stop(struct ata_host *host)
writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
}
-static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
+static void qs_host_init(struct ata_host *host, unsigned int chip_id)
{
- void __iomem *mmio_base = pe->iomap[QS_MMIO_BAR];
+ void __iomem *mmio_base = host->iomap[QS_MMIO_BAR];
unsigned int port_no;
writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
/* reset each channel in turn */
- for (port_no = 0; port_no < pe->n_ports; ++port_no) {
+ for (port_no = 0; port_no < host->n_ports; ++port_no) {
u8 __iomem *chan = mmio_base + (port_no * 0x4000);
writeb(QS_CTR1_RDEV|QS_CTR1_RCHN, chan + QS_CCT_CTR1);
writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
@@ -547,7 +544,7 @@ static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
}
writeb(QS_SERD3_PHY_ENA, mmio_base + QS_HVS_SERD3); /* enable phy */
- for (port_no = 0; port_no < pe->n_ports; ++port_no) {
+ for (port_no = 0; port_no < host->n_ports; ++port_no) {
u8 __iomem *chan = mmio_base + (port_no * 0x4000);
/* set FIFO depths to same settings as Windows driver */
writew(32, chan + QS_CFC_HUFT);
@@ -564,15 +561,21 @@ static int qs_ata_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
static int printed_version;
- struct ata_probe_ent *probe_ent;
- void __iomem * const *iomap;
unsigned int board_idx = (unsigned int) ent->driver_data;
+ const struct ata_port_info *ppi[] = { &qs_port_info[board_idx], NULL };
+ struct ata_host *host;
int rc, port_no;
u64 dma_mask;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ /* alloc host */
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, QS_PORTS);
+ if (!host)
+ return -ENOMEM;
+
+ /* acquire resources and fill host */
rc = pcim_enable_device(pdev);
if (rc)
return rc;
@@ -583,51 +586,28 @@ static int qs_ata_init_one(struct pci_dev *pdev,
rc = pcim_iomap_regions(pdev, 1 << QS_MMIO_BAR, DRV_NAME);
if (rc)
return rc;
- iomap = pcim_iomap_table(pdev);
+ host->iomap = pcim_iomap_table(pdev);
dma_mask = DMA_32BIT_MASK;
- if (readl(iomap[QS_MMIO_BAR] + QS_HID_HPHY) & QS_HPHY_64BIT)
+ if (readl(host->iomap[QS_MMIO_BAR] + QS_HID_HPHY) & QS_HPHY_64BIT)
dma_mask = DMA_64BIT_MASK;
rc = pci_configure_dma_masks(pdev, dma_mask, NULL);
if (rc)
return rc;
- probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
- if (probe_ent == NULL)
- return -ENOMEM;
-
- probe_ent->dev = pci_dev_to_dev(pdev);
- INIT_LIST_HEAD(&probe_ent->node);
-
- probe_ent->sht = qs_port_info[board_idx].sht;
- probe_ent->port_flags = qs_port_info[board_idx].flags;
- probe_ent->pio_mask = qs_port_info[board_idx].pio_mask;
- probe_ent->mwdma_mask = qs_port_info[board_idx].mwdma_mask;
- probe_ent->udma_mask = qs_port_info[board_idx].udma_mask;
- probe_ent->port_ops = qs_port_info[board_idx].port_ops;
-
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->iomap = iomap;
- probe_ent->n_ports = QS_PORTS;
-
- for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
+ for (port_no = 0; port_no < host->n_ports; ++port_no) {
void __iomem *chan =
- probe_ent->iomap[QS_MMIO_BAR] + (port_no * 0x4000);
- qs_ata_setup_port(&probe_ent->port[port_no], chan);
+ host->iomap[QS_MMIO_BAR] + (port_no * 0x4000);
+ qs_ata_setup_port(&host->ports[port_no]->ioaddr, chan);
}
- pci_set_master(pdev);
-
/* initialize adapter */
- qs_host_init(board_idx, probe_ent);
+ qs_host_init(host, board_idx);
- if (ata_device_add(probe_ent) != QS_PORTS)
- return -EIO;
-
- devm_kfree(&pdev->dev, probe_ent);
- return 0;
+ pci_set_master(pdev);
+ return ata_host_activate(host, pdev->irq, qs_intr, IRQF_SHARED,
+ &qs_ata_sht);
}
static int __init qs_ata_init(void)
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 10e3aea..981dda2 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -118,7 +118,6 @@ static void sil_dev_config(struct ata_device *dev);
static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static void sil_post_set_mode (struct ata_port *ap);
-static irqreturn_t sil_interrupt(int irq, void *dev_instance);
static void sil_freeze(struct ata_port *ap);
static void sil_thaw(struct ata_port *ap);
@@ -209,7 +208,6 @@ static const struct ata_port_operations sil_ops = {
.thaw = sil_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .irq_handler = sil_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -221,7 +219,6 @@ static const struct ata_port_operations sil_ops = {
static const struct ata_port_info sil_port_info[] = {
/* sil_3112 */
{
- .sht = &sil_sht,
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@@ -230,7 +227,6 @@ static const struct ata_port_info sil_port_info[] = {
},
/* sil_3112_no_sata_irq */
{
- .sht = &sil_sht,
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE |
SIL_FLAG_NO_SATA_IRQ,
.pio_mask = 0x1f, /* pio0-4 */
@@ -240,7 +236,6 @@ static const struct ata_port_info sil_port_info[] = {
},
/* sil_3512 */
{
- .sht = &sil_sht,
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@@ -249,7 +244,6 @@ static const struct ata_port_info sil_port_info[] = {
},
/* sil_3114 */
{
- .sht = &sil_sht,
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@@ -583,10 +577,10 @@ static void sil_dev_config(struct ata_device *dev)
}
}
-static void sil_init_controller(struct pci_dev *pdev,
- int n_ports, unsigned long port_flags,
- void __iomem *mmio_base)
+static void sil_init_controller(struct ata_host *host)
{
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+ void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR];
u8 cls;
u32 tmp;
int i;
@@ -596,7 +590,7 @@ static void sil_init_controller(struct pci_dev *pdev,
if (cls) {
cls >>= 3;
cls++; /* cls = (line_size/8)+1 */
- for (i = 0; i < n_ports; i++)
+ for (i = 0; i < host->n_ports; i++)
writew(cls << 8 | cls,
mmio_base + sil_port[i].fifo_cfg);
} else
@@ -604,10 +598,10 @@ static void sil_init_controller(struct pci_dev *pdev,
"cache line size not set. Driver may not function\n");
/* Apply R_ERR on DMA activate FIS errata workaround */
- if (port_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
+ if (host->ports[0]->flags & SIL_FLAG_RERR_ON_DMA_ACT) {
int cnt;
- for (i = 0, cnt = 0; i < n_ports; i++) {
+ for (i = 0, cnt = 0; i < host->n_ports; i++) {
tmp = readl(mmio_base + sil_port[i].sfis_cfg);
if ((tmp & 0x3) != 0x01)
continue;
@@ -620,7 +614,7 @@ static void sil_init_controller(struct pci_dev *pdev,
}
}
- if (n_ports == 4) {
+ if (host->n_ports == 4) {
/* flip the magic "make 4 ports work" bit */
tmp = readl(mmio_base + sil_port[2].bmdma);
if ((tmp & SIL_INTR_STEERING) == 0)
@@ -632,15 +626,26 @@ static void sil_init_controller(struct pci_dev *pdev,
static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
- struct device *dev = &pdev->dev;
- struct ata_probe_ent *probe_ent;
+ int board_id = ent->driver_data;
+ const struct ata_port_info *ppi[] = { &sil_port_info[board_id], NULL };
+ struct ata_host *host;
void __iomem *mmio_base;
- int rc;
+ int n_ports, rc;
unsigned int i;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ /* allocate host */
+ n_ports = 2;
+ if (board_id == sil_3114)
+ n_ports = 4;
+
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
+ if (!host)
+ return -ENOMEM;
+
+ /* acquire resources and fill host */
rc = pcim_enable_device(pdev);
if (rc)
return rc;
@@ -650,50 +655,31 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
pcim_pin_device(pdev);
if (rc)
return rc;
+ host->iomap = pcim_iomap_table(pdev);
rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
if (rc)
return rc;
- probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
- if (probe_ent == NULL)
- return -ENOMEM;
+ mmio_base = host->iomap[SIL_MMIO_BAR];
- INIT_LIST_HEAD(&probe_ent->node);
- probe_ent->dev = pci_dev_to_dev(pdev);
- probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops;
- probe_ent->sht = sil_port_info[ent->driver_data].sht;
- probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2;
- probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask;
- probe_ent->mwdma_mask = sil_port_info[ent->driver_data].mwdma_mask;
- probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask;
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->port_flags = sil_port_info[ent->driver_data].flags;
-
- probe_ent->iomap = pcim_iomap_table(pdev);
-
- mmio_base = probe_ent->iomap[SIL_MMIO_BAR];
-
- for (i = 0; i < probe_ent->n_ports; i++) {
- probe_ent->port[i].cmd_addr = mmio_base + sil_port[i].tf;
- probe_ent->port[i].altstatus_addr =
- probe_ent->port[i].ctl_addr = mmio_base + sil_port[i].ctl;
- probe_ent->port[i].bmdma_addr = mmio_base + sil_port[i].bmdma;
- probe_ent->port[i].scr_addr = mmio_base + sil_port[i].scr;
- ata_std_ports(&probe_ent->port[i]);
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_ioports *ioaddr = &host->ports[i]->ioaddr;
+
+ ioaddr->cmd_addr = mmio_base + sil_port[i].tf;
+ ioaddr->altstatus_addr =
+ ioaddr->ctl_addr = mmio_base + sil_port[i].ctl;
+ ioaddr->bmdma_addr = mmio_base + sil_port[i].bmdma;
+ ioaddr->scr_addr = mmio_base + sil_port[i].scr;
+ ata_std_ports(ioaddr);
}
- sil_init_controller(pdev, probe_ent->n_ports, probe_ent->port_flags,
- mmio_base);
+ /* initialize and activate */
+ sil_init_controller(host);
pci_set_master(pdev);
-
- if (!ata_device_add(probe_ent))
- return -ENODEV;
-
- devm_kfree(dev, probe_ent);
- return 0;
+ return ata_host_activate(host, pdev->irq, sil_interrupt, IRQF_SHARED,
+ &sil_sht);
}
#ifdef CONFIG_PM
@@ -706,8 +692,7 @@ static int sil_pci_device_resume(struct pci_dev *pdev)
if (rc)
return rc;
- sil_init_controller(pdev, host->n_ports, host->ports[0]->flags,
- host->iomap[SIL_MMIO_BAR]);
+ sil_init_controller(host);
ata_host_resume(host);
return 0;
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index ad5add7..729c454 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -331,7 +331,6 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
static void sil24_qc_prep(struct ata_queued_cmd *qc);
static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
static void sil24_irq_clear(struct ata_port *ap);
-static irqreturn_t sil24_interrupt(int irq, void *dev_instance);
static void sil24_freeze(struct ata_port *ap);
static void sil24_thaw(struct ata_port *ap);
static void sil24_error_handler(struct ata_port *ap);
@@ -400,7 +399,6 @@ static const struct ata_port_operations sil24_ops = {
.qc_prep = sil24_qc_prep,
.qc_issue = sil24_qc_issue,
- .irq_handler = sil24_interrupt,
.irq_clear = sil24_irq_clear,
.irq_on = ata_dummy_irq_on,
.irq_ack = ata_dummy_irq_ack,
@@ -423,10 +421,9 @@ static const struct ata_port_operations sil24_ops = {
#define SIL24_NPORTS2FLAG(nports) ((((unsigned)(nports) - 1) & 0x3) << 30)
#define SIL24_FLAG2NPORTS(flag) ((((flag) >> 30) & 0x3) + 1)
-static struct ata_port_info sil24_port_info[] = {
+static const struct ata_port_info sil24_port_info[] = {
/* sil_3124 */
{
- .sht = &sil24_sht,
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
SIL24_FLAG_PCIX_IRQ_WOC,
.pio_mask = 0x1f, /* pio0-4 */
@@ -436,7 +433,6 @@ static struct ata_port_info sil24_port_info[] = {
},
/* sil_3132 */
{
- .sht = &sil24_sht,
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@@ -445,7 +441,6 @@ static struct ata_port_info sil24_port_info[] = {
},
/* sil_3131/sil_3531 */
{
- .sht = &sil24_sht,
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@@ -963,11 +958,10 @@ static int sil24_port_start(struct ata_port *ap)
return 0;
}
-static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
- unsigned long port_flags,
- void __iomem *host_base,
- void __iomem *port_base)
+static void sil24_init_controller(struct ata_host *host)
{
+ void __iomem *host_base = host->iomap[SIL24_HOST_BAR];
+ void __iomem *port_base = host->iomap[SIL24_PORT_BAR];
u32 tmp;
int i;
@@ -978,7 +972,7 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
writel(0, host_base + HOST_CTRL);
/* init ports */
- for (i = 0; i < n_ports; i++) {
+ for (i = 0; i < host->n_ports; i++) {
void __iomem *port = port_base + i * PORT_REGS_SIZE;
/* Initial PHY setting */
@@ -992,12 +986,12 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
PORT_CS_PORT_RST,
PORT_CS_PORT_RST, 10, 100);
if (tmp & PORT_CS_PORT_RST)
- dev_printk(KERN_ERR, &pdev->dev,
+ dev_printk(KERN_ERR, host->dev,
"failed to clear port RST\n");
}
/* Configure IRQ WoC */
- if (port_flags & SIL24_FLAG_PCIX_IRQ_WOC)
+ if (host->ports[0]->flags & SIL24_FLAG_PCIX_IRQ_WOC)
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
else
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
@@ -1025,18 +1019,17 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version = 0;
- struct device *dev = &pdev->dev;
- unsigned int board_id = (unsigned int)ent->driver_data;
- struct ata_port_info *pinfo = &sil24_port_info[board_id];
- struct ata_probe_ent *probe_ent;
- void __iomem *host_base;
- void __iomem *port_base;
+ struct ata_port_info pi = sil24_port_info[ent->driver_data];
+ const struct ata_port_info *ppi[] = { &pi, NULL };
+ void __iomem * const *iomap;
+ struct ata_host *host;
int i, rc;
u32 tmp;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ /* acquire resources */
rc = pcim_enable_device(pdev);
if (rc)
return rc;
@@ -1046,67 +1039,45 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
DRV_NAME);
if (rc)
return rc;
+ iomap = pcim_iomap_table(pdev);
- /* allocate & init probe_ent */
- probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
- if (!probe_ent)
- return -ENOMEM;
-
- probe_ent->dev = pci_dev_to_dev(pdev);
- INIT_LIST_HEAD(&probe_ent->node);
-
- probe_ent->sht = pinfo->sht;
- probe_ent->port_flags = pinfo->flags;
- probe_ent->pio_mask = pinfo->pio_mask;
- probe_ent->mwdma_mask = pinfo->mwdma_mask;
- probe_ent->udma_mask = pinfo->udma_mask;
- probe_ent->port_ops = pinfo->port_ops;
- probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->flags);
-
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->iomap = pcim_iomap_table(pdev);
-
- host_base = probe_ent->iomap[SIL24_HOST_BAR];
- port_base = probe_ent->iomap[SIL24_PORT_BAR];
-
- /*
- * Configure the device
- */
- rc = pci_configure_dma_masks(pdev, DMA_64BIT_MASK, NULL);
- if (rc)
- return rc;
-
- /* Apply workaround for completion IRQ loss on PCI-X errata */
- if (probe_ent->port_flags & SIL24_FLAG_PCIX_IRQ_WOC) {
- tmp = readl(host_base + HOST_CTRL);
+ /* apply workaround for completion IRQ loss on PCI-X errata */
+ if (pi.flags & SIL24_FLAG_PCIX_IRQ_WOC) {
+ tmp = readl(iomap[SIL24_HOST_BAR] + HOST_CTRL);
if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL))
dev_printk(KERN_INFO, &pdev->dev,
"Applying completion IRQ loss on PCI-X "
"errata fix\n");
else
- probe_ent->port_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
+ pi.flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
}
- for (i = 0; i < probe_ent->n_ports; i++) {
- void __iomem *port = port_base + i * PORT_REGS_SIZE;
+ /* allocate and fill host */
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi,
+ SIL24_FLAG2NPORTS(ppi[0]->flags));
+ if (!host)
+ return -ENOMEM;
+ host->iomap = iomap;
- probe_ent->port[i].cmd_addr = port;
- probe_ent->port[i].scr_addr = port + PORT_SCONTROL;
+ for (i = 0; i < host->n_ports; i++) {
+ void __iomem *port = iomap[SIL24_PORT_BAR] + i * PORT_REGS_SIZE;
- ata_std_ports(&probe_ent->port[i]);
- }
+ host->ports[i]->ioaddr.cmd_addr = port;
+ host->ports[i]->ioaddr.scr_addr = port + PORT_SCONTROL;
- sil24_init_controller(pdev, probe_ent->n_ports, probe_ent->port_flags,
- host_base, port_base);
+ ata_std_ports(&host->ports[i]->ioaddr);
+ }
- pci_set_master(pdev);
+ /* configure and activate the device */
+ rc = pci_configure_dma_masks(pdev, DMA_64BIT_MASK, NULL);
+ if (rc)
+ return rc;
- if (!ata_device_add(probe_ent))
- return -ENODEV;
+ sil24_init_controller(host);
- devm_kfree(dev, probe_ent);
- return 0;
+ pci_set_master(pdev);
+ return ata_host_activate(host, pdev->irq, sil24_interrupt, IRQF_SHARED,
+ &sil24_sht);
}
#ifdef CONFIG_PM
@@ -1114,7 +1085,6 @@ static int sil24_pci_device_resume(struct pci_dev *pdev)
{
struct ata_host *host = dev_get_drvdata(&pdev->dev);
void __iomem *host_base = host->iomap[SIL24_HOST_BAR];
- void __iomem *port_base = host->iomap[SIL24_PORT_BAR];
int rc;
rc = ata_pci_device_do_resume(pdev);
@@ -1124,8 +1094,7 @@ static int sil24_pci_device_resume(struct pci_dev *pdev)
if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
writel(HOST_CTRL_GLOBAL_RST, host_base + HOST_CTRL);
- sil24_init_controller(pdev, host->n_ports, host->ports[0]->flags,
- host_base, port_base);
+ sil24_init_controller(host);
ata_host_resume(host);
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index e83a608..e68d034 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -56,7 +56,9 @@
#define DRV_VERSION "2.1"
enum {
- K2_FLAG_NO_ATAPI_DMA = (1 << 29),
+ /* ap->flags bits */
+ K2_FLAG_SATA_8_PORTS = (1 << 24),
+ K2_FLAG_NO_ATAPI_DMA = (1 << 25),
/* Taskfile registers offsets */
K2_SATA_TF_CMD_OFFSET = 0x00,
@@ -90,17 +92,6 @@ enum {
board_svw8 = 1,
};
-static const struct k2_board_info {
- unsigned int n_ports;
- unsigned long port_flags;
-} k2_board_info[] = {
- /* board_svw4 */
- { 4, K2_FLAG_NO_ATAPI_DMA },
-
- /* board_svw8 */
- { 8, K2_FLAG_NO_ATAPI_DMA },
-};
-
static u8 k2_stat_check_status(struct ata_port *ap);
@@ -354,7 +345,6 @@ static const struct ata_port_operations k2_sata_ops = {
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -363,6 +353,28 @@ static const struct ata_port_operations k2_sata_ops = {
.port_start = ata_port_start,
};
+static const struct ata_port_info k2_port_info[] = {
+ /* board_svw4 */
+ {
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f,
+ .port_ops = &k2_sata_ops,
+ },
+ /* board_svw8 */
+ {
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA |
+ K2_FLAG_SATA_8_PORTS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f,
+ .port_ops = &k2_sata_ops,
+ },
+};
+
static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base)
{
port->cmd_addr = base + K2_SATA_TF_CMD_OFFSET;
@@ -386,17 +398,24 @@ static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base)
static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
- struct device *dev = &pdev->dev;
- struct ata_probe_ent *probe_ent;
+ const struct ata_port_info *ppi[] =
+ { &k2_port_info[ent->driver_data], NULL };
+ struct ata_host *host;
void __iomem *mmio_base;
- const struct k2_board_info *board_info =
- &k2_board_info[ent->driver_data];
- int rc;
- int i;
+ int n_ports, i, rc;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ /* allocate host */
+ n_ports = 4;
+ if (ppi[0]->flags & K2_FLAG_SATA_8_PORTS)
+ n_ports = 8;
+
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
+ if (!host)
+ return -ENOMEM;
+
/*
* If this driver happens to only be useful on Apple's K2, then
* we should check that here as it has a normal Serverworks ID
@@ -404,6 +423,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
rc = pcim_enable_device(pdev);
if (rc)
return rc;
+
/*
* Check if we have resources mapped at all (second function may
* have been disabled by firmware)
@@ -417,43 +437,20 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
pcim_pin_device(pdev);
if (rc)
return rc;
-
- rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
- if (rc)
- return rc;
-
- probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
- if (probe_ent == NULL)
- return -ENOMEM;
-
- probe_ent->dev = pci_dev_to_dev(pdev);
- INIT_LIST_HEAD(&probe_ent->node);
-
- probe_ent->sht = &k2_sata_sht;
- probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_MMIO | board_info->port_flags;
- probe_ent->port_ops = &k2_sata_ops;
- probe_ent->n_ports = 4;
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->iomap = pcim_iomap_table(pdev);
-
- /* We don't care much about the PIO/UDMA masks, but the core won't like us
- * if we don't fill these
- */
- probe_ent->pio_mask = 0x1f;
- probe_ent->mwdma_mask = 0x7;
- probe_ent->udma_mask = 0x7f;
-
- mmio_base = probe_ent->iomap[5];
+ host->iomap = pcim_iomap_table(pdev);
+ mmio_base = host->iomap[5];
/* different controllers have different number of ports - currently 4 or 8 */
/* All ports are on the same function. Multi-function device is no
* longer available. This should not be seen in any system. */
- for (i = 0; i < board_info->n_ports; i++)
- k2_sata_setup_port(&probe_ent->port[i],
+ for (i = 0; i < host->n_ports; i++)
+ k2_sata_setup_port(&host->ports[i]->ioaddr,
mmio_base + i * K2_SATA_PORT_OFFSET);
+ rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
+ if (rc)
+ return rc;
+
/* Clear a magic bit in SCR1 according to Darwin, those help
* some funky seagate drives (though so far, those were already
* set by the firmware on the machines I had access to)
@@ -466,12 +463,8 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
pci_set_master(pdev);
-
- if (!ata_device_add(probe_ent))
- return -ENODEV;
-
- devm_kfree(dev, probe_ent);
- return 0;
+ return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+ &k2_sata_sht);
}
/* 0x240 is device ID for Apple K2 device
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 29a68a7..c1b6ddb 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -151,24 +151,23 @@ struct pdc_host_priv {
static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance);
static void pdc_eng_timeout(struct ata_port *ap);
static void pdc_20621_phy_reset (struct ata_port *ap);
static int pdc_port_start(struct ata_port *ap);
static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
-static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
-static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe,
+static unsigned int pdc20621_dimm_init(struct ata_host *host);
+static int pdc20621_detect_dimm(struct ata_host *host);
+static unsigned int pdc20621_i2c_read(struct ata_host *host,
u32 device, u32 subaddr, u32 *pdata);
-static int pdc20621_prog_dimm0(struct ata_probe_ent *pe);
-static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe);
+static int pdc20621_prog_dimm0(struct ata_host *host);
+static unsigned int pdc20621_prog_dimm_global(struct ata_host *host);
#ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
+static void pdc20621_get_from_dimm(struct ata_host *host,
void *psource, u32 offset, u32 size);
#endif
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
+static void pdc20621_put_to_dimm(struct ata_host *host,
void *psource, u32 offset, u32 size);
static void pdc20621_irq_clear(struct ata_port *ap);
static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -204,7 +203,6 @@ static const struct ata_port_operations pdc_20621_ops = {
.qc_issue = pdc20621_qc_issue_prot,
.data_xfer = ata_data_xfer,
.eng_timeout = pdc_eng_timeout,
- .irq_handler = pdc20621_interrupt,
.irq_clear = pdc20621_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -214,7 +212,6 @@ static const struct ata_port_operations pdc_20621_ops = {
static const struct ata_port_info pdc_port_info[] = {
/* board_20621 */
{
- .sht = &pdc_sata_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO |
ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
@@ -882,15 +879,15 @@ static void pdc_sata_setup_port(struct ata_ioports *port, void __iomem *base)
#ifdef ATA_VERBOSE_DEBUG
-static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
+static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,
u32 offset, u32 size)
{
u32 window_size;
u16 idx;
u8 page_mask;
long dist;
- void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
- void __iomem *dimm_mmio = pe->iomap[PDC_DIMM_BAR];
+ void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
+ void __iomem *dimm_mmio = host->iomap[PDC_DIMM_BAR];
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -937,15 +934,15 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource,
#endif
-static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
+static void pdc20621_put_to_dimm(struct ata_host *host, void *psource,
u32 offset, u32 size)
{
u32 window_size;
u16 idx;
u8 page_mask;
long dist;
- void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
- void __iomem *dimm_mmio = pe->iomap[PDC_DIMM_BAR];
+ void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
+ void __iomem *dimm_mmio = host->iomap[PDC_DIMM_BAR];
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -987,10 +984,10 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
}
-static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
+static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device,
u32 subaddr, u32 *pdata)
{
- void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
+ void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
u32 i2creg = 0;
u32 status;
u32 count =0;
@@ -1023,17 +1020,17 @@ static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
}
-static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
+static int pdc20621_detect_dimm(struct ata_host *host)
{
u32 data=0 ;
- if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+ if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
if (data == 100)
return 100;
} else
return 0;
- if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
+ if (pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
if(data <= 0x75)
return 133;
} else
@@ -1043,13 +1040,13 @@ static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
}
-static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
+static int pdc20621_prog_dimm0(struct ata_host *host)
{
u32 spd0[50];
u32 data = 0;
int size, i;
u8 bdimmsize;
- void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
+ void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
static const struct {
unsigned int reg;
unsigned int ofs;
@@ -1072,7 +1069,7 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
mmio += PDC_CHIP0_OFS;
for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
- pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+ pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
pdc_i2c_read_data[i].reg,
&spd0[pdc_i2c_read_data[i].ofs]);
@@ -1108,11 +1105,11 @@ static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
}
-static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
+static unsigned int pdc20621_prog_dimm_global(struct ata_host *host)
{
u32 data, spd0;
int error, i;
- void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
+ void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -1129,7 +1126,7 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
/* Turn on for ECC */
- pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+ pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0);
if (spd0 == 0x02) {
data |= (0x01 << 16);
@@ -1156,7 +1153,7 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
}
-static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
+static unsigned int pdc20621_dimm_init(struct ata_host *host)
{
int speed, size, length;
u32 addr,spd0,pci_status;
@@ -1166,7 +1163,7 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
u32 ticks=0;
u32 clock=0;
u32 fparam=0;
- void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
+ void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -1225,18 +1222,18 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
Read SPD of DIMM by I2C interface,
and program the DIMM Module Controller.
*/
- if (!(speed = pdc20621_detect_dimm(pe))) {
+ if (!(speed = pdc20621_detect_dimm(host))) {
printk(KERN_ERR "Detect Local DIMM Fail\n");
return 1; /* DIMM error */
}
VPRINTK("Local DIMM Speed = %d\n", speed);
/* Programming DIMM0 Module Control Register (index_CID0:80h) */
- size = pdc20621_prog_dimm0(pe);
+ size = pdc20621_prog_dimm0(host);
VPRINTK("Local DIMM Size = %dMB\n",size);
/* Programming DIMM Module Global Control Register (index_CID0:88h) */
- if (pdc20621_prog_dimm_global(pe)) {
+ if (pdc20621_prog_dimm_global(host)) {
printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
return 1;
}
@@ -1249,20 +1246,20 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
'9','8','0','3','1','6','1','2',0,0};
u8 test_parttern2[40] = {0};
- pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x10040, 40);
- pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x40, 40);
+ pdc20621_put_to_dimm(host, (void *) test_parttern2, 0x10040, 40);
+ pdc20621_put_to_dimm(host, (void *) test_parttern2, 0x40, 40);
- pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40);
- pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
+ pdc20621_put_to_dimm(host, (void *) test_parttern1, 0x10040, 40);
+ pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x40, 40);
printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
- pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040,
+ pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x10040,
40);
printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
- pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40);
- pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
+ pdc20621_put_to_dimm(host, (void *) test_parttern1, 0x40, 40);
+ pdc20621_get_from_dimm(host, (void *) test_parttern2, 0x40, 40);
printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
}
@@ -1270,14 +1267,14 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
/* ECC initiliazation. */
- pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+ pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0);
if (spd0 == 0x02) {
VPRINTK("Start ECC initialization\n");
addr = 0;
length = size * 1024 * 1024;
while (addr < length) {
- pdc20621_put_to_dimm(pe, (void *) &tmp, addr,
+ pdc20621_put_to_dimm(host, (void *) &tmp, addr,
sizeof(u32));
addr += sizeof(u32);
}
@@ -1287,10 +1284,10 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
}
-static void pdc_20621_init(struct ata_probe_ent *pe)
+static void pdc_20621_init(struct ata_host *host)
{
u32 tmp;
- void __iomem *mmio = pe->iomap[PDC_MMIO_BAR];
+ void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
@@ -1321,15 +1318,25 @@ static void pdc_20621_init(struct ata_probe_ent *pe)
static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
- struct ata_probe_ent *probe_ent;
+ const struct ata_port_info *ppi[] =
+ { &pdc_port_info[ent->driver_data], NULL };
+ struct ata_host *host;
void __iomem *base;
struct pdc_host_priv *hpriv;
- unsigned int board_idx = (unsigned int) ent->driver_data;
int rc;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ /* allocate host */
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4);
+ hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
+ if (!host || !hpriv)
+ return -ENOMEM;
+
+ host->private_data = hpriv;
+
+ /* acquire resources and fill host */
rc = pcim_enable_device(pdev);
if (rc)
return rc;
@@ -1340,55 +1347,26 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
pcim_pin_device(pdev);
if (rc)
return rc;
+ host->iomap = pcim_iomap_table(pdev);
+
+ base = host->iomap[PDC_MMIO_BAR] + PDC_CHIP0_OFS;
+ pdc_sata_setup_port(&host->ports[0]->ioaddr, base + 0x200);
+ pdc_sata_setup_port(&host->ports[1]->ioaddr, base + 0x280);
+ pdc_sata_setup_port(&host->ports[2]->ioaddr, base + 0x300);
+ pdc_sata_setup_port(&host->ports[3]->ioaddr, base + 0x380);
+ /* configure and activate */
rc = pci_configure_dma_masks(pdev, ATA_DMA_MASK, NULL);
if (rc)
return rc;
- probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
- if (probe_ent == NULL)
+ if (pdc20621_dimm_init(host))
return -ENOMEM;
-
- probe_ent->dev = pci_dev_to_dev(pdev);
- INIT_LIST_HEAD(&probe_ent->node);
-
- hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
- if (!hpriv)
- return -ENOMEM;
-
- probe_ent->sht = pdc_port_info[board_idx].sht;
- probe_ent->port_flags = pdc_port_info[board_idx].flags;
- probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask;
- probe_ent->mwdma_mask = pdc_port_info[board_idx].mwdma_mask;
- probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask;
- probe_ent->port_ops = pdc_port_info[board_idx].port_ops;
-
- probe_ent->irq = pdev->irq;
- probe_ent->irq_flags = IRQF_SHARED;
- probe_ent->iomap = pcim_iomap_table(pdev);
-
- probe_ent->private_data = hpriv;
- base = probe_ent->iomap[PDC_MMIO_BAR] + PDC_CHIP0_OFS;
-
- probe_ent->n_ports = 4;
- pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
- pdc_sata_setup_port(&probe_ent->port[1], base + 0x280);
- pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
- pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
+ pdc_20621_init(host);
pci_set_master(pdev);
-
- /* initialize adapter */
- /* initialize local dimm */
- if (pdc20621_dimm_init(probe_ent))
- return -ENOMEM;
- pdc_20621_init(probe_ent);
-
- if (!ata_device_add(probe_ent))
- return -ENODEV;
-
- devm_kfree(&pdev->dev, probe_ent);
- return 0;
+ return ata_host_activate(host, pdev->irq, pdc20621_interrupt,
+ IRQF_SHARED, &pdc_sata_sht);
}
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 675508f..717f55a 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -333,7 +333,6 @@ static const struct ata_port_operations vsc_sata_ops = {
.thaw = vsc_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .irq_handler = vsc_sata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -367,30 +366,50 @@ static void __devinit vsc_sata_setup_port(struct ata_ioports *port,
static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
+ static const struct ata_port_info pi = {
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x7f,
+ .port_ops = &vsc_sata_ops,
+ };
+ const struct ata_port_info *ppi[] = { &pi, NULL };
static int printed_version;
- struct ata_probe_ent *probe_ent;
+ struct ata_host *host;
void __iomem *mmio_base;
- int rc;
+ int i, rc;
u8 cls;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+ /* allocate host */
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4);
+ if (!host)
+ return -ENOMEM;
+
rc = pcim_enable_device(pdev);
if (rc)
return rc;
- /*
- * Check if we have needed resource mapped.
- */
+ /* check if we have needed resource mapped */
if (pci_resource_len(pdev, 0) == 0)
return -ENODEV;
+ /* map IO regions and intialize host accordingly */
rc = pcim_iomap_regions(pdev, 1 << VSC_MMIO_BAR, DRV_NAME);
if (rc == -EBUSY)
pcim_pin_device(pdev);
if (rc)
return rc;
+ host->iomap = pcim_iomap_table(pdev);
+
+ mmio_base = host->iomap[VSC_MMIO_BAR];
+
+ for (i = 0; i < host->n_ports; i++)
+ vsc_sata_setup_port(&host->ports[i]->ioaddr,
+ mmio_base + (i + 1) * VSC_SATA_PORT_OFFSET);
/*
* Use 32 bit DMA mask, because 64 bit address support is poor.
@@ -399,12 +418,6 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
if (rc)
return rc;
- probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL);
- if (probe_ent == NULL)
- return -ENOMEM;
- probe_ent->dev = pci_dev_to_dev(pdev);
- INIT_LIST_HEAD(&probe_ent->node);
-
/*
* Due to a bug in the chip, the default cache line size can't be
* used (unless the default is non-zero).
@@ -415,33 +428,6 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
if (pci_enable_msi(pdev) == 0)
pci_intx(pdev, 0);
- else
- probe_ent->irq_flags = IRQF_SHARED;
-
- probe_ent->sht = &vsc_sata_sht;
- probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_MMIO;
- probe_ent->port_ops = &vsc_sata_ops;
- probe_ent->n_ports = 4;
- probe_ent->irq = pdev->irq;
- probe_ent->iomap = pcim_iomap_table(pdev);
-
- /* We don't care much about the PIO/UDMA masks, but the core won't like us
- * if we don't fill these
- */
- probe_ent->pio_mask = 0x1f;
- probe_ent->mwdma_mask = 0x07;
- probe_ent->udma_mask = 0x7f;
-
- mmio_base = probe_ent->iomap[VSC_MMIO_BAR];
-
- /* We have 4 ports per PCI function */
- vsc_sata_setup_port(&probe_ent->port[0], mmio_base + 1 * VSC_SATA_PORT_OFFSET);
- vsc_sata_setup_port(&probe_ent->port[1], mmio_base + 2 * VSC_SATA_PORT_OFFSET);
- vsc_sata_setup_port(&probe_ent->port[2], mmio_base + 3 * VSC_SATA_PORT_OFFSET);
- vsc_sata_setup_port(&probe_ent->port[3], mmio_base + 4 * VSC_SATA_PORT_OFFSET);
-
- pci_set_master(pdev);
/*
* Config offset 0x98 is "Extended Control and Status Register 0"
@@ -451,11 +437,9 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
*/
pci_write_config_dword(pdev, 0x98, 0);
- if (!ata_device_add(probe_ent))
- return -ENODEV;
-
- devm_kfree(&pdev->dev, probe_ent);
- return 0;
+ pci_set_master(pdev);
+ return ata_host_activate(host, pdev->irq, vsc_sata_interrupt,
+ IRQF_SHARED, &vsc_sata_sht);
}
static const struct pci_device_id vsc_sata_pci_tbl[] = {
--
1.5.0.1
^ permalink raw reply related [flat|nested] 27+ messages in thread