diff options
-rw-r--r-- | drivers/pci/msi.c | 21 | ||||
-rw-r--r-- | include/linux/msi.h | 1 |
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 | ||
126 | static void msi_set_mask_bit(unsigned int irq, int flag) | 126 | static 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 | ||
242 | void mask_msi_irq(unsigned int irq) | 242 | void 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 | ||
248 | void unmask_msi_irq(unsigned int irq) | 248 | void 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; |