svn commit: r366161 - head/sys/dev/extres/syscon

Michal Meloun mmel at FreeBSD.org
Fri Sep 25 16:44:02 UTC 2020


Author: mmel
Date: Fri Sep 25 16:44:01 2020
New Revision: 366161
URL: https://svnweb.freebsd.org/changeset/base/366161

Log:
  Refine locking inside of syscon driver.
  In some cases, the syscon driver may be used by consumer requiring better
  control about locking (ie. it may be used as registe file provider for clock
  driver which needs locked access to multiple registers).
  Add fine locking protocol methods together with bunch of helper functions
  in syscon driver and implement this functionality in syscon_generic driver.
  
  MFC after:	4 weeks

Modified:
  head/sys/dev/extres/syscon/syscon.c
  head/sys/dev/extres/syscon/syscon_generic.c
  head/sys/dev/extres/syscon/syscon_if.m

Modified: head/sys/dev/extres/syscon/syscon.c
==============================================================================
--- head/sys/dev/extres/syscon/syscon.c	Fri Sep 25 16:34:42 2020	(r366160)
+++ head/sys/dev/extres/syscon/syscon.c	Fri Sep 25 16:44:01 2020	(r366161)
@@ -67,7 +67,13 @@ typedef TAILQ_HEAD(syscon_list, syscon) syscon_list_t;
  */
 static int syscon_method_init(struct syscon *syscon);
 static int syscon_method_uninit(struct syscon *syscon);
+static uint32_t syscon_method_read_4(struct syscon *syscon, bus_size_t offset);
+static int syscon_method_write_4(struct syscon *syscon, bus_size_t offset,
+    uint32_t val);
+static int syscon_method_modify_4(struct syscon *syscon, bus_size_t offset,
+    uint32_t clear_bits, uint32_t set_bits);
 
+
 MALLOC_DEFINE(M_SYSCON, "syscon", "Syscon driver");
 
 static syscon_list_t syscon_list = TAILQ_HEAD_INITIALIZER(syscon_list);
@@ -80,6 +86,9 @@ SX_SYSINIT(syscon_topology, &syscon_topo_lock, "Syscon
 static syscon_method_t syscon_methods[] = {
 	SYSCONMETHOD(syscon_init,	syscon_method_init),
 	SYSCONMETHOD(syscon_uninit,	syscon_method_uninit),
+	SYSCONMETHOD(syscon_read_4,	syscon_method_read_4),
+	SYSCONMETHOD(syscon_write_4,	syscon_method_write_4),
+	SYSCONMETHOD(syscon_modify_4,	syscon_method_modify_4),
 
 	SYSCONMETHOD_END
 };
@@ -115,6 +124,39 @@ syscon_get_softc(struct syscon *syscon)
 	return (syscon->softc);
 };
 
+static uint32_t
+syscon_method_read_4(struct syscon *syscon, bus_size_t offset)
+{
+	uint32_t val;
+
+	SYSCON_DEVICE_LOCK(syscon->pdev);
+	val = SYSCON_UNLOCKED_READ_4(syscon, offset);
+	SYSCON_DEVICE_UNLOCK(syscon->pdev);
+	return(val);
+}
+
+static int
+syscon_method_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val)
+{
+	int	rv;
+
+	SYSCON_DEVICE_LOCK(syscon->pdev);
+	rv = SYSCON_UNLOCKED_WRITE_4(syscon, offset, val);
+	SYSCON_DEVICE_UNLOCK(syscon->pdev);
+	return(rv);
+}
+
+static int
+syscon_method_modify_4(struct syscon *syscon, bus_size_t offset,
+    uint32_t clear_bits, uint32_t set_bits)
+{
+	int	rv;
+
+	SYSCON_DEVICE_LOCK(syscon->pdev);
+	rv = SYSCON_UNLOCKED_MODIFY_4(syscon, offset, clear_bits, set_bits);
+	SYSCON_DEVICE_UNLOCK(syscon->pdev);
+	return(rv);
+}
 /*
  * Create and initialize syscon object, but do not register it.
  */
@@ -254,14 +296,3 @@ syscon_get_by_ofw_property(device_t cdev, phandle_t cn
 	return (0);
 }
 #endif
-
-int
-syscon_get_handle_default(device_t dev, struct syscon **syscon)
-{
-	device_t parent;
-
-	parent = device_get_parent(dev);
-	if (parent == NULL)
-		return (ENODEV);
-	return (SYSCON_GET_HANDLE(parent, syscon));
-}

Modified: head/sys/dev/extres/syscon/syscon_generic.c
==============================================================================
--- head/sys/dev/extres/syscon/syscon_generic.c	Fri Sep 25 16:34:42 2020	(r366160)
+++ head/sys/dev/extres/syscon/syscon_generic.c	Fri Sep 25 16:44:01 2020	(r366161)
@@ -55,11 +55,12 @@ __FBSDID("$FreeBSD$");
 
 MALLOC_DECLARE(M_SYSCON);
 
-static uint32_t syscon_generic_read_4(struct syscon *syscon, bus_size_t offset);
-static int syscon_generic_write_4(struct syscon *syscon, bus_size_t offset,
-    uint32_t val);
-static int syscon_generic_modify_4(struct syscon *syscon, bus_size_t offset,
-    uint32_t clear_bits, uint32_t set_bits);
+static uint32_t syscon_generic_unlocked_read_4(struct syscon *syscon,
+    bus_size_t offset);
+static int syscon_generic_unlocked_write_4(struct syscon *syscon,
+    bus_size_t offset, uint32_t val);
+static int syscon_generic_unlocked_modify_4(struct syscon *syscon,
+    bus_size_t offset, uint32_t clear_bits, uint32_t set_bits);
 static int syscon_generic_detach(device_t dev);
 /*
  * Generic syscon driver (FDT)
@@ -78,9 +79,9 @@ static struct ofw_compat_data compat_data[] = {
 #define SYSCON_ASSERT_UNLOCKED(_sc)	mtx_assert(&(_sc)->mtx, MA_NOTOWNED);
 
 static syscon_method_t syscon_generic_methods[] = {
-	SYSCONMETHOD(syscon_read_4,	syscon_generic_read_4),
-	SYSCONMETHOD(syscon_write_4,	syscon_generic_write_4),
-	SYSCONMETHOD(syscon_modify_4,	syscon_generic_modify_4),
+	SYSCONMETHOD(syscon_unlocked_read_4,  syscon_generic_unlocked_read_4),
+	SYSCONMETHOD(syscon_unlocked_write_4, syscon_generic_unlocked_write_4),
+	SYSCONMETHOD(syscon_unlocked_modify_4, syscon_generic_unlocked_modify_4),
 
 	SYSCONMETHOD_END
 };
@@ -88,50 +89,62 @@ DEFINE_CLASS_1(syscon_generic, syscon_generic_class, s
     0, syscon_class);
 
 static uint32_t
-syscon_generic_read_4(struct syscon *syscon, bus_size_t offset)
+syscon_generic_unlocked_read_4(struct syscon *syscon, bus_size_t offset)
 {
 	struct syscon_generic_softc *sc;
 	uint32_t val;
 
 	sc = device_get_softc(syscon->pdev);
-
-	SYSCON_LOCK(sc);
+	SYSCON_ASSERT_UNLOCKED(sc);
 	val = bus_read_4(sc->mem_res, offset);
-	SYSCON_UNLOCK(sc);
 	return (val);
 }
 
 static int
-syscon_generic_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val)
+syscon_generic_unlocked_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val)
 {
 	struct syscon_generic_softc *sc;
 
 	sc = device_get_softc(syscon->pdev);
-
-	SYSCON_LOCK(sc);
+	SYSCON_ASSERT_UNLOCKED(sc);
 	bus_write_4(sc->mem_res, offset, val);
-	SYSCON_UNLOCK(sc);
 	return (0);
 }
 
 static int
-syscon_generic_modify_4(struct syscon *syscon, bus_size_t offset,
+syscon_generic_unlocked_modify_4(struct syscon *syscon, bus_size_t offset,
     uint32_t clear_bits, uint32_t set_bits)
 {
 	struct syscon_generic_softc *sc;
 	uint32_t val;
 
 	sc = device_get_softc(syscon->pdev);
-
-	SYSCON_LOCK(sc);
+	SYSCON_ASSERT_UNLOCKED(sc);
 	val = bus_read_4(sc->mem_res, offset);
 	val &= ~clear_bits;
 	val |= set_bits;
 	bus_write_4(sc->mem_res, offset, val);
-	SYSCON_UNLOCK(sc);
 	return (0);
 }
 
+static void
+syscon_generic_lock(device_t dev)
+{
+	struct syscon_generic_softc *sc;
+
+	sc = device_get_softc(dev);
+	SYSCON_LOCK(sc);
+}
+
+static void
+syscon_generic_unlock(device_t dev)
+{
+	struct syscon_generic_softc *sc;
+
+	sc = device_get_softc(dev);
+	SYSCON_UNLOCK(sc);
+}
+
 static int
 syscon_generic_probe(device_t dev)
 {
@@ -210,6 +223,9 @@ static device_method_t syscon_generic_dmethods[] = {
 	DEVMETHOD(device_probe,		syscon_generic_probe),
 	DEVMETHOD(device_attach,	syscon_generic_attach),
 	DEVMETHOD(device_detach,	syscon_generic_detach),
+
+	DEVMETHOD(syscon_device_lock,	syscon_generic_lock),
+	DEVMETHOD(syscon_device_unlock,	syscon_generic_unlock),
 
 	DEVMETHOD_END
 };

Modified: head/sys/dev/extres/syscon/syscon_if.m
==============================================================================
--- head/sys/dev/extres/syscon/syscon_if.m	Fri Sep 25 16:34:42 2020	(r366160)
+++ head/sys/dev/extres/syscon/syscon_if.m	Fri Sep 25 16:44:01 2020	(r366161)
@@ -35,6 +35,36 @@ HEADER {
 	int syscon_get_handle_default(device_t dev, struct syscon **syscon);
 }
 
+CODE {
+	#include <sys/systm.h>
+	#include <sys/bus.h>
+
+	int
+	syscon_get_handle_default(device_t dev, struct syscon **syscon)
+	{
+		device_t parent;
+
+		parent = device_get_parent(dev);
+		if (parent == NULL)
+			return (ENODEV);
+		return (SYSCON_GET_HANDLE(parent, syscon));
+	}
+
+	static void
+	syscon_device_lock_default(device_t dev)
+	{
+
+		panic("syscon_device_lock is not implemented");
+	};
+
+	static void
+	syscon_device_unlock_default(device_t dev)
+	{
+
+		panic("syscon_device_unlock is not implemented");
+	};
+}
+
 METHOD int init {
 	struct syscon	*syscon;
 };
@@ -63,6 +93,38 @@ METHOD int modify_4 {
 	uint32_t	clear_bits;
 	uint32_t	set_bits;
 };
+
+/**
+ * Unlocked verion of access function
+ */
+METHOD uint32_t unlocked_read_4 {
+	struct syscon	*syscon;
+	bus_size_t	offset;
+};
+
+METHOD int unlocked_write_4 {
+	struct syscon	*syscon;
+	bus_size_t	offset;
+	uint32_t	val;
+};
+
+METHOD int unlocked_modify_4 {
+	struct syscon	*syscon;
+	bus_size_t	offset;
+	uint32_t	clear_bits;
+	uint32_t	set_bits;
+};
+
+/**
+* Locking for exclusive access to underlying device
+*/
+METHOD void device_lock {
+	device_t	dev;
+} DEFAULT syscon_device_lock_default;
+
+METHOD void device_unlock {
+	device_t	dev;
+} DEFAULT syscon_device_unlock_default;
 
 /**
  * Get syscon handle from parent driver


More information about the svn-src-head mailing list