From patchwork Fri Dec 8 14:29:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 10102639 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 C9FD5602A0 for ; Fri, 8 Dec 2017 14:30:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B615A28A1D for ; Fri, 8 Dec 2017 14:30:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AA90428D06; Fri, 8 Dec 2017 14:30:25 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 4DE9828BED for ; Fri, 8 Dec 2017 14:30:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754126AbdLHO3x (ORCPT ); Fri, 8 Dec 2017 09:29:53 -0500 Received: from mx1.redhat.com ([209.132.183.28]:54270 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753608AbdLHO3v (ORCPT ); Fri, 8 Dec 2017 09:29:51 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C76EF2DB709; Fri, 8 Dec 2017 14:29:51 +0000 (UTC) Received: from plouf.banquise.eu.com (ovpn-116-46.ams2.redhat.com [10.36.116.46]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1019760BE0; Fri, 8 Dec 2017 14:29:46 +0000 (UTC) From: Benjamin Tissoires To: Jiri Kosina Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, Benjamin Tissoires Subject: [PATCH 1/1] HID: core: rewrite the hid-generic automatic unbind Date: Fri, 8 Dec 2017 15:29:44 +0100 Message-Id: <20171208142944.15695-1-benjamin.tissoires@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Fri, 08 Dec 2017 14:29:51 +0000 (UTC) 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 We actually can have the unbind/rebind logic in hid-core.c, leaving only the match function in hid-generic. This makes hid-generic simpler and the whole logic simpler too. Signed-off-by: Benjamin Tissoires --- Hi Jiri, while trying to find out a local bug, I figured out we don't really need the bus_add_driver and bus_removed_driver callbacks. This makes the code simpler and also allows other drivers to remove themself if other conditions are met. They just need to implement a smart enough .matchcallback and they are done. Cheers, Benjamin drivers/hid/hid-core.c | 35 ++++++++++++++++++++++++----------- drivers/hid/hid-generic.c | 33 --------------------------------- include/linux/hid.h | 4 ---- 3 files changed, 24 insertions(+), 48 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index c2560aae5542..c058bb911ca1 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2197,31 +2197,40 @@ void hid_destroy_device(struct hid_device *hdev) EXPORT_SYMBOL_GPL(hid_destroy_device); -static int __bus_add_driver(struct device_driver *drv, void *data) +static int __hid_bus_reprobe_drivers(struct device *dev, void *data) { - struct hid_driver *added_hdrv = data; - struct hid_driver *hdrv = to_hid_driver(drv); + struct hid_driver *hdrv = data; + struct hid_device *hdev = to_hid_device(dev); - if (hdrv->bus_add_driver) - hdrv->bus_add_driver(added_hdrv); + if (hdev->driver == hdrv && + !hdrv->match(hdev, hid_ignore_special_drivers)) + return device_reprobe(dev); return 0; } -static int __bus_removed_driver(struct device_driver *drv, void *data) +static int __hid_bus_driver_added(struct device_driver *drv, void *data) { - struct hid_driver *removed_hdrv = data; struct hid_driver *hdrv = to_hid_driver(drv); - if (hdrv->bus_removed_driver) - hdrv->bus_removed_driver(removed_hdrv); + if (hdrv->match) { + bus_for_each_dev(&hid_bus_type, NULL, hdrv, + __hid_bus_reprobe_drivers); + } return 0; } +static int __bus_removed_driver(struct device_driver *drv, void *data) +{ + return bus_rescan_devices(&hid_bus_type); +} + int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, const char *mod_name) { + int ret; + hdrv->driver.name = hdrv->name; hdrv->driver.bus = &hid_bus_type; hdrv->driver.owner = owner; @@ -2230,9 +2239,13 @@ int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, INIT_LIST_HEAD(&hdrv->dyn_list); spin_lock_init(&hdrv->dyn_lock); - bus_for_each_drv(&hid_bus_type, NULL, hdrv, __bus_add_driver); + ret = driver_register(&hdrv->driver); + + if (ret == 0) + bus_for_each_drv(&hid_bus_type, NULL, NULL, + __hid_bus_driver_added); - return driver_register(&hdrv->driver); + return ret; } EXPORT_SYMBOL_GPL(__hid_register_driver); diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c index 3c0a1bf433d7..c25b4718de44 100644 --- a/drivers/hid/hid-generic.c +++ b/drivers/hid/hid-generic.c @@ -26,37 +26,6 @@ static struct hid_driver hid_generic; -static int __unmap_hid_generic(struct device *dev, void *data) -{ - struct hid_driver *hdrv = data; - struct hid_device *hdev = to_hid_device(dev); - - /* only unbind matching devices already bound to hid-generic */ - if (hdev->driver != &hid_generic || - hid_match_device(hdev, hdrv) == NULL) - return 0; - - if (dev->parent) /* Needed for USB */ - device_lock(dev->parent); - device_release_driver(dev); - if (dev->parent) - device_unlock(dev->parent); - - return 0; -} - -static void hid_generic_add_driver(struct hid_driver *hdrv) -{ - bus_for_each_dev(&hid_bus_type, NULL, hdrv, __unmap_hid_generic); -} - -static void hid_generic_removed_driver(struct hid_driver *hdrv) -{ - int ret; - - ret = driver_attach(&hid_generic.driver); -} - static int __check_hid_generic(struct device_driver *drv, void *data) { struct hid_driver *hdrv = to_hid_driver(drv); @@ -97,8 +66,6 @@ static struct hid_driver hid_generic = { .name = "hid-generic", .id_table = hid_table, .match = hid_generic_match, - .bus_add_driver = hid_generic_add_driver, - .bus_removed_driver = hid_generic_removed_driver, }; module_hid_driver(hid_generic); diff --git a/include/linux/hid.h b/include/linux/hid.h index 091a81cf330f..a62ee4a609ac 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -686,8 +686,6 @@ struct hid_usage_id { * @input_mapped: invoked on input registering after mapping an usage * @input_configured: invoked just before the device is registered * @feature_mapping: invoked on feature registering - * @bus_add_driver: invoked when a HID driver is about to be added - * @bus_removed_driver: invoked when a HID driver has been removed * @suspend: invoked on suspend (NULL means nop) * @resume: invoked on resume if device was not reset (NULL means nop) * @reset_resume: invoked on resume if device was reset (NULL means nop) @@ -742,8 +740,6 @@ struct hid_driver { void (*feature_mapping)(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage); - void (*bus_add_driver)(struct hid_driver *driver); - void (*bus_removed_driver)(struct hid_driver *driver); #ifdef CONFIG_PM int (*suspend)(struct hid_device *hdev, pm_message_t message); int (*resume)(struct hid_device *hdev);