aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/industrialio-buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/industrialio-buffer.c')
-rw-r--r--drivers/iio/industrialio-buffer.c52
1 files changed, 44 insertions, 8 deletions
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index ac185b8694bd..4add9bb40eeb 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -285,11 +285,14 @@ int iio_buffer_register(struct iio_dev *indio_dev,
285 if (channels) { 285 if (channels) {
286 /* new magic */ 286 /* new magic */
287 for (i = 0; i < num_channels; i++) { 287 for (i = 0; i < num_channels; i++) {
288 if (channels[i].scan_index < 0)
289 continue;
290
288 /* Establish necessary mask length */ 291 /* Establish necessary mask length */
289 if (channels[i].scan_index > 292 if (channels[i].scan_index >
290 (int)indio_dev->masklength - 1) 293 (int)indio_dev->masklength - 1)
291 indio_dev->masklength 294 indio_dev->masklength
292 = indio_dev->channels[i].scan_index + 1; 295 = channels[i].scan_index + 1;
293 296
294 ret = iio_buffer_add_channel_sysfs(indio_dev, 297 ret = iio_buffer_add_channel_sysfs(indio_dev,
295 &channels[i]); 298 &channels[i]);
@@ -553,6 +556,10 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
553 buffer->scan_mask); 556 buffer->scan_mask);
554 else 557 else
555 indio_dev->active_scan_mask = buffer->scan_mask; 558 indio_dev->active_scan_mask = buffer->scan_mask;
559
560 if (indio_dev->active_scan_mask == NULL)
561 return -EINVAL;
562
556 iio_update_demux(indio_dev); 563 iio_update_demux(indio_dev);
557 564
558 if (indio_dev->info->update_scan_mode) 565 if (indio_dev->info->update_scan_mode)
@@ -564,6 +571,31 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
564EXPORT_SYMBOL(iio_sw_buffer_preenable); 571EXPORT_SYMBOL(iio_sw_buffer_preenable);
565 572
566/** 573/**
574 * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected
575 * @indio_dev: the iio device
576 * @mask: scan mask to be checked
577 *
578 * Return true if exactly one bit is set in the scan mask, false otherwise. It
579 * can be used for devices where only one channel can be active for sampling at
580 * a time.
581 */
582bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
583 const unsigned long *mask)
584{
585 return bitmap_weight(mask, indio_dev->masklength) == 1;
586}
587EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot);
588
589static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
590 const unsigned long *mask)
591{
592 if (!indio_dev->setup_ops->validate_scan_mask)
593 return true;
594
595 return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask);
596}
597
598/**
567 * iio_scan_mask_set() - set particular bit in the scan mask 599 * iio_scan_mask_set() - set particular bit in the scan mask
568 * @buffer: the buffer whose scan mask we are interested in 600 * @buffer: the buffer whose scan mask we are interested in
569 * @bit: the bit to be set. 601 * @bit: the bit to be set.
@@ -582,27 +614,31 @@ int iio_scan_mask_set(struct iio_dev *indio_dev,
582 return -ENOMEM; 614 return -ENOMEM;
583 if (!indio_dev->masklength) { 615 if (!indio_dev->masklength) {
584 WARN_ON("trying to set scanmask prior to registering buffer\n"); 616 WARN_ON("trying to set scanmask prior to registering buffer\n");
585 kfree(trialmask); 617 goto err_invalid_mask;
586 return -EINVAL;
587 } 618 }
588 bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); 619 bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength);
589 set_bit(bit, trialmask); 620 set_bit(bit, trialmask);
590 621
622 if (!iio_validate_scan_mask(indio_dev, trialmask))
623 goto err_invalid_mask;
624
591 if (indio_dev->available_scan_masks) { 625 if (indio_dev->available_scan_masks) {
592 mask = iio_scan_mask_match(indio_dev->available_scan_masks, 626 mask = iio_scan_mask_match(indio_dev->available_scan_masks,
593 indio_dev->masklength, 627 indio_dev->masklength,
594 trialmask); 628 trialmask);
595 if (!mask) { 629 if (!mask)
596 kfree(trialmask); 630 goto err_invalid_mask;
597 return -EINVAL;
598 }
599 } 631 }
600 bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); 632 bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength);
601 633
602 kfree(trialmask); 634 kfree(trialmask);
603 635
604 return 0; 636 return 0;
605}; 637
638err_invalid_mask:
639 kfree(trialmask);
640 return -EINVAL;
641}
606EXPORT_SYMBOL_GPL(iio_scan_mask_set); 642EXPORT_SYMBOL_GPL(iio_scan_mask_set);
607 643
608int iio_scan_mask_query(struct iio_dev *indio_dev, 644int iio_scan_mask_query(struct iio_dev *indio_dev,