aboutsummaryrefslogtreecommitdiff
path: root/drivers/spi/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r--drivers/spi/spi.c53
1 files changed, 28 insertions, 25 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 89769ce16f8..682a6a48fec 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -457,10 +457,11 @@ done:
EXPORT_SYMBOL_GPL(spi_register_master);
-static int __unregister(struct device *dev, void *unused)
+static int __unregister(struct device *dev, void *master_dev)
{
/* note: before about 2.6.14-rc1 this would corrupt memory: */
- spi_unregister_device(to_spi_device(dev));
+ if (dev != master_dev)
+ spi_unregister_device(to_spi_device(dev));
return 0;
}
@@ -478,11 +479,21 @@ void spi_unregister_master(struct spi_master *master)
{
int dummy;
- dummy = device_for_each_child(master->dev.parent, NULL, __unregister);
+ dummy = device_for_each_child(master->dev.parent, &master->dev,
+ __unregister);
device_unregister(&master->dev);
}
EXPORT_SYMBOL_GPL(spi_unregister_master);
+static int __spi_master_match(struct device *dev, void *data)
+{
+ struct spi_master *m;
+ u16 *bus_num = data;
+
+ m = container_of(dev, struct spi_master, dev);
+ return m->bus_num == *bus_num;
+}
+
/**
* spi_busnum_to_master - look up master associated with bus_num
* @bus_num: the master's bus number
@@ -497,17 +508,12 @@ struct spi_master *spi_busnum_to_master(u16 bus_num)
{
struct device *dev;
struct spi_master *master = NULL;
- struct spi_master *m;
-
- down(&spi_master_class.sem);
- list_for_each_entry(dev, &spi_master_class.children, node) {
- m = container_of(dev, struct spi_master, dev);
- if (m->bus_num == bus_num) {
- master = spi_master_get(m);
- break;
- }
- }
- up(&spi_master_class.sem);
+
+ dev = class_find_device(&spi_master_class, &bus_num,
+ __spi_master_match);
+ if (dev)
+ master = container_of(dev, struct spi_master, dev);
+ /* reference got in class_find_device */
return master;
}
EXPORT_SYMBOL_GPL(spi_busnum_to_master);
@@ -539,10 +545,7 @@ static void spi_complete(void *arg)
* Also, the caller is guaranteeing that the memory associated with the
* message will not be freed before this call returns.
*
- * The return value is a negative error code if the message could not be
- * submitted, else zero. When the value is zero, then message->status is
- * also defined; it's the completion code for the transfer, either zero
- * or a negative error code from the controller driver.
+ * It returns zero on success, else a negative error code.
*/
int spi_sync(struct spi_device *spi, struct spi_message *message)
{
@@ -552,8 +555,10 @@ int spi_sync(struct spi_device *spi, struct spi_message *message)
message->complete = spi_complete;
message->context = &done;
status = spi_async(spi, message);
- if (status == 0)
+ if (status == 0) {
wait_for_completion(&done);
+ status = message->status;
+ }
message->context = NULL;
return status;
}
@@ -587,7 +592,7 @@ int spi_write_then_read(struct spi_device *spi,
const u8 *txbuf, unsigned n_tx,
u8 *rxbuf, unsigned n_rx)
{
- static DECLARE_MUTEX(lock);
+ static DEFINE_MUTEX(lock);
int status;
struct spi_message message;
@@ -613,7 +618,7 @@ int spi_write_then_read(struct spi_device *spi,
}
/* ... unless someone else is using the pre-allocated buffer */
- if (down_trylock(&lock)) {
+ if (!mutex_trylock(&lock)) {
local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
if (!local_buf)
return -ENOMEM;
@@ -626,13 +631,11 @@ int spi_write_then_read(struct spi_device *spi,
/* do the i/o */
status = spi_sync(spi, &message);
- if (status == 0) {
+ if (status == 0)
memcpy(rxbuf, x[1].rx_buf, n_rx);
- status = message.status;
- }
if (x[0].tx_buf == buf)
- up(&lock);
+ mutex_unlock(&lock);
else
kfree(local_buf);