configfs: switch ->default groups to a linked list
Replace the current NULL-terminated array of default groups with a linked list. This gets rid of lots of nasty code to size and/or dynamically allocate the array. While we're at it also provide a conveniant helper to remove the default groups. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Felipe Balbi <balbi@kernel.org> [drivers/usb/gadget] Acked-by: Joel Becker <jlbec@evilplan.org> Acked-by: Nicholas Bellinger <nab@linux-iscsi.org> Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
This commit is contained in:
@@ -49,7 +49,6 @@ struct gadget_info {
|
||||
struct config_group configs_group;
|
||||
struct config_group strings_group;
|
||||
struct config_group os_desc_group;
|
||||
struct config_group *default_groups[5];
|
||||
|
||||
struct mutex lock;
|
||||
struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
|
||||
@@ -71,7 +70,6 @@ static inline struct gadget_info *to_gadget_info(struct config_item *item)
|
||||
struct config_usb_cfg {
|
||||
struct config_group group;
|
||||
struct config_group strings_group;
|
||||
struct config_group *default_groups[2];
|
||||
struct list_head string_list;
|
||||
struct usb_configuration c;
|
||||
struct list_head func_list;
|
||||
@@ -666,13 +664,12 @@ static struct config_group *config_desc_make(
|
||||
INIT_LIST_HEAD(&cfg->string_list);
|
||||
INIT_LIST_HEAD(&cfg->func_list);
|
||||
|
||||
cfg->group.default_groups = cfg->default_groups;
|
||||
cfg->default_groups[0] = &cfg->strings_group;
|
||||
|
||||
config_group_init_type_name(&cfg->group, name,
|
||||
&gadget_config_type);
|
||||
|
||||
config_group_init_type_name(&cfg->strings_group, "strings",
|
||||
&gadget_config_name_strings_type);
|
||||
configfs_add_default_group(&cfg->strings_group, &cfg->group);
|
||||
|
||||
ret = usb_add_config_only(&gi->cdev, &cfg->c);
|
||||
if (ret)
|
||||
@@ -1149,15 +1146,11 @@ int usb_os_desc_prepare_interf_dir(struct config_group *parent,
|
||||
char **names,
|
||||
struct module *owner)
|
||||
{
|
||||
struct config_group **f_default_groups, *os_desc_group,
|
||||
**interface_groups;
|
||||
struct config_group *os_desc_group;
|
||||
struct config_item_type *os_desc_type, *interface_type;
|
||||
|
||||
vla_group(data_chunk);
|
||||
vla_item(data_chunk, struct config_group *, f_default_groups, 2);
|
||||
vla_item(data_chunk, struct config_group, os_desc_group, 1);
|
||||
vla_item(data_chunk, struct config_group *, interface_groups,
|
||||
n_interf + 1);
|
||||
vla_item(data_chunk, struct config_item_type, os_desc_type, 1);
|
||||
vla_item(data_chunk, struct config_item_type, interface_type, 1);
|
||||
|
||||
@@ -1165,18 +1158,14 @@ int usb_os_desc_prepare_interf_dir(struct config_group *parent,
|
||||
if (!vlabuf)
|
||||
return -ENOMEM;
|
||||
|
||||
f_default_groups = vla_ptr(vlabuf, data_chunk, f_default_groups);
|
||||
os_desc_group = vla_ptr(vlabuf, data_chunk, os_desc_group);
|
||||
os_desc_type = vla_ptr(vlabuf, data_chunk, os_desc_type);
|
||||
interface_groups = vla_ptr(vlabuf, data_chunk, interface_groups);
|
||||
interface_type = vla_ptr(vlabuf, data_chunk, interface_type);
|
||||
|
||||
parent->default_groups = f_default_groups;
|
||||
os_desc_type->ct_owner = owner;
|
||||
config_group_init_type_name(os_desc_group, "os_desc", os_desc_type);
|
||||
f_default_groups[0] = os_desc_group;
|
||||
configfs_add_default_group(os_desc_group, parent);
|
||||
|
||||
os_desc_group->default_groups = interface_groups;
|
||||
interface_type->ct_group_ops = &interf_grp_ops;
|
||||
interface_type->ct_attrs = interf_grp_attrs;
|
||||
interface_type->ct_owner = owner;
|
||||
@@ -1189,7 +1178,7 @@ int usb_os_desc_prepare_interf_dir(struct config_group *parent,
|
||||
config_group_init_type_name(&d->group, "", interface_type);
|
||||
config_item_set_name(&d->group.cg_item, "interface.%s",
|
||||
names[n_interf]);
|
||||
interface_groups[n_interf] = &d->group;
|
||||
configfs_add_default_group(&d->group, os_desc_group);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1423,20 +1412,23 @@ static struct config_group *gadgets_make(
|
||||
if (!gi)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
gi->group.default_groups = gi->default_groups;
|
||||
gi->group.default_groups[0] = &gi->functions_group;
|
||||
gi->group.default_groups[1] = &gi->configs_group;
|
||||
gi->group.default_groups[2] = &gi->strings_group;
|
||||
gi->group.default_groups[3] = &gi->os_desc_group;
|
||||
config_group_init_type_name(&gi->group, name, &gadget_root_type);
|
||||
|
||||
config_group_init_type_name(&gi->functions_group, "functions",
|
||||
&functions_type);
|
||||
configfs_add_default_group(&gi->functions_group, &gi->group);
|
||||
|
||||
config_group_init_type_name(&gi->configs_group, "configs",
|
||||
&config_desc_type);
|
||||
configfs_add_default_group(&gi->configs_group, &gi->group);
|
||||
|
||||
config_group_init_type_name(&gi->strings_group, "strings",
|
||||
&gadget_strings_strings_type);
|
||||
configfs_add_default_group(&gi->strings_group, &gi->group);
|
||||
|
||||
config_group_init_type_name(&gi->os_desc_group, "os_desc",
|
||||
&os_desc_type);
|
||||
configfs_add_default_group(&gi->os_desc_group, &gi->group);
|
||||
|
||||
gi->composite.bind = configfs_do_nothing;
|
||||
gi->composite.unbind = configfs_do_nothing;
|
||||
@@ -1461,8 +1453,6 @@ static struct config_group *gadgets_make(
|
||||
if (!gi->composite.gadget_driver.function)
|
||||
goto err;
|
||||
|
||||
config_group_init_type_name(&gi->group, name,
|
||||
&gadget_root_type);
|
||||
return &gi->group;
|
||||
err:
|
||||
kfree(gi);
|
||||
|
@@ -3484,12 +3484,12 @@ static struct usb_function_instance *fsg_alloc_inst(void)
|
||||
|
||||
opts->lun0.lun = opts->common->luns[0];
|
||||
opts->lun0.lun_id = 0;
|
||||
config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type);
|
||||
opts->default_groups[0] = &opts->lun0.group;
|
||||
opts->func_inst.group.default_groups = opts->default_groups;
|
||||
|
||||
config_group_init_type_name(&opts->func_inst.group, "", &fsg_func_type);
|
||||
|
||||
config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type);
|
||||
configfs_add_default_group(&opts->lun0.group, &opts->func_inst.group);
|
||||
|
||||
return &opts->func_inst;
|
||||
|
||||
release_buffers:
|
||||
|
@@ -889,7 +889,6 @@ static void rndis_free_inst(struct usb_function_instance *f)
|
||||
free_netdev(opts->net);
|
||||
}
|
||||
|
||||
kfree(opts->rndis_os_desc.group.default_groups); /* single VLA chunk */
|
||||
kfree(opts);
|
||||
}
|
||||
|
||||
@@ -916,10 +915,10 @@ static struct usb_function_instance *rndis_alloc_inst(void)
|
||||
|
||||
descs[0] = &opts->rndis_os_desc;
|
||||
names[0] = "rndis";
|
||||
usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
|
||||
names, THIS_MODULE);
|
||||
config_group_init_type_name(&opts->func_inst.group, "",
|
||||
&rndis_func_type);
|
||||
usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
|
||||
names, THIS_MODULE);
|
||||
|
||||
return &opts->func_inst;
|
||||
}
|
||||
|
@@ -272,11 +272,6 @@ static struct config_item_type uvcg_default_processing_type = {
|
||||
|
||||
/* struct uvcg_processing {}; */
|
||||
|
||||
static struct config_group *uvcg_processing_default_groups[] = {
|
||||
&uvcg_default_processing.group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* control/processing */
|
||||
static struct uvcg_processing_grp {
|
||||
struct config_group group;
|
||||
@@ -394,11 +389,6 @@ static struct config_item_type uvcg_default_camera_type = {
|
||||
|
||||
/* struct uvcg_camera {}; */
|
||||
|
||||
static struct config_group *uvcg_camera_default_groups[] = {
|
||||
&uvcg_default_camera.group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* control/terminal/camera */
|
||||
static struct uvcg_camera_grp {
|
||||
struct config_group group;
|
||||
@@ -477,11 +467,6 @@ static struct config_item_type uvcg_default_output_type = {
|
||||
|
||||
/* struct uvcg_output {}; */
|
||||
|
||||
static struct config_group *uvcg_output_default_groups[] = {
|
||||
&uvcg_default_output.group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* control/terminal/output */
|
||||
static struct uvcg_output_grp {
|
||||
struct config_group group;
|
||||
@@ -491,12 +476,6 @@ static struct config_item_type uvcg_output_grp_type = {
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct config_group *uvcg_terminal_default_groups[] = {
|
||||
&uvcg_camera_grp.group,
|
||||
&uvcg_output_grp.group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* control/terminal */
|
||||
static struct uvcg_terminal_grp {
|
||||
struct config_group group;
|
||||
@@ -619,12 +598,6 @@ static struct config_item_type uvcg_control_class_type = {
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct config_group *uvcg_control_class_default_groups[] = {
|
||||
&uvcg_control_class_fs.group,
|
||||
&uvcg_control_class_ss.group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* control/class */
|
||||
static struct uvcg_control_class_grp {
|
||||
struct config_group group;
|
||||
@@ -634,14 +607,6 @@ static struct config_item_type uvcg_control_class_grp_type = {
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct config_group *uvcg_control_default_groups[] = {
|
||||
&uvcg_control_header_grp.group,
|
||||
&uvcg_processing_grp.group,
|
||||
&uvcg_terminal_grp.group,
|
||||
&uvcg_control_class_grp.group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* control */
|
||||
static struct uvcg_control_grp {
|
||||
struct config_group group;
|
||||
@@ -1780,11 +1745,6 @@ static struct config_item_type uvcg_default_color_matching_type = {
|
||||
|
||||
/* struct uvcg_color_matching {}; */
|
||||
|
||||
static struct config_group *uvcg_color_matching_default_groups[] = {
|
||||
&uvcg_default_color_matching.group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* streaming/color_matching */
|
||||
static struct uvcg_color_matching_grp {
|
||||
struct config_group group;
|
||||
@@ -2145,13 +2105,6 @@ static struct config_item_type uvcg_streaming_class_type = {
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct config_group *uvcg_streaming_class_default_groups[] = {
|
||||
&uvcg_streaming_class_fs.group,
|
||||
&uvcg_streaming_class_hs.group,
|
||||
&uvcg_streaming_class_ss.group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* streaming/class */
|
||||
static struct uvcg_streaming_class_grp {
|
||||
struct config_group group;
|
||||
@@ -2161,15 +2114,6 @@ static struct config_item_type uvcg_streaming_class_grp_type = {
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct config_group *uvcg_streaming_default_groups[] = {
|
||||
&uvcg_streaming_header_grp.group,
|
||||
&uvcg_uncompressed_grp.group,
|
||||
&uvcg_mjpeg_grp.group,
|
||||
&uvcg_color_matching_grp.group,
|
||||
&uvcg_streaming_class_grp.group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* streaming */
|
||||
static struct uvcg_streaming_grp {
|
||||
struct config_group group;
|
||||
@@ -2179,12 +2123,6 @@ static struct config_item_type uvcg_streaming_grp_type = {
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct config_group *uvcg_default_groups[] = {
|
||||
&uvcg_control_grp.group,
|
||||
&uvcg_streaming_grp.group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
|
||||
{
|
||||
return container_of(to_config_group(item), struct f_uvc_opts,
|
||||
@@ -2273,59 +2211,64 @@ static struct config_item_type uvc_func_type = {
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static inline void uvcg_init_group(struct config_group *g,
|
||||
struct config_group **default_groups,
|
||||
const char *name,
|
||||
struct config_item_type *type)
|
||||
{
|
||||
g->default_groups = default_groups;
|
||||
config_group_init_type_name(g, name, type);
|
||||
}
|
||||
|
||||
int uvcg_attach_configfs(struct f_uvc_opts *opts)
|
||||
{
|
||||
config_group_init_type_name(&uvcg_control_header_grp.group,
|
||||
"header",
|
||||
&uvcg_control_header_grp_type);
|
||||
|
||||
config_group_init_type_name(&uvcg_default_processing.group,
|
||||
"default",
|
||||
&uvcg_default_processing_type);
|
||||
uvcg_init_group(&uvcg_processing_grp.group,
|
||||
uvcg_processing_default_groups,
|
||||
"processing",
|
||||
&uvcg_processing_grp_type);
|
||||
"default", &uvcg_default_processing_type);
|
||||
config_group_init_type_name(&uvcg_processing_grp.group,
|
||||
"processing", &uvcg_processing_grp_type);
|
||||
configfs_add_default_group(&uvcg_default_processing.group,
|
||||
&uvcg_processing_grp.group);
|
||||
|
||||
config_group_init_type_name(&uvcg_default_camera.group,
|
||||
"default",
|
||||
&uvcg_default_camera_type);
|
||||
uvcg_init_group(&uvcg_camera_grp.group,
|
||||
uvcg_camera_default_groups,
|
||||
"camera",
|
||||
&uvcg_camera_grp_type);
|
||||
"default", &uvcg_default_camera_type);
|
||||
config_group_init_type_name(&uvcg_camera_grp.group,
|
||||
"camera", &uvcg_camera_grp_type);
|
||||
configfs_add_default_group(&uvcg_default_camera.group,
|
||||
&uvcg_camera_grp.group);
|
||||
|
||||
config_group_init_type_name(&uvcg_default_output.group,
|
||||
"default",
|
||||
&uvcg_default_output_type);
|
||||
uvcg_init_group(&uvcg_output_grp.group,
|
||||
uvcg_output_default_groups,
|
||||
"output",
|
||||
&uvcg_output_grp_type);
|
||||
uvcg_init_group(&uvcg_terminal_grp.group,
|
||||
uvcg_terminal_default_groups,
|
||||
"terminal",
|
||||
&uvcg_terminal_grp_type);
|
||||
"default", &uvcg_default_output_type);
|
||||
config_group_init_type_name(&uvcg_output_grp.group,
|
||||
"output", &uvcg_output_grp_type);
|
||||
configfs_add_default_group(&uvcg_default_output.group,
|
||||
&uvcg_output_grp.group);
|
||||
|
||||
config_group_init_type_name(&uvcg_terminal_grp.group,
|
||||
"terminal", &uvcg_terminal_grp_type);
|
||||
configfs_add_default_group(&uvcg_camera_grp.group,
|
||||
&uvcg_terminal_grp.group);
|
||||
configfs_add_default_group(&uvcg_output_grp.group,
|
||||
&uvcg_terminal_grp.group);
|
||||
|
||||
config_group_init_type_name(&uvcg_control_class_fs.group,
|
||||
"fs",
|
||||
&uvcg_control_class_type);
|
||||
"fs", &uvcg_control_class_type);
|
||||
config_group_init_type_name(&uvcg_control_class_ss.group,
|
||||
"ss",
|
||||
&uvcg_control_class_type);
|
||||
uvcg_init_group(&uvcg_control_class_grp.group,
|
||||
uvcg_control_class_default_groups,
|
||||
"ss", &uvcg_control_class_type);
|
||||
config_group_init_type_name(&uvcg_control_class_grp.group,
|
||||
"class",
|
||||
&uvcg_control_class_grp_type);
|
||||
uvcg_init_group(&uvcg_control_grp.group,
|
||||
uvcg_control_default_groups,
|
||||
configfs_add_default_group(&uvcg_control_class_fs.group,
|
||||
&uvcg_control_class_grp.group);
|
||||
configfs_add_default_group(&uvcg_control_class_ss.group,
|
||||
&uvcg_control_class_grp.group);
|
||||
|
||||
config_group_init_type_name(&uvcg_control_grp.group,
|
||||
"control",
|
||||
&uvcg_control_grp_type);
|
||||
configfs_add_default_group(&uvcg_control_header_grp.group,
|
||||
&uvcg_control_grp.group);
|
||||
configfs_add_default_group(&uvcg_processing_grp.group,
|
||||
&uvcg_control_grp.group);
|
||||
configfs_add_default_group(&uvcg_terminal_grp.group,
|
||||
&uvcg_control_grp.group);
|
||||
configfs_add_default_group(&uvcg_control_class_grp.group,
|
||||
&uvcg_control_grp.group);
|
||||
|
||||
config_group_init_type_name(&uvcg_streaming_header_grp.group,
|
||||
"header",
|
||||
&uvcg_streaming_header_grp_type);
|
||||
@@ -2338,30 +2281,47 @@ int uvcg_attach_configfs(struct f_uvc_opts *opts)
|
||||
config_group_init_type_name(&uvcg_default_color_matching.group,
|
||||
"default",
|
||||
&uvcg_default_color_matching_type);
|
||||
uvcg_init_group(&uvcg_color_matching_grp.group,
|
||||
uvcg_color_matching_default_groups,
|
||||
config_group_init_type_name(&uvcg_color_matching_grp.group,
|
||||
"color_matching",
|
||||
&uvcg_color_matching_grp_type);
|
||||
configfs_add_default_group(&uvcg_default_color_matching.group,
|
||||
&uvcg_color_matching_grp.group);
|
||||
|
||||
config_group_init_type_name(&uvcg_streaming_class_fs.group,
|
||||
"fs",
|
||||
&uvcg_streaming_class_type);
|
||||
"fs", &uvcg_streaming_class_type);
|
||||
config_group_init_type_name(&uvcg_streaming_class_hs.group,
|
||||
"hs",
|
||||
&uvcg_streaming_class_type);
|
||||
"hs", &uvcg_streaming_class_type);
|
||||
config_group_init_type_name(&uvcg_streaming_class_ss.group,
|
||||
"ss",
|
||||
&uvcg_streaming_class_type);
|
||||
uvcg_init_group(&uvcg_streaming_class_grp.group,
|
||||
uvcg_streaming_class_default_groups,
|
||||
"class",
|
||||
&uvcg_streaming_class_grp_type);
|
||||
uvcg_init_group(&uvcg_streaming_grp.group,
|
||||
uvcg_streaming_default_groups,
|
||||
"streaming",
|
||||
&uvcg_streaming_grp_type);
|
||||
uvcg_init_group(&opts->func_inst.group,
|
||||
uvcg_default_groups,
|
||||
"ss", &uvcg_streaming_class_type);
|
||||
config_group_init_type_name(&uvcg_streaming_class_grp.group,
|
||||
"class", &uvcg_streaming_class_grp_type);
|
||||
configfs_add_default_group(&uvcg_streaming_class_fs.group,
|
||||
&uvcg_streaming_class_grp.group);
|
||||
configfs_add_default_group(&uvcg_streaming_class_hs.group,
|
||||
&uvcg_streaming_class_grp.group);
|
||||
configfs_add_default_group(&uvcg_streaming_class_ss.group,
|
||||
&uvcg_streaming_class_grp.group);
|
||||
|
||||
config_group_init_type_name(&uvcg_streaming_grp.group,
|
||||
"streaming", &uvcg_streaming_grp_type);
|
||||
configfs_add_default_group(&uvcg_streaming_header_grp.group,
|
||||
&uvcg_streaming_grp.group);
|
||||
configfs_add_default_group(&uvcg_uncompressed_grp.group,
|
||||
&uvcg_streaming_grp.group);
|
||||
configfs_add_default_group(&uvcg_mjpeg_grp.group,
|
||||
&uvcg_streaming_grp.group);
|
||||
configfs_add_default_group(&uvcg_color_matching_grp.group,
|
||||
&uvcg_streaming_grp.group);
|
||||
configfs_add_default_group(&uvcg_streaming_class_grp.group,
|
||||
&uvcg_streaming_grp.group);
|
||||
|
||||
config_group_init_type_name(&opts->func_inst.group,
|
||||
"",
|
||||
&uvc_func_type);
|
||||
configfs_add_default_group(&uvcg_control_grp.group,
|
||||
&opts->func_inst.group);
|
||||
configfs_add_default_group(&uvcg_streaming_grp.group,
|
||||
&opts->func_inst.group);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user