From patchwork Fri Dec 17 13:24:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 525096 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13A9BC433FE for ; Fri, 17 Dec 2021 13:24:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236639AbhLQNYO (ORCPT ); Fri, 17 Dec 2021 08:24:14 -0500 Received: from mga17.intel.com ([192.55.52.151]:36394 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232592AbhLQNYN (ORCPT ); Fri, 17 Dec 2021 08:24:13 -0500 X-IronPort-AV: E=McAfee;i="6200,9189,10200"; a="220433346" X-IronPort-AV: E=Sophos;i="5.88,213,1635231600"; d="scan'208";a="220433346" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Dec 2021 05:24:13 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,213,1635231600"; d="scan'208";a="662843753" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 17 Dec 2021 05:24:10 -0800 From: Heikki Krogerus To: "Rafael J. Wysocki" , Greg Kroah-Hartman Cc: Andy Shevchenko , Sakari Ailus , Prashant Malani , linux-acpi@vger.kernel.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/4] acpi: Store the known device locations Date: Fri, 17 Dec 2021 16:24:12 +0300 Message-Id: <20211217132415.39726-2-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20211217132415.39726-1-heikki.krogerus@linux.intel.com> References: <20211217132415.39726-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org This adds a list that will hold all the detected device locations. The location of a device is known if it has Physical Location of Device (_PLD) object within its scope. Each entry in the list represents a known location, and each of those locations can then have a list of devices that are currently assigned to those locations. The location entry that contains the current location of a device can be acquired with a new function acpi_device_get_location(). The location structure returned by this function contains the list of devices sharing it. The knowledge of the other devices that share a location can be used in device drivers that need to know the connections to other components inside a system. USB3 ports will for example always share their location with a USB2 port. For now, the device locations can not be updated, so they will only contain lists the devices that are initially in those locations. But that can later be easily changed if needed by adding API that can be used to update the locations. Signed-off-by: Heikki Krogerus --- drivers/acpi/scan.c | 77 +++++++++++++++++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 19 ++++++++++ 2 files changed, 96 insertions(+) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5991dddbc9ceb..f147c0ad5f944 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "internal.h" @@ -42,6 +43,8 @@ static LIST_HEAD(acpi_scan_handlers_list); DEFINE_MUTEX(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); static DEFINE_MUTEX(acpi_hp_context_lock); +static LIST_HEAD(acpi_location_list); +static DEFINE_MUTEX(acpi_location_lock); /* * The UART device described by the SPCR table is the only object which needs @@ -485,6 +488,7 @@ static void acpi_device_del(struct acpi_device *device) break; } + list_del(&device->location_list); list_del(&device->wakeup_list); mutex_unlock(&acpi_device_lock); @@ -654,6 +658,76 @@ static int acpi_tie_acpi_dev(struct acpi_device *adev) return 0; } +static void acpi_store_device_location(struct acpi_device *adev) +{ + struct acpi_device_location *location; + struct acpi_pld_info *pld; + acpi_status status; + u32 crc; + + status = acpi_get_physical_device_location(adev->handle, &pld); + if (ACPI_FAILURE(status)) + return; + + crc = crc32(~0, pld, sizeof(*pld)); + + mutex_lock(&acpi_location_lock); + + list_for_each_entry(location, &acpi_location_list, node) + if (location->pld_crc == crc) + goto out_add_to_location; + + /* The location does not exist yet so creating it. */ + + location = kzalloc(sizeof(*location), GFP_KERNEL); + if (!location) { + acpi_handle_err(adev->handle, "Unable to store location\n"); + goto err_unlock; + } + + list_add_tail(&location->node, &acpi_location_list); + INIT_LIST_HEAD(&location->devices); + location->pld_crc = crc; + +out_add_to_location: + list_add_tail(&adev->location_list, &location->devices); + +err_unlock: + ACPI_FREE(pld); + mutex_unlock(&acpi_location_lock); +} + +/** + * acpi_device_get_location - Get the device location + * @adev: ACPI device handle + * + * Return a pointer to a struct acpi_device_location object containing the + * location information obtained by evaluating _PLD (Physical Location of + * Device) for @adev when it is available, along with the list of devices + * sharing the same location information (if any), or NULL otherwise. + */ +struct acpi_device_location *acpi_device_get_location(struct acpi_device *adev) +{ + struct acpi_device_location *location; + struct list_head *tmp; + + mutex_lock(&acpi_location_lock); + + list_for_each_entry(location, &acpi_location_list, node) { + list_for_each(tmp, &location->devices) { + if (tmp == &adev->location_list) + goto out_unlock; + } + } + location = NULL; + +out_unlock: + mutex_unlock(&acpi_location_lock); + + return location; +} +EXPORT_SYMBOL_GPL(acpi_device_get_location); + static int __acpi_device_add(struct acpi_device *device, void (*release)(struct device *)) { @@ -670,6 +744,7 @@ static int __acpi_device_add(struct acpi_device *device, INIT_LIST_HEAD(&device->wakeup_list); INIT_LIST_HEAD(&device->physical_node_list); INIT_LIST_HEAD(&device->del_list); + INIT_LIST_HEAD(&device->location_list); mutex_init(&device->physical_node_lock); mutex_lock(&acpi_device_lock); @@ -712,6 +787,8 @@ static int __acpi_device_add(struct acpi_device *device, if (device->wakeup.flags.valid) list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list); + acpi_store_device_location(device); + mutex_unlock(&acpi_device_lock); if (device->parent) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index d6fe27b695c3d..9123884e4e7ec 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -354,6 +354,18 @@ struct acpi_device_data { struct list_head subnodes; }; +/* + * struct acpi_device_location - Device location based on _PLD + * @devices: List of devices that share this location + * @node: Entry in the internal list of locations + * @pld_crc: CRC-32 hash of the _PLD + */ +struct acpi_device_location { + struct list_head devices; + struct list_head node; + u32 pld_crc; +}; + struct acpi_gpio_mapping; /* Device */ @@ -366,6 +378,7 @@ struct acpi_device { struct list_head node; struct list_head wakeup_list; struct list_head del_list; + struct list_head location_list; struct acpi_device_status status; struct acpi_device_flags flags; struct acpi_device_pnp pnp; @@ -731,11 +744,17 @@ static inline void acpi_bus_put_acpi_device(struct acpi_device *adev) { acpi_dev_put(adev); } + +struct acpi_device_location *acpi_device_get_location(struct acpi_device *adev); #else /* CONFIG_ACPI */ static inline int register_acpi_bus_type(void *bus) { return 0; } static inline int unregister_acpi_bus_type(void *bus) { return 0; } +static inline struct acpi_device_location *acpi_device_get_location(struct acpi_device *adev) +{ + return NULL; +} #endif /* CONFIG_ACPI */ #endif /*__ACPI_BUS_H__*/ From patchwork Fri Dec 17 13:24:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 525863 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13DD1C433FE for ; Fri, 17 Dec 2021 13:24:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236662AbhLQNYR (ORCPT ); Fri, 17 Dec 2021 08:24:17 -0500 Received: from mga17.intel.com ([192.55.52.151]:36394 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236648AbhLQNYQ (ORCPT ); Fri, 17 Dec 2021 08:24:16 -0500 X-IronPort-AV: E=McAfee;i="6200,9189,10200"; a="220433349" X-IronPort-AV: E=Sophos;i="5.88,213,1635231600"; d="scan'208";a="220433349" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Dec 2021 05:24:16 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,213,1635231600"; d="scan'208";a="662843758" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 17 Dec 2021 05:24:13 -0800 From: Heikki Krogerus To: "Rafael J. Wysocki" , Greg Kroah-Hartman Cc: Andy Shevchenko , Sakari Ailus , Prashant Malani , linux-acpi@vger.kernel.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/4] usb: Link the ports to the connectors they are attached to Date: Fri, 17 Dec 2021 16:24:13 +0300 Message-Id: <20211217132415.39726-3-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20211217132415.39726-1-heikki.krogerus@linux.intel.com> References: <20211217132415.39726-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Creating link to the USB Type-C connector for every new port that is added when possible. Signed-off-by: Heikki Krogerus --- Documentation/ABI/testing/sysfs-bus-usb | 9 +++++++ drivers/usb/core/port.c | 32 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 2ebe5708b4bc0..7efe31ed3a25c 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -244,6 +244,15 @@ Description: is permitted, "u2" if only u2 is permitted, "u1_u2" if both u1 and u2 are permitted. +What: /sys/bus/usb/devices/...//port/connector +Date: December 2021 +Contact: Heikki Krogerus +Description: + Link to the USB Type-C connector when available. This link is + only created when USB Type-C Connector Class is enabled, and + only if the system firmware is capable of describing the + connection between a port and its connector. + What: /sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout Date: May 2013 Contact: Mathias Nyman diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index dfcca9c876c73..c2bbf97a79bec 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -9,6 +9,7 @@ #include #include +#include #include "hub.h" @@ -528,6 +529,32 @@ static void find_and_link_peer(struct usb_hub *hub, int port1) link_peers_report(port_dev, peer); } +static int connector_bind(struct device *dev, struct device *connector, void *data) +{ + int ret; + + ret = sysfs_create_link(&dev->kobj, &connector->kobj, "connector"); + if (ret) + return ret; + + ret = sysfs_create_link(&connector->kobj, &dev->kobj, dev_name(dev)); + if (ret) + sysfs_remove_link(&dev->kobj, "connector"); + + return ret; +} + +static void connector_unbind(struct device *dev, struct device *connector, void *data) +{ + sysfs_remove_link(&connector->kobj, dev_name(dev)); + sysfs_remove_link(&dev->kobj, "connector"); +} + +static const struct component_ops connector_ops = { + .bind = connector_bind, + .unbind = connector_unbind, +}; + int usb_hub_create_port_device(struct usb_hub *hub, int port1) { struct usb_port *port_dev; @@ -577,6 +604,10 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) find_and_link_peer(hub, port1); + retval = component_add(&port_dev->dev, &connector_ops); + if (retval) + dev_warn(&port_dev->dev, "failed to add component\n"); + /* * Enable runtime pm and hold a refernce that hub_configure() * will drop once the PM_QOS_NO_POWER_OFF flag state has been set @@ -619,5 +650,6 @@ void usb_hub_remove_port_device(struct usb_hub *hub, int port1) peer = port_dev->peer; if (peer) unlink_peers(port_dev, peer); + component_del(&port_dev->dev, &connector_ops); device_unregister(&port_dev->dev); } From patchwork Fri Dec 17 13:24:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 525862 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B524FC4167D for ; Fri, 17 Dec 2021 13:24:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236664AbhLQNYY (ORCPT ); Fri, 17 Dec 2021 08:24:24 -0500 Received: from mga17.intel.com ([192.55.52.151]:36394 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236692AbhLQNYV (ORCPT ); Fri, 17 Dec 2021 08:24:21 -0500 X-IronPort-AV: E=McAfee;i="6200,9189,10200"; a="220433352" X-IronPort-AV: E=Sophos;i="5.88,213,1635231600"; d="scan'208";a="220433352" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Dec 2021 05:24:21 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,213,1635231600"; d="scan'208";a="662843773" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 17 Dec 2021 05:24:19 -0800 From: Heikki Krogerus To: "Rafael J. Wysocki" , Greg Kroah-Hartman Cc: Andy Shevchenko , Sakari Ailus , Prashant Malani , linux-acpi@vger.kernel.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 4/4] usb: Remove usb_for_each_port() Date: Fri, 17 Dec 2021 16:24:15 +0300 Message-Id: <20211217132415.39726-5-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20211217132415.39726-1-heikki.krogerus@linux.intel.com> References: <20211217132415.39726-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org There are no more users for the function. Signed-off-by: Heikki Krogerus --- drivers/usb/core/usb.c | 46 ------------------------------------------ include/linux/usb.h | 9 --------- 2 files changed, 55 deletions(-) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 62368c4ed37af..2ce3667ec6fae 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -398,52 +398,6 @@ int usb_for_each_dev(void *data, int (*fn)(struct usb_device *, void *)) } EXPORT_SYMBOL_GPL(usb_for_each_dev); -struct each_hub_arg { - void *data; - int (*fn)(struct device *, void *); -}; - -static int __each_hub(struct usb_device *hdev, void *data) -{ - struct each_hub_arg *arg = (struct each_hub_arg *)data; - struct usb_hub *hub; - int ret = 0; - int i; - - hub = usb_hub_to_struct_hub(hdev); - if (!hub) - return 0; - - mutex_lock(&usb_port_peer_mutex); - - for (i = 0; i < hdev->maxchild; i++) { - ret = arg->fn(&hub->ports[i]->dev, arg->data); - if (ret) - break; - } - - mutex_unlock(&usb_port_peer_mutex); - - return ret; -} - -/** - * usb_for_each_port - interate over all USB ports in the system - * @data: data pointer that will be handed to the callback function - * @fn: callback function to be called for each USB port - * - * Iterate over all USB ports and call @fn for each, passing it @data. If it - * returns anything other than 0, we break the iteration prematurely and return - * that value. - */ -int usb_for_each_port(void *data, int (*fn)(struct device *, void *)) -{ - struct each_hub_arg arg = {data, fn}; - - return usb_for_each_dev(&arg, __each_hub); -} -EXPORT_SYMBOL_GPL(usb_for_each_port); - /** * usb_release_dev - free a usb device structure when all users of it are finished. * @dev: device that's been disconnected diff --git a/include/linux/usb.h b/include/linux/usb.h index 7ccaa76a9a968..200b7b79acb56 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -875,15 +875,6 @@ extern struct usb_host_interface *usb_find_alt_setting( unsigned int iface_num, unsigned int alt_num); -#if IS_REACHABLE(CONFIG_USB) -int usb_for_each_port(void *data, int (*fn)(struct device *, void *)); -#else -static inline int usb_for_each_port(void *data, int (*fn)(struct device *, void *)) -{ - return 0; -} -#endif - /* port claiming functions */ int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, struct usb_dev_state *owner);