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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
1c659d61cf
commit
5b912c108c
@@ -74,7 +74,7 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
|||||||
struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
|
struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
|
||||||
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
|
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
|
||||||
|
|
||||||
entry = get_irq_data(irq);
|
entry = get_irq_msi(irq);
|
||||||
if (!entry->msi_attrib.is_64)
|
if (!entry->msi_attrib.is_64)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@@ -24,7 +24,6 @@
|
|||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
#include "msi.h"
|
#include "msi.h"
|
||||||
|
|
||||||
static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
|
|
||||||
static struct kmem_cache* msi_cachep;
|
static struct kmem_cache* msi_cachep;
|
||||||
|
|
||||||
static int pci_msi_enable = 1;
|
static int pci_msi_enable = 1;
|
||||||
@@ -43,7 +42,7 @@ static void msi_set_mask_bit(unsigned int irq, int flag)
|
|||||||
{
|
{
|
||||||
struct msi_desc *entry;
|
struct msi_desc *entry;
|
||||||
|
|
||||||
entry = msi_desc[irq];
|
entry = get_irq_msi(irq);
|
||||||
BUG_ON(!entry || !entry->dev);
|
BUG_ON(!entry || !entry->dev);
|
||||||
switch (entry->msi_attrib.type) {
|
switch (entry->msi_attrib.type) {
|
||||||
case PCI_CAP_ID_MSI:
|
case PCI_CAP_ID_MSI:
|
||||||
@@ -73,7 +72,7 @@ static void msi_set_mask_bit(unsigned int irq, int flag)
|
|||||||
|
|
||||||
void read_msi_msg(unsigned int irq, struct msi_msg *msg)
|
void read_msi_msg(unsigned int irq, struct msi_msg *msg)
|
||||||
{
|
{
|
||||||
struct msi_desc *entry = get_irq_data(irq);
|
struct msi_desc *entry = get_irq_msi(irq);
|
||||||
switch(entry->msi_attrib.type) {
|
switch(entry->msi_attrib.type) {
|
||||||
case PCI_CAP_ID_MSI:
|
case PCI_CAP_ID_MSI:
|
||||||
{
|
{
|
||||||
@@ -112,7 +111,7 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg)
|
|||||||
|
|
||||||
void write_msi_msg(unsigned int irq, struct msi_msg *msg)
|
void write_msi_msg(unsigned int irq, struct msi_msg *msg)
|
||||||
{
|
{
|
||||||
struct msi_desc *entry = get_irq_data(irq);
|
struct msi_desc *entry = get_irq_msi(irq);
|
||||||
switch (entry->msi_attrib.type) {
|
switch (entry->msi_attrib.type) {
|
||||||
case PCI_CAP_ID_MSI:
|
case PCI_CAP_ID_MSI:
|
||||||
{
|
{
|
||||||
@@ -208,7 +207,7 @@ static int create_msi_irq(void)
|
|||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_irq_data(irq, entry);
|
set_irq_msi(irq, entry);
|
||||||
|
|
||||||
return irq;
|
return irq;
|
||||||
}
|
}
|
||||||
@@ -217,9 +216,9 @@ static void destroy_msi_irq(unsigned int irq)
|
|||||||
{
|
{
|
||||||
struct msi_desc *entry;
|
struct msi_desc *entry;
|
||||||
|
|
||||||
entry = get_irq_data(irq);
|
entry = get_irq_msi(irq);
|
||||||
set_irq_chip(irq, NULL);
|
set_irq_chip(irq, NULL);
|
||||||
set_irq_data(irq, NULL);
|
set_irq_msi(irq, NULL);
|
||||||
destroy_irq(irq);
|
destroy_irq(irq);
|
||||||
kmem_cache_free(msi_cachep, entry);
|
kmem_cache_free(msi_cachep, entry);
|
||||||
}
|
}
|
||||||
@@ -360,10 +359,10 @@ static int __pci_save_msix_state(struct pci_dev *dev)
|
|||||||
while (head != tail) {
|
while (head != tail) {
|
||||||
struct msi_desc *entry;
|
struct msi_desc *entry;
|
||||||
|
|
||||||
entry = msi_desc[irq];
|
entry = get_irq_msi(irq);
|
||||||
read_msi_msg(irq, &entry->msg_save);
|
read_msi_msg(irq, &entry->msg_save);
|
||||||
|
|
||||||
tail = msi_desc[irq]->link.tail;
|
tail = entry->link.tail;
|
||||||
irq = tail;
|
irq = tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,10 +409,10 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
|
|||||||
/* route the table */
|
/* route the table */
|
||||||
irq = head = dev->first_msi_irq;
|
irq = head = dev->first_msi_irq;
|
||||||
while (head != tail) {
|
while (head != tail) {
|
||||||
entry = msi_desc[irq];
|
entry = get_irq_msi(irq);
|
||||||
write_msi_msg(irq, &entry->msg_save);
|
write_msi_msg(irq, &entry->msg_save);
|
||||||
|
|
||||||
tail = msi_desc[irq]->link.tail;
|
tail = entry->link.tail;
|
||||||
irq = tail;
|
irq = tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +450,7 @@ static int msi_capability_init(struct pci_dev *dev)
|
|||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
return irq;
|
return irq;
|
||||||
|
|
||||||
entry = get_irq_data(irq);
|
entry = get_irq_msi(irq);
|
||||||
entry->link.head = irq;
|
entry->link.head = irq;
|
||||||
entry->link.tail = irq;
|
entry->link.tail = irq;
|
||||||
entry->msi_attrib.type = PCI_CAP_ID_MSI;
|
entry->msi_attrib.type = PCI_CAP_ID_MSI;
|
||||||
@@ -486,7 +485,7 @@ static int msi_capability_init(struct pci_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev->first_msi_irq = irq;
|
dev->first_msi_irq = irq;
|
||||||
msi_desc[irq] = entry;
|
set_irq_msi(irq, entry);
|
||||||
/* Set MSI enabled bits */
|
/* Set MSI enabled bits */
|
||||||
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
|
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
|
||||||
|
|
||||||
@@ -535,7 +534,7 @@ static int msix_capability_init(struct pci_dev *dev,
|
|||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
entry = get_irq_data(irq);
|
entry = get_irq_msi(irq);
|
||||||
j = entries[i].entry;
|
j = entries[i].entry;
|
||||||
entries[i].vector = irq;
|
entries[i].vector = irq;
|
||||||
entry->msi_attrib.type = PCI_CAP_ID_MSIX;
|
entry->msi_attrib.type = PCI_CAP_ID_MSIX;
|
||||||
@@ -565,7 +564,7 @@ static int msix_capability_init(struct pci_dev *dev,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
msi_desc[irq] = entry;
|
set_irq_msi(irq, entry);
|
||||||
}
|
}
|
||||||
if (i != nvec) {
|
if (i != nvec) {
|
||||||
int avail = i - 1;
|
int avail = i - 1;
|
||||||
@@ -682,7 +681,7 @@ void pci_disable_msi(struct pci_dev* dev)
|
|||||||
|
|
||||||
disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
|
disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
|
||||||
|
|
||||||
entry = msi_desc[dev->first_msi_irq];
|
entry = get_irq_msi(dev->first_msi_irq);
|
||||||
if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
|
if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -709,7 +708,7 @@ static int msi_free_irq(struct pci_dev* dev, int irq)
|
|||||||
|
|
||||||
arch_teardown_msi_irq(irq);
|
arch_teardown_msi_irq(irq);
|
||||||
|
|
||||||
entry = msi_desc[irq];
|
entry = get_irq_msi(irq);
|
||||||
if (!entry || entry->dev != dev) {
|
if (!entry || entry->dev != dev) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -717,10 +716,9 @@ static int msi_free_irq(struct pci_dev* dev, int irq)
|
|||||||
entry_nr = entry->msi_attrib.entry_nr;
|
entry_nr = entry->msi_attrib.entry_nr;
|
||||||
head = entry->link.head;
|
head = entry->link.head;
|
||||||
base = entry->mask_base;
|
base = entry->mask_base;
|
||||||
msi_desc[entry->link.head]->link.tail = entry->link.tail;
|
get_irq_msi(entry->link.head)->link.tail = entry->link.tail;
|
||||||
msi_desc[entry->link.tail]->link.head = entry->link.head;
|
get_irq_msi(entry->link.tail)->link.head = entry->link.head;
|
||||||
entry->dev = NULL;
|
entry->dev = NULL;
|
||||||
msi_desc[irq] = NULL;
|
|
||||||
|
|
||||||
destroy_msi_irq(irq);
|
destroy_msi_irq(irq);
|
||||||
|
|
||||||
@@ -821,7 +819,7 @@ void pci_disable_msix(struct pci_dev* dev)
|
|||||||
|
|
||||||
irq = head = dev->first_msi_irq;
|
irq = head = dev->first_msi_irq;
|
||||||
while (head != tail) {
|
while (head != tail) {
|
||||||
tail = msi_desc[irq]->link.tail;
|
tail = get_irq_msi(irq)->link.tail;
|
||||||
if (irq_has_action(irq))
|
if (irq_has_action(irq))
|
||||||
warning = 1;
|
warning = 1;
|
||||||
else if (irq != head) /* Release MSI-X irq */
|
else if (irq != head) /* Release MSI-X irq */
|
||||||
@@ -867,8 +865,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
|
|||||||
|
|
||||||
irq = head = dev->first_msi_irq;
|
irq = head = dev->first_msi_irq;
|
||||||
while (head != tail) {
|
while (head != tail) {
|
||||||
tail = msi_desc[irq]->link.tail;
|
tail = get_irq_msi(irq)->link.tail;
|
||||||
base = msi_desc[irq]->mask_base;
|
base = get_irq_msi(irq)->mask_base;
|
||||||
if (irq_has_action(irq))
|
if (irq_has_action(irq))
|
||||||
warning = 1;
|
warning = 1;
|
||||||
else if (irq != head) /* Release MSI-X irq */
|
else if (irq != head) /* Release MSI-X irq */
|
||||||
|
@@ -68,6 +68,7 @@ typedef void fastcall (*irq_flow_handler_t)(unsigned int irq,
|
|||||||
#define IRQ_MOVE_PENDING 0x40000000 /* need to re-target IRQ destination */
|
#define IRQ_MOVE_PENDING 0x40000000 /* need to re-target IRQ destination */
|
||||||
|
|
||||||
struct proc_dir_entry;
|
struct proc_dir_entry;
|
||||||
|
struct msi_desc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct irq_chip - hardware interrupt chip descriptor
|
* struct irq_chip - hardware interrupt chip descriptor
|
||||||
@@ -148,6 +149,7 @@ struct irq_chip {
|
|||||||
struct irq_desc {
|
struct irq_desc {
|
||||||
irq_flow_handler_t handle_irq;
|
irq_flow_handler_t handle_irq;
|
||||||
struct irq_chip *chip;
|
struct irq_chip *chip;
|
||||||
|
struct msi_desc *msi_desc;
|
||||||
void *handler_data;
|
void *handler_data;
|
||||||
void *chip_data;
|
void *chip_data;
|
||||||
struct irqaction *action; /* IRQ action list */
|
struct irqaction *action; /* IRQ action list */
|
||||||
@@ -373,10 +375,12 @@ extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
|
|||||||
extern int set_irq_data(unsigned int irq, void *data);
|
extern int set_irq_data(unsigned int irq, void *data);
|
||||||
extern int set_irq_chip_data(unsigned int irq, void *data);
|
extern int set_irq_chip_data(unsigned int irq, void *data);
|
||||||
extern int set_irq_type(unsigned int irq, unsigned int type);
|
extern int set_irq_type(unsigned int irq, unsigned int type);
|
||||||
|
extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
|
||||||
|
|
||||||
#define get_irq_chip(irq) (irq_desc[irq].chip)
|
#define get_irq_chip(irq) (irq_desc[irq].chip)
|
||||||
#define get_irq_chip_data(irq) (irq_desc[irq].chip_data)
|
#define get_irq_chip_data(irq) (irq_desc[irq].chip_data)
|
||||||
#define get_irq_data(irq) (irq_desc[irq].handler_data)
|
#define get_irq_data(irq) (irq_desc[irq].handler_data)
|
||||||
|
#define get_irq_msi(irq) (irq_desc[irq].msi_desc)
|
||||||
|
|
||||||
#endif /* CONFIG_GENERIC_HARDIRQS */
|
#endif /* CONFIG_GENERIC_HARDIRQS */
|
||||||
|
|
||||||
|
@@ -39,6 +39,7 @@ void dynamic_irq_init(unsigned int irq)
|
|||||||
desc->chip = &no_irq_chip;
|
desc->chip = &no_irq_chip;
|
||||||
desc->handle_irq = handle_bad_irq;
|
desc->handle_irq = handle_bad_irq;
|
||||||
desc->depth = 1;
|
desc->depth = 1;
|
||||||
|
desc->msi_desc = NULL;
|
||||||
desc->handler_data = NULL;
|
desc->handler_data = NULL;
|
||||||
desc->chip_data = NULL;
|
desc->chip_data = NULL;
|
||||||
desc->action = NULL;
|
desc->action = NULL;
|
||||||
@@ -74,6 +75,9 @@ void dynamic_irq_cleanup(unsigned int irq)
|
|||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
desc->msi_desc = NULL;
|
||||||
|
desc->handler_data = NULL;
|
||||||
|
desc->chip_data = NULL;
|
||||||
desc->handle_irq = handle_bad_irq;
|
desc->handle_irq = handle_bad_irq;
|
||||||
desc->chip = &no_irq_chip;
|
desc->chip = &no_irq_chip;
|
||||||
spin_unlock_irqrestore(&desc->lock, flags);
|
spin_unlock_irqrestore(&desc->lock, flags);
|
||||||
@@ -161,6 +165,30 @@ int set_irq_data(unsigned int irq, void *data)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(set_irq_data);
|
EXPORT_SYMBOL(set_irq_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set_irq_data - set irq type data for an irq
|
||||||
|
* @irq: Interrupt number
|
||||||
|
* @data: Pointer to interrupt specific data
|
||||||
|
*
|
||||||
|
* Set the hardware irq controller data for an irq
|
||||||
|
*/
|
||||||
|
int set_irq_msi(unsigned int irq, struct msi_desc *entry)
|
||||||
|
{
|
||||||
|
struct irq_desc *desc;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (irq >= NR_IRQS) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"Trying to install msi data for IRQ%d\n", irq);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
desc = irq_desc + irq;
|
||||||
|
spin_lock_irqsave(&desc->lock, flags);
|
||||||
|
desc->msi_desc = entry;
|
||||||
|
spin_unlock_irqrestore(&desc->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set_irq_chip_data - set irq chip data for an irq
|
* set_irq_chip_data - set irq chip data for an irq
|
||||||
* @irq: Interrupt number
|
* @irq: Interrupt number
|
||||||
|
Reference in New Issue
Block a user