diff options
-rw-r--r-- | drivers/net/tg3.c | 9 | ||||
-rw-r--r-- | drivers/pci/msi.c | 18 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 24 | ||||
-rw-r--r-- | include/linux/pci.h | 9 |
4 files changed, 45 insertions, 15 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 09440d783e65..cad519910767 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -7365,10 +7365,6 @@ static int tg3_open(struct net_device *dev) | |||
7365 | } else if (pci_enable_msi(tp->pdev) == 0) { | 7365 | } else if (pci_enable_msi(tp->pdev) == 0) { |
7366 | u32 msi_mode; | 7366 | u32 msi_mode; |
7367 | 7367 | ||
7368 | /* Hardware bug - MSI won't work if INTX disabled. */ | ||
7369 | if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) | ||
7370 | pci_intx(tp->pdev, 1); | ||
7371 | |||
7372 | msi_mode = tr32(MSGINT_MODE); | 7368 | msi_mode = tr32(MSGINT_MODE); |
7373 | tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE); | 7369 | tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE); |
7374 | tp->tg3_flags2 |= TG3_FLG2_USING_MSI; | 7370 | tp->tg3_flags2 |= TG3_FLG2_USING_MSI; |
@@ -12681,11 +12677,6 @@ static int tg3_resume(struct pci_dev *pdev) | |||
12681 | if (err) | 12677 | if (err) |
12682 | return err; | 12678 | return err; |
12683 | 12679 | ||
12684 | /* Hardware bug - MSI won't work if INTX disabled. */ | ||
12685 | if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) && | ||
12686 | (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) | ||
12687 | pci_intx(tp->pdev, 1); | ||
12688 | |||
12689 | netif_device_attach(dev); | 12680 | netif_device_attach(dev); |
12690 | 12681 | ||
12691 | tg3_full_lock(tp, 0); | 12682 | tg3_full_lock(tp, 0); |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 87e01615053d..07c9f09c856d 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -224,6 +224,12 @@ static struct msi_desc* alloc_msi_entry(void) | |||
224 | return entry; | 224 | return entry; |
225 | } | 225 | } |
226 | 226 | ||
227 | static void pci_intx_for_msi(struct pci_dev *dev, int enable) | ||
228 | { | ||
229 | if (!(dev->dev_flags & PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG)) | ||
230 | pci_intx(dev, enable); | ||
231 | } | ||
232 | |||
227 | #ifdef CONFIG_PM | 233 | #ifdef CONFIG_PM |
228 | static void __pci_restore_msi_state(struct pci_dev *dev) | 234 | static void __pci_restore_msi_state(struct pci_dev *dev) |
229 | { | 235 | { |
@@ -237,7 +243,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev) | |||
237 | entry = get_irq_msi(dev->irq); | 243 | entry = get_irq_msi(dev->irq); |
238 | pos = entry->msi_attrib.pos; | 244 | pos = entry->msi_attrib.pos; |
239 | 245 | ||
240 | pci_intx(dev, 0); /* disable intx */ | 246 | pci_intx_for_msi(dev, 0); |
241 | msi_set_enable(dev, 0); | 247 | msi_set_enable(dev, 0); |
242 | write_msi_msg(dev->irq, &entry->msg); | 248 | write_msi_msg(dev->irq, &entry->msg); |
243 | if (entry->msi_attrib.maskbit) | 249 | if (entry->msi_attrib.maskbit) |
@@ -260,7 +266,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev) | |||
260 | return; | 266 | return; |
261 | 267 | ||
262 | /* route the table */ | 268 | /* route the table */ |
263 | pci_intx(dev, 0); /* disable intx */ | 269 | pci_intx_for_msi(dev, 0); |
264 | msix_set_enable(dev, 0); | 270 | msix_set_enable(dev, 0); |
265 | 271 | ||
266 | list_for_each_entry(entry, &dev->msi_list, list) { | 272 | list_for_each_entry(entry, &dev->msi_list, list) { |
@@ -343,7 +349,7 @@ static int msi_capability_init(struct pci_dev *dev) | |||
343 | } | 349 | } |
344 | 350 | ||
345 | /* Set MSI enabled bits */ | 351 | /* Set MSI enabled bits */ |
346 | pci_intx(dev, 0); /* disable intx */ | 352 | pci_intx_for_msi(dev, 0); |
347 | msi_set_enable(dev, 1); | 353 | msi_set_enable(dev, 1); |
348 | dev->msi_enabled = 1; | 354 | dev->msi_enabled = 1; |
349 | 355 | ||
@@ -433,7 +439,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
433 | i++; | 439 | i++; |
434 | } | 440 | } |
435 | /* Set MSI-X enabled bits */ | 441 | /* Set MSI-X enabled bits */ |
436 | pci_intx(dev, 0); /* disable intx */ | 442 | pci_intx_for_msi(dev, 0); |
437 | msix_set_enable(dev, 1); | 443 | msix_set_enable(dev, 1); |
438 | dev->msix_enabled = 1; | 444 | dev->msix_enabled = 1; |
439 | 445 | ||
@@ -528,7 +534,7 @@ void pci_disable_msi(struct pci_dev* dev) | |||
528 | return; | 534 | return; |
529 | 535 | ||
530 | msi_set_enable(dev, 0); | 536 | msi_set_enable(dev, 0); |
531 | pci_intx(dev, 1); /* enable intx */ | 537 | pci_intx_for_msi(dev, 1); |
532 | dev->msi_enabled = 0; | 538 | dev->msi_enabled = 0; |
533 | 539 | ||
534 | BUG_ON(list_empty(&dev->msi_list)); | 540 | BUG_ON(list_empty(&dev->msi_list)); |
@@ -640,7 +646,7 @@ void pci_disable_msix(struct pci_dev* dev) | |||
640 | return; | 646 | return; |
641 | 647 | ||
642 | msix_set_enable(dev, 0); | 648 | msix_set_enable(dev, 0); |
643 | pci_intx(dev, 1); /* enable intx */ | 649 | pci_intx_for_msi(dev, 1); |
644 | dev->msix_enabled = 0; | 650 | dev->msix_enabled = 0; |
645 | 651 | ||
646 | msix_free_all_irqs(dev); | 652 | msix_free_all_irqs(dev); |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f975f7fccb1d..9e8c7af0cc16 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -1707,4 +1707,28 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) | |||
1707 | } | 1707 | } |
1708 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, | 1708 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, |
1709 | quirk_nvidia_ck804_msi_ht_cap); | 1709 | quirk_nvidia_ck804_msi_ht_cap); |
1710 | |||
1711 | static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev) | ||
1712 | { | ||
1713 | dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG; | ||
1714 | } | ||
1715 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, | ||
1716 | PCI_DEVICE_ID_TIGON3_5780, | ||
1717 | quirk_msi_intx_disable_bug); | ||
1718 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, | ||
1719 | PCI_DEVICE_ID_TIGON3_5780S, | ||
1720 | quirk_msi_intx_disable_bug); | ||
1721 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, | ||
1722 | PCI_DEVICE_ID_TIGON3_5714, | ||
1723 | quirk_msi_intx_disable_bug); | ||
1724 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, | ||
1725 | PCI_DEVICE_ID_TIGON3_5714S, | ||
1726 | quirk_msi_intx_disable_bug); | ||
1727 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, | ||
1728 | PCI_DEVICE_ID_TIGON3_5715, | ||
1729 | quirk_msi_intx_disable_bug); | ||
1730 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, | ||
1731 | PCI_DEVICE_ID_TIGON3_5715S, | ||
1732 | quirk_msi_intx_disable_bug); | ||
1733 | |||
1710 | #endif /* CONFIG_PCI_MSI */ | 1734 | #endif /* CONFIG_PCI_MSI */ |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 5d2281f661f7..7c04f38e6ac3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -109,6 +109,14 @@ enum pcie_reset_state { | |||
109 | pcie_hot_reset = (__force pcie_reset_state_t) 3 | 109 | pcie_hot_reset = (__force pcie_reset_state_t) 3 |
110 | }; | 110 | }; |
111 | 111 | ||
112 | typedef unsigned short __bitwise pci_dev_flags_t; | ||
113 | enum pci_dev_flags { | ||
114 | /* INTX_DISABLE in PCI_COMMAND register disables MSI | ||
115 | * generation too. | ||
116 | */ | ||
117 | PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG = (__force pci_dev_flags_t) 1, | ||
118 | }; | ||
119 | |||
112 | typedef unsigned short __bitwise pci_bus_flags_t; | 120 | typedef unsigned short __bitwise pci_bus_flags_t; |
113 | enum pci_bus_flags { | 121 | enum pci_bus_flags { |
114 | PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, | 122 | PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, |
@@ -185,6 +193,7 @@ struct pci_dev { | |||
185 | unsigned int msix_enabled:1; | 193 | unsigned int msix_enabled:1; |
186 | unsigned int is_managed:1; | 194 | unsigned int is_managed:1; |
187 | unsigned int is_pcie:1; | 195 | unsigned int is_pcie:1; |
196 | pci_dev_flags_t dev_flags; | ||
188 | atomic_t enable_cnt; /* pci_enable_device has been called */ | 197 | atomic_t enable_cnt; /* pci_enable_device has been called */ |
189 | 198 | ||
190 | u32 saved_config_space[16]; /* config space saved at suspend time */ | 199 | u32 saved_config_space[16]; /* config space saved at suspend time */ |