From patchwork Thu Jan 20 07:42:15 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 491201 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0K7gNx6007580 for ; Thu, 20 Jan 2011 07:42:23 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752194Ab1ATHmW (ORCPT ); Thu, 20 Jan 2011 02:42:22 -0500 Received: from mail-iy0-f174.google.com ([209.85.210.174]:58711 "EHLO mail-iy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751921Ab1ATHmV (ORCPT ); Thu, 20 Jan 2011 02:42:21 -0500 Received: by iyj18 with SMTP id 18so286229iyj.19 for ; Wed, 19 Jan 2011 23:42:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:date:from:to:cc:subject:message-id:mime-version :content-type:content-disposition:user-agent; bh=I8nVf3wSG6Zn42oQDP9X2i/fALAJ2wAG6hmbgZHpISw=; b=C5wWLukrqeejwY4o+Wndq5/i/SjMg74VorxupDJ97qw2mJ7QYccpOWZjpF6T7hoWiK o4Lon4O3Jmu3DggT9jbHF4DUPdkbvN/LUxYIMxc2zzDggOi7o+2e3NUjD8WZ13bDKW2U CXkEhS6WiTdkH9+A0NaOHS367TBZk/Urs53wY= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:mime-version:content-type :content-disposition:user-agent; b=EjE9hzczCSEoBbxrUcpu9uM8+EZuBUCKily5qyXGS6pisn1zJ4wHrpW/e45WVgKAtR LJ33zfOmPm9D70eUvQtCumZjQ/tIGly15rrsbW7OeoNQXXiv6w4VyktgTcEMOXMeFyWZ ibmIP96DAVStH4sK+dkXaeS95ENh/tE2Q1JG0= Received: by 10.42.223.132 with SMTP id ik4mr2123193icb.333.1295509341248; Wed, 19 Jan 2011 23:42:21 -0800 (PST) Received: from mailhub.coreip.homeip.net (c-98-234-113-65.hsd1.ca.comcast.net [98.234.113.65]) by mx.google.com with ESMTPS id 34sm6625713ibi.2.2011.01.19.23.42.19 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 19 Jan 2011 23:42:19 -0800 (PST) Date: Wed, 19 Jan 2011 23:42:15 -0800 From: Dmitry Torokhov To: Linux Input Cc: Tejun Heo , LKML Subject: [RFC] Input: input-polldev - create workqueue upfront Message-ID: <20110120074215.GB30522@core.coreip.homeip.net> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 20 Jan 2011 07:42:50 +0000 (UTC) diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 3037842..0a5304c 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c @@ -13,6 +13,7 @@ #include #include #include +#include #include MODULE_AUTHOR("Dmitry Torokhov "); @@ -20,44 +21,8 @@ MODULE_DESCRIPTION("Generic implementation of a polled input device"); MODULE_LICENSE("GPL v2"); MODULE_VERSION("0.1"); -static DEFINE_MUTEX(polldev_mutex); -static int polldev_users; static struct workqueue_struct *polldev_wq; -static int input_polldev_start_workqueue(void) -{ - int retval; - - retval = mutex_lock_interruptible(&polldev_mutex); - if (retval) - return retval; - - if (!polldev_users) { - polldev_wq = create_singlethread_workqueue("ipolldevd"); - if (!polldev_wq) { - pr_err("failed to create ipolldevd workqueue\n"); - retval = -ENOMEM; - goto out; - } - } - - polldev_users++; - - out: - mutex_unlock(&polldev_mutex); - return retval; -} - -static void input_polldev_stop_workqueue(void) -{ - mutex_lock(&polldev_mutex); - - if (!--polldev_users) - destroy_workqueue(polldev_wq); - - mutex_unlock(&polldev_mutex); -} - static void input_polldev_queue_work(struct input_polled_dev *dev) { unsigned long delay; @@ -81,11 +46,6 @@ static void input_polled_device_work(struct work_struct *work) static int input_open_polled_device(struct input_dev *input) { struct input_polled_dev *dev = input_get_drvdata(input); - int error; - - error = input_polldev_start_workqueue(); - if (error) - return error; if (dev->open) dev->open(dev); @@ -102,13 +62,6 @@ static void input_close_polled_device(struct input_dev *input) struct input_polled_dev *dev = input_get_drvdata(input); cancel_delayed_work_sync(&dev->work); - /* - * Clean up work struct to remove references to the workqueue. - * It may be destroyed by the next call. This causes problems - * at next device open-close in case of poll_interval == 0. - */ - INIT_DELAYED_WORK(&dev->work, dev->work.work.func); - input_polldev_stop_workqueue(); if (dev->close) dev->close(dev); @@ -296,3 +249,26 @@ void input_unregister_polled_device(struct input_polled_dev *dev) } EXPORT_SYMBOL(input_unregister_polled_device); +static int __init input_polldev_init(void) +{ + /* + * We are using a dedicated workqueue because we want it to + * be freezable. This ensures that we stop polling when + * system goes into sleep mode. + */ + polldev_wq = alloc_workqueue("ipolldev_wq", + WQ_FREEZEABLE | WQ_UNBOUND, 0); + if (!polldev_wq) { + pr_err("failed to create ipolldev_wq workqueue\n"); + return -ENOMEM; + } + + return 0; +} +module_init(input_polldev_init); + +static void __exit input_polldev_exit(void) +{ + destroy_workqueue(polldev_wq); +} +module_exit(input_polldev_exit);