svn commit: r356166 - head/sys/riscv/sifive

Philip Paeps philip at FreeBSD.org
Sun Dec 29 04:26:10 UTC 2019


Author: philip
Date: Sun Dec 29 04:26:10 2019
New Revision: 356166
URL: https://svnweb.freebsd.org/changeset/base/356166

Log:
  fuspi: Fix 'sleepable after non-sleepable' lock
  
  With WITNESS enabled we see the following warning:
  
      lock order reversal: (sleepable after non-sleepable)
       1st 0xffffffd0847c7210 fu540spi0 (fu540spi0) @
       /usr/home/kp/axiado/hornet-freebsd/src/sys/riscv/sifive/fu540_spi.c:297
        2nd 0xffffffc00372bb30 Clock topology lock (Clock topology lock) @
        /usr/home/kp/axiado/hornet-freebsd/src/sys/dev/extres/clk/clk.c:1137
        stack backtrace:
        #0 0xffffffc0002a579e at witness_checkorder+0xb72
        #1 0xffffffc0002a5556 at witness_checkorder+0x92a
        #2 0xffffffc000254c7a at _sx_slock_int+0x66
        #3 0xffffffc00025537a at _sx_slock+0x8
        #4 0xffffffc000123022 at clk_get_freq+0x38
        #5 0xffffffc0005463e4 at __clzdi2+0x2bb8
        #6 0xffffffc00014af58 at randomdev_getkey+0x76e
        #7 0xffffffc0001278b0 at simplebus_add_device+0x7ee
        #8 0xffffffc00027c9a8 at device_attach+0x2e6
        #9 0xffffffc00027c634 at device_probe_and_attach+0x7a
        #10 0xffffffc00027d76a at bus_generic_attach+0x10
        #11 0xffffffc00014aab0 at randomdev_getkey+0x2c6
        #12 0xffffffc00027c9a8 at device_attach+0x2e6
        #13 0xffffffc00027c634 at device_probe_and_attach+0x7a
        #14 0xffffffc00027d76a at bus_generic_attach+0x10
        #15 0xffffffc000278bd2 at config_intrhook_oneshot+0x52
        #16 0xffffffc000278b3e at config_intrhook_establish+0x146
        #17 0xffffffc000278cf2 at config_intrhook_disestablish+0xfe
  
  The clock topology lock can sleep, which means we cannot attempt to
  acquire it while holding the non-sleepable mutex.
  
  Fix that by retrieving the clock speed once, during attach and not every
  time during SPI transaction setup.
  
  Submitted by:   kp
  Sponsored by:   Axiado

Modified:
  head/sys/riscv/sifive/fu540_spi.c

Modified: head/sys/riscv/sifive/fu540_spi.c
==============================================================================
--- head/sys/riscv/sifive/fu540_spi.c	Sun Dec 29 02:12:18 2019	(r356165)
+++ head/sys/riscv/sifive/fu540_spi.c	Sun Dec 29 04:26:10 2019	(r356166)
@@ -80,6 +80,7 @@ struct fuspi_softc {
 	void			*ih;
 
 	clk_t			clk;
+	uint64_t		freq;
 	uint32_t		cs_max;
 };
 
@@ -207,22 +208,14 @@ fuspi_setup(struct fuspi_softc *sc, uint32_t cs, uint3
     uint32_t freq)
 {
 	uint32_t csmode, fmt, sckdiv, sckmode;
-	uint64_t clock;
-	int ret;
 
 	FUSPI_ASSERT_LOCKED(sc);
 
-	ret = clk_get_freq(sc->clk, &clock);
-	if (ret) {
-		device_printf(sc->dev, "Cannot get clock frequency: %d\n", ret);
-		return (ret);
-	}
-
 	/*
 	 * Fsck = Fin / 2 * (div + 1)
 	 * -> div = Fin / (2 * Fsck) - 1
 	 */
-	sckdiv = (howmany(clock >> 1, freq) - 1) & FUSPI_SCKDIV_MASK;
+	sckdiv = (howmany(sc->freq >> 1, freq) - 1) & FUSPI_SCKDIV_MASK;
 	FUSPI_WRITE(sc, FUSPI_REG_SCKDIV, sckdiv);
 
 	switch (mode) {
@@ -328,6 +321,12 @@ fuspi_attach(device_t dev)
 	error = clk_enable(sc->clk);
 	if (error) {
 		device_printf(dev, "Couldn't enable clock: %d\n", error);
+		goto fail;
+	}
+
+	error = clk_get_freq(sc->clk, &sc->freq);
+	if (error) {
+		device_printf(sc->dev, "Couldn't get frequency: %d\n", error);
 		goto fail;
 	}
 


More information about the svn-src-head mailing list