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