diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-02-26 06:53:50 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-02-26 06:53:50 +0100 |
commit | a560a5672826fc1e057068bda93b3d4c98d037a2 (patch) | |
tree | 7bc3774f7ec5fa2346a86b7158f975b9a762697a /drivers/usb/roles | |
parent | e89fbb5bc21a10a0de2bb878d4df09f538dc523b (diff) | |
parent | d206a76d7d2726f3b096037f2079ce0bd3ba329b (diff) | |
download | lwn-a560a5672826fc1e057068bda93b3d4c98d037a2.tar.gz lwn-a560a5672826fc1e057068bda93b3d4c98d037a2.zip |
Merge v6.8-rc6 into usb-next
We need it here for the USB fixes, and it resolves a merge conflict as
reported in linux-next in drivers/usb/roles/class.c
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/roles')
-rw-r--r-- | drivers/usb/roles/class.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 4ad03c93c17f..d7aa913ceb8a 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -22,7 +22,9 @@ static const struct class role_class = { struct usb_role_switch { struct device dev; struct mutex lock; /* device lock*/ + struct module *module; /* the module this device depends on */ enum usb_role role; + bool registered; /* From descriptor */ struct device *usb2_port; @@ -75,6 +77,9 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role) if (IS_ERR_OR_NULL(sw)) return 0; + if (!sw->registered) + return -EOPNOTSUPP; + mutex_lock(&sw->lock); ret = sw->set(sw, role); @@ -100,7 +105,7 @@ enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw) { enum usb_role role; - if (IS_ERR_OR_NULL(sw)) + if (IS_ERR_OR_NULL(sw) || !sw->registered) return USB_ROLE_NONE; mutex_lock(&sw->lock); @@ -162,7 +167,7 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) usb_role_switch_match); if (!IS_ERR_OR_NULL(sw)) - WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); + WARN_ON(!try_module_get(sw->module)); return sw; } @@ -184,7 +189,7 @@ struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) sw = fwnode_connection_find_match(fwnode, "usb-role-switch", NULL, usb_role_switch_match); if (!IS_ERR_OR_NULL(sw)) - WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); + WARN_ON(!try_module_get(sw->module)); return sw; } @@ -199,7 +204,7 @@ EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get); void usb_role_switch_put(struct usb_role_switch *sw) { if (!IS_ERR_OR_NULL(sw)) { - module_put(sw->dev.parent->driver->owner); + module_put(sw->module); put_device(&sw->dev); } } @@ -216,15 +221,18 @@ struct usb_role_switch * usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode) { struct device *dev; + struct usb_role_switch *sw = NULL; if (!fwnode) return NULL; dev = class_find_device_by_fwnode(&role_class, fwnode); - if (dev) - WARN_ON(!try_module_get(dev->parent->driver->owner)); + if (dev) { + sw = to_role_switch(dev); + WARN_ON(!try_module_get(sw->module)); + } - return dev ? to_role_switch(dev) : NULL; + return sw; } EXPORT_SYMBOL_GPL(usb_role_switch_find_by_fwnode); @@ -365,6 +373,7 @@ usb_role_switch_register(struct device *parent, sw->set = desc->set; sw->get = desc->get; + sw->module = parent->driver->owner; sw->dev.parent = parent; sw->dev.fwnode = desc->fwnode; sw->dev.class = &role_class; @@ -385,6 +394,8 @@ usb_role_switch_register(struct device *parent, dev_warn(&sw->dev, "failed to add component\n"); } + sw->registered = true; + /* TODO: Symlinks for the host port and the device controller. */ return sw; @@ -401,6 +412,7 @@ void usb_role_switch_unregister(struct usb_role_switch *sw) { if (IS_ERR_OR_NULL(sw)) return; + sw->registered = false; if (dev_fwnode(&sw->dev)) component_del(&sw->dev, &connector_ops); device_unregister(&sw->dev); |