Commit 61740810 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-fixes-for-3.12a' of...

Merge tag 'iio-fixes-for-3.12a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-linus

Jonathan writes:

First round of IIO fixes for 3.12

A series of wrong 'struct dev' assumptions in suspend/resume callbacks
following on from this issue being identified in a new driver review.
One to watch out for in future.

A number of driver specific fixes
1) at91 - fix a overflow in clock rate computation
2) dummy - Kconfig dependency issue
3) isl29018 - uninitialized value
4) hmc5843 - measurement conversion bug introduced by recent cleanup.
5) ade7854-spi - wrong return value.

Some IIO core fixes
1) Wrong value picked up for event code creation for a modified channel
2) A null dereference on failure to initialize a buffer after no buffer has
   been in use, when using the available_scan_masks approach.
3) Sampling not stopped when a device is removed. Effects forced removal
   such as hot unplugging.
4) Prevent device going away if a chrdev is still open in userspace.
5) Prevent race on chardev opening and device being freed.
6) Add a missing iio_buffer_init in the call back buffer.

These last few are the first part of a set from Lars-Peter Clausen who
has been taking a closer look at our removal paths and buffer handling
than anyone has for quite some time.
parents c3cb718a bda2f8fc
...@@ -620,7 +620,7 @@ static int bma180_remove(struct i2c_client *client) ...@@ -620,7 +620,7 @@ static int bma180_remove(struct i2c_client *client)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int bma180_suspend(struct device *dev) static int bma180_suspend(struct device *dev)
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct bma180_data *data = iio_priv(indio_dev); struct bma180_data *data = iio_priv(indio_dev);
int ret; int ret;
...@@ -633,7 +633,7 @@ static int bma180_suspend(struct device *dev) ...@@ -633,7 +633,7 @@ static int bma180_suspend(struct device *dev)
static int bma180_resume(struct device *dev) static int bma180_resume(struct device *dev)
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct bma180_data *data = iio_priv(indio_dev); struct bma180_data *data = iio_priv(indio_dev);
int ret; int ret;
......
...@@ -556,7 +556,7 @@ static const struct iio_info at91_adc_info = { ...@@ -556,7 +556,7 @@ static const struct iio_info at91_adc_info = {
static int at91_adc_probe(struct platform_device *pdev) static int at91_adc_probe(struct platform_device *pdev)
{ {
unsigned int prsc, mstrclk, ticks, adc_clk, shtim; unsigned int prsc, mstrclk, ticks, adc_clk, adc_clk_khz, shtim;
int ret; int ret;
struct iio_dev *idev; struct iio_dev *idev;
struct at91_adc_state *st; struct at91_adc_state *st;
...@@ -649,6 +649,7 @@ static int at91_adc_probe(struct platform_device *pdev) ...@@ -649,6 +649,7 @@ static int at91_adc_probe(struct platform_device *pdev)
*/ */
mstrclk = clk_get_rate(st->clk); mstrclk = clk_get_rate(st->clk);
adc_clk = clk_get_rate(st->adc_clk); adc_clk = clk_get_rate(st->adc_clk);
adc_clk_khz = adc_clk / 1000;
prsc = (mstrclk / (2 * adc_clk)) - 1; prsc = (mstrclk / (2 * adc_clk)) - 1;
if (!st->startup_time) { if (!st->startup_time) {
...@@ -662,15 +663,15 @@ static int at91_adc_probe(struct platform_device *pdev) ...@@ -662,15 +663,15 @@ static int at91_adc_probe(struct platform_device *pdev)
* defined in the electrical characteristics of the board, divided by 8. * defined in the electrical characteristics of the board, divided by 8.
* The formula thus is : Startup Time = (ticks + 1) * 8 / ADC Clock * The formula thus is : Startup Time = (ticks + 1) * 8 / ADC Clock
*/ */
ticks = round_up((st->startup_time * adc_clk / ticks = round_up((st->startup_time * adc_clk_khz /
1000000) - 1, 8) / 8; 1000) - 1, 8) / 8;
/* /*
* a minimal Sample and Hold Time is necessary for the ADC to guarantee * a minimal Sample and Hold Time is necessary for the ADC to guarantee
* the best converted final value between two channels selection * the best converted final value between two channels selection
* The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock * The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock
*/ */
shtim = round_up((st->sample_hold_time * adc_clk / shtim = round_up((st->sample_hold_time * adc_clk_khz /
1000000) - 1, 1); 1000) - 1, 1);
reg = AT91_ADC_PRESCAL_(prsc) & st->registers->mr_prescal_mask; reg = AT91_ADC_PRESCAL_(prsc) & st->registers->mr_prescal_mask;
reg |= AT91_ADC_STARTUP_(ticks) & st->registers->mr_startup_mask; reg |= AT91_ADC_STARTUP_(ticks) & st->registers->mr_startup_mask;
......
...@@ -41,6 +41,8 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev, ...@@ -41,6 +41,8 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
goto error_ret; goto error_ret;
} }
iio_buffer_init(&cb_buff->buffer);
cb_buff->private = private; cb_buff->private = private;
cb_buff->cb = cb; cb_buff->cb = cb;
cb_buff->buffer.access = &iio_cb_access; cb_buff->buffer.access = &iio_cb_access;
......
...@@ -37,21 +37,21 @@ struct mcp4725_data { ...@@ -37,21 +37,21 @@ struct mcp4725_data {
static int mcp4725_suspend(struct device *dev) static int mcp4725_suspend(struct device *dev)
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
struct mcp4725_data *data = iio_priv(indio_dev); to_i2c_client(dev)));
u8 outbuf[2]; u8 outbuf[2];
outbuf[0] = (data->powerdown_mode + 1) << 4; outbuf[0] = (data->powerdown_mode + 1) << 4;
outbuf[1] = 0; outbuf[1] = 0;
data->powerdown = true; data->powerdown = true;
return i2c_master_send(to_i2c_client(dev), outbuf, 2); return i2c_master_send(data->client, outbuf, 2);
} }
static int mcp4725_resume(struct device *dev) static int mcp4725_resume(struct device *dev)
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
struct mcp4725_data *data = iio_priv(indio_dev); to_i2c_client(dev)));
u8 outbuf[2]; u8 outbuf[2];
/* restore previous DAC value */ /* restore previous DAC value */
...@@ -59,7 +59,7 @@ static int mcp4725_resume(struct device *dev) ...@@ -59,7 +59,7 @@ static int mcp4725_resume(struct device *dev)
outbuf[1] = data->dac_value & 0xff; outbuf[1] = data->dac_value & 0xff;
data->powerdown = false; data->powerdown = false;
return i2c_master_send(to_i2c_client(dev), outbuf, 2); return i2c_master_send(data->client, outbuf, 2);
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
......
...@@ -49,11 +49,15 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, ...@@ -49,11 +49,15 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
#define iio_buffer_poll_addr (&iio_buffer_poll) #define iio_buffer_poll_addr (&iio_buffer_poll)
#define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer) #define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer)
void iio_disable_all_buffers(struct iio_dev *indio_dev);
#else #else
#define iio_buffer_poll_addr NULL #define iio_buffer_poll_addr NULL
#define iio_buffer_read_first_n_outer_addr NULL #define iio_buffer_read_first_n_outer_addr NULL
static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {}
#endif #endif
int iio_device_register_eventset(struct iio_dev *indio_dev); int iio_device_register_eventset(struct iio_dev *indio_dev);
......
...@@ -460,6 +460,25 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask, ...@@ -460,6 +460,25 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask,
return bytes; return bytes;
} }
void iio_disable_all_buffers(struct iio_dev *indio_dev)
{
struct iio_buffer *buffer, *_buffer;
if (list_empty(&indio_dev->buffer_list))
return;
if (indio_dev->setup_ops->predisable)
indio_dev->setup_ops->predisable(indio_dev);
list_for_each_entry_safe(buffer, _buffer,
&indio_dev->buffer_list, buffer_list)
list_del_init(&buffer->buffer_list);
indio_dev->currentmode = INDIO_DIRECT_MODE;
if (indio_dev->setup_ops->postdisable)
indio_dev->setup_ops->postdisable(indio_dev);
}
int iio_update_buffers(struct iio_dev *indio_dev, int iio_update_buffers(struct iio_dev *indio_dev,
struct iio_buffer *insert_buffer, struct iio_buffer *insert_buffer,
struct iio_buffer *remove_buffer) struct iio_buffer *remove_buffer)
...@@ -528,9 +547,16 @@ int iio_update_buffers(struct iio_dev *indio_dev, ...@@ -528,9 +547,16 @@ int iio_update_buffers(struct iio_dev *indio_dev,
* Note can only occur when adding a buffer. * Note can only occur when adding a buffer.
*/ */
list_del(&insert_buffer->buffer_list); list_del(&insert_buffer->buffer_list);
if (old_mask) {
indio_dev->active_scan_mask = old_mask; indio_dev->active_scan_mask = old_mask;
success = -EINVAL; success = -EINVAL;
} }
else {
kfree(compound_mask);
ret = -EINVAL;
goto error_ret;
}
}
} else { } else {
indio_dev->active_scan_mask = compound_mask; indio_dev->active_scan_mask = compound_mask;
} }
......
...@@ -848,8 +848,6 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) ...@@ -848,8 +848,6 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
static void iio_dev_release(struct device *device) static void iio_dev_release(struct device *device)
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(device); struct iio_dev *indio_dev = dev_to_iio_dev(device);
if (indio_dev->chrdev.dev)
cdev_del(&indio_dev->chrdev);
if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
iio_device_unregister_trigger_consumer(indio_dev); iio_device_unregister_trigger_consumer(indio_dev);
iio_device_unregister_eventset(indio_dev); iio_device_unregister_eventset(indio_dev);
...@@ -970,6 +968,8 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp) ...@@ -970,6 +968,8 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp)
if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags)) if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags))
return -EBUSY; return -EBUSY;
iio_device_get(indio_dev);
filp->private_data = indio_dev; filp->private_data = indio_dev;
return 0; return 0;
...@@ -983,6 +983,8 @@ static int iio_chrdev_release(struct inode *inode, struct file *filp) ...@@ -983,6 +983,8 @@ static int iio_chrdev_release(struct inode *inode, struct file *filp)
struct iio_dev *indio_dev = container_of(inode->i_cdev, struct iio_dev *indio_dev = container_of(inode->i_cdev,
struct iio_dev, chrdev); struct iio_dev, chrdev);
clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags);
iio_device_put(indio_dev);
return 0; return 0;
} }
...@@ -1052,18 +1054,20 @@ int iio_device_register(struct iio_dev *indio_dev) ...@@ -1052,18 +1054,20 @@ int iio_device_register(struct iio_dev *indio_dev)
indio_dev->setup_ops == NULL) indio_dev->setup_ops == NULL)
indio_dev->setup_ops = &noop_ring_setup_ops; indio_dev->setup_ops = &noop_ring_setup_ops;
ret = device_add(&indio_dev->dev);
if (ret < 0)
goto error_unreg_eventset;
cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
indio_dev->chrdev.owner = indio_dev->info->driver_module; indio_dev->chrdev.owner = indio_dev->info->driver_module;
indio_dev->chrdev.kobj.parent = &indio_dev->dev.kobj;
ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1);
if (ret < 0) if (ret < 0)
goto error_del_device; goto error_unreg_eventset;
return 0;
error_del_device: ret = device_add(&indio_dev->dev);
device_del(&indio_dev->dev); if (ret < 0)
goto error_cdev_del;
return 0;
error_cdev_del:
cdev_del(&indio_dev->chrdev);
error_unreg_eventset: error_unreg_eventset:
iio_device_unregister_eventset(indio_dev); iio_device_unregister_eventset(indio_dev);
error_free_sysfs: error_free_sysfs:
...@@ -1078,9 +1082,16 @@ EXPORT_SYMBOL(iio_device_register); ...@@ -1078,9 +1082,16 @@ EXPORT_SYMBOL(iio_device_register);
void iio_device_unregister(struct iio_dev *indio_dev) void iio_device_unregister(struct iio_dev *indio_dev)
{ {
mutex_lock(&indio_dev->info_exist_lock); mutex_lock(&indio_dev->info_exist_lock);
device_del(&indio_dev->dev);
if (indio_dev->chrdev.dev)
cdev_del(&indio_dev->chrdev);
iio_disable_all_buffers(indio_dev);
indio_dev->info = NULL; indio_dev->info = NULL;
mutex_unlock(&indio_dev->info_exist_lock); mutex_unlock(&indio_dev->info_exist_lock);
device_del(&indio_dev->dev);
} }
EXPORT_SYMBOL(iio_device_unregister); EXPORT_SYMBOL(iio_device_unregister);
subsys_initcall(iio_init); subsys_initcall(iio_init);
......
...@@ -72,7 +72,8 @@ EXPORT_SYMBOL(iio_push_event); ...@@ -72,7 +72,8 @@ EXPORT_SYMBOL(iio_push_event);
static unsigned int iio_event_poll(struct file *filep, static unsigned int iio_event_poll(struct file *filep,
struct poll_table_struct *wait) struct poll_table_struct *wait)
{ {
struct iio_event_interface *ev_int = filep->private_data; struct iio_dev *indio_dev = filep->private_data;
struct iio_event_interface *ev_int = indio_dev->event_interface;
unsigned int events = 0; unsigned int events = 0;
poll_wait(filep, &ev_int->wait, wait); poll_wait(filep, &ev_int->wait, wait);
...@@ -90,7 +91,8 @@ static ssize_t iio_event_chrdev_read(struct file *filep, ...@@ -90,7 +91,8 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
size_t count, size_t count,
loff_t *f_ps) loff_t *f_ps)
{ {
struct iio_event_interface *ev_int = filep->private_data; struct iio_dev *indio_dev = filep->private_data;
struct iio_event_interface *ev_int = indio_dev->event_interface;
unsigned int copied; unsigned int copied;
int ret; int ret;
...@@ -121,7 +123,8 @@ static ssize_t iio_event_chrdev_read(struct file *filep, ...@@ -121,7 +123,8 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
static int iio_event_chrdev_release(struct inode *inode, struct file *filep) static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
{ {
struct iio_event_interface *ev_int = filep->private_data; struct iio_dev *indio_dev = filep->private_data;
struct iio_event_interface *ev_int = indio_dev->event_interface;
spin_lock_irq(&ev_int->wait.lock); spin_lock_irq(&ev_int->wait.lock);
__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
...@@ -133,6 +136,8 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) ...@@ -133,6 +136,8 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
kfifo_reset_out(&ev_int->det_events); kfifo_reset_out(&ev_int->det_events);
spin_unlock_irq(&ev_int->wait.lock); spin_unlock_irq(&ev_int->wait.lock);
iio_device_put(indio_dev);
return 0; return 0;
} }
...@@ -158,12 +163,15 @@ int iio_event_getfd(struct iio_dev *indio_dev) ...@@ -158,12 +163,15 @@ int iio_event_getfd(struct iio_dev *indio_dev)
return -EBUSY; return -EBUSY;
} }
spin_unlock_irq(&ev_int->wait.lock); spin_unlock_irq(&ev_int->wait.lock);
fd = anon_inode_getfd("iio:event", iio_device_get(indio_dev);
&iio_event_chrdev_fileops, ev_int, O_RDONLY);
fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops,
indio_dev, O_RDONLY);
if (fd < 0) { if (fd < 0) {
spin_lock_irq(&ev_int->wait.lock); spin_lock_irq(&ev_int->wait.lock);
__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
spin_unlock_irq(&ev_int->wait.lock); spin_unlock_irq(&ev_int->wait.lock);
iio_device_put(indio_dev);
} }
return fd; return fd;
} }
...@@ -276,7 +284,7 @@ static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, ...@@ -276,7 +284,7 @@ static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
goto error_ret; goto error_ret;
} }
if (chan->modified) if (chan->modified)
mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel2,
i/IIO_EV_DIR_MAX, i/IIO_EV_DIR_MAX,
i%IIO_EV_DIR_MAX); i%IIO_EV_DIR_MAX);
else if (chan->differential) else if (chan->differential)
......
...@@ -255,12 +255,14 @@ static int tmp006_remove(struct i2c_client *client) ...@@ -255,12 +255,14 @@ static int tmp006_remove(struct i2c_client *client)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int tmp006_suspend(struct device *dev) static int tmp006_suspend(struct device *dev)
{ {
return tmp006_powerdown(iio_priv(dev_to_iio_dev(dev))); struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
return tmp006_powerdown(iio_priv(indio_dev));
} }
static int tmp006_resume(struct device *dev) static int tmp006_resume(struct device *dev)
{ {
struct tmp006_data *data = iio_priv(dev_to_iio_dev(dev)); struct tmp006_data *data = iio_priv(i2c_get_clientdata(
to_i2c_client(dev)));
return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG, return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
data->config | TMP006_CONFIG_MOD_MASK); data->config | TMP006_CONFIG_MOD_MASK);
} }
......
...@@ -37,7 +37,7 @@ config IIO_SIMPLE_DUMMY_EVENTS ...@@ -37,7 +37,7 @@ config IIO_SIMPLE_DUMMY_EVENTS
config IIO_SIMPLE_DUMMY_BUFFER config IIO_SIMPLE_DUMMY_BUFFER
boolean "Buffered capture support" boolean "Buffered capture support"
depends on IIO_KFIFO_BUF select IIO_KFIFO_BUF
help help
Add buffered data capture to the simple dummy driver. Add buffered data capture to the simple dummy driver.
......
...@@ -563,6 +563,7 @@ static int isl29018_probe(struct i2c_client *client, ...@@ -563,6 +563,7 @@ static int isl29018_probe(struct i2c_client *client,
mutex_init(&chip->lock); mutex_init(&chip->lock);
chip->lux_scale = 1; chip->lux_scale = 1;
chip->lux_uscale = 0;
chip->range = 1000; chip->range = 1000;
chip->adc_bit = 16; chip->adc_bit = 16;
chip->suspended = false; chip->suspended = false;
......
...@@ -229,7 +229,7 @@ static int hmc5843_read_measurement(struct iio_dev *indio_dev, ...@@ -229,7 +229,7 @@ static int hmc5843_read_measurement(struct iio_dev *indio_dev,
if (result < 0) if (result < 0)
return -EINVAL; return -EINVAL;
*val = result; *val = sign_extend32(result, 15);
return IIO_VAL_INT; return IIO_VAL_INT;
} }
......
...@@ -299,7 +299,7 @@ static int ade7854_spi_probe(struct spi_device *spi) ...@@ -299,7 +299,7 @@ static int ade7854_spi_probe(struct spi_device *spi)
if (ret) if (ret)
iio_device_free(indio_dev); iio_device_free(indio_dev);
return 0; return ret;
} }
static int ade7854_spi_remove(struct spi_device *spi) static int ade7854_spi_remove(struct spi_device *spi)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment