From patchwork Tue Feb 28 09:45:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TWljaGHFgiBLxJlwaWXFhA==?= X-Patchwork-Id: 9595037 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E426760453 for ; Tue, 28 Feb 2017 09:50:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D54812756B for ; Tue, 28 Feb 2017 09:50:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CA5B72851E; Tue, 28 Feb 2017 09:50:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C7CB5284FF for ; Tue, 28 Feb 2017 09:50:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751341AbdB1JsJ (ORCPT ); Tue, 28 Feb 2017 04:48:09 -0500 Received: from mail-lf0-f67.google.com ([209.85.215.67]:34855 "EHLO mail-lf0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751060AbdB1JrF (ORCPT ); Tue, 28 Feb 2017 04:47:05 -0500 Received: by mail-lf0-f67.google.com with SMTP id z127so560393lfa.2 for ; Tue, 28 Feb 2017 01:45:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kempniu.pl; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=7lPRhnWNmQ4oN9fAv7chmpLYc7x2lRhYZj0bnoLAAjg=; b=QsbRRSYgVjhqzfVkGAtdhp+YWJUNhZl1d6RzVL2RczLU4P8tQ8K907Usvb2+5EZjK4 b8cZJNU5rVLO27sVnAh4tbuMPdTpwQGwMW6u6Tlqv51TSNQTzAQM8FRSFg1HOrS9XX46 2/189JKsL3dAVnnIl1DVitt2XT598yOxaYteA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=7lPRhnWNmQ4oN9fAv7chmpLYc7x2lRhYZj0bnoLAAjg=; b=mV5VtHzlfAz/fVrDOr2rrKqtpkJLeY8FlyJKDhEeeqAAMH3upwfoA01z/493GV07aj mYwgZvwI3QJucP/yCteUtZbVptfNWPtJS9JkrTMLMk6I4vgPSlku5Zbt9uuPJAfl0fXb iglx6RA+VWIu4Ub5o2BiTNdI+AnnYYS5yhOartZsrqM25qdfN+oqnc0xEXKDFTHpnb70 mct266Qo9CEQHfOfgErdZ9F+uZhuDKnxa/dsIAytX9nX16a/B5jZQC3geYgMPSuN0yxr IW8s3yfiGHapQ35O4BLWeLQ+Ce8V1t5v8KYsbvZSRoHMShvhdHfxIZATNybeIU/ksksj STPQ== X-Gm-Message-State: AMke39kKpnXSGZlL8271i8LyxCTv5gD0x9pOpPoWjTMiQ9RgygP5222do1pfT8gIV8Jfzg== X-Received: by 10.25.195.14 with SMTP id t14mr513243lff.34.1488275130665; Tue, 28 Feb 2017 01:45:30 -0800 (PST) Received: from ozzy.nask.waw.pl ([2001:a10:160:3::3]) by smtp.googlemail.com with ESMTPSA id l196sm248808lfe.65.2017.02.28.01.45.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Feb 2017 01:45:30 -0800 (PST) From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= To: Dmitry Torokhov Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] Input: sparse-keymap - add managed version of sparse_keymap_setup() Date: Tue, 28 Feb 2017 10:45:25 +0100 Message-Id: <20170228094525.26683-1-kernel@kempniu.pl> X-Mailer: git-send-email 2.12.0 MIME-Version: 1.0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some platform drivers use devm_input_allocate_device() together with sparse_keymap_setup() in their .probe callbacks. While using the former simplifies error handling, using the latter necessitates calling sparse_keymap_free() in the error path and upon module unloading to avoid leaking the copy of the keymap allocated by sparse_keymap_setup(). To help prevent such leaks and enable simpler error handling in these drivers, add a new function which allows automatic freeing of the keymap copy upon probe failure and on driver detach. As devm_input_allocate_device() adds its devres to the device owning the input device, we do the same for managed input devices to ensure freeing the keymap copy is properly slotted in the devres stack. The new function can also be used by non-managed input devices, though in this case the devres is attached to the struct device embedded inside the input device itself. Signed-off-by: Michał Kępień --- drivers/input/sparse-keymap.c | 51 +++++++++++++++++++++++++++++++++++++ include/linux/input/sparse-keymap.h | 4 +++ 2 files changed, 55 insertions(+) diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index e7409c45bdd0..9cb37762f5fd 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -228,6 +228,57 @@ int sparse_keymap_setup(struct input_dev *dev, } EXPORT_SYMBOL(sparse_keymap_setup); +struct sparse_keymap_devres { + struct input_dev *dev; +}; + +static void devm_sparse_keymap_free(struct device *dev, void *res) +{ + struct sparse_keymap_devres *devres = res; + + sparse_keymap_free(devres->dev); +} + +/** + * devm_sparse_keymap_setup - set up managed sparse keymap for an input device + * @dev: Input device + * @keymap: Keymap in form of array of &key_entry structures ending + * with %KE_END type entry + * @setup: Function that can be used to adjust keymap entries + * depending on device's needs, may be %NULL + * + * The function calculates size and allocates copy of the original + * keymap after which sets up input device event bits appropriately. + * The allocated copy of the keymap is automatically freed when it is no + * longer needed, thus drivers using this function must not explicitly + * call sparse_keymap_free() for the same input device. + */ +int devm_sparse_keymap_setup(struct input_dev *dev, + const struct key_entry *keymap, + int (*setup)(struct input_dev *, + struct key_entry *)) +{ + struct sparse_keymap_devres *devres; + int ret; + + devres = devres_alloc(devm_sparse_keymap_free, sizeof(*devres), + GFP_KERNEL); + if (!devres) + return -ENOMEM; + + ret = sparse_keymap_setup(dev, keymap, setup); + if (ret) { + devres_free(devres); + return ret; + } + + devres->dev = dev; + devres_add(dev->devres_managed ? dev->dev.parent : &dev->dev, devres); + + return 0; +} +EXPORT_SYMBOL_GPL(devm_sparse_keymap_setup); + /** * sparse_keymap_free - free memory allocated for sparse keymap * @dev: Input device using sparse keymap diff --git a/include/linux/input/sparse-keymap.h b/include/linux/input/sparse-keymap.h index 52db62064c6e..bb8cc7bd6a29 100644 --- a/include/linux/input/sparse-keymap.h +++ b/include/linux/input/sparse-keymap.h @@ -51,6 +51,10 @@ struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev, int sparse_keymap_setup(struct input_dev *dev, const struct key_entry *keymap, int (*setup)(struct input_dev *, struct key_entry *)); +int devm_sparse_keymap_setup(struct input_dev *dev, + const struct key_entry *keymap, + int (*setup)(struct input_dev *, + struct key_entry *)); void sparse_keymap_free(struct input_dev *dev); void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke,