aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-07-04 05:02:07 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-10 21:27:09 -0400
commitd583bc18812f8da52bf25eef9cd111e5fd46a6ab (patch)
tree7b886a4ce61b7c0bf8085da5e56b323a9a2fa193 /drivers
parent35142ddbf7d81ff3f1d9521611e734b8d5014df2 (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.c4
-rw-r--r--drivers/ata/libata-sff.c288
-rw-r--r--drivers/ata/sata_nv.c2
-rw-r--r--drivers/ata/sata_sis.c2
-rw-r--r--drivers/ata/sata_uli.c2
-rw-r--r--drivers/ata/sata_via.c2
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
6927EXPORT_SYMBOL_GPL(pci_test_config_bits); 6927EXPORT_SYMBOL_GPL(pci_test_config_bits);
6928EXPORT_SYMBOL_GPL(ata_pci_init_native_host); 6928EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
6929EXPORT_SYMBOL_GPL(ata_pci_init_bmdma); 6929EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
6930EXPORT_SYMBOL_GPL(ata_pci_prepare_native_host); 6930EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
6931EXPORT_SYMBOL_GPL(ata_pci_init_one); 6931EXPORT_SYMBOL_GPL(ata_pci_init_one);
6932EXPORT_SYMBOL_GPL(ata_pci_remove_one); 6932EXPORT_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 */
621int ata_pci_init_native_host(struct ata_host *host) 625int 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 */
690int ata_pci_prepare_native_host(struct pci_dev *pdev, 694int 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
733struct 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
742static 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
756static 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
773static 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 */
831static 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 */
891static 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;