diff options
32 files changed, 1073 insertions, 1572 deletions
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 3c10b9a1ddf5..ab642a4f08de 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c | |||
| @@ -575,3 +575,7 @@ void pci_iounmap(struct pci_dev *dev, void __iomem * addr) | |||
| 575 | 575 | ||
| 576 | EXPORT_SYMBOL(pci_iomap); | 576 | EXPORT_SYMBOL(pci_iomap); |
| 577 | EXPORT_SYMBOL(pci_iounmap); | 577 | EXPORT_SYMBOL(pci_iounmap); |
| 578 | |||
| 579 | /* FIXME: Some boxes have multiple ISA bridges! */ | ||
| 580 | struct pci_dev *isa_bridge; | ||
| 581 | EXPORT_SYMBOL(isa_bridge); | ||
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 6a3875f81a0a..5592fa6e1fa1 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
| @@ -2606,25 +2606,32 @@ static struct irq_chip msi_chip = { | |||
| 2606 | .retrigger = ioapic_retrigger_irq, | 2606 | .retrigger = ioapic_retrigger_irq, |
| 2607 | }; | 2607 | }; |
| 2608 | 2608 | ||
| 2609 | int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev) | 2609 | int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) |
| 2610 | { | 2610 | { |
| 2611 | struct msi_msg msg; | 2611 | struct msi_msg msg; |
| 2612 | int ret; | 2612 | int irq, ret; |
| 2613 | irq = create_irq(); | ||
| 2614 | if (irq < 0) | ||
| 2615 | return irq; | ||
| 2616 | |||
| 2617 | set_irq_msi(irq, desc); | ||
| 2613 | ret = msi_compose_msg(dev, irq, &msg); | 2618 | ret = msi_compose_msg(dev, irq, &msg); |
| 2614 | if (ret < 0) | 2619 | if (ret < 0) { |
| 2620 | destroy_irq(irq); | ||
| 2615 | return ret; | 2621 | return ret; |
| 2622 | } | ||
| 2616 | 2623 | ||
| 2617 | write_msi_msg(irq, &msg); | 2624 | write_msi_msg(irq, &msg); |
| 2618 | 2625 | ||
| 2619 | set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, | 2626 | set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, |
| 2620 | "edge"); | 2627 | "edge"); |
| 2621 | 2628 | ||
| 2622 | return 0; | 2629 | return irq; |
| 2623 | } | 2630 | } |
| 2624 | 2631 | ||
| 2625 | void arch_teardown_msi_irq(unsigned int irq) | 2632 | void arch_teardown_msi_irq(unsigned int irq) |
| 2626 | { | 2633 | { |
| 2627 | return; | 2634 | destroy_irq(irq); |
| 2628 | } | 2635 | } |
| 2629 | 2636 | ||
| 2630 | #endif /* CONFIG_PCI_MSI */ | 2637 | #endif /* CONFIG_PCI_MSI */ |
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index 822e59a1b822..0d05450c91c4 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c | |||
| @@ -64,12 +64,17 @@ static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask) | |||
| 64 | } | 64 | } |
| 65 | #endif /* CONFIG_SMP */ | 65 | #endif /* CONFIG_SMP */ |
| 66 | 66 | ||
| 67 | int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | 67 | int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) |
| 68 | { | 68 | { |
| 69 | struct msi_msg msg; | 69 | struct msi_msg msg; |
| 70 | unsigned long dest_phys_id; | 70 | unsigned long dest_phys_id; |
| 71 | unsigned int vector; | 71 | unsigned int irq, vector; |
| 72 | 72 | ||
| 73 | irq = create_irq(); | ||
| 74 | if (irq < 0) | ||
| 75 | return irq; | ||
| 76 | |||
| 77 | set_irq_msi(irq, desc); | ||
| 73 | dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); | 78 | dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); |
| 74 | vector = irq; | 79 | vector = irq; |
| 75 | 80 | ||
| @@ -89,12 +94,12 @@ int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | |||
| 89 | write_msi_msg(irq, &msg); | 94 | write_msi_msg(irq, &msg); |
| 90 | set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); | 95 | set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); |
| 91 | 96 | ||
| 92 | return 0; | 97 | return irq; |
| 93 | } | 98 | } |
| 94 | 99 | ||
| 95 | void ia64_teardown_msi_irq(unsigned int irq) | 100 | void ia64_teardown_msi_irq(unsigned int irq) |
| 96 | { | 101 | { |
| 97 | return; /* no-op */ | 102 | destroy_irq(irq); |
| 98 | } | 103 | } |
| 99 | 104 | ||
| 100 | static void ia64_ack_msi_irq(unsigned int irq) | 105 | static void ia64_ack_msi_irq(unsigned int irq) |
| @@ -126,12 +131,12 @@ static struct irq_chip ia64_msi_chip = { | |||
| 126 | }; | 131 | }; |
| 127 | 132 | ||
| 128 | 133 | ||
| 129 | int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | 134 | int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) |
| 130 | { | 135 | { |
| 131 | if (platform_setup_msi_irq) | 136 | if (platform_setup_msi_irq) |
| 132 | return platform_setup_msi_irq(irq, pdev); | 137 | return platform_setup_msi_irq(pdev, desc); |
| 133 | 138 | ||
| 134 | return ia64_setup_msi_irq(irq, pdev); | 139 | return ia64_setup_msi_irq(pdev, desc); |
| 135 | } | 140 | } |
| 136 | 141 | ||
| 137 | void arch_teardown_msi_irq(unsigned int irq) | 142 | void arch_teardown_msi_irq(unsigned int irq) |
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c index b3a435fd70fb..ea3dc38d73fd 100644 --- a/arch/ia64/sn/kernel/msi_sn.c +++ b/arch/ia64/sn/kernel/msi_sn.c | |||
| @@ -59,13 +59,12 @@ void sn_teardown_msi_irq(unsigned int irq) | |||
| 59 | sn_intr_free(nasid, widget, sn_irq_info); | 59 | sn_intr_free(nasid, widget, sn_irq_info); |
| 60 | sn_msi_info[irq].sn_irq_info = NULL; | 60 | sn_msi_info[irq].sn_irq_info = NULL; |
| 61 | 61 | ||
| 62 | return; | 62 | destroy_irq(irq); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | 65 | int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) |
| 66 | { | 66 | { |
| 67 | struct msi_msg msg; | 67 | struct msi_msg msg; |
| 68 | struct msi_desc *entry; | ||
| 69 | int widget; | 68 | int widget; |
| 70 | int status; | 69 | int status; |
| 71 | nasid_t nasid; | 70 | nasid_t nasid; |
| @@ -73,8 +72,8 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | |||
| 73 | struct sn_irq_info *sn_irq_info; | 72 | struct sn_irq_info *sn_irq_info; |
| 74 | struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); | 73 | struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); |
| 75 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); | 74 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); |
| 75 | int irq; | ||
| 76 | 76 | ||
| 77 | entry = get_irq_data(irq); | ||
| 78 | if (!entry->msi_attrib.is_64) | 77 | if (!entry->msi_attrib.is_64) |
| 79 | return -EINVAL; | 78 | return -EINVAL; |
| 80 | 79 | ||
| @@ -84,6 +83,11 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | |||
| 84 | if (provider == NULL || provider->dma_map_consistent == NULL) | 83 | if (provider == NULL || provider->dma_map_consistent == NULL) |
| 85 | return -EINVAL; | 84 | return -EINVAL; |
| 86 | 85 | ||
| 86 | irq = create_irq(); | ||
| 87 | if (irq < 0) | ||
| 88 | return irq; | ||
| 89 | |||
| 90 | set_irq_msi(irq, entry); | ||
| 87 | /* | 91 | /* |
| 88 | * Set up the vector plumbing. Let the prom (via sn_intr_alloc) | 92 | * Set up the vector plumbing. Let the prom (via sn_intr_alloc) |
| 89 | * decide which cpu to direct this msi at by default. | 93 | * decide which cpu to direct this msi at by default. |
| @@ -95,12 +99,15 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | |||
| 95 | SWIN_WIDGETNUM(bussoft->bs_base); | 99 | SWIN_WIDGETNUM(bussoft->bs_base); |
| 96 | 100 | ||
| 97 | sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); | 101 | sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); |
| 98 | if (! sn_irq_info) | 102 | if (! sn_irq_info) { |
| 103 | destroy_irq(irq); | ||
| 99 | return -ENOMEM; | 104 | return -ENOMEM; |
| 105 | } | ||
| 100 | 106 | ||
| 101 | status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1); | 107 | status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1); |
| 102 | if (status) { | 108 | if (status) { |
| 103 | kfree(sn_irq_info); | 109 | kfree(sn_irq_info); |
| 110 | destroy_irq(irq); | ||
| 104 | return -ENOMEM; | 111 | return -ENOMEM; |
| 105 | } | 112 | } |
| 106 | 113 | ||
| @@ -121,6 +128,7 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | |||
| 121 | if (! bus_addr) { | 128 | if (! bus_addr) { |
| 122 | sn_intr_free(nasid, widget, sn_irq_info); | 129 | sn_intr_free(nasid, widget, sn_irq_info); |
| 123 | kfree(sn_irq_info); | 130 | kfree(sn_irq_info); |
| 131 | destroy_irq(irq); | ||
| 124 | return -ENOMEM; | 132 | return -ENOMEM; |
| 125 | } | 133 | } |
| 126 | 134 | ||
| @@ -139,7 +147,7 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | |||
| 139 | write_msi_msg(irq, &msg); | 147 | write_msi_msg(irq, &msg); |
| 140 | set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq); | 148 | set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq); |
| 141 | 149 | ||
| 142 | return 0; | 150 | return irq; |
| 143 | } | 151 | } |
| 144 | 152 | ||
| 145 | #ifdef CONFIG_SMP | 153 | #ifdef CONFIG_SMP |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 01f18c683407..2b52b087aaa8 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
| @@ -381,8 +381,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
| 381 | 381 | ||
| 382 | pci_device_add(dev, bus); | 382 | pci_device_add(dev, bus); |
| 383 | 383 | ||
| 384 | /* XXX pci_scan_msi_device(dev); */ | ||
| 385 | |||
| 386 | return dev; | 384 | return dev; |
| 387 | } | 385 | } |
| 388 | EXPORT_SYMBOL(of_create_pci_dev); | 386 | EXPORT_SYMBOL(of_create_pci_dev); |
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index d7bad90a5ad8..6be6730acb5c 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c | |||
| @@ -1956,24 +1956,31 @@ static struct irq_chip msi_chip = { | |||
| 1956 | .retrigger = ioapic_retrigger_irq, | 1956 | .retrigger = ioapic_retrigger_irq, |
| 1957 | }; | 1957 | }; |
| 1958 | 1958 | ||
| 1959 | int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev) | 1959 | int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) |
| 1960 | { | 1960 | { |
| 1961 | struct msi_msg msg; | 1961 | struct msi_msg msg; |
| 1962 | int ret; | 1962 | int irq, ret; |
| 1963 | irq = create_irq(); | ||
| 1964 | if (irq < 0) | ||
| 1965 | return irq; | ||
| 1966 | |||
| 1967 | set_irq_msi(irq, desc); | ||
| 1963 | ret = msi_compose_msg(dev, irq, &msg); | 1968 | ret = msi_compose_msg(dev, irq, &msg); |
| 1964 | if (ret < 0) | 1969 | if (ret < 0) { |
| 1970 | destroy_irq(irq); | ||
| 1965 | return ret; | 1971 | return ret; |
| 1972 | } | ||
| 1966 | 1973 | ||
| 1967 | write_msi_msg(irq, &msg); | 1974 | write_msi_msg(irq, &msg); |
| 1968 | 1975 | ||
| 1969 | set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); | 1976 | set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); |
| 1970 | 1977 | ||
| 1971 | return 0; | 1978 | return irq; |
| 1972 | } | 1979 | } |
| 1973 | 1980 | ||
| 1974 | void arch_teardown_msi_irq(unsigned int irq) | 1981 | void arch_teardown_msi_irq(unsigned int irq) |
| 1975 | { | 1982 | { |
| 1976 | return; | 1983 | destroy_irq(irq); |
| 1977 | } | 1984 | } |
| 1978 | 1985 | ||
| 1979 | #endif /* CONFIG_PCI_MSI */ | 1986 | #endif /* CONFIG_PCI_MSI */ |
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index c416c18007da..5a96d7611af1 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
| @@ -5947,8 +5947,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
| 5947 | * responding after a while. | 5947 | * responding after a while. |
| 5948 | * | 5948 | * |
| 5949 | * AMD believes this incompatibility is unique to the 5706, and | 5949 | * AMD believes this incompatibility is unique to the 5706, and |
| 5950 | * prefers to locally disable MSI rather than globally disabling it | 5950 | * prefers to locally disable MSI rather than globally disabling it. |
| 5951 | * using pci_msi_quirk. | ||
| 5952 | */ | 5951 | */ |
| 5953 | if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) { | 5952 | if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) { |
| 5954 | struct pci_dev *amd_8132 = NULL; | 5953 | struct pci_dev *amd_8132 = NULL; |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 222fcd2d10de..619c89218b4b 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
| @@ -3584,7 +3584,7 @@ e1000_update_stats(struct e1000_adapter *adapter) | |||
| 3584 | */ | 3584 | */ |
| 3585 | if (adapter->link_speed == 0) | 3585 | if (adapter->link_speed == 0) |
| 3586 | return; | 3586 | return; |
| 3587 | if (pdev->error_state && pdev->error_state != pci_channel_io_normal) | 3587 | if (pci_channel_offline(pdev)) |
| 3588 | return; | 3588 | return; |
| 3589 | 3589 | ||
| 3590 | spin_lock_irqsave(&adapter->stats_lock, flags); | 3590 | spin_lock_irqsave(&adapter->stats_lock, flags); |
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 51bd7e8ff0d6..0c3682889344 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c | |||
| @@ -1605,7 +1605,7 @@ ixgb_update_stats(struct ixgb_adapter *adapter) | |||
| 1605 | struct pci_dev *pdev = adapter->pdev; | 1605 | struct pci_dev *pdev = adapter->pdev; |
| 1606 | 1606 | ||
| 1607 | /* Prevent stats update while adapter is being reset */ | 1607 | /* Prevent stats update while adapter is being reset */ |
| 1608 | if (pdev->error_state && pdev->error_state != pci_channel_io_normal) | 1608 | if (pci_channel_offline(pdev)) |
| 1609 | return; | 1609 | return; |
| 1610 | 1610 | ||
| 1611 | if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) || | 1611 | if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) || |
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index adce4204d87d..be92695a7833 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig | |||
| @@ -145,15 +145,6 @@ config HOTPLUG_PCI_SHPC | |||
| 145 | 145 | ||
| 146 | When in doubt, say N. | 146 | When in doubt, say N. |
| 147 | 147 | ||
| 148 | config HOTPLUG_PCI_SHPC_POLL_EVENT_MODE | ||
| 149 | bool "Use polling mechanism for hot-plug events (for testing purpose)" | ||
| 150 | depends on HOTPLUG_PCI_SHPC | ||
| 151 | help | ||
| 152 | Say Y here if you want to use the polling mechanism for hot-plug | ||
| 153 | events for early platform testing. | ||
| 154 | |||
| 155 | When in doubt, say N. | ||
| 156 | |||
| 157 | config HOTPLUG_PCI_RPA | 148 | config HOTPLUG_PCI_RPA |
| 158 | tristate "RPA PCI Hotplug driver" | 149 | tristate "RPA PCI Hotplug driver" |
| 159 | depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE | 150 | depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 4fb12fcda563..d19fcae8a7c0 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
| @@ -44,15 +44,20 @@ extern int pciehp_poll_time; | |||
| 44 | extern int pciehp_debug; | 44 | extern int pciehp_debug; |
| 45 | extern int pciehp_force; | 45 | extern int pciehp_force; |
| 46 | 46 | ||
| 47 | /*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ | 47 | #define dbg(format, arg...) \ |
| 48 | #define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) | 48 | do { \ |
| 49 | #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) | 49 | if (pciehp_debug) \ |
| 50 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) | 50 | printk("%s: " format, MY_NAME , ## arg); \ |
| 51 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) | 51 | } while (0) |
| 52 | 52 | #define err(format, arg...) \ | |
| 53 | printk(KERN_ERR "%s: " format, MY_NAME , ## arg) | ||
| 54 | #define info(format, arg...) \ | ||
| 55 | printk(KERN_INFO "%s: " format, MY_NAME , ## arg) | ||
| 56 | #define warn(format, arg...) \ | ||
| 57 | printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) | ||
| 53 | 58 | ||
| 59 | #define SLOT_NAME_SIZE 10 | ||
| 54 | struct slot { | 60 | struct slot { |
| 55 | struct slot *next; | ||
| 56 | u8 bus; | 61 | u8 bus; |
| 57 | u8 device; | 62 | u8 device; |
| 58 | u32 number; | 63 | u32 number; |
| @@ -63,6 +68,8 @@ struct slot { | |||
| 63 | struct hpc_ops *hpc_ops; | 68 | struct hpc_ops *hpc_ops; |
| 64 | struct hotplug_slot *hotplug_slot; | 69 | struct hotplug_slot *hotplug_slot; |
| 65 | struct list_head slot_list; | 70 | struct list_head slot_list; |
| 71 | char name[SLOT_NAME_SIZE]; | ||
| 72 | unsigned long last_emi_toggle; | ||
| 66 | }; | 73 | }; |
| 67 | 74 | ||
| 68 | struct event_info { | 75 | struct event_info { |
| @@ -70,34 +77,15 @@ struct event_info { | |||
| 70 | u8 hp_slot; | 77 | u8 hp_slot; |
| 71 | }; | 78 | }; |
| 72 | 79 | ||
| 73 | typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id); | ||
| 74 | |||
| 75 | struct php_ctlr_state_s { | ||
| 76 | struct php_ctlr_state_s *pnext; | ||
| 77 | struct pci_dev *pci_dev; | ||
| 78 | unsigned int irq; | ||
| 79 | unsigned long flags; /* spinlock's */ | ||
| 80 | u32 slot_device_offset; | ||
| 81 | u32 num_slots; | ||
| 82 | struct timer_list int_poll_timer; /* Added for poll event */ | ||
| 83 | php_intr_callback_t attention_button_callback; | ||
| 84 | php_intr_callback_t switch_change_callback; | ||
| 85 | php_intr_callback_t presence_change_callback; | ||
| 86 | php_intr_callback_t power_fault_callback; | ||
| 87 | void *callback_instance_id; | ||
| 88 | struct ctrl_reg *creg; /* Ptr to controller register space */ | ||
| 89 | }; | ||
| 90 | |||
| 91 | #define MAX_EVENTS 10 | 80 | #define MAX_EVENTS 10 |
| 92 | struct controller { | 81 | struct controller { |
| 93 | struct controller *next; | 82 | struct controller *next; |
| 94 | struct mutex crit_sect; /* critical section mutex */ | 83 | struct mutex crit_sect; /* critical section mutex */ |
| 95 | struct mutex ctrl_lock; /* controller lock */ | 84 | struct mutex ctrl_lock; /* controller lock */ |
| 96 | struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ | ||
| 97 | int num_slots; /* Number of slots on ctlr */ | 85 | int num_slots; /* Number of slots on ctlr */ |
| 98 | int slot_num_inc; /* 1 or -1 */ | 86 | int slot_num_inc; /* 1 or -1 */ |
| 99 | struct pci_dev *pci_dev; | 87 | struct pci_dev *pci_dev; |
| 100 | struct pci_bus *pci_bus; | 88 | struct list_head slot_list; |
| 101 | struct event_info event_queue[MAX_EVENTS]; | 89 | struct event_info event_queue[MAX_EVENTS]; |
| 102 | struct slot *slot; | 90 | struct slot *slot; |
| 103 | struct hpc_ops *hpc_ops; | 91 | struct hpc_ops *hpc_ops; |
| @@ -112,6 +100,8 @@ struct controller { | |||
| 112 | u8 ctrlcap; | 100 | u8 ctrlcap; |
| 113 | u16 vendor_id; | 101 | u16 vendor_id; |
| 114 | u8 cap_base; | 102 | u8 cap_base; |
| 103 | struct timer_list poll_timer; | ||
| 104 | volatile int cmd_busy; | ||
| 115 | }; | 105 | }; |
| 116 | 106 | ||
| 117 | #define INT_BUTTON_IGNORE 0 | 107 | #define INT_BUTTON_IGNORE 0 |
| @@ -131,8 +121,6 @@ struct controller { | |||
| 131 | #define POWERON_STATE 3 | 121 | #define POWERON_STATE 3 |
| 132 | #define POWEROFF_STATE 4 | 122 | #define POWEROFF_STATE 4 |
| 133 | 123 | ||
| 134 | #define PCI_TO_PCI_BRIDGE_CLASS 0x00060400 | ||
| 135 | |||
| 136 | /* Error messages */ | 124 | /* Error messages */ |
| 137 | #define INTERLOCK_OPEN 0x00000002 | 125 | #define INTERLOCK_OPEN 0x00000002 |
| 138 | #define ADD_NOT_SUPPORTED 0x00000003 | 126 | #define ADD_NOT_SUPPORTED 0x00000003 |
| @@ -144,10 +132,6 @@ struct controller { | |||
| 144 | #define WRONG_BUS_FREQUENCY 0x0000000D | 132 | #define WRONG_BUS_FREQUENCY 0x0000000D |
| 145 | #define POWER_FAILURE 0x0000000E | 133 | #define POWER_FAILURE 0x0000000E |
| 146 | 134 | ||
| 147 | #define REMOVE_NOT_SUPPORTED 0x00000003 | ||
| 148 | |||
| 149 | #define DISABLE_CARD 1 | ||
| 150 | |||
| 151 | /* Field definitions in Slot Capabilities Register */ | 135 | /* Field definitions in Slot Capabilities Register */ |
| 152 | #define ATTN_BUTTN_PRSN 0x00000001 | 136 | #define ATTN_BUTTN_PRSN 0x00000001 |
| 153 | #define PWR_CTRL_PRSN 0x00000002 | 137 | #define PWR_CTRL_PRSN 0x00000002 |
| @@ -155,6 +139,7 @@ struct controller { | |||
| 155 | #define ATTN_LED_PRSN 0x00000008 | 139 | #define ATTN_LED_PRSN 0x00000008 |
| 156 | #define PWR_LED_PRSN 0x00000010 | 140 | #define PWR_LED_PRSN 0x00000010 |
| 157 | #define HP_SUPR_RM_SUP 0x00000020 | 141 | #define HP_SUPR_RM_SUP 0x00000020 |
| 142 | #define EMI_PRSN 0x00020000 | ||
| 158 | 143 | ||
| 159 | #define ATTN_BUTTN(cap) (cap & ATTN_BUTTN_PRSN) | 144 | #define ATTN_BUTTN(cap) (cap & ATTN_BUTTN_PRSN) |
| 160 | #define POWER_CTRL(cap) (cap & PWR_CTRL_PRSN) | 145 | #define POWER_CTRL(cap) (cap & PWR_CTRL_PRSN) |
| @@ -162,130 +147,65 @@ struct controller { | |||
| 162 | #define ATTN_LED(cap) (cap & ATTN_LED_PRSN) | 147 | #define ATTN_LED(cap) (cap & ATTN_LED_PRSN) |
| 163 | #define PWR_LED(cap) (cap & PWR_LED_PRSN) | 148 | #define PWR_LED(cap) (cap & PWR_LED_PRSN) |
| 164 | #define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP) | 149 | #define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP) |
| 165 | 150 | #define EMI(cap) (cap & EMI_PRSN) | |
| 166 | /* | 151 | |
| 167 | * error Messages | 152 | extern int pciehp_event_start_thread(void); |
| 168 | */ | 153 | extern void pciehp_event_stop_thread(void); |
| 169 | #define msg_initialization_err "Initialization failure, error=%d\n" | 154 | extern int pciehp_enable_slot(struct slot *slot); |
| 170 | #define msg_button_on "PCI slot #%s - powering on due to button press.\n" | 155 | extern int pciehp_disable_slot(struct slot *slot); |
| 171 | #define msg_button_off "PCI slot #%s - powering off due to button press.\n" | 156 | extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl); |
| 172 | #define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n" | 157 | extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl); |
| 173 | #define msg_button_ignore "PCI slot #%s - button press ignored. (action in progress...)\n" | 158 | extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl); |
| 174 | 159 | extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl); | |
| 175 | /* controller functions */ | 160 | extern int pciehp_configure_device(struct slot *p_slot); |
| 176 | extern int pciehp_event_start_thread (void); | 161 | extern int pciehp_unconfigure_device(struct slot *p_slot); |
| 177 | extern void pciehp_event_stop_thread (void); | 162 | int pcie_init(struct controller *ctrl, struct pcie_device *dev); |
| 178 | extern int pciehp_enable_slot (struct slot *slot); | ||
| 179 | extern int pciehp_disable_slot (struct slot *slot); | ||
| 180 | |||
| 181 | extern u8 pciehp_handle_attention_button (u8 hp_slot, void *inst_id); | ||
| 182 | extern u8 pciehp_handle_switch_change (u8 hp_slot, void *inst_id); | ||
| 183 | extern u8 pciehp_handle_presence_change (u8 hp_slot, void *inst_id); | ||
| 184 | extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); | ||
| 185 | /* extern void long_delay (int delay); */ | ||
| 186 | |||
| 187 | /* pci functions */ | ||
| 188 | extern int pciehp_configure_device (struct slot *p_slot); | ||
| 189 | extern int pciehp_unconfigure_device (struct slot *p_slot); | ||
| 190 | |||
| 191 | |||
| 192 | 163 | ||
| 193 | /* Global variables */ | 164 | /* Global variables */ |
| 194 | extern struct controller *pciehp_ctrl_list; | 165 | extern struct controller *pciehp_ctrl_list; |
| 195 | 166 | ||
| 196 | /* Inline functions */ | ||
| 197 | |||
| 198 | static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) | 167 | static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) |
| 199 | { | 168 | { |
| 200 | struct slot *p_slot, *tmp_slot = NULL; | 169 | struct slot *slot; |
| 201 | |||
| 202 | p_slot = ctrl->slot; | ||
| 203 | 170 | ||
| 204 | while (p_slot && (p_slot->device != device)) { | 171 | list_for_each_entry(slot, &ctrl->slot_list, slot_list) { |
| 205 | tmp_slot = p_slot; | 172 | if (slot->device == device) |
| 206 | p_slot = p_slot->next; | 173 | return slot; |
| 207 | } | 174 | } |
| 208 | if (p_slot == NULL) { | ||
| 209 | err("ERROR: pciehp_find_slot device=0x%x\n", device); | ||
| 210 | p_slot = tmp_slot; | ||
| 211 | } | ||
| 212 | |||
| 213 | return p_slot; | ||
| 214 | } | ||
| 215 | |||
| 216 | static inline int wait_for_ctrl_irq(struct controller *ctrl) | ||
| 217 | { | ||
| 218 | int retval = 0; | ||
| 219 | |||
| 220 | DECLARE_WAITQUEUE(wait, current); | ||
| 221 | |||
| 222 | add_wait_queue(&ctrl->queue, &wait); | ||
| 223 | if (!pciehp_poll_mode) | ||
| 224 | /* Sleep for up to 1 second */ | ||
| 225 | msleep_interruptible(1000); | ||
| 226 | else | ||
| 227 | msleep_interruptible(2500); | ||
| 228 | |||
| 229 | remove_wait_queue(&ctrl->queue, &wait); | ||
| 230 | if (signal_pending(current)) | ||
| 231 | retval = -EINTR; | ||
| 232 | |||
| 233 | return retval; | ||
| 234 | } | ||
| 235 | |||
| 236 | #define SLOT_NAME_SIZE 10 | ||
| 237 | 175 | ||
| 238 | static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) | 176 | err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device); |
| 239 | { | 177 | return NULL; |
| 240 | snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number); | ||
| 241 | } | 178 | } |
| 242 | 179 | ||
| 243 | enum php_ctlr_type { | ||
| 244 | PCI, | ||
| 245 | ISA, | ||
| 246 | ACPI | ||
| 247 | }; | ||
| 248 | |||
| 249 | int pcie_init(struct controller *ctrl, struct pcie_device *dev); | ||
| 250 | |||
| 251 | /* This has no meaning for PCI Express, as there is only 1 slot per port */ | ||
| 252 | int pcie_get_ctlr_slot_config(struct controller *ctrl, | ||
| 253 | int *num_ctlr_slots, | ||
| 254 | int *first_device_num, | ||
| 255 | int *physical_slot_num, | ||
| 256 | u8 *ctrlcap); | ||
| 257 | |||
| 258 | struct hpc_ops { | 180 | struct hpc_ops { |
| 259 | int (*power_on_slot) (struct slot *slot); | 181 | int (*power_on_slot)(struct slot *slot); |
| 260 | int (*power_off_slot) (struct slot *slot); | 182 | int (*power_off_slot)(struct slot *slot); |
| 261 | int (*get_power_status) (struct slot *slot, u8 *status); | 183 | int (*get_power_status)(struct slot *slot, u8 *status); |
| 262 | int (*get_attention_status) (struct slot *slot, u8 *status); | 184 | int (*get_attention_status)(struct slot *slot, u8 *status); |
| 263 | int (*set_attention_status) (struct slot *slot, u8 status); | 185 | int (*set_attention_status)(struct slot *slot, u8 status); |
| 264 | int (*get_latch_status) (struct slot *slot, u8 *status); | 186 | int (*get_latch_status)(struct slot *slot, u8 *status); |
| 265 | int (*get_adapter_status) (struct slot *slot, u8 *status); | 187 | int (*get_adapter_status)(struct slot *slot, u8 *status); |
| 266 | 188 | int (*get_emi_status)(struct slot *slot, u8 *status); | |
| 267 | int (*get_max_bus_speed) (struct slot *slot, enum pci_bus_speed *speed); | 189 | int (*toggle_emi)(struct slot *slot); |
| 268 | int (*get_cur_bus_speed) (struct slot *slot, enum pci_bus_speed *speed); | 190 | int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); |
| 269 | 191 | int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); | |
| 270 | int (*get_max_lnk_width) (struct slot *slot, enum pcie_link_width *value); | 192 | int (*get_max_lnk_width)(struct slot *slot, enum pcie_link_width *val); |
| 271 | int (*get_cur_lnk_width) (struct slot *slot, enum pcie_link_width *value); | 193 | int (*get_cur_lnk_width)(struct slot *slot, enum pcie_link_width *val); |
| 272 | 194 | int (*query_power_fault)(struct slot *slot); | |
| 273 | int (*query_power_fault) (struct slot *slot); | 195 | void (*green_led_on)(struct slot *slot); |
| 274 | void (*green_led_on) (struct slot *slot); | 196 | void (*green_led_off)(struct slot *slot); |
| 275 | void (*green_led_off) (struct slot *slot); | 197 | void (*green_led_blink)(struct slot *slot); |
| 276 | void (*green_led_blink) (struct slot *slot); | 198 | void (*release_ctlr)(struct controller *ctrl); |
| 277 | void (*release_ctlr) (struct controller *ctrl); | 199 | int (*check_lnk_status)(struct controller *ctrl); |
| 278 | int (*check_lnk_status) (struct controller *ctrl); | ||
| 279 | }; | 200 | }; |
| 280 | 201 | ||
| 281 | |||
| 282 | #ifdef CONFIG_ACPI | 202 | #ifdef CONFIG_ACPI |
| 283 | #include <acpi/acpi.h> | 203 | #include <acpi/acpi.h> |
| 284 | #include <acpi/acpi_bus.h> | 204 | #include <acpi/acpi_bus.h> |
| 285 | #include <acpi/actypes.h> | 205 | #include <acpi/actypes.h> |
| 286 | #include <linux/pci-acpi.h> | 206 | #include <linux/pci-acpi.h> |
| 287 | 207 | ||
| 288 | #define pciehp_get_hp_hw_control_from_firmware(dev) \ | 208 | #define pciehp_get_hp_hw_control_from_firmware(dev) \ |
| 289 | pciehp_acpi_get_hp_hw_control_from_firmware(dev) | 209 | pciehp_acpi_get_hp_hw_control_from_firmware(dev) |
| 290 | static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, | 210 | static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, |
| 291 | struct hotplug_params *hpp) | 211 | struct hotplug_params *hpp) |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index f13f31323e85..a92eda6e02f6 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
| 35 | #include "pciehp.h" | 35 | #include "pciehp.h" |
| 36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
| 37 | #include <linux/time.h> | ||
| 37 | 38 | ||
| 38 | /* Global variables */ | 39 | /* Global variables */ |
| 39 | int pciehp_debug; | 40 | int pciehp_debug; |
| @@ -87,6 +88,95 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { | |||
| 87 | .get_cur_bus_speed = get_cur_bus_speed, | 88 | .get_cur_bus_speed = get_cur_bus_speed, |
| 88 | }; | 89 | }; |
| 89 | 90 | ||
| 91 | /* | ||
| 92 | * Check the status of the Electro Mechanical Interlock (EMI) | ||
| 93 | */ | ||
| 94 | static int get_lock_status(struct hotplug_slot *hotplug_slot, u8 *value) | ||
| 95 | { | ||
| 96 | struct slot *slot = hotplug_slot->private; | ||
| 97 | return (slot->hpc_ops->get_emi_status(slot, value)); | ||
| 98 | } | ||
| 99 | |||
| 100 | /* | ||
| 101 | * sysfs interface for the Electro Mechanical Interlock (EMI) | ||
| 102 | * 1 == locked, 0 == unlocked | ||
| 103 | */ | ||
| 104 | static ssize_t lock_read_file(struct hotplug_slot *slot, char *buf) | ||
| 105 | { | ||
| 106 | int retval; | ||
| 107 | u8 value; | ||
| 108 | |||
| 109 | retval = get_lock_status(slot, &value); | ||
| 110 | if (retval) | ||
| 111 | goto lock_read_exit; | ||
| 112 | retval = sprintf (buf, "%d\n", value); | ||
| 113 | |||
| 114 | lock_read_exit: | ||
| 115 | return retval; | ||
| 116 | } | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Change the status of the Electro Mechanical Interlock (EMI) | ||
| 120 | * This is a toggle - in addition there must be at least 1 second | ||
| 121 | * in between toggles. | ||
| 122 | */ | ||
| 123 | static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status) | ||
| 124 | { | ||
| 125 | struct slot *slot = hotplug_slot->private; | ||
| 126 | int retval; | ||
| 127 | u8 value; | ||
| 128 | |||
| 129 | mutex_lock(&slot->ctrl->crit_sect); | ||
| 130 | |||
| 131 | /* has it been >1 sec since our last toggle? */ | ||
| 132 | if ((get_seconds() - slot->last_emi_toggle) < 1) | ||
| 133 | return -EINVAL; | ||
| 134 | |||
| 135 | /* see what our current state is */ | ||
| 136 | retval = get_lock_status(hotplug_slot, &value); | ||
| 137 | if (retval || (value == status)) | ||
| 138 | goto set_lock_exit; | ||
| 139 | |||
| 140 | slot->hpc_ops->toggle_emi(slot); | ||
| 141 | set_lock_exit: | ||
| 142 | mutex_unlock(&slot->ctrl->crit_sect); | ||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* | ||
| 147 | * sysfs interface which allows the user to toggle the Electro Mechanical | ||
| 148 | * Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock | ||
| 149 | */ | ||
| 150 | static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf, | ||
| 151 | size_t count) | ||
| 152 | { | ||
| 153 | unsigned long llock; | ||
| 154 | u8 lock; | ||
| 155 | int retval = 0; | ||
| 156 | |||
| 157 | llock = simple_strtoul(buf, NULL, 10); | ||
| 158 | lock = (u8)(llock & 0xff); | ||
| 159 | |||
| 160 | switch (lock) { | ||
| 161 | case 0: | ||
| 162 | case 1: | ||
| 163 | retval = set_lock_status(slot, lock); | ||
| 164 | break; | ||
| 165 | default: | ||
| 166 | err ("%d is an invalid lock value\n", lock); | ||
| 167 | retval = -EINVAL; | ||
| 168 | } | ||
| 169 | if (retval) | ||
| 170 | return retval; | ||
| 171 | return count; | ||
| 172 | } | ||
| 173 | |||
| 174 | static struct hotplug_slot_attribute hotplug_slot_attr_lock = { | ||
| 175 | .attr = {.name = "lock", .mode = S_IFREG | S_IRUGO | S_IWUSR}, | ||
| 176 | .show = lock_read_file, | ||
| 177 | .store = lock_write_file | ||
| 178 | }; | ||
| 179 | |||
| 90 | /** | 180 | /** |
| 91 | * release_slot - free up the memory used by a slot | 181 | * release_slot - free up the memory used by a slot |
| 92 | * @hotplug_slot: slot to free | 182 | * @hotplug_slot: slot to free |
| @@ -98,148 +188,108 @@ static void release_slot(struct hotplug_slot *hotplug_slot) | |||
| 98 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 188 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
| 99 | 189 | ||
| 100 | kfree(slot->hotplug_slot->info); | 190 | kfree(slot->hotplug_slot->info); |
| 101 | kfree(slot->hotplug_slot->name); | ||
| 102 | kfree(slot->hotplug_slot); | 191 | kfree(slot->hotplug_slot); |
| 103 | kfree(slot); | 192 | kfree(slot); |
| 104 | } | 193 | } |
| 105 | 194 | ||
| 195 | static void make_slot_name(struct slot *slot) | ||
| 196 | { | ||
| 197 | snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", | ||
| 198 | slot->bus, slot->number); | ||
| 199 | } | ||
| 200 | |||
| 106 | static int init_slots(struct controller *ctrl) | 201 | static int init_slots(struct controller *ctrl) |
| 107 | { | 202 | { |
| 108 | struct slot *slot; | 203 | struct slot *slot; |
| 109 | struct hpc_ops *hpc_ops; | ||
| 110 | struct hotplug_slot *hotplug_slot; | 204 | struct hotplug_slot *hotplug_slot; |
| 111 | struct hotplug_slot_info *hotplug_slot_info; | 205 | struct hotplug_slot_info *info; |
| 112 | u8 number_of_slots; | 206 | int retval = -ENOMEM; |
| 113 | u8 slot_device; | 207 | int i; |
| 114 | u32 slot_number; | ||
| 115 | int result = -ENOMEM; | ||
| 116 | 208 | ||
| 117 | number_of_slots = ctrl->num_slots; | 209 | for (i = 0; i < ctrl->num_slots; i++) { |
| 118 | slot_device = ctrl->slot_device_offset; | ||
| 119 | slot_number = ctrl->first_slot; | ||
| 120 | |||
| 121 | while (number_of_slots) { | ||
| 122 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | 210 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
| 123 | if (!slot) | 211 | if (!slot) |
| 124 | goto error; | 212 | goto error; |
| 125 | 213 | ||
| 126 | slot->hotplug_slot = | 214 | hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); |
| 127 | kzalloc(sizeof(*(slot->hotplug_slot)), | 215 | if (!hotplug_slot) |
| 128 | GFP_KERNEL); | ||
| 129 | if (!slot->hotplug_slot) | ||
| 130 | goto error_slot; | 216 | goto error_slot; |
| 131 | hotplug_slot = slot->hotplug_slot; | 217 | slot->hotplug_slot = hotplug_slot; |
| 132 | 218 | ||
| 133 | hotplug_slot->info = | 219 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
| 134 | kzalloc(sizeof(*(hotplug_slot->info)), | 220 | if (!info) |
| 135 | GFP_KERNEL); | ||
| 136 | if (!hotplug_slot->info) | ||
| 137 | goto error_hpslot; | 221 | goto error_hpslot; |
| 138 | hotplug_slot_info = hotplug_slot->info; | 222 | hotplug_slot->info = info; |
| 139 | hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); | ||
| 140 | if (!hotplug_slot->name) | ||
| 141 | goto error_info; | ||
| 142 | 223 | ||
| 143 | slot->ctrl = ctrl; | 224 | hotplug_slot->name = slot->name; |
| 144 | slot->bus = ctrl->slot_bus; | ||
| 145 | slot->device = slot_device; | ||
| 146 | slot->hpc_ops = hpc_ops = ctrl->hpc_ops; | ||
| 147 | 225 | ||
| 226 | slot->hp_slot = i; | ||
| 227 | slot->ctrl = ctrl; | ||
| 228 | slot->bus = ctrl->pci_dev->subordinate->number; | ||
| 229 | slot->device = ctrl->slot_device_offset + i; | ||
| 230 | slot->hpc_ops = ctrl->hpc_ops; | ||
| 148 | slot->number = ctrl->first_slot; | 231 | slot->number = ctrl->first_slot; |
| 149 | slot->hp_slot = slot_device - ctrl->slot_device_offset; | ||
| 150 | 232 | ||
| 151 | /* register this slot with the hotplug pci core */ | 233 | /* register this slot with the hotplug pci core */ |
| 152 | hotplug_slot->private = slot; | 234 | hotplug_slot->private = slot; |
| 153 | hotplug_slot->release = &release_slot; | 235 | hotplug_slot->release = &release_slot; |
| 154 | make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot); | 236 | make_slot_name(slot); |
| 155 | hotplug_slot->ops = &pciehp_hotplug_slot_ops; | 237 | hotplug_slot->ops = &pciehp_hotplug_slot_ops; |
| 156 | 238 | ||
| 157 | hpc_ops->get_power_status(slot, | 239 | get_power_status(hotplug_slot, &info->power_status); |
| 158 | &(hotplug_slot_info->power_status)); | 240 | get_attention_status(hotplug_slot, &info->attention_status); |
| 159 | hpc_ops->get_attention_status(slot, | 241 | get_latch_status(hotplug_slot, &info->latch_status); |
| 160 | &(hotplug_slot_info->attention_status)); | 242 | get_adapter_status(hotplug_slot, &info->adapter_status); |
| 161 | hpc_ops->get_latch_status(slot, | ||
| 162 | &(hotplug_slot_info->latch_status)); | ||
| 163 | hpc_ops->get_adapter_status(slot, | ||
| 164 | &(hotplug_slot_info->adapter_status)); | ||
| 165 | 243 | ||
| 166 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " | 244 | dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " |
| 167 | "slot_device_offset=%x\n", | 245 | "slot_device_offset=%x\n", slot->bus, slot->device, |
| 168 | slot->bus, slot->device, slot->hp_slot, slot->number, | 246 | slot->hp_slot, slot->number, ctrl->slot_device_offset); |
| 169 | ctrl->slot_device_offset); | 247 | retval = pci_hp_register(hotplug_slot); |
| 170 | result = pci_hp_register(hotplug_slot); | 248 | if (retval) { |
| 171 | if (result) { | 249 | err ("pci_hp_register failed with error %d\n", retval); |
| 172 | err ("pci_hp_register failed with error %d\n", result); | 250 | goto error_info; |
| 173 | goto error_name; | 251 | } |
| 252 | /* create additional sysfs entries */ | ||
| 253 | if (EMI(ctrl->ctrlcap)) { | ||
| 254 | retval = sysfs_create_file(&hotplug_slot->kobj, | ||
| 255 | &hotplug_slot_attr_lock.attr); | ||
| 256 | if (retval) { | ||
| 257 | pci_hp_deregister(hotplug_slot); | ||
| 258 | err("cannot create additional sysfs entries\n"); | ||
| 259 | goto error_info; | ||
| 260 | } | ||
| 174 | } | 261 | } |
| 175 | 262 | ||
| 176 | slot->next = ctrl->slot; | 263 | list_add(&slot->slot_list, &ctrl->slot_list); |
| 177 | ctrl->slot = slot; | ||
| 178 | |||
| 179 | number_of_slots--; | ||
| 180 | slot_device++; | ||
| 181 | slot_number += ctrl->slot_num_inc; | ||
| 182 | } | 264 | } |
| 183 | 265 | ||
| 184 | return 0; | 266 | return 0; |
| 185 | |||
| 186 | error_name: | ||
| 187 | kfree(hotplug_slot->name); | ||
| 188 | error_info: | 267 | error_info: |
| 189 | kfree(hotplug_slot_info); | 268 | kfree(info); |
| 190 | error_hpslot: | 269 | error_hpslot: |
| 191 | kfree(hotplug_slot); | 270 | kfree(hotplug_slot); |
| 192 | error_slot: | 271 | error_slot: |
| 193 | kfree(slot); | 272 | kfree(slot); |
| 194 | error: | 273 | error: |
| 195 | return result; | 274 | return retval; |
| 196 | } | ||
| 197 | |||
| 198 | |||
| 199 | static int cleanup_slots (struct controller * ctrl) | ||
| 200 | { | ||
| 201 | struct slot *old_slot, *next_slot; | ||
| 202 | |||
| 203 | old_slot = ctrl->slot; | ||
| 204 | ctrl->slot = NULL; | ||
| 205 | |||
| 206 | while (old_slot) { | ||
| 207 | next_slot = old_slot->next; | ||
| 208 | pci_hp_deregister (old_slot->hotplug_slot); | ||
| 209 | old_slot = next_slot; | ||
| 210 | } | ||
| 211 | |||
| 212 | |||
| 213 | return(0); | ||
| 214 | } | 275 | } |
| 215 | 276 | ||
| 216 | static int get_ctlr_slot_config(struct controller *ctrl) | 277 | static void cleanup_slots(struct controller *ctrl) |
| 217 | { | 278 | { |
| 218 | int num_ctlr_slots; /* Not needed; PCI Express has 1 slot per port*/ | 279 | struct list_head *tmp; |
| 219 | int first_device_num; /* Not needed */ | 280 | struct list_head *next; |
| 220 | int physical_slot_num; | 281 | struct slot *slot; |
| 221 | u8 ctrlcap; | ||
| 222 | int rc; | ||
| 223 | 282 | ||
| 224 | rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &ctrlcap); | 283 | list_for_each_safe(tmp, next, &ctrl->slot_list) { |
| 225 | if (rc) { | 284 | slot = list_entry(tmp, struct slot, slot_list); |
| 226 | err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); | 285 | list_del(&slot->slot_list); |
| 227 | return (-1); | 286 | if (EMI(ctrl->ctrlcap)) |
| 287 | sysfs_remove_file(&slot->hotplug_slot->kobj, | ||
| 288 | &hotplug_slot_attr_lock.attr); | ||
| 289 | pci_hp_deregister(slot->hotplug_slot); | ||
| 228 | } | 290 | } |
| 229 | |||
| 230 | ctrl->num_slots = num_ctlr_slots; /* PCI Express has 1 slot per port */ | ||
| 231 | ctrl->slot_device_offset = first_device_num; | ||
| 232 | ctrl->first_slot = physical_slot_num; | ||
| 233 | ctrl->ctrlcap = ctrlcap; | ||
| 234 | |||
| 235 | dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) ctrlcap(%x) for b:d (%x:%x)\n", | ||
| 236 | __FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, ctrlcap, | ||
| 237 | ctrl->bus, ctrl->device); | ||
| 238 | |||
| 239 | return (0); | ||
| 240 | } | 291 | } |
| 241 | 292 | ||
| 242 | |||
| 243 | /* | 293 | /* |
| 244 | * set_attention_status - Turns the Amber LED for a slot on, off or blink | 294 | * set_attention_status - Turns the Amber LED for a slot on, off or blink |
| 245 | */ | 295 | */ |
| @@ -378,8 +428,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 378 | int rc; | 428 | int rc; |
| 379 | struct controller *ctrl; | 429 | struct controller *ctrl; |
| 380 | struct slot *t_slot; | 430 | struct slot *t_slot; |
| 381 | int first_device_num = 0 ; /* first PCI device number supported by this PCIE */ | ||
| 382 | int num_ctlr_slots; /* number of slots supported by this HPC */ | ||
| 383 | u8 value; | 431 | u8 value; |
| 384 | struct pci_dev *pdev; | 432 | struct pci_dev *pdev; |
| 385 | 433 | ||
| @@ -388,6 +436,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 388 | err("%s : out of memory\n", __FUNCTION__); | 436 | err("%s : out of memory\n", __FUNCTION__); |
| 389 | goto err_out_none; | 437 | goto err_out_none; |
| 390 | } | 438 | } |
| 439 | INIT_LIST_HEAD(&ctrl->slot_list); | ||
| 391 | 440 | ||
| 392 | pdev = dev->port; | 441 | pdev = dev->port; |
| 393 | ctrl->pci_dev = pdev; | 442 | ctrl->pci_dev = pdev; |
| @@ -400,13 +449,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 400 | 449 | ||
| 401 | pci_set_drvdata(pdev, ctrl); | 450 | pci_set_drvdata(pdev, ctrl); |
| 402 | 451 | ||
| 403 | ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); | ||
| 404 | if (!ctrl->pci_bus) { | ||
| 405 | err("%s: out of memory\n", __FUNCTION__); | ||
| 406 | rc = -ENOMEM; | ||
| 407 | goto err_out_unmap_mmio_region; | ||
| 408 | } | ||
| 409 | memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); | ||
| 410 | ctrl->bus = pdev->bus->number; /* ctrl bus */ | 452 | ctrl->bus = pdev->bus->number; /* ctrl bus */ |
| 411 | ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ | 453 | ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ |
| 412 | 454 | ||
| @@ -415,26 +457,14 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 415 | dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__, | 457 | dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__, |
| 416 | ctrl->bus, ctrl->device, ctrl->function, pdev->irq); | 458 | ctrl->bus, ctrl->device, ctrl->function, pdev->irq); |
| 417 | 459 | ||
| 418 | /* | ||
| 419 | * Save configuration headers for this and subordinate PCI buses | ||
| 420 | */ | ||
| 421 | |||
| 422 | rc = get_ctlr_slot_config(ctrl); | ||
| 423 | if (rc) { | ||
| 424 | err(msg_initialization_err, rc); | ||
| 425 | goto err_out_free_ctrl_bus; | ||
| 426 | } | ||
| 427 | first_device_num = ctrl->slot_device_offset; | ||
| 428 | num_ctlr_slots = ctrl->num_slots; | ||
| 429 | |||
| 430 | /* Setup the slot information structures */ | 460 | /* Setup the slot information structures */ |
| 431 | rc = init_slots(ctrl); | 461 | rc = init_slots(ctrl); |
| 432 | if (rc) { | 462 | if (rc) { |
| 433 | err(msg_initialization_err, 6); | 463 | err("%s: slot initialization failed\n", PCIE_MODULE_NAME); |
| 434 | goto err_out_free_ctrl_slot; | 464 | goto err_out_release_ctlr; |
| 435 | } | 465 | } |
| 436 | 466 | ||
| 437 | t_slot = pciehp_find_slot(ctrl, first_device_num); | 467 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); |
| 438 | 468 | ||
| 439 | /* Finish setting up the hot plug ctrl device */ | 469 | /* Finish setting up the hot plug ctrl device */ |
| 440 | ctrl->next_event = 0; | 470 | ctrl->next_event = 0; |
| @@ -447,32 +477,18 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
| 447 | pciehp_ctrl_list = ctrl; | 477 | pciehp_ctrl_list = ctrl; |
| 448 | } | 478 | } |
| 449 | 479 | ||
| 450 | /* Wait for exclusive access to hardware */ | ||
| 451 | mutex_lock(&ctrl->ctrl_lock); | ||
| 452 | |||
| 453 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ | 480 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ |
| 454 | |||
| 455 | if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { | 481 | if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { |
| 456 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ | 482 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ |
| 457 | if (rc) { | 483 | if (rc) |
| 458 | /* Done with exclusive hardware access */ | ||
| 459 | mutex_unlock(&ctrl->ctrl_lock); | ||
| 460 | goto err_out_free_ctrl_slot; | 484 | goto err_out_free_ctrl_slot; |
| 461 | } else | ||
| 462 | /* Wait for the command to complete */ | ||
| 463 | wait_for_ctrl_irq (ctrl); | ||
| 464 | } | 485 | } |
| 465 | 486 | ||
| 466 | /* Done with exclusive hardware access */ | ||
| 467 | mutex_unlock(&ctrl->ctrl_lock); | ||
| 468 | |||
| 469 | return 0; | 487 | return 0; |
| 470 | 488 | ||
| 471 | err_out_free_ctrl_slot: | 489 | err_out_free_ctrl_slot: |
| 472 | cleanup_slots(ctrl); | 490 | cleanup_slots(ctrl); |
| 473 | err_out_free_ctrl_bus: | 491 | err_out_release_ctlr: |
| 474 | kfree(ctrl->pci_bus); | ||
| 475 | err_out_unmap_mmio_region: | ||
| 476 | ctrl->hpc_ops->release_ctlr(ctrl); | 492 | ctrl->hpc_ops->release_ctlr(ctrl); |
| 477 | err_out_free_ctrl: | 493 | err_out_free_ctrl: |
| 478 | kfree(ctrl); | 494 | kfree(ctrl); |
| @@ -506,8 +522,6 @@ static void __exit unload_pciehpd(void) | |||
| 506 | while (ctrl) { | 522 | while (ctrl) { |
| 507 | cleanup_slots(ctrl); | 523 | cleanup_slots(ctrl); |
| 508 | 524 | ||
| 509 | kfree (ctrl->pci_bus); | ||
| 510 | |||
| 511 | ctrl->hpc_ops->release_ctlr(ctrl); | 525 | ctrl->hpc_ops->release_ctlr(ctrl); |
| 512 | 526 | ||
| 513 | tctrl = ctrl; | 527 | tctrl = ctrl; |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 372c63e35aa9..4283ef56dbd9 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
| @@ -48,9 +48,8 @@ static inline char *slot_name(struct slot *p_slot) | |||
| 48 | return p_slot->hotplug_slot->name; | 48 | return p_slot->hotplug_slot->name; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | 51 | u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) |
| 52 | { | 52 | { |
| 53 | struct controller *ctrl = (struct controller *) inst_id; | ||
| 54 | struct slot *p_slot; | 53 | struct slot *p_slot; |
| 55 | u8 rc = 0; | 54 | u8 rc = 0; |
| 56 | u8 getstatus; | 55 | u8 getstatus; |
| @@ -101,9 +100,8 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) | |||
| 101 | 100 | ||
| 102 | } | 101 | } |
| 103 | 102 | ||
| 104 | u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) | 103 | u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) |
| 105 | { | 104 | { |
| 106 | struct controller *ctrl = (struct controller *) inst_id; | ||
| 107 | struct slot *p_slot; | 105 | struct slot *p_slot; |
| 108 | u8 rc = 0; | 106 | u8 rc = 0; |
| 109 | u8 getstatus; | 107 | u8 getstatus; |
| @@ -143,9 +141,8 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) | |||
| 143 | return rc; | 141 | return rc; |
| 144 | } | 142 | } |
| 145 | 143 | ||
| 146 | u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) | 144 | u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) |
| 147 | { | 145 | { |
| 148 | struct controller *ctrl = (struct controller *) inst_id; | ||
| 149 | struct slot *p_slot; | 146 | struct slot *p_slot; |
| 150 | u8 presence_save, rc = 0; | 147 | u8 presence_save, rc = 0; |
| 151 | struct event_info *taskInfo; | 148 | struct event_info *taskInfo; |
| @@ -187,9 +184,8 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) | |||
| 187 | return rc; | 184 | return rc; |
| 188 | } | 185 | } |
| 189 | 186 | ||
| 190 | u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | 187 | u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) |
| 191 | { | 188 | { |
| 192 | struct controller *ctrl = (struct controller *) inst_id; | ||
| 193 | struct slot *p_slot; | 189 | struct slot *p_slot; |
| 194 | u8 rc = 0; | 190 | u8 rc = 0; |
| 195 | struct event_info *taskInfo; | 191 | struct event_info *taskInfo; |
| @@ -233,35 +229,25 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) | |||
| 233 | 229 | ||
| 234 | static void set_slot_off(struct controller *ctrl, struct slot * pslot) | 230 | static void set_slot_off(struct controller *ctrl, struct slot * pslot) |
| 235 | { | 231 | { |
| 236 | /* Wait for exclusive access to hardware */ | ||
| 237 | mutex_lock(&ctrl->ctrl_lock); | ||
| 238 | |||
| 239 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ | 232 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ |
| 240 | if (POWER_CTRL(ctrl->ctrlcap)) { | 233 | if (POWER_CTRL(ctrl->ctrlcap)) { |
| 241 | if (pslot->hpc_ops->power_off_slot(pslot)) { | 234 | if (pslot->hpc_ops->power_off_slot(pslot)) { |
| 242 | err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); | 235 | err("%s: Issue of Slot Power Off command failed\n", |
| 243 | mutex_unlock(&ctrl->ctrl_lock); | 236 | __FUNCTION__); |
| 244 | return; | 237 | return; |
| 245 | } | 238 | } |
| 246 | wait_for_ctrl_irq (ctrl); | ||
| 247 | } | 239 | } |
| 248 | 240 | ||
| 249 | if (PWR_LED(ctrl->ctrlcap)) { | 241 | if (PWR_LED(ctrl->ctrlcap)) |
| 250 | pslot->hpc_ops->green_led_off(pslot); | 242 | pslot->hpc_ops->green_led_off(pslot); |
| 251 | wait_for_ctrl_irq (ctrl); | ||
| 252 | } | ||
| 253 | 243 | ||
| 254 | if (ATTN_LED(ctrl->ctrlcap)) { | 244 | if (ATTN_LED(ctrl->ctrlcap)) { |
| 255 | if (pslot->hpc_ops->set_attention_status(pslot, 1)) { | 245 | if (pslot->hpc_ops->set_attention_status(pslot, 1)) { |
| 256 | err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); | 246 | err("%s: Issue of Set Attention Led command failed\n", |
| 257 | mutex_unlock(&ctrl->ctrl_lock); | 247 | __FUNCTION__); |
| 258 | return; | 248 | return; |
| 259 | } | 249 | } |
| 260 | wait_for_ctrl_irq (ctrl); | ||
| 261 | } | 250 | } |
| 262 | |||
| 263 | /* Done with exclusive hardware access */ | ||
| 264 | mutex_unlock(&ctrl->ctrl_lock); | ||
| 265 | } | 251 | } |
| 266 | 252 | ||
| 267 | /** | 253 | /** |
| @@ -274,7 +260,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) | |||
| 274 | static int board_added(struct slot *p_slot) | 260 | static int board_added(struct slot *p_slot) |
| 275 | { | 261 | { |
| 276 | u8 hp_slot; | 262 | u8 hp_slot; |
| 277 | int rc = 0; | 263 | int retval = 0; |
| 278 | struct controller *ctrl = p_slot->ctrl; | 264 | struct controller *ctrl = p_slot->ctrl; |
| 279 | 265 | ||
| 280 | hp_slot = p_slot->device - ctrl->slot_device_offset; | 266 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
| @@ -283,53 +269,38 @@ static int board_added(struct slot *p_slot) | |||
| 283 | __FUNCTION__, p_slot->device, | 269 | __FUNCTION__, p_slot->device, |
| 284 | ctrl->slot_device_offset, hp_slot); | 270 | ctrl->slot_device_offset, hp_slot); |
| 285 | 271 | ||
| 286 | /* Wait for exclusive access to hardware */ | ||
| 287 | mutex_lock(&ctrl->ctrl_lock); | ||
| 288 | |||
| 289 | if (POWER_CTRL(ctrl->ctrlcap)) { | 272 | if (POWER_CTRL(ctrl->ctrlcap)) { |
| 290 | /* Power on slot */ | 273 | /* Power on slot */ |
| 291 | rc = p_slot->hpc_ops->power_on_slot(p_slot); | 274 | retval = p_slot->hpc_ops->power_on_slot(p_slot); |
| 292 | if (rc) { | 275 | if (retval) |
| 293 | mutex_unlock(&ctrl->ctrl_lock); | 276 | return retval; |
| 294 | return -1; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* Wait for the command to complete */ | ||
| 298 | wait_for_ctrl_irq (ctrl); | ||
| 299 | } | 277 | } |
| 300 | 278 | ||
| 301 | if (PWR_LED(ctrl->ctrlcap)) { | 279 | if (PWR_LED(ctrl->ctrlcap)) |
| 302 | p_slot->hpc_ops->green_led_blink(p_slot); | 280 | p_slot->hpc_ops->green_led_blink(p_slot); |
| 303 | |||
| 304 | /* Wait for the command to complete */ | ||
| 305 | wait_for_ctrl_irq (ctrl); | ||
| 306 | } | ||
| 307 | |||
| 308 | /* Done with exclusive hardware access */ | ||
| 309 | mutex_unlock(&ctrl->ctrl_lock); | ||
| 310 | 281 | ||
| 311 | /* Wait for ~1 second */ | 282 | /* Wait for ~1 second */ |
| 312 | wait_for_ctrl_irq (ctrl); | 283 | msleep(1000); |
| 313 | 284 | ||
| 314 | /* Check link training status */ | 285 | /* Check link training status */ |
| 315 | rc = p_slot->hpc_ops->check_lnk_status(ctrl); | 286 | retval = p_slot->hpc_ops->check_lnk_status(ctrl); |
| 316 | if (rc) { | 287 | if (retval) { |
| 317 | err("%s: Failed to check link status\n", __FUNCTION__); | 288 | err("%s: Failed to check link status\n", __FUNCTION__); |
| 318 | set_slot_off(ctrl, p_slot); | 289 | set_slot_off(ctrl, p_slot); |
| 319 | return rc; | 290 | return retval; |
| 320 | } | 291 | } |
| 321 | 292 | ||
| 322 | /* Check for a power fault */ | 293 | /* Check for a power fault */ |
| 323 | if (p_slot->hpc_ops->query_power_fault(p_slot)) { | 294 | if (p_slot->hpc_ops->query_power_fault(p_slot)) { |
| 324 | dbg("%s: power fault detected\n", __FUNCTION__); | 295 | dbg("%s: power fault detected\n", __FUNCTION__); |
| 325 | rc = POWER_FAILURE; | 296 | retval = POWER_FAILURE; |
| 326 | goto err_exit; | 297 | goto err_exit; |
| 327 | } | 298 | } |
| 328 | 299 | ||
| 329 | rc = pciehp_configure_device(p_slot); | 300 | retval = pciehp_configure_device(p_slot); |
| 330 | if (rc) { | 301 | if (retval) { |
| 331 | err("Cannot add device 0x%x:%x\n", p_slot->bus, | 302 | err("Cannot add device 0x%x:%x\n", p_slot->bus, |
| 332 | p_slot->device); | 303 | p_slot->device); |
| 333 | goto err_exit; | 304 | goto err_exit; |
| 334 | } | 305 | } |
| 335 | 306 | ||
| @@ -338,26 +309,16 @@ static int board_added(struct slot *p_slot) | |||
| 338 | */ | 309 | */ |
| 339 | if (pcie_mch_quirk) | 310 | if (pcie_mch_quirk) |
| 340 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); | 311 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); |
| 341 | if (PWR_LED(ctrl->ctrlcap)) { | 312 | if (PWR_LED(ctrl->ctrlcap)) |
| 342 | /* Wait for exclusive access to hardware */ | ||
| 343 | mutex_lock(&ctrl->ctrl_lock); | ||
| 344 | |||
| 345 | p_slot->hpc_ops->green_led_on(p_slot); | 313 | p_slot->hpc_ops->green_led_on(p_slot); |
| 346 | 314 | ||
| 347 | /* Wait for the command to complete */ | ||
| 348 | wait_for_ctrl_irq (ctrl); | ||
| 349 | |||
| 350 | /* Done with exclusive hardware access */ | ||
| 351 | mutex_unlock(&ctrl->ctrl_lock); | ||
| 352 | } | ||
| 353 | return 0; | 315 | return 0; |
| 354 | 316 | ||
| 355 | err_exit: | 317 | err_exit: |
| 356 | set_slot_off(ctrl, p_slot); | 318 | set_slot_off(ctrl, p_slot); |
| 357 | return -1; | 319 | return retval; |
| 358 | } | 320 | } |
| 359 | 321 | ||
| 360 | |||
| 361 | /** | 322 | /** |
| 362 | * remove_board - Turns off slot and LED's | 323 | * remove_board - Turns off slot and LED's |
| 363 | * | 324 | * |
| @@ -366,44 +327,32 @@ static int remove_board(struct slot *p_slot) | |||
| 366 | { | 327 | { |
| 367 | u8 device; | 328 | u8 device; |
| 368 | u8 hp_slot; | 329 | u8 hp_slot; |
| 369 | int rc; | 330 | int retval = 0; |
| 370 | struct controller *ctrl = p_slot->ctrl; | 331 | struct controller *ctrl = p_slot->ctrl; |
| 371 | 332 | ||
| 372 | if (pciehp_unconfigure_device(p_slot)) | 333 | retval = pciehp_unconfigure_device(p_slot); |
| 373 | return 1; | 334 | if (retval) |
| 335 | return retval; | ||
| 374 | 336 | ||
| 375 | device = p_slot->device; | 337 | device = p_slot->device; |
| 376 | |||
| 377 | hp_slot = p_slot->device - ctrl->slot_device_offset; | 338 | hp_slot = p_slot->device - ctrl->slot_device_offset; |
| 378 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 339 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 379 | 340 | ||
| 380 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); | 341 | dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); |
| 381 | 342 | ||
| 382 | /* Wait for exclusive access to hardware */ | ||
| 383 | mutex_lock(&ctrl->ctrl_lock); | ||
| 384 | |||
| 385 | if (POWER_CTRL(ctrl->ctrlcap)) { | 343 | if (POWER_CTRL(ctrl->ctrlcap)) { |
| 386 | /* power off slot */ | 344 | /* power off slot */ |
| 387 | rc = p_slot->hpc_ops->power_off_slot(p_slot); | 345 | retval = p_slot->hpc_ops->power_off_slot(p_slot); |
| 388 | if (rc) { | 346 | if (retval) { |
| 389 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); | 347 | err("%s: Issue of Slot Disable command failed\n", |
| 390 | mutex_unlock(&ctrl->ctrl_lock); | 348 | __FUNCTION__); |
| 391 | return rc; | 349 | return retval; |
| 392 | } | 350 | } |
| 393 | /* Wait for the command to complete */ | ||
| 394 | wait_for_ctrl_irq (ctrl); | ||
| 395 | } | 351 | } |
| 396 | 352 | ||
| 397 | if (PWR_LED(ctrl->ctrlcap)) { | 353 | if (PWR_LED(ctrl->ctrlcap)) |
| 398 | /* turn off Green LED */ | 354 | /* turn off Green LED */ |
| 399 | p_slot->hpc_ops->green_led_off(p_slot); | 355 | p_slot->hpc_ops->green_led_off(p_slot); |
| 400 | |||
| 401 | /* Wait for the command to complete */ | ||
| 402 | wait_for_ctrl_irq (ctrl); | ||
| 403 | } | ||
| 404 | |||
| 405 | /* Done with exclusive hardware access */ | ||
| 406 | mutex_unlock(&ctrl->ctrl_lock); | ||
| 407 | 356 | ||
| 408 | return 0; | 357 | return 0; |
| 409 | } | 358 | } |
| @@ -448,18 +397,10 @@ static void pciehp_pushbutton_thread(unsigned long slot) | |||
| 448 | dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, | 397 | dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, |
| 449 | p_slot->bus, p_slot->device); | 398 | p_slot->bus, p_slot->device); |
| 450 | 399 | ||
| 451 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 400 | if (pciehp_enable_slot(p_slot) && |
| 452 | /* Wait for exclusive access to hardware */ | 401 | PWR_LED(p_slot->ctrl->ctrlcap)) |
| 453 | mutex_lock(&p_slot->ctrl->ctrl_lock); | ||
| 454 | |||
| 455 | p_slot->hpc_ops->green_led_off(p_slot); | 402 | p_slot->hpc_ops->green_led_off(p_slot); |
| 456 | 403 | ||
| 457 | /* Wait for the command to complete */ | ||
| 458 | wait_for_ctrl_irq (p_slot->ctrl); | ||
| 459 | |||
| 460 | /* Done with exclusive hardware access */ | ||
| 461 | mutex_unlock(&p_slot->ctrl->ctrl_lock); | ||
| 462 | } | ||
| 463 | p_slot->state = STATIC_STATE; | 404 | p_slot->state = STATIC_STATE; |
| 464 | } | 405 | } |
| 465 | 406 | ||
| @@ -498,18 +439,10 @@ static void pciehp_surprise_rm_thread(unsigned long slot) | |||
| 498 | dbg("%s: adding bus:device(%x:%x)\n", | 439 | dbg("%s: adding bus:device(%x:%x)\n", |
| 499 | __FUNCTION__, p_slot->bus, p_slot->device); | 440 | __FUNCTION__, p_slot->bus, p_slot->device); |
| 500 | 441 | ||
| 501 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { | 442 | if (pciehp_enable_slot(p_slot) && |
| 502 | /* Wait for exclusive access to hardware */ | 443 | PWR_LED(p_slot->ctrl->ctrlcap)) |
| 503 | mutex_lock(&p_slot->ctrl->ctrl_lock); | ||
| 504 | |||
| 505 | p_slot->hpc_ops->green_led_off(p_slot); | 444 | p_slot->hpc_ops->green_led_off(p_slot); |
| 506 | 445 | ||
| 507 | /* Wait for the command to complete */ | ||
| 508 | wait_for_ctrl_irq (p_slot->ctrl); | ||
| 509 | |||
| 510 | /* Done with exclusive hardware access */ | ||
| 511 | mutex_unlock(&p_slot->ctrl->ctrl_lock); | ||
| 512 | } | ||
| 513 | p_slot->state = STATIC_STATE; | 446 | p_slot->state = STATIC_STATE; |
| 514 | } | 447 | } |
| 515 | 448 | ||
| @@ -620,46 +553,24 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 620 | 553 | ||
| 621 | switch (p_slot->state) { | 554 | switch (p_slot->state) { |
| 622 | case BLINKINGOFF_STATE: | 555 | case BLINKINGOFF_STATE: |
| 623 | /* Wait for exclusive access to hardware */ | 556 | if (PWR_LED(ctrl->ctrlcap)) |
| 624 | mutex_lock(&ctrl->ctrl_lock); | ||
| 625 | |||
| 626 | if (PWR_LED(ctrl->ctrlcap)) { | ||
| 627 | p_slot->hpc_ops->green_led_on(p_slot); | 557 | p_slot->hpc_ops->green_led_on(p_slot); |
| 628 | /* Wait for the command to complete */ | ||
| 629 | wait_for_ctrl_irq (ctrl); | ||
| 630 | } | ||
| 631 | if (ATTN_LED(ctrl->ctrlcap)) { | ||
| 632 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | ||
| 633 | 558 | ||
| 634 | /* Wait for the command to complete */ | 559 | if (ATTN_LED(ctrl->ctrlcap)) |
| 635 | wait_for_ctrl_irq (ctrl); | 560 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
| 636 | } | ||
| 637 | /* Done with exclusive hardware access */ | ||
| 638 | mutex_unlock(&ctrl->ctrl_lock); | ||
| 639 | break; | 561 | break; |
| 640 | case BLINKINGON_STATE: | 562 | case BLINKINGON_STATE: |
| 641 | /* Wait for exclusive access to hardware */ | 563 | if (PWR_LED(ctrl->ctrlcap)) |
| 642 | mutex_lock(&ctrl->ctrl_lock); | ||
| 643 | |||
| 644 | if (PWR_LED(ctrl->ctrlcap)) { | ||
| 645 | p_slot->hpc_ops->green_led_off(p_slot); | 564 | p_slot->hpc_ops->green_led_off(p_slot); |
| 646 | /* Wait for the command to complete */ | ||
| 647 | wait_for_ctrl_irq (ctrl); | ||
| 648 | } | ||
| 649 | if (ATTN_LED(ctrl->ctrlcap)){ | ||
| 650 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | ||
| 651 | /* Wait for the command to complete */ | ||
| 652 | wait_for_ctrl_irq (ctrl); | ||
| 653 | } | ||
| 654 | /* Done with exclusive hardware access */ | ||
| 655 | mutex_unlock(&ctrl->ctrl_lock); | ||
| 656 | 565 | ||
| 566 | if (ATTN_LED(ctrl->ctrlcap)) | ||
| 567 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | ||
| 657 | break; | 568 | break; |
| 658 | default: | 569 | default: |
| 659 | warn("Not a valid state\n"); | 570 | warn("Not a valid state\n"); |
| 660 | return; | 571 | return; |
| 661 | } | 572 | } |
| 662 | info(msg_button_cancel, slot_name(p_slot)); | 573 | info("PCI slot #%s - action canceled due to button press.\n", slot_name(p_slot)); |
| 663 | p_slot->state = STATIC_STATE; | 574 | p_slot->state = STATIC_STATE; |
| 664 | } | 575 | } |
| 665 | /* ***********Button Pressed (No action on 1st press...) */ | 576 | /* ***********Button Pressed (No action on 1st press...) */ |
| @@ -672,34 +583,21 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 672 | /* slot is on */ | 583 | /* slot is on */ |
| 673 | dbg("slot is on\n"); | 584 | dbg("slot is on\n"); |
| 674 | p_slot->state = BLINKINGOFF_STATE; | 585 | p_slot->state = BLINKINGOFF_STATE; |
| 675 | info(msg_button_off, slot_name(p_slot)); | 586 | info("PCI slot #%s - powering off due to button press.\n", slot_name(p_slot)); |
| 676 | } else { | 587 | } else { |
| 677 | /* slot is off */ | 588 | /* slot is off */ |
| 678 | dbg("slot is off\n"); | 589 | dbg("slot is off\n"); |
| 679 | p_slot->state = BLINKINGON_STATE; | 590 | p_slot->state = BLINKINGON_STATE; |
| 680 | info(msg_button_on, slot_name(p_slot)); | 591 | info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot)); |
| 681 | } | 592 | } |
| 682 | 593 | ||
| 683 | /* Wait for exclusive access to hardware */ | ||
| 684 | mutex_lock(&ctrl->ctrl_lock); | ||
| 685 | |||
| 686 | /* blink green LED and turn off amber */ | 594 | /* blink green LED and turn off amber */ |
| 687 | if (PWR_LED(ctrl->ctrlcap)) { | 595 | if (PWR_LED(ctrl->ctrlcap)) |
| 688 | p_slot->hpc_ops->green_led_blink(p_slot); | 596 | p_slot->hpc_ops->green_led_blink(p_slot); |
| 689 | /* Wait for the command to complete */ | ||
| 690 | wait_for_ctrl_irq (ctrl); | ||
| 691 | } | ||
| 692 | 597 | ||
| 693 | if (ATTN_LED(ctrl->ctrlcap)) { | 598 | if (ATTN_LED(ctrl->ctrlcap)) |
| 694 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 599 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
| 695 | 600 | ||
| 696 | /* Wait for the command to complete */ | ||
| 697 | wait_for_ctrl_irq (ctrl); | ||
| 698 | } | ||
| 699 | |||
| 700 | /* Done with exclusive hardware access */ | ||
| 701 | mutex_unlock(&ctrl->ctrl_lock); | ||
| 702 | |||
| 703 | init_timer(&p_slot->task_event); | 601 | init_timer(&p_slot->task_event); |
| 704 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ | 602 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ |
| 705 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; | 603 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; |
| @@ -712,21 +610,11 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 712 | else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { | 610 | else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { |
| 713 | if (POWER_CTRL(ctrl->ctrlcap)) { | 611 | if (POWER_CTRL(ctrl->ctrlcap)) { |
| 714 | dbg("power fault\n"); | 612 | dbg("power fault\n"); |
| 715 | /* Wait for exclusive access to hardware */ | 613 | if (ATTN_LED(ctrl->ctrlcap)) |
| 716 | mutex_lock(&ctrl->ctrl_lock); | ||
| 717 | |||
| 718 | if (ATTN_LED(ctrl->ctrlcap)) { | ||
| 719 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | 614 | p_slot->hpc_ops->set_attention_status(p_slot, 1); |
| 720 | wait_for_ctrl_irq (ctrl); | ||
| 721 | } | ||
| 722 | 615 | ||
| 723 | if (PWR_LED(ctrl->ctrlcap)) { | 616 | if (PWR_LED(ctrl->ctrlcap)) |
| 724 | p_slot->hpc_ops->green_led_off(p_slot); | 617 | p_slot->hpc_ops->green_led_off(p_slot); |
| 725 | wait_for_ctrl_irq (ctrl); | ||
| 726 | } | ||
| 727 | |||
| 728 | /* Done with exclusive hardware access */ | ||
| 729 | mutex_unlock(&ctrl->ctrl_lock); | ||
| 730 | } | 618 | } |
| 731 | } | 619 | } |
| 732 | /***********SURPRISE REMOVAL********************/ | 620 | /***********SURPRISE REMOVAL********************/ |
| @@ -754,7 +642,6 @@ static void interrupt_event_handler(struct controller *ctrl) | |||
| 754 | } | 642 | } |
| 755 | } | 643 | } |
| 756 | 644 | ||
| 757 | |||
| 758 | int pciehp_enable_slot(struct slot *p_slot) | 645 | int pciehp_enable_slot(struct slot *p_slot) |
| 759 | { | 646 | { |
| 760 | u8 getstatus = 0; | 647 | u8 getstatus = 0; |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 25d3aadfddbf..fbc64aa2dd68 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/timer.h> | 35 | #include <linux/timer.h> |
| 36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
| 37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
| 38 | #include <linux/time.h> | ||
| 38 | 39 | ||
| 39 | #include "../pci.h" | 40 | #include "../pci.h" |
| 40 | #include "pciehp.h" | 41 | #include "pciehp.h" |
| @@ -105,34 +106,30 @@ enum ctrl_offsets { | |||
| 105 | ROOTCTRL = offsetof(struct ctrl_reg, root_ctrl), | 106 | ROOTCTRL = offsetof(struct ctrl_reg, root_ctrl), |
| 106 | ROOTSTATUS = offsetof(struct ctrl_reg, root_status), | 107 | ROOTSTATUS = offsetof(struct ctrl_reg, root_status), |
| 107 | }; | 108 | }; |
| 108 | static int pcie_cap_base = 0; /* Base of the PCI Express capability item structure */ | 109 | |
| 109 | 110 | static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) | |
| 110 | #define PCIE_CAP_ID(cb) ( cb + PCIECAPID ) | 111 | { |
| 111 | #define NXT_CAP_PTR(cb) ( cb + NXTCAPPTR ) | 112 | struct pci_dev *dev = ctrl->pci_dev; |
| 112 | #define CAP_REG(cb) ( cb + CAPREG ) | 113 | return pci_read_config_word(dev, ctrl->cap_base + reg, value); |
| 113 | #define DEV_CAP(cb) ( cb + DEVCAP ) | 114 | } |
| 114 | #define DEV_CTRL(cb) ( cb + DEVCTRL ) | 115 | |
| 115 | #define DEV_STATUS(cb) ( cb + DEVSTATUS ) | 116 | static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value) |
| 116 | #define LNK_CAP(cb) ( cb + LNKCAP ) | 117 | { |
| 117 | #define LNK_CTRL(cb) ( cb + LNKCTRL ) | 118 | struct pci_dev *dev = ctrl->pci_dev; |
| 118 | #define LNK_STATUS(cb) ( cb + LNKSTATUS ) | 119 | return pci_read_config_dword(dev, ctrl->cap_base + reg, value); |
| 119 | #define SLOT_CAP(cb) ( cb + SLOTCAP ) | 120 | } |
| 120 | #define SLOT_CTRL(cb) ( cb + SLOTCTRL ) | 121 | |
| 121 | #define SLOT_STATUS(cb) ( cb + SLOTSTATUS ) | 122 | static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value) |
| 122 | #define ROOT_CTRL(cb) ( cb + ROOTCTRL ) | 123 | { |
| 123 | #define ROOT_STATUS(cb) ( cb + ROOTSTATUS ) | 124 | struct pci_dev *dev = ctrl->pci_dev; |
| 124 | 125 | return pci_write_config_word(dev, ctrl->cap_base + reg, value); | |
| 125 | #define hp_register_read_word(pdev, reg , value) \ | 126 | } |
| 126 | pci_read_config_word(pdev, reg, &value) | 127 | |
| 127 | 128 | static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) | |
| 128 | #define hp_register_read_dword(pdev, reg , value) \ | 129 | { |
| 129 | pci_read_config_dword(pdev, reg, &value) | 130 | struct pci_dev *dev = ctrl->pci_dev; |
| 130 | 131 | return pci_write_config_dword(dev, ctrl->cap_base + reg, value); | |
| 131 | #define hp_register_write_word(pdev, reg , value) \ | 132 | } |
| 132 | pci_write_config_word(pdev, reg, value) | ||
| 133 | |||
| 134 | #define hp_register_dwrite_word(pdev, reg , value) \ | ||
| 135 | pci_write_config_dword(pdev, reg, value) | ||
| 136 | 133 | ||
| 137 | /* Field definitions in PCI Express Capabilities Register */ | 134 | /* Field definitions in PCI Express Capabilities Register */ |
| 138 | #define CAP_VER 0x000F | 135 | #define CAP_VER 0x000F |
| @@ -196,6 +193,7 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct | |||
| 196 | #define ATTN_LED_CTRL 0x00C0 | 193 | #define ATTN_LED_CTRL 0x00C0 |
| 197 | #define PWR_LED_CTRL 0x0300 | 194 | #define PWR_LED_CTRL 0x0300 |
| 198 | #define PWR_CTRL 0x0400 | 195 | #define PWR_CTRL 0x0400 |
| 196 | #define EMI_CTRL 0x0800 | ||
| 199 | 197 | ||
| 200 | /* Attention indicator and Power indicator states */ | 198 | /* Attention indicator and Power indicator states */ |
| 201 | #define LED_ON 0x01 | 199 | #define LED_ON 0x01 |
| @@ -206,6 +204,10 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct | |||
| 206 | #define POWER_ON 0 | 204 | #define POWER_ON 0 |
| 207 | #define POWER_OFF 0x0400 | 205 | #define POWER_OFF 0x0400 |
| 208 | 206 | ||
| 207 | /* EMI Status defines */ | ||
| 208 | #define EMI_DISENGAGED 0 | ||
| 209 | #define EMI_ENGAGED 1 | ||
| 210 | |||
| 209 | /* Field definitions in Slot Status Register */ | 211 | /* Field definitions in Slot Status Register */ |
| 210 | #define ATTN_BUTTN_PRESSED 0x0001 | 212 | #define ATTN_BUTTN_PRESSED 0x0001 |
| 211 | #define PWR_FAULT_DETECTED 0x0002 | 213 | #define PWR_FAULT_DETECTED 0x0002 |
| @@ -214,114 +216,117 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct | |||
| 214 | #define CMD_COMPLETED 0x0010 | 216 | #define CMD_COMPLETED 0x0010 |
| 215 | #define MRL_STATE 0x0020 | 217 | #define MRL_STATE 0x0020 |
| 216 | #define PRSN_STATE 0x0040 | 218 | #define PRSN_STATE 0x0040 |
| 219 | #define EMI_STATE 0x0080 | ||
| 220 | #define EMI_STATUS_BIT 7 | ||
| 217 | 221 | ||
| 218 | static spinlock_t hpc_event_lock; | 222 | static spinlock_t hpc_event_lock; |
| 219 | 223 | ||
| 220 | DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ | 224 | DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ |
| 221 | static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */ | ||
| 222 | static int ctlr_seq_num = 0; /* Controller sequence # */ | 225 | static int ctlr_seq_num = 0; /* Controller sequence # */ |
| 223 | static spinlock_t list_lock; | ||
| 224 | |||
| 225 | static irqreturn_t pcie_isr(int IRQ, void *dev_id); | ||
| 226 | 226 | ||
| 227 | static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); | 227 | static irqreturn_t pcie_isr(int irq, void *dev_id); |
| 228 | static void start_int_poll_timer(struct controller *ctrl, int sec); | ||
| 228 | 229 | ||
| 229 | /* This is the interrupt polling timeout function. */ | 230 | /* This is the interrupt polling timeout function. */ |
| 230 | static void int_poll_timeout(unsigned long lphp_ctlr) | 231 | static void int_poll_timeout(unsigned long data) |
| 231 | { | 232 | { |
| 232 | struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr; | 233 | struct controller *ctrl = (struct controller *)data; |
| 233 | 234 | ||
| 234 | DBG_ENTER_ROUTINE | 235 | DBG_ENTER_ROUTINE |
| 235 | 236 | ||
| 236 | if ( !php_ctlr ) { | ||
| 237 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 238 | return; | ||
| 239 | } | ||
| 240 | |||
| 241 | /* Poll for interrupt events. regs == NULL => polling */ | 237 | /* Poll for interrupt events. regs == NULL => polling */ |
| 242 | pcie_isr( 0, (void *)php_ctlr ); | 238 | pcie_isr(0, ctrl); |
| 243 | |||
| 244 | init_timer(&php_ctlr->int_poll_timer); | ||
| 245 | 239 | ||
| 240 | init_timer(&ctrl->poll_timer); | ||
| 246 | if (!pciehp_poll_time) | 241 | if (!pciehp_poll_time) |
| 247 | pciehp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/ | 242 | pciehp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/ |
| 248 | 243 | ||
| 249 | start_int_poll_timer(php_ctlr, pciehp_poll_time); | 244 | start_int_poll_timer(ctrl, pciehp_poll_time); |
| 250 | |||
| 251 | return; | ||
| 252 | } | 245 | } |
| 253 | 246 | ||
| 254 | /* This function starts the interrupt polling timer. */ | 247 | /* This function starts the interrupt polling timer. */ |
| 255 | static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds) | 248 | static void start_int_poll_timer(struct controller *ctrl, int sec) |
| 256 | { | 249 | { |
| 257 | if (!php_ctlr) { | 250 | /* Clamp to sane value */ |
| 258 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 251 | if ((sec <= 0) || (sec > 60)) |
| 259 | return; | 252 | sec = 2; |
| 260 | } | 253 | |
| 254 | ctrl->poll_timer.function = &int_poll_timeout; | ||
| 255 | ctrl->poll_timer.data = (unsigned long)ctrl; | ||
| 256 | ctrl->poll_timer.expires = jiffies + sec * HZ; | ||
| 257 | add_timer(&ctrl->poll_timer); | ||
| 258 | } | ||
| 261 | 259 | ||
| 262 | if ( ( seconds <= 0 ) || ( seconds > 60 ) ) | 260 | static inline int pcie_wait_cmd(struct controller *ctrl) |
| 263 | seconds = 2; /* Clamp to sane value */ | 261 | { |
| 262 | int retval = 0; | ||
| 263 | unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; | ||
| 264 | unsigned long timeout = msecs_to_jiffies(msecs); | ||
| 265 | int rc; | ||
| 264 | 266 | ||
| 265 | php_ctlr->int_poll_timer.function = &int_poll_timeout; | 267 | rc = wait_event_interruptible_timeout(ctrl->queue, |
| 266 | php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; /* Instance data */ | 268 | !ctrl->cmd_busy, timeout); |
| 267 | php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ; | 269 | if (!rc) |
| 268 | add_timer(&php_ctlr->int_poll_timer); | 270 | dbg("Command not completed in 1000 msec\n"); |
| 271 | else if (rc < 0) { | ||
| 272 | retval = -EINTR; | ||
| 273 | info("Command was interrupted by a signal\n"); | ||
| 274 | } | ||
| 269 | 275 | ||
| 270 | return; | 276 | return retval; |
| 271 | } | 277 | } |
| 272 | 278 | ||
| 273 | static int pcie_write_cmd(struct slot *slot, u16 cmd) | 279 | static int pcie_write_cmd(struct slot *slot, u16 cmd) |
| 274 | { | 280 | { |
| 275 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 281 | struct controller *ctrl = slot->ctrl; |
| 276 | int retval = 0; | 282 | int retval = 0; |
| 277 | u16 slot_status; | 283 | u16 slot_status; |
| 278 | 284 | ||
| 279 | DBG_ENTER_ROUTINE | 285 | DBG_ENTER_ROUTINE |
| 280 | |||
| 281 | if (!php_ctlr) { | ||
| 282 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 283 | return -1; | ||
| 284 | } | ||
| 285 | 286 | ||
| 286 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); | 287 | mutex_lock(&ctrl->ctrl_lock); |
| 288 | |||
| 289 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | ||
| 287 | if (retval) { | 290 | if (retval) { |
| 288 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 291 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); |
| 289 | return retval; | 292 | goto out; |
| 290 | } | 293 | } |
| 291 | 294 | ||
| 292 | if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { | 295 | if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { |
| 293 | /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue | 296 | /* After 1 sec and CMD_COMPLETED still not set, just |
| 294 | the next command according to spec. Just print out the error message */ | 297 | proceed forward to issue the next command according |
| 295 | dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__); | 298 | to spec. Just print out the error message */ |
| 299 | dbg("%s: CMD_COMPLETED not clear after 1 sec.\n", | ||
| 300 | __FUNCTION__); | ||
| 296 | } | 301 | } |
| 297 | 302 | ||
| 298 | retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE); | 303 | ctrl->cmd_busy = 1; |
| 304 | retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE)); | ||
| 299 | if (retval) { | 305 | if (retval) { |
| 300 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 306 | err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); |
| 301 | return retval; | 307 | goto out; |
| 302 | } | 308 | } |
| 303 | 309 | ||
| 310 | /* | ||
| 311 | * Wait for command completion. | ||
| 312 | */ | ||
| 313 | retval = pcie_wait_cmd(ctrl); | ||
| 314 | out: | ||
| 315 | mutex_unlock(&ctrl->ctrl_lock); | ||
| 304 | DBG_LEAVE_ROUTINE | 316 | DBG_LEAVE_ROUTINE |
| 305 | return retval; | 317 | return retval; |
| 306 | } | 318 | } |
| 307 | 319 | ||
| 308 | static int hpc_check_lnk_status(struct controller *ctrl) | 320 | static int hpc_check_lnk_status(struct controller *ctrl) |
| 309 | { | 321 | { |
| 310 | struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; | ||
| 311 | u16 lnk_status; | 322 | u16 lnk_status; |
| 312 | int retval = 0; | 323 | int retval = 0; |
| 313 | 324 | ||
| 314 | DBG_ENTER_ROUTINE | 325 | DBG_ENTER_ROUTINE |
| 315 | 326 | ||
| 316 | if (!php_ctlr) { | 327 | retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); |
| 317 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 318 | return -1; | ||
| 319 | } | ||
| 320 | |||
| 321 | retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(ctrl->cap_base), lnk_status); | ||
| 322 | |||
| 323 | if (retval) { | 328 | if (retval) { |
| 324 | err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); | 329 | err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__); |
| 325 | return retval; | 330 | return retval; |
| 326 | } | 331 | } |
| 327 | 332 | ||
| @@ -340,26 +345,21 @@ static int hpc_check_lnk_status(struct controller *ctrl) | |||
| 340 | 345 | ||
| 341 | static int hpc_get_attention_status(struct slot *slot, u8 *status) | 346 | static int hpc_get_attention_status(struct slot *slot, u8 *status) |
| 342 | { | 347 | { |
| 343 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 348 | struct controller *ctrl = slot->ctrl; |
| 344 | u16 slot_ctrl; | 349 | u16 slot_ctrl; |
| 345 | u8 atten_led_state; | 350 | u8 atten_led_state; |
| 346 | int retval = 0; | 351 | int retval = 0; |
| 347 | 352 | ||
| 348 | DBG_ENTER_ROUTINE | 353 | DBG_ENTER_ROUTINE |
| 349 | 354 | ||
| 350 | if (!php_ctlr) { | 355 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); |
| 351 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 352 | return -1; | ||
| 353 | } | ||
| 354 | |||
| 355 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); | ||
| 356 | |||
| 357 | if (retval) { | 356 | if (retval) { |
| 358 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 357 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
| 359 | return retval; | 358 | return retval; |
| 360 | } | 359 | } |
| 361 | 360 | ||
| 362 | dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); | 361 | dbg("%s: SLOTCTRL %x, value read %x\n", |
| 362 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); | ||
| 363 | 363 | ||
| 364 | atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6; | 364 | atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6; |
| 365 | 365 | ||
| @@ -385,27 +385,22 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) | |||
| 385 | return 0; | 385 | return 0; |
| 386 | } | 386 | } |
| 387 | 387 | ||
| 388 | static int hpc_get_power_status(struct slot * slot, u8 *status) | 388 | static int hpc_get_power_status(struct slot *slot, u8 *status) |
| 389 | { | 389 | { |
| 390 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 390 | struct controller *ctrl = slot->ctrl; |
| 391 | u16 slot_ctrl; | 391 | u16 slot_ctrl; |
| 392 | u8 pwr_state; | 392 | u8 pwr_state; |
| 393 | int retval = 0; | 393 | int retval = 0; |
| 394 | 394 | ||
| 395 | DBG_ENTER_ROUTINE | 395 | DBG_ENTER_ROUTINE |
| 396 | 396 | ||
| 397 | if (!php_ctlr) { | 397 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); |
| 398 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 399 | return -1; | ||
| 400 | } | ||
| 401 | |||
| 402 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); | ||
| 403 | |||
| 404 | if (retval) { | 398 | if (retval) { |
| 405 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 399 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
| 406 | return retval; | 400 | return retval; |
| 407 | } | 401 | } |
| 408 | dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); | 402 | dbg("%s: SLOTCTRL %x value read %x\n", |
| 403 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); | ||
| 409 | 404 | ||
| 410 | pwr_state = (slot_ctrl & PWR_CTRL) >> 10; | 405 | pwr_state = (slot_ctrl & PWR_CTRL) >> 10; |
| 411 | 406 | ||
| @@ -428,21 +423,15 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) | |||
| 428 | 423 | ||
| 429 | static int hpc_get_latch_status(struct slot *slot, u8 *status) | 424 | static int hpc_get_latch_status(struct slot *slot, u8 *status) |
| 430 | { | 425 | { |
| 431 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 426 | struct controller *ctrl = slot->ctrl; |
| 432 | u16 slot_status; | 427 | u16 slot_status; |
| 433 | int retval = 0; | 428 | int retval = 0; |
| 434 | 429 | ||
| 435 | DBG_ENTER_ROUTINE | 430 | DBG_ENTER_ROUTINE |
| 436 | 431 | ||
| 437 | if (!php_ctlr) { | 432 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
| 438 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 439 | return -1; | ||
| 440 | } | ||
| 441 | |||
| 442 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); | ||
| 443 | |||
| 444 | if (retval) { | 433 | if (retval) { |
| 445 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 434 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); |
| 446 | return retval; | 435 | return retval; |
| 447 | } | 436 | } |
| 448 | 437 | ||
| @@ -454,22 +443,16 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status) | |||
| 454 | 443 | ||
| 455 | static int hpc_get_adapter_status(struct slot *slot, u8 *status) | 444 | static int hpc_get_adapter_status(struct slot *slot, u8 *status) |
| 456 | { | 445 | { |
| 457 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 446 | struct controller *ctrl = slot->ctrl; |
| 458 | u16 slot_status; | 447 | u16 slot_status; |
| 459 | u8 card_state; | 448 | u8 card_state; |
| 460 | int retval = 0; | 449 | int retval = 0; |
| 461 | 450 | ||
| 462 | DBG_ENTER_ROUTINE | 451 | DBG_ENTER_ROUTINE |
| 463 | 452 | ||
| 464 | if (!php_ctlr) { | 453 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
| 465 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 466 | return -1; | ||
| 467 | } | ||
| 468 | |||
| 469 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); | ||
| 470 | |||
| 471 | if (retval) { | 454 | if (retval) { |
| 472 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 455 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); |
| 473 | return retval; | 456 | return retval; |
| 474 | } | 457 | } |
| 475 | card_state = (u8)((slot_status & PRSN_STATE) >> 6); | 458 | card_state = (u8)((slot_status & PRSN_STATE) >> 6); |
| @@ -479,24 +462,18 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status) | |||
| 479 | return 0; | 462 | return 0; |
| 480 | } | 463 | } |
| 481 | 464 | ||
| 482 | static int hpc_query_power_fault(struct slot * slot) | 465 | static int hpc_query_power_fault(struct slot *slot) |
| 483 | { | 466 | { |
| 484 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 467 | struct controller *ctrl = slot->ctrl; |
| 485 | u16 slot_status; | 468 | u16 slot_status; |
| 486 | u8 pwr_fault; | 469 | u8 pwr_fault; |
| 487 | int retval = 0; | 470 | int retval = 0; |
| 488 | 471 | ||
| 489 | DBG_ENTER_ROUTINE | 472 | DBG_ENTER_ROUTINE |
| 490 | 473 | ||
| 491 | if (!php_ctlr) { | 474 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
| 492 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 493 | return -1; | ||
| 494 | } | ||
| 495 | |||
| 496 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); | ||
| 497 | |||
| 498 | if (retval) { | 475 | if (retval) { |
| 499 | err("%s : Cannot check for power fault\n", __FUNCTION__); | 476 | err("%s: Cannot check for power fault\n", __FUNCTION__); |
| 500 | return retval; | 477 | return retval; |
| 501 | } | 478 | } |
| 502 | pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); | 479 | pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); |
| @@ -505,28 +482,63 @@ static int hpc_query_power_fault(struct slot * slot) | |||
| 505 | return pwr_fault; | 482 | return pwr_fault; |
| 506 | } | 483 | } |
| 507 | 484 | ||
| 508 | static int hpc_set_attention_status(struct slot *slot, u8 value) | 485 | static int hpc_get_emi_status(struct slot *slot, u8 *status) |
| 509 | { | 486 | { |
| 510 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 487 | struct controller *ctrl = slot->ctrl; |
| 488 | u16 slot_status; | ||
| 489 | int retval = 0; | ||
| 490 | |||
| 491 | DBG_ENTER_ROUTINE | ||
| 492 | |||
| 493 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | ||
| 494 | if (retval) { | ||
| 495 | err("%s : Cannot check EMI status\n", __FUNCTION__); | ||
| 496 | return retval; | ||
| 497 | } | ||
| 498 | *status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT; | ||
| 499 | |||
| 500 | DBG_LEAVE_ROUTINE | ||
| 501 | return retval; | ||
| 502 | } | ||
| 503 | |||
| 504 | static int hpc_toggle_emi(struct slot *slot) | ||
| 505 | { | ||
| 506 | struct controller *ctrl = slot->ctrl; | ||
| 511 | u16 slot_cmd = 0; | 507 | u16 slot_cmd = 0; |
| 512 | u16 slot_ctrl; | 508 | u16 slot_ctrl; |
| 513 | int rc = 0; | 509 | int rc = 0; |
| 514 | 510 | ||
| 515 | DBG_ENTER_ROUTINE | 511 | DBG_ENTER_ROUTINE |
| 516 | 512 | ||
| 517 | if (!php_ctlr) { | 513 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); |
| 518 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 514 | if (rc) { |
| 519 | return -1; | 515 | err("%s : hp_register_read_word SLOT_CTRL failed\n", |
| 516 | __FUNCTION__); | ||
| 517 | return rc; | ||
| 520 | } | 518 | } |
| 521 | 519 | ||
| 522 | if (slot->hp_slot >= php_ctlr->num_slots) { | 520 | slot_cmd = (slot_ctrl | EMI_CTRL); |
| 523 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | 521 | if (!pciehp_poll_mode) |
| 524 | return -1; | 522 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
| 525 | } | ||
| 526 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); | ||
| 527 | 523 | ||
| 524 | pcie_write_cmd(slot, slot_cmd); | ||
| 525 | slot->last_emi_toggle = get_seconds(); | ||
| 526 | DBG_LEAVE_ROUTINE | ||
| 527 | return rc; | ||
| 528 | } | ||
| 529 | |||
| 530 | static int hpc_set_attention_status(struct slot *slot, u8 value) | ||
| 531 | { | ||
| 532 | struct controller *ctrl = slot->ctrl; | ||
| 533 | u16 slot_cmd = 0; | ||
| 534 | u16 slot_ctrl; | ||
| 535 | int rc = 0; | ||
| 536 | |||
| 537 | DBG_ENTER_ROUTINE | ||
| 538 | |||
| 539 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | ||
| 528 | if (rc) { | 540 | if (rc) { |
| 529 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 541 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
| 530 | return rc; | 542 | return rc; |
| 531 | } | 543 | } |
| 532 | 544 | ||
| @@ -547,7 +559,8 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) | |||
| 547 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 559 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
| 548 | 560 | ||
| 549 | pcie_write_cmd(slot, slot_cmd); | 561 | pcie_write_cmd(slot, slot_cmd); |
| 550 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 562 | dbg("%s: SLOTCTRL %x write cmd %x\n", |
| 563 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); | ||
| 551 | 564 | ||
| 552 | DBG_LEAVE_ROUTINE | 565 | DBG_LEAVE_ROUTINE |
| 553 | return rc; | 566 | return rc; |
| @@ -556,27 +569,16 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) | |||
| 556 | 569 | ||
| 557 | static void hpc_set_green_led_on(struct slot *slot) | 570 | static void hpc_set_green_led_on(struct slot *slot) |
| 558 | { | 571 | { |
| 559 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 572 | struct controller *ctrl = slot->ctrl; |
| 560 | u16 slot_cmd; | 573 | u16 slot_cmd; |
| 561 | u16 slot_ctrl; | 574 | u16 slot_ctrl; |
| 562 | int rc = 0; | 575 | int rc = 0; |
| 563 | 576 | ||
| 564 | DBG_ENTER_ROUTINE | 577 | DBG_ENTER_ROUTINE |
| 565 | 578 | ||
| 566 | if (!php_ctlr) { | 579 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); |
| 567 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 568 | return ; | ||
| 569 | } | ||
| 570 | |||
| 571 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
| 572 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
| 573 | return ; | ||
| 574 | } | ||
| 575 | |||
| 576 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); | ||
| 577 | |||
| 578 | if (rc) { | 580 | if (rc) { |
| 579 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 581 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
| 580 | return; | 582 | return; |
| 581 | } | 583 | } |
| 582 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100; | 584 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100; |
| @@ -585,34 +587,24 @@ static void hpc_set_green_led_on(struct slot *slot) | |||
| 585 | 587 | ||
| 586 | pcie_write_cmd(slot, slot_cmd); | 588 | pcie_write_cmd(slot, slot_cmd); |
| 587 | 589 | ||
| 588 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 590 | dbg("%s: SLOTCTRL %x write cmd %x\n", |
| 591 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); | ||
| 589 | DBG_LEAVE_ROUTINE | 592 | DBG_LEAVE_ROUTINE |
| 590 | return; | 593 | return; |
| 591 | } | 594 | } |
| 592 | 595 | ||
| 593 | static void hpc_set_green_led_off(struct slot *slot) | 596 | static void hpc_set_green_led_off(struct slot *slot) |
| 594 | { | 597 | { |
| 595 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 598 | struct controller *ctrl = slot->ctrl; |
| 596 | u16 slot_cmd; | 599 | u16 slot_cmd; |
| 597 | u16 slot_ctrl; | 600 | u16 slot_ctrl; |
| 598 | int rc = 0; | 601 | int rc = 0; |
| 599 | 602 | ||
| 600 | DBG_ENTER_ROUTINE | 603 | DBG_ENTER_ROUTINE |
| 601 | 604 | ||
| 602 | if (!php_ctlr) { | 605 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); |
| 603 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 604 | return ; | ||
| 605 | } | ||
| 606 | |||
| 607 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
| 608 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
| 609 | return ; | ||
| 610 | } | ||
| 611 | |||
| 612 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); | ||
| 613 | |||
| 614 | if (rc) { | 606 | if (rc) { |
| 615 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 607 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
| 616 | return; | 608 | return; |
| 617 | } | 609 | } |
| 618 | 610 | ||
| @@ -621,7 +613,8 @@ static void hpc_set_green_led_off(struct slot *slot) | |||
| 621 | if (!pciehp_poll_mode) | 613 | if (!pciehp_poll_mode) |
| 622 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 614 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
| 623 | pcie_write_cmd(slot, slot_cmd); | 615 | pcie_write_cmd(slot, slot_cmd); |
| 624 | dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 616 | dbg("%s: SLOTCTRL %x write cmd %x\n", |
| 617 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); | ||
| 625 | 618 | ||
| 626 | DBG_LEAVE_ROUTINE | 619 | DBG_LEAVE_ROUTINE |
| 627 | return; | 620 | return; |
| @@ -629,27 +622,16 @@ static void hpc_set_green_led_off(struct slot *slot) | |||
| 629 | 622 | ||
| 630 | static void hpc_set_green_led_blink(struct slot *slot) | 623 | static void hpc_set_green_led_blink(struct slot *slot) |
| 631 | { | 624 | { |
| 632 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 625 | struct controller *ctrl = slot->ctrl; |
| 633 | u16 slot_cmd; | 626 | u16 slot_cmd; |
| 634 | u16 slot_ctrl; | 627 | u16 slot_ctrl; |
| 635 | int rc = 0; | 628 | int rc = 0; |
| 636 | 629 | ||
| 637 | DBG_ENTER_ROUTINE | 630 | DBG_ENTER_ROUTINE |
| 638 | 631 | ||
| 639 | if (!php_ctlr) { | 632 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); |
| 640 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 641 | return ; | ||
| 642 | } | ||
| 643 | |||
| 644 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
| 645 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
| 646 | return ; | ||
| 647 | } | ||
| 648 | |||
| 649 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); | ||
| 650 | |||
| 651 | if (rc) { | 633 | if (rc) { |
| 652 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 634 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
| 653 | return; | 635 | return; |
| 654 | } | 636 | } |
| 655 | 637 | ||
| @@ -659,126 +641,54 @@ static void hpc_set_green_led_blink(struct slot *slot) | |||
| 659 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 641 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
| 660 | pcie_write_cmd(slot, slot_cmd); | 642 | pcie_write_cmd(slot, slot_cmd); |
| 661 | 643 | ||
| 662 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 644 | dbg("%s: SLOTCTRL %x write cmd %x\n", |
| 645 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); | ||
| 663 | DBG_LEAVE_ROUTINE | 646 | DBG_LEAVE_ROUTINE |
| 664 | return; | 647 | return; |
| 665 | } | 648 | } |
| 666 | 649 | ||
| 667 | int pcie_get_ctlr_slot_config(struct controller *ctrl, | ||
| 668 | int *num_ctlr_slots, /* number of slots in this HPC; only 1 in PCIE */ | ||
| 669 | int *first_device_num, /* PCI dev num of the first slot in this PCIE */ | ||
| 670 | int *physical_slot_num, /* phy slot num of the first slot in this PCIE */ | ||
| 671 | u8 *ctrlcap) | ||
| 672 | { | ||
| 673 | struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; | ||
| 674 | u32 slot_cap; | ||
| 675 | int rc = 0; | ||
| 676 | |||
| 677 | DBG_ENTER_ROUTINE | ||
| 678 | |||
| 679 | if (!php_ctlr) { | ||
| 680 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 681 | return -1; | ||
| 682 | } | ||
| 683 | |||
| 684 | *first_device_num = 0; | ||
| 685 | *num_ctlr_slots = 1; | ||
| 686 | |||
| 687 | rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap); | ||
| 688 | |||
| 689 | if (rc) { | ||
| 690 | err("%s : hp_register_read_dword SLOT_CAP failed\n", __FUNCTION__); | ||
| 691 | return -1; | ||
| 692 | } | ||
| 693 | |||
| 694 | *physical_slot_num = slot_cap >> 19; | ||
| 695 | dbg("%s: PSN %d \n", __FUNCTION__, *physical_slot_num); | ||
| 696 | |||
| 697 | *ctrlcap = slot_cap & 0x0000007f; | ||
| 698 | |||
| 699 | DBG_LEAVE_ROUTINE | ||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | static void hpc_release_ctlr(struct controller *ctrl) | 650 | static void hpc_release_ctlr(struct controller *ctrl) |
| 704 | { | 651 | { |
| 705 | struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; | ||
| 706 | struct php_ctlr_state_s *p, *p_prev; | ||
| 707 | |||
| 708 | DBG_ENTER_ROUTINE | 652 | DBG_ENTER_ROUTINE |
| 709 | 653 | ||
| 710 | if (!php_ctlr) { | 654 | if (pciehp_poll_mode) |
| 711 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | 655 | del_timer(&ctrl->poll_timer); |
| 712 | return ; | 656 | else |
| 713 | } | 657 | free_irq(ctrl->pci_dev->irq, ctrl); |
| 714 | |||
| 715 | if (pciehp_poll_mode) { | ||
| 716 | del_timer(&php_ctlr->int_poll_timer); | ||
| 717 | } else { | ||
| 718 | if (php_ctlr->irq) { | ||
| 719 | free_irq(php_ctlr->irq, ctrl); | ||
| 720 | php_ctlr->irq = 0; | ||
| 721 | } | ||
| 722 | } | ||
| 723 | if (php_ctlr->pci_dev) | ||
| 724 | php_ctlr->pci_dev = NULL; | ||
| 725 | |||
| 726 | spin_lock(&list_lock); | ||
| 727 | p = php_ctlr_list_head; | ||
| 728 | p_prev = NULL; | ||
| 729 | while (p) { | ||
| 730 | if (p == php_ctlr) { | ||
| 731 | if (p_prev) | ||
| 732 | p_prev->pnext = p->pnext; | ||
| 733 | else | ||
| 734 | php_ctlr_list_head = p->pnext; | ||
| 735 | break; | ||
| 736 | } else { | ||
| 737 | p_prev = p; | ||
| 738 | p = p->pnext; | ||
| 739 | } | ||
| 740 | } | ||
| 741 | spin_unlock(&list_lock); | ||
| 742 | |||
| 743 | kfree(php_ctlr); | ||
| 744 | 658 | ||
| 745 | DBG_LEAVE_ROUTINE | 659 | DBG_LEAVE_ROUTINE |
| 746 | |||
| 747 | } | 660 | } |
| 748 | 661 | ||
| 749 | static int hpc_power_on_slot(struct slot * slot) | 662 | static int hpc_power_on_slot(struct slot * slot) |
| 750 | { | 663 | { |
| 751 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 664 | struct controller *ctrl = slot->ctrl; |
| 752 | u16 slot_cmd; | 665 | u16 slot_cmd; |
| 753 | u16 slot_ctrl, slot_status; | 666 | u16 slot_ctrl, slot_status; |
| 754 | |||
| 755 | int retval = 0; | 667 | int retval = 0; |
| 756 | 668 | ||
| 757 | DBG_ENTER_ROUTINE | 669 | DBG_ENTER_ROUTINE |
| 758 | 670 | ||
| 759 | if (!php_ctlr) { | ||
| 760 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 761 | return -1; | ||
| 762 | } | ||
| 763 | |||
| 764 | dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); | 671 | dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); |
| 765 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
| 766 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
| 767 | return -1; | ||
| 768 | } | ||
| 769 | 672 | ||
| 770 | /* Clear sticky power-fault bit from previous power failures */ | 673 | /* Clear sticky power-fault bit from previous power failures */ |
| 771 | hp_register_read_word(php_ctlr->pci_dev, | 674 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
| 772 | SLOT_STATUS(slot->ctrl->cap_base), slot_status); | 675 | if (retval) { |
| 676 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); | ||
| 677 | return retval; | ||
| 678 | } | ||
| 773 | slot_status &= PWR_FAULT_DETECTED; | 679 | slot_status &= PWR_FAULT_DETECTED; |
| 774 | if (slot_status) | 680 | if (slot_status) { |
| 775 | hp_register_write_word(php_ctlr->pci_dev, | 681 | retval = pciehp_writew(ctrl, SLOTSTATUS, slot_status); |
| 776 | SLOT_STATUS(slot->ctrl->cap_base), slot_status); | 682 | if (retval) { |
| 777 | 683 | err("%s: Cannot write to SLOTSTATUS register\n", | |
| 778 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); | 684 | __FUNCTION__); |
| 685 | return retval; | ||
| 686 | } | ||
| 687 | } | ||
| 779 | 688 | ||
| 689 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | ||
| 780 | if (retval) { | 690 | if (retval) { |
| 781 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 691 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
| 782 | return retval; | 692 | return retval; |
| 783 | } | 693 | } |
| 784 | 694 | ||
| @@ -798,7 +708,8 @@ static int hpc_power_on_slot(struct slot * slot) | |||
| 798 | err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd); | 708 | err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd); |
| 799 | return -1; | 709 | return -1; |
| 800 | } | 710 | } |
| 801 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 711 | dbg("%s: SLOTCTRL %x write cmd %x\n", |
| 712 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); | ||
| 802 | 713 | ||
| 803 | DBG_LEAVE_ROUTINE | 714 | DBG_LEAVE_ROUTINE |
| 804 | 715 | ||
| @@ -807,29 +718,18 @@ static int hpc_power_on_slot(struct slot * slot) | |||
| 807 | 718 | ||
| 808 | static int hpc_power_off_slot(struct slot * slot) | 719 | static int hpc_power_off_slot(struct slot * slot) |
| 809 | { | 720 | { |
| 810 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 721 | struct controller *ctrl = slot->ctrl; |
| 811 | u16 slot_cmd; | 722 | u16 slot_cmd; |
| 812 | u16 slot_ctrl; | 723 | u16 slot_ctrl; |
| 813 | |||
| 814 | int retval = 0; | 724 | int retval = 0; |
| 815 | 725 | ||
| 816 | DBG_ENTER_ROUTINE | 726 | DBG_ENTER_ROUTINE |
| 817 | 727 | ||
| 818 | if (!php_ctlr) { | ||
| 819 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 820 | return -1; | ||
| 821 | } | ||
| 822 | |||
| 823 | dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); | 728 | dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); |
| 824 | slot->hp_slot = 0; | ||
| 825 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
| 826 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
| 827 | return -1; | ||
| 828 | } | ||
| 829 | retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); | ||
| 830 | 729 | ||
| 730 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | ||
| 831 | if (retval) { | 731 | if (retval) { |
| 832 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 732 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
| 833 | return retval; | 733 | return retval; |
| 834 | } | 734 | } |
| 835 | 735 | ||
| @@ -854,47 +754,25 @@ static int hpc_power_off_slot(struct slot * slot) | |||
| 854 | err("%s: Write command failed!\n", __FUNCTION__); | 754 | err("%s: Write command failed!\n", __FUNCTION__); |
| 855 | return -1; | 755 | return -1; |
| 856 | } | 756 | } |
| 857 | dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); | 757 | dbg("%s: SLOTCTRL %x write cmd %x\n", |
| 758 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); | ||
| 858 | 759 | ||
| 859 | DBG_LEAVE_ROUTINE | 760 | DBG_LEAVE_ROUTINE |
| 860 | 761 | ||
| 861 | return retval; | 762 | return retval; |
| 862 | } | 763 | } |
| 863 | 764 | ||
| 864 | static irqreturn_t pcie_isr(int IRQ, void *dev_id) | 765 | static irqreturn_t pcie_isr(int irq, void *dev_id) |
| 865 | { | 766 | { |
| 866 | struct controller *ctrl = NULL; | 767 | struct controller *ctrl = (struct controller *)dev_id; |
| 867 | struct php_ctlr_state_s *php_ctlr; | ||
| 868 | u8 schedule_flag = 0; | ||
| 869 | u16 slot_status, intr_detect, intr_loc; | 768 | u16 slot_status, intr_detect, intr_loc; |
| 870 | u16 temp_word; | 769 | u16 temp_word; |
| 871 | int hp_slot = 0; /* only 1 slot per PCI Express port */ | 770 | int hp_slot = 0; /* only 1 slot per PCI Express port */ |
| 872 | int rc = 0; | 771 | int rc = 0; |
| 873 | 772 | ||
| 874 | if (!dev_id) | 773 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
| 875 | return IRQ_NONE; | ||
| 876 | |||
| 877 | if (!pciehp_poll_mode) { | ||
| 878 | ctrl = dev_id; | ||
| 879 | php_ctlr = ctrl->hpc_ctlr_handle; | ||
| 880 | } else { | ||
| 881 | php_ctlr = dev_id; | ||
| 882 | ctrl = (struct controller *)php_ctlr->callback_instance_id; | ||
| 883 | } | ||
| 884 | |||
| 885 | if (!ctrl) { | ||
| 886 | dbg("%s: dev_id %p ctlr == NULL\n", __FUNCTION__, (void*) dev_id); | ||
| 887 | return IRQ_NONE; | ||
| 888 | } | ||
| 889 | |||
| 890 | if (!php_ctlr) { | ||
| 891 | dbg("%s: php_ctlr == NULL\n", __FUNCTION__); | ||
| 892 | return IRQ_NONE; | ||
| 893 | } | ||
| 894 | |||
| 895 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | ||
| 896 | if (rc) { | 774 | if (rc) { |
| 897 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 775 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); |
| 898 | return IRQ_NONE; | 776 | return IRQ_NONE; |
| 899 | } | 777 | } |
| 900 | 778 | ||
| @@ -910,33 +788,38 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id) | |||
| 910 | dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); | 788 | dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); |
| 911 | /* Mask Hot-plug Interrupt Enable */ | 789 | /* Mask Hot-plug Interrupt Enable */ |
| 912 | if (!pciehp_poll_mode) { | 790 | if (!pciehp_poll_mode) { |
| 913 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); | 791 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); |
| 914 | if (rc) { | 792 | if (rc) { |
| 915 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 793 | err("%s: Cannot read SLOT_CTRL register\n", |
| 794 | __FUNCTION__); | ||
| 916 | return IRQ_NONE; | 795 | return IRQ_NONE; |
| 917 | } | 796 | } |
| 918 | 797 | ||
| 919 | dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); | 798 | dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n", |
| 799 | __FUNCTION__, temp_word); | ||
| 920 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; | 800 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; |
| 921 | 801 | rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); | |
| 922 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); | ||
| 923 | if (rc) { | 802 | if (rc) { |
| 924 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 803 | err("%s: Cannot write to SLOTCTRL register\n", |
| 804 | __FUNCTION__); | ||
| 925 | return IRQ_NONE; | 805 | return IRQ_NONE; |
| 926 | } | 806 | } |
| 927 | 807 | ||
| 928 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 808 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
| 929 | if (rc) { | 809 | if (rc) { |
| 930 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 810 | err("%s: Cannot read SLOT_STATUS register\n", |
| 811 | __FUNCTION__); | ||
| 931 | return IRQ_NONE; | 812 | return IRQ_NONE; |
| 932 | } | 813 | } |
| 933 | dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); | 814 | dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n", |
| 815 | __FUNCTION__, slot_status); | ||
| 934 | 816 | ||
| 935 | /* Clear command complete interrupt caused by this write */ | 817 | /* Clear command complete interrupt caused by this write */ |
| 936 | temp_word = 0x1f; | 818 | temp_word = 0x1f; |
| 937 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); | 819 | rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); |
| 938 | if (rc) { | 820 | if (rc) { |
| 939 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 821 | err("%s: Cannot write to SLOTSTATUS register\n", |
| 822 | __FUNCTION__); | ||
| 940 | return IRQ_NONE; | 823 | return IRQ_NONE; |
| 941 | } | 824 | } |
| 942 | } | 825 | } |
| @@ -945,60 +828,65 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id) | |||
| 945 | /* | 828 | /* |
| 946 | * Command Complete Interrupt Pending | 829 | * Command Complete Interrupt Pending |
| 947 | */ | 830 | */ |
| 831 | ctrl->cmd_busy = 0; | ||
| 948 | wake_up_interruptible(&ctrl->queue); | 832 | wake_up_interruptible(&ctrl->queue); |
| 949 | } | 833 | } |
| 950 | 834 | ||
| 951 | if ((php_ctlr->switch_change_callback) && (intr_loc & MRL_SENS_CHANGED)) | 835 | if (intr_loc & MRL_SENS_CHANGED) |
| 952 | schedule_flag += php_ctlr->switch_change_callback( | 836 | pciehp_handle_switch_change(hp_slot, ctrl); |
| 953 | hp_slot, php_ctlr->callback_instance_id); | 837 | |
| 954 | if ((php_ctlr->attention_button_callback) && (intr_loc & ATTN_BUTTN_PRESSED)) | 838 | if (intr_loc & ATTN_BUTTN_PRESSED) |
| 955 | schedule_flag += php_ctlr->attention_button_callback( | 839 | pciehp_handle_attention_button(hp_slot, ctrl); |
| 956 | hp_slot, php_ctlr->callback_instance_id); | 840 | |
| 957 | if ((php_ctlr->presence_change_callback) && (intr_loc & PRSN_DETECT_CHANGED)) | 841 | if (intr_loc & PRSN_DETECT_CHANGED) |
| 958 | schedule_flag += php_ctlr->presence_change_callback( | 842 | pciehp_handle_presence_change(hp_slot, ctrl); |
| 959 | hp_slot , php_ctlr->callback_instance_id); | 843 | |
| 960 | if ((php_ctlr->power_fault_callback) && (intr_loc & PWR_FAULT_DETECTED)) | 844 | if (intr_loc & PWR_FAULT_DETECTED) |
| 961 | schedule_flag += php_ctlr->power_fault_callback( | 845 | pciehp_handle_power_fault(hp_slot, ctrl); |
| 962 | hp_slot, php_ctlr->callback_instance_id); | ||
| 963 | 846 | ||
| 964 | /* Clear all events after serving them */ | 847 | /* Clear all events after serving them */ |
| 965 | temp_word = 0x1F; | 848 | temp_word = 0x1F; |
| 966 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); | 849 | rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); |
| 967 | if (rc) { | 850 | if (rc) { |
| 968 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 851 | err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); |
| 969 | return IRQ_NONE; | 852 | return IRQ_NONE; |
| 970 | } | 853 | } |
| 971 | /* Unmask Hot-plug Interrupt Enable */ | 854 | /* Unmask Hot-plug Interrupt Enable */ |
| 972 | if (!pciehp_poll_mode) { | 855 | if (!pciehp_poll_mode) { |
| 973 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); | 856 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); |
| 974 | if (rc) { | 857 | if (rc) { |
| 975 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 858 | err("%s: Cannot read SLOTCTRL register\n", |
| 859 | __FUNCTION__); | ||
| 976 | return IRQ_NONE; | 860 | return IRQ_NONE; |
| 977 | } | 861 | } |
| 978 | 862 | ||
| 979 | dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__); | 863 | dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__); |
| 980 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; | 864 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; |
| 981 | 865 | ||
| 982 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); | 866 | rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); |
| 983 | if (rc) { | 867 | if (rc) { |
| 984 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 868 | err("%s: Cannot write to SLOTCTRL register\n", |
| 869 | __FUNCTION__); | ||
| 985 | return IRQ_NONE; | 870 | return IRQ_NONE; |
| 986 | } | 871 | } |
| 987 | 872 | ||
| 988 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 873 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
| 989 | if (rc) { | 874 | if (rc) { |
| 990 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 875 | err("%s: Cannot read SLOT_STATUS register\n", |
| 876 | __FUNCTION__); | ||
| 991 | return IRQ_NONE; | 877 | return IRQ_NONE; |
| 992 | } | 878 | } |
| 993 | 879 | ||
| 994 | /* Clear command complete interrupt caused by this write */ | 880 | /* Clear command complete interrupt caused by this write */ |
| 995 | temp_word = 0x1F; | 881 | temp_word = 0x1F; |
| 996 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); | 882 | rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); |
| 997 | if (rc) { | 883 | if (rc) { |
| 998 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 884 | err("%s: Cannot write to SLOTSTATUS failed\n", |
| 885 | __FUNCTION__); | ||
| 999 | return IRQ_NONE; | 886 | return IRQ_NONE; |
| 1000 | } | 887 | } |
| 1001 | dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); | 888 | dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n", |
| 889 | __FUNCTION__, temp_word); | ||
| 1002 | } | 890 | } |
| 1003 | 891 | ||
| 1004 | return IRQ_HANDLED; | 892 | return IRQ_HANDLED; |
| @@ -1006,27 +894,16 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id) | |||
| 1006 | 894 | ||
| 1007 | static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value) | 895 | static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value) |
| 1008 | { | 896 | { |
| 1009 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 897 | struct controller *ctrl = slot->ctrl; |
| 1010 | enum pcie_link_speed lnk_speed; | 898 | enum pcie_link_speed lnk_speed; |
| 1011 | u32 lnk_cap; | 899 | u32 lnk_cap; |
| 1012 | int retval = 0; | 900 | int retval = 0; |
| 1013 | 901 | ||
| 1014 | DBG_ENTER_ROUTINE | 902 | DBG_ENTER_ROUTINE |
| 1015 | 903 | ||
| 1016 | if (!php_ctlr) { | 904 | retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap); |
| 1017 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 1018 | return -1; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
| 1022 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
| 1023 | return -1; | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap); | ||
| 1027 | |||
| 1028 | if (retval) { | 905 | if (retval) { |
| 1029 | err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__); | 906 | err("%s: Cannot read LNKCAP register\n", __FUNCTION__); |
| 1030 | return retval; | 907 | return retval; |
| 1031 | } | 908 | } |
| 1032 | 909 | ||
| @@ -1047,27 +924,16 @@ static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value) | |||
| 1047 | 924 | ||
| 1048 | static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value) | 925 | static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value) |
| 1049 | { | 926 | { |
| 1050 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 927 | struct controller *ctrl = slot->ctrl; |
| 1051 | enum pcie_link_width lnk_wdth; | 928 | enum pcie_link_width lnk_wdth; |
| 1052 | u32 lnk_cap; | 929 | u32 lnk_cap; |
| 1053 | int retval = 0; | 930 | int retval = 0; |
| 1054 | 931 | ||
| 1055 | DBG_ENTER_ROUTINE | 932 | DBG_ENTER_ROUTINE |
| 1056 | 933 | ||
| 1057 | if (!php_ctlr) { | 934 | retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap); |
| 1058 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 1059 | return -1; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
| 1063 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
| 1064 | return -1; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap); | ||
| 1068 | |||
| 1069 | if (retval) { | 935 | if (retval) { |
| 1070 | err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__); | 936 | err("%s: Cannot read LNKCAP register\n", __FUNCTION__); |
| 1071 | return retval; | 937 | return retval; |
| 1072 | } | 938 | } |
| 1073 | 939 | ||
| @@ -1109,27 +975,16 @@ static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value | |||
| 1109 | 975 | ||
| 1110 | static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value) | 976 | static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value) |
| 1111 | { | 977 | { |
| 1112 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 978 | struct controller *ctrl = slot->ctrl; |
| 1113 | enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN; | 979 | enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN; |
| 1114 | int retval = 0; | 980 | int retval = 0; |
| 1115 | u16 lnk_status; | 981 | u16 lnk_status; |
| 1116 | 982 | ||
| 1117 | DBG_ENTER_ROUTINE | 983 | DBG_ENTER_ROUTINE |
| 1118 | 984 | ||
| 1119 | if (!php_ctlr) { | 985 | retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); |
| 1120 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 1121 | return -1; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
| 1125 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
| 1126 | return -1; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status); | ||
| 1130 | |||
| 1131 | if (retval) { | 986 | if (retval) { |
| 1132 | err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); | 987 | err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__); |
| 1133 | return retval; | 988 | return retval; |
| 1134 | } | 989 | } |
| 1135 | 990 | ||
| @@ -1150,27 +1005,16 @@ static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value) | |||
| 1150 | 1005 | ||
| 1151 | static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value) | 1006 | static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value) |
| 1152 | { | 1007 | { |
| 1153 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 1008 | struct controller *ctrl = slot->ctrl; |
| 1154 | enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN; | 1009 | enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN; |
| 1155 | int retval = 0; | 1010 | int retval = 0; |
| 1156 | u16 lnk_status; | 1011 | u16 lnk_status; |
| 1157 | 1012 | ||
| 1158 | DBG_ENTER_ROUTINE | 1013 | DBG_ENTER_ROUTINE |
| 1159 | 1014 | ||
| 1160 | if (!php_ctlr) { | 1015 | retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); |
| 1161 | err("%s: Invalid HPC controller handle!\n", __FUNCTION__); | ||
| 1162 | return -1; | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | if (slot->hp_slot >= php_ctlr->num_slots) { | ||
| 1166 | err("%s: Invalid HPC slot number!\n", __FUNCTION__); | ||
| 1167 | return -1; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status); | ||
| 1171 | |||
| 1172 | if (retval) { | 1016 | if (retval) { |
| 1173 | err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); | 1017 | err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__); |
| 1174 | return retval; | 1018 | return retval; |
| 1175 | } | 1019 | } |
| 1176 | 1020 | ||
| @@ -1218,6 +1062,8 @@ static struct hpc_ops pciehp_hpc_ops = { | |||
| 1218 | .get_attention_status = hpc_get_attention_status, | 1062 | .get_attention_status = hpc_get_attention_status, |
| 1219 | .get_latch_status = hpc_get_latch_status, | 1063 | .get_latch_status = hpc_get_latch_status, |
| 1220 | .get_adapter_status = hpc_get_adapter_status, | 1064 | .get_adapter_status = hpc_get_adapter_status, |
| 1065 | .get_emi_status = hpc_get_emi_status, | ||
| 1066 | .toggle_emi = hpc_toggle_emi, | ||
| 1221 | 1067 | ||
| 1222 | .get_max_bus_speed = hpc_get_max_lnk_speed, | 1068 | .get_max_bus_speed = hpc_get_max_lnk_speed, |
| 1223 | .get_cur_bus_speed = hpc_get_cur_lnk_speed, | 1069 | .get_cur_bus_speed = hpc_get_cur_lnk_speed, |
| @@ -1305,38 +1151,24 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) | |||
| 1305 | 1151 | ||
| 1306 | int pcie_init(struct controller * ctrl, struct pcie_device *dev) | 1152 | int pcie_init(struct controller * ctrl, struct pcie_device *dev) |
| 1307 | { | 1153 | { |
| 1308 | struct php_ctlr_state_s *php_ctlr, *p; | ||
| 1309 | void *instance_id = ctrl; | ||
| 1310 | int rc; | 1154 | int rc; |
| 1311 | static int first = 1; | 1155 | static int first = 1; |
| 1312 | u16 temp_word; | 1156 | u16 temp_word; |
| 1313 | u16 cap_reg; | 1157 | u16 cap_reg; |
| 1314 | u16 intr_enable = 0; | 1158 | u16 intr_enable = 0; |
| 1315 | u32 slot_cap; | 1159 | u32 slot_cap; |
| 1316 | int cap_base, saved_cap_base; | 1160 | int cap_base; |
| 1317 | u16 slot_status, slot_ctrl; | 1161 | u16 slot_status, slot_ctrl; |
| 1318 | struct pci_dev *pdev; | 1162 | struct pci_dev *pdev; |
| 1319 | 1163 | ||
| 1320 | DBG_ENTER_ROUTINE | 1164 | DBG_ENTER_ROUTINE |
| 1321 | 1165 | ||
| 1322 | spin_lock_init(&list_lock); | ||
| 1323 | php_ctlr = kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); | ||
| 1324 | |||
| 1325 | if (!php_ctlr) { /* allocate controller state data */ | ||
| 1326 | err("%s: HPC controller memory allocation error!\n", __FUNCTION__); | ||
| 1327 | goto abort; | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s)); | ||
| 1331 | |||
| 1332 | pdev = dev->port; | 1166 | pdev = dev->port; |
| 1333 | php_ctlr->pci_dev = pdev; /* save pci_dev in context */ | 1167 | ctrl->pci_dev = pdev; /* save pci_dev in context */ |
| 1334 | 1168 | ||
| 1335 | dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n", | 1169 | dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n", |
| 1336 | __FUNCTION__, pdev->vendor, pdev->device); | 1170 | __FUNCTION__, pdev->vendor, pdev->device); |
| 1337 | 1171 | ||
| 1338 | saved_cap_base = pcie_cap_base; | ||
| 1339 | |||
| 1340 | if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) { | 1172 | if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) { |
| 1341 | dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__); | 1173 | dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__); |
| 1342 | goto abort_free_ctlr; | 1174 | goto abort_free_ctlr; |
| @@ -1344,14 +1176,15 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
| 1344 | 1176 | ||
| 1345 | ctrl->cap_base = cap_base; | 1177 | ctrl->cap_base = cap_base; |
| 1346 | 1178 | ||
| 1347 | dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base); | 1179 | dbg("%s: pcie_cap_base %x\n", __FUNCTION__, cap_base); |
| 1348 | 1180 | ||
| 1349 | rc = hp_register_read_word(pdev, CAP_REG(ctrl->cap_base), cap_reg); | 1181 | rc = pciehp_readw(ctrl, CAPREG, &cap_reg); |
| 1350 | if (rc) { | 1182 | if (rc) { |
| 1351 | err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__); | 1183 | err("%s: Cannot read CAPREG register\n", __FUNCTION__); |
| 1352 | goto abort_free_ctlr; | 1184 | goto abort_free_ctlr; |
| 1353 | } | 1185 | } |
| 1354 | dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG(ctrl->cap_base), cap_reg); | 1186 | dbg("%s: CAPREG offset %x cap_reg %x\n", |
| 1187 | __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg); | ||
| 1355 | 1188 | ||
| 1356 | if (((cap_reg & SLOT_IMPL) == 0) || (((cap_reg & DEV_PORT_TYPE) != 0x0040) | 1189 | if (((cap_reg & SLOT_IMPL) == 0) || (((cap_reg & DEV_PORT_TYPE) != 0x0040) |
| 1357 | && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) { | 1190 | && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) { |
| @@ -1359,31 +1192,34 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
| 1359 | goto abort_free_ctlr; | 1192 | goto abort_free_ctlr; |
| 1360 | } | 1193 | } |
| 1361 | 1194 | ||
| 1362 | rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap); | 1195 | rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap); |
| 1363 | if (rc) { | 1196 | if (rc) { |
| 1364 | err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__); | 1197 | err("%s: Cannot read SLOTCAP register\n", __FUNCTION__); |
| 1365 | goto abort_free_ctlr; | 1198 | goto abort_free_ctlr; |
| 1366 | } | 1199 | } |
| 1367 | dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP(ctrl->cap_base), slot_cap); | 1200 | dbg("%s: SLOTCAP offset %x slot_cap %x\n", |
| 1201 | __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap); | ||
| 1368 | 1202 | ||
| 1369 | if (!(slot_cap & HP_CAP)) { | 1203 | if (!(slot_cap & HP_CAP)) { |
| 1370 | dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__); | 1204 | dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__); |
| 1371 | goto abort_free_ctlr; | 1205 | goto abort_free_ctlr; |
| 1372 | } | 1206 | } |
| 1373 | /* For debugging purpose */ | 1207 | /* For debugging purpose */ |
| 1374 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 1208 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
| 1375 | if (rc) { | 1209 | if (rc) { |
| 1376 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 1210 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); |
| 1377 | goto abort_free_ctlr; | 1211 | goto abort_free_ctlr; |
| 1378 | } | 1212 | } |
| 1379 | dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), slot_status); | 1213 | dbg("%s: SLOTSTATUS offset %x slot_status %x\n", |
| 1214 | __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status); | ||
| 1380 | 1215 | ||
| 1381 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), slot_ctrl); | 1216 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); |
| 1382 | if (rc) { | 1217 | if (rc) { |
| 1383 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 1218 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
| 1384 | goto abort_free_ctlr; | 1219 | goto abort_free_ctlr; |
| 1385 | } | 1220 | } |
| 1386 | dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), slot_ctrl); | 1221 | dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n", |
| 1222 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); | ||
| 1387 | 1223 | ||
| 1388 | if (first) { | 1224 | if (first) { |
| 1389 | spin_lock_init(&hpc_event_lock); | 1225 | spin_lock_init(&hpc_event_lock); |
| @@ -1405,69 +1241,64 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
| 1405 | /* setup wait queue */ | 1241 | /* setup wait queue */ |
| 1406 | init_waitqueue_head(&ctrl->queue); | 1242 | init_waitqueue_head(&ctrl->queue); |
| 1407 | 1243 | ||
| 1408 | /* find the IRQ */ | ||
| 1409 | php_ctlr->irq = dev->irq; | ||
| 1410 | |||
| 1411 | /* Save interrupt callback info */ | ||
| 1412 | php_ctlr->attention_button_callback = pciehp_handle_attention_button; | ||
| 1413 | php_ctlr->switch_change_callback = pciehp_handle_switch_change; | ||
| 1414 | php_ctlr->presence_change_callback = pciehp_handle_presence_change; | ||
| 1415 | php_ctlr->power_fault_callback = pciehp_handle_power_fault; | ||
| 1416 | php_ctlr->callback_instance_id = instance_id; | ||
| 1417 | |||
| 1418 | /* return PCI Controller Info */ | 1244 | /* return PCI Controller Info */ |
| 1419 | php_ctlr->slot_device_offset = 0; | 1245 | ctrl->slot_device_offset = 0; |
| 1420 | php_ctlr->num_slots = 1; | 1246 | ctrl->num_slots = 1; |
| 1247 | ctrl->first_slot = slot_cap >> 19; | ||
| 1248 | ctrl->ctrlcap = slot_cap & 0x0000007f; | ||
| 1421 | 1249 | ||
| 1422 | /* Mask Hot-plug Interrupt Enable */ | 1250 | /* Mask Hot-plug Interrupt Enable */ |
| 1423 | rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); | 1251 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); |
| 1424 | if (rc) { | 1252 | if (rc) { |
| 1425 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 1253 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
| 1426 | goto abort_free_ctlr; | 1254 | goto abort_free_ctlr; |
| 1427 | } | 1255 | } |
| 1428 | 1256 | ||
| 1429 | dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word); | 1257 | dbg("%s: SLOTCTRL %x value read %x\n", |
| 1258 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word); | ||
| 1430 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; | 1259 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; |
| 1431 | 1260 | ||
| 1432 | rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); | 1261 | rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); |
| 1433 | if (rc) { | 1262 | if (rc) { |
| 1434 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 1263 | err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); |
| 1435 | goto abort_free_ctlr; | 1264 | goto abort_free_ctlr; |
| 1436 | } | 1265 | } |
| 1437 | 1266 | ||
| 1438 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 1267 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
| 1439 | if (rc) { | 1268 | if (rc) { |
| 1440 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 1269 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); |
| 1441 | goto abort_free_ctlr; | 1270 | goto abort_free_ctlr; |
| 1442 | } | 1271 | } |
| 1443 | 1272 | ||
| 1444 | temp_word = 0x1F; /* Clear all events */ | 1273 | temp_word = 0x1F; /* Clear all events */ |
| 1445 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); | 1274 | rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); |
| 1446 | if (rc) { | 1275 | if (rc) { |
| 1447 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 1276 | err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); |
| 1448 | goto abort_free_ctlr; | 1277 | goto abort_free_ctlr; |
| 1449 | } | 1278 | } |
| 1450 | 1279 | ||
| 1451 | if (pciehp_poll_mode) {/* Install interrupt polling code */ | 1280 | if (pciehp_poll_mode) { |
| 1452 | /* Install and start the interrupt polling timer */ | 1281 | /* Install interrupt polling timer. Start with 10 sec delay */ |
| 1453 | init_timer(&php_ctlr->int_poll_timer); | 1282 | init_timer(&ctrl->poll_timer); |
| 1454 | start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ | 1283 | start_int_poll_timer(ctrl, 10); |
| 1455 | } else { | 1284 | } else { |
| 1456 | /* Installs the interrupt handler */ | 1285 | /* Installs the interrupt handler */ |
| 1457 | rc = request_irq(php_ctlr->irq, pcie_isr, IRQF_SHARED, MY_NAME, (void *) ctrl); | 1286 | rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED, |
| 1458 | dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); | 1287 | MY_NAME, (void *)ctrl); |
| 1288 | dbg("%s: request_irq %d for hpc%d (returns %d)\n", | ||
| 1289 | __FUNCTION__, ctrl->pci_dev->irq, ctlr_seq_num, rc); | ||
| 1459 | if (rc) { | 1290 | if (rc) { |
| 1460 | err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq); | 1291 | err("Can't get irq %d for the hotplug controller\n", |
| 1292 | ctrl->pci_dev->irq); | ||
| 1461 | goto abort_free_ctlr; | 1293 | goto abort_free_ctlr; |
| 1462 | } | 1294 | } |
| 1463 | } | 1295 | } |
| 1464 | |||
| 1465 | dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, | 1296 | dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, |
| 1466 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); | 1297 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); |
| 1467 | 1298 | ||
| 1468 | rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); | 1299 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); |
| 1469 | if (rc) { | 1300 | if (rc) { |
| 1470 | err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); | 1301 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
| 1471 | goto abort_free_irq; | 1302 | goto abort_free_irq; |
| 1472 | } | 1303 | } |
| 1473 | 1304 | ||
| @@ -1491,21 +1322,21 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
| 1491 | } | 1322 | } |
| 1492 | 1323 | ||
| 1493 | /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */ | 1324 | /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */ |
| 1494 | rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); | 1325 | rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); |
| 1495 | if (rc) { | 1326 | if (rc) { |
| 1496 | err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); | 1327 | err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); |
| 1497 | goto abort_free_irq; | 1328 | goto abort_free_irq; |
| 1498 | } | 1329 | } |
| 1499 | rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); | 1330 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
| 1500 | if (rc) { | 1331 | if (rc) { |
| 1501 | err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); | 1332 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); |
| 1502 | goto abort_disable_intr; | 1333 | goto abort_disable_intr; |
| 1503 | } | 1334 | } |
| 1504 | 1335 | ||
| 1505 | temp_word = 0x1F; /* Clear all events */ | 1336 | temp_word = 0x1F; /* Clear all events */ |
| 1506 | rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); | 1337 | rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); |
| 1507 | if (rc) { | 1338 | if (rc) { |
| 1508 | err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); | 1339 | err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); |
| 1509 | goto abort_disable_intr; | 1340 | goto abort_disable_intr; |
| 1510 | } | 1341 | } |
| 1511 | 1342 | ||
| @@ -1518,24 +1349,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
| 1518 | goto abort_disable_intr; | 1349 | goto abort_disable_intr; |
| 1519 | } | 1350 | } |
| 1520 | 1351 | ||
| 1521 | /* Add this HPC instance into the HPC list */ | ||
| 1522 | spin_lock(&list_lock); | ||
| 1523 | if (php_ctlr_list_head == 0) { | ||
| 1524 | php_ctlr_list_head = php_ctlr; | ||
| 1525 | p = php_ctlr_list_head; | ||
| 1526 | p->pnext = NULL; | ||
| 1527 | } else { | ||
| 1528 | p = php_ctlr_list_head; | ||
| 1529 | |||
| 1530 | while (p->pnext) | ||
| 1531 | p = p->pnext; | ||
| 1532 | |||
| 1533 | p->pnext = php_ctlr; | ||
| 1534 | } | ||
| 1535 | spin_unlock(&list_lock); | ||
| 1536 | |||
| 1537 | ctlr_seq_num++; | 1352 | ctlr_seq_num++; |
| 1538 | ctrl->hpc_ctlr_handle = php_ctlr; | ||
| 1539 | ctrl->hpc_ops = &pciehp_hpc_ops; | 1353 | ctrl->hpc_ops = &pciehp_hpc_ops; |
| 1540 | 1354 | ||
| 1541 | DBG_LEAVE_ROUTINE | 1355 | DBG_LEAVE_ROUTINE |
| @@ -1543,24 +1357,21 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
| 1543 | 1357 | ||
| 1544 | /* We end up here for the many possible ways to fail this API. */ | 1358 | /* We end up here for the many possible ways to fail this API. */ |
| 1545 | abort_disable_intr: | 1359 | abort_disable_intr: |
| 1546 | rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); | 1360 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); |
| 1547 | if (!rc) { | 1361 | if (!rc) { |
| 1548 | temp_word &= ~(intr_enable | HP_INTR_ENABLE); | 1362 | temp_word &= ~(intr_enable | HP_INTR_ENABLE); |
| 1549 | rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); | 1363 | rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); |
| 1550 | } | 1364 | } |
| 1551 | if (rc) | 1365 | if (rc) |
| 1552 | err("%s : disabling interrupts failed\n", __FUNCTION__); | 1366 | err("%s : disabling interrupts failed\n", __FUNCTION__); |
| 1553 | 1367 | ||
| 1554 | abort_free_irq: | 1368 | abort_free_irq: |
| 1555 | if (pciehp_poll_mode) | 1369 | if (pciehp_poll_mode) |
| 1556 | del_timer_sync(&php_ctlr->int_poll_timer); | 1370 | del_timer_sync(&ctrl->poll_timer); |
| 1557 | else | 1371 | else |
| 1558 | free_irq(php_ctlr->irq, ctrl); | 1372 | free_irq(ctrl->pci_dev->irq, ctrl); |
| 1559 | 1373 | ||
| 1560 | abort_free_ctlr: | 1374 | abort_free_ctlr: |
| 1561 | pcie_cap_base = saved_cap_base; | ||
| 1562 | kfree(php_ctlr); | ||
| 1563 | abort: | ||
| 1564 | DBG_LEAVE_ROUTINE | 1375 | DBG_LEAVE_ROUTINE |
| 1565 | return -1; | 1376 | return -1; |
| 1566 | } | 1377 | } |
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 3ca6a4f574b3..01d31a1f697c 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
| @@ -106,7 +106,7 @@ struct controller { | |||
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | /* Define AMD SHPC ID */ | 108 | /* Define AMD SHPC ID */ |
| 109 | #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 | 109 | #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 |
| 110 | #define PCI_DEVICE_ID_AMD_POGO_7458 0x7458 | 110 | #define PCI_DEVICE_ID_AMD_POGO_7458 0x7458 |
| 111 | 111 | ||
| 112 | /* AMD PCIX bridge registers */ | 112 | /* AMD PCIX bridge registers */ |
| @@ -221,7 +221,7 @@ enum ctrl_offsets { | |||
| 221 | }; | 221 | }; |
| 222 | 222 | ||
| 223 | static inline struct slot *get_slot(struct hotplug_slot *hotplug_slot) | 223 | static inline struct slot *get_slot(struct hotplug_slot *hotplug_slot) |
| 224 | { | 224 | { |
| 225 | return hotplug_slot->private; | 225 | return hotplug_slot->private; |
| 226 | } | 226 | } |
| 227 | 227 | ||
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 590cd3cbe010..5f4bc08a633a 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
| @@ -401,10 +401,6 @@ static int __init shpcd_init(void) | |||
| 401 | { | 401 | { |
| 402 | int retval = 0; | 402 | int retval = 0; |
| 403 | 403 | ||
| 404 | #ifdef CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE | ||
| 405 | shpchp_poll_mode = 1; | ||
| 406 | #endif | ||
| 407 | |||
| 408 | retval = pci_register_driver(&shpc_driver); | 404 | retval = pci_register_driver(&shpc_driver); |
| 409 | dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval); | 405 | dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval); |
| 410 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 406 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 6bb84734cd6c..b746bd265bc6 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
| @@ -64,7 +64,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl) | |||
| 64 | 64 | ||
| 65 | /* Attention Button Change */ | 65 | /* Attention Button Change */ |
| 66 | dbg("shpchp: Attention button interrupt received.\n"); | 66 | dbg("shpchp: Attention button interrupt received.\n"); |
| 67 | 67 | ||
| 68 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 68 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 69 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); | 69 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
| 70 | 70 | ||
| @@ -128,7 +128,7 @@ u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl) | |||
| 128 | 128 | ||
| 129 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 129 | p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
| 130 | 130 | ||
| 131 | /* | 131 | /* |
| 132 | * Save the presence state | 132 | * Save the presence state |
| 133 | */ | 133 | */ |
| 134 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); | 134 | p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); |
| @@ -184,12 +184,12 @@ u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl) | |||
| 184 | return 1; | 184 | return 1; |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | /* The following routines constitute the bulk of the | 187 | /* The following routines constitute the bulk of the |
| 188 | hotplug controller logic | 188 | hotplug controller logic |
| 189 | */ | 189 | */ |
| 190 | static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, | 190 | static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, |
| 191 | enum pci_bus_speed speed) | 191 | enum pci_bus_speed speed) |
| 192 | { | 192 | { |
| 193 | int rc = 0; | 193 | int rc = 0; |
| 194 | 194 | ||
| 195 | dbg("%s: change to speed %d\n", __FUNCTION__, speed); | 195 | dbg("%s: change to speed %d\n", __FUNCTION__, speed); |
| @@ -204,7 +204,7 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, | |||
| 204 | static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, | 204 | static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, |
| 205 | u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp, | 205 | u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp, |
| 206 | enum pci_bus_speed msp) | 206 | enum pci_bus_speed msp) |
| 207 | { | 207 | { |
| 208 | int rc = 0; | 208 | int rc = 0; |
| 209 | 209 | ||
| 210 | /* | 210 | /* |
| @@ -257,23 +257,23 @@ static int board_added(struct slot *p_slot) | |||
| 257 | err("%s: Failed to power on slot\n", __FUNCTION__); | 257 | err("%s: Failed to power on slot\n", __FUNCTION__); |
| 258 | return -1; | 258 | return -1; |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { | 261 | if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { |
| 262 | if (slots_not_empty) | 262 | if (slots_not_empty) |
| 263 | return WRONG_BUS_FREQUENCY; | 263 | return WRONG_BUS_FREQUENCY; |
| 264 | 264 | ||
| 265 | if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { | 265 | if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { |
| 266 | err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); | 266 | err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); |
| 267 | return WRONG_BUS_FREQUENCY; | 267 | return WRONG_BUS_FREQUENCY; |
| 268 | } | 268 | } |
| 269 | 269 | ||
| 270 | /* turn on board, blink green LED, turn off Amber LED */ | 270 | /* turn on board, blink green LED, turn off Amber LED */ |
| 271 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { | 271 | if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { |
| 272 | err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); | 272 | err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); |
| 273 | return rc; | 273 | return rc; |
| 274 | } | 274 | } |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); | 277 | rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); |
| 278 | if (rc) { | 278 | if (rc) { |
| 279 | err("%s: Can't get adapter speed or bus mode mismatch\n", | 279 | err("%s: Can't get adapter speed or bus mode mismatch\n", |
| @@ -378,7 +378,7 @@ static int remove_board(struct slot *p_slot) | |||
| 378 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); | 378 | err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); |
| 379 | return rc; | 379 | return rc; |
| 380 | } | 380 | } |
| 381 | 381 | ||
| 382 | rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); | 382 | rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); |
| 383 | if (rc) { | 383 | if (rc) { |
| 384 | err("%s: Issue of Set Attention command failed\n", __FUNCTION__); | 384 | err("%s: Issue of Set Attention command failed\n", __FUNCTION__); |
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index b7bede4b7c27..5183a45d45b5 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
| @@ -35,38 +35,6 @@ | |||
| 35 | 35 | ||
| 36 | #include "shpchp.h" | 36 | #include "shpchp.h" |
| 37 | 37 | ||
| 38 | #ifdef DEBUG | ||
| 39 | #define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ | ||
| 40 | #define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ | ||
| 41 | #define DBG_K_INFO ((unsigned int)0x00000004) /* Info messages */ | ||
| 42 | #define DBG_K_ERROR ((unsigned int)0x00000008) /* Error messages */ | ||
| 43 | #define DBG_K_TRACE (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT) | ||
| 44 | #define DBG_K_STANDARD (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE) | ||
| 45 | /* Redefine this flagword to set debug level */ | ||
| 46 | #define DEBUG_LEVEL DBG_K_STANDARD | ||
| 47 | |||
| 48 | #define DEFINE_DBG_BUFFER char __dbg_str_buf[256]; | ||
| 49 | |||
| 50 | #define DBG_PRINT( dbg_flags, args... ) \ | ||
| 51 | do { \ | ||
| 52 | if ( DEBUG_LEVEL & ( dbg_flags ) ) \ | ||
| 53 | { \ | ||
| 54 | int len; \ | ||
| 55 | len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \ | ||
| 56 | __FILE__, __LINE__, __FUNCTION__ ); \ | ||
| 57 | sprintf( __dbg_str_buf + len, args ); \ | ||
| 58 | printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \ | ||
| 59 | } \ | ||
| 60 | } while (0) | ||
| 61 | |||
| 62 | #define DBG_ENTER_ROUTINE DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]"); | ||
| 63 | #define DBG_LEAVE_ROUTINE DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]"); | ||
| 64 | #else | ||
| 65 | #define DEFINE_DBG_BUFFER | ||
| 66 | #define DBG_ENTER_ROUTINE | ||
| 67 | #define DBG_LEAVE_ROUTINE | ||
| 68 | #endif /* DEBUG */ | ||
| 69 | |||
| 70 | /* Slot Available Register I field definition */ | 38 | /* Slot Available Register I field definition */ |
| 71 | #define SLOT_33MHZ 0x0000001f | 39 | #define SLOT_33MHZ 0x0000001f |
| 72 | #define SLOT_66MHZ_PCIX 0x00001f00 | 40 | #define SLOT_66MHZ_PCIX 0x00001f00 |
| @@ -211,7 +179,6 @@ | |||
| 211 | #define SLOT_EVENT_LATCH 0x2 | 179 | #define SLOT_EVENT_LATCH 0x2 |
| 212 | #define SLOT_SERR_INT_MASK 0x3 | 180 | #define SLOT_SERR_INT_MASK 0x3 |
| 213 | 181 | ||
| 214 | DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ | ||
| 215 | static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); | 182 | static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); |
| 216 | 183 | ||
| 217 | static irqreturn_t shpc_isr(int irq, void *dev_id); | 184 | static irqreturn_t shpc_isr(int irq, void *dev_id); |
| @@ -268,8 +235,6 @@ static void int_poll_timeout(unsigned long data) | |||
| 268 | { | 235 | { |
| 269 | struct controller *ctrl = (struct controller *)data; | 236 | struct controller *ctrl = (struct controller *)data; |
| 270 | 237 | ||
| 271 | DBG_ENTER_ROUTINE | ||
| 272 | |||
| 273 | /* Poll for interrupt events. regs == NULL => polling */ | 238 | /* Poll for interrupt events. regs == NULL => polling */ |
| 274 | shpc_isr(0, ctrl); | 239 | shpc_isr(0, ctrl); |
| 275 | 240 | ||
| @@ -278,8 +243,6 @@ static void int_poll_timeout(unsigned long data) | |||
| 278 | shpchp_poll_time = 2; /* default polling interval is 2 sec */ | 243 | shpchp_poll_time = 2; /* default polling interval is 2 sec */ |
| 279 | 244 | ||
| 280 | start_int_poll_timer(ctrl, shpchp_poll_time); | 245 | start_int_poll_timer(ctrl, shpchp_poll_time); |
| 281 | |||
| 282 | DBG_LEAVE_ROUTINE | ||
| 283 | } | 246 | } |
| 284 | 247 | ||
| 285 | /* | 248 | /* |
| @@ -353,8 +316,6 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
| 353 | int retval = 0; | 316 | int retval = 0; |
| 354 | u16 temp_word; | 317 | u16 temp_word; |
| 355 | 318 | ||
| 356 | DBG_ENTER_ROUTINE | ||
| 357 | |||
| 358 | mutex_lock(&slot->ctrl->cmd_lock); | 319 | mutex_lock(&slot->ctrl->cmd_lock); |
| 359 | 320 | ||
| 360 | if (!shpc_poll_ctrl_busy(ctrl)) { | 321 | if (!shpc_poll_ctrl_busy(ctrl)) { |
| @@ -368,9 +329,9 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
| 368 | ++t_slot; | 329 | ++t_slot; |
| 369 | temp_word = (t_slot << 8) | (cmd & 0xFF); | 330 | temp_word = (t_slot << 8) | (cmd & 0xFF); |
| 370 | dbg("%s: t_slot %x cmd %x\n", __FUNCTION__, t_slot, cmd); | 331 | dbg("%s: t_slot %x cmd %x\n", __FUNCTION__, t_slot, cmd); |
| 371 | 332 | ||
| 372 | /* To make sure the Controller Busy bit is 0 before we send out the | 333 | /* To make sure the Controller Busy bit is 0 before we send out the |
| 373 | * command. | 334 | * command. |
| 374 | */ | 335 | */ |
| 375 | shpc_writew(ctrl, CMD, temp_word); | 336 | shpc_writew(ctrl, CMD, temp_word); |
| 376 | 337 | ||
| @@ -389,20 +350,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
| 389 | } | 350 | } |
| 390 | out: | 351 | out: |
| 391 | mutex_unlock(&slot->ctrl->cmd_lock); | 352 | mutex_unlock(&slot->ctrl->cmd_lock); |
| 392 | |||
| 393 | DBG_LEAVE_ROUTINE | ||
| 394 | return retval; | 353 | return retval; |
| 395 | } | 354 | } |
| 396 | 355 | ||
| 397 | static int hpc_check_cmd_status(struct controller *ctrl) | 356 | static int hpc_check_cmd_status(struct controller *ctrl) |
| 398 | { | 357 | { |
| 399 | u16 cmd_status; | ||
| 400 | int retval = 0; | 358 | int retval = 0; |
| 359 | u16 cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; | ||
| 401 | 360 | ||
| 402 | DBG_ENTER_ROUTINE | ||
| 403 | |||
| 404 | cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; | ||
| 405 | |||
| 406 | switch (cmd_status >> 1) { | 361 | switch (cmd_status >> 1) { |
| 407 | case 0: | 362 | case 0: |
| 408 | retval = 0; | 363 | retval = 0; |
| @@ -423,7 +378,6 @@ static int hpc_check_cmd_status(struct controller *ctrl) | |||
| 423 | retval = cmd_status; | 378 | retval = cmd_status; |
| 424 | } | 379 | } |
| 425 | 380 | ||
| 426 | DBG_LEAVE_ROUTINE | ||
| 427 | return retval; | 381 | return retval; |
| 428 | } | 382 | } |
| 429 | 383 | ||
| @@ -431,13 +385,8 @@ static int hpc_check_cmd_status(struct controller *ctrl) | |||
| 431 | static int hpc_get_attention_status(struct slot *slot, u8 *status) | 385 | static int hpc_get_attention_status(struct slot *slot, u8 *status) |
| 432 | { | 386 | { |
| 433 | struct controller *ctrl = slot->ctrl; | 387 | struct controller *ctrl = slot->ctrl; |
| 434 | u32 slot_reg; | 388 | u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); |
| 435 | u8 state; | 389 | u8 state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; |
| 436 | |||
| 437 | DBG_ENTER_ROUTINE | ||
| 438 | |||
| 439 | slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); | ||
| 440 | state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; | ||
| 441 | 390 | ||
| 442 | switch (state) { | 391 | switch (state) { |
| 443 | case ATN_LED_STATE_ON: | 392 | case ATN_LED_STATE_ON: |
| @@ -454,20 +403,14 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) | |||
| 454 | break; | 403 | break; |
| 455 | } | 404 | } |
| 456 | 405 | ||
| 457 | DBG_LEAVE_ROUTINE | ||
| 458 | return 0; | 406 | return 0; |
| 459 | } | 407 | } |
| 460 | 408 | ||
| 461 | static int hpc_get_power_status(struct slot * slot, u8 *status) | 409 | static int hpc_get_power_status(struct slot * slot, u8 *status) |
| 462 | { | 410 | { |
| 463 | struct controller *ctrl = slot->ctrl; | 411 | struct controller *ctrl = slot->ctrl; |
| 464 | u32 slot_reg; | 412 | u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); |
| 465 | u8 state; | 413 | u8 state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; |
| 466 | |||
| 467 | DBG_ENTER_ROUTINE | ||
| 468 | |||
| 469 | slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); | ||
| 470 | state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; | ||
| 471 | 414 | ||
| 472 | switch (state) { | 415 | switch (state) { |
| 473 | case SLOT_STATE_PWRONLY: | 416 | case SLOT_STATE_PWRONLY: |
| @@ -484,7 +427,6 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) | |||
| 484 | break; | 427 | break; |
| 485 | } | 428 | } |
| 486 | 429 | ||
| 487 | DBG_LEAVE_ROUTINE | ||
| 488 | return 0; | 430 | return 0; |
| 489 | } | 431 | } |
| 490 | 432 | ||
| @@ -492,30 +434,21 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) | |||
| 492 | static int hpc_get_latch_status(struct slot *slot, u8 *status) | 434 | static int hpc_get_latch_status(struct slot *slot, u8 *status) |
| 493 | { | 435 | { |
| 494 | struct controller *ctrl = slot->ctrl; | 436 | struct controller *ctrl = slot->ctrl; |
| 495 | u32 slot_reg; | 437 | u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); |
| 496 | |||
| 497 | DBG_ENTER_ROUTINE | ||
| 498 | 438 | ||
| 499 | slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); | ||
| 500 | *status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */ | 439 | *status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */ |
| 501 | 440 | ||
| 502 | DBG_LEAVE_ROUTINE | ||
| 503 | return 0; | 441 | return 0; |
| 504 | } | 442 | } |
| 505 | 443 | ||
| 506 | static int hpc_get_adapter_status(struct slot *slot, u8 *status) | 444 | static int hpc_get_adapter_status(struct slot *slot, u8 *status) |
| 507 | { | 445 | { |
| 508 | struct controller *ctrl = slot->ctrl; | 446 | struct controller *ctrl = slot->ctrl; |
| 509 | u32 slot_reg; | 447 | u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); |
| 510 | u8 state; | 448 | u8 state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; |
| 511 | |||
| 512 | DBG_ENTER_ROUTINE | ||
| 513 | 449 | ||
| 514 | slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); | ||
| 515 | state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; | ||
| 516 | *status = (state != 0x3) ? 1 : 0; | 450 | *status = (state != 0x3) ? 1 : 0; |
| 517 | 451 | ||
| 518 | DBG_LEAVE_ROUTINE | ||
| 519 | return 0; | 452 | return 0; |
| 520 | } | 453 | } |
| 521 | 454 | ||
| @@ -523,11 +456,8 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) | |||
| 523 | { | 456 | { |
| 524 | struct controller *ctrl = slot->ctrl; | 457 | struct controller *ctrl = slot->ctrl; |
| 525 | 458 | ||
| 526 | DBG_ENTER_ROUTINE | ||
| 527 | |||
| 528 | *prog_int = shpc_readb(ctrl, PROG_INTERFACE); | 459 | *prog_int = shpc_readb(ctrl, PROG_INTERFACE); |
| 529 | 460 | ||
| 530 | DBG_LEAVE_ROUTINE | ||
| 531 | return 0; | 461 | return 0; |
| 532 | } | 462 | } |
| 533 | 463 | ||
| @@ -539,8 +469,6 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) | |||
| 539 | u8 m66_cap = !!(slot_reg & MHZ66_CAP); | 469 | u8 m66_cap = !!(slot_reg & MHZ66_CAP); |
| 540 | u8 pi, pcix_cap; | 470 | u8 pi, pcix_cap; |
| 541 | 471 | ||
| 542 | DBG_ENTER_ROUTINE | ||
| 543 | |||
| 544 | if ((retval = hpc_get_prog_int(slot, &pi))) | 472 | if ((retval = hpc_get_prog_int(slot, &pi))) |
| 545 | return retval; | 473 | return retval; |
| 546 | 474 | ||
| @@ -582,21 +510,15 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) | |||
| 582 | } | 510 | } |
| 583 | 511 | ||
| 584 | dbg("Adapter speed = %d\n", *value); | 512 | dbg("Adapter speed = %d\n", *value); |
| 585 | DBG_LEAVE_ROUTINE | ||
| 586 | return retval; | 513 | return retval; |
| 587 | } | 514 | } |
| 588 | 515 | ||
| 589 | static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) | 516 | static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) |
| 590 | { | 517 | { |
| 591 | struct controller *ctrl = slot->ctrl; | ||
| 592 | u16 sec_bus_status; | ||
| 593 | u8 pi; | ||
| 594 | int retval = 0; | 518 | int retval = 0; |
| 595 | 519 | struct controller *ctrl = slot->ctrl; | |
| 596 | DBG_ENTER_ROUTINE | 520 | u16 sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); |
| 597 | 521 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); | |
| 598 | pi = shpc_readb(ctrl, PROG_INTERFACE); | ||
| 599 | sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); | ||
| 600 | 522 | ||
| 601 | if (pi == 2) { | 523 | if (pi == 2) { |
| 602 | *mode = (sec_bus_status & 0x0100) >> 8; | 524 | *mode = (sec_bus_status & 0x0100) >> 8; |
| @@ -605,21 +527,14 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) | |||
| 605 | } | 527 | } |
| 606 | 528 | ||
| 607 | dbg("Mode 1 ECC cap = %d\n", *mode); | 529 | dbg("Mode 1 ECC cap = %d\n", *mode); |
| 608 | |||
| 609 | DBG_LEAVE_ROUTINE | ||
| 610 | return retval; | 530 | return retval; |
| 611 | } | 531 | } |
| 612 | 532 | ||
| 613 | static int hpc_query_power_fault(struct slot * slot) | 533 | static int hpc_query_power_fault(struct slot * slot) |
| 614 | { | 534 | { |
| 615 | struct controller *ctrl = slot->ctrl; | 535 | struct controller *ctrl = slot->ctrl; |
| 616 | u32 slot_reg; | 536 | u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); |
| 617 | |||
| 618 | DBG_ENTER_ROUTINE | ||
| 619 | |||
| 620 | slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); | ||
| 621 | 537 | ||
| 622 | DBG_LEAVE_ROUTINE | ||
| 623 | /* Note: Logic 0 => fault */ | 538 | /* Note: Logic 0 => fault */ |
| 624 | return !(slot_reg & POWER_FAULT); | 539 | return !(slot_reg & POWER_FAULT); |
| 625 | } | 540 | } |
| @@ -629,7 +544,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) | |||
| 629 | u8 slot_cmd = 0; | 544 | u8 slot_cmd = 0; |
| 630 | 545 | ||
| 631 | switch (value) { | 546 | switch (value) { |
| 632 | case 0 : | 547 | case 0 : |
| 633 | slot_cmd = SET_ATTN_OFF; /* OFF */ | 548 | slot_cmd = SET_ATTN_OFF; /* OFF */ |
| 634 | break; | 549 | break; |
| 635 | case 1: | 550 | case 1: |
| @@ -666,8 +581,6 @@ static void hpc_release_ctlr(struct controller *ctrl) | |||
| 666 | int i; | 581 | int i; |
| 667 | u32 slot_reg, serr_int; | 582 | u32 slot_reg, serr_int; |
| 668 | 583 | ||
| 669 | DBG_ENTER_ROUTINE | ||
| 670 | |||
| 671 | /* | 584 | /* |
| 672 | * Mask event interrupts and SERRs of all slots | 585 | * Mask event interrupts and SERRs of all slots |
| 673 | */ | 586 | */ |
| @@ -708,61 +621,43 @@ static void hpc_release_ctlr(struct controller *ctrl) | |||
| 708 | */ | 621 | */ |
| 709 | if (atomic_dec_and_test(&shpchp_num_controllers)) | 622 | if (atomic_dec_and_test(&shpchp_num_controllers)) |
| 710 | destroy_workqueue(shpchp_wq); | 623 | destroy_workqueue(shpchp_wq); |
| 711 | |||
| 712 | DBG_LEAVE_ROUTINE | ||
| 713 | } | 624 | } |
| 714 | 625 | ||
| 715 | static int hpc_power_on_slot(struct slot * slot) | 626 | static int hpc_power_on_slot(struct slot * slot) |
| 716 | { | 627 | { |
| 717 | int retval; | 628 | int retval; |
| 718 | 629 | ||
| 719 | DBG_ENTER_ROUTINE | ||
| 720 | |||
| 721 | retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR); | 630 | retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR); |
| 722 | if (retval) { | 631 | if (retval) |
| 723 | err("%s: Write command failed!\n", __FUNCTION__); | 632 | err("%s: Write command failed!\n", __FUNCTION__); |
| 724 | return retval; | ||
| 725 | } | ||
| 726 | |||
| 727 | DBG_LEAVE_ROUTINE | ||
| 728 | 633 | ||
| 729 | return 0; | 634 | return retval; |
| 730 | } | 635 | } |
| 731 | 636 | ||
| 732 | static int hpc_slot_enable(struct slot * slot) | 637 | static int hpc_slot_enable(struct slot * slot) |
| 733 | { | 638 | { |
| 734 | int retval; | 639 | int retval; |
| 735 | 640 | ||
| 736 | DBG_ENTER_ROUTINE | ||
| 737 | |||
| 738 | /* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ | 641 | /* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ |
| 739 | retval = shpc_write_cmd(slot, slot->hp_slot, | 642 | retval = shpc_write_cmd(slot, slot->hp_slot, |
| 740 | SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF); | 643 | SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF); |
| 741 | if (retval) { | 644 | if (retval) |
| 742 | err("%s: Write command failed!\n", __FUNCTION__); | 645 | err("%s: Write command failed!\n", __FUNCTION__); |
| 743 | return retval; | ||
| 744 | } | ||
| 745 | 646 | ||
| 746 | DBG_LEAVE_ROUTINE | 647 | return retval; |
| 747 | return 0; | ||
| 748 | } | 648 | } |
| 749 | 649 | ||
| 750 | static int hpc_slot_disable(struct slot * slot) | 650 | static int hpc_slot_disable(struct slot * slot) |
| 751 | { | 651 | { |
| 752 | int retval; | 652 | int retval; |
| 753 | 653 | ||
| 754 | DBG_ENTER_ROUTINE | ||
| 755 | |||
| 756 | /* Slot - Disable, Power Indicator - Off, Attention Indicator - On */ | 654 | /* Slot - Disable, Power Indicator - Off, Attention Indicator - On */ |
| 757 | retval = shpc_write_cmd(slot, slot->hp_slot, | 655 | retval = shpc_write_cmd(slot, slot->hp_slot, |
| 758 | SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON); | 656 | SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON); |
| 759 | if (retval) { | 657 | if (retval) |
| 760 | err("%s: Write command failed!\n", __FUNCTION__); | 658 | err("%s: Write command failed!\n", __FUNCTION__); |
| 761 | return retval; | ||
| 762 | } | ||
| 763 | 659 | ||
| 764 | DBG_LEAVE_ROUTINE | 660 | return retval; |
| 765 | return 0; | ||
| 766 | } | 661 | } |
| 767 | 662 | ||
| 768 | static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) | 663 | static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) |
| @@ -771,8 +666,6 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) | |||
| 771 | struct controller *ctrl = slot->ctrl; | 666 | struct controller *ctrl = slot->ctrl; |
| 772 | u8 pi, cmd; | 667 | u8 pi, cmd; |
| 773 | 668 | ||
| 774 | DBG_ENTER_ROUTINE | ||
| 775 | |||
| 776 | pi = shpc_readb(ctrl, PROG_INTERFACE); | 669 | pi = shpc_readb(ctrl, PROG_INTERFACE); |
| 777 | if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) | 670 | if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) |
| 778 | return -EINVAL; | 671 | return -EINVAL; |
| @@ -828,7 +721,6 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) | |||
| 828 | if (retval) | 721 | if (retval) |
| 829 | err("%s: Write command failed!\n", __FUNCTION__); | 722 | err("%s: Write command failed!\n", __FUNCTION__); |
| 830 | 723 | ||
| 831 | DBG_LEAVE_ROUTINE | ||
| 832 | return retval; | 724 | return retval; |
| 833 | } | 725 | } |
| 834 | 726 | ||
| @@ -843,7 +735,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) | |||
| 843 | if (!intr_loc) | 735 | if (!intr_loc) |
| 844 | return IRQ_NONE; | 736 | return IRQ_NONE; |
| 845 | 737 | ||
| 846 | dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); | 738 | dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); |
| 847 | 739 | ||
| 848 | if(!shpchp_poll_mode) { | 740 | if(!shpchp_poll_mode) { |
| 849 | /* | 741 | /* |
| @@ -856,12 +748,12 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) | |||
| 856 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); | 748 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); |
| 857 | 749 | ||
| 858 | intr_loc2 = shpc_readl(ctrl, INTR_LOC); | 750 | intr_loc2 = shpc_readl(ctrl, INTR_LOC); |
| 859 | dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); | 751 | dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); |
| 860 | } | 752 | } |
| 861 | 753 | ||
| 862 | if (intr_loc & CMD_INTR_PENDING) { | 754 | if (intr_loc & CMD_INTR_PENDING) { |
| 863 | /* | 755 | /* |
| 864 | * Command Complete Interrupt Pending | 756 | * Command Complete Interrupt Pending |
| 865 | * RO only - clear by writing 1 to the Command Completion | 757 | * RO only - clear by writing 1 to the Command Completion |
| 866 | * Detect bit in Controller SERR-INT register | 758 | * Detect bit in Controller SERR-INT register |
| 867 | */ | 759 | */ |
| @@ -875,7 +767,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) | |||
| 875 | if (!(intr_loc & ~CMD_INTR_PENDING)) | 767 | if (!(intr_loc & ~CMD_INTR_PENDING)) |
| 876 | goto out; | 768 | goto out; |
| 877 | 769 | ||
| 878 | for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { | 770 | for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { |
| 879 | /* To find out which slot has interrupt pending */ | 771 | /* To find out which slot has interrupt pending */ |
| 880 | if (!(intr_loc & SLOT_INTR_PENDING(hp_slot))) | 772 | if (!(intr_loc & SLOT_INTR_PENDING(hp_slot))) |
| 881 | continue; | 773 | continue; |
| @@ -907,7 +799,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) | |||
| 907 | serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); | 799 | serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); |
| 908 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); | 800 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); |
| 909 | } | 801 | } |
| 910 | 802 | ||
| 911 | return IRQ_HANDLED; | 803 | return IRQ_HANDLED; |
| 912 | } | 804 | } |
| 913 | 805 | ||
| @@ -920,8 +812,6 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
| 920 | u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); | 812 | u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); |
| 921 | u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2); | 813 | u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2); |
| 922 | 814 | ||
| 923 | DBG_ENTER_ROUTINE | ||
| 924 | |||
| 925 | if (pi == 2) { | 815 | if (pi == 2) { |
| 926 | if (slot_avail2 & SLOT_133MHZ_PCIX_533) | 816 | if (slot_avail2 & SLOT_133MHZ_PCIX_533) |
| 927 | bus_speed = PCI_SPEED_133MHz_PCIX_533; | 817 | bus_speed = PCI_SPEED_133MHz_PCIX_533; |
| @@ -954,7 +844,7 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
| 954 | 844 | ||
| 955 | *value = bus_speed; | 845 | *value = bus_speed; |
| 956 | dbg("Max bus speed = %d\n", bus_speed); | 846 | dbg("Max bus speed = %d\n", bus_speed); |
| 957 | DBG_LEAVE_ROUTINE | 847 | |
| 958 | return retval; | 848 | return retval; |
| 959 | } | 849 | } |
| 960 | 850 | ||
| @@ -967,8 +857,6 @@ static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
| 967 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); | 857 | u8 pi = shpc_readb(ctrl, PROG_INTERFACE); |
| 968 | u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); | 858 | u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); |
| 969 | 859 | ||
| 970 | DBG_ENTER_ROUTINE | ||
| 971 | |||
| 972 | if ((pi == 1) && (speed_mode > 4)) { | 860 | if ((pi == 1) && (speed_mode > 4)) { |
| 973 | *value = PCI_SPEED_UNKNOWN; | 861 | *value = PCI_SPEED_UNKNOWN; |
| 974 | return -ENODEV; | 862 | return -ENODEV; |
| @@ -1024,7 +912,6 @@ static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
| 1024 | } | 912 | } |
| 1025 | 913 | ||
| 1026 | dbg("Current bus speed = %d\n", bus_speed); | 914 | dbg("Current bus speed = %d\n", bus_speed); |
| 1027 | DBG_LEAVE_ROUTINE | ||
| 1028 | return retval; | 915 | return retval; |
| 1029 | } | 916 | } |
| 1030 | 917 | ||
| @@ -1032,7 +919,7 @@ static struct hpc_ops shpchp_hpc_ops = { | |||
| 1032 | .power_on_slot = hpc_power_on_slot, | 919 | .power_on_slot = hpc_power_on_slot, |
| 1033 | .slot_enable = hpc_slot_enable, | 920 | .slot_enable = hpc_slot_enable, |
| 1034 | .slot_disable = hpc_slot_disable, | 921 | .slot_disable = hpc_slot_disable, |
| 1035 | .set_bus_speed_mode = hpc_set_bus_speed_mode, | 922 | .set_bus_speed_mode = hpc_set_bus_speed_mode, |
| 1036 | .set_attention_status = hpc_set_attention_status, | 923 | .set_attention_status = hpc_set_attention_status, |
| 1037 | .get_power_status = hpc_get_power_status, | 924 | .get_power_status = hpc_get_power_status, |
| 1038 | .get_attention_status = hpc_get_attention_status, | 925 | .get_attention_status = hpc_get_attention_status, |
| @@ -1049,7 +936,7 @@ static struct hpc_ops shpchp_hpc_ops = { | |||
| 1049 | .green_led_on = hpc_set_green_led_on, | 936 | .green_led_on = hpc_set_green_led_on, |
| 1050 | .green_led_off = hpc_set_green_led_off, | 937 | .green_led_off = hpc_set_green_led_off, |
| 1051 | .green_led_blink = hpc_set_green_led_blink, | 938 | .green_led_blink = hpc_set_green_led_blink, |
| 1052 | 939 | ||
| 1053 | .release_ctlr = hpc_release_ctlr, | 940 | .release_ctlr = hpc_release_ctlr, |
| 1054 | }; | 941 | }; |
| 1055 | 942 | ||
| @@ -1061,8 +948,6 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) | |||
| 1061 | u32 tempdword, slot_reg, slot_config; | 948 | u32 tempdword, slot_reg, slot_config; |
| 1062 | u8 i; | 949 | u8 i; |
| 1063 | 950 | ||
| 1064 | DBG_ENTER_ROUTINE | ||
| 1065 | |||
| 1066 | ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ | 951 | ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ |
| 1067 | 952 | ||
| 1068 | if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == | 953 | if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == |
| @@ -1108,9 +993,9 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) | |||
| 1108 | ctrl->mmio_size = 0x24 + 0x4 * num_slots; | 993 | ctrl->mmio_size = 0x24 + 0x4 * num_slots; |
| 1109 | } | 994 | } |
| 1110 | 995 | ||
| 1111 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, | 996 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, |
| 1112 | pdev->subsystem_device); | 997 | pdev->subsystem_device); |
| 1113 | 998 | ||
| 1114 | rc = pci_enable_device(pdev); | 999 | rc = pci_enable_device(pdev); |
| 1115 | if (rc) { | 1000 | if (rc) { |
| 1116 | err("%s: pci_enable_device failed\n", __FUNCTION__); | 1001 | err("%s: pci_enable_device failed\n", __FUNCTION__); |
| @@ -1172,7 +1057,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) | |||
| 1172 | slot_reg &= ~SLOT_REG_RSVDZ_MASK; | 1057 | slot_reg &= ~SLOT_REG_RSVDZ_MASK; |
| 1173 | shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); | 1058 | shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); |
| 1174 | } | 1059 | } |
| 1175 | 1060 | ||
| 1176 | if (shpchp_poll_mode) { | 1061 | if (shpchp_poll_mode) { |
| 1177 | /* Install interrupt polling timer. Start with 10 sec delay */ | 1062 | /* Install interrupt polling timer. Start with 10 sec delay */ |
| 1178 | init_timer(&ctrl->poll_timer); | 1063 | init_timer(&ctrl->poll_timer); |
| @@ -1184,7 +1069,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) | |||
| 1184 | info("Can't get msi for the hotplug controller\n"); | 1069 | info("Can't get msi for the hotplug controller\n"); |
| 1185 | info("Use INTx for the hotplug controller\n"); | 1070 | info("Use INTx for the hotplug controller\n"); |
| 1186 | } | 1071 | } |
| 1187 | 1072 | ||
| 1188 | rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, | 1073 | rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, |
| 1189 | MY_NAME, (void *)ctrl); | 1074 | MY_NAME, (void *)ctrl); |
| 1190 | dbg("%s: request_irq %d for hpc%d (returns %d)\n", | 1075 | dbg("%s: request_irq %d for hpc%d (returns %d)\n", |
| @@ -1235,13 +1120,11 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) | |||
| 1235 | dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); | 1120 | dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); |
| 1236 | } | 1121 | } |
| 1237 | 1122 | ||
| 1238 | DBG_LEAVE_ROUTINE | ||
| 1239 | return 0; | 1123 | return 0; |
| 1240 | 1124 | ||
| 1241 | /* We end up here for the many possible ways to fail this API. */ | 1125 | /* We end up here for the many possible ways to fail this API. */ |
| 1242 | abort_iounmap: | 1126 | abort_iounmap: |
| 1243 | iounmap(ctrl->creg); | 1127 | iounmap(ctrl->creg); |
| 1244 | abort: | 1128 | abort: |
| 1245 | DBG_LEAVE_ROUTINE | ||
| 1246 | return rc; | 1129 | return rc; |
| 1247 | } | 1130 | } |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index ed3f7e1a563c..68555c11f556 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
| @@ -24,8 +24,6 @@ | |||
| 24 | #include "pci.h" | 24 | #include "pci.h" |
| 25 | #include "msi.h" | 25 | #include "msi.h" |
| 26 | 26 | ||
| 27 | static DEFINE_SPINLOCK(msi_lock); | ||
| 28 | static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; | ||
| 29 | static struct kmem_cache* msi_cachep; | 27 | static struct kmem_cache* msi_cachep; |
| 30 | 28 | ||
| 31 | static int pci_msi_enable = 1; | 29 | static int pci_msi_enable = 1; |
| @@ -44,13 +42,13 @@ static void msi_set_mask_bit(unsigned int irq, int flag) | |||
| 44 | { | 42 | { |
| 45 | struct msi_desc *entry; | 43 | struct msi_desc *entry; |
| 46 | 44 | ||
| 47 | entry = msi_desc[irq]; | 45 | entry = get_irq_msi(irq); |
| 48 | BUG_ON(!entry || !entry->dev); | 46 | BUG_ON(!entry || !entry->dev); |
| 49 | switch (entry->msi_attrib.type) { | 47 | switch (entry->msi_attrib.type) { |
| 50 | case PCI_CAP_ID_MSI: | 48 | case PCI_CAP_ID_MSI: |
| 51 | if (entry->msi_attrib.maskbit) { | 49 | if (entry->msi_attrib.maskbit) { |
| 52 | int pos; | 50 | int pos; |
| 53 | u32 mask_bits; | 51 | u32 mask_bits; |
| 54 | 52 | ||
| 55 | pos = (long)entry->mask_base; | 53 | pos = (long)entry->mask_base; |
| 56 | pci_read_config_dword(entry->dev, pos, &mask_bits); | 54 | pci_read_config_dword(entry->dev, pos, &mask_bits); |
| @@ -74,7 +72,7 @@ static void msi_set_mask_bit(unsigned int irq, int flag) | |||
| 74 | 72 | ||
| 75 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) | 73 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) |
| 76 | { | 74 | { |
| 77 | struct msi_desc *entry = get_irq_data(irq); | 75 | struct msi_desc *entry = get_irq_msi(irq); |
| 78 | switch(entry->msi_attrib.type) { | 76 | switch(entry->msi_attrib.type) { |
| 79 | case PCI_CAP_ID_MSI: | 77 | case PCI_CAP_ID_MSI: |
| 80 | { | 78 | { |
| @@ -113,7 +111,7 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg) | |||
| 113 | 111 | ||
| 114 | void write_msi_msg(unsigned int irq, struct msi_msg *msg) | 112 | void write_msi_msg(unsigned int irq, struct msi_msg *msg) |
| 115 | { | 113 | { |
| 116 | struct msi_desc *entry = get_irq_data(irq); | 114 | struct msi_desc *entry = get_irq_msi(irq); |
| 117 | switch (entry->msi_attrib.type) { | 115 | switch (entry->msi_attrib.type) { |
| 118 | case PCI_CAP_ID_MSI: | 116 | case PCI_CAP_ID_MSI: |
| 119 | { | 117 | { |
| @@ -162,6 +160,7 @@ void unmask_msi_irq(unsigned int irq) | |||
| 162 | } | 160 | } |
| 163 | 161 | ||
| 164 | static int msi_free_irq(struct pci_dev* dev, int irq); | 162 | static int msi_free_irq(struct pci_dev* dev, int irq); |
| 163 | |||
| 165 | static int msi_init(void) | 164 | static int msi_init(void) |
| 166 | { | 165 | { |
| 167 | static int status = -ENOMEM; | 166 | static int status = -ENOMEM; |
| @@ -169,13 +168,6 @@ static int msi_init(void) | |||
| 169 | if (!status) | 168 | if (!status) |
| 170 | return status; | 169 | return status; |
| 171 | 170 | ||
| 172 | if (pci_msi_quirk) { | ||
| 173 | pci_msi_enable = 0; | ||
| 174 | printk(KERN_WARNING "PCI: MSI quirk detected. MSI disabled.\n"); | ||
| 175 | status = -EINVAL; | ||
| 176 | return status; | ||
| 177 | } | ||
| 178 | |||
| 179 | status = msi_cache_init(); | 171 | status = msi_cache_init(); |
| 180 | if (status < 0) { | 172 | if (status < 0) { |
| 181 | pci_msi_enable = 0; | 173 | pci_msi_enable = 0; |
| @@ -200,46 +192,6 @@ static struct msi_desc* alloc_msi_entry(void) | |||
| 200 | return entry; | 192 | return entry; |
| 201 | } | 193 | } |
| 202 | 194 | ||
| 203 | static void attach_msi_entry(struct msi_desc *entry, int irq) | ||
| 204 | { | ||
| 205 | unsigned long flags; | ||
| 206 | |||
| 207 | spin_lock_irqsave(&msi_lock, flags); | ||
| 208 | msi_desc[irq] = entry; | ||
| 209 | spin_unlock_irqrestore(&msi_lock, flags); | ||
| 210 | } | ||
| 211 | |||
| 212 | static int create_msi_irq(void) | ||
| 213 | { | ||
| 214 | struct msi_desc *entry; | ||
| 215 | int irq; | ||
| 216 | |||
| 217 | entry = alloc_msi_entry(); | ||
| 218 | if (!entry) | ||
| 219 | return -ENOMEM; | ||
| 220 | |||
| 221 | irq = create_irq(); | ||
| 222 | if (irq < 0) { | ||
| 223 | kmem_cache_free(msi_cachep, entry); | ||
| 224 | return -EBUSY; | ||
| 225 | } | ||
| 226 | |||
| 227 | set_irq_data(irq, entry); | ||
| 228 | |||
| 229 | return irq; | ||
| 230 | } | ||
| 231 | |||
| 232 | static void destroy_msi_irq(unsigned int irq) | ||
| 233 | { | ||
| 234 | struct msi_desc *entry; | ||
| 235 | |||
| 236 | entry = get_irq_data(irq); | ||
| 237 | set_irq_chip(irq, NULL); | ||
| 238 | set_irq_data(irq, NULL); | ||
| 239 | destroy_irq(irq); | ||
| 240 | kmem_cache_free(msi_cachep, entry); | ||
| 241 | } | ||
| 242 | |||
| 243 | static void enable_msi_mode(struct pci_dev *dev, int pos, int type) | 195 | static void enable_msi_mode(struct pci_dev *dev, int pos, int type) |
| 244 | { | 196 | { |
| 245 | u16 control; | 197 | u16 control; |
| @@ -278,36 +230,8 @@ void disable_msi_mode(struct pci_dev *dev, int pos, int type) | |||
| 278 | pci_intx(dev, 1); /* enable intx */ | 230 | pci_intx(dev, 1); /* enable intx */ |
| 279 | } | 231 | } |
| 280 | 232 | ||
| 281 | static int msi_lookup_irq(struct pci_dev *dev, int type) | ||
| 282 | { | ||
| 283 | int irq; | ||
| 284 | unsigned long flags; | ||
| 285 | |||
| 286 | spin_lock_irqsave(&msi_lock, flags); | ||
| 287 | for (irq = 0; irq < NR_IRQS; irq++) { | ||
| 288 | if (!msi_desc[irq] || msi_desc[irq]->dev != dev || | ||
| 289 | msi_desc[irq]->msi_attrib.type != type || | ||
| 290 | msi_desc[irq]->msi_attrib.default_irq != dev->irq) | ||
| 291 | continue; | ||
| 292 | spin_unlock_irqrestore(&msi_lock, flags); | ||
| 293 | /* This pre-assigned MSI irq for this device | ||
| 294 | already exits. Override dev->irq with this irq */ | ||
| 295 | dev->irq = irq; | ||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | spin_unlock_irqrestore(&msi_lock, flags); | ||
| 299 | |||
| 300 | return -EACCES; | ||
| 301 | } | ||
| 302 | |||
| 303 | void pci_scan_msi_device(struct pci_dev *dev) | ||
| 304 | { | ||
| 305 | if (!dev) | ||
| 306 | return; | ||
| 307 | } | ||
| 308 | |||
| 309 | #ifdef CONFIG_PM | 233 | #ifdef CONFIG_PM |
| 310 | int pci_save_msi_state(struct pci_dev *dev) | 234 | static int __pci_save_msi_state(struct pci_dev *dev) |
| 311 | { | 235 | { |
| 312 | int pos, i = 0; | 236 | int pos, i = 0; |
| 313 | u16 control; | 237 | u16 control; |
| @@ -345,7 +269,7 @@ int pci_save_msi_state(struct pci_dev *dev) | |||
| 345 | return 0; | 269 | return 0; |
| 346 | } | 270 | } |
| 347 | 271 | ||
| 348 | void pci_restore_msi_state(struct pci_dev *dev) | 272 | static void __pci_restore_msi_state(struct pci_dev *dev) |
| 349 | { | 273 | { |
| 350 | int i = 0, pos; | 274 | int i = 0, pos; |
| 351 | u16 control; | 275 | u16 control; |
| @@ -373,14 +297,16 @@ void pci_restore_msi_state(struct pci_dev *dev) | |||
| 373 | kfree(save_state); | 297 | kfree(save_state); |
| 374 | } | 298 | } |
| 375 | 299 | ||
| 376 | int pci_save_msix_state(struct pci_dev *dev) | 300 | static int __pci_save_msix_state(struct pci_dev *dev) |
| 377 | { | 301 | { |
| 378 | int pos; | 302 | int pos; |
| 379 | int temp; | ||
| 380 | int irq, head, tail = 0; | 303 | int irq, head, tail = 0; |
| 381 | u16 control; | 304 | u16 control; |
| 382 | struct pci_cap_saved_state *save_state; | 305 | struct pci_cap_saved_state *save_state; |
| 383 | 306 | ||
| 307 | if (!dev->msix_enabled) | ||
| 308 | return 0; | ||
| 309 | |||
| 384 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 310 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
| 385 | if (pos <= 0 || dev->no_msi) | 311 | if (pos <= 0 || dev->no_msi) |
| 386 | return 0; | 312 | return 0; |
| @@ -398,38 +324,46 @@ int pci_save_msix_state(struct pci_dev *dev) | |||
| 398 | *((u16 *)&save_state->data[0]) = control; | 324 | *((u16 *)&save_state->data[0]) = control; |
| 399 | 325 | ||
| 400 | /* save the table */ | 326 | /* save the table */ |
| 401 | temp = dev->irq; | 327 | irq = head = dev->first_msi_irq; |
| 402 | if (msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { | ||
| 403 | kfree(save_state); | ||
| 404 | return -EINVAL; | ||
| 405 | } | ||
| 406 | |||
| 407 | irq = head = dev->irq; | ||
| 408 | while (head != tail) { | 328 | while (head != tail) { |
| 409 | struct msi_desc *entry; | 329 | struct msi_desc *entry; |
| 410 | 330 | ||
| 411 | entry = msi_desc[irq]; | 331 | entry = get_irq_msi(irq); |
| 412 | read_msi_msg(irq, &entry->msg_save); | 332 | read_msi_msg(irq, &entry->msg_save); |
| 413 | 333 | ||
| 414 | tail = msi_desc[irq]->link.tail; | 334 | tail = entry->link.tail; |
| 415 | irq = tail; | 335 | irq = tail; |
| 416 | } | 336 | } |
| 417 | dev->irq = temp; | ||
| 418 | 337 | ||
| 419 | save_state->cap_nr = PCI_CAP_ID_MSIX; | 338 | save_state->cap_nr = PCI_CAP_ID_MSIX; |
| 420 | pci_add_saved_cap(dev, save_state); | 339 | pci_add_saved_cap(dev, save_state); |
| 421 | return 0; | 340 | return 0; |
| 422 | } | 341 | } |
| 423 | 342 | ||
| 424 | void pci_restore_msix_state(struct pci_dev *dev) | 343 | int pci_save_msi_state(struct pci_dev *dev) |
| 344 | { | ||
| 345 | int rc; | ||
| 346 | |||
| 347 | rc = __pci_save_msi_state(dev); | ||
| 348 | if (rc) | ||
| 349 | return rc; | ||
| 350 | |||
| 351 | rc = __pci_save_msix_state(dev); | ||
| 352 | |||
| 353 | return rc; | ||
| 354 | } | ||
| 355 | |||
| 356 | static void __pci_restore_msix_state(struct pci_dev *dev) | ||
| 425 | { | 357 | { |
| 426 | u16 save; | 358 | u16 save; |
| 427 | int pos; | 359 | int pos; |
| 428 | int irq, head, tail = 0; | 360 | int irq, head, tail = 0; |
| 429 | struct msi_desc *entry; | 361 | struct msi_desc *entry; |
| 430 | int temp; | ||
| 431 | struct pci_cap_saved_state *save_state; | 362 | struct pci_cap_saved_state *save_state; |
| 432 | 363 | ||
| 364 | if (!dev->msix_enabled) | ||
| 365 | return; | ||
| 366 | |||
| 433 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX); | 367 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX); |
| 434 | if (!save_state) | 368 | if (!save_state) |
| 435 | return; | 369 | return; |
| @@ -442,23 +376,25 @@ void pci_restore_msix_state(struct pci_dev *dev) | |||
| 442 | return; | 376 | return; |
| 443 | 377 | ||
| 444 | /* route the table */ | 378 | /* route the table */ |
| 445 | temp = dev->irq; | 379 | irq = head = dev->first_msi_irq; |
| 446 | if (msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) | ||
| 447 | return; | ||
| 448 | irq = head = dev->irq; | ||
| 449 | while (head != tail) { | 380 | while (head != tail) { |
| 450 | entry = msi_desc[irq]; | 381 | entry = get_irq_msi(irq); |
| 451 | write_msi_msg(irq, &entry->msg_save); | 382 | write_msi_msg(irq, &entry->msg_save); |
| 452 | 383 | ||
| 453 | tail = msi_desc[irq]->link.tail; | 384 | tail = entry->link.tail; |
| 454 | irq = tail; | 385 | irq = tail; |
| 455 | } | 386 | } |
| 456 | dev->irq = temp; | ||
| 457 | 387 | ||
| 458 | pci_write_config_word(dev, msi_control_reg(pos), save); | 388 | pci_write_config_word(dev, msi_control_reg(pos), save); |
| 459 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); | 389 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); |
| 460 | } | 390 | } |
| 461 | #endif | 391 | |
| 392 | void pci_restore_msi_state(struct pci_dev *dev) | ||
| 393 | { | ||
| 394 | __pci_restore_msi_state(dev); | ||
| 395 | __pci_restore_msix_state(dev); | ||
| 396 | } | ||
| 397 | #endif /* CONFIG_PM */ | ||
| 462 | 398 | ||
| 463 | /** | 399 | /** |
| 464 | * msi_capability_init - configure device's MSI capability structure | 400 | * msi_capability_init - configure device's MSI capability structure |
| @@ -471,7 +407,6 @@ void pci_restore_msix_state(struct pci_dev *dev) | |||
| 471 | **/ | 407 | **/ |
| 472 | static int msi_capability_init(struct pci_dev *dev) | 408 | static int msi_capability_init(struct pci_dev *dev) |
| 473 | { | 409 | { |
| 474 | int status; | ||
| 475 | struct msi_desc *entry; | 410 | struct msi_desc *entry; |
| 476 | int pos, irq; | 411 | int pos, irq; |
| 477 | u16 control; | 412 | u16 control; |
| @@ -479,13 +414,10 @@ static int msi_capability_init(struct pci_dev *dev) | |||
| 479 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | 414 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
| 480 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 415 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
| 481 | /* MSI Entry Initialization */ | 416 | /* MSI Entry Initialization */ |
| 482 | irq = create_msi_irq(); | 417 | entry = alloc_msi_entry(); |
| 483 | if (irq < 0) | 418 | if (!entry) |
| 484 | return irq; | 419 | return -ENOMEM; |
| 485 | 420 | ||
| 486 | entry = get_irq_data(irq); | ||
| 487 | entry->link.head = irq; | ||
| 488 | entry->link.tail = irq; | ||
| 489 | entry->msi_attrib.type = PCI_CAP_ID_MSI; | 421 | entry->msi_attrib.type = PCI_CAP_ID_MSI; |
| 490 | entry->msi_attrib.is_64 = is_64bit_address(control); | 422 | entry->msi_attrib.is_64 = is_64bit_address(control); |
| 491 | entry->msi_attrib.entry_nr = 0; | 423 | entry->msi_attrib.entry_nr = 0; |
| @@ -511,13 +443,16 @@ static int msi_capability_init(struct pci_dev *dev) | |||
| 511 | maskbits); | 443 | maskbits); |
| 512 | } | 444 | } |
| 513 | /* Configure MSI capability structure */ | 445 | /* Configure MSI capability structure */ |
| 514 | status = arch_setup_msi_irq(irq, dev); | 446 | irq = arch_setup_msi_irq(dev, entry); |
| 515 | if (status < 0) { | 447 | if (irq < 0) { |
| 516 | destroy_msi_irq(irq); | 448 | kmem_cache_free(msi_cachep, entry); |
| 517 | return status; | 449 | return irq; |
| 518 | } | 450 | } |
| 451 | entry->link.head = irq; | ||
| 452 | entry->link.tail = irq; | ||
| 453 | dev->first_msi_irq = irq; | ||
| 454 | set_irq_msi(irq, entry); | ||
| 519 | 455 | ||
| 520 | attach_msi_entry(entry, irq); | ||
| 521 | /* Set MSI enabled bits */ | 456 | /* Set MSI enabled bits */ |
| 522 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | 457 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
| 523 | 458 | ||
| @@ -539,7 +474,6 @@ static int msix_capability_init(struct pci_dev *dev, | |||
| 539 | struct msix_entry *entries, int nvec) | 474 | struct msix_entry *entries, int nvec) |
| 540 | { | 475 | { |
| 541 | struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; | 476 | struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; |
| 542 | int status; | ||
| 543 | int irq, pos, i, j, nr_entries, temp = 0; | 477 | int irq, pos, i, j, nr_entries, temp = 0; |
| 544 | unsigned long phys_addr; | 478 | unsigned long phys_addr; |
| 545 | u32 table_offset; | 479 | u32 table_offset; |
| @@ -562,13 +496,11 @@ static int msix_capability_init(struct pci_dev *dev, | |||
| 562 | 496 | ||
| 563 | /* MSI-X Table Initialization */ | 497 | /* MSI-X Table Initialization */ |
| 564 | for (i = 0; i < nvec; i++) { | 498 | for (i = 0; i < nvec; i++) { |
| 565 | irq = create_msi_irq(); | 499 | entry = alloc_msi_entry(); |
| 566 | if (irq < 0) | 500 | if (!entry) |
| 567 | break; | 501 | break; |
| 568 | 502 | ||
| 569 | entry = get_irq_data(irq); | ||
| 570 | j = entries[i].entry; | 503 | j = entries[i].entry; |
| 571 | entries[i].vector = irq; | ||
| 572 | entry->msi_attrib.type = PCI_CAP_ID_MSIX; | 504 | entry->msi_attrib.type = PCI_CAP_ID_MSIX; |
| 573 | entry->msi_attrib.is_64 = 1; | 505 | entry->msi_attrib.is_64 = 1; |
| 574 | entry->msi_attrib.entry_nr = j; | 506 | entry->msi_attrib.entry_nr = j; |
| @@ -577,6 +509,14 @@ static int msix_capability_init(struct pci_dev *dev, | |||
| 577 | entry->msi_attrib.pos = pos; | 509 | entry->msi_attrib.pos = pos; |
| 578 | entry->dev = dev; | 510 | entry->dev = dev; |
| 579 | entry->mask_base = base; | 511 | entry->mask_base = base; |
| 512 | |||
| 513 | /* Configure MSI-X capability structure */ | ||
| 514 | irq = arch_setup_msi_irq(dev, entry); | ||
| 515 | if (irq < 0) { | ||
| 516 | kmem_cache_free(msi_cachep, entry); | ||
| 517 | break; | ||
| 518 | } | ||
| 519 | entries[i].vector = irq; | ||
| 580 | if (!head) { | 520 | if (!head) { |
| 581 | entry->link.head = irq; | 521 | entry->link.head = irq; |
| 582 | entry->link.tail = irq; | 522 | entry->link.tail = irq; |
| @@ -589,14 +529,8 @@ static int msix_capability_init(struct pci_dev *dev, | |||
| 589 | } | 529 | } |
| 590 | temp = irq; | 530 | temp = irq; |
| 591 | tail = entry; | 531 | tail = entry; |
| 592 | /* Configure MSI-X capability structure */ | ||
| 593 | status = arch_setup_msi_irq(irq, dev); | ||
| 594 | if (status < 0) { | ||
| 595 | destroy_msi_irq(irq); | ||
| 596 | break; | ||
| 597 | } | ||
| 598 | 532 | ||
| 599 | attach_msi_entry(entry, irq); | 533 | set_irq_msi(irq, entry); |
| 600 | } | 534 | } |
| 601 | if (i != nvec) { | 535 | if (i != nvec) { |
| 602 | int avail = i - 1; | 536 | int avail = i - 1; |
| @@ -613,6 +547,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
| 613 | avail = -EBUSY; | 547 | avail = -EBUSY; |
| 614 | return avail; | 548 | return avail; |
| 615 | } | 549 | } |
| 550 | dev->first_msi_irq = entries[0].vector; | ||
| 616 | /* Set MSI-X enabled bits */ | 551 | /* Set MSI-X enabled bits */ |
| 617 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); | 552 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); |
| 618 | 553 | ||
| @@ -660,13 +595,11 @@ int pci_msi_supported(struct pci_dev * dev) | |||
| 660 | **/ | 595 | **/ |
| 661 | int pci_enable_msi(struct pci_dev* dev) | 596 | int pci_enable_msi(struct pci_dev* dev) |
| 662 | { | 597 | { |
| 663 | int pos, temp, status; | 598 | int pos, status; |
| 664 | 599 | ||
| 665 | if (pci_msi_supported(dev) < 0) | 600 | if (pci_msi_supported(dev) < 0) |
| 666 | return -EINVAL; | 601 | return -EINVAL; |
| 667 | 602 | ||
| 668 | temp = dev->irq; | ||
| 669 | |||
| 670 | status = msi_init(); | 603 | status = msi_init(); |
| 671 | if (status < 0) | 604 | if (status < 0) |
| 672 | return status; | 605 | return status; |
| @@ -675,15 +608,14 @@ int pci_enable_msi(struct pci_dev* dev) | |||
| 675 | if (!pos) | 608 | if (!pos) |
| 676 | return -EINVAL; | 609 | return -EINVAL; |
| 677 | 610 | ||
| 678 | WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSI)); | 611 | WARN_ON(!!dev->msi_enabled); |
| 679 | 612 | ||
| 680 | /* Check whether driver already requested for MSI-X irqs */ | 613 | /* Check whether driver already requested for MSI-X irqs */ |
| 681 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 614 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
| 682 | if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { | 615 | if (pos > 0 && dev->msix_enabled) { |
| 683 | printk(KERN_INFO "PCI: %s: Can't enable MSI. " | 616 | printk(KERN_INFO "PCI: %s: Can't enable MSI. " |
| 684 | "Device already has MSI-X irq assigned\n", | 617 | "Device already has MSI-X enabled\n", |
| 685 | pci_name(dev)); | 618 | pci_name(dev)); |
| 686 | dev->irq = temp; | ||
| 687 | return -EINVAL; | 619 | return -EINVAL; |
| 688 | } | 620 | } |
| 689 | status = msi_capability_init(dev); | 621 | status = msi_capability_init(dev); |
| @@ -695,13 +627,15 @@ void pci_disable_msi(struct pci_dev* dev) | |||
| 695 | struct msi_desc *entry; | 627 | struct msi_desc *entry; |
| 696 | int pos, default_irq; | 628 | int pos, default_irq; |
| 697 | u16 control; | 629 | u16 control; |
| 698 | unsigned long flags; | ||
| 699 | 630 | ||
| 700 | if (!pci_msi_enable) | 631 | if (!pci_msi_enable) |
| 701 | return; | 632 | return; |
| 702 | if (!dev) | 633 | if (!dev) |
| 703 | return; | 634 | return; |
| 704 | 635 | ||
| 636 | if (!dev->msi_enabled) | ||
| 637 | return; | ||
| 638 | |||
| 705 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | 639 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
| 706 | if (!pos) | 640 | if (!pos) |
| 707 | return; | 641 | return; |
| @@ -710,28 +644,26 @@ void pci_disable_msi(struct pci_dev* dev) | |||
| 710 | if (!(control & PCI_MSI_FLAGS_ENABLE)) | 644 | if (!(control & PCI_MSI_FLAGS_ENABLE)) |
| 711 | return; | 645 | return; |
| 712 | 646 | ||
| 647 | |||
| 713 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | 648 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
| 714 | 649 | ||
| 715 | spin_lock_irqsave(&msi_lock, flags); | 650 | entry = get_irq_msi(dev->first_msi_irq); |
| 716 | entry = msi_desc[dev->irq]; | ||
| 717 | if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { | 651 | if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { |
| 718 | spin_unlock_irqrestore(&msi_lock, flags); | ||
| 719 | return; | 652 | return; |
| 720 | } | 653 | } |
| 721 | if (irq_has_action(dev->irq)) { | 654 | if (irq_has_action(dev->first_msi_irq)) { |
| 722 | spin_unlock_irqrestore(&msi_lock, flags); | ||
| 723 | printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without " | 655 | printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without " |
| 724 | "free_irq() on MSI irq %d\n", | 656 | "free_irq() on MSI irq %d\n", |
| 725 | pci_name(dev), dev->irq); | 657 | pci_name(dev), dev->first_msi_irq); |
| 726 | BUG_ON(irq_has_action(dev->irq)); | 658 | BUG_ON(irq_has_action(dev->first_msi_irq)); |
| 727 | } else { | 659 | } else { |
| 728 | default_irq = entry->msi_attrib.default_irq; | 660 | default_irq = entry->msi_attrib.default_irq; |
| 729 | spin_unlock_irqrestore(&msi_lock, flags); | 661 | msi_free_irq(dev, dev->first_msi_irq); |
| 730 | msi_free_irq(dev, dev->irq); | ||
| 731 | 662 | ||
| 732 | /* Restore dev->irq to its default pin-assertion irq */ | 663 | /* Restore dev->irq to its default pin-assertion irq */ |
| 733 | dev->irq = default_irq; | 664 | dev->irq = default_irq; |
| 734 | } | 665 | } |
| 666 | dev->first_msi_irq = 0; | ||
| 735 | } | 667 | } |
| 736 | 668 | ||
| 737 | static int msi_free_irq(struct pci_dev* dev, int irq) | 669 | static int msi_free_irq(struct pci_dev* dev, int irq) |
| @@ -739,27 +671,20 @@ static int msi_free_irq(struct pci_dev* dev, int irq) | |||
| 739 | struct msi_desc *entry; | 671 | struct msi_desc *entry; |
| 740 | int head, entry_nr, type; | 672 | int head, entry_nr, type; |
| 741 | void __iomem *base; | 673 | void __iomem *base; |
| 742 | unsigned long flags; | ||
| 743 | 674 | ||
| 744 | arch_teardown_msi_irq(irq); | 675 | entry = get_irq_msi(irq); |
| 745 | |||
| 746 | spin_lock_irqsave(&msi_lock, flags); | ||
| 747 | entry = msi_desc[irq]; | ||
| 748 | if (!entry || entry->dev != dev) { | 676 | if (!entry || entry->dev != dev) { |
| 749 | spin_unlock_irqrestore(&msi_lock, flags); | ||
| 750 | return -EINVAL; | 677 | return -EINVAL; |
| 751 | } | 678 | } |
| 752 | type = entry->msi_attrib.type; | 679 | type = entry->msi_attrib.type; |
| 753 | entry_nr = entry->msi_attrib.entry_nr; | 680 | entry_nr = entry->msi_attrib.entry_nr; |
| 754 | head = entry->link.head; | 681 | head = entry->link.head; |
| 755 | base = entry->mask_base; | 682 | base = entry->mask_base; |
| 756 | msi_desc[entry->link.head]->link.tail = entry->link.tail; | 683 | get_irq_msi(entry->link.head)->link.tail = entry->link.tail; |
| 757 | msi_desc[entry->link.tail]->link.head = entry->link.head; | 684 | get_irq_msi(entry->link.tail)->link.head = entry->link.head; |
| 758 | entry->dev = NULL; | ||
| 759 | msi_desc[irq] = NULL; | ||
| 760 | spin_unlock_irqrestore(&msi_lock, flags); | ||
| 761 | 685 | ||
| 762 | destroy_msi_irq(irq); | 686 | arch_teardown_msi_irq(irq); |
| 687 | kmem_cache_free(msi_cachep, entry); | ||
| 763 | 688 | ||
| 764 | if (type == PCI_CAP_ID_MSIX) { | 689 | if (type == PCI_CAP_ID_MSIX) { |
| 765 | writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE + | 690 | writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE + |
| @@ -790,7 +715,7 @@ static int msi_free_irq(struct pci_dev* dev, int irq) | |||
| 790 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | 715 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) |
| 791 | { | 716 | { |
| 792 | int status, pos, nr_entries; | 717 | int status, pos, nr_entries; |
| 793 | int i, j, temp; | 718 | int i, j; |
| 794 | u16 control; | 719 | u16 control; |
| 795 | 720 | ||
| 796 | if (!entries || pci_msi_supported(dev) < 0) | 721 | if (!entries || pci_msi_supported(dev) < 0) |
| @@ -818,16 +743,14 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | |||
| 818 | return -EINVAL; /* duplicate entry */ | 743 | return -EINVAL; /* duplicate entry */ |
| 819 | } | 744 | } |
| 820 | } | 745 | } |
| 821 | temp = dev->irq; | 746 | WARN_ON(!!dev->msix_enabled); |
| 822 | WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)); | ||
| 823 | 747 | ||
| 824 | /* Check whether driver already requested for MSI irq */ | 748 | /* Check whether driver already requested for MSI irq */ |
| 825 | if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 && | 749 | if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 && |
| 826 | !msi_lookup_irq(dev, PCI_CAP_ID_MSI)) { | 750 | dev->msi_enabled) { |
| 827 | printk(KERN_INFO "PCI: %s: Can't enable MSI-X. " | 751 | printk(KERN_INFO "PCI: %s: Can't enable MSI-X. " |
| 828 | "Device already has an MSI irq assigned\n", | 752 | "Device already has an MSI irq assigned\n", |
| 829 | pci_name(dev)); | 753 | pci_name(dev)); |
| 830 | dev->irq = temp; | ||
| 831 | return -EINVAL; | 754 | return -EINVAL; |
| 832 | } | 755 | } |
| 833 | status = msix_capability_init(dev, entries, nvec); | 756 | status = msix_capability_init(dev, entries, nvec); |
| @@ -836,7 +759,8 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | |||
| 836 | 759 | ||
| 837 | void pci_disable_msix(struct pci_dev* dev) | 760 | void pci_disable_msix(struct pci_dev* dev) |
| 838 | { | 761 | { |
| 839 | int pos, temp; | 762 | int irq, head, tail = 0, warning = 0; |
| 763 | int pos; | ||
| 840 | u16 control; | 764 | u16 control; |
| 841 | 765 | ||
| 842 | if (!pci_msi_enable) | 766 | if (!pci_msi_enable) |
| @@ -844,6 +768,9 @@ void pci_disable_msix(struct pci_dev* dev) | |||
| 844 | if (!dev) | 768 | if (!dev) |
| 845 | return; | 769 | return; |
| 846 | 770 | ||
| 771 | if (!dev->msix_enabled) | ||
| 772 | return; | ||
| 773 | |||
| 847 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 774 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
| 848 | if (!pos) | 775 | if (!pos) |
| 849 | return; | 776 | return; |
| @@ -854,31 +781,23 @@ void pci_disable_msix(struct pci_dev* dev) | |||
| 854 | 781 | ||
| 855 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); | 782 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); |
| 856 | 783 | ||
| 857 | temp = dev->irq; | 784 | irq = head = dev->first_msi_irq; |
| 858 | if (!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { | 785 | while (head != tail) { |
| 859 | int irq, head, tail = 0, warning = 0; | 786 | tail = get_irq_msi(irq)->link.tail; |
| 860 | unsigned long flags; | 787 | if (irq_has_action(irq)) |
| 861 | 788 | warning = 1; | |
| 862 | irq = head = dev->irq; | 789 | else if (irq != head) /* Release MSI-X irq */ |
| 863 | dev->irq = temp; /* Restore pin IRQ */ | 790 | msi_free_irq(dev, irq); |
| 864 | while (head != tail) { | 791 | irq = tail; |
| 865 | spin_lock_irqsave(&msi_lock, flags); | 792 | } |
| 866 | tail = msi_desc[irq]->link.tail; | 793 | msi_free_irq(dev, irq); |
| 867 | spin_unlock_irqrestore(&msi_lock, flags); | 794 | if (warning) { |
| 868 | if (irq_has_action(irq)) | 795 | printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without " |
| 869 | warning = 1; | 796 | "free_irq() on all MSI-X irqs\n", |
| 870 | else if (irq != head) /* Release MSI-X irq */ | 797 | pci_name(dev)); |
| 871 | msi_free_irq(dev, irq); | 798 | BUG_ON(warning > 0); |
| 872 | irq = tail; | ||
| 873 | } | ||
| 874 | msi_free_irq(dev, irq); | ||
| 875 | if (warning) { | ||
| 876 | printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without " | ||
| 877 | "free_irq() on all MSI-X irqs\n", | ||
| 878 | pci_name(dev)); | ||
| 879 | BUG_ON(warning > 0); | ||
| 880 | } | ||
| 881 | } | 799 | } |
| 800 | dev->first_msi_irq = 0; | ||
| 882 | } | 801 | } |
| 883 | 802 | ||
| 884 | /** | 803 | /** |
| @@ -892,35 +811,26 @@ void pci_disable_msix(struct pci_dev* dev) | |||
| 892 | **/ | 811 | **/ |
| 893 | void msi_remove_pci_irq_vectors(struct pci_dev* dev) | 812 | void msi_remove_pci_irq_vectors(struct pci_dev* dev) |
| 894 | { | 813 | { |
| 895 | int pos, temp; | ||
| 896 | unsigned long flags; | ||
| 897 | |||
| 898 | if (!pci_msi_enable || !dev) | 814 | if (!pci_msi_enable || !dev) |
| 899 | return; | 815 | return; |
| 900 | 816 | ||
| 901 | temp = dev->irq; /* Save IOAPIC IRQ */ | 817 | if (dev->msi_enabled) { |
| 902 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | 818 | if (irq_has_action(dev->first_msi_irq)) { |
| 903 | if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSI)) { | ||
| 904 | if (irq_has_action(dev->irq)) { | ||
| 905 | printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " | 819 | printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " |
| 906 | "called without free_irq() on MSI irq %d\n", | 820 | "called without free_irq() on MSI irq %d\n", |
| 907 | pci_name(dev), dev->irq); | 821 | pci_name(dev), dev->first_msi_irq); |
| 908 | BUG_ON(irq_has_action(dev->irq)); | 822 | BUG_ON(irq_has_action(dev->first_msi_irq)); |
| 909 | } else /* Release MSI irq assigned to this device */ | 823 | } else /* Release MSI irq assigned to this device */ |
| 910 | msi_free_irq(dev, dev->irq); | 824 | msi_free_irq(dev, dev->first_msi_irq); |
| 911 | dev->irq = temp; /* Restore IOAPIC IRQ */ | ||
| 912 | } | 825 | } |
| 913 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 826 | if (dev->msix_enabled) { |
| 914 | if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { | ||
| 915 | int irq, head, tail = 0, warning = 0; | 827 | int irq, head, tail = 0, warning = 0; |
| 916 | void __iomem *base = NULL; | 828 | void __iomem *base = NULL; |
| 917 | 829 | ||
| 918 | irq = head = dev->irq; | 830 | irq = head = dev->first_msi_irq; |
| 919 | while (head != tail) { | 831 | while (head != tail) { |
| 920 | spin_lock_irqsave(&msi_lock, flags); | 832 | tail = get_irq_msi(irq)->link.tail; |
| 921 | tail = msi_desc[irq]->link.tail; | 833 | base = get_irq_msi(irq)->mask_base; |
| 922 | base = msi_desc[irq]->mask_base; | ||
| 923 | spin_unlock_irqrestore(&msi_lock, flags); | ||
| 924 | if (irq_has_action(irq)) | 834 | if (irq_has_action(irq)) |
| 925 | warning = 1; | 835 | warning = 1; |
| 926 | else if (irq != head) /* Release MSI-X irq */ | 836 | else if (irq != head) /* Release MSI-X irq */ |
| @@ -935,7 +845,6 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) | |||
| 935 | pci_name(dev)); | 845 | pci_name(dev)); |
| 936 | BUG_ON(warning > 0); | 846 | BUG_ON(warning > 0); |
| 937 | } | 847 | } |
| 938 | dev->irq = temp; /* Restore IOAPIC IRQ */ | ||
| 939 | } | 848 | } |
| 940 | } | 849 | } |
| 941 | 850 | ||
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 358766885260..4438ae1ede4f 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -324,8 +324,7 @@ static int pci_default_resume(struct pci_dev *pci_dev) | |||
| 324 | /* restore the PCI config space */ | 324 | /* restore the PCI config space */ |
| 325 | pci_restore_state(pci_dev); | 325 | pci_restore_state(pci_dev); |
| 326 | /* if the device was enabled before suspend, reenable */ | 326 | /* if the device was enabled before suspend, reenable */ |
| 327 | if (atomic_read(&pci_dev->enable_cnt)) | 327 | retval = __pci_reenable_device(pci_dev); |
| 328 | retval = __pci_enable_device(pci_dev); | ||
| 329 | /* if the device was busmaster before the suspend, make it busmaster again */ | 328 | /* if the device was busmaster before the suspend, make it busmaster again */ |
| 330 | if (pci_dev->is_busmaster) | 329 | if (pci_dev->is_busmaster) |
| 331 | pci_set_master(pci_dev); | 330 | pci_set_master(pci_dev); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 206c834d263a..84c757ba0664 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -392,6 +392,14 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
| 392 | if (state > PCI_D3hot) | 392 | if (state > PCI_D3hot) |
| 393 | state = PCI_D3hot; | 393 | state = PCI_D3hot; |
| 394 | 394 | ||
| 395 | /* | ||
| 396 | * If the device or the parent bridge can't support PCI PM, ignore | ||
| 397 | * the request if we're doing anything besides putting it into D0 | ||
| 398 | * (which would only happen on boot). | ||
| 399 | */ | ||
| 400 | if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev)) | ||
| 401 | return 0; | ||
| 402 | |||
| 395 | /* Validate current state: | 403 | /* Validate current state: |
| 396 | * Can enter D0 from any state, but if we can only go deeper | 404 | * Can enter D0 from any state, but if we can only go deeper |
| 397 | * to sleep if we're already in a low power state | 405 | * to sleep if we're already in a low power state |
| @@ -403,13 +411,6 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
| 403 | } else if (dev->current_state == state) | 411 | } else if (dev->current_state == state) |
| 404 | return 0; /* we're already there */ | 412 | return 0; /* we're already there */ |
| 405 | 413 | ||
| 406 | /* | ||
| 407 | * If the device or the parent bridge can't support PCI PM, ignore | ||
| 408 | * the request if we're doing anything besides putting it into D0 | ||
| 409 | * (which would only happen on boot). | ||
| 410 | */ | ||
| 411 | if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev)) | ||
| 412 | return 0; | ||
| 413 | 414 | ||
| 414 | /* find PCI PM capability in list */ | 415 | /* find PCI PM capability in list */ |
| 415 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); | 416 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); |
| @@ -633,8 +634,6 @@ pci_save_state(struct pci_dev *dev) | |||
| 633 | pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); | 634 | pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); |
| 634 | if ((i = pci_save_msi_state(dev)) != 0) | 635 | if ((i = pci_save_msi_state(dev)) != 0) |
| 635 | return i; | 636 | return i; |
| 636 | if ((i = pci_save_msix_state(dev)) != 0) | ||
| 637 | return i; | ||
| 638 | if ((i = pci_save_pcie_state(dev)) != 0) | 637 | if ((i = pci_save_pcie_state(dev)) != 0) |
| 639 | return i; | 638 | return i; |
| 640 | if ((i = pci_save_pcix_state(dev)) != 0) | 639 | if ((i = pci_save_pcix_state(dev)) != 0) |
| @@ -672,22 +671,11 @@ pci_restore_state(struct pci_dev *dev) | |||
| 672 | } | 671 | } |
| 673 | pci_restore_pcix_state(dev); | 672 | pci_restore_pcix_state(dev); |
| 674 | pci_restore_msi_state(dev); | 673 | pci_restore_msi_state(dev); |
| 675 | pci_restore_msix_state(dev); | 674 | |
| 676 | return 0; | 675 | return 0; |
| 677 | } | 676 | } |
| 678 | 677 | ||
| 679 | /** | 678 | static int do_pci_enable_device(struct pci_dev *dev, int bars) |
| 680 | * pci_enable_device_bars - Initialize some of a device for use | ||
| 681 | * @dev: PCI device to be initialized | ||
| 682 | * @bars: bitmask of BAR's that must be configured | ||
| 683 | * | ||
| 684 | * Initialize device before it's used by a driver. Ask low-level code | ||
| 685 | * to enable selected I/O and memory resources. Wake up the device if it | ||
| 686 | * was suspended. Beware, this function can fail. | ||
| 687 | */ | ||
| 688 | |||
| 689 | int | ||
| 690 | pci_enable_device_bars(struct pci_dev *dev, int bars) | ||
| 691 | { | 679 | { |
| 692 | int err; | 680 | int err; |
| 693 | 681 | ||
| @@ -697,30 +685,47 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) | |||
| 697 | err = pcibios_enable_device(dev, bars); | 685 | err = pcibios_enable_device(dev, bars); |
| 698 | if (err < 0) | 686 | if (err < 0) |
| 699 | return err; | 687 | return err; |
| 688 | pci_fixup_device(pci_fixup_enable, dev); | ||
| 689 | |||
| 700 | return 0; | 690 | return 0; |
| 701 | } | 691 | } |
| 702 | 692 | ||
| 703 | /** | 693 | /** |
| 704 | * __pci_enable_device - Initialize device before it's used by a driver. | 694 | * __pci_reenable_device - Resume abandoned device |
| 695 | * @dev: PCI device to be resumed | ||
| 696 | * | ||
| 697 | * Note this function is a backend of pci_default_resume and is not supposed | ||
| 698 | * to be called by normal code, write proper resume handler and use it instead. | ||
| 699 | */ | ||
| 700 | int | ||
| 701 | __pci_reenable_device(struct pci_dev *dev) | ||
| 702 | { | ||
| 703 | if (atomic_read(&dev->enable_cnt)) | ||
| 704 | return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1); | ||
| 705 | return 0; | ||
| 706 | } | ||
| 707 | |||
| 708 | /** | ||
| 709 | * pci_enable_device_bars - Initialize some of a device for use | ||
| 705 | * @dev: PCI device to be initialized | 710 | * @dev: PCI device to be initialized |
| 711 | * @bars: bitmask of BAR's that must be configured | ||
| 706 | * | 712 | * |
| 707 | * Initialize device before it's used by a driver. Ask low-level code | 713 | * Initialize device before it's used by a driver. Ask low-level code |
| 708 | * to enable I/O and memory. Wake up the device if it was suspended. | 714 | * to enable selected I/O and memory resources. Wake up the device if it |
| 709 | * Beware, this function can fail. | 715 | * was suspended. Beware, this function can fail. |
| 710 | * | ||
| 711 | * Note this function is a backend and is not supposed to be called by | ||
| 712 | * normal code, use pci_enable_device() instead. | ||
| 713 | */ | 716 | */ |
| 714 | int | 717 | int |
| 715 | __pci_enable_device(struct pci_dev *dev) | 718 | pci_enable_device_bars(struct pci_dev *dev, int bars) |
| 716 | { | 719 | { |
| 717 | int err; | 720 | int err; |
| 718 | 721 | ||
| 719 | err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); | 722 | if (atomic_add_return(1, &dev->enable_cnt) > 1) |
| 720 | if (err) | 723 | return 0; /* already enabled */ |
| 721 | return err; | 724 | |
| 722 | pci_fixup_device(pci_fixup_enable, dev); | 725 | err = do_pci_enable_device(dev, bars); |
| 723 | return 0; | 726 | if (err < 0) |
| 727 | atomic_dec(&dev->enable_cnt); | ||
| 728 | return err; | ||
| 724 | } | 729 | } |
| 725 | 730 | ||
| 726 | /** | 731 | /** |
| @@ -736,13 +741,7 @@ __pci_enable_device(struct pci_dev *dev) | |||
| 736 | */ | 741 | */ |
| 737 | int pci_enable_device(struct pci_dev *dev) | 742 | int pci_enable_device(struct pci_dev *dev) |
| 738 | { | 743 | { |
| 739 | int result; | 744 | return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); |
| 740 | if (atomic_add_return(1, &dev->enable_cnt) > 1) | ||
| 741 | return 0; /* already enabled */ | ||
| 742 | result = __pci_enable_device(dev); | ||
| 743 | if (result < 0) | ||
| 744 | atomic_dec(&dev->enable_cnt); | ||
| 745 | return result; | ||
| 746 | } | 745 | } |
| 747 | 746 | ||
| 748 | /** | 747 | /** |
| @@ -921,6 +920,47 @@ err_out: | |||
| 921 | return -EBUSY; | 920 | return -EBUSY; |
| 922 | } | 921 | } |
| 923 | 922 | ||
| 923 | /** | ||
| 924 | * pci_release_selected_regions - Release selected PCI I/O and memory resources | ||
| 925 | * @pdev: PCI device whose resources were previously reserved | ||
| 926 | * @bars: Bitmask of BARs to be released | ||
| 927 | * | ||
| 928 | * Release selected PCI I/O and memory resources previously reserved. | ||
| 929 | * Call this function only after all use of the PCI regions has ceased. | ||
| 930 | */ | ||
| 931 | void pci_release_selected_regions(struct pci_dev *pdev, int bars) | ||
| 932 | { | ||
| 933 | int i; | ||
| 934 | |||
| 935 | for (i = 0; i < 6; i++) | ||
| 936 | if (bars & (1 << i)) | ||
| 937 | pci_release_region(pdev, i); | ||
| 938 | } | ||
| 939 | |||
| 940 | /** | ||
| 941 | * pci_request_selected_regions - Reserve selected PCI I/O and memory resources | ||
| 942 | * @pdev: PCI device whose resources are to be reserved | ||
| 943 | * @bars: Bitmask of BARs to be requested | ||
| 944 | * @res_name: Name to be associated with resource | ||
| 945 | */ | ||
| 946 | int pci_request_selected_regions(struct pci_dev *pdev, int bars, | ||
| 947 | const char *res_name) | ||
| 948 | { | ||
| 949 | int i; | ||
| 950 | |||
| 951 | for (i = 0; i < 6; i++) | ||
| 952 | if (bars & (1 << i)) | ||
| 953 | if(pci_request_region(pdev, i, res_name)) | ||
| 954 | goto err_out; | ||
| 955 | return 0; | ||
| 956 | |||
| 957 | err_out: | ||
| 958 | while(--i >= 0) | ||
| 959 | if (bars & (1 << i)) | ||
| 960 | pci_release_region(pdev, i); | ||
| 961 | |||
| 962 | return -EBUSY; | ||
| 963 | } | ||
| 924 | 964 | ||
| 925 | /** | 965 | /** |
| 926 | * pci_release_regions - Release reserved PCI I/O and memory resources | 966 | * pci_release_regions - Release reserved PCI I/O and memory resources |
| @@ -933,10 +973,7 @@ err_out: | |||
| 933 | 973 | ||
| 934 | void pci_release_regions(struct pci_dev *pdev) | 974 | void pci_release_regions(struct pci_dev *pdev) |
| 935 | { | 975 | { |
| 936 | int i; | 976 | pci_release_selected_regions(pdev, (1 << 6) - 1); |
| 937 | |||
| 938 | for (i = 0; i < 6; i++) | ||
| 939 | pci_release_region(pdev, i); | ||
| 940 | } | 977 | } |
| 941 | 978 | ||
| 942 | /** | 979 | /** |
| @@ -954,18 +991,7 @@ void pci_release_regions(struct pci_dev *pdev) | |||
| 954 | */ | 991 | */ |
| 955 | int pci_request_regions(struct pci_dev *pdev, const char *res_name) | 992 | int pci_request_regions(struct pci_dev *pdev, const char *res_name) |
| 956 | { | 993 | { |
| 957 | int i; | 994 | return pci_request_selected_regions(pdev, ((1 << 6) - 1), res_name); |
| 958 | |||
| 959 | for (i = 0; i < 6; i++) | ||
| 960 | if(pci_request_region(pdev, i, res_name)) | ||
| 961 | goto err_out; | ||
| 962 | return 0; | ||
| 963 | |||
| 964 | err_out: | ||
| 965 | while(--i >= 0) | ||
| 966 | pci_release_region(pdev, i); | ||
| 967 | |||
| 968 | return -EBUSY; | ||
| 969 | } | 995 | } |
| 970 | 996 | ||
| 971 | /** | 997 | /** |
| @@ -1148,7 +1174,23 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) | |||
| 1148 | return 0; | 1174 | return 0; |
| 1149 | } | 1175 | } |
| 1150 | #endif | 1176 | #endif |
| 1151 | 1177 | ||
| 1178 | /** | ||
| 1179 | * pci_select_bars - Make BAR mask from the type of resource | ||
| 1180 | * @pdev: the PCI device for which BAR mask is made | ||
| 1181 | * @flags: resource type mask to be selected | ||
| 1182 | * | ||
| 1183 | * This helper routine makes bar mask from the type of resource. | ||
| 1184 | */ | ||
| 1185 | int pci_select_bars(struct pci_dev *dev, unsigned long flags) | ||
| 1186 | { | ||
| 1187 | int i, bars = 0; | ||
| 1188 | for (i = 0; i < PCI_NUM_RESOURCES; i++) | ||
| 1189 | if (pci_resource_flags(dev, i) & flags) | ||
| 1190 | bars |= (1 << i); | ||
| 1191 | return bars; | ||
| 1192 | } | ||
| 1193 | |||
| 1152 | static int __devinit pci_init(void) | 1194 | static int __devinit pci_init(void) |
| 1153 | { | 1195 | { |
| 1154 | struct pci_dev *dev = NULL; | 1196 | struct pci_dev *dev = NULL; |
| @@ -1181,12 +1223,6 @@ early_param("pci", pci_setup); | |||
| 1181 | 1223 | ||
| 1182 | device_initcall(pci_init); | 1224 | device_initcall(pci_init); |
| 1183 | 1225 | ||
| 1184 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | ||
| 1185 | /* FIXME: Some boxes have multiple ISA bridges! */ | ||
| 1186 | struct pci_dev *isa_bridge; | ||
| 1187 | EXPORT_SYMBOL(isa_bridge); | ||
| 1188 | #endif | ||
| 1189 | |||
| 1190 | EXPORT_SYMBOL_GPL(pci_restore_bars); | 1226 | EXPORT_SYMBOL_GPL(pci_restore_bars); |
| 1191 | EXPORT_SYMBOL(pci_enable_device_bars); | 1227 | EXPORT_SYMBOL(pci_enable_device_bars); |
| 1192 | EXPORT_SYMBOL(pci_enable_device); | 1228 | EXPORT_SYMBOL(pci_enable_device); |
| @@ -1197,6 +1233,8 @@ EXPORT_SYMBOL(pci_release_regions); | |||
| 1197 | EXPORT_SYMBOL(pci_request_regions); | 1233 | EXPORT_SYMBOL(pci_request_regions); |
| 1198 | EXPORT_SYMBOL(pci_release_region); | 1234 | EXPORT_SYMBOL(pci_release_region); |
| 1199 | EXPORT_SYMBOL(pci_request_region); | 1235 | EXPORT_SYMBOL(pci_request_region); |
| 1236 | EXPORT_SYMBOL(pci_release_selected_regions); | ||
| 1237 | EXPORT_SYMBOL(pci_request_selected_regions); | ||
| 1200 | EXPORT_SYMBOL(pci_set_master); | 1238 | EXPORT_SYMBOL(pci_set_master); |
| 1201 | EXPORT_SYMBOL(pci_set_mwi); | 1239 | EXPORT_SYMBOL(pci_set_mwi); |
| 1202 | EXPORT_SYMBOL(pci_clear_mwi); | 1240 | EXPORT_SYMBOL(pci_clear_mwi); |
| @@ -1205,13 +1243,10 @@ EXPORT_SYMBOL(pci_set_dma_mask); | |||
| 1205 | EXPORT_SYMBOL(pci_set_consistent_dma_mask); | 1243 | EXPORT_SYMBOL(pci_set_consistent_dma_mask); |
| 1206 | EXPORT_SYMBOL(pci_assign_resource); | 1244 | EXPORT_SYMBOL(pci_assign_resource); |
| 1207 | EXPORT_SYMBOL(pci_find_parent_resource); | 1245 | EXPORT_SYMBOL(pci_find_parent_resource); |
| 1246 | EXPORT_SYMBOL(pci_select_bars); | ||
| 1208 | 1247 | ||
| 1209 | EXPORT_SYMBOL(pci_set_power_state); | 1248 | EXPORT_SYMBOL(pci_set_power_state); |
| 1210 | EXPORT_SYMBOL(pci_save_state); | 1249 | EXPORT_SYMBOL(pci_save_state); |
| 1211 | EXPORT_SYMBOL(pci_restore_state); | 1250 | EXPORT_SYMBOL(pci_restore_state); |
| 1212 | EXPORT_SYMBOL(pci_enable_wake); | 1251 | EXPORT_SYMBOL(pci_enable_wake); |
| 1213 | 1252 | ||
| 1214 | /* Quirk info */ | ||
| 1215 | |||
| 1216 | EXPORT_SYMBOL(isa_dma_bridge_buggy); | ||
| 1217 | EXPORT_SYMBOL(pci_pci_problems); | ||
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 398852f526a6..a4f2d580625e 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* Functions internal to the PCI core code */ | 1 | /* Functions internal to the PCI core code */ |
| 2 | 2 | ||
| 3 | extern int __must_check __pci_enable_device(struct pci_dev *); | 3 | extern int __must_check __pci_reenable_device(struct pci_dev *); |
| 4 | extern int pci_uevent(struct device *dev, char **envp, int num_envp, | 4 | extern int pci_uevent(struct device *dev, char **envp, int num_envp, |
| 5 | char *buffer, int buffer_size); | 5 | char *buffer, int buffer_size); |
| 6 | extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); | 6 | extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); |
| @@ -43,12 +43,8 @@ extern void pci_remove_legacy_files(struct pci_bus *bus); | |||
| 43 | /* Lock for read/write access to pci device and bus lists */ | 43 | /* Lock for read/write access to pci device and bus lists */ |
| 44 | extern struct rw_semaphore pci_bus_sem; | 44 | extern struct rw_semaphore pci_bus_sem; |
| 45 | 45 | ||
| 46 | #ifdef CONFIG_PCI_MSI | ||
| 47 | extern int pci_msi_quirk; | ||
| 48 | #else | ||
| 49 | #define pci_msi_quirk 0 | ||
| 50 | #endif | ||
| 51 | extern unsigned int pci_pm_d3_delay; | 46 | extern unsigned int pci_pm_d3_delay; |
| 47 | |||
| 52 | #ifdef CONFIG_PCI_MSI | 48 | #ifdef CONFIG_PCI_MSI |
| 53 | void disable_msi_mode(struct pci_dev *dev, int pos, int type); | 49 | void disable_msi_mode(struct pci_dev *dev, int pos, int type); |
| 54 | void pci_no_msi(void); | 50 | void pci_no_msi(void); |
| @@ -56,17 +52,15 @@ void pci_no_msi(void); | |||
| 56 | static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { } | 52 | static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { } |
| 57 | static inline void pci_no_msi(void) { } | 53 | static inline void pci_no_msi(void) { } |
| 58 | #endif | 54 | #endif |
| 55 | |||
| 59 | #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM) | 56 | #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM) |
| 60 | int pci_save_msi_state(struct pci_dev *dev); | 57 | int pci_save_msi_state(struct pci_dev *dev); |
| 61 | int pci_save_msix_state(struct pci_dev *dev); | ||
| 62 | void pci_restore_msi_state(struct pci_dev *dev); | 58 | void pci_restore_msi_state(struct pci_dev *dev); |
| 63 | void pci_restore_msix_state(struct pci_dev *dev); | ||
| 64 | #else | 59 | #else |
| 65 | static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; } | 60 | static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; } |
| 66 | static inline int pci_save_msix_state(struct pci_dev *dev) { return 0; } | ||
| 67 | static inline void pci_restore_msi_state(struct pci_dev *dev) {} | 61 | static inline void pci_restore_msi_state(struct pci_dev *dev) {} |
| 68 | static inline void pci_restore_msix_state(struct pci_dev *dev) {} | ||
| 69 | #endif | 62 | #endif |
| 63 | |||
| 70 | static inline int pci_no_d1d2(struct pci_dev *dev) | 64 | static inline int pci_no_d1d2(struct pci_dev *dev) |
| 71 | { | 65 | { |
| 72 | unsigned int parent_dstates = 0; | 66 | unsigned int parent_dstates = 0; |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 0e0401dd02cb..2fe1d690eb13 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -144,6 +144,32 @@ static u32 pci_size(u32 base, u32 maxbase, u32 mask) | |||
| 144 | return size; | 144 | return size; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | static u64 pci_size64(u64 base, u64 maxbase, u64 mask) | ||
| 148 | { | ||
| 149 | u64 size = mask & maxbase; /* Find the significant bits */ | ||
| 150 | if (!size) | ||
| 151 | return 0; | ||
| 152 | |||
| 153 | /* Get the lowest of them to find the decode size, and | ||
| 154 | from that the extent. */ | ||
| 155 | size = (size & ~(size-1)) - 1; | ||
| 156 | |||
| 157 | /* base == maxbase can be valid only if the BAR has | ||
| 158 | already been programmed with all 1s. */ | ||
| 159 | if (base == maxbase && ((base | size) & mask) != mask) | ||
| 160 | return 0; | ||
| 161 | |||
| 162 | return size; | ||
| 163 | } | ||
| 164 | |||
| 165 | static inline int is_64bit_memory(u32 mask) | ||
| 166 | { | ||
| 167 | if ((mask & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == | ||
| 168 | (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) | ||
| 169 | return 1; | ||
| 170 | return 0; | ||
| 171 | } | ||
| 172 | |||
| 147 | static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | 173 | static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) |
| 148 | { | 174 | { |
| 149 | unsigned int pos, reg, next; | 175 | unsigned int pos, reg, next; |
| @@ -151,6 +177,10 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | |||
| 151 | struct resource *res; | 177 | struct resource *res; |
| 152 | 178 | ||
| 153 | for(pos=0; pos<howmany; pos = next) { | 179 | for(pos=0; pos<howmany; pos = next) { |
| 180 | u64 l64; | ||
| 181 | u64 sz64; | ||
| 182 | u32 raw_sz; | ||
| 183 | |||
| 154 | next = pos+1; | 184 | next = pos+1; |
| 155 | res = &dev->resource[pos]; | 185 | res = &dev->resource[pos]; |
| 156 | res->name = pci_name(dev); | 186 | res->name = pci_name(dev); |
| @@ -163,9 +193,16 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | |||
| 163 | continue; | 193 | continue; |
| 164 | if (l == 0xffffffff) | 194 | if (l == 0xffffffff) |
| 165 | l = 0; | 195 | l = 0; |
| 166 | if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) { | 196 | raw_sz = sz; |
| 197 | if ((l & PCI_BASE_ADDRESS_SPACE) == | ||
| 198 | PCI_BASE_ADDRESS_SPACE_MEMORY) { | ||
| 167 | sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK); | 199 | sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK); |
| 168 | if (!sz) | 200 | /* |
| 201 | * For 64bit prefetchable memory sz could be 0, if the | ||
| 202 | * real size is bigger than 4G, so we need to check | ||
| 203 | * szhi for that. | ||
| 204 | */ | ||
| 205 | if (!is_64bit_memory(l) && !sz) | ||
| 169 | continue; | 206 | continue; |
| 170 | res->start = l & PCI_BASE_ADDRESS_MEM_MASK; | 207 | res->start = l & PCI_BASE_ADDRESS_MEM_MASK; |
| 171 | res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK; | 208 | res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK; |
| @@ -178,30 +215,36 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | |||
| 178 | } | 215 | } |
| 179 | res->end = res->start + (unsigned long) sz; | 216 | res->end = res->start + (unsigned long) sz; |
| 180 | res->flags |= pci_calc_resource_flags(l); | 217 | res->flags |= pci_calc_resource_flags(l); |
| 181 | if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) | 218 | if (is_64bit_memory(l)) { |
| 182 | == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { | ||
| 183 | u32 szhi, lhi; | 219 | u32 szhi, lhi; |
| 220 | |||
| 184 | pci_read_config_dword(dev, reg+4, &lhi); | 221 | pci_read_config_dword(dev, reg+4, &lhi); |
| 185 | pci_write_config_dword(dev, reg+4, ~0); | 222 | pci_write_config_dword(dev, reg+4, ~0); |
| 186 | pci_read_config_dword(dev, reg+4, &szhi); | 223 | pci_read_config_dword(dev, reg+4, &szhi); |
| 187 | pci_write_config_dword(dev, reg+4, lhi); | 224 | pci_write_config_dword(dev, reg+4, lhi); |
| 188 | szhi = pci_size(lhi, szhi, 0xffffffff); | 225 | sz64 = ((u64)szhi << 32) | raw_sz; |
| 226 | l64 = ((u64)lhi << 32) | l; | ||
| 227 | sz64 = pci_size64(l64, sz64, PCI_BASE_ADDRESS_MEM_MASK); | ||
| 189 | next++; | 228 | next++; |
| 190 | #if BITS_PER_LONG == 64 | 229 | #if BITS_PER_LONG == 64 |
| 191 | res->start |= ((unsigned long) lhi) << 32; | 230 | if (!sz64) { |
| 192 | res->end = res->start + sz; | 231 | res->start = 0; |
| 193 | if (szhi) { | 232 | res->end = 0; |
| 194 | /* This BAR needs > 4GB? Wow. */ | 233 | res->flags = 0; |
| 195 | res->end |= (unsigned long)szhi<<32; | 234 | continue; |
| 196 | } | 235 | } |
| 236 | res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK; | ||
| 237 | res->end = res->start + sz64; | ||
| 197 | #else | 238 | #else |
| 198 | if (szhi) { | 239 | if (sz64 > 0x100000000ULL) { |
| 199 | printk(KERN_ERR "PCI: Unable to handle 64-bit BAR for device %s\n", pci_name(dev)); | 240 | printk(KERN_ERR "PCI: Unable to handle 64-bit " |
| 241 | "BAR for device %s\n", pci_name(dev)); | ||
| 200 | res->start = 0; | 242 | res->start = 0; |
| 201 | res->flags = 0; | 243 | res->flags = 0; |
| 202 | } else if (lhi) { | 244 | } else if (lhi) { |
| 203 | /* 64-bit wide address, treat as disabled */ | 245 | /* 64-bit wide address, treat as disabled */ |
| 204 | pci_write_config_dword(dev, reg, l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); | 246 | pci_write_config_dword(dev, reg, |
| 247 | l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); | ||
| 205 | pci_write_config_dword(dev, reg+4, 0); | 248 | pci_write_config_dword(dev, reg+4, 0); |
| 206 | res->start = 0; | 249 | res->start = 0; |
| 207 | res->end = sz; | 250 | res->end = sz; |
| @@ -902,7 +945,6 @@ pci_scan_single_device(struct pci_bus *bus, int devfn) | |||
| 902 | return NULL; | 945 | return NULL; |
| 903 | 946 | ||
| 904 | pci_device_add(dev, bus); | 947 | pci_device_add(dev, bus); |
| 905 | pci_scan_msi_device(dev); | ||
| 906 | 948 | ||
| 907 | return dev; | 949 | return dev; |
| 908 | } | 950 | } |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index c913ea4e545c..0d0ba2fad5fc 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -61,7 +61,8 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_p | |||
| 61 | 61 | ||
| 62 | This appears to be BIOS not version dependent. So presumably there is a | 62 | This appears to be BIOS not version dependent. So presumably there is a |
| 63 | chipset level fix */ | 63 | chipset level fix */ |
| 64 | int isa_dma_bridge_buggy; /* Exported */ | 64 | int isa_dma_bridge_buggy; |
| 65 | EXPORT_SYMBOL(isa_dma_bridge_buggy); | ||
| 65 | 66 | ||
| 66 | static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev) | 67 | static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev) |
| 67 | { | 68 | { |
| @@ -83,6 +84,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_d | |||
| 83 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs ); | 84 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs ); |
| 84 | 85 | ||
| 85 | int pci_pci_problems; | 86 | int pci_pci_problems; |
| 87 | EXPORT_SYMBOL(pci_pci_problems); | ||
| 86 | 88 | ||
| 87 | /* | 89 | /* |
| 88 | * Chipsets where PCI->PCI transfers vanish or hang | 90 | * Chipsets where PCI->PCI transfers vanish or hang |
| @@ -94,6 +96,8 @@ static void __devinit quirk_nopcipci(struct pci_dev *dev) | |||
| 94 | pci_pci_problems |= PCIPCI_FAIL; | 96 | pci_pci_problems |= PCIPCI_FAIL; |
| 95 | } | 97 | } |
| 96 | } | 98 | } |
| 99 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci ); | ||
| 100 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci ); | ||
| 97 | 101 | ||
| 98 | static void __devinit quirk_nopciamd(struct pci_dev *dev) | 102 | static void __devinit quirk_nopciamd(struct pci_dev *dev) |
| 99 | { | 103 | { |
| @@ -105,9 +109,6 @@ static void __devinit quirk_nopciamd(struct pci_dev *dev) | |||
| 105 | pci_pci_problems |= PCIAGP_FAIL; | 109 | pci_pci_problems |= PCIAGP_FAIL; |
| 106 | } | 110 | } |
| 107 | } | 111 | } |
| 108 | |||
| 109 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci ); | ||
| 110 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci ); | ||
| 111 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8151_0, quirk_nopciamd ); | 112 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8151_0, quirk_nopciamd ); |
| 112 | 113 | ||
| 113 | /* | 114 | /* |
| @@ -976,52 +977,51 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) | |||
| 976 | case 0x1626: /* L3C notebook */ | 977 | case 0x1626: /* L3C notebook */ |
| 977 | asus_hides_smbus = 1; | 978 | asus_hides_smbus = 1; |
| 978 | } | 979 | } |
| 979 | if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) | 980 | else if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) |
| 980 | switch(dev->subsystem_device) { | 981 | switch(dev->subsystem_device) { |
| 981 | case 0x80b1: /* P4GE-V */ | 982 | case 0x80b1: /* P4GE-V */ |
| 982 | case 0x80b2: /* P4PE */ | 983 | case 0x80b2: /* P4PE */ |
| 983 | case 0x8093: /* P4B533-V */ | 984 | case 0x8093: /* P4B533-V */ |
| 984 | asus_hides_smbus = 1; | 985 | asus_hides_smbus = 1; |
| 985 | } | 986 | } |
| 986 | if (dev->device == PCI_DEVICE_ID_INTEL_82850_HB) | 987 | else if (dev->device == PCI_DEVICE_ID_INTEL_82850_HB) |
| 987 | switch(dev->subsystem_device) { | 988 | switch(dev->subsystem_device) { |
| 988 | case 0x8030: /* P4T533 */ | 989 | case 0x8030: /* P4T533 */ |
| 989 | asus_hides_smbus = 1; | 990 | asus_hides_smbus = 1; |
| 990 | } | 991 | } |
| 991 | if (dev->device == PCI_DEVICE_ID_INTEL_7205_0) | 992 | else if (dev->device == PCI_DEVICE_ID_INTEL_7205_0) |
| 992 | switch (dev->subsystem_device) { | 993 | switch (dev->subsystem_device) { |
| 993 | case 0x8070: /* P4G8X Deluxe */ | 994 | case 0x8070: /* P4G8X Deluxe */ |
| 994 | asus_hides_smbus = 1; | 995 | asus_hides_smbus = 1; |
| 995 | } | 996 | } |
| 996 | if (dev->device == PCI_DEVICE_ID_INTEL_E7501_MCH) | 997 | else if (dev->device == PCI_DEVICE_ID_INTEL_E7501_MCH) |
| 997 | switch (dev->subsystem_device) { | 998 | switch (dev->subsystem_device) { |
| 998 | case 0x80c9: /* PU-DLS */ | 999 | case 0x80c9: /* PU-DLS */ |
| 999 | asus_hides_smbus = 1; | 1000 | asus_hides_smbus = 1; |
| 1000 | } | 1001 | } |
| 1001 | if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) | 1002 | else if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) |
| 1002 | switch (dev->subsystem_device) { | 1003 | switch (dev->subsystem_device) { |
| 1003 | case 0x1751: /* M2N notebook */ | 1004 | case 0x1751: /* M2N notebook */ |
| 1004 | case 0x1821: /* M5N notebook */ | 1005 | case 0x1821: /* M5N notebook */ |
| 1005 | asus_hides_smbus = 1; | 1006 | asus_hides_smbus = 1; |
| 1006 | } | 1007 | } |
| 1007 | if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) | 1008 | else if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) |
| 1008 | switch (dev->subsystem_device) { | 1009 | switch (dev->subsystem_device) { |
| 1009 | case 0x184b: /* W1N notebook */ | 1010 | case 0x184b: /* W1N notebook */ |
| 1010 | case 0x186a: /* M6Ne notebook */ | 1011 | case 0x186a: /* M6Ne notebook */ |
| 1011 | asus_hides_smbus = 1; | 1012 | asus_hides_smbus = 1; |
| 1012 | } | 1013 | } |
| 1013 | if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB) | 1014 | else if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB) |
| 1014 | switch (dev->subsystem_device) { | 1015 | switch (dev->subsystem_device) { |
| 1015 | case 0x80f2: /* P4P800-X */ | 1016 | case 0x80f2: /* P4P800-X */ |
| 1016 | asus_hides_smbus = 1; | 1017 | asus_hides_smbus = 1; |
| 1017 | } | 1018 | } |
| 1018 | if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) { | 1019 | else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) |
| 1019 | switch (dev->subsystem_device) { | 1020 | switch (dev->subsystem_device) { |
| 1020 | case 0x1882: /* M6V notebook */ | 1021 | case 0x1882: /* M6V notebook */ |
| 1021 | case 0x1977: /* A6VA notebook */ | 1022 | case 0x1977: /* A6VA notebook */ |
| 1022 | asus_hides_smbus = 1; | 1023 | asus_hides_smbus = 1; |
| 1023 | } | 1024 | } |
| 1024 | } | ||
| 1025 | } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_HP)) { | 1025 | } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_HP)) { |
| 1026 | if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) | 1026 | if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) |
| 1027 | switch(dev->subsystem_device) { | 1027 | switch(dev->subsystem_device) { |
| @@ -1029,25 +1029,24 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) | |||
| 1029 | case 0x0890: /* HP Compaq nc6000 */ | 1029 | case 0x0890: /* HP Compaq nc6000 */ |
| 1030 | asus_hides_smbus = 1; | 1030 | asus_hides_smbus = 1; |
| 1031 | } | 1031 | } |
| 1032 | if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB) | 1032 | else if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB) |
| 1033 | switch (dev->subsystem_device) { | 1033 | switch (dev->subsystem_device) { |
| 1034 | case 0x12bc: /* HP D330L */ | 1034 | case 0x12bc: /* HP D330L */ |
| 1035 | case 0x12bd: /* HP D530 */ | 1035 | case 0x12bd: /* HP D530 */ |
| 1036 | asus_hides_smbus = 1; | 1036 | asus_hides_smbus = 1; |
| 1037 | } | 1037 | } |
| 1038 | if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) { | 1038 | else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) |
| 1039 | switch (dev->subsystem_device) { | 1039 | switch (dev->subsystem_device) { |
| 1040 | case 0x099c: /* HP Compaq nx6110 */ | 1040 | case 0x099c: /* HP Compaq nx6110 */ |
| 1041 | asus_hides_smbus = 1; | 1041 | asus_hides_smbus = 1; |
| 1042 | } | 1042 | } |
| 1043 | } | ||
| 1044 | } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) { | 1043 | } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) { |
| 1045 | if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) | 1044 | if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) |
| 1046 | switch(dev->subsystem_device) { | 1045 | switch(dev->subsystem_device) { |
| 1047 | case 0x0001: /* Toshiba Satellite A40 */ | 1046 | case 0x0001: /* Toshiba Satellite A40 */ |
| 1048 | asus_hides_smbus = 1; | 1047 | asus_hides_smbus = 1; |
| 1049 | } | 1048 | } |
| 1050 | if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) | 1049 | else if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) |
| 1051 | switch(dev->subsystem_device) { | 1050 | switch(dev->subsystem_device) { |
| 1052 | case 0x0001: /* Toshiba Tecra M2 */ | 1051 | case 0x0001: /* Toshiba Tecra M2 */ |
| 1053 | asus_hides_smbus = 1; | 1052 | asus_hides_smbus = 1; |
| @@ -1136,6 +1135,14 @@ static void quirk_sis_96x_smbus(struct pci_dev *dev) | |||
| 1136 | pci_write_config_byte(dev, 0x77, val & ~0x10); | 1135 | pci_write_config_byte(dev, 0x77, val & ~0x10); |
| 1137 | } | 1136 | } |
| 1138 | } | 1137 | } |
| 1138 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); | ||
| 1139 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); | ||
| 1140 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); | ||
| 1141 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); | ||
| 1142 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); | ||
| 1143 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); | ||
| 1144 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); | ||
| 1145 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); | ||
| 1139 | 1146 | ||
| 1140 | /* | 1147 | /* |
| 1141 | * ... This is further complicated by the fact that some SiS96x south | 1148 | * ... This is further complicated by the fact that some SiS96x south |
| @@ -1145,8 +1152,6 @@ static void quirk_sis_96x_smbus(struct pci_dev *dev) | |||
| 1145 | * | 1152 | * |
| 1146 | * We can also enable the sis96x bit in the discovery register.. | 1153 | * We can also enable the sis96x bit in the discovery register.. |
| 1147 | */ | 1154 | */ |
| 1148 | static int __devinitdata sis_96x_compatible = 0; | ||
| 1149 | |||
| 1150 | #define SIS_DETECT_REGISTER 0x40 | 1155 | #define SIS_DETECT_REGISTER 0x40 |
| 1151 | 1156 | ||
| 1152 | static void quirk_sis_503(struct pci_dev *dev) | 1157 | static void quirk_sis_503(struct pci_dev *dev) |
| @@ -1162,9 +1167,6 @@ static void quirk_sis_503(struct pci_dev *dev) | |||
| 1162 | return; | 1167 | return; |
| 1163 | } | 1168 | } |
| 1164 | 1169 | ||
| 1165 | /* Make people aware that we changed the config.. */ | ||
| 1166 | printk(KERN_WARNING "Uncovering SIS%x that hid as a SIS503 (compatible=%d)\n", devid, sis_96x_compatible); | ||
| 1167 | |||
| 1168 | /* | 1170 | /* |
| 1169 | * Ok, it now shows up as a 96x.. run the 96x quirk by | 1171 | * Ok, it now shows up as a 96x.. run the 96x quirk by |
| 1170 | * hand in case it has already been processed. | 1172 | * hand in case it has already been processed. |
| @@ -1173,20 +1175,10 @@ static void quirk_sis_503(struct pci_dev *dev) | |||
| 1173 | dev->device = devid; | 1175 | dev->device = devid; |
| 1174 | quirk_sis_96x_smbus(dev); | 1176 | quirk_sis_96x_smbus(dev); |
| 1175 | } | 1177 | } |
| 1176 | |||
| 1177 | static void __init quirk_sis_96x_compatible(struct pci_dev *dev) | ||
| 1178 | { | ||
| 1179 | sis_96x_compatible = 1; | ||
| 1180 | } | ||
| 1181 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_645, quirk_sis_96x_compatible ); | ||
| 1182 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_646, quirk_sis_96x_compatible ); | ||
| 1183 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_648, quirk_sis_96x_compatible ); | ||
| 1184 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650, quirk_sis_96x_compatible ); | ||
| 1185 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_compatible ); | ||
| 1186 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible ); | ||
| 1187 | |||
| 1188 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); | 1178 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); |
| 1189 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); | 1179 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); |
| 1180 | |||
| 1181 | |||
| 1190 | /* | 1182 | /* |
| 1191 | * On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller | 1183 | * On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller |
| 1192 | * and MC97 modem controller are disabled when a second PCI soundcard is | 1184 | * and MC97 modem controller are disabled when a second PCI soundcard is |
| @@ -1217,21 +1209,8 @@ static void asus_hides_ac97_lpc(struct pci_dev *dev) | |||
| 1217 | } | 1209 | } |
| 1218 | } | 1210 | } |
| 1219 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc ); | 1211 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc ); |
| 1220 | |||
| 1221 | |||
| 1222 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); | ||
| 1223 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); | ||
| 1224 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); | ||
| 1225 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); | ||
| 1226 | |||
| 1227 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc ); | 1212 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc ); |
| 1228 | 1213 | ||
| 1229 | |||
| 1230 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); | ||
| 1231 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); | ||
| 1232 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); | ||
| 1233 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); | ||
| 1234 | |||
| 1235 | #if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE) | 1214 | #if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE) |
| 1236 | 1215 | ||
| 1237 | /* | 1216 | /* |
| @@ -1276,7 +1255,6 @@ static void quirk_jmicron_dualfn(struct pci_dev *pdev) | |||
| 1276 | break; | 1255 | break; |
| 1277 | } | 1256 | } |
| 1278 | } | 1257 | } |
| 1279 | |||
| 1280 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); | 1258 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); |
| 1281 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); | 1259 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); |
| 1282 | 1260 | ||
| @@ -1420,6 +1398,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_co | |||
| 1420 | 1398 | ||
| 1421 | 1399 | ||
| 1422 | int pcie_mch_quirk; | 1400 | int pcie_mch_quirk; |
| 1401 | EXPORT_SYMBOL(pcie_mch_quirk); | ||
| 1423 | 1402 | ||
| 1424 | static void __devinit quirk_pcie_mch(struct pci_dev *pdev) | 1403 | static void __devinit quirk_pcie_mch(struct pci_dev *pdev) |
| 1425 | { | 1404 | { |
| @@ -1646,6 +1625,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) | |||
| 1646 | } | 1625 | } |
| 1647 | pci_do_fixups(dev, start, end); | 1626 | pci_do_fixups(dev, start, end); |
| 1648 | } | 1627 | } |
| 1628 | EXPORT_SYMBOL(pci_fixup_device); | ||
| 1649 | 1629 | ||
| 1650 | /* Enable 1k I/O space granularity on the Intel P64H2 */ | 1630 | /* Enable 1k I/O space granularity on the Intel P64H2 */ |
| 1651 | static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) | 1631 | static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) |
| @@ -1673,6 +1653,31 @@ static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) | |||
| 1673 | } | 1653 | } |
| 1674 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); | 1654 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); |
| 1675 | 1655 | ||
| 1656 | /* Fix the IOBL_ADR for 1k I/O space granularity on the Intel P64H2 | ||
| 1657 | * The IOBL_ADR gets re-written to 4k boundaries in pci_setup_bridge() | ||
| 1658 | * in drivers/pci/setup-bus.c | ||
| 1659 | */ | ||
| 1660 | static void __devinit quirk_p64h2_1k_io_fix_iobl(struct pci_dev *dev) | ||
| 1661 | { | ||
| 1662 | u16 en1k, iobl_adr, iobl_adr_1k; | ||
| 1663 | struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES; | ||
| 1664 | |||
| 1665 | pci_read_config_word(dev, 0x40, &en1k); | ||
| 1666 | |||
| 1667 | if (en1k & 0x200) { | ||
| 1668 | pci_read_config_word(dev, PCI_IO_BASE, &iobl_adr); | ||
| 1669 | |||
| 1670 | iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00); | ||
| 1671 | |||
| 1672 | if (iobl_adr != iobl_adr_1k) { | ||
| 1673 | printk(KERN_INFO "PCI: Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1 KB Granularity\n", | ||
| 1674 | iobl_adr,iobl_adr_1k); | ||
| 1675 | pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k); | ||
| 1676 | } | ||
| 1677 | } | ||
| 1678 | } | ||
| 1679 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io_fix_iobl); | ||
| 1680 | |||
| 1676 | /* Under some circumstances, AER is not linked with extended capabilities. | 1681 | /* Under some circumstances, AER is not linked with extended capabilities. |
| 1677 | * Force it to be linked by setting the corresponding control bit in the | 1682 | * Force it to be linked by setting the corresponding control bit in the |
| 1678 | * config space. | 1683 | * config space. |
| @@ -1695,9 +1700,6 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, | |||
| 1695 | quirk_nvidia_ck804_pcie_aer_ext_cap); | 1700 | quirk_nvidia_ck804_pcie_aer_ext_cap); |
| 1696 | 1701 | ||
| 1697 | #ifdef CONFIG_PCI_MSI | 1702 | #ifdef CONFIG_PCI_MSI |
| 1698 | /* To disable MSI globally */ | ||
| 1699 | int pci_msi_quirk; | ||
| 1700 | |||
| 1701 | /* The Serverworks PCI-X chipset does not support MSI. We cannot easily rely | 1703 | /* The Serverworks PCI-X chipset does not support MSI. We cannot easily rely |
| 1702 | * on setting PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually | 1704 | * on setting PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually |
| 1703 | * some other busses controlled by the chipset even if Linux is not aware of it. | 1705 | * some other busses controlled by the chipset even if Linux is not aware of it. |
| @@ -1706,8 +1708,8 @@ int pci_msi_quirk; | |||
| 1706 | */ | 1708 | */ |
| 1707 | static void __init quirk_svw_msi(struct pci_dev *dev) | 1709 | static void __init quirk_svw_msi(struct pci_dev *dev) |
| 1708 | { | 1710 | { |
| 1709 | pci_msi_quirk = 1; | 1711 | pci_no_msi(); |
| 1710 | printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n"); | 1712 | printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n"); |
| 1711 | } | 1713 | } |
| 1712 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi); | 1714 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi); |
| 1713 | 1715 | ||
| @@ -1788,8 +1790,3 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) | |||
| 1788 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, | 1790 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, |
| 1789 | quirk_nvidia_ck804_msi_ht_cap); | 1791 | quirk_nvidia_ck804_msi_ht_cap); |
| 1790 | #endif /* CONFIG_PCI_MSI */ | 1792 | #endif /* CONFIG_PCI_MSI */ |
| 1791 | |||
| 1792 | EXPORT_SYMBOL(pcie_mch_quirk); | ||
| 1793 | #ifdef CONFIG_HOTPLUG | ||
| 1794 | EXPORT_SYMBOL(pci_fixup_device); | ||
| 1795 | #endif | ||
diff --git a/drivers/pci/search.c b/drivers/pci/search.c index b2653c4afe9e..ff98eaddaa73 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c | |||
| @@ -358,43 +358,6 @@ exit: | |||
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | /** | 360 | /** |
| 361 | * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id | ||
| 362 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids | ||
| 363 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids | ||
| 364 | * @from: Previous PCI device found in search, or %NULL for new search. | ||
| 365 | * | ||
| 366 | * Iterates through the list of known PCI devices in the reverse order of | ||
| 367 | * pci_find_device(). | ||
| 368 | * If a PCI device is found with a matching @vendor and @device, a pointer to | ||
| 369 | * its device structure is returned. Otherwise, %NULL is returned. | ||
| 370 | * A new search is initiated by passing %NULL as the @from argument. | ||
| 371 | * Otherwise if @from is not %NULL, searches continue from previous device | ||
| 372 | * on the global list. | ||
| 373 | */ | ||
| 374 | struct pci_dev * | ||
| 375 | pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from) | ||
| 376 | { | ||
| 377 | struct list_head *n; | ||
| 378 | struct pci_dev *dev; | ||
| 379 | |||
| 380 | WARN_ON(in_interrupt()); | ||
| 381 | down_read(&pci_bus_sem); | ||
| 382 | n = from ? from->global_list.prev : pci_devices.prev; | ||
| 383 | |||
| 384 | while (n && (n != &pci_devices)) { | ||
| 385 | dev = pci_dev_g(n); | ||
| 386 | if ((vendor == PCI_ANY_ID || dev->vendor == vendor) && | ||
| 387 | (device == PCI_ANY_ID || dev->device == device)) | ||
| 388 | goto exit; | ||
| 389 | n = n->prev; | ||
| 390 | } | ||
| 391 | dev = NULL; | ||
| 392 | exit: | ||
| 393 | up_read(&pci_bus_sem); | ||
| 394 | return dev; | ||
| 395 | } | ||
| 396 | |||
| 397 | /** | ||
| 398 | * pci_get_class - begin or continue searching for a PCI device by class | 361 | * pci_get_class - begin or continue searching for a PCI device by class |
| 399 | * @class: search for a PCI device with this class designation | 362 | * @class: search for a PCI device with this class designation |
| 400 | * @from: Previous PCI device found in search, or %NULL for new search. | 363 | * @from: Previous PCI device found in search, or %NULL for new search. |
| @@ -469,7 +432,6 @@ EXPORT_SYMBOL(pci_dev_present); | |||
| 469 | EXPORT_SYMBOL(pci_find_present); | 432 | EXPORT_SYMBOL(pci_find_present); |
| 470 | 433 | ||
| 471 | EXPORT_SYMBOL(pci_find_device); | 434 | EXPORT_SYMBOL(pci_find_device); |
| 472 | EXPORT_SYMBOL(pci_find_device_reverse); | ||
| 473 | EXPORT_SYMBOL(pci_find_slot); | 435 | EXPORT_SYMBOL(pci_find_slot); |
| 474 | /* For boot time work */ | 436 | /* For boot time work */ |
| 475 | EXPORT_SYMBOL(pci_find_bus); | 437 | EXPORT_SYMBOL(pci_find_bus); |
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index b318500785e5..821386c7b576 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
| @@ -7558,9 +7558,6 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { | |||
| 7558 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, | 7558 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, |
| 7559 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, | 7559 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, |
| 7560 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | 7560 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, |
| 7561 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, | ||
| 7562 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B8, | ||
| 7563 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | ||
| 7564 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, | 7561 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, |
| 7565 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, | 7562 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, |
| 7566 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | 7563 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, |
diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h index 4e115f368d5f..85aa1127c903 100644 --- a/include/asm-alpha/pci.h +++ b/include/asm-alpha/pci.h | |||
| @@ -293,4 +293,6 @@ struct pci_dev *alpha_gendev_to_pci(struct device *dev); | |||
| 293 | #define IOBASE_ROOT_BUS 5 | 293 | #define IOBASE_ROOT_BUS 5 |
| 294 | #define IOBASE_FROM_HOSE 0x10000 | 294 | #define IOBASE_FROM_HOSE 0x10000 |
| 295 | 295 | ||
| 296 | extern struct pci_dev *isa_bridge; | ||
| 297 | |||
| 296 | #endif /* __ALPHA_PCI_H */ | 298 | #endif /* __ALPHA_PCI_H */ |
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h index a3891eb3f217..3c96ac19154e 100644 --- a/include/asm-ia64/machvec.h +++ b/include/asm-ia64/machvec.h | |||
| @@ -21,6 +21,7 @@ struct mm_struct; | |||
| 21 | struct pci_bus; | 21 | struct pci_bus; |
| 22 | struct task_struct; | 22 | struct task_struct; |
| 23 | struct pci_dev; | 23 | struct pci_dev; |
| 24 | struct msi_desc; | ||
| 24 | 25 | ||
| 25 | typedef void ia64_mv_setup_t (char **); | 26 | typedef void ia64_mv_setup_t (char **); |
| 26 | typedef void ia64_mv_cpu_init_t (void); | 27 | typedef void ia64_mv_cpu_init_t (void); |
| @@ -79,7 +80,7 @@ typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *); | |||
| 79 | typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *); | 80 | typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *); |
| 80 | typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *); | 81 | typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *); |
| 81 | 82 | ||
| 82 | typedef int ia64_mv_setup_msi_irq_t (unsigned int irq, struct pci_dev *pdev); | 83 | typedef int ia64_mv_setup_msi_irq_t (struct pci_dev *pdev, struct msi_desc *); |
| 83 | typedef void ia64_mv_teardown_msi_irq_t (unsigned int irq); | 84 | typedef void ia64_mv_teardown_msi_irq_t (unsigned int irq); |
| 84 | 85 | ||
| 85 | static inline void | 86 | static inline void |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 52fc4052a0ae..5504b671357f 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
| @@ -68,6 +68,7 @@ typedef void fastcall (*irq_flow_handler_t)(unsigned int irq, | |||
| 68 | #define IRQ_MOVE_PENDING 0x40000000 /* need to re-target IRQ destination */ | 68 | #define IRQ_MOVE_PENDING 0x40000000 /* need to re-target IRQ destination */ |
| 69 | 69 | ||
| 70 | struct proc_dir_entry; | 70 | struct proc_dir_entry; |
| 71 | struct msi_desc; | ||
| 71 | 72 | ||
| 72 | /** | 73 | /** |
| 73 | * struct irq_chip - hardware interrupt chip descriptor | 74 | * struct irq_chip - hardware interrupt chip descriptor |
| @@ -148,6 +149,7 @@ struct irq_chip { | |||
| 148 | struct irq_desc { | 149 | struct irq_desc { |
| 149 | irq_flow_handler_t handle_irq; | 150 | irq_flow_handler_t handle_irq; |
| 150 | struct irq_chip *chip; | 151 | struct irq_chip *chip; |
| 152 | struct msi_desc *msi_desc; | ||
| 151 | void *handler_data; | 153 | void *handler_data; |
| 152 | void *chip_data; | 154 | void *chip_data; |
| 153 | struct irqaction *action; /* IRQ action list */ | 155 | struct irqaction *action; /* IRQ action list */ |
| @@ -373,10 +375,12 @@ extern int set_irq_chip(unsigned int irq, struct irq_chip *chip); | |||
| 373 | extern int set_irq_data(unsigned int irq, void *data); | 375 | extern int set_irq_data(unsigned int irq, void *data); |
| 374 | extern int set_irq_chip_data(unsigned int irq, void *data); | 376 | extern int set_irq_chip_data(unsigned int irq, void *data); |
| 375 | extern int set_irq_type(unsigned int irq, unsigned int type); | 377 | extern int set_irq_type(unsigned int irq, unsigned int type); |
| 378 | extern int set_irq_msi(unsigned int irq, struct msi_desc *entry); | ||
| 376 | 379 | ||
| 377 | #define get_irq_chip(irq) (irq_desc[irq].chip) | 380 | #define get_irq_chip(irq) (irq_desc[irq].chip) |
| 378 | #define get_irq_chip_data(irq) (irq_desc[irq].chip_data) | 381 | #define get_irq_chip_data(irq) (irq_desc[irq].chip_data) |
| 379 | #define get_irq_data(irq) (irq_desc[irq].handler_data) | 382 | #define get_irq_data(irq) (irq_desc[irq].handler_data) |
| 383 | #define get_irq_msi(irq) (irq_desc[irq].msi_desc) | ||
| 380 | 384 | ||
| 381 | #endif /* CONFIG_GENERIC_HARDIRQS */ | 385 | #endif /* CONFIG_GENERIC_HARDIRQS */ |
| 382 | 386 | ||
diff --git a/include/linux/msi.h b/include/linux/msi.h index c7ef94343673..74c8a2ecc9dd 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h | |||
| @@ -7,11 +7,10 @@ struct msi_msg { | |||
| 7 | u32 data; /* 16 bits of msi message data */ | 7 | u32 data; /* 16 bits of msi message data */ |
| 8 | }; | 8 | }; |
| 9 | 9 | ||
| 10 | /* Heper functions */ | 10 | /* Helper functions */ |
| 11 | extern void mask_msi_irq(unsigned int irq); | 11 | extern void mask_msi_irq(unsigned int irq); |
| 12 | extern void unmask_msi_irq(unsigned int irq); | 12 | extern void unmask_msi_irq(unsigned int irq); |
| 13 | extern void read_msi_msg(unsigned int irq, struct msi_msg *msg); | 13 | extern void read_msi_msg(unsigned int irq, struct msi_msg *msg); |
| 14 | |||
| 15 | extern void write_msi_msg(unsigned int irq, struct msi_msg *msg); | 14 | extern void write_msi_msg(unsigned int irq, struct msi_msg *msg); |
| 16 | 15 | ||
| 17 | struct msi_desc { | 16 | struct msi_desc { |
| @@ -42,7 +41,7 @@ struct msi_desc { | |||
| 42 | /* | 41 | /* |
| 43 | * The arch hook for setup up msi irqs | 42 | * The arch hook for setup up msi irqs |
| 44 | */ | 43 | */ |
| 45 | int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev); | 44 | int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc); |
| 46 | void arch_teardown_msi_irq(unsigned int irq); | 45 | void arch_teardown_msi_irq(unsigned int irq); |
| 47 | 46 | ||
| 48 | 47 | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index cb899eb95d31..805412cc6875 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -174,6 +174,9 @@ struct pci_dev { | |||
| 174 | struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */ | 174 | struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */ |
| 175 | int rom_attr_enabled; /* has display of the rom attribute been enabled? */ | 175 | int rom_attr_enabled; /* has display of the rom attribute been enabled? */ |
| 176 | struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ | 176 | struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ |
| 177 | #ifdef CONFIG_PCI_MSI | ||
| 178 | unsigned int first_msi_irq; | ||
| 179 | #endif | ||
| 177 | }; | 180 | }; |
| 178 | 181 | ||
| 179 | #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list) | 182 | #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list) |
| @@ -181,6 +184,11 @@ struct pci_dev { | |||
| 181 | #define to_pci_dev(n) container_of(n, struct pci_dev, dev) | 184 | #define to_pci_dev(n) container_of(n, struct pci_dev, dev) |
| 182 | #define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL) | 185 | #define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL) |
| 183 | 186 | ||
| 187 | static inline int pci_channel_offline(struct pci_dev *pdev) | ||
| 188 | { | ||
| 189 | return (pdev->error_state != pci_channel_io_normal); | ||
| 190 | } | ||
| 191 | |||
| 184 | static inline struct pci_cap_saved_state *pci_find_saved_cap( | 192 | static inline struct pci_cap_saved_state *pci_find_saved_cap( |
| 185 | struct pci_dev *pci_dev,char cap) | 193 | struct pci_dev *pci_dev,char cap) |
| 186 | { | 194 | { |
| @@ -463,8 +471,7 @@ extern void pci_sort_breadthfirst(void); | |||
| 463 | 471 | ||
| 464 | /* Generic PCI functions exported to card drivers */ | 472 | /* Generic PCI functions exported to card drivers */ |
| 465 | 473 | ||
| 466 | struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from); | 474 | struct pci_dev __deprecated *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from); |
| 467 | struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int device, const struct pci_dev *from); | ||
| 468 | struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); | 475 | struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); |
| 469 | int pci_find_capability (struct pci_dev *dev, int cap); | 476 | int pci_find_capability (struct pci_dev *dev, int cap); |
| 470 | int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap); | 477 | int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap); |
| @@ -533,6 +540,7 @@ void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); | |||
| 533 | int __must_check pci_assign_resource(struct pci_dev *dev, int i); | 540 | int __must_check pci_assign_resource(struct pci_dev *dev, int i); |
| 534 | int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i); | 541 | int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i); |
| 535 | void pci_restore_bars(struct pci_dev *dev); | 542 | void pci_restore_bars(struct pci_dev *dev); |
| 543 | int pci_select_bars(struct pci_dev *dev, unsigned long flags); | ||
| 536 | 544 | ||
| 537 | /* ROM control related routines */ | 545 | /* ROM control related routines */ |
| 538 | void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size); | 546 | void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size); |
| @@ -561,6 +569,8 @@ int __must_check pci_request_regions(struct pci_dev *, const char *); | |||
| 561 | void pci_release_regions(struct pci_dev *); | 569 | void pci_release_regions(struct pci_dev *); |
| 562 | int __must_check pci_request_region(struct pci_dev *, int, const char *); | 570 | int __must_check pci_request_region(struct pci_dev *, int, const char *); |
| 563 | void pci_release_region(struct pci_dev *, int); | 571 | void pci_release_region(struct pci_dev *, int); |
| 572 | int pci_request_selected_regions(struct pci_dev *, int, const char *); | ||
| 573 | void pci_release_selected_regions(struct pci_dev *, int); | ||
| 564 | 574 | ||
| 565 | /* drivers/pci/bus.c */ | 575 | /* drivers/pci/bus.c */ |
| 566 | int __must_check pci_bus_alloc_resource(struct pci_bus *bus, | 576 | int __must_check pci_bus_alloc_resource(struct pci_bus *bus, |
| @@ -612,10 +622,6 @@ enum pci_dma_burst_strategy { | |||
| 612 | strategy_parameter byte boundaries */ | 622 | strategy_parameter byte boundaries */ |
| 613 | }; | 623 | }; |
| 614 | 624 | ||
| 615 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | ||
| 616 | extern struct pci_dev *isa_bridge; | ||
| 617 | #endif | ||
| 618 | |||
| 619 | struct msix_entry { | 625 | struct msix_entry { |
| 620 | u16 vector; /* kernel uses to write allocated vector */ | 626 | u16 vector; /* kernel uses to write allocated vector */ |
| 621 | u16 entry; /* driver uses to specify entry, OS writes */ | 627 | u16 entry; /* driver uses to specify entry, OS writes */ |
| @@ -623,7 +629,6 @@ struct msix_entry { | |||
| 623 | 629 | ||
| 624 | 630 | ||
| 625 | #ifndef CONFIG_PCI_MSI | 631 | #ifndef CONFIG_PCI_MSI |
| 626 | static inline void pci_scan_msi_device(struct pci_dev *dev) {} | ||
| 627 | static inline int pci_enable_msi(struct pci_dev *dev) {return -1;} | 632 | static inline int pci_enable_msi(struct pci_dev *dev) {return -1;} |
| 628 | static inline void pci_disable_msi(struct pci_dev *dev) {} | 633 | static inline void pci_disable_msi(struct pci_dev *dev) {} |
| 629 | static inline int pci_enable_msix(struct pci_dev* dev, | 634 | static inline int pci_enable_msix(struct pci_dev* dev, |
| @@ -631,7 +636,6 @@ static inline int pci_enable_msix(struct pci_dev* dev, | |||
| 631 | static inline void pci_disable_msix(struct pci_dev *dev) {} | 636 | static inline void pci_disable_msix(struct pci_dev *dev) {} |
| 632 | static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {} | 637 | static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {} |
| 633 | #else | 638 | #else |
| 634 | extern void pci_scan_msi_device(struct pci_dev *dev); | ||
| 635 | extern int pci_enable_msi(struct pci_dev *dev); | 639 | extern int pci_enable_msi(struct pci_dev *dev); |
| 636 | extern void pci_disable_msi(struct pci_dev *dev); | 640 | extern void pci_disable_msi(struct pci_dev *dev); |
| 637 | extern int pci_enable_msix(struct pci_dev* dev, | 641 | extern int pci_enable_msix(struct pci_dev* dev, |
| @@ -723,8 +727,6 @@ static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { | |||
| 723 | static inline pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { return PCI_D0; } | 727 | static inline pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { return PCI_D0; } |
| 724 | static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { return 0; } | 728 | static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { return 0; } |
| 725 | 729 | ||
| 726 | #define isa_bridge ((struct pci_dev *)NULL) | ||
| 727 | |||
| 728 | #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0) | 730 | #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0) |
| 729 | 731 | ||
| 730 | static inline void pci_block_user_cfg_access(struct pci_dev *dev) { } | 732 | static inline void pci_block_user_cfg_access(struct pci_dev *dev) { } |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index d27b25855743..475e8a71bcdc 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
| @@ -39,6 +39,7 @@ void dynamic_irq_init(unsigned int irq) | |||
| 39 | desc->chip = &no_irq_chip; | 39 | desc->chip = &no_irq_chip; |
| 40 | desc->handle_irq = handle_bad_irq; | 40 | desc->handle_irq = handle_bad_irq; |
| 41 | desc->depth = 1; | 41 | desc->depth = 1; |
| 42 | desc->msi_desc = NULL; | ||
| 42 | desc->handler_data = NULL; | 43 | desc->handler_data = NULL; |
| 43 | desc->chip_data = NULL; | 44 | desc->chip_data = NULL; |
| 44 | desc->action = NULL; | 45 | desc->action = NULL; |
| @@ -74,6 +75,9 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
| 74 | WARN_ON(1); | 75 | WARN_ON(1); |
| 75 | return; | 76 | return; |
| 76 | } | 77 | } |
| 78 | desc->msi_desc = NULL; | ||
| 79 | desc->handler_data = NULL; | ||
| 80 | desc->chip_data = NULL; | ||
| 77 | desc->handle_irq = handle_bad_irq; | 81 | desc->handle_irq = handle_bad_irq; |
| 78 | desc->chip = &no_irq_chip; | 82 | desc->chip = &no_irq_chip; |
| 79 | spin_unlock_irqrestore(&desc->lock, flags); | 83 | spin_unlock_irqrestore(&desc->lock, flags); |
| @@ -162,6 +166,30 @@ int set_irq_data(unsigned int irq, void *data) | |||
| 162 | EXPORT_SYMBOL(set_irq_data); | 166 | EXPORT_SYMBOL(set_irq_data); |
| 163 | 167 | ||
| 164 | /** | 168 | /** |
| 169 | * set_irq_data - set irq type data for an irq | ||
| 170 | * @irq: Interrupt number | ||
| 171 | * @data: Pointer to interrupt specific data | ||
| 172 | * | ||
| 173 | * Set the hardware irq controller data for an irq | ||
| 174 | */ | ||
| 175 | int set_irq_msi(unsigned int irq, struct msi_desc *entry) | ||
| 176 | { | ||
| 177 | struct irq_desc *desc; | ||
| 178 | unsigned long flags; | ||
| 179 | |||
| 180 | if (irq >= NR_IRQS) { | ||
| 181 | printk(KERN_ERR | ||
| 182 | "Trying to install msi data for IRQ%d\n", irq); | ||
| 183 | return -EINVAL; | ||
| 184 | } | ||
| 185 | desc = irq_desc + irq; | ||
| 186 | spin_lock_irqsave(&desc->lock, flags); | ||
| 187 | desc->msi_desc = entry; | ||
| 188 | spin_unlock_irqrestore(&desc->lock, flags); | ||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | /** | ||
| 165 | * set_irq_chip_data - set irq chip data for an irq | 193 | * set_irq_chip_data - set irq chip data for an irq |
| 166 | * @irq: Interrupt number | 194 | * @irq: Interrupt number |
| 167 | * @data: Pointer to chip specific data | 195 | * @data: Pointer to chip specific data |
