Author: ian
Date: Tue Jun  2 16:07:28 2015
New Revision: 283918
URL: https://svnweb.freebsd.org/changeset/base/283918

Log:
  Add a missing wakeup when releasing ownership of the SPI hardware.
  
  Also, validate the chipselect parameter before grabbing ownership of the
  hardware, and report timeout errors after releasing it.
  
  PR:           200584

Modified:
  head/sys/arm/broadcom/bcm2835/bcm2835_spi.c

Modified: head/sys/arm/broadcom/bcm2835/bcm2835_spi.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_spi.c Tue Jun  2 15:35:38 2015        
(r283917)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_spi.c Tue Jun  2 16:07:28 2015        
(r283918)
@@ -427,6 +427,15 @@ bcm_spi_transfer(device_t dev, device_t 
        KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, 
            ("TX/RX data sizes should be equal"));
 
+       /* Get the proper chip select for this child. */
+       spibus_get_cs(child, &cs);
+       if (cs < 0 || cs > 2) {
+               device_printf(dev,
+                   "Invalid chip select %d requested by %s\n", cs,
+                   device_get_nameunit(child));
+               return (EINVAL);
+       }
+
        BCM_SPI_LOCK(sc);
 
        /* If the controller is in use wait until it is available. */
@@ -441,16 +450,6 @@ bcm_spi_transfer(device_t dev, device_t 
            SPI_CS_CLEAR_RXFIFO | SPI_CS_CLEAR_TXFIFO,
            SPI_CS_CLEAR_RXFIFO | SPI_CS_CLEAR_TXFIFO);
 
-       /* Get the proper chip select for this child. */
-       spibus_get_cs(child, &cs);
-       if (cs < 0 || cs > 2) {
-               device_printf(dev,
-                   "Invalid chip select %d requested by %s\n", cs,
-                   device_get_nameunit(child));
-               BCM_SPI_UNLOCK(sc);
-               return (EINVAL);
-       }
-
        /* Save a pointer to the SPI command. */
        sc->sc_cmd = cmd;
        sc->sc_read = 0;
@@ -471,8 +470,10 @@ bcm_spi_transfer(device_t dev, device_t 
        /* Make sure the SPI engine and interrupts are disabled. */
        bcm_spi_modifyreg(sc, SPI_CS, SPI_CS_TA | SPI_CS_INTR | SPI_CS_INTD, 0);
 
-       /* Clear the controller flags. */
+       /* Release the controller and wakeup the next thread waiting for it. */
        sc->sc_flags = 0;
+       wakeup_one(dev);
+       BCM_SPI_UNLOCK(sc);
 
        /*
         * Check for transfer timeout.  The SPI controller doesn't
@@ -483,8 +484,6 @@ bcm_spi_transfer(device_t dev, device_t 
                err = EIO;
        }
 
-       BCM_SPI_UNLOCK(sc);
-
        return (err);
 }
 
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to