diff options
| author | Tejun Heo <htejun@gmail.com> | 2007-04-17 10:44:07 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2007-04-28 14:16:03 -0400 |
| commit | 21b0ad4fb8306ac2bf5a249ffc978b1b8924c7d0 (patch) | |
| tree | 9f82cc6a4bca146ce1021f0825cc12f18f9063b9 | |
| parent | d491b27b1959565671e2c05dff09b5f535a854ce (diff) | |
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>
| -rw-r--r-- | drivers/ata/libata-core.c | 6 | ||||
| -rw-r--r-- | drivers/ata/libata-sff.c | 67 | ||||
| -rw-r--r-- | 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 8d3ae66572e9..2a38aa2841fd 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -6623,6 +6623,10 @@ const struct ata_port_operations ata_dummy_port_ops = { | |||
| 6623 | .port_stop = ata_dummy_noret, | 6623 | .port_stop = ata_dummy_noret, |
| 6624 | }; | 6624 | }; |
| 6625 | 6625 | ||
| 6626 | const struct ata_port_info ata_dummy_port_info = { | ||
| 6627 | .port_ops = &ata_dummy_port_ops, | ||
| 6628 | }; | ||
| 6629 | |||
| 6626 | /* | 6630 | /* |
| 6627 | * libata is essentially a library of internal helper functions for | 6631 | * libata is essentially a library of internal helper functions for |
| 6628 | * low-level ATA host controller drivers. As such, the API/ABI is | 6632 | * low-level ATA host controller drivers. As such, the API/ABI is |
| @@ -6634,6 +6638,7 @@ EXPORT_SYMBOL_GPL(sata_deb_timing_normal); | |||
| 6634 | EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug); | 6638 | EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug); |
| 6635 | EXPORT_SYMBOL_GPL(sata_deb_timing_long); | 6639 | EXPORT_SYMBOL_GPL(sata_deb_timing_long); |
| 6636 | EXPORT_SYMBOL_GPL(ata_dummy_port_ops); | 6640 | EXPORT_SYMBOL_GPL(ata_dummy_port_ops); |
| 6641 | EXPORT_SYMBOL_GPL(ata_dummy_port_info); | ||
| 6637 | EXPORT_SYMBOL_GPL(ata_std_bios_param); | 6642 | EXPORT_SYMBOL_GPL(ata_std_bios_param); |
| 6638 | EXPORT_SYMBOL_GPL(ata_std_ports); | 6643 | EXPORT_SYMBOL_GPL(ata_std_ports); |
| 6639 | EXPORT_SYMBOL_GPL(ata_host_init); | 6644 | EXPORT_SYMBOL_GPL(ata_host_init); |
| @@ -6727,6 +6732,7 @@ EXPORT_SYMBOL_GPL(ata_timing_merge); | |||
| 6727 | EXPORT_SYMBOL_GPL(pci_test_config_bits); | 6732 | EXPORT_SYMBOL_GPL(pci_test_config_bits); |
| 6728 | EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); | 6733 | EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); |
| 6729 | EXPORT_SYMBOL_GPL(ata_pci_init_native_host); | 6734 | EXPORT_SYMBOL_GPL(ata_pci_init_native_host); |
| 6735 | EXPORT_SYMBOL_GPL(ata_pci_prepare_native_host); | ||
| 6730 | EXPORT_SYMBOL_GPL(ata_pci_init_one); | 6736 | EXPORT_SYMBOL_GPL(ata_pci_init_one); |
| 6731 | EXPORT_SYMBOL_GPL(ata_pci_remove_one); | 6737 | EXPORT_SYMBOL_GPL(ata_pci_remove_one); |
| 6732 | #ifdef CONFIG_PM | 6738 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index d551fa1cb104..142120cab874 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
| @@ -663,13 +663,12 @@ static int ata_pci_init_bmdma(struct ata_host *host) | |||
| 663 | 663 | ||
| 664 | for (i = 0; i < 2; i++) { | 664 | for (i = 0; i < 2; i++) { |
| 665 | struct ata_port *ap = host->ports[i]; | 665 | struct ata_port *ap = host->ports[i]; |
| 666 | struct ata_ioports *ioaddr = &ap->ioaddr; | ||
| 667 | void __iomem *bmdma = host->iomap[4] + 8 * i; | 666 | void __iomem *bmdma = host->iomap[4] + 8 * i; |
| 668 | 667 | ||
| 669 | if (ata_port_is_dummy(ap)) | 668 | if (ata_port_is_dummy(ap)) |
| 670 | continue; | 669 | continue; |
| 671 | 670 | ||
| 672 | ioaddr->bmdma_addr = bmdma; | 671 | ap->ioaddr.bmdma_addr = bmdma; |
| 673 | if ((!(ap->flags & ATA_FLAG_IGN_SIMPLEX)) && | 672 | if ((!(ap->flags & ATA_FLAG_IGN_SIMPLEX)) && |
| 674 | (ioread8(bmdma + 2) & 0x80)) | 673 | (ioread8(bmdma + 2) & 0x80)) |
| 675 | host->flags |= ATA_HOST_SIMPLEX; | 674 | host->flags |= ATA_HOST_SIMPLEX; |
| @@ -742,6 +741,70 @@ int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask) | |||
| 742 | return 0; | 741 | return 0; |
| 743 | } | 742 | } |
| 744 | 743 | ||
| 744 | /** | ||
| 745 | * ata_pci_prepare_native_host - helper to prepare native PCI ATA host | ||
| 746 | * @pdev: target PCI device | ||
| 747 | * @ppi: array of port_info | ||
| 748 | * @n_ports: number of ports to allocate | ||
| 749 | * @r_host: out argument for the initialized ATA host | ||
| 750 | * | ||
| 751 | * Helper to allocate ATA host for @pdev, acquire all native PCI | ||
| 752 | * resources and initialize it accordingly in one go. | ||
| 753 | * | ||
| 754 | * LOCKING: | ||
| 755 | * Inherited from calling layer (may sleep). | ||
| 756 | * | ||
| 757 | * RETURNS: | ||
| 758 | * 0 on success, -errno otherwise. | ||
| 759 | */ | ||
| 760 | int ata_pci_prepare_native_host(struct pci_dev *pdev, | ||
| 761 | const struct ata_port_info * const * ppi, | ||
| 762 | int n_ports, struct ata_host **r_host) | ||
| 763 | { | ||
| 764 | struct ata_host *host; | ||
| 765 | unsigned int port_mask; | ||
| 766 | int rc; | ||
| 767 | |||
| 768 | if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) | ||
| 769 | return -ENOMEM; | ||
| 770 | |||
| 771 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); | ||
| 772 | if (!host) { | ||
| 773 | dev_printk(KERN_ERR, &pdev->dev, | ||
| 774 | "failed to allocate ATA host\n"); | ||
| 775 | rc = -ENOMEM; | ||
| 776 | goto err_out; | ||
| 777 | } | ||
| 778 | |||
| 779 | port_mask = ATA_PORT_PRIMARY; | ||
| 780 | if (n_ports > 1) | ||
| 781 | port_mask |= ATA_PORT_SECONDARY; | ||
| 782 | |||
| 783 | rc = ata_pci_init_native_host(host, port_mask); | ||
| 784 | if (rc) | ||
| 785 | goto err_out; | ||
| 786 | |||
| 787 | /* init DMA related stuff */ | ||
| 788 | rc = ata_pci_init_bmdma(host); | ||
| 789 | if (rc) | ||
| 790 | goto err_bmdma; | ||
| 791 | |||
| 792 | devres_remove_group(&pdev->dev, NULL); | ||
| 793 | *r_host = host; | ||
| 794 | return 0; | ||
| 795 | |||
| 796 | err_bmdma: | ||
| 797 | /* This is necessary because PCI and iomap resources are | ||
| 798 | * merged and releasing the top group won't release the | ||
| 799 | * acquired resources if some of those have been acquired | ||
| 800 | * before entering this function. | ||
| 801 | */ | ||
| 802 | pcim_iounmap_regions(pdev, 0xf); | ||
| 803 | err_out: | ||
| 804 | devres_release_group(&pdev->dev, NULL); | ||
| 805 | return rc; | ||
| 806 | } | ||
| 807 | |||
| 745 | struct ata_legacy_devres { | 808 | struct ata_legacy_devres { |
| 746 | unsigned int mask; | 809 | unsigned int mask; |
| 747 | unsigned long cmd_port[2]; | 810 | unsigned long cmd_port[2]; |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 400429f9cd9d..5d32c157de60 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -668,6 +668,7 @@ struct ata_port_info { | |||
| 668 | unsigned long mwdma_mask; | 668 | unsigned long mwdma_mask; |
| 669 | unsigned long udma_mask; | 669 | unsigned long udma_mask; |
| 670 | const struct ata_port_operations *port_ops; | 670 | const struct ata_port_operations *port_ops; |
| 671 | irq_handler_t irq_handler; | ||
| 671 | void *private_data; | 672 | void *private_data; |
| 672 | }; | 673 | }; |
| 673 | 674 | ||
| @@ -690,6 +691,7 @@ extern const unsigned long sata_deb_timing_hotplug[]; | |||
| 690 | extern const unsigned long sata_deb_timing_long[]; | 691 | extern const unsigned long sata_deb_timing_long[]; |
| 691 | 692 | ||
| 692 | extern const struct ata_port_operations ata_dummy_port_ops; | 693 | extern const struct ata_port_operations ata_dummy_port_ops; |
| 694 | extern const struct ata_port_info ata_dummy_port_info; | ||
| 693 | 695 | ||
| 694 | static inline const unsigned long * | 696 | static inline const unsigned long * |
| 695 | sata_ehc_deb_timing(struct ata_eh_context *ehc) | 697 | sata_ehc_deb_timing(struct ata_eh_context *ehc) |
| @@ -894,6 +896,9 @@ extern struct ata_probe_ent * | |||
| 894 | ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int portmask); | 896 | ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int portmask); |
| 895 | extern int ata_pci_init_native_host(struct ata_host *host, | 897 | extern int ata_pci_init_native_host(struct ata_host *host, |
| 896 | unsigned int port_mask); | 898 | unsigned int port_mask); |
| 899 | extern int ata_pci_prepare_native_host(struct pci_dev *pdev, | ||
| 900 | const struct ata_port_info * const * ppi, | ||
| 901 | int n_ports, struct ata_host **r_host); | ||
| 897 | extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits); | 902 | extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits); |
| 898 | extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long); | 903 | extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long); |
| 899 | #endif /* CONFIG_PCI */ | 904 | #endif /* CONFIG_PCI */ |
