diff options
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r-- | drivers/ata/libata-sff.c | 162 |
1 files changed, 83 insertions, 79 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index d211db6b35a2..e35d13466c69 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -544,7 +544,7 @@ static int ata_resources_present(struct pci_dev *pdev, int port) | |||
544 | * RETURNS: | 544 | * RETURNS: |
545 | * 0 on success, -errno otherwise. | 545 | * 0 on success, -errno otherwise. |
546 | */ | 546 | */ |
547 | static int ata_pci_init_bmdma(struct ata_host *host) | 547 | int ata_pci_init_bmdma(struct ata_host *host) |
548 | { | 548 | { |
549 | struct device *gdev = host->dev; | 549 | struct device *gdev = host->dev; |
550 | struct pci_dev *pdev = to_pci_dev(gdev); | 550 | struct pci_dev *pdev = to_pci_dev(gdev); |
@@ -566,7 +566,7 @@ static int ata_pci_init_bmdma(struct ata_host *host) | |||
566 | } | 566 | } |
567 | host->iomap = pcim_iomap_table(pdev); | 567 | host->iomap = pcim_iomap_table(pdev); |
568 | 568 | ||
569 | for (i = 0; i < host->n_ports; i++) { | 569 | for (i = 0; i < 2; i++) { |
570 | struct ata_port *ap = host->ports[i]; | 570 | struct ata_port *ap = host->ports[i]; |
571 | void __iomem *bmdma = host->iomap[4] + 8 * i; | 571 | void __iomem *bmdma = host->iomap[4] + 8 * i; |
572 | 572 | ||
@@ -585,54 +585,52 @@ static int ata_pci_init_bmdma(struct ata_host *host) | |||
585 | /** | 585 | /** |
586 | * ata_pci_init_native_host - acquire native ATA resources and init host | 586 | * ata_pci_init_native_host - acquire native ATA resources and init host |
587 | * @host: target ATA host | 587 | * @host: target ATA host |
588 | * @port_mask: ports to consider | ||
589 | * | 588 | * |
590 | * Acquire native PCI ATA resources for @host and initialize | 589 | * Acquire native PCI ATA resources for @host and initialize the |
591 | * @host accordoingly. | 590 | * first two ports of @host accordingly. Ports marked dummy are |
591 | * skipped and allocation failure makes the port dummy. | ||
592 | * | 592 | * |
593 | * LOCKING: | 593 | * LOCKING: |
594 | * Inherited from calling layer (may sleep). | 594 | * Inherited from calling layer (may sleep). |
595 | * | 595 | * |
596 | * RETURNS: | 596 | * RETURNS: |
597 | * 0 on success, -errno otherwise. | 597 | * 0 if at least one port is initialized, -ENODEV if no port is |
598 | * available. | ||
598 | */ | 599 | */ |
599 | int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask) | 600 | int ata_pci_init_native_host(struct ata_host *host) |
600 | { | 601 | { |
601 | struct device *gdev = host->dev; | 602 | struct device *gdev = host->dev; |
602 | struct pci_dev *pdev = to_pci_dev(gdev); | 603 | struct pci_dev *pdev = to_pci_dev(gdev); |
604 | unsigned int mask = 0; | ||
603 | int i, rc; | 605 | int i, rc; |
604 | 606 | ||
605 | /* Discard disabled ports. Some controllers show their unused | ||
606 | * channels this way. Disabled ports are made dummy. | ||
607 | */ | ||
608 | for (i = 0; i < 2; i++) { | ||
609 | if ((port_mask & (1 << i)) && !ata_resources_present(pdev, i)) { | ||
610 | host->ports[i]->ops = &ata_dummy_port_ops; | ||
611 | port_mask &= ~(1 << i); | ||
612 | } | ||
613 | } | ||
614 | |||
615 | if (!port_mask) { | ||
616 | dev_printk(KERN_ERR, gdev, "no available port\n"); | ||
617 | return -ENODEV; | ||
618 | } | ||
619 | |||
620 | /* request, iomap BARs and init port addresses accordingly */ | 607 | /* request, iomap BARs and init port addresses accordingly */ |
621 | for (i = 0; i < 2; i++) { | 608 | for (i = 0; i < 2; i++) { |
622 | struct ata_port *ap = host->ports[i]; | 609 | struct ata_port *ap = host->ports[i]; |
623 | int base = i * 2; | 610 | int base = i * 2; |
624 | void __iomem * const *iomap; | 611 | void __iomem * const *iomap; |
625 | 612 | ||
626 | if (!(port_mask & (1 << i))) | 613 | if (ata_port_is_dummy(ap)) |
614 | continue; | ||
615 | |||
616 | /* Discard disabled ports. Some controllers show | ||
617 | * their unused channels this way. Disabled ports are | ||
618 | * made dummy. | ||
619 | */ | ||
620 | if (!ata_resources_present(pdev, i)) { | ||
621 | ap->ops = &ata_dummy_port_ops; | ||
627 | continue; | 622 | continue; |
623 | } | ||
628 | 624 | ||
629 | rc = pcim_iomap_regions(pdev, 0x3 << base, DRV_NAME); | 625 | rc = pcim_iomap_regions(pdev, 0x3 << base, DRV_NAME); |
630 | if (rc) { | 626 | if (rc) { |
631 | dev_printk(KERN_ERR, gdev, "failed to request/iomap " | 627 | dev_printk(KERN_WARNING, gdev, |
632 | "BARs for port %d (errno=%d)\n", i, rc); | 628 | "failed to request/iomap BARs for port %d " |
629 | "(errno=%d)\n", i, rc); | ||
633 | if (rc == -EBUSY) | 630 | if (rc == -EBUSY) |
634 | pcim_pin_device(pdev); | 631 | pcim_pin_device(pdev); |
635 | return rc; | 632 | ap->ops = &ata_dummy_port_ops; |
633 | continue; | ||
636 | } | 634 | } |
637 | host->iomap = iomap = pcim_iomap_table(pdev); | 635 | host->iomap = iomap = pcim_iomap_table(pdev); |
638 | 636 | ||
@@ -641,6 +639,13 @@ int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask) | |||
641 | ap->ioaddr.ctl_addr = (void __iomem *) | 639 | ap->ioaddr.ctl_addr = (void __iomem *) |
642 | ((unsigned long)iomap[base + 1] | ATA_PCI_CTL_OFS); | 640 | ((unsigned long)iomap[base + 1] | ATA_PCI_CTL_OFS); |
643 | ata_std_ports(&ap->ioaddr); | 641 | ata_std_ports(&ap->ioaddr); |
642 | |||
643 | mask |= 1 << i; | ||
644 | } | ||
645 | |||
646 | if (!mask) { | ||
647 | dev_printk(KERN_ERR, gdev, "no available native port\n"); | ||
648 | return -ENODEV; | ||
644 | } | 649 | } |
645 | 650 | ||
646 | return 0; | 651 | return 0; |
@@ -649,8 +654,7 @@ int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask) | |||
649 | /** | 654 | /** |
650 | * ata_pci_prepare_native_host - helper to prepare native PCI ATA host | 655 | * ata_pci_prepare_native_host - helper to prepare native PCI ATA host |
651 | * @pdev: target PCI device | 656 | * @pdev: target PCI device |
652 | * @ppi: array of port_info | 657 | * @ppi: array of port_info, must be enough for two ports |
653 | * @n_ports: number of ports to allocate | ||
654 | * @r_host: out argument for the initialized ATA host | 658 | * @r_host: out argument for the initialized ATA host |
655 | * | 659 | * |
656 | * Helper to allocate ATA host for @pdev, acquire all native PCI | 660 | * Helper to allocate ATA host for @pdev, acquire all native PCI |
@@ -664,10 +668,9 @@ int ata_pci_init_native_host(struct ata_host *host, unsigned int port_mask) | |||
664 | */ | 668 | */ |
665 | int ata_pci_prepare_native_host(struct pci_dev *pdev, | 669 | int ata_pci_prepare_native_host(struct pci_dev *pdev, |
666 | const struct ata_port_info * const * ppi, | 670 | const struct ata_port_info * const * ppi, |
667 | int n_ports, struct ata_host **r_host) | 671 | struct ata_host **r_host) |
668 | { | 672 | { |
669 | struct ata_host *host; | 673 | struct ata_host *host; |
670 | unsigned int port_mask; | ||
671 | int rc; | 674 | int rc; |
672 | 675 | ||
673 | if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) | 676 | if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) |
@@ -681,11 +684,7 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev, | |||
681 | goto err_out; | 684 | goto err_out; |
682 | } | 685 | } |
683 | 686 | ||
684 | port_mask = ATA_PORT_PRIMARY; | 687 | rc = ata_pci_init_native_host(host); |
685 | if (n_ports > 1) | ||
686 | port_mask |= ATA_PORT_SECONDARY; | ||
687 | |||
688 | rc = ata_pci_init_native_host(host, port_mask); | ||
689 | if (rc) | 688 | if (rc) |
690 | goto err_out; | 689 | goto err_out; |
691 | 690 | ||
@@ -777,8 +776,11 @@ static int ata_init_legacy_port(struct ata_port *ap, | |||
777 | /* iomap cmd and ctl ports */ | 776 | /* iomap cmd and ctl ports */ |
778 | legacy_dr->cmd_addr[port_no] = ioport_map(cmd_port, 8); | 777 | legacy_dr->cmd_addr[port_no] = ioport_map(cmd_port, 8); |
779 | legacy_dr->ctl_addr[port_no] = ioport_map(ctl_port, 1); | 778 | legacy_dr->ctl_addr[port_no] = ioport_map(ctl_port, 1); |
780 | if (!legacy_dr->cmd_addr[port_no] || !legacy_dr->ctl_addr[port_no]) | 779 | if (!legacy_dr->cmd_addr[port_no] || !legacy_dr->ctl_addr[port_no]) { |
780 | dev_printk(KERN_WARNING, host->dev, | ||
781 | "failed to map cmd/ctl ports\n"); | ||
781 | return -ENOMEM; | 782 | return -ENOMEM; |
783 | } | ||
782 | 784 | ||
783 | /* init IO addresses */ | 785 | /* init IO addresses */ |
784 | ap->ioaddr.cmd_addr = legacy_dr->cmd_addr[port_no]; | 786 | ap->ioaddr.cmd_addr = legacy_dr->cmd_addr[port_no]; |
@@ -792,19 +794,20 @@ static int ata_init_legacy_port(struct ata_port *ap, | |||
792 | /** | 794 | /** |
793 | * ata_init_legacy_host - acquire legacy ATA resources and init ATA host | 795 | * ata_init_legacy_host - acquire legacy ATA resources and init ATA host |
794 | * @host: target ATA host | 796 | * @host: target ATA host |
795 | * @legacy_mask: out parameter, mask indicating ports is in legacy mode | ||
796 | * @was_busy: out parameter, indicates whether any port was busy | 797 | * @was_busy: out parameter, indicates whether any port was busy |
797 | * | 798 | * |
798 | * Acquire legacy ATA resources for ports. | 799 | * Acquire legacy ATA resources for the first two ports of @host |
800 | * and initialize it accordingly. Ports marked dummy are skipped | ||
801 | * and resource acquistion failure makes the port dummy. | ||
799 | * | 802 | * |
800 | * LOCKING: | 803 | * LOCKING: |
801 | * Inherited from calling layer (may sleep). | 804 | * Inherited from calling layer (may sleep). |
802 | * | 805 | * |
803 | * RETURNS: | 806 | * RETURNS: |
804 | * 0 on success, -errno otherwise. | 807 | * 0 if at least one port is initialized, -ENODEV if no port is |
808 | * available. | ||
805 | */ | 809 | */ |
806 | static int ata_init_legacy_host(struct ata_host *host, | 810 | static int ata_init_legacy_host(struct ata_host *host, int *was_busy) |
807 | unsigned int *legacy_mask, int *was_busy) | ||
808 | { | 811 | { |
809 | struct device *gdev = host->dev; | 812 | struct device *gdev = host->dev; |
810 | struct ata_legacy_devres *legacy_dr; | 813 | struct ata_legacy_devres *legacy_dr; |
@@ -821,22 +824,23 @@ static int ata_init_legacy_host(struct ata_host *host, | |||
821 | devres_add(gdev, legacy_dr); | 824 | devres_add(gdev, legacy_dr); |
822 | 825 | ||
823 | for (i = 0; i < 2; i++) { | 826 | for (i = 0; i < 2; i++) { |
824 | *legacy_mask &= ~(1 << i); | 827 | if (ata_port_is_dummy(host->ports[i])) |
828 | continue; | ||
829 | |||
825 | rc = ata_init_legacy_port(host->ports[i], legacy_dr); | 830 | rc = ata_init_legacy_port(host->ports[i], legacy_dr); |
826 | if (rc == 0) | 831 | if (rc == 0) |
827 | legacy_dr->mask |= 1 << i; | 832 | legacy_dr->mask |= 1 << i; |
828 | else if (rc == -EBUSY) | 833 | else { |
829 | (*was_busy)++; | 834 | if (rc == -EBUSY) |
830 | } | 835 | (*was_busy)++; |
831 | |||
832 | if (!legacy_dr->mask) | ||
833 | return -EBUSY; | ||
834 | |||
835 | for (i = 0; i < 2; i++) | ||
836 | if (!(legacy_dr->mask & (1 << i))) | ||
837 | host->ports[i]->ops = &ata_dummy_port_ops; | 836 | host->ports[i]->ops = &ata_dummy_port_ops; |
837 | } | ||
838 | } | ||
838 | 839 | ||
839 | *legacy_mask |= legacy_dr->mask; | 840 | if (!legacy_dr->mask) { |
841 | dev_printk(KERN_ERR, gdev, "no available legacy port\n"); | ||
842 | return -ENODEV; | ||
843 | } | ||
840 | 844 | ||
841 | devres_remove_group(gdev, NULL); | 845 | devres_remove_group(gdev, NULL); |
842 | return 0; | 846 | return 0; |
@@ -875,7 +879,7 @@ static int ata_request_legacy_irqs(struct ata_host *host, | |||
875 | legacy_dr = devres_find(host->dev, ata_legacy_release, NULL, NULL); | 879 | legacy_dr = devres_find(host->dev, ata_legacy_release, NULL, NULL); |
876 | BUG_ON(!legacy_dr); | 880 | BUG_ON(!legacy_dr); |
877 | 881 | ||
878 | for (i = 0; i < host->n_ports; i++) { | 882 | for (i = 0; i < 2; i++) { |
879 | unsigned int irq; | 883 | unsigned int irq; |
880 | 884 | ||
881 | /* FIXME: ATA_*_IRQ() should take generic device not pci_dev */ | 885 | /* FIXME: ATA_*_IRQ() should take generic device not pci_dev */ |
@@ -923,8 +927,7 @@ static int ata_request_legacy_irqs(struct ata_host *host, | |||
923 | /** | 927 | /** |
924 | * ata_pci_init_one - Initialize/register PCI IDE host controller | 928 | * ata_pci_init_one - Initialize/register PCI IDE host controller |
925 | * @pdev: Controller to be initialized | 929 | * @pdev: Controller to be initialized |
926 | * @port_info: Information from low-level host driver | 930 | * @ppi: array of port_info, must be enough for two ports |
927 | * @n_ports: Number of ports attached to host controller | ||
928 | * | 931 | * |
929 | * This is a helper function which can be called from a driver's | 932 | * This is a helper function which can be called from a driver's |
930 | * xxx_init_one() probe function if the hardware uses traditional | 933 | * xxx_init_one() probe function if the hardware uses traditional |
@@ -944,26 +947,34 @@ static int ata_request_legacy_irqs(struct ata_host *host, | |||
944 | * RETURNS: | 947 | * RETURNS: |
945 | * Zero on success, negative on errno-based value on error. | 948 | * Zero on success, negative on errno-based value on error. |
946 | */ | 949 | */ |
947 | 950 | int ata_pci_init_one(struct pci_dev *pdev, | |
948 | int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, | 951 | const struct ata_port_info * const * ppi) |
949 | unsigned int n_ports) | ||
950 | { | 952 | { |
951 | struct device *dev = &pdev->dev; | 953 | struct device *dev = &pdev->dev; |
954 | const struct ata_port_info *pi = NULL; | ||
952 | struct ata_host *host = NULL; | 955 | struct ata_host *host = NULL; |
953 | const struct ata_port_info *port[2]; | ||
954 | u8 mask; | 956 | u8 mask; |
955 | unsigned int legacy_mode = 0; | 957 | int legacy_mode = 0; |
956 | int rc; | 958 | int i, rc; |
957 | 959 | ||
958 | DPRINTK("ENTER\n"); | 960 | DPRINTK("ENTER\n"); |
959 | 961 | ||
960 | if (!devres_open_group(dev, NULL, GFP_KERNEL)) | 962 | /* look up the first valid port_info */ |
961 | return -ENOMEM; | 963 | for (i = 0; i < 2 && ppi[i]; i++) { |
964 | if (ppi[i]->port_ops != &ata_dummy_port_ops) { | ||
965 | pi = ppi[i]; | ||
966 | break; | ||
967 | } | ||
968 | } | ||
962 | 969 | ||
963 | BUG_ON(n_ports < 1 || n_ports > 2); | 970 | if (!pi) { |
971 | dev_printk(KERN_ERR, &pdev->dev, | ||
972 | "no valid port_info specified\n"); | ||
973 | return -EINVAL; | ||
974 | } | ||
964 | 975 | ||
965 | port[0] = port_info[0]; | 976 | if (!devres_open_group(dev, NULL, GFP_KERNEL)) |
966 | port[1] = (n_ports > 1) ? port_info[1] : NULL; | 977 | return -ENOMEM; |
967 | 978 | ||
968 | /* FIXME: Really for ATA it isn't safe because the device may be | 979 | /* FIXME: Really for ATA it isn't safe because the device may be |
969 | multi-purpose and we want to leave it alone if it was already | 980 | multi-purpose and we want to leave it alone if it was already |
@@ -984,7 +995,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, | |||
984 | pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); | 995 | pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); |
985 | mask = (1 << 2) | (1 << 0); | 996 | mask = (1 << 2) | (1 << 0); |
986 | if ((tmp8 & mask) != mask) | 997 | if ((tmp8 & mask) != mask) |
987 | legacy_mode = (1 << 3); | 998 | legacy_mode = 1; |
988 | #if defined(CONFIG_NO_ATA_LEGACY) | 999 | #if defined(CONFIG_NO_ATA_LEGACY) |
989 | /* Some platforms with PCI limits cannot address compat | 1000 | /* Some platforms with PCI limits cannot address compat |
990 | port space. In that case we punt if their firmware has | 1001 | port space. In that case we punt if their firmware has |
@@ -998,7 +1009,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, | |||
998 | } | 1009 | } |
999 | 1010 | ||
1000 | /* alloc and init host */ | 1011 | /* alloc and init host */ |
1001 | host = ata_host_alloc_pinfo(dev, port, n_ports); | 1012 | host = ata_host_alloc_pinfo(dev, ppi, 2); |
1002 | if (!host) { | 1013 | if (!host) { |
1003 | dev_printk(KERN_ERR, &pdev->dev, | 1014 | dev_printk(KERN_ERR, &pdev->dev, |
1004 | "failed to allocate ATA host\n"); | 1015 | "failed to allocate ATA host\n"); |
@@ -1007,19 +1018,13 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, | |||
1007 | } | 1018 | } |
1008 | 1019 | ||
1009 | if (!legacy_mode) { | 1020 | if (!legacy_mode) { |
1010 | unsigned int port_mask; | 1021 | rc = ata_pci_init_native_host(host); |
1011 | |||
1012 | port_mask = ATA_PORT_PRIMARY; | ||
1013 | if (n_ports > 1) | ||
1014 | port_mask |= ATA_PORT_SECONDARY; | ||
1015 | |||
1016 | rc = ata_pci_init_native_host(host, port_mask); | ||
1017 | if (rc) | 1022 | if (rc) |
1018 | goto err_out; | 1023 | goto err_out; |
1019 | } else { | 1024 | } else { |
1020 | int was_busy = 0; | 1025 | int was_busy = 0; |
1021 | 1026 | ||
1022 | rc = ata_init_legacy_host(host, &legacy_mode, &was_busy); | 1027 | rc = ata_init_legacy_host(host, &was_busy); |
1023 | if (was_busy) | 1028 | if (was_busy) |
1024 | pcim_pin_device(pdev); | 1029 | pcim_pin_device(pdev); |
1025 | if (rc) | 1030 | if (rc) |
@@ -1040,8 +1045,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, | |||
1040 | goto err_out; | 1045 | goto err_out; |
1041 | 1046 | ||
1042 | if (!legacy_mode) | 1047 | if (!legacy_mode) |
1043 | rc = devm_request_irq(dev, pdev->irq, | 1048 | rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler, |
1044 | port_info[0]->port_ops->irq_handler, | ||
1045 | IRQF_SHARED, DRV_NAME, host); | 1049 | IRQF_SHARED, DRV_NAME, host); |
1046 | else { | 1050 | else { |
1047 | irq_handler_t handler[2] = { host->ops->irq_handler, | 1051 | irq_handler_t handler[2] = { host->ops->irq_handler, |
@@ -1055,7 +1059,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, | |||
1055 | goto err_out; | 1059 | goto err_out; |
1056 | 1060 | ||
1057 | /* register */ | 1061 | /* register */ |
1058 | rc = ata_host_register(host, port_info[0]->sht); | 1062 | rc = ata_host_register(host, pi->sht); |
1059 | if (rc) | 1063 | if (rc) |
1060 | goto err_out; | 1064 | goto err_out; |
1061 | 1065 | ||