diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2007-01-28 14:52:03 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-02-07 18:50:08 -0500 |
commit | 5b912c108c8b1fcecbfe13d6d9a183db97b682d3 (patch) | |
tree | 0267f65fd9237a41207e4359e09d09e60f6cd754 | |
parent | 1c659d61cfbd8dc3926688c1bbf12d80f4cfb5c2 (diff) |
msi: Kill the msi_desc array.
We need to be able to get from an irq number to a struct msi_desc.
The msi_desc array in msi.c had several short comings the big one was
that it could not be used outside of msi.c. Using irq_data in struct
irq_desc almost worked except on some architectures irq_data needs to
be used for something else.
So this patch adds a msi_desc pointer to irq_desc, adds the appropriate
wrappers and changes all of the msi code to use them.
The dynamic_irq_init/cleanup code was tweaked to ensure the new
field is left in a well defined state.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | arch/ia64/sn/kernel/msi_sn.c | 2 | ||||
-rw-r--r-- | drivers/pci/msi.c | 44 | ||||
-rw-r--r-- | include/linux/irq.h | 4 | ||||
-rw-r--r-- | kernel/irq/chip.c | 28 |
4 files changed, 54 insertions, 24 deletions
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c index b3a435fd70fb..31fbb859b67e 100644 --- a/arch/ia64/sn/kernel/msi_sn.c +++ b/arch/ia64/sn/kernel/msi_sn.c | |||
@@ -74,7 +74,7 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) | |||
74 | struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); | 74 | struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); |
75 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); | 75 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); |
76 | 76 | ||
77 | entry = get_irq_data(irq); | 77 | entry = get_irq_msi(irq); |
78 | if (!entry->msi_attrib.is_64) | 78 | if (!entry->msi_attrib.is_64) |
79 | return -EINVAL; | 79 | return -EINVAL; |
80 | 80 | ||
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 55fe83dfd77b..52c253c5ad3d 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "pci.h" | 24 | #include "pci.h" |
25 | #include "msi.h" | 25 | #include "msi.h" |
26 | 26 | ||
27 | static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; | ||
28 | static struct kmem_cache* msi_cachep; | 27 | static struct kmem_cache* msi_cachep; |
29 | 28 | ||
30 | static int pci_msi_enable = 1; | 29 | static int pci_msi_enable = 1; |
@@ -43,7 +42,7 @@ static void msi_set_mask_bit(unsigned int irq, int flag) | |||
43 | { | 42 | { |
44 | struct msi_desc *entry; | 43 | struct msi_desc *entry; |
45 | 44 | ||
46 | entry = msi_desc[irq]; | 45 | entry = get_irq_msi(irq); |
47 | BUG_ON(!entry || !entry->dev); | 46 | BUG_ON(!entry || !entry->dev); |
48 | switch (entry->msi_attrib.type) { | 47 | switch (entry->msi_attrib.type) { |
49 | case PCI_CAP_ID_MSI: | 48 | case PCI_CAP_ID_MSI: |
@@ -73,7 +72,7 @@ static void msi_set_mask_bit(unsigned int irq, int flag) | |||
73 | 72 | ||
74 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) | 73 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) |
75 | { | 74 | { |
76 | struct msi_desc *entry = get_irq_data(irq); | 75 | struct msi_desc *entry = get_irq_msi(irq); |
77 | switch(entry->msi_attrib.type) { | 76 | switch(entry->msi_attrib.type) { |
78 | case PCI_CAP_ID_MSI: | 77 | case PCI_CAP_ID_MSI: |
79 | { | 78 | { |
@@ -112,7 +111,7 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg) | |||
112 | 111 | ||
113 | void write_msi_msg(unsigned int irq, struct msi_msg *msg) | 112 | void write_msi_msg(unsigned int irq, struct msi_msg *msg) |
114 | { | 113 | { |
115 | struct msi_desc *entry = get_irq_data(irq); | 114 | struct msi_desc *entry = get_irq_msi(irq); |
116 | switch (entry->msi_attrib.type) { | 115 | switch (entry->msi_attrib.type) { |
117 | case PCI_CAP_ID_MSI: | 116 | case PCI_CAP_ID_MSI: |
118 | { | 117 | { |
@@ -208,7 +207,7 @@ static int create_msi_irq(void) | |||
208 | return -EBUSY; | 207 | return -EBUSY; |
209 | } | 208 | } |
210 | 209 | ||
211 | set_irq_data(irq, entry); | 210 | set_irq_msi(irq, entry); |
212 | 211 | ||
213 | return irq; | 212 | return irq; |
214 | } | 213 | } |
@@ -217,9 +216,9 @@ static void destroy_msi_irq(unsigned int irq) | |||
217 | { | 216 | { |
218 | struct msi_desc *entry; | 217 | struct msi_desc *entry; |
219 | 218 | ||
220 | entry = get_irq_data(irq); | 219 | entry = get_irq_msi(irq); |
221 | set_irq_chip(irq, NULL); | 220 | set_irq_chip(irq, NULL); |
222 | set_irq_data(irq, NULL); | 221 | set_irq_msi(irq, NULL); |
223 | destroy_irq(irq); | 222 | destroy_irq(irq); |
224 | kmem_cache_free(msi_cachep, entry); | 223 | kmem_cache_free(msi_cachep, entry); |
225 | } | 224 | } |
@@ -360,10 +359,10 @@ static int __pci_save_msix_state(struct pci_dev *dev) | |||
360 | while (head != tail) { | 359 | while (head != tail) { |
361 | struct msi_desc *entry; | 360 | struct msi_desc *entry; |
362 | 361 | ||
363 | entry = msi_desc[irq]; | 362 | entry = get_irq_msi(irq); |
364 | read_msi_msg(irq, &entry->msg_save); | 363 | read_msi_msg(irq, &entry->msg_save); |
365 | 364 | ||
366 | tail = msi_desc[irq]->link.tail; | 365 | tail = entry->link.tail; |
367 | irq = tail; | 366 | irq = tail; |
368 | } | 367 | } |
369 | 368 | ||
@@ -410,10 +409,10 @@ static void __pci_restore_msix_state(struct pci_dev *dev) | |||
410 | /* route the table */ | 409 | /* route the table */ |
411 | irq = head = dev->first_msi_irq; | 410 | irq = head = dev->first_msi_irq; |
412 | while (head != tail) { | 411 | while (head != tail) { |
413 | entry = msi_desc[irq]; | 412 | entry = get_irq_msi(irq); |
414 | write_msi_msg(irq, &entry->msg_save); | 413 | write_msi_msg(irq, &entry->msg_save); |
415 | 414 | ||
416 | tail = msi_desc[irq]->link.tail; | 415 | tail = entry->link.tail; |
417 | irq = tail; | 416 | irq = tail; |
418 | } | 417 | } |
419 | 418 | ||
@@ -451,7 +450,7 @@ static int msi_capability_init(struct pci_dev *dev) | |||
451 | if (irq < 0) | 450 | if (irq < 0) |
452 | return irq; | 451 | return irq; |
453 | 452 | ||
454 | entry = get_irq_data(irq); | 453 | entry = get_irq_msi(irq); |
455 | entry->link.head = irq; | 454 | entry->link.head = irq; |
456 | entry->link.tail = irq; | 455 | entry->link.tail = irq; |
457 | entry->msi_attrib.type = PCI_CAP_ID_MSI; | 456 | entry->msi_attrib.type = PCI_CAP_ID_MSI; |
@@ -486,7 +485,7 @@ static int msi_capability_init(struct pci_dev *dev) | |||
486 | } | 485 | } |
487 | 486 | ||
488 | dev->first_msi_irq = irq; | 487 | dev->first_msi_irq = irq; |
489 | msi_desc[irq] = entry; | 488 | set_irq_msi(irq, entry); |
490 | /* Set MSI enabled bits */ | 489 | /* Set MSI enabled bits */ |
491 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | 490 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
492 | 491 | ||
@@ -535,7 +534,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
535 | if (irq < 0) | 534 | if (irq < 0) |
536 | break; | 535 | break; |
537 | 536 | ||
538 | entry = get_irq_data(irq); | 537 | entry = get_irq_msi(irq); |
539 | j = entries[i].entry; | 538 | j = entries[i].entry; |
540 | entries[i].vector = irq; | 539 | entries[i].vector = irq; |
541 | entry->msi_attrib.type = PCI_CAP_ID_MSIX; | 540 | entry->msi_attrib.type = PCI_CAP_ID_MSIX; |
@@ -565,7 +564,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
565 | break; | 564 | break; |
566 | } | 565 | } |
567 | 566 | ||
568 | msi_desc[irq] = entry; | 567 | set_irq_msi(irq, entry); |
569 | } | 568 | } |
570 | if (i != nvec) { | 569 | if (i != nvec) { |
571 | int avail = i - 1; | 570 | int avail = i - 1; |
@@ -682,7 +681,7 @@ void pci_disable_msi(struct pci_dev* dev) | |||
682 | 681 | ||
683 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | 682 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
684 | 683 | ||
685 | entry = msi_desc[dev->first_msi_irq]; | 684 | entry = get_irq_msi(dev->first_msi_irq); |
686 | if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { | 685 | if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { |
687 | return; | 686 | return; |
688 | } | 687 | } |
@@ -709,7 +708,7 @@ static int msi_free_irq(struct pci_dev* dev, int irq) | |||
709 | 708 | ||
710 | arch_teardown_msi_irq(irq); | 709 | arch_teardown_msi_irq(irq); |
711 | 710 | ||
712 | entry = msi_desc[irq]; | 711 | entry = get_irq_msi(irq); |
713 | if (!entry || entry->dev != dev) { | 712 | if (!entry || entry->dev != dev) { |
714 | return -EINVAL; | 713 | return -EINVAL; |
715 | } | 714 | } |
@@ -717,10 +716,9 @@ static int msi_free_irq(struct pci_dev* dev, int irq) | |||
717 | entry_nr = entry->msi_attrib.entry_nr; | 716 | entry_nr = entry->msi_attrib.entry_nr; |
718 | head = entry->link.head; | 717 | head = entry->link.head; |
719 | base = entry->mask_base; | 718 | base = entry->mask_base; |
720 | msi_desc[entry->link.head]->link.tail = entry->link.tail; | 719 | get_irq_msi(entry->link.head)->link.tail = entry->link.tail; |
721 | msi_desc[entry->link.tail]->link.head = entry->link.head; | 720 | get_irq_msi(entry->link.tail)->link.head = entry->link.head; |
722 | entry->dev = NULL; | 721 | entry->dev = NULL; |
723 | msi_desc[irq] = NULL; | ||
724 | 722 | ||
725 | destroy_msi_irq(irq); | 723 | destroy_msi_irq(irq); |
726 | 724 | ||
@@ -821,7 +819,7 @@ void pci_disable_msix(struct pci_dev* dev) | |||
821 | 819 | ||
822 | irq = head = dev->first_msi_irq; | 820 | irq = head = dev->first_msi_irq; |
823 | while (head != tail) { | 821 | while (head != tail) { |
824 | tail = msi_desc[irq]->link.tail; | 822 | tail = get_irq_msi(irq)->link.tail; |
825 | if (irq_has_action(irq)) | 823 | if (irq_has_action(irq)) |
826 | warning = 1; | 824 | warning = 1; |
827 | else if (irq != head) /* Release MSI-X irq */ | 825 | else if (irq != head) /* Release MSI-X irq */ |
@@ -867,8 +865,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) | |||
867 | 865 | ||
868 | irq = head = dev->first_msi_irq; | 866 | irq = head = dev->first_msi_irq; |
869 | while (head != tail) { | 867 | while (head != tail) { |
870 | tail = msi_desc[irq]->link.tail; | 868 | tail = get_irq_msi(irq)->link.tail; |
871 | base = msi_desc[irq]->mask_base; | 869 | base = get_irq_msi(irq)->mask_base; |
872 | if (irq_has_action(irq)) | 870 | if (irq_has_action(irq)) |
873 | warning = 1; | 871 | warning = 1; |
874 | else if (irq != head) /* Release MSI-X irq */ | 872 | else if (irq != head) /* Release MSI-X irq */ |
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/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 |