Author: mmel
Date: Tue Mar 15 15:28:24 2016
New Revision: 296905
URL: https://svnweb.freebsd.org/changeset/base/296905

Log:
  CLK: Add and use explicit locking for access to clock device registers.
  Implicit locking (for read/write/modify) is not sufficient for complex
  cases.

Modified:
  head/sys/dev/extres/clk/clk_div.c
  head/sys/dev/extres/clk/clk_gate.c
  head/sys/dev/extres/clk/clk_mux.c
  head/sys/dev/extres/clk/clkdev_if.m

Modified: head/sys/dev/extres/clk/clk_div.c
==============================================================================
--- head/sys/dev/extres/clk/clk_div.c   Tue Mar 15 15:27:15 2016        
(r296904)
+++ head/sys/dev/extres/clk/clk_div.c   Tue Mar 15 15:28:24 2016        
(r296905)
@@ -46,6 +46,10 @@ __FBSDID("$FreeBSD$");
        CLKDEV_READ_4(clknode_get_device(_clk), off, val)
 #define        MD4(_clk, off, clr, set )                                       
\
        CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
+#define        DEVICE_LOCK(_clk)                                               
        \
+       CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define        DEVICE_UNLOCK(_clk)                                             
\
+       CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
 
 static int clknode_div_init(struct clknode *clk, device_t dev);
 static int clknode_div_recalc(struct clknode *clk, uint64_t *req);
@@ -86,7 +90,9 @@ clknode_div_init(struct clknode *clk, de
 
        sc = clknode_get_softc(clk);
 
+       DEVICE_LOCK(clk);
        rv = RD4(clk, sc->offset, &reg);
+       DEVICE_UNLOCK(clk);
        if (rv != 0)
                return (rv);
 
@@ -171,12 +177,17 @@ clknode_div_set_freq(struct clknode *clk
                    (*fout != (_fin / divider)))
                        return (ERANGE);
 
+               DEVICE_LOCK(clk);
                rv = MD4(clk, sc->offset,
                    (sc->i_mask << sc->i_shift) | (sc->f_mask << sc->f_shift),
                    (i_div << sc->i_shift) | (f_div << sc->f_shift));
-               if (rv != 0)
+               if (rv != 0) {
+                       DEVICE_UNLOCK(clk);
                        return (rv);
+               }
                RD4(clk, sc->offset, &reg);
+               DEVICE_UNLOCK(clk);
+
                sc->divider = divider;
        }
 

Modified: head/sys/dev/extres/clk/clk_gate.c
==============================================================================
--- head/sys/dev/extres/clk/clk_gate.c  Tue Mar 15 15:27:15 2016        
(r296904)
+++ head/sys/dev/extres/clk/clk_gate.c  Tue Mar 15 15:28:24 2016        
(r296905)
@@ -46,7 +46,10 @@ __FBSDID("$FreeBSD$");
        CLKDEV_READ_4(clknode_get_device(_clk), off, val)
 #define        MD4(_clk, off, clr, set )                                       
\
        CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
-
+#define        DEVICE_LOCK(_clk)                                               
        \
+       CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define        DEVICE_UNLOCK(_clk)                                             
\
+       CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
 
 static int clknode_gate_init(struct clknode *clk, device_t dev);
 static int clknode_gate_set_gate(struct clknode *clk, bool enable);
@@ -77,7 +80,9 @@ clknode_gate_init(struct clknode *clk, d
        int rv;
 
        sc = clknode_get_softc(clk);
+       DEVICE_LOCK(clk);
        rv = RD4(clk, sc->offset, &reg);
+       DEVICE_UNLOCK(clk);
        if (rv != 0)
                return (rv);
        reg = (reg >> sc->shift) & sc->mask;
@@ -95,11 +100,15 @@ clknode_gate_set_gate(struct clknode *cl
 
        sc = clknode_get_softc(clk);
        sc->ungated = enable;
+       DEVICE_LOCK(clk);
        rv = MD4(clk, sc->offset, sc->mask << sc->shift,
            (sc->ungated ? sc->on_value : sc->off_value) << sc->shift);
-       if (rv != 0)
+       if (rv != 0) {
+               DEVICE_UNLOCK(clk);
                return (rv);
+       }
        RD4(clk, sc->offset, &reg);
+       DEVICE_UNLOCK(clk);
        return(0);
 }
 

Modified: head/sys/dev/extres/clk/clk_mux.c
==============================================================================
--- head/sys/dev/extres/clk/clk_mux.c   Tue Mar 15 15:27:15 2016        
(r296904)
+++ head/sys/dev/extres/clk/clk_mux.c   Tue Mar 15 15:28:24 2016        
(r296905)
@@ -46,6 +46,10 @@ __FBSDID("$FreeBSD$");
        CLKDEV_READ_4(clknode_get_device(_clk), off, val)
 #define        MD4(_clk, off, clr, set )                                       
\
        CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
+#define        DEVICE_LOCK(_clk)                                               
        \
+       CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define        DEVICE_UNLOCK(_clk)                                             
\
+       CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
 
 static int clknode_mux_init(struct clknode *clk, device_t dev);
 static int clknode_mux_set_mux(struct clknode *clk, int idx);
@@ -76,9 +80,12 @@ clknode_mux_init(struct clknode *clk, de
 
        sc = clknode_get_softc(clk);
 
+       DEVICE_LOCK(clk);
        rv = RD4(clk, sc->offset, &reg);
-       if (rv != 0)
+       DEVICE_UNLOCK(clk);
+       if (rv != 0) {
                return (rv);
+       }
        reg = (reg >> sc->shift) & sc->mask;
        clknode_init_parent_idx(clk, reg);
        return(0);
@@ -93,11 +100,16 @@ clknode_mux_set_mux(struct clknode *clk,
 
        sc = clknode_get_softc(clk);
 
+       DEVICE_LOCK(clk);
        rv = MD4(clk, sc->offset, sc->mask << sc->shift,
            (idx & sc->mask) << sc->shift);
-       if (rv != 0)
+       if (rv != 0) {
+               DEVICE_UNLOCK(clk);
                return (rv);
+       }
        RD4(clk, sc->offset, &reg);
+       DEVICE_UNLOCK(clk);
+
        return(0);
 }
 

Modified: head/sys/dev/extres/clk/clkdev_if.m
==============================================================================
--- head/sys/dev/extres/clk/clkdev_if.m Tue Mar 15 15:27:15 2016        
(r296904)
+++ head/sys/dev/extres/clk/clkdev_if.m Tue Mar 15 15:28:24 2016        
(r296905)
@@ -30,6 +30,23 @@
 
 INTERFACE clkdev;
 
+CODE {
+       #include <sys/systm.h>
+       static void
+       clkdev_default_device_lock(device_t dev)
+       {
+
+               panic("clkdev_device_lock() is not implemented");
+       }
+
+       static void
+       clkdev_default_device_unlock(device_t dev)
+       {
+
+               panic("clkdev_device_unlock() is not implemented");
+       }
+}
+
 #
 # Write single register
 #
@@ -57,3 +74,17 @@ METHOD int modify_4 {
        uint32_t        clear_mask;
        uint32_t        set_mask;
 };
+
+#
+# Get exclusive access to underlying device
+#
+METHOD void device_lock {
+       device_t        dev;
+} DEFAULT clkdev_default_device_lock;
+
+#
+# Release exclusive access to underlying device
+#
+METHOD void device_unlock {
+       device_t        dev;
+} DEFAULT clkdev_default_device_unlock;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to