@@ -354,7 +354,7 @@ static int config_usb_cfg_link(
struct usb_function_instance *fi = container_of(group,
struct usb_function_instance, group);
struct usb_function_instance *a_fi;
- struct usb_function *f;
+ struct config_usb_function *cf;
int ret;
mutex_lock(&gi->lock);
@@ -372,21 +372,29 @@ static int config_usb_cfg_link(
goto out;
}
- list_for_each_entry(f, &cfg->func_list, list) {
- if (f->fi == fi) {
+ list_for_each_entry(cf, &cfg->func_list, list) {
+ if (cf->f->fi == fi) {
ret = -EEXIST;
goto out;
}
}
- f = usb_get_function(fi);
- if (IS_ERR(f)) {
- ret = PTR_ERR(f);
+ cf = kzalloc(sizeof(*cf), GFP_KERNEL);
+ if (!cf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ INIT_LIST_HEAD(&cf->list);
+
+ cf->f = usb_get_function(fi);
+ if (IS_ERR(cf->f)) {
+ ret = PTR_ERR(cf->f);
+ kfree(cf);
goto out;
}
/* stash the function until we bind it to the gadget */
- list_add_tail(&f->list, &cfg->func_list);
+ list_add_tail(&cf->list, &cfg->func_list);
ret = 0;
out:
mutex_unlock(&gi->lock);
@@ -404,7 +412,7 @@ static void config_usb_cfg_unlink(
struct config_group *group = to_config_group(usb_func_ci);
struct usb_function_instance *fi = container_of(group,
struct usb_function_instance, group);
- struct usb_function *f;
+ struct config_usb_function *cf;
/*
* ideally I would like to forbid to unlink functions while a gadget is
@@ -417,10 +425,11 @@ static void config_usb_cfg_unlink(
unregister_gadget(gi);
WARN_ON(gi->composite.gadget_driver.udc_name);
- list_for_each_entry(f, &cfg->func_list, list) {
- if (f->fi == fi) {
- list_del(&f->list);
- usb_put_function(f);
+ list_for_each_entry(cf, &cfg->func_list, list) {
+ if (cf->f->fi == fi) {
+ list_del(&cf->list);
+ usb_put_function(cf->f);
+ kfree(cf);
mutex_unlock(&gi->lock);
return;
}
@@ -1191,13 +1200,10 @@ static void purge_configs_funcs(struct gadget_info *gi)
list_for_each_entry(c, &gi->cdev.configs, list) {
struct usb_function *f, *tmp;
- struct config_usb_cfg *cfg;
-
- cfg = container_of(c, struct config_usb_cfg, c);
list_for_each_entry_safe_reverse(f, tmp, &c->functions, list) {
- list_move(&f->list, &cfg->func_list);
+ list_del(&f->list);
if (f->unbind) {
dev_dbg(&gi->cdev.gadget->dev,
"unbind function '%s'/%p\n",
@@ -1299,8 +1305,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
/* Go through all configs, attach all functions */
list_for_each_entry(c, &gi->cdev.configs, list) {
struct config_usb_cfg *cfg;
- struct usb_function *f;
- struct usb_function *tmp;
+ struct config_usb_function *cf, *tmp;
struct gadget_config_name *cn;
if (gadget_is_otg(gadget))
@@ -1324,13 +1329,10 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
c->iConfiguration = s[0].id;
}
- list_for_each_entry_safe(f, tmp, &cfg->func_list, list) {
- list_del(&f->list);
- ret = usb_add_function(c, f);
- if (ret) {
- list_add(&f->list, &cfg->func_list);
+ list_for_each_entry_safe(cf, tmp, &cfg->func_list, list) {
+ ret = usb_add_function(c, cf->f);
+ if (ret)
goto err_purge_funcs;
- }
}
ret = usb_gadget_check_config(cdev->gadget);
if (ret)
@@ -44,6 +44,11 @@ static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
group);
}
+struct config_usb_function {
+ struct list_head list;
+ struct usb_function *f;
+};
+
struct gadget_strings {
struct usb_gadget_strings stringtab_dev;
struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX];
add a new list which link all usb_function at configfs layers, it means that after link a function a configuration, from configfs layer, we can still found all functions, it will allow trace all functions from configfs. Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Linyu Yuan <quic_linyyuan@quicinc.com> --- v2: fix unused cfg variable warning drivers/usb/gadget/configfs.c | 50 ++++++++++++++++++++++--------------------- drivers/usb/gadget/configfs.h | 5 +++++ 2 files changed, 31 insertions(+), 24 deletions(-)