summaryrefslogtreecommitdiffstats
path: root/sys/arm/mv/mv_pci.c
diff options
context:
space:
mode:
authorzbb <zbb@FreeBSD.org>2016-01-20 14:05:21 +0000
committerzbb <zbb@FreeBSD.org>2016-01-20 14:05:21 +0000
commit8d821a3b902538e032e528f745233c54ac947c0c (patch)
tree62fe241cde115d31b4097b28ecfaaf12f5b0901d /sys/arm/mv/mv_pci.c
parent44fdaddddd1b785bd722370a7cd47e917911e22f (diff)
downloadFreeBSD-src-8d821a3b902538e032e528f745233c54ac947c0c.zip
FreeBSD-src-8d821a3b902538e032e528f745233c54ac947c0c.tar.gz
Fix invalid root link detection in mv_pci driver
mv_pci driver omitted slot 0, which can be valid device on Armada38x. New mechanism detects if device is root link, basing on vendor's and device's IDs. It is restricted to Armada38x; on other machines, behaviour remains the same. Reviewed by: andrew Obtained from: Semihalf Sponsored by: Stormshield Submitted by: Bartosz Szczepanek <bsz@semihalf.com> Differential revision: https://reviews.freebsd.org/D4377
Diffstat (limited to 'sys/arm/mv/mv_pci.c')
-rw-r--r--sys/arm/mv/mv_pci.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/sys/arm/mv/mv_pci.c b/sys/arm/mv/mv_pci.c
index 42f9218..1bf065d 100644
--- a/sys/arm/mv/mv_pci.c
+++ b/sys/arm/mv/mv_pci.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2008 MARVELL INTERNATIONAL LTD.
* Copyright (c) 2010 The FreeBSD Foundation
- * Copyright (c) 2010-2012 Semihalf
+ * Copyright (c) 2010-2015 Semihalf
* All rights reserved.
*
* Developed by Semihalf.
@@ -1016,6 +1016,25 @@ mv_pcib_maxslots(device_t dev)
return ((sc->sc_type != MV_TYPE_PCI) ? 1 : PCI_SLOTMAX);
}
+static int
+mv_pcib_root_slot(device_t dev, u_int bus, u_int slot, u_int func)
+{
+#if defined(SOC_MV_ARMADA38X)
+ struct mv_pcib_softc *sc = device_get_softc(dev);
+ uint32_t vendor, device;
+
+ vendor = mv_pcib_hw_cfgread(sc, bus, slot, func, PCIR_VENDOR,
+ PCIR_VENDOR_LENGTH);
+ device = mv_pcib_hw_cfgread(sc, bus, slot, func, PCIR_DEVICE,
+ PCIR_DEVICE_LENGTH) & MV_DEV_FAMILY_MASK;
+
+ return (vendor == PCI_VENDORID_MRVL && device == MV_DEV_ARMADA38X);
+#else
+ /* On platforms other than Armada38x, root link is always at slot 0 */
+ return (slot == 0);
+#endif
+}
+
static uint32_t
mv_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, int bytes)
@@ -1024,7 +1043,7 @@ mv_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
/* Return ~0 if link is inactive or trying to read from Root */
if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_STATUS) &
- PCIE_STATUS_LINK_DOWN) || (slot == 0))
+ PCIE_STATUS_LINK_DOWN) || mv_pcib_root_slot(dev, bus, slot, func))
return (~0U);
return (mv_pcib_hw_cfgread(sc, bus, slot, func, reg, bytes));
@@ -1038,7 +1057,7 @@ mv_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
/* Return if link is inactive or trying to write to Root */
if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_STATUS) &
- PCIE_STATUS_LINK_DOWN) || (slot == 0))
+ PCIE_STATUS_LINK_DOWN) || mv_pcib_root_slot(dev, bus, slot, func))
return;
mv_pcib_hw_cfgwrite(sc, bus, slot, func, reg, val, bytes);
OpenPOWER on IntegriCloud