From patchwork Mon Mar 22 04:22:34 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 87354 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o2M4MeUg028628 for ; Mon, 22 Mar 2010 04:22:40 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750850Ab0CVEWk (ORCPT ); Mon, 22 Mar 2010 00:22:40 -0400 Received: from mail-gy0-f174.google.com ([209.85.160.174]:42058 "EHLO mail-gy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750718Ab0CVEWj (ORCPT ); Mon, 22 Mar 2010 00:22:39 -0400 Received: by gyg8 with SMTP id 8so2516262gyg.19 for ; Sun, 21 Mar 2010 21:22:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:date:from:to:cc:subject :message-id:references:mime-version:content-type:content-disposition :in-reply-to:user-agent; bh=m7KOQSoqhQfHroRUI4a4xsbXvOHNXlleCMPJTmnPuCM=; b=i0j21/NzBT4VNdj5BSneIJlYjl+IOGSUeC8zfJYruubCcjPAIRSGj9th9yMJdmhoFE 9pNbMggaHm0tk11nLTA5DeJ2aSG97+9cx+6ehiTHUi+4lDbBqvOuD10Ou2/J8pwpu6WX ZgCyvKxYcjhId0vbZLDyyux+o8G7vDj1HKpM0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; b=bSIxiDbsi+RxN+Rz0PKnB7qTrg+buTRzgWGh/dWuKhBd57KYHJM4EdM851ICCwcZow gd+2ai/fOXlMRT29HoBe1L+OvtEpe9OJIc0wVAcblhO/TbKGMDQ8+joU/b8oqv8G05Da oGfXsh3G6KAUzRAsLIMHlo+ew/mu34PELKokQ= Received: by 10.101.11.9 with SMTP id o9mr6852136ani.69.1269231758442; Sun, 21 Mar 2010 21:22:38 -0700 (PDT) Received: from mailhub.coreip.homeip.net (c-24-6-153-206.hsd1.ca.comcast.net [24.6.153.206]) by mx.google.com with ESMTPS id 9sm731741yxf.11.2010.03.21.21.22.36 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sun, 21 Mar 2010 21:22:37 -0700 (PDT) Date: Sun, 21 Mar 2010 21:22:34 -0700 From: Dmitry Torokhov To: Yong Wang Cc: linux-input@vger.kernel.org Subject: Re: [PATCH] Check whether getkeycode and setkeycode are still valide Message-ID: <20100322042233.GA31621@core.coreip.homeip.net> References: <20100321025648.GA24497@ywang-moblin2.bj.intel.com> <20100321031149.GC29360@core.coreip.homeip.net> <20100322024811.GA25096@ywang-moblin2.bj.intel.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20100322024811.GA25096@ywang-moblin2.bj.intel.com> User-Agent: Mutt/1.5.20 (2009-08-17) 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.3 (demeter.kernel.org [140.211.167.41]); Mon, 22 Mar 2010 04:22:41 +0000 (UTC) diff --git a/drivers/input/input.c b/drivers/input/input.c index e2aad0a..be18fa9 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -659,7 +659,14 @@ static int input_default_setkeycode(struct input_dev *dev, int input_get_keycode(struct input_dev *dev, unsigned int scancode, unsigned int *keycode) { - return dev->getkeycode(dev, scancode, keycode); + unsigned long flags; + int retval; + + spin_lock_irqsave(&dev->event_lock, flags); + retval = dev->getkeycode(dev, scancode, keycode); + spin_unlock_irqrestore(&dev->event_lock, flags); + + return retval; } EXPORT_SYMBOL(input_get_keycode); diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index f64e004..f896f24 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -67,12 +67,14 @@ static int sparse_keymap_getkeycode(struct input_dev *dev, unsigned int scancode, unsigned int *keycode) { - const struct key_entry *key = - sparse_keymap_entry_from_scancode(dev, scancode); + const struct key_entry *key; - if (key && key->type == KE_KEY) { - *keycode = key->keycode; - return 0; + if (dev->keycode) { + key = sparse_keymap_entry_from_scancode(dev, scancode); + if (key && key->type == KE_KEY) { + *keycode = key->keycode; + return 0; + } } return -EINVAL; @@ -85,17 +87,16 @@ static int sparse_keymap_setkeycode(struct input_dev *dev, struct key_entry *key; int old_keycode; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - - key = sparse_keymap_entry_from_scancode(dev, scancode); - if (key && key->type == KE_KEY) { - old_keycode = key->keycode; - key->keycode = keycode; - set_bit(keycode, dev->keybit); - if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) - clear_bit(old_keycode, dev->keybit); - return 0; + if (dev->keymap) { + key = sparse_keymap_entry_from_scancode(dev, scancode); + if (key && key->type == KE_KEY) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; + } } return -EINVAL; @@ -175,14 +176,27 @@ EXPORT_SYMBOL(sparse_keymap_setup); * * This function is used to free memory allocated by sparse keymap * in an input device that was set up by sparse_keymap_setup(). + * NOTE: It is safe to cal this function while input device is + * still registered (however the drivers should care not to try to + * use freed keymap and thus have to shut off interrups/polling + * before freeing the keymap). */ void sparse_keymap_free(struct input_dev *dev) { + unsigned long flags; + + /* + * Take event lock to prevent racing with input_get_keycode() + * and input_set_keycode() if we are called while input device + * is still registered. + */ + spin_lock_irqsave(&dev->event_lock, flags); + kfree(dev->keycode); dev->keycode = NULL; dev->keycodemax = 0; - dev->getkeycode = NULL; - dev->setkeycode = NULL; + + spin_unlock_irqrestore(&dev->event_lock, flags); } EXPORT_SYMBOL(sparse_keymap_free);