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 |