aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/io_apic.c17
-rw-r--r--arch/ia64/kernel/msi_ia64.c19
-rw-r--r--arch/ia64/sn/kernel/msi_sn.c20
-rw-r--r--arch/x86_64/kernel/io_apic.c17
-rw-r--r--drivers/pci/msi.c80
-rw-r--r--include/asm-ia64/machvec.h3
-rw-r--r--include/linux/msi.h2
7 files changed, 75 insertions, 83 deletions
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
2609int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev) 2609int 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
2625void arch_teardown_msi_irq(unsigned int irq) 2632void 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
67int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) 67int 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
95void ia64_teardown_msi_irq(unsigned int irq) 100void ia64_teardown_msi_irq(unsigned int irq)
96{ 101{
97 return; /* no-op */ 102 destroy_irq(irq);
98} 103}
99 104
100static void ia64_ack_msi_irq(unsigned int irq) 105static 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
129int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) 134int 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
137void arch_teardown_msi_irq(unsigned int irq) 142void 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 31fbb859b67e..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
65int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) 65int 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_msi(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/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
1959int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev) 1959int 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
1974void arch_teardown_msi_irq(unsigned int irq) 1981void 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/pci/msi.c b/drivers/pci/msi.c
index 52c253c5ad3d..68555c11f556 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -192,37 +192,6 @@ static struct msi_desc* alloc_msi_entry(void)
192 return entry; 192 return entry;
193} 193}
194 194
195static int create_msi_irq(void)
196{
197 struct msi_desc *entry;
198 int irq;
199
200 entry = alloc_msi_entry();
201 if (!entry)
202 return -ENOMEM;
203
204 irq = create_irq();
205 if (irq < 0) {
206 kmem_cache_free(msi_cachep, entry);
207 return -EBUSY;
208 }
209
210 set_irq_msi(irq, entry);
211
212 return irq;
213}
214
215static void destroy_msi_irq(unsigned int irq)
216{
217 struct msi_desc *entry;
218
219 entry = get_irq_msi(irq);
220 set_irq_chip(irq, NULL);
221 set_irq_msi(irq, NULL);
222 destroy_irq(irq);
223 kmem_cache_free(msi_cachep, entry);
224}
225
226static void enable_msi_mode(struct pci_dev *dev, int pos, int type) 195static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
227{ 196{
228 u16 control; 197 u16 control;
@@ -438,7 +407,6 @@ void pci_restore_msi_state(struct pci_dev *dev)
438 **/ 407 **/
439static int msi_capability_init(struct pci_dev *dev) 408static int msi_capability_init(struct pci_dev *dev)
440{ 409{
441 int status;
442 struct msi_desc *entry; 410 struct msi_desc *entry;
443 int pos, irq; 411 int pos, irq;
444 u16 control; 412 u16 control;
@@ -446,13 +414,10 @@ static int msi_capability_init(struct pci_dev *dev)
446 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 414 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
447 pci_read_config_word(dev, msi_control_reg(pos), &control); 415 pci_read_config_word(dev, msi_control_reg(pos), &control);
448 /* MSI Entry Initialization */ 416 /* MSI Entry Initialization */
449 irq = create_msi_irq(); 417 entry = alloc_msi_entry();
450 if (irq < 0) 418 if (!entry)
451 return irq; 419 return -ENOMEM;
452 420
453 entry = get_irq_msi(irq);
454 entry->link.head = irq;
455 entry->link.tail = irq;
456 entry->msi_attrib.type = PCI_CAP_ID_MSI; 421 entry->msi_attrib.type = PCI_CAP_ID_MSI;
457 entry->msi_attrib.is_64 = is_64bit_address(control); 422 entry->msi_attrib.is_64 = is_64bit_address(control);
458 entry->msi_attrib.entry_nr = 0; 423 entry->msi_attrib.entry_nr = 0;
@@ -478,14 +443,16 @@ static int msi_capability_init(struct pci_dev *dev)
478 maskbits); 443 maskbits);
479 } 444 }
480 /* Configure MSI capability structure */ 445 /* Configure MSI capability structure */
481 status = arch_setup_msi_irq(irq, dev); 446 irq = arch_setup_msi_irq(dev, entry);
482 if (status < 0) { 447 if (irq < 0) {
483 destroy_msi_irq(irq); 448 kmem_cache_free(msi_cachep, entry);
484 return status; 449 return irq;
485 } 450 }
486 451 entry->link.head = irq;
452 entry->link.tail = irq;
487 dev->first_msi_irq = irq; 453 dev->first_msi_irq = irq;
488 set_irq_msi(irq, entry); 454 set_irq_msi(irq, entry);
455
489 /* Set MSI enabled bits */ 456 /* Set MSI enabled bits */
490 enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); 457 enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
491 458
@@ -507,7 +474,6 @@ static int msix_capability_init(struct pci_dev *dev,
507 struct msix_entry *entries, int nvec) 474 struct msix_entry *entries, int nvec)
508{ 475{
509 struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; 476 struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
510 int status;
511 int irq, pos, i, j, nr_entries, temp = 0; 477 int irq, pos, i, j, nr_entries, temp = 0;
512 unsigned long phys_addr; 478 unsigned long phys_addr;
513 u32 table_offset; 479 u32 table_offset;
@@ -530,13 +496,11 @@ static int msix_capability_init(struct pci_dev *dev,
530 496
531 /* MSI-X Table Initialization */ 497 /* MSI-X Table Initialization */
532 for (i = 0; i < nvec; i++) { 498 for (i = 0; i < nvec; i++) {
533 irq = create_msi_irq(); 499 entry = alloc_msi_entry();
534 if (irq < 0) 500 if (!entry)
535 break; 501 break;
536 502
537 entry = get_irq_msi(irq);
538 j = entries[i].entry; 503 j = entries[i].entry;
539 entries[i].vector = irq;
540 entry->msi_attrib.type = PCI_CAP_ID_MSIX; 504 entry->msi_attrib.type = PCI_CAP_ID_MSIX;
541 entry->msi_attrib.is_64 = 1; 505 entry->msi_attrib.is_64 = 1;
542 entry->msi_attrib.entry_nr = j; 506 entry->msi_attrib.entry_nr = j;
@@ -545,6 +509,14 @@ static int msix_capability_init(struct pci_dev *dev,
545 entry->msi_attrib.pos = pos; 509 entry->msi_attrib.pos = pos;
546 entry->dev = dev; 510 entry->dev = dev;
547 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;
548 if (!head) { 520 if (!head) {
549 entry->link.head = irq; 521 entry->link.head = irq;
550 entry->link.tail = irq; 522 entry->link.tail = irq;
@@ -557,12 +529,6 @@ static int msix_capability_init(struct pci_dev *dev,
557 } 529 }
558 temp = irq; 530 temp = irq;
559 tail = entry; 531 tail = entry;
560 /* Configure MSI-X capability structure */
561 status = arch_setup_msi_irq(irq, dev);
562 if (status < 0) {
563 destroy_msi_irq(irq);
564 break;
565 }
566 532
567 set_irq_msi(irq, entry); 533 set_irq_msi(irq, entry);
568 } 534 }
@@ -706,8 +672,6 @@ static int msi_free_irq(struct pci_dev* dev, int irq)
706 int head, entry_nr, type; 672 int head, entry_nr, type;
707 void __iomem *base; 673 void __iomem *base;
708 674
709 arch_teardown_msi_irq(irq);
710
711 entry = get_irq_msi(irq); 675 entry = get_irq_msi(irq);
712 if (!entry || entry->dev != dev) { 676 if (!entry || entry->dev != dev) {
713 return -EINVAL; 677 return -EINVAL;
@@ -718,9 +682,9 @@ static int msi_free_irq(struct pci_dev* dev, int irq)
718 base = entry->mask_base; 682 base = entry->mask_base;
719 get_irq_msi(entry->link.head)->link.tail = entry->link.tail; 683 get_irq_msi(entry->link.head)->link.tail = entry->link.tail;
720 get_irq_msi(entry->link.tail)->link.head = entry->link.head; 684 get_irq_msi(entry->link.tail)->link.head = entry->link.head;
721 entry->dev = NULL;
722 685
723 destroy_msi_irq(irq); 686 arch_teardown_msi_irq(irq);
687 kmem_cache_free(msi_cachep, entry);
724 688
725 if (type == PCI_CAP_ID_MSIX) { 689 if (type == PCI_CAP_ID_MSIX) {
726 writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE + 690 writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE +
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;
21struct pci_bus; 21struct pci_bus;
22struct task_struct; 22struct task_struct;
23struct pci_dev; 23struct pci_dev;
24struct msi_desc;
24 25
25typedef void ia64_mv_setup_t (char **); 26typedef void ia64_mv_setup_t (char **);
26typedef void ia64_mv_cpu_init_t (void); 27typedef void ia64_mv_cpu_init_t (void);
@@ -79,7 +80,7 @@ typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *);
79typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *); 80typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *);
80typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *); 81typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *);
81 82
82typedef int ia64_mv_setup_msi_irq_t (unsigned int irq, struct pci_dev *pdev); 83typedef int ia64_mv_setup_msi_irq_t (struct pci_dev *pdev, struct msi_desc *);
83typedef void ia64_mv_teardown_msi_irq_t (unsigned int irq); 84typedef void ia64_mv_teardown_msi_irq_t (unsigned int irq);
84 85
85static inline void 86static inline void
diff --git a/include/linux/msi.h b/include/linux/msi.h
index b99976b1536e..74c8a2ecc9dd 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -41,7 +41,7 @@ struct msi_desc {
41/* 41/*
42 * The arch hook for setup up msi irqs 42 * The arch hook for setup up msi irqs
43 */ 43 */
44int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev); 44int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
45void arch_teardown_msi_irq(unsigned int irq); 45void arch_teardown_msi_irq(unsigned int irq);
46 46
47 47