Skip to content

Commit

Permalink
fuspi: Fix 'sleepable after non-sleepable' lock
Browse files Browse the repository at this point in the history
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
      opnsense#1 0xffffffc0002a5556 at witness_checkorder+0x92a
      opnsense#2 0xffffffc000254c7a at _sx_slock_int+0x66
      opnsense#3 0xffffffc00025537a at _sx_slock+0x8
      opnsense#4 0xffffffc000123022 at clk_get_freq+0x38
      opnsense#5 0xffffffc0005463e4 at __clzdi2+0x2bb8
      opnsense#6 0xffffffc00014af58 at randomdev_getkey+0x76e
      opnsense#7 0xffffffc0001278b0 at simplebus_add_device+0x7ee
      opnsense#8 0xffffffc00027c9a8 at device_attach+0x2e6
      opnsense#9 0xffffffc00027c634 at device_probe_and_attach+0x7a
      opnsense#10 0xffffffc00027d76a at bus_generic_attach+0x10
      opnsense#11 0xffffffc00014aab0 at randomdev_getkey+0x2c6
      opnsense#12 0xffffffc00027c9a8 at device_attach+0x2e6
      opnsense#13 0xffffffc00027c634 at device_probe_and_attach+0x7a
      opnsense#14 0xffffffc00027d76a at bus_generic_attach+0x10
      opnsense#15 0xffffffc000278bd2 at config_intrhook_oneshot+0x52
      opnsense#16 0xffffffc000278b3e at config_intrhook_establish+0x146
      opnsense#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
  • Loading branch information
ppaeps committed Dec 29, 2019
1 parent d8fa560 commit 2d581b3
Showing 1 changed file with 8 additions and 9 deletions.
17 changes: 8 additions & 9 deletions sys/riscv/sifive/fu540_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ struct fuspi_softc {
void *ih;

clk_t clk;
uint64_t freq;
uint32_t cs_max;
};

Expand Down Expand Up @@ -207,22 +208,14 @@ fuspi_setup(struct fuspi_softc *sc, uint32_t cs, uint32_t mode,
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) {
Expand Down Expand Up @@ -331,6 +324,12 @@ fuspi_attach(device_t dev)
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;
}

/*
* From Sifive-Unleashed-FU540-C000-v1.0.pdf page 103:
* csdef is cs_width bits wide and all ones on reset.
Expand Down

0 comments on commit 2d581b3

Please sign in to comment.