libata: add init helpers including ata_pci_prepare_native_host()
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> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
Родитель
d491b27b19
Коммит
21b0ad4fb8
|
@ -6623,6 +6623,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
|
||||
|
@ -6634,6 +6638,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);
|
||||
|
@ -6727,6 +6732,7 @@ EXPORT_SYMBOL_GPL(ata_timing_merge);
|
|||
EXPORT_SYMBOL_GPL(pci_test_config_bits);
|
||||
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
|
||||
|
|
|
@ -663,13 +663,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;
|
||||
|
@ -742,6 +741,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];
|
||||
|
|
|
@ -668,6 +668,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;
|
||||
};
|
||||
|
||||
|
@ -690,6 +691,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)
|
||||
|
@ -894,6 +896,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 unsigned long ata_pci_default_filter(struct ata_device *, unsigned long);
|
||||
#endif /* CONFIG_PCI */
|
||||
|
|
Загрузка…
Ссылка в новой задаче