mtip32xx: Fix ERO and NoSnoop values in PCIe upstream on AMD systems
PATCH 1/1 mtip32xx: Fix ERO and NoSnoop values in PCIe upstream on AMD systems
A hardware quirk in P320h/P420m interfere with PCIe transactions on some AMD chipsets, making P320h/P420m unusable. This workaround is to disable ERO and NoSnoop bits in the parent and root complex for normal functioning of these devices
NOTE: This workaround is specific to AMD chipset with a PCIe upstream device with device id 0x5aXX
Signed-off-by Asai Thambi S P <[email protected]>
Signed-off-by Sam Bradshaw <[email protected]>
--- drivers/block/mtip32xx/mtip32xx.c | 53 +++++++++++++++++++++++++++++++++++++ 1 files changed, 53 insertions(+), 0 deletions(-)
drivers/block/mtip32xx/mtip32xx.c +53 -0
@@ -4479,6 +4479,57 @@ static DEFINE_HANDLER(5); static DEFINE_HANDLER(6); static DEFINE_HANDLER(7); +static void mtip_disable_link_opts (struct driver_data *dd,struct pci_dev *pdev) +{ +int pos; +unsigned short pcie_dev_ctrl; + + pos =pci_find_capability (pdev,PCI_CAP_ID_EXP ); +if (pos) { +pci_read_config_word (pdev, + pos +PCI_EXP_DEVCTL , + &pcie_dev_ctrl); +if (pcie_dev_ctrl & (1 <<11 ) || + pcie_dev_ctrl & (1 <<4 )) { +dev_info (&dd->pdev->dev, +"Disabling ERO/No-Snoop on bridge device %04x:%04x\n" , + pdev->vendor, pdev->device); + pcie_dev_ctrl &= ~(PCI_EXP_DEVCTL_NOSNOOP_EN | +PCI_EXP_DEVCTL_RELAX_EN ); +pci_write_config_word (pdev, + pos +PCI_EXP_DEVCTL , + pcie_dev_ctrl); + } + } +} + +static void mtip_fix_ero_nosnoop (struct driver_data *dd,struct pci_dev *pdev) +{ +/* +* This workaround is specific to AMD/ATI chipset with a PCI upstream +* device with device id 0x5aXX +*/ +if (pdev->bus && pdev->bus->self) { +if (pdev->bus->self->vendor ==PCI_VENDOR_ID_ATI && + ((pdev->bus->self->device &0xff00 ) ==0x5a00 )) { +mtip_disable_link_opts (dd, pdev->bus->self); + }else { +/* Check further up the topology */ +struct pci_dev *parent_dev = pdev->bus->self; +if (parent_dev->bus && + parent_dev->bus->parent && + parent_dev->bus->parent->self && + parent_dev->bus->parent->self->vendor == +PCI_VENDOR_ID_ATI && + (parent_dev->bus->parent->self->device & +0xff00 ) ==0x5a00 ) { +mtip_disable_link_opts (dd, + parent_dev->bus->parent->self); + } + } + } +} +/* * Called for each supported PCI device detected. *
@@ -4630,6 +4681,8 @@ static int mtip_pci_probe(struct pci_dev *pdev, goto msi_initialize_err; } +mtip_fix_ero_nosnoop (dd, pdev); +/* Initialize the block layer. */ rv =mtip_block_initialize (dd);if (rv <0 ) {
Signature · 1 line
1.7.1