diff options
| -rw-r--r-- | arch/ia64/kernel/msi_ia64.c | 2 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/msi_sn.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 2 | ||||
| -rw-r--r-- | drivers/pci/msi.c | 47 | ||||
| -rw-r--r-- | include/linux/msi.h | 2 |
5 files changed, 47 insertions, 8 deletions
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index 6c8922856049..4a746ea838ff 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c | |||
| @@ -25,7 +25,7 @@ static int ia64_set_msi_irq_affinity(unsigned int irq, | |||
| 25 | if (irq_prepare_move(irq, cpu)) | 25 | if (irq_prepare_move(irq, cpu)) |
| 26 | return -1; | 26 | return -1; |
| 27 | 27 | ||
| 28 | read_msi_msg(irq, &msg); | 28 | get_cached_msi_msg(irq, &msg); |
| 29 | 29 | ||
| 30 | addr = msg.address_lo; | 30 | addr = msg.address_lo; |
| 31 | addr &= MSI_ADDR_DEST_ID_MASK; | 31 | addr &= MSI_ADDR_DEST_ID_MASK; |
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c index ebfdd6a9ae1a..0c72dd463831 100644 --- a/arch/ia64/sn/kernel/msi_sn.c +++ b/arch/ia64/sn/kernel/msi_sn.c | |||
| @@ -175,7 +175,7 @@ static int sn_set_msi_irq_affinity(unsigned int irq, | |||
| 175 | * Release XIO resources for the old MSI PCI address | 175 | * Release XIO resources for the old MSI PCI address |
| 176 | */ | 176 | */ |
| 177 | 177 | ||
| 178 | read_msi_msg(irq, &msg); | 178 | get_cached_msi_msg(irq, &msg); |
| 179 | sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; | 179 | sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; |
| 180 | pdev = sn_pdev->pdi_linux_pcidev; | 180 | pdev = sn_pdev->pdi_linux_pcidev; |
| 181 | provider = SN_PCIDEV_BUSPROVIDER(pdev); | 181 | provider = SN_PCIDEV_BUSPROVIDER(pdev); |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index e41ed24ab26d..4dc0084ec1b1 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -3397,7 +3397,7 @@ static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask) | |||
| 3397 | 3397 | ||
| 3398 | cfg = desc->chip_data; | 3398 | cfg = desc->chip_data; |
| 3399 | 3399 | ||
| 3400 | read_msi_msg_desc(desc, &msg); | 3400 | get_cached_msi_msg_desc(desc, &msg); |
| 3401 | 3401 | ||
| 3402 | msg.data &= ~MSI_DATA_VECTOR_MASK; | 3402 | msg.data &= ~MSI_DATA_VECTOR_MASK; |
| 3403 | msg.data |= MSI_DATA_VECTOR(cfg->vector); | 3403 | msg.data |= MSI_DATA_VECTOR(cfg->vector); |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 4c14f31f2b4d..69b7be33b3a2 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
| @@ -197,9 +197,46 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
| 197 | { | 197 | { |
| 198 | struct msi_desc *entry = get_irq_desc_msi(desc); | 198 | struct msi_desc *entry = get_irq_desc_msi(desc); |
| 199 | 199 | ||
| 200 | /* We do not touch the hardware (which may not even be | 200 | BUG_ON(entry->dev->current_state != PCI_D0); |
| 201 | * accessible at the moment) but return the last message | 201 | |
| 202 | * written. Assert that this is valid, assuming that | 202 | if (entry->msi_attrib.is_msix) { |
| 203 | void __iomem *base = entry->mask_base + | ||
| 204 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | ||
| 205 | |||
| 206 | msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR); | ||
| 207 | msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR); | ||
| 208 | msg->data = readl(base + PCI_MSIX_ENTRY_DATA); | ||
| 209 | } else { | ||
| 210 | struct pci_dev *dev = entry->dev; | ||
| 211 | int pos = entry->msi_attrib.pos; | ||
| 212 | u16 data; | ||
| 213 | |||
| 214 | pci_read_config_dword(dev, msi_lower_address_reg(pos), | ||
| 215 | &msg->address_lo); | ||
| 216 | if (entry->msi_attrib.is_64) { | ||
| 217 | pci_read_config_dword(dev, msi_upper_address_reg(pos), | ||
| 218 | &msg->address_hi); | ||
| 219 | pci_read_config_word(dev, msi_data_reg(pos, 1), &data); | ||
| 220 | } else { | ||
| 221 | msg->address_hi = 0; | ||
| 222 | pci_read_config_word(dev, msi_data_reg(pos, 0), &data); | ||
| 223 | } | ||
| 224 | msg->data = data; | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) | ||
| 229 | { | ||
| 230 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 231 | |||
| 232 | read_msi_msg_desc(desc, msg); | ||
| 233 | } | ||
| 234 | |||
| 235 | void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | ||
| 236 | { | ||
| 237 | struct msi_desc *entry = get_irq_desc_msi(desc); | ||
| 238 | |||
| 239 | /* Assert that the cache is valid, assuming that | ||
| 203 | * valid messages are not all-zeroes. */ | 240 | * valid messages are not all-zeroes. */ |
| 204 | BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo | | 241 | BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo | |
| 205 | entry->msg.data)); | 242 | entry->msg.data)); |
| @@ -207,11 +244,11 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
| 207 | *msg = entry->msg; | 244 | *msg = entry->msg; |
| 208 | } | 245 | } |
| 209 | 246 | ||
| 210 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) | 247 | void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg) |
| 211 | { | 248 | { |
| 212 | struct irq_desc *desc = irq_to_desc(irq); | 249 | struct irq_desc *desc = irq_to_desc(irq); |
| 213 | 250 | ||
| 214 | read_msi_msg_desc(desc, msg); | 251 | get_cached_msi_msg_desc(desc, msg); |
| 215 | } | 252 | } |
| 216 | 253 | ||
| 217 | void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | 254 | void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) |
diff --git a/include/linux/msi.h b/include/linux/msi.h index 6991ab5b24d1..91b05c171854 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h | |||
| @@ -14,8 +14,10 @@ struct irq_desc; | |||
| 14 | extern void mask_msi_irq(unsigned int irq); | 14 | extern void mask_msi_irq(unsigned int irq); |
| 15 | extern void unmask_msi_irq(unsigned int irq); | 15 | extern void unmask_msi_irq(unsigned int irq); |
| 16 | extern void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); | 16 | extern void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); |
| 17 | extern void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); | ||
| 17 | extern void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); | 18 | extern void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg); |
| 18 | extern void read_msi_msg(unsigned int irq, struct msi_msg *msg); | 19 | extern void read_msi_msg(unsigned int irq, struct msi_msg *msg); |
| 20 | extern void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg); | ||
| 19 | extern void write_msi_msg(unsigned int irq, struct msi_msg *msg); | 21 | extern void write_msi_msg(unsigned int irq, struct msi_msg *msg); |
| 20 | 22 | ||
| 21 | struct msi_desc { | 23 | struct msi_desc { |
