diff options
author | Tejun Heo <htejun@gmail.com> | 2007-07-04 05:02:07 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-07-10 21:27:09 -0400 |
commit | d583bc18812f8da52bf25eef9cd111e5fd46a6ab (patch) | |
tree | 7b886a4ce61b7c0bf8085da5e56b323a9a2fa193 /drivers | |
parent | 35142ddbf7d81ff3f1d9521611e734b8d5014df2 (diff) |
libata: simplify PCI legacy SFF host handling
With PCI resource fix up for legacy hosts. We can use the same code
path to allocate IO resources and initialize host for both legacy and
native SFF hosts. Only IRQ requesting needs to be different.
Rename ata_pci_*_native_host() to ata_pci_*_sff_host(), kill all
legacy specific functions and use the renamed functions instead. This
simplifies code a lot.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/libata-core.c | 4 | ||||
-rw-r--r-- | drivers/ata/libata-sff.c | 288 | ||||
-rw-r--r-- | drivers/ata/sata_nv.c | 2 | ||||
-rw-r--r-- | drivers/ata/sata_sis.c | 2 | ||||
-rw-r--r-- | drivers/ata/sata_uli.c | 2 | ||||
-rw-r--r-- | drivers/ata/sata_via.c | 2 |
6 files changed, 38 insertions, 262 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 257fda90e527..681693534f4f 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -6925,9 +6925,9 @@ EXPORT_SYMBOL_GPL(ata_timing_merge); | |||
6925 | 6925 | ||
6926 | #ifdef CONFIG_PCI | 6926 | #ifdef CONFIG_PCI |
6927 | EXPORT_SYMBOL_GPL(pci_test_config_bits); | 6927 | EXPORT_SYMBOL_GPL(pci_test_config_bits); |
6928 | EXPORT_SYMBOL_GPL(ata_pci_init_native_host); | 6928 | EXPORT_SYMBOL_GPL(ata_pci_init_sff_host); |
6929 | EXPORT_SYMBOL_GPL(ata_pci_init_bmdma); | 6929 | EXPORT_SYMBOL_GPL(ata_pci_init_bmdma); |
6930 | EXPORT_SYMBOL_GPL(ata_pci_prepare_native_host); | 6930 | EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host); |
6931 | EXPORT_SYMBOL_GPL(ata_pci_init_one); | 6931 | EXPORT_SYMBOL_GPL(ata_pci_init_one); |
6932 | EXPORT_SYMBOL_GPL(ata_pci_remove_one); | 6932 | EXPORT_SYMBOL_GPL(ata_pci_remove_one); |
6933 | #ifdef CONFIG_PM | 6933 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index fa1c22c7b38f..ca7d2245d684 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -604,13 +604,17 @@ int ata_pci_init_bmdma(struct ata_host *host) | |||
604 | } | 604 | } |
605 | 605 | ||
606 | /** | 606 | /** |
607 | * ata_pci_init_native_host - acquire native ATA resources and init host | 607 | * ata_pci_init_sff_host - acquire native PCI ATA resources and init host |
608 | * @host: target ATA host | 608 | * @host: target ATA host |
609 | * | 609 | * |
610 | * Acquire native PCI ATA resources for @host and initialize the | 610 | * Acquire native PCI ATA resources for @host and initialize the |
611 | * first two ports of @host accordingly. Ports marked dummy are | 611 | * first two ports of @host accordingly. Ports marked dummy are |
612 | * skipped and allocation failure makes the port dummy. | 612 | * skipped and allocation failure makes the port dummy. |
613 | * | 613 | * |
614 | * Note that native PCI resources are valid even for legacy hosts | ||
615 | * as we fix up pdev resources array early in boot, so this | ||
616 | * function can be used for both native and legacy SFF hosts. | ||
617 | * | ||
614 | * LOCKING: | 618 | * LOCKING: |
615 | * Inherited from calling layer (may sleep). | 619 | * Inherited from calling layer (may sleep). |
616 | * | 620 | * |
@@ -618,7 +622,7 @@ int ata_pci_init_bmdma(struct ata_host *host) | |||
618 | * 0 if at least one port is initialized, -ENODEV if no port is | 622 | * 0 if at least one port is initialized, -ENODEV if no port is |
619 | * available. | 623 | * available. |
620 | */ | 624 | */ |
621 | int ata_pci_init_native_host(struct ata_host *host) | 625 | int ata_pci_init_sff_host(struct ata_host *host) |
622 | { | 626 | { |
623 | struct device *gdev = host->dev; | 627 | struct device *gdev = host->dev; |
624 | struct pci_dev *pdev = to_pci_dev(gdev); | 628 | struct pci_dev *pdev = to_pci_dev(gdev); |
@@ -673,7 +677,7 @@ int ata_pci_init_native_host(struct ata_host *host) | |||
673 | } | 677 | } |
674 | 678 | ||
675 | /** | 679 | /** |
676 | * ata_pci_prepare_native_host - helper to prepare native PCI ATA host | 680 | * ata_pci_prepare_sff_host - helper to prepare native PCI ATA host |
677 | * @pdev: target PCI device | 681 | * @pdev: target PCI device |
678 | * @ppi: array of port_info, must be enough for two ports | 682 | * @ppi: array of port_info, must be enough for two ports |
679 | * @r_host: out argument for the initialized ATA host | 683 | * @r_host: out argument for the initialized ATA host |
@@ -687,9 +691,9 @@ int ata_pci_init_native_host(struct ata_host *host) | |||
687 | * RETURNS: | 691 | * RETURNS: |
688 | * 0 on success, -errno otherwise. | 692 | * 0 on success, -errno otherwise. |
689 | */ | 693 | */ |
690 | int ata_pci_prepare_native_host(struct pci_dev *pdev, | 694 | int ata_pci_prepare_sff_host(struct pci_dev *pdev, |
691 | const struct ata_port_info * const * ppi, | 695 | const struct ata_port_info * const * ppi, |
692 | struct ata_host **r_host) | 696 | struct ata_host **r_host) |
693 | { | 697 | { |
694 | struct ata_host *host; | 698 | struct ata_host *host; |
695 | int rc; | 699 | int rc; |
@@ -705,7 +709,7 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev, | |||
705 | goto err_out; | 709 | goto err_out; |
706 | } | 710 | } |
707 | 711 | ||
708 | rc = ata_pci_init_native_host(host); | 712 | rc = ata_pci_init_sff_host(host); |
709 | if (rc) | 713 | if (rc) |
710 | goto err_out; | 714 | goto err_out; |
711 | 715 | ||
@@ -730,221 +734,6 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev, | |||
730 | return rc; | 734 | return rc; |
731 | } | 735 | } |
732 | 736 | ||
733 | struct ata_legacy_devres { | ||
734 | unsigned int mask; | ||
735 | unsigned long cmd_port[2]; | ||
736 | void __iomem * cmd_addr[2]; | ||
737 | void __iomem * ctl_addr[2]; | ||
738 | unsigned int irq[2]; | ||
739 | void * irq_dev_id[2]; | ||
740 | }; | ||
741 | |||
742 | static void ata_legacy_free_irqs(struct ata_legacy_devres *legacy_dr) | ||
743 | { | ||
744 | int i; | ||
745 | |||
746 | for (i = 0; i < 2; i++) { | ||
747 | if (!legacy_dr->irq[i]) | ||
748 | continue; | ||
749 | |||
750 | free_irq(legacy_dr->irq[i], legacy_dr->irq_dev_id[i]); | ||
751 | legacy_dr->irq[i] = 0; | ||
752 | legacy_dr->irq_dev_id[i] = NULL; | ||
753 | } | ||
754 | } | ||
755 | |||
756 | static void ata_legacy_release(struct device *gdev, void *res) | ||
757 | { | ||
758 | struct ata_legacy_devres *this = res; | ||
759 | int i; | ||
760 | |||
761 | ata_legacy_free_irqs(this); | ||
762 | |||
763 | for (i = 0; i < 2; i++) { | ||
764 | if (this->cmd_addr[i]) | ||
765 | ioport_unmap(this->cmd_addr[i]); | ||
766 | if (this->ctl_addr[i]) | ||
767 | ioport_unmap(this->ctl_addr[i]); | ||
768 | if (this->cmd_port[i]) | ||
769 | release_region(this->cmd_port[i], 8); | ||
770 | } | ||
771 | } | ||
772 | |||
773 | static int ata_init_legacy_port(struct ata_port *ap, | ||
774 | struct ata_legacy_devres *legacy_dr) | ||
775 | { | ||
776 | struct ata_host *host = ap->host; | ||
777 | int port_no = ap->port_no; | ||
778 | unsigned long cmd_port, ctl_port; | ||
779 | |||
780 | if (port_no == 0) { | ||
781 | cmd_port = ATA_PRIMARY_CMD; | ||
782 | ctl_port = ATA_PRIMARY_CTL; | ||
783 | } else { | ||
784 | cmd_port = ATA_SECONDARY_CMD; | ||
785 | ctl_port = ATA_SECONDARY_CTL; | ||
786 | } | ||
787 | |||
788 | /* request cmd_port */ | ||
789 | if (request_region(cmd_port, 8, "libata")) | ||
790 | legacy_dr->cmd_port[port_no] = cmd_port; | ||
791 | else { | ||
792 | dev_printk(KERN_WARNING, host->dev, | ||
793 | "0x%0lX IDE port busy\n", cmd_port); | ||
794 | return -EBUSY; | ||
795 | } | ||
796 | |||
797 | /* iomap cmd and ctl ports */ | ||
798 | legacy_dr->cmd_addr[port_no] = ioport_map(cmd_port, 8); | ||
799 | legacy_dr->ctl_addr[port_no] = ioport_map(ctl_port, 1); | ||
800 | if (!legacy_dr->cmd_addr[port_no] || !legacy_dr->ctl_addr[port_no]) { | ||
801 | dev_printk(KERN_WARNING, host->dev, | ||
802 | "failed to map cmd/ctl ports\n"); | ||
803 | return -ENOMEM; | ||
804 | } | ||
805 | |||
806 | /* init IO addresses */ | ||
807 | ap->ioaddr.cmd_addr = legacy_dr->cmd_addr[port_no]; | ||
808 | ap->ioaddr.altstatus_addr = legacy_dr->ctl_addr[port_no]; | ||
809 | ap->ioaddr.ctl_addr = legacy_dr->ctl_addr[port_no]; | ||
810 | ata_std_ports(&ap->ioaddr); | ||
811 | |||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | /** | ||
816 | * ata_init_legacy_host - acquire legacy ATA resources and init ATA host | ||
817 | * @host: target ATA host | ||
818 | * @was_busy: out parameter, indicates whether any port was busy | ||
819 | * | ||
820 | * Acquire legacy ATA resources for the first two ports of @host | ||
821 | * and initialize it accordingly. Ports marked dummy are skipped | ||
822 | * and resource acquistion failure makes the port dummy. | ||
823 | * | ||
824 | * LOCKING: | ||
825 | * Inherited from calling layer (may sleep). | ||
826 | * | ||
827 | * RETURNS: | ||
828 | * 0 if at least one port is initialized, -ENODEV if no port is | ||
829 | * available. | ||
830 | */ | ||
831 | static int ata_init_legacy_host(struct ata_host *host, int *was_busy) | ||
832 | { | ||
833 | struct device *gdev = host->dev; | ||
834 | struct ata_legacy_devres *legacy_dr; | ||
835 | int i, rc; | ||
836 | |||
837 | if (!devres_open_group(gdev, NULL, GFP_KERNEL)) | ||
838 | return -ENOMEM; | ||
839 | |||
840 | rc = -ENOMEM; | ||
841 | legacy_dr = devres_alloc(ata_legacy_release, sizeof(*legacy_dr), | ||
842 | GFP_KERNEL); | ||
843 | if (!legacy_dr) | ||
844 | goto err_out; | ||
845 | devres_add(gdev, legacy_dr); | ||
846 | |||
847 | for (i = 0; i < 2; i++) { | ||
848 | if (ata_port_is_dummy(host->ports[i])) | ||
849 | continue; | ||
850 | |||
851 | rc = ata_init_legacy_port(host->ports[i], legacy_dr); | ||
852 | if (rc == 0) | ||
853 | legacy_dr->mask |= 1 << i; | ||
854 | else { | ||
855 | if (rc == -EBUSY) | ||
856 | (*was_busy)++; | ||
857 | host->ports[i]->ops = &ata_dummy_port_ops; | ||
858 | } | ||
859 | } | ||
860 | |||
861 | if (!legacy_dr->mask) { | ||
862 | dev_printk(KERN_ERR, gdev, "no available legacy port\n"); | ||
863 | return -ENODEV; | ||
864 | } | ||
865 | |||
866 | devres_remove_group(gdev, NULL); | ||
867 | return 0; | ||
868 | |||
869 | err_out: | ||
870 | devres_release_group(gdev, NULL); | ||
871 | return rc; | ||
872 | } | ||
873 | |||
874 | /** | ||
875 | * ata_request_legacy_irqs - request legacy ATA IRQs | ||
876 | * @host: target ATA host | ||
877 | * @handler: array of IRQ handlers | ||
878 | * @irq_flags: array of IRQ flags | ||
879 | * @dev_id: array of IRQ dev_ids | ||
880 | * | ||
881 | * Request legacy IRQs for non-dummy legacy ports in @host. All | ||
882 | * IRQ parameters are passed as array to allow ports to have | ||
883 | * separate IRQ handlers. | ||
884 | * | ||
885 | * LOCKING: | ||
886 | * Inherited from calling layer (may sleep). | ||
887 | * | ||
888 | * RETURNS: | ||
889 | * 0 on success, -errno otherwise. | ||
890 | */ | ||
891 | static int ata_request_legacy_irqs(struct ata_host *host, | ||
892 | irq_handler_t const *handler, | ||
893 | const unsigned int *irq_flags, | ||
894 | void * const *dev_id) | ||
895 | { | ||
896 | struct device *gdev = host->dev; | ||
897 | struct ata_legacy_devres *legacy_dr; | ||
898 | int i, rc; | ||
899 | |||
900 | legacy_dr = devres_find(host->dev, ata_legacy_release, NULL, NULL); | ||
901 | BUG_ON(!legacy_dr); | ||
902 | |||
903 | for (i = 0; i < 2; i++) { | ||
904 | unsigned int irq; | ||
905 | |||
906 | /* FIXME: ATA_*_IRQ() should take generic device not pci_dev */ | ||
907 | if (i == 0) | ||
908 | irq = ATA_PRIMARY_IRQ(to_pci_dev(gdev)); | ||
909 | else | ||
910 | irq = ATA_SECONDARY_IRQ(to_pci_dev(gdev)); | ||
911 | |||
912 | if (!(legacy_dr->mask & (1 << i))) | ||
913 | continue; | ||
914 | |||
915 | if (!handler[i]) { | ||
916 | dev_printk(KERN_ERR, gdev, | ||
917 | "NULL handler specified for port %d\n", i); | ||
918 | rc = -EINVAL; | ||
919 | goto err_out; | ||
920 | } | ||
921 | |||
922 | rc = request_irq(irq, handler[i], irq_flags[i], DRV_NAME, | ||
923 | dev_id[i]); | ||
924 | if (rc) { | ||
925 | dev_printk(KERN_ERR, gdev, | ||
926 | "irq %u request failed (errno=%d)\n", irq, rc); | ||
927 | goto err_out; | ||
928 | } | ||
929 | |||
930 | /* record irq allocation in legacy_dr */ | ||
931 | legacy_dr->irq[i] = irq; | ||
932 | legacy_dr->irq_dev_id[i] = dev_id[i]; | ||
933 | |||
934 | /* only used to print info */ | ||
935 | if (i == 0) | ||
936 | host->irq = irq; | ||
937 | else | ||
938 | host->irq2 = irq; | ||
939 | } | ||
940 | |||
941 | return 0; | ||
942 | |||
943 | err_out: | ||
944 | ata_legacy_free_irqs(legacy_dr); | ||
945 | return rc; | ||
946 | } | ||
947 | |||
948 | /** | 737 | /** |
949 | * ata_pci_init_one - Initialize/register PCI IDE host controller | 738 | * ata_pci_init_one - Initialize/register PCI IDE host controller |
950 | * @pdev: Controller to be initialized | 739 | * @pdev: Controller to be initialized |
@@ -1029,35 +818,11 @@ int ata_pci_init_one(struct pci_dev *pdev, | |||
1029 | #endif | 818 | #endif |
1030 | } | 819 | } |
1031 | 820 | ||
1032 | /* alloc and init host */ | 821 | /* prepare host */ |
1033 | host = ata_host_alloc_pinfo(dev, ppi, 2); | 822 | rc = ata_pci_prepare_sff_host(pdev, ppi, &host); |
1034 | if (!host) { | 823 | if (rc) |
1035 | dev_printk(KERN_ERR, &pdev->dev, | ||
1036 | "failed to allocate ATA host\n"); | ||
1037 | rc = -ENOMEM; | ||
1038 | goto err_out; | 824 | goto err_out; |
1039 | } | ||
1040 | 825 | ||
1041 | if (!legacy_mode) { | ||
1042 | rc = ata_pci_init_native_host(host); | ||
1043 | if (rc) | ||
1044 | goto err_out; | ||
1045 | } else { | ||
1046 | int was_busy = 0; | ||
1047 | |||
1048 | rc = ata_init_legacy_host(host, &was_busy); | ||
1049 | if (was_busy) | ||
1050 | pcim_pin_device(pdev); | ||
1051 | if (rc) | ||
1052 | goto err_out; | ||
1053 | |||
1054 | /* request respective PCI regions, may fail */ | ||
1055 | rc = pci_request_region(pdev, 1, DRV_NAME); | ||
1056 | rc = pci_request_region(pdev, 3, DRV_NAME); | ||
1057 | } | ||
1058 | |||
1059 | /* init BMDMA, may fail */ | ||
1060 | ata_pci_init_bmdma(host); | ||
1061 | pci_set_master(pdev); | 826 | pci_set_master(pdev); |
1062 | 827 | ||
1063 | /* start host and request IRQ */ | 828 | /* start host and request IRQ */ |
@@ -1068,17 +833,28 @@ int ata_pci_init_one(struct pci_dev *pdev, | |||
1068 | if (!legacy_mode) { | 833 | if (!legacy_mode) { |
1069 | rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler, | 834 | rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler, |
1070 | IRQF_SHARED, DRV_NAME, host); | 835 | IRQF_SHARED, DRV_NAME, host); |
836 | if (rc) | ||
837 | goto err_out; | ||
1071 | host->irq = pdev->irq; | 838 | host->irq = pdev->irq; |
1072 | } else { | 839 | } else { |
1073 | irq_handler_t handler[2] = { host->ops->irq_handler, | 840 | if (!ata_port_is_dummy(host->ports[0])) { |
1074 | host->ops->irq_handler }; | 841 | host->irq = ATA_PRIMARY_IRQ(pdev); |
1075 | unsigned int irq_flags[2] = { IRQF_SHARED, IRQF_SHARED }; | 842 | rc = devm_request_irq(dev, host->irq, |
1076 | void *dev_id[2] = { host, host }; | 843 | pi->port_ops->irq_handler, |
844 | IRQF_SHARED, DRV_NAME, host); | ||
845 | if (rc) | ||
846 | goto err_out; | ||
847 | } | ||
1077 | 848 | ||
1078 | rc = ata_request_legacy_irqs(host, handler, irq_flags, dev_id); | 849 | if (!ata_port_is_dummy(host->ports[1])) { |
850 | host->irq2 = ATA_SECONDARY_IRQ(pdev); | ||
851 | rc = devm_request_irq(dev, host->irq2, | ||
852 | pi->port_ops->irq_handler, | ||
853 | IRQF_SHARED, DRV_NAME, host); | ||
854 | if (rc) | ||
855 | goto err_out; | ||
856 | } | ||
1079 | } | 857 | } |
1080 | if (rc) | ||
1081 | goto err_out; | ||
1082 | 858 | ||
1083 | /* register */ | 859 | /* register */ |
1084 | rc = ata_host_register(host, pi->sht); | 860 | rc = ata_host_register(host, pi->sht); |
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index b2656867c647..db81e3efa5ec 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
@@ -1560,7 +1560,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1560 | } | 1560 | } |
1561 | 1561 | ||
1562 | ppi[0] = &nv_port_info[type]; | 1562 | ppi[0] = &nv_port_info[type]; |
1563 | rc = ata_pci_prepare_native_host(pdev, ppi, &host); | 1563 | rc = ata_pci_prepare_sff_host(pdev, ppi, &host); |
1564 | if (rc) | 1564 | if (rc) |
1565 | return rc; | 1565 | return rc; |
1566 | 1566 | ||
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index fd80bcf1b236..33716b00c6b7 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c | |||
@@ -334,7 +334,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
334 | break; | 334 | break; |
335 | } | 335 | } |
336 | 336 | ||
337 | rc = ata_pci_prepare_native_host(pdev, ppi, &host); | 337 | rc = ata_pci_prepare_sff_host(pdev, ppi, &host); |
338 | if (rc) | 338 | if (rc) |
339 | return rc; | 339 | return rc; |
340 | 340 | ||
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index aca71819f6e8..b52f83ab056a 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c | |||
@@ -213,7 +213,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
213 | host->private_data = hpriv; | 213 | host->private_data = hpriv; |
214 | 214 | ||
215 | /* the first two ports are standard SFF */ | 215 | /* the first two ports are standard SFF */ |
216 | rc = ata_pci_init_native_host(host); | 216 | rc = ata_pci_init_sff_host(host); |
217 | if (rc) | 217 | if (rc) |
218 | return rc; | 218 | return rc; |
219 | 219 | ||
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index a4c0832033d8..c4124475f754 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c | |||
@@ -412,7 +412,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) | |||
412 | struct ata_host *host; | 412 | struct ata_host *host; |
413 | int rc; | 413 | int rc; |
414 | 414 | ||
415 | rc = ata_pci_prepare_native_host(pdev, ppi, &host); | 415 | rc = ata_pci_prepare_sff_host(pdev, ppi, &host); |
416 | if (rc) | 416 | if (rc) |
417 | return rc; | 417 | return rc; |
418 | *r_host = host; | 418 | *r_host = host; |