aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2008-01-18 04:36:28 -0500
committerJeff Garzik <jeff@garzik.org>2008-01-23 05:24:16 -0500
commit4e6b79fa61091a0ed9b0af0f573cc257772cd88d (patch)
treecd3e9dca0355741713d038b0068cd4ba32f87b56 /drivers/ata
parentcadb7345d92628d46cccd3765cc15cb9cd6abccf (diff)
libata: factor out ata_pci_activate_sff_host() from ata_pci_one()
Factor out ata_pci_activate_sff_host() from ata_pci_one(). This does about the same thing as ata_host_activate() but needs to be separate because SFF controllers use different and multiple IRQs in legacy mode. This will be used to make SFF LLD initialization more flexible. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-core.c1
-rw-r--r--drivers/ata/libata-sff.c187
2 files changed, 104 insertions, 84 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 8c82193b077e..ce803d18e96a 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -7629,6 +7629,7 @@ EXPORT_SYMBOL_GPL(pci_test_config_bits);
7629EXPORT_SYMBOL_GPL(ata_pci_init_sff_host); 7629EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
7630EXPORT_SYMBOL_GPL(ata_pci_init_bmdma); 7630EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
7631EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host); 7631EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
7632EXPORT_SYMBOL_GPL(ata_pci_activate_sff_host);
7632EXPORT_SYMBOL_GPL(ata_pci_init_one); 7633EXPORT_SYMBOL_GPL(ata_pci_init_one);
7633EXPORT_SYMBOL_GPL(ata_pci_remove_one); 7634EXPORT_SYMBOL_GPL(ata_pci_remove_one);
7634#ifdef CONFIG_PM 7635#ifdef CONFIG_PM
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 97dd8f2796b7..60cd4b179766 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -714,6 +714,99 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
714} 714}
715 715
716/** 716/**
717 * ata_pci_activate_sff_host - start SFF host, request IRQ and register it
718 * @host: target SFF ATA host
719 * @irq_handler: irq_handler used when requesting IRQ(s)
720 * @sht: scsi_host_template to use when registering the host
721 *
722 * This is the counterpart of ata_host_activate() for SFF ATA
723 * hosts. This separate helper is necessary because SFF hosts
724 * use two separate interrupts in legacy mode.
725 *
726 * LOCKING:
727 * Inherited from calling layer (may sleep).
728 *
729 * RETURNS:
730 * 0 on success, -errno otherwise.
731 */
732int ata_pci_activate_sff_host(struct ata_host *host,
733 irq_handler_t irq_handler,
734 struct scsi_host_template *sht)
735{
736 struct device *dev = host->dev;
737 struct pci_dev *pdev = to_pci_dev(dev);
738 const char *drv_name = dev_driver_string(host->dev);
739 int legacy_mode = 0, rc;
740
741 rc = ata_host_start(host);
742 if (rc)
743 return rc;
744
745 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
746 u8 tmp8, mask;
747
748 /* TODO: What if one channel is in native mode ... */
749 pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
750 mask = (1 << 2) | (1 << 0);
751 if ((tmp8 & mask) != mask)
752 legacy_mode = 1;
753#if defined(CONFIG_NO_ATA_LEGACY)
754 /* Some platforms with PCI limits cannot address compat
755 port space. In that case we punt if their firmware has
756 left a device in compatibility mode */
757 if (legacy_mode) {
758 printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
759 return -EOPNOTSUPP;
760 }
761#endif
762 }
763
764 if (!devres_open_group(dev, NULL, GFP_KERNEL))
765 return -ENOMEM;
766
767 if (!legacy_mode && pdev->irq) {
768 rc = devm_request_irq(dev, pdev->irq, irq_handler,
769 IRQF_SHARED, drv_name, host);
770 if (rc)
771 goto out;
772
773 ata_port_desc(host->ports[0], "irq %d", pdev->irq);
774 ata_port_desc(host->ports[1], "irq %d", pdev->irq);
775 } else if (legacy_mode) {
776 if (!ata_port_is_dummy(host->ports[0])) {
777 rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev),
778 irq_handler, IRQF_SHARED,
779 drv_name, host);
780 if (rc)
781 goto out;
782
783 ata_port_desc(host->ports[0], "irq %d",
784 ATA_PRIMARY_IRQ(pdev));
785 }
786
787 if (!ata_port_is_dummy(host->ports[1])) {
788 rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev),
789 irq_handler, IRQF_SHARED,
790 drv_name, host);
791 if (rc)
792 goto out;
793
794 ata_port_desc(host->ports[1], "irq %d",
795 ATA_SECONDARY_IRQ(pdev));
796 }
797 }
798
799 rc = ata_host_register(host, sht);
800 out:
801 if (rc == 0)
802 devres_remove_group(dev, NULL);
803 else
804 devres_release_group(dev, NULL);
805
806 return rc;
807}
808
809/**
717 * ata_pci_init_one - Initialize/register PCI IDE host controller 810 * ata_pci_init_one - Initialize/register PCI IDE host controller
718 * @pdev: Controller to be initialized 811 * @pdev: Controller to be initialized
719 * @ppi: array of port_info, must be enough for two ports 812 * @ppi: array of port_info, must be enough for two ports
@@ -742,9 +835,6 @@ int ata_pci_init_one(struct pci_dev *pdev,
742 struct device *dev = &pdev->dev; 835 struct device *dev = &pdev->dev;
743 const struct ata_port_info *pi = NULL; 836 const struct ata_port_info *pi = NULL;
744 struct ata_host *host = NULL; 837 struct ata_host *host = NULL;
745 const char *drv_name = dev_driver_string(&pdev->dev);
746 u8 mask;
747 int legacy_mode = 0;
748 int i, rc; 838 int i, rc;
749 839
750 DPRINTK("ENTER\n"); 840 DPRINTK("ENTER\n");
@@ -766,95 +856,24 @@ int ata_pci_init_one(struct pci_dev *pdev,
766 if (!devres_open_group(dev, NULL, GFP_KERNEL)) 856 if (!devres_open_group(dev, NULL, GFP_KERNEL))
767 return -ENOMEM; 857 return -ENOMEM;
768 858
769 /* FIXME: Really for ATA it isn't safe because the device may be
770 multi-purpose and we want to leave it alone if it was already
771 enabled. Secondly for shared use as Arjan says we want refcounting
772
773 Checking dev->is_enabled is insufficient as this is not set at
774 boot for the primary video which is BIOS enabled
775 */
776
777 rc = pcim_enable_device(pdev); 859 rc = pcim_enable_device(pdev);
778 if (rc) 860 if (rc)
779 goto err_out; 861 goto out;
780 862
781 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { 863 /* prepare and activate SFF host */
782 u8 tmp8;
783
784 /* TODO: What if one channel is in native mode ... */
785 pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
786 mask = (1 << 2) | (1 << 0);
787 if ((tmp8 & mask) != mask)
788 legacy_mode = 1;
789#if defined(CONFIG_NO_ATA_LEGACY)
790 /* Some platforms with PCI limits cannot address compat
791 port space. In that case we punt if their firmware has
792 left a device in compatibility mode */
793 if (legacy_mode) {
794 printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
795 rc = -EOPNOTSUPP;
796 goto err_out;
797 }
798#endif
799 }
800
801 /* prepare host */
802 rc = ata_pci_prepare_sff_host(pdev, ppi, &host); 864 rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
803 if (rc) 865 if (rc)
804 goto err_out; 866 goto out;
805 867
806 pci_set_master(pdev); 868 pci_set_master(pdev);
869 rc = ata_pci_activate_sff_host(host, pi->port_ops->irq_handler,
870 pi->sht);
871 out:
872 if (rc == 0)
873 devres_remove_group(&pdev->dev, NULL);
874 else
875 devres_release_group(&pdev->dev, NULL);
807 876
808 /* start host and request IRQ */
809 rc = ata_host_start(host);
810 if (rc)
811 goto err_out;
812
813 if (!legacy_mode && pdev->irq) {
814 /* We may have no IRQ assigned in which case we can poll. This
815 shouldn't happen on a sane system but robustness is cheap
816 in this case */
817 rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler,
818 IRQF_SHARED, drv_name, host);
819 if (rc)
820 goto err_out;
821
822 ata_port_desc(host->ports[0], "irq %d", pdev->irq);
823 ata_port_desc(host->ports[1], "irq %d", pdev->irq);
824 } else if (legacy_mode) {
825 if (!ata_port_is_dummy(host->ports[0])) {
826 rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev),
827 pi->port_ops->irq_handler,
828 IRQF_SHARED, drv_name, host);
829 if (rc)
830 goto err_out;
831
832 ata_port_desc(host->ports[0], "irq %d",
833 ATA_PRIMARY_IRQ(pdev));
834 }
835
836 if (!ata_port_is_dummy(host->ports[1])) {
837 rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev),
838 pi->port_ops->irq_handler,
839 IRQF_SHARED, drv_name, host);
840 if (rc)
841 goto err_out;
842
843 ata_port_desc(host->ports[1], "irq %d",
844 ATA_SECONDARY_IRQ(pdev));
845 }
846 }
847
848 /* register */
849 rc = ata_host_register(host, pi->sht);
850 if (rc)
851 goto err_out;
852
853 devres_remove_group(dev, NULL);
854 return 0;
855
856err_out:
857 devres_release_group(dev, NULL);
858 return rc; 877 return rc;
859} 878}
860 879