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