svn commit: r327798 - head/sys/powerpc/powermac
Landon J. Fuller
landonf at FreeBSD.org
Wed Jan 10 22:19:13 UTC 2018
Author: landonf
Date: Wed Jan 10 22:19:11 2018
New Revision: 327798
URL: https://svnweb.freebsd.org/changeset/base/327798
Log:
Fix minor locking issues in the Power Mac Uninorth PCI bridge driver.
- Call resource_int_value() once during attach, rather than within the
pci_(read|write)_config() code path; this avoids taking a blocking mutex
to read kenv variables.
- Use a spin lock to protect non-atomic config space accesses; this matches
the behavior of Darwin's AppleMacRiscPCI driver.
Reviewed by: jhibbits
Differential Revision: https://reviews.freebsd.org/D13839
Modified:
head/sys/powerpc/powermac/uninorthpci.c
head/sys/powerpc/powermac/uninorthvar.h
Modified: head/sys/powerpc/powermac/uninorthpci.c
==============================================================================
--- head/sys/powerpc/powermac/uninorthpci.c Wed Jan 10 21:59:21 2018 (r327797)
+++ head/sys/powerpc/powermac/uninorthpci.c Wed Jan 10 22:19:11 2018 (r327798)
@@ -34,6 +34,8 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/rman.h>
#include <dev/ofw/openfirm.h>
@@ -134,13 +136,17 @@ uninorth_attach(device_t dev)
{
struct uninorth_softc *sc;
const char *compatible;
+ const char *name;
phandle_t node;
uint32_t reg[3];
uint64_t regbase;
cell_t acells;
+ int unit;
node = ofw_bus_get_node(dev);
sc = device_get_softc(dev);
+ name = device_get_name(dev);
+ unit = device_get_unit(dev);
if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8)
return (ENXIO);
@@ -164,6 +170,11 @@ uninorth_attach(device_t dev)
sc->sc_addr = (vm_offset_t)pmap_mapdev(regbase + 0x800000, PAGE_SIZE);
sc->sc_data = (vm_offset_t)pmap_mapdev(regbase + 0xc00000, PAGE_SIZE);
+ if (resource_int_value(name, unit, "skipslot", &sc->sc_skipslot) != 0)
+ sc->sc_skipslot = -1;
+
+ mtx_init(&sc->sc_cfg_mtx, "uninorth pcicfg", NULL, MTX_SPIN);
+
return (ofw_pci_attach(dev));
}
@@ -173,25 +184,29 @@ uninorth_read_config(device_t dev, u_int bus, u_int sl
{
struct uninorth_softc *sc;
vm_offset_t caoff;
+ u_int32_t val;
sc = device_get_softc(dev);
caoff = sc->sc_data + (reg & 0x07);
+ val = 0xffffffff;
+ mtx_lock_spin(&sc->sc_cfg_mtx);
if (uninorth_enable_config(sc, bus, slot, func, reg) != 0) {
switch (width) {
case 1:
- return (in8rb(caoff));
+ val = in8rb(caoff);
break;
case 2:
- return (in16rb(caoff));
+ val = in16rb(caoff);
break;
case 4:
- return (in32rb(caoff));
+ val = in32rb(caoff);
break;
}
}
+ mtx_unlock_spin(&sc->sc_cfg_mtx);
- return (0xffffffff);
+ return (val);
}
static void
@@ -204,6 +219,7 @@ uninorth_write_config(device_t dev, u_int bus, u_int s
sc = device_get_softc(dev);
caoff = sc->sc_data + (reg & 0x07);
+ mtx_lock_spin(&sc->sc_cfg_mtx);
if (uninorth_enable_config(sc, bus, slot, func, reg)) {
switch (width) {
case 1:
@@ -217,6 +233,7 @@ uninorth_write_config(device_t dev, u_int bus, u_int s
break;
}
}
+ mtx_unlock_spin(&sc->sc_cfg_mtx);
}
static int
@@ -224,13 +241,11 @@ uninorth_enable_config(struct uninorth_softc *sc, u_in
u_int func, u_int reg)
{
uint32_t cfgval;
- uint32_t pass;
- if (resource_int_value(device_get_name(sc->pci_sc.sc_dev),
- device_get_unit(sc->pci_sc.sc_dev), "skipslot", &pass) == 0) {
- if (pass == slot)
- return (0);
- }
+ mtx_assert(&sc->sc_cfg_mtx, MA_OWNED);
+
+ if (sc->sc_skipslot == slot)
+ return (0);
/*
* Issue type 0 configuration space accesses for the root bus.
Modified: head/sys/powerpc/powermac/uninorthvar.h
==============================================================================
--- head/sys/powerpc/powermac/uninorthvar.h Wed Jan 10 21:59:21 2018 (r327797)
+++ head/sys/powerpc/powermac/uninorthvar.h Wed Jan 10 22:19:11 2018 (r327798)
@@ -39,6 +39,8 @@ struct uninorth_softc {
vm_offset_t sc_addr;
vm_offset_t sc_data;
int sc_ver;
+ int sc_skipslot;
+ struct mtx sc_cfg_mtx;
};
struct unin_chip_softc {
More information about the svn-src-head
mailing list