aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/msi.c21
-rw-r--r--include/linux/msi.h1
2 files changed, 15 insertions, 7 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 26938da8f438..e3a05cc9a595 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -123,7 +123,7 @@ static void msix_flush_writes(unsigned int irq)
123 } 123 }
124} 124}
125 125
126static void msi_set_mask_bit(unsigned int irq, int flag) 126static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
127{ 127{
128 struct msi_desc *entry; 128 struct msi_desc *entry;
129 129
@@ -137,8 +137,8 @@ static void msi_set_mask_bit(unsigned int irq, int flag)
137 137
138 pos = (long)entry->mask_base; 138 pos = (long)entry->mask_base;
139 pci_read_config_dword(entry->dev, pos, &mask_bits); 139 pci_read_config_dword(entry->dev, pos, &mask_bits);
140 mask_bits &= ~(1); 140 mask_bits &= ~(mask);
141 mask_bits |= flag; 141 mask_bits |= flag & mask;
142 pci_write_config_dword(entry->dev, pos, mask_bits); 142 pci_write_config_dword(entry->dev, pos, mask_bits);
143 } else { 143 } else {
144 msi_set_enable(entry->dev, !flag); 144 msi_set_enable(entry->dev, !flag);
@@ -241,13 +241,13 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg)
241 241
242void mask_msi_irq(unsigned int irq) 242void mask_msi_irq(unsigned int irq)
243{ 243{
244 msi_set_mask_bit(irq, 1); 244 msi_set_mask_bits(irq, 1, 1);
245 msix_flush_writes(irq); 245 msix_flush_writes(irq);
246} 246}
247 247
248void unmask_msi_irq(unsigned int irq) 248void unmask_msi_irq(unsigned int irq)
249{ 249{
250 msi_set_mask_bit(irq, 0); 250 msi_set_mask_bits(irq, 1, 0);
251 msix_flush_writes(irq); 251 msix_flush_writes(irq);
252} 252}
253 253
@@ -291,7 +291,8 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
291 msi_set_enable(dev, 0); 291 msi_set_enable(dev, 0);
292 write_msi_msg(dev->irq, &entry->msg); 292 write_msi_msg(dev->irq, &entry->msg);
293 if (entry->msi_attrib.maskbit) 293 if (entry->msi_attrib.maskbit)
294 msi_set_mask_bit(dev->irq, entry->msi_attrib.masked); 294 msi_set_mask_bits(dev->irq, entry->msi_attrib.maskbits_mask,
295 entry->msi_attrib.masked);
295 296
296 pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); 297 pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
297 control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE); 298 control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
@@ -315,7 +316,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
315 316
316 list_for_each_entry(entry, &dev->msi_list, list) { 317 list_for_each_entry(entry, &dev->msi_list, list) {
317 write_msi_msg(entry->irq, &entry->msg); 318 write_msi_msg(entry->irq, &entry->msg);
318 msi_set_mask_bit(entry->irq, entry->msi_attrib.masked); 319 msi_set_mask_bits(entry->irq, 1, entry->msi_attrib.masked);
319 } 320 }
320 321
321 BUG_ON(list_empty(&dev->msi_list)); 322 BUG_ON(list_empty(&dev->msi_list));
@@ -382,6 +383,7 @@ static int msi_capability_init(struct pci_dev *dev)
382 pci_write_config_dword(dev, 383 pci_write_config_dword(dev,
383 msi_mask_bits_reg(pos, is_64bit_address(control)), 384 msi_mask_bits_reg(pos, is_64bit_address(control)),
384 maskbits); 385 maskbits);
386 entry->msi_attrib.maskbits_mask = temp;
385 } 387 }
386 list_add_tail(&entry->list, &dev->msi_list); 388 list_add_tail(&entry->list, &dev->msi_list);
387 389
@@ -583,6 +585,11 @@ void pci_disable_msi(struct pci_dev* dev)
583 585
584 BUG_ON(list_empty(&dev->msi_list)); 586 BUG_ON(list_empty(&dev->msi_list));
585 entry = list_entry(dev->msi_list.next, struct msi_desc, list); 587 entry = list_entry(dev->msi_list.next, struct msi_desc, list);
588 /* Return the the pci reset with msi irqs unmasked */
589 if (entry->msi_attrib.maskbit) {
590 u32 mask = entry->msi_attrib.maskbits_mask;
591 msi_set_mask_bits(dev->irq, mask, ~mask);
592 }
586 if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { 593 if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
587 return; 594 return;
588 } 595 }
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 94bb46d82efd..8f2939227207 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -22,6 +22,7 @@ struct msi_desc {
22 __u8 masked : 1; 22 __u8 masked : 1;
23 __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */ 23 __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
24 __u8 pos; /* Location of the msi capability */ 24 __u8 pos; /* Location of the msi capability */
25 __u32 maskbits_mask; /* mask bits mask */
25 __u16 entry_nr; /* specific enabled entry */ 26 __u16 entry_nr; /* specific enabled entry */
26 unsigned default_irq; /* default pre-assigned irq */ 27 unsigned default_irq; /* default pre-assigned irq */
27 }msi_attrib; 28 }msi_attrib;