Diff
Modified: trunk/drivers/mmc/host/mmc_spi.c (9221 => 9222)
--- trunk/drivers/mmc/host/mmc_spi.c 2010-10-16 21:13:03 UTC (rev 9221)
+++ trunk/drivers/mmc/host/mmc_spi.c 2010-10-16 21:40:24 UTC (rev 9222)
@@ -182,7 +182,7 @@
host->data_dma, sizeof(*host->data),
DMA_FROM_DEVICE);
- status = spi_sync(host->spi, &host->readback);
+ status = spi_sync_locked(host->spi, &host->readback);
if (host->dma_dev)
dma_sync_single_for_cpu(host->dma_dev,
@@ -541,7 +541,7 @@
host->data_dma, sizeof(*host->data),
DMA_BIDIRECTIONAL);
}
- status = spi_sync(host->spi, &host->m);
+ status = spi_sync_locked(host->spi, &host->m);
if (host->dma_dev)
dma_sync_single_for_cpu(host->dma_dev,
@@ -685,7 +685,7 @@
host->data_dma, sizeof(*scratch),
DMA_BIDIRECTIONAL);
- status = spi_sync(spi, &host->m);
+ status = spi_sync_locked(spi, &host->m);
if (status != 0) {
dev_dbg(&spi->dev, "write error (%d)\n", status);
@@ -822,7 +822,7 @@
DMA_FROM_DEVICE);
}
- status = spi_sync(spi, &host->m);
+ status = spi_sync_locked(spi, &host->m);
if (host->dma_dev) {
dma_sync_single_for_cpu(host->dma_dev,
@@ -1018,7 +1018,7 @@
host->data_dma, sizeof(*scratch),
DMA_BIDIRECTIONAL);
- tmp = spi_sync(spi, &host->m);
+ tmp = spi_sync_locked(spi, &host->m);
if (host->dma_dev)
dma_sync_single_for_cpu(host->dma_dev,
@@ -1086,14 +1086,11 @@
}
#endif
- /* issue command; then optionally data and stop */
- status = spi_lock_bus(host->spi);
- if (status == -ENOLCK) {
- dev_err(&host->spi->dev, "failed to lock spi bus\n");
- return;
- }
+ /* request exclusive bus access */
+ spi_bus_lock(host->spi->master);
-crc_recover:
+ crc_recover:
+ /* issue command; then optionally data and stop */
status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL);
if (status == 0 && mrq->data) {
mmc_spi_data_do(host, mrq->cmd, mrq->data, mrq->data->blksz);
@@ -1121,11 +1118,10 @@
else
mmc_cs_off(host);
}
- status = spi_unlock_bus(host->spi);
- if (status == -ENOLCK) {
- dev_err(&host->spi->dev, "failed to unlock spi bus\n");
- return;
- }
+
+ /* release the bus */
+ spi_bus_unlock(host->spi->master);
+
mmc_request_done(host->mmc, mrq);
}
@@ -1322,23 +1318,6 @@
return IRQ_HANDLED;
}
-struct count_children {
- unsigned n;
- struct bus_type *bus;
-};
-
-static int maybe_count_child(struct device *dev, void *c)
-{
- struct count_children *ccp = c;
-
- if (dev->bus == ccp->bus) {
- if (ccp->n)
- return -EBUSY;
- ccp->n++;
- }
- return 0;
-}
-
static int mmc_spi_probe(struct spi_device *spi)
{
void *ones;
@@ -1370,41 +1349,6 @@
return status;
}
- /* We can use the bus safely if nobody else will interfere with us.
- * Most commands consist of one SPI message to issue a command, then
- * several more to collect its response, then possibly more for data
- * transfer. Clocking access to other devices during that period will
- * corrupt the command execution.
- *
- * spi_lock_bus() is used to guarantee exclusive access to spi bus. For
- * system without spi_lock_bus(), if mmc_spi is the only registered spi
- * device, we use spi bus based on the unsafe assumption that no other
- * spi devices will be added later.
- */
-
- if (spi->master->num_chipselect > 1) {
- struct count_children cc;
-
- /* Test if spi master implementes spi_lock_bus() */
- status = spi_lock_bus(spi);
- spi_unlock_bus(spi);
- if (status == -ENOSYS) {
- /* No. Am I the only spi device registered? */
- cc.n = 0;
- cc.bus = spi->dev.bus;
- status = device_for_each_child(spi->dev.parent, &cc,
- maybe_count_child);
- if (status < 0) {
- dev_err(&spi->dev, "can't share SPI bus\n");
- return status;
- }
- /* REVISIT we can't guarantee another device
- * won't be added later... */
- dev_warn(&spi->dev,
- "ASSUMING SPI bus stays unshared!\n");
- }
- }
-
/* We need a supply of ones to transmit. This is the only time
* the CPU touches these, so cache coherency isn't a concern.
*
Modified: trunk/drivers/spi/Kconfig (9221 => 9222)
--- trunk/drivers/spi/Kconfig 2010-10-16 21:13:03 UTC (rev 9221)
+++ trunk/drivers/spi/Kconfig 2010-10-16 21:40:24 UTC (rev 9222)
@@ -66,14 +66,6 @@
help
This is the SPI controller master driver for Blackfin 5xx processor.
-config SPI_BFIN_LOCK
- bool "SPI bus lock"
- depends on SPI_BFIN
- default n
- help
- Enable support for spi_lock_bus()/spi_unlock_bus(). Useful when multiple
- SPI devices share a bus, especially for devices like MMC_SPI.
-
config SPI_BFIN_SPORT
tristate "emulate SPI bus with Blackfin SPORT"
depends on BLACKFIN
Modified: trunk/drivers/spi/bfin_sport_spi.c (9221 => 9222)
--- trunk/drivers/spi/bfin_sport_spi.c 2010-10-16 21:13:03 UTC (rev 9221)
+++ trunk/drivers/spi/bfin_sport_spi.c 2010-10-16 21:40:24 UTC (rev 9222)
@@ -70,10 +70,7 @@
struct list_head queue;
int busy;
bool run;
-#ifdef CONFIG_SPI_BFIN_LOCK
- /* SPI bus is lock by a slave for exclusive access */
- int locked;
-#endif
+
/* Message Transfer pump */
struct tasklet_struct pump_transfers;
@@ -474,10 +471,6 @@
struct master_data *drv_data;
unsigned long flags;
struct spi_message *next_msg;
-#ifdef CONFIG_SPI_BFIN_LOCK
- int locked_cs = -1;
- struct spi_message *msg = NULL;
-#endif
drv_data = container_of(work, struct master_data, pump_messages);
@@ -500,27 +493,6 @@
next_msg = list_entry(drv_data->queue.next,
struct spi_message, queue);
-#ifdef CONFIG_SPI_BFIN_LOCK
- if (drv_data->locked)
- locked_cs = drv_data->locked;
-
- /* Someone has locked the bus */
- if (drv_data->locked && next_msg->spi->chip_select != locked_cs) {
- list_for_each_entry(msg, &drv_data->queue, queue) {
- if (msg->spi->chip_select == locked_cs) {
- next_msg = msg;
- break;
- }
- }
- /* Do nothing even if there are messages for other devices */
- if (next_msg->spi->chip_select != locked_cs) {
- drv_data->busy = 0;
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return;
- }
- }
-#endif
-
drv_data->cur_msg = next_msg;
/* Setup the SSP using the per chip configuration */
@@ -550,42 +522,6 @@
}
/*
- * lock the spi bus for exclusive access
- */
-#ifdef CONFIG_SPI_BFIN_LOCK
-static int bfin_sport_spi_lock_bus(struct spi_device *spi)
-{
- struct master_data *drv_data = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- spin_lock_irqsave(&drv_data->lock, flags);
- if (drv_data->locked) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return -ENOLCK;
- }
- drv_data->locked = spi->chip_select;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- return 0;
-}
-
-static int bfin_sport_spi_unlock_bus(struct spi_device *spi)
-{
- struct master_data *drv_data = spi_master_get_devdata(spi->master);
- unsigned long flags;
-
- spin_lock_irqsave(&drv_data->lock, flags);
- drv_data->locked = 0;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-
- return 0;
-}
-#else
-# define bfin_sport_spi_lock_bus NULL
-# define bfin_sport_spi_unlock_bus NULL
-#endif
-
-/*
* got a msg to transfer, queue it in drv_data->queue.
* And kick off message pumper
*/
@@ -715,9 +651,6 @@
INIT_LIST_HEAD(&drv_data->queue);
spin_lock_init(&drv_data->lock);
-#ifdef CONFIG_SPI_BFIN_LOCK
- drv_data->locked = 0;
-#endif
drv_data->run = false;
drv_data->busy = 0;
@@ -765,9 +698,6 @@
spin_lock_irqsave(&drv_data->lock, flags);
-#ifdef CONFIG_SPI_BFIN_LOCK
- drv_data->locked = 0;
-#endif
/*
* This is a bit lame, but is optimized for the common execution path.
* A wait_queue on the drv_data->busy could be used, but then the common
@@ -831,8 +761,6 @@
master->cleanup = bfin_sport_spi_cleanup;
master->setup = bfin_sport_spi_setup;
master->transfer = bfin_sport_spi_transfer;
- master->lock_bus = bfin_sport_spi_lock_bus;
- master->unlock_bus = bfin_sport_spi_unlock_bus;
/* Find and map our resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Modified: trunk/drivers/spi/spi.c (9221 => 9222)
--- trunk/drivers/spi/spi.c 2010-10-16 21:13:03 UTC (rev 9221)
+++ trunk/drivers/spi/spi.c 2010-10-16 21:40:24 UTC (rev 9222)
@@ -527,6 +527,10 @@
dynamic = 1;
}
+ spin_lock_init(&master->bus_lock_spinlock);
+ mutex_init(&master->bus_lock_mutex);
+ master->bus_lock_flag = 0;
+
/* register the device, then userspace will see it.
* registration fails if the bus ID is in use.
*/
@@ -666,6 +670,35 @@
}
EXPORT_SYMBOL_GPL(spi_setup);
+static int __spi_async(struct spi_device *spi, struct spi_message *message)
+{
+ struct spi_master *master = spi->master;
+
+ /* Half-duplex links include original MicroWire, and ones with
+ * only one data pin like SPI_3WIRE (switches direction) or where
+ * either MOSI or MISO is missing. They can also be caused by
+ * software limitations.
+ */
+ if ((master->flags & SPI_MASTER_HALF_DUPLEX)
+ || (spi->mode & SPI_3WIRE)) {
+ struct spi_transfer *xfer;
+ unsigned flags = master->flags;
+
+ list_for_each_entry(xfer, &message->transfers, transfer_list) {
+ if (xfer->rx_buf && xfer->tx_buf)
+ return -EINVAL;
+ if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf)
+ return -EINVAL;
+ if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf)
+ return -EINVAL;
+ }
+ }
+
+ message->spi = spi;
+ message->status = -EINPROGRESS;
+ return master->transfer(spi, message);
+}
+
/**
* spi_async - asynchronous SPI transfer
* @spi: device with which data will be exchanged
@@ -698,34 +731,69 @@
int spi_async(struct spi_device *spi, struct spi_message *message)
{
struct spi_master *master = spi->master;
+ int ret;
+ unsigned long flags;
- /* Half-duplex links include original MicroWire, and ones with
- * only one data pin like SPI_3WIRE (switches direction) or where
- * either MOSI or MISO is missing. They can also be caused by
- * software limitations.
- */
- if ((master->flags & SPI_MASTER_HALF_DUPLEX)
- || (spi->mode & SPI_3WIRE)) {
- struct spi_transfer *xfer;
- unsigned flags = master->flags;
+ spin_lock_irqsave(&master->bus_lock_spinlock, flags);
- list_for_each_entry(xfer, &message->transfers, transfer_list) {
- if (xfer->rx_buf && xfer->tx_buf)
- return -EINVAL;
- if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf)
- return -EINVAL;
- if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf)
- return -EINVAL;
- }
- }
+ if (master->bus_lock_flag)
+ ret = -EBUSY;
+ else
+ ret = __spi_async(spi, message);
- message->spi = spi;
- message->status = -EINPROGRESS;
- return master->transfer(spi, message);
+ spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(spi_async);
+/**
+ * spi_async_locked - version of spi_async with exclusive bus usage
+ * @spi: device with which data will be exchanged
+ * @message: describes the data transfers, including completion callback
+ * Context: any (irqs may be blocked, etc)
+ *
+ * This call may be used in_irq and other contexts which can't sleep,
+ * as well as from task contexts which can sleep.
+ *
+ * The completion callback is invoked in a context which can't sleep.
+ * Before that invocation, the value of message->status is undefined.
+ * When the callback is issued, message->status holds either zero (to
+ * indicate complete success) or a negative error code. After that
+ * callback returns, the driver which issued the transfer request may
+ * deallocate the associated memory; it's no longer in use by any SPI
+ * core or controller driver code.
+ *
+ * Note that although all messages to a spi_device are handled in
+ * FIFO order, messages may go to different devices in other orders.
+ * Some device might be higher priority, or have various "hard" access
+ * time requirements, for example.
+ *
+ * On detection of any fault during the transfer, processing of
+ * the entire message is aborted, and the device is deselected.
+ * Until returning from the associated message completion callback,
+ * no other spi_message queued to that device will be processed.
+ * (This rule applies equally to all the synchronous transfer calls,
+ * which are wrappers around this core asynchronous primitive.)
+ */
+int spi_async_locked(struct spi_device *spi, struct spi_message *message)
+{
+ struct spi_master *master = spi->master;
+ int ret;
+ unsigned long flags;
+ spin_lock_irqsave(&master->bus_lock_spinlock, flags);
+
+ ret = __spi_async(spi, message);
+
+ spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
+
+ return ret;
+
+}
+EXPORT_SYMBOL_GPL(spi_async_locked);
+
+
/*-------------------------------------------------------------------------*/
/* Utility methods for SPI master protocol drivers, layered on
@@ -738,57 +806,31 @@
complete(arg);
}
-/**
- * spi_lock_bus - lock SPI bus for exclusive access
- * @spi: device which want to lock the bus
- * Context: any
- *
- * Once the caller owns exclusive access to the SPI bus,
- * only messages for this device will be transferred.
- * Messages for other devices are queued but not transferred until
- * the bus owner unlock the bus.
- *
- * The caller may call spi_lock_bus() before spi_sync() or spi_async().
- * So this call may be used in irq and other contexts which can't sleep,
- * as well as from task contexts which can sleep.
- *
- * It returns zero on success, else a negative error code:
- * -ENOSYS: spi master driver does not implement this function
- * -ENOLCK: cannot lock the bus
- */
-int spi_lock_bus(struct spi_device *spi)
+static int __spi_sync(struct spi_device *spi, struct spi_message *message,
+ int bus_locked)
{
- if (spi->master->lock_bus)
- return spi->master->lock_bus(spi);
- else
- return -ENOSYS;
-}
-EXPORT_SYMBOL_GPL(spi_lock_bus);
+ DECLARE_COMPLETION_ONSTACK(done);
+ int status;
+ struct spi_master *master = spi->master;
-/**
- * spi_unlock_bus - unlock SPI bus
- * @spi: device which want to unlock the bus
- * Context: any
- *
- * The caller has called spi_lock_bus() to lock the bus. It calls
- * spi_unlock_bus() to release the bus so messages for other devices
- * can be transferred.
- *
- * If the caller did not call spi_lock_bus() before, spi_unlock_bus()
- * will return -ENOLCK.
- *
- * It returns zero on success, else a negative error code:
- * -ENOSYS: spi master driver does not implement this function
- * -ENOLCK: cannot unlock the bus
- */
-int spi_unlock_bus(struct spi_device *spi)
-{
- if (spi->master->unlock_bus)
- return spi->master->unlock_bus(spi);
- else
- return -ENOSYS;
+ message->complete = spi_complete;
+ message->context = &done;
+
+ if (!bus_locked)
+ mutex_lock(&master->bus_lock_mutex);
+
+ status = spi_async_locked(spi, message);
+
+ if (!bus_locked)
+ mutex_unlock(&master->bus_lock_mutex);
+
+ if (status == 0) {
+ wait_for_completion(&done);
+ status = message->status;
+ }
+ message->context = NULL;
+ return status;
}
-EXPORT_SYMBOL_GPL(spi_unlock_bus);
/**
* spi_sync - blocking/synchronous SPI data transfers
@@ -813,21 +855,86 @@
*/
int spi_sync(struct spi_device *spi, struct spi_message *message)
{
- DECLARE_COMPLETION_ONSTACK(done);
- int status;
-
- message->complete = spi_complete;
- message->context = &done;
- status = spi_async(spi, message);
- if (status == 0) {
- wait_for_completion(&done);
- status = message->status;
- }
- message->context = NULL;
- return status;
+ return __spi_sync(spi, message, 0);
}
EXPORT_SYMBOL_GPL(spi_sync);
+/**
+ * spi_sync_locked - version of spi_sync with exclusive bus usage
+ * @spi: device with which data will be exchanged
+ * @message: describes the data transfers
+ * Context: can sleep
+ *
+ * This call may only be used from a context that may sleep. The sleep
+ * is non-interruptible, and has no timeout. Low-overhead controller
+ * drivers may DMA directly into and out of the message buffers.
+ *
+ * This call should be used by drivers that require exclusive access to the
+ * SPI bus. It has to be preceeded by a spi_bus_lock call. The SPI bus must
+ * be released by a spi_bus_unlock call when the exclusive access is over.
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int spi_sync_locked(struct spi_device *spi, struct spi_message *message)
+{
+ return __spi_sync(spi, message, 1);
+}
+EXPORT_SYMBOL_GPL(spi_sync_locked);
+
+/**
+ * spi_bus_lock - obtain a lock for exclusive SPI bus usage
+ * @master: SPI bus master that should be locked for exclusive bus access
+ * Context: can sleep
+ *
+ * This call may only be used from a context that may sleep. The sleep
+ * is non-interruptible, and has no timeout.
+ *
+ * This call should be used by drivers that require exclusive access to the
+ * SPI bus. The SPI bus must be released by a spi_bus_unlock call when the
+ * exclusive access is over. Data transfer must be done by spi_sync_locked
+ * and spi_async_locked calls when the SPI bus lock is held.
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int spi_bus_lock(struct spi_master *master)
+{
+ unsigned long flags;
+
+ mutex_lock(&master->bus_lock_mutex);
+
+ spin_lock_irqsave(&master->bus_lock_spinlock, flags);
+ master->bus_lock_flag = 1;
+ spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
+
+ /* mutex remains locked until spi_bus_unlock is called */
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bus_lock);
+
+/**
+ * spi_bus_unlock - release the lock for exclusive SPI bus usage
+ * @master: SPI bus master that was locked for exclusive bus access
+ * Context: can sleep
+ *
+ * This call may only be used from a context that may sleep. The sleep
+ * is non-interruptible, and has no timeout.
+ *
+ * This call releases an SPI bus lock previously obtained by an spi_bus_lock
+ * call.
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int spi_bus_unlock(struct spi_master *master)
+{
+ master->bus_lock_flag = 0;
+
+ mutex_unlock(&master->bus_lock_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bus_unlock);
+
/* portable code must never pass more than 32 bytes */
#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
Modified: trunk/drivers/spi/spi_bfin5xx.c (9221 => 9222)
--- trunk/drivers/spi/spi_bfin5xx.c 2010-10-16 21:13:03 UTC (rev 9221)
+++ trunk/drivers/spi/spi_bfin5xx.c 2010-10-16 21:40:24 UTC (rev 9222)
@@ -73,10 +73,7 @@
struct list_head queue;
int busy;
bool running;
-#ifdef CONFIG_SPI_BFIN_LOCK
- /* SPI bus is lock by a slave for exclusive access */
- int locked;
-#endif
+
/* Message Transfer pump */
struct tasklet_struct pump_transfers;
@@ -882,12 +879,6 @@
{
struct master_data *drv_data;
unsigned long flags;
-#ifdef CONFIG_SPI_BFIN_LOCK
- int locked_cs = -1;
- int next_cs = -1;
- struct slave_data *chip = NULL;
- struct spi_message *next_msg = NULL, *msg = NULL;
-#endif
drv_data = container_of(work, struct master_data, pump_messages);
@@ -906,42 +897,10 @@
return;
}
-#ifdef CONFIG_SPI_BFIN_LOCK
/* Extract head of queue */
- next_msg = list_entry(drv_data->queue.next,
- struct spi_message, queue);
-
- if (drv_data->locked) {
- locked_cs = drv_data->locked;
- chip = spi_get_ctldata(next_msg->spi);
- next_cs = next_msg->spi->chip_select ? next_msg->spi->chip_select :
- chip->cs_gpio;
- }
-
- /* Someone has locked the bus */
- if (drv_data->locked && next_cs != locked_cs) {
- list_for_each_entry(msg, &drv_data->queue, queue) {
- chip = spi_get_ctldata(msg->spi);
- next_cs = msg->spi->chip_select ?
- msg->spi->chip_select : chip->cs_gpio;
- if (next_cs == locked_cs) {
- next_msg = msg;
- break;
- }
- }
- /* Do nothing even if there are messages for other devices */
- if (next_cs != locked_cs) {
- drv_data->busy = 0;
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return;
- }
- }
- drv_data->cur_msg = next_msg;
-#else
- /* Extract head of queue */
drv_data->cur_msg = list_entry(drv_data->queue.next,
- struct spi_message, queue);
-#endif
+ struct spi_message, queue);
+
/* Setup the SSP using the per chip configuration */
drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
bfin_spi_restore_state(drv_data);
@@ -970,54 +929,6 @@
}
/*
- * lock the spi bus for exclusive access
- */
-static int bfin_spi_lock_bus(struct spi_device *spi)
-{
- int ret = -ENOSYS;
-#ifdef CONFIG_SPI_BFIN_LOCK
- struct master_data *drv_data = spi_master_get_devdata(spi->master);
- struct slave_data *chip = spi_get_ctldata(spi);
- unsigned long flags;
-
- spin_lock_irqsave(&drv_data->lock, flags);
- if (!drv_data->locked) {
- drv_data->locked = spi->chip_select ?
- spi->chip_select : chip->cs_gpio;
- ret = 0;
- } else
- ret = -ENOLCK;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-#endif
- return ret;
-}
-
-static int bfin_spi_unlock_bus(struct spi_device *spi)
-{
- int ret = -ENOSYS;
-#ifdef CONFIG_SPI_BFIN_LOCK
- struct master_data *drv_data = spi_master_get_devdata(spi->master);
- struct slave_data *chip = spi_get_ctldata(spi);
- unsigned long flags;
- int cs = spi->chip_select ? spi->chip_select : chip->cs_gpio;
-
- spin_lock_irqsave(&drv_data->lock, flags);
- if (cs == drv_data->locked) {
- drv_data->locked = 0;
- ret = 0;
-
- /* kick off transfer of all pending messeages */
- if (drv_data->running && !drv_data->busy &&
- !list_empty(&drv_data->queue))
- queue_work(drv_data->workqueue, &drv_data->pump_messages);
- } else
- ret = -ENOLCK;
- spin_unlock_irqrestore(&drv_data->lock, flags);
-#endif
- return ret;
-}
-
-/*
* got a msg to transfer, queue it in drv_data->queue.
* And kick off message pumper
*/
@@ -1286,9 +1197,6 @@
INIT_LIST_HEAD(&drv_data->queue);
spin_lock_init(&drv_data->lock);
-#ifdef CONFIG_SPI_BFIN_LOCK
- drv_data->locked = 0;
-#endif
drv_data->running = false;
drv_data->busy = 0;
@@ -1336,9 +1244,6 @@
spin_lock_irqsave(&drv_data->lock, flags);
-#ifdef CONFIG_SPI_BFIN_LOCK
- drv_data->locked = 0;
-#endif
/*
* This is a bit lame, but is optimized for the common execution path.
* A wait_queue on the drv_data->busy could be used, but then the common
@@ -1405,8 +1310,6 @@
master->cleanup = bfin_spi_cleanup;
master->setup = bfin_spi_setup;
master->transfer = bfin_spi_transfer;
- master->lock_bus = bfin_spi_lock_bus;
- master->unlock_bus = bfin_spi_unlock_bus;
/* Find and map our resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Modified: trunk/include/linux/spi/spi.h (9221 => 9222)
--- trunk/include/linux/spi/spi.h 2010-10-16 21:13:03 UTC (rev 9221)
+++ trunk/include/linux/spi/spi.h 2010-10-16 21:40:24 UTC (rev 9222)
@@ -222,8 +222,6 @@
* the device whose settings are being modified.
* @transfer: adds a message to the controller's transfer queue.
* @cleanup: frees controller-specific state
- * @lock_bus: lock SPI bus for exclusive access
- * @unlock_bus: unlock SPI bus so other devices can access
*
* Each SPI master controller can communicate with one or more @spi_device
* children. These make a small bus, sharing MOSI, MISO and SCK signals
@@ -266,6 +264,13 @@
#define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */
#define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */
+ /* lock and mutex for SPI bus locking */
+ spinlock_t bus_lock_spinlock;
+ struct mutex bus_lock_mutex;
+
+ /* flag indicating that the SPI bus is locked for exclusive use */
+ bool bus_lock_flag;
+
/* Setup mode and clock, etc (spi driver may call many times).
*
* IMPORTANT: this may be called when transfers to another
@@ -298,9 +303,6 @@
/* called on release() to free memory provided by spi_master */
void (*cleanup)(struct spi_device *spi);
-
- int (*lock_bus)(struct spi_device *spi);
- int (*unlock_bus)(struct spi_device *spi);
};
static inline void *spi_master_get_devdata(struct spi_master *master)
@@ -549,6 +551,8 @@
extern int spi_setup(struct spi_device *spi);
extern int spi_async(struct spi_device *spi, struct spi_message *message);
+extern int spi_async_locked(struct spi_device *spi,
+ struct spi_message *message);
/*---------------------------------------------------------------------------*/
@@ -558,8 +562,9 @@
*/
extern int spi_sync(struct spi_device *spi, struct spi_message *message);
-extern int spi_lock_bus(struct spi_device *spi);
-extern int spi_unlock_bus(struct spi_device *spi);
+extern int spi_sync_locked(struct spi_device *spi, struct spi_message *message);
+extern int spi_bus_lock(struct spi_master *master);
+extern int spi_bus_unlock(struct spi_master *master);
/**
* spi_write - SPI synchronous write