Prakash Punnoor wrote: > On Dienstag 24 Februar 2009 18:37:35 Jesse Barnes wrote: >> On Monday, February 23, 2009 11:51:59 am Yinghai Lu wrote: >>> Impact: fix bug >>> >>> Prakash reported that his c51-mcp51 system ondie sound card doesn't work >>> MSI but if he hack out the HT-MSI on mcp51, the MSI will work well with >>> sound card. >>> >>> this patch rework the nv_msi_ht_cap_quirk() >>> and will only enable ht_msi on own root device and try to avoid to enable >>> ht_msi on device following that root dev >>> >>> Reported-by: Prakash Punnoor <prakash@xxxxxxxxxx> >>> Tested-by: Prakash Punnoor <prakash@xxxxxxxxxx> >>> Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx> >> Thanks Yinghai & Prakash, applied this fix to my for-linus branch. > > I am very sorry, but I made a mistake testing this patch. I messed up my > kernels and got a false positive and only noticed this now. The patch does NOT > work and even makes things worse: > > dmesg|grep HT > pci 0000:00:09.0: Found disabled HT MSI Mapping > pci 0000:00:09.0: Enabling HT MSI Mapping > pci 0000:00:09.0: Found enabled HT MSI Mapping > pci 0000:00:09.0: Found enabled HT MSI Mapping > pci 0000:00:09.0: Found enabled HT MSI Mapping > pci 0000:00:09.0: Found enabled HT MSI Mapping > > This is exactly the device which shouldn't be MSI enabled for me. On the other > hand, it doesn't enable the needed devices anymore. > please check this one, please power off the system before load the kernel with new patch. [PATCH] pci: don't enable too much HT MSI mapping -v2 Impact: fix bug Prakash reported that his c51-mcp51 system ondie sound card doesn't work MSI but if he hack out the HT-MSI on mcp51, the MSI will work well with sound card. this patch rework the nv_msi_ht_cap_quirk() and will only try to avoid to enable ht_msi on device following that root dev, and don't touch that root dev Reported-by: Prakash Punnoor <prakash@xxxxxxxxxx> Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx> --- drivers/pci/quirks.c | 119 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 104 insertions(+), 15 deletions(-) Index: linux-2.6/drivers/pci/quirks.c =================================================================== --- linux-2.6.orig/drivers/pci/quirks.c +++ linux-2.6/drivers/pci/quirks.c @@ -2050,10 +2050,104 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NV PCI_DEVICE_ID_NVIDIA_NVENET_15, nvenet_msi_disable); -static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) +static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev) { struct pci_dev *host_bridge; + int pos; + int i, dev_no; + int found = 0; + + dev_no = dev->devfn >> 3; + for (i = dev_no; i >= 0; i--) { + host_bridge = pci_get_slot(dev->bus, PCI_DEVFN(i, 0)); + if (!host_bridge) + continue; + + pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE); + if (pos != 0) { + found = 1; + break; + } + pci_dev_put(host_bridge); + } + + if (!found) + return; + + /* don't enable host_bridge directly here */ + if (host_bridge == dev) + goto out; + + /* root did that ! */ + if (msi_ht_cap_enabled(host_bridge)) + goto out; + + ht_enable_msi_mapping(dev); + +out: + pci_dev_put(host_bridge); +} + +static void __devinit ht_disable_msi_mapping(struct pci_dev *dev) +{ + int pos, ttl = 48; + + pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); + while (pos && ttl--) { + u8 flags; + + if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, + &flags) == 0) { + dev_info(&dev->dev, "Enabling HT MSI Mapping\n"); + + pci_write_config_byte(dev, pos + HT_MSI_FLAGS, + flags & ~HT_MSI_FLAGS_ENABLE); + } + pos = pci_find_next_ht_capability(dev, pos, + HT_CAPTYPE_MSI_MAPPING); + } +} + +static int __devinit ht_check_msi_mapping(struct pci_dev *dev) +{ int pos, ttl = 48; + int found = 0; + + /* check if there is HT MSI cap or enabled on this device */ + pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); + while (pos && ttl--) { + u8 flags; + + if (found < 1) + found = 1; + if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, + &flags) == 0) { + if (flags & HT_MSI_FLAGS_ENABLE) { + if (found < 2) { + found = 2; + break; + } + } + } + pos = pci_find_next_ht_capability(dev, pos, + HT_CAPTYPE_MSI_MAPPING); + } + + return found; +} + +static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) +{ + struct pci_dev *host_bridge; + int pos; + int found; + + /* check if there is HT MSI cap or enabled on this device */ + found = ht_check_msi_mapping(dev); + + /* no HT MSI CAP */ + if (found == 0) + return; /* * HT MSI mapping should be disabled on devices that are below @@ -2069,24 +2163,19 @@ static void __devinit nv_msi_ht_cap_quir pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE); if (pos != 0) { /* Host bridge is to HT */ - ht_enable_msi_mapping(dev); + if (found == 1) { + /* it is not enabled, try to enable it */ + nv_ht_enable_msi_mapping(dev); + } return; } - /* Host bridge is not to HT, disable HT MSI mapping on this device */ - pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); - while (pos && ttl--) { - u8 flags; + /* HT MSI is not enabled */ + if (found == 1) + return; - if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, - &flags) == 0) { - dev_info(&dev->dev, "Disabling HT MSI mapping"); - pci_write_config_byte(dev, pos + HT_MSI_FLAGS, - flags & ~HT_MSI_FLAGS_ENABLE); - } - pos = pci_find_next_ht_capability(dev, pos, - HT_CAPTYPE_MSI_MAPPING); - } + /* Host bridge is not to HT, disable HT MSI mapping on this device */ + ht_disable_msi_mapping(dev); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk); -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html