lkml.org 
[lkml]   [2009]   [Mar]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH] pci: don't enable too much HT MSI mapping -v5 -resend

    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

    v3: will enable c51...
    v4: will enable c51 kind of without leaf too.
    v5: update to mainline

    Reported-by: Prakash Punnoor <prakash@punnoor.de>
    Signed-off-by: Yinghai Lu <yinghai@kernel.org>

    ---
    drivers/pci/quirks.c | 118 +++++++++++++++++++++++++++++++++++----------------
    1 file changed, 82 insertions(+), 36 deletions(-)

    Index: linux-2.6/drivers/pci/quirks.c
    ===================================================================
    --- linux-2.6.orig/drivers/pci/quirks.c
    +++ linux-2.6/drivers/pci/quirks.c
    @@ -2078,6 +2078,65 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NV
    PCI_DEVICE_ID_NVIDIA_NVENET_15,
    nvenet_msi_disable);

    +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 int __devinit host_bridge_with_leaf(struct pci_dev *host_bridge)
    +{
    + struct pci_dev *dev;
    + int pos;
    + int i, dev_no;
    + int found = 0;
    +
    + dev_no = host_bridge->devfn >> 3;
    + for (i = dev_no + 1; i < 0x20; i++) {
    + dev = pci_get_slot(host_bridge->bus, PCI_DEVFN(i, 0));
    + if (!dev)
    + continue;
    +
    + /* found next host bridge ?*/
    + pos = pci_find_ht_capability(dev, HT_CAPTYPE_SLAVE);
    + if (pos != 0) {
    + pci_dev_put(dev);
    + break;
    + }
    +
    + if (ht_check_msi_mapping(dev)) {
    + found = 1;
    + pci_dev_put(dev);
    + break;
    + }
    + pci_dev_put(dev);
    + }
    +
    + return found;
    +}
    +
    static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev)
    {
    struct pci_dev *host_bridge;
    @@ -2102,6 +2161,10 @@ static void __devinit nv_ht_enable_msi_m
    if (!found)
    return;

    + /* don't enable host_bridge with leaf directly here */
    + if (host_bridge == dev && host_bridge_with_leaf(host_bridge))
    + goto out;
    +
    /* root did that ! */
    if (msi_ht_cap_enabled(host_bridge))
    goto out;
    @@ -2132,44 +2195,12 @@ static void __devinit ht_disable_msi_map
    }
    }

    -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)
    +static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all)
    {
    struct pci_dev *host_bridge;
    int pos;
    int found;

    - /* Enabling HT MSI mapping on this device breaks MCP51 */
    - if (dev->device == 0x270)
    - return;
    -
    /* check if there is HT MSI cap or enabled on this device */
    found = ht_check_msi_mapping(dev);

    @@ -2193,7 +2224,10 @@ static void __devinit nv_msi_ht_cap_quir
    /* Host bridge is to HT */
    if (found == 1) {
    /* it is not enabled, try to enable it */
    - nv_ht_enable_msi_mapping(dev);
    + if (all)
    + ht_enable_msi_mapping(dev);
    + else
    + nv_ht_enable_msi_mapping(dev);
    }
    return;
    }
    @@ -2205,8 +2239,20 @@ static void __devinit nv_msi_ht_cap_quir
    /* 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);
    +
    +static void __devinit nv_msi_ht_cap_quirk_all(struct pci_dev *dev)
    +{
    + return __nv_msi_ht_cap_quirk(dev, 1);
    +}
    +
    +static void __devinit nv_msi_ht_cap_quirk_leaf(struct pci_dev *dev)
    +{
    + return __nv_msi_ht_cap_quirk(dev, 0);
    +}
    +
    +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk_leaf);
    +
    +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all);

    static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev)
    {

    \
     
     \ /
      Last update: 2009-03-21 03:33    [W:0.028 / U:0.524 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site