aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/quirks.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2009-03-29 15:30:05 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-03-30 15:15:52 -0400
commiteeafda70bf2807544e96fa4e52b2433cd470ff46 (patch)
tree24ca3b703ec512a8b7eceec525c697f5ff88d2e5 /drivers/pci/quirks.c
parentde7453065d5d5243686467998f1fcc58d20e0a7c (diff)
PCI: fix HT MSI mapping fix
Impact: fix bug This patch reworks 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, but only do that trick with end_device on the chain. Reported-by: Prakash Punnoor <prakash@punnoor.de> Tested-by: Prakash Punnoor <prakash@punnoor.de> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r--drivers/pci/quirks.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index faf02dd00015..9b2f0d96900d 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2206,6 +2206,33 @@ static int __devinit host_bridge_with_leaf(struct pci_dev *host_bridge)
2206 return found; 2206 return found;
2207} 2207}
2208 2208
2209#define PCI_HT_CAP_SLAVE_CTRL0 4 /* link control */
2210#define PCI_HT_CAP_SLAVE_CTRL1 8 /* link control to */
2211
2212static int __devinit is_end_of_ht_chain(struct pci_dev *dev)
2213{
2214 int pos, ctrl_off;
2215 int end = 0;
2216 u16 flags, ctrl;
2217
2218 pos = pci_find_ht_capability(dev, HT_CAPTYPE_SLAVE);
2219
2220 if (!pos)
2221 goto out;
2222
2223 pci_read_config_word(dev, pos + PCI_CAP_FLAGS, &flags);
2224
2225 ctrl_off = ((flags >> 10) & 1) ?
2226 PCI_HT_CAP_SLAVE_CTRL0 : PCI_HT_CAP_SLAVE_CTRL1;
2227 pci_read_config_word(dev, pos + ctrl_off, &ctrl);
2228
2229 if (ctrl & (1 << 6))
2230 end = 1;
2231
2232out:
2233 return end;
2234}
2235
2209static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev) 2236static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev)
2210{ 2237{
2211 struct pci_dev *host_bridge; 2238 struct pci_dev *host_bridge;
@@ -2230,8 +2257,9 @@ static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev)
2230 if (!found) 2257 if (!found)
2231 return; 2258 return;
2232 2259
2233 /* don't enable host_bridge with leaf directly here */ 2260 /* don't enable end_device/host_bridge with leaf directly here */
2234 if (host_bridge == dev && host_bridge_with_leaf(host_bridge)) 2261 if (host_bridge == dev && is_end_of_ht_chain(host_bridge) &&
2262 host_bridge_with_leaf(host_bridge))
2235 goto out; 2263 goto out;
2236 2264
2237 /* root did that ! */ 2265 /* root did that ! */