From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753436AbbG2M5a (ORCPT ); Wed, 29 Jul 2015 08:57:30 -0400 Received: from mail-wi0-f175.google.com ([209.85.212.175]:38375 "EHLO mail-wi0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753396AbbG2M51 (ORCPT ); Wed, 29 Jul 2015 08:57:27 -0400 From: Vladimir Barinov To: Jonathan Cameron Cc: Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald , Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, devicetree@vger.kernel.org, cory.tusar@pid1solutions.com Subject: [PATCH v3 4/7] iio: trigger: Add periodic polling to SYSFS trigger Date: Wed, 29 Jul 2015 15:57:22 +0300 Message-Id: <1438174642-19258-1-git-send-email-vladimir.barinov@cogentembedded.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1438174469-19054-1-git-send-email-vladimir.barinov@cogentembedded.com> References: <1438174469-19054-1-git-send-email-vladimir.barinov@cogentembedded.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add periodic polling functionality to SYSFS trigger Signed-off-by: Vladimir Barinov --- Changes in version 2: - initially added Changes in version 3: - fixed typos in ABI description .../ABI/testing/sysfs-bus-iio-trigger-sysfs | 11 ++++ drivers/iio/trigger/iio-trig-sysfs.c | 58 ++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs b/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs index 5235e6c..03c18eb 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs +++ b/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs @@ -9,3 +9,14 @@ Description: automated testing or in situations, where other trigger methods are not applicable. For example no RTC or spare GPIOs. X is the IIO index of the trigger. + +What: /sys/bus/iio/devices/triggerX/trigger_poll +KernelVersion: 4.2.0 +Contact: linux-iio@vger.kernel.org +Description: + This file is provided by the iio-trig-sysfs stand-alone trigger + driver. Writing this file with positive value (in milliseconds) + will start periodic event triggering of the driver, associated + with this trigger. Writing this file with 0 will stop periodic + triggering. + X is the IIO index of the trigger. diff --git a/drivers/iio/trigger/iio-trig-sysfs.c b/drivers/iio/trigger/iio-trig-sysfs.c index 3dfab2b..ea79311 100644 --- a/drivers/iio/trigger/iio-trig-sysfs.c +++ b/drivers/iio/trigger/iio-trig-sysfs.c @@ -18,6 +18,8 @@ struct iio_sysfs_trig { struct iio_trigger *trig; struct irq_work work; + struct delayed_work poll_work; + unsigned int poll_interval; /* msec */ int id; struct list_head l; }; @@ -110,10 +112,63 @@ static ssize_t iio_sysfs_trigger_poll(struct device *dev, return count; } +static void iio_sysfs_trigger_queue_poll_work(struct iio_sysfs_trig *trig) +{ + unsigned long delay; + + delay = msecs_to_jiffies(trig->poll_interval); + if (delay >= HZ) + delay = round_jiffies_relative(delay); + + queue_delayed_work(system_freezable_wq, &trig->poll_work, delay); +} + +static void iio_sysfs_trigger_poll_work(struct work_struct *work) +{ + struct iio_sysfs_trig *trig = container_of(work, struct iio_sysfs_trig, + poll_work.work); + + irq_work_queue(&trig->work); + iio_sysfs_trigger_queue_poll_work(trig); +} + +static ssize_t iio_sysfs_trigger_get_poll(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_trigger *trig = to_iio_trigger(dev); + struct iio_sysfs_trig *sysfs_trig = iio_trigger_get_drvdata(trig); + + return sprintf(buf, "%d\n", sysfs_trig->poll_interval); +} + +static ssize_t iio_sysfs_trigger_set_poll(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct iio_trigger *trig = to_iio_trigger(dev); + struct iio_sysfs_trig *sysfs_trig = iio_trigger_get_drvdata(trig); + unsigned int interval; + int err; + + err = kstrtouint(buf, 0, &interval); + if (err) + return err; + + sysfs_trig->poll_interval = interval; + + cancel_delayed_work_sync(&sysfs_trig->poll_work); + if (sysfs_trig->poll_interval > 0) + iio_sysfs_trigger_queue_poll_work(sysfs_trig); + + return count; +} + static DEVICE_ATTR(trigger_now, S_IWUSR, NULL, iio_sysfs_trigger_poll); +static DEVICE_ATTR(trigger_poll, S_IRUGO | S_IWUSR, iio_sysfs_trigger_get_poll, + iio_sysfs_trigger_set_poll); static struct attribute *iio_sysfs_trigger_attrs[] = { &dev_attr_trigger_now.attr, + &dev_attr_trigger_poll.attr, NULL, }; @@ -164,6 +219,7 @@ static int iio_sysfs_trigger_probe(int id) iio_trigger_set_drvdata(t->trig, t); init_irq_work(&t->work, iio_sysfs_trigger_work); + INIT_DELAYED_WORK(&t->poll_work, iio_sysfs_trigger_poll_work); ret = iio_trigger_register(t->trig); if (ret) @@ -198,6 +254,8 @@ static int iio_sysfs_trigger_remove(int id) return -EINVAL; } + cancel_delayed_work_sync(&t->poll_work); + iio_trigger_unregister(t->trig); iio_trigger_free(t->trig); -- 1.9.1