diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-07 01:48:27 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-07 01:48:27 +0100 |
commit | f90d64483ebd394958841f67f8794ab203b319a7 (patch) | |
tree | 3da8638603681adfe9bea7897c03ea27b40ef4f4 /drivers/base | |
parent | Merge tag 'tty-5.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/greg... (diff) | |
parent | wusb: Remove unnecessary static function ckhdid_printf (diff) | |
download | linux-f90d64483ebd394958841f67f8794ab203b319a7.tar.xz linux-f90d64483ebd394958841f67f8794ab203b319a7.zip |
Merge tag 'usb-5.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB/PHY updates from Greg KH:
"Here is the big USB/PHY driver pull request for 5.1-rc1.
The usual set of gadget driver updates, phy driver updates, xhci
updates, and typec additions. Also included in here are a lot of small
cleanups and fixes and driver updates where needed.
All of these have been in linux-next for a while with no reported
issues"
* tag 'usb-5.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (167 commits)
wusb: Remove unnecessary static function ckhdid_printf
usb: core: make default autosuspend delay configurable
usb: core: Fix typo in description of "authorized_default"
usb: chipidea: Refactor USB PHY selection and keep a single PHY
usb: chipidea: Grab the (legacy) USB PHY by phandle first
usb: chipidea: imx: set power polarity
dt-bindings: usb: ci-hdrc-usb2: add property power-active-high
usb: chipidea: imx: remove unused header files
usb: chipidea: tegra: Fix missed ci_hdrc_remove_device()
usb: core: add option of only authorizing internal devices
usb: typec: tps6598x: handle block writes separately with plain-I2C adapters
usb: xhci: Fix for Enabling USB ROLE SWITCH QUIRK on INTEL_SUNRISEPOINT_LP_XHCI
usb: xhci: fix build warning - missing prototype
usb: xhci: dbc: Fixing typo error.
usb: xhci: remove unused member 'parent' in xhci_regset struct
xhci: tegra: Prevent error pointer dereference
USB: serial: option: add Telit ME910 ECM composition
usb: core: Replace hardcoded check with inline function from usb.h
usb: core: skip interfaces disabled in devicetree
usb: typec: mux: remove redundant check on variable match
...
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/devcon.c | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/drivers/base/devcon.c b/drivers/base/devcon.c index d427e806cd73..04db9ae235e4 100644 --- a/drivers/base/devcon.c +++ b/drivers/base/devcon.c @@ -7,10 +7,37 @@ */ #include <linux/device.h> +#include <linux/property.h> static DEFINE_MUTEX(devcon_lock); static LIST_HEAD(devcon_list); +typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep, + void *data); + +static void * +fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id, + void *data, devcon_match_fn_t match) +{ + struct device_connection con = { .id = con_id }; + struct fwnode_handle *ep; + void *ret; + + fwnode_graph_for_each_endpoint(fwnode, ep) { + con.fwnode = fwnode_graph_get_remote_port_parent(ep); + if (!fwnode_device_is_available(con.fwnode)) + continue; + + ret = match(&con, -1, data); + fwnode_handle_put(con.fwnode); + if (ret) { + fwnode_handle_put(ep); + return ret; + } + } + return NULL; +} + /** * device_connection_find_match - Find physical connection to a device * @dev: Device with the connection @@ -23,10 +50,9 @@ static LIST_HEAD(devcon_list); * caller is expecting to be returned. */ void *device_connection_find_match(struct device *dev, const char *con_id, - void *data, - void *(*match)(struct device_connection *con, - int ep, void *data)) + void *data, devcon_match_fn_t match) { + struct fwnode_handle *fwnode = dev_fwnode(dev); const char *devname = dev_name(dev); struct device_connection *con; void *ret = NULL; @@ -35,6 +61,12 @@ void *device_connection_find_match(struct device *dev, const char *con_id, if (!match) return NULL; + if (fwnode) { + ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); + if (ret) + return ret; + } + mutex_lock(&devcon_lock); list_for_each_entry(con, &devcon_list, list) { @@ -75,12 +107,36 @@ static struct bus_type *generic_match_buses[] = { NULL, }; +static int device_fwnode_match(struct device *dev, void *fwnode) +{ + return dev_fwnode(dev) == fwnode; +} + +static void *device_connection_fwnode_match(struct device_connection *con) +{ + struct bus_type *bus; + struct device *dev; + + for (bus = generic_match_buses[0]; bus; bus++) { + dev = bus_find_device(bus, NULL, (void *)con->fwnode, + device_fwnode_match); + if (dev && !strncmp(dev_name(dev), con->id, strlen(con->id))) + return dev; + + put_device(dev); + } + return NULL; +} + /* This tries to find the device from the most common bus types by name. */ static void *generic_match(struct device_connection *con, int ep, void *data) { struct bus_type *bus; struct device *dev; + if (con->fwnode) + return device_connection_fwnode_match(con); + for (bus = generic_match_buses[0]; bus; bus++) { dev = bus_find_device_by_name(bus, NULL, con->endpoint[ep]); if (dev) |