diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-28 16:26:12 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-28 16:26:12 +0100 |
commit | 7a9787e1eba95a166265e6a260cf30af04ef0a99 (patch) | |
tree | e730a4565e0318140d2fbd2f0415d18a339d7336 /drivers/spi/spidev.c | |
parent | 41b9eb264c8407655db57b60b4457fe1b2ec9977 (diff) | |
parent | 0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff) |
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
Diffstat (limited to 'drivers/spi/spidev.c')
-rw-r--r-- | drivers/spi/spidev.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index ddbe1a5e970..89a43755a45 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -228,7 +228,6 @@ static int spidev_message(struct spidev_data *spidev, * We walk the array of user-provided transfers, using each one * to initialize a kernel version of the same transfer. */ - mutex_lock(&spidev->buf_lock); buf = spidev->buffer; total = 0; for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; @@ -296,14 +295,12 @@ static int spidev_message(struct spidev_data *spidev, status = total; done: - mutex_unlock(&spidev->buf_lock); kfree(k_xfers); return status; } -static int -spidev_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static long +spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; int retval = 0; @@ -341,6 +338,14 @@ spidev_ioctl(struct inode *inode, struct file *filp, if (spi == NULL) return -ESHUTDOWN; + /* use the buffer lock here for triple duty: + * - prevent I/O (from us) so calling spi_setup() is safe; + * - prevent concurrent SPI_IOC_WR_* from morphing + * data fields while SPI_IOC_RD_* reads them; + * - SPI_IOC_MESSAGE needs the buffer locked "normally". + */ + mutex_lock(&spidev->buf_lock); + switch (cmd) { /* read requests */ case SPI_IOC_RD_MODE: @@ -456,6 +461,8 @@ spidev_ioctl(struct inode *inode, struct file *filp, kfree(ioc); break; } + + mutex_unlock(&spidev->buf_lock); spi_dev_put(spi); return retval; } @@ -533,7 +540,7 @@ static struct file_operations spidev_fops = { */ .write = spidev_write, .read = spidev_read, - .ioctl = spidev_ioctl, + .unlocked_ioctl = spidev_ioctl, .open = spidev_open, .release = spidev_release, }; @@ -577,8 +584,8 @@ static int spidev_probe(struct spi_device *spi) spidev->devt = MKDEV(SPIDEV_MAJOR, minor); dev = device_create(spidev_class, &spi->dev, spidev->devt, - "spidev%d.%d", - spi->master->bus_num, spi->chip_select); + spidev, "spidev%d.%d", + spi->master->bus_num, spi->chip_select); status = IS_ERR(dev) ? PTR_ERR(dev) : 0; } else { dev_dbg(&spi->dev, "no minor number available!\n"); @@ -586,7 +593,6 @@ static int spidev_probe(struct spi_device *spi) } if (status == 0) { set_bit(minor, minors); - spi_set_drvdata(spi, spidev); list_add(&spidev->device_entry, &device_list); } mutex_unlock(&device_list_lock); |