aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/msi.c34
1 files changed, 11 insertions, 23 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 6a0f2f07f955..4c14f31f2b4d 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -196,30 +196,15 @@ void unmask_msi_irq(unsigned int irq)
196void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) 196void 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 if (entry->msi_attrib.is_msix) {
200 void __iomem *base = entry->mask_base +
201 entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
202 199
203 msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR); 200 /* We do not touch the hardware (which may not even be
204 msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR); 201 * accessible at the moment) but return the last message
205 msg->data = readl(base + PCI_MSIX_ENTRY_DATA); 202 * written. Assert that this is valid, assuming that
206 } else { 203 * valid messages are not all-zeroes. */
207 struct pci_dev *dev = entry->dev; 204 BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo |
208 int pos = entry->msi_attrib.pos; 205 entry->msg.data));
209 u16 data;
210 206
211 pci_read_config_dword(dev, msi_lower_address_reg(pos), 207 *msg = entry->msg;
212 &msg->address_lo);
213 if (entry->msi_attrib.is_64) {
214 pci_read_config_dword(dev, msi_upper_address_reg(pos),
215 &msg->address_hi);
216 pci_read_config_word(dev, msi_data_reg(pos, 1), &data);
217 } else {
218 msg->address_hi = 0;
219 pci_read_config_word(dev, msi_data_reg(pos, 0), &data);
220 }
221 msg->data = data;
222 }
223} 208}
224 209
225void read_msi_msg(unsigned int irq, struct msi_msg *msg) 210void read_msi_msg(unsigned int irq, struct msi_msg *msg)
@@ -232,7 +217,10 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg)
232void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) 217void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
233{ 218{
234 struct msi_desc *entry = get_irq_desc_msi(desc); 219 struct msi_desc *entry = get_irq_desc_msi(desc);
235 if (entry->msi_attrib.is_msix) { 220
221 if (entry->dev->current_state != PCI_D0) {
222 /* Don't touch the hardware now */
223 } else if (entry->msi_attrib.is_msix) {
236 void __iomem *base; 224 void __iomem *base;
237 base = entry->mask_base + 225 base = entry->mask_base +
238 entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; 226 entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;