]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
pci: tegra: skip read/write config if pcie link is down
authorManikanta <mmaddireddy@nvidia.com>
Tue, 6 Sep 2016 11:20:31 +0000 (16:50 +0530)
committermobile promotions <svcmobile_promotions@nvidia.com>
Fri, 9 Sep 2016 06:23:40 +0000 (23:23 -0700)
When Wi-Fi is turned OFF, bcm4359 driver powers off the chip.
But it will not de-register the pci driver. This will result
in response decoding error if any application tries to read
config space register. To fix this issue, skip read/write
config if pcie link is down.

bug 200211162

Change-Id: I61fa3f0ae155263aecc22b609344e8e980176f01
Signed-off-by: Manikanta <mmaddireddy@nvidia.com>
Reviewed-on: http://git-master/r/1215523
(cherry picked from commit 30d3613ff7e795fb420b85d3f8f18ef6e3610fc3)
Reviewed-on: http://git-master/r/1216435
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sumeet Gupta <sumeetg@nvidia.com>
drivers/pci/host/pci-tegra.c

index c627e5d7a6fa15ea60be6a6e7d91bae8c34b3625..c8a2d60d1973d07d575e281bcd3393a1ad4971e0 100644 (file)
@@ -709,7 +709,24 @@ static int tegra_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
                                int where, int size, u32 *value)
 {
        void __iomem *addr;
+       struct tegra_pcie *pcie = sys_to_pcie(bus->sysdata);
+       struct tegra_pcie_port *port = NULL;
+       u32 rp = 0;
+       struct pci_dev *dn_dev;
+
+       dn_dev = bus->self;
+
+       if (!dn_dev || !pcie)
+               goto skip_ep_check;
+
+       rp = PCI_SLOT(dn_dev->devfn);
 
+       list_for_each_entry(port, &pcie->ports, list)
+               if (rp == port->index + 1)
+                       break;
+       if (!port->ep_status)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+skip_ep_check:
        addr = tegra_pcie_conf_address(bus, devfn, where);
        if (!addr) {
                *value = 0xffffffff;
@@ -731,7 +748,23 @@ static int tegra_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
 {
        void __iomem *addr;
        u32 mask, tmp;
+       struct tegra_pcie *pcie = sys_to_pcie(bus->sysdata);
+       struct tegra_pcie_port *port = NULL;
+       u32 rp = 0;
+       struct pci_dev *dn_dev;
+
+       dn_dev = bus->self;
+       if (!dn_dev || !pcie)
+               goto skip_ep_check;
+       rp = PCI_SLOT(dn_dev->devfn);
+
+       list_for_each_entry(port, &pcie->ports, list)
+               if (rp == port->index + 1)
+                       break;
+       if (!port->ep_status)
+               return PCIBIOS_DEVICE_NOT_FOUND;
 
+skip_ep_check:
        addr = tegra_pcie_conf_address(bus, devfn, where);
        if (!addr)
                return PCIBIOS_DEVICE_NOT_FOUND;