Commit 1ae1602d authored by Christoph Hellwig's avatar Christoph Hellwig

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: 's avatarChristoph Hellwig <hch@lst.de>
Acked-by: Felipe Balbi <balbi@kernel.org>		[drivers/usb/gadget]
Acked-by: 's avatarJoel Becker <jlbec@evilplan.org>
Acked-by: 's avatarNicholas Bellinger <nab@linux-iscsi.org>
Reviewed-by: 's avatarSagi Grimberg <sagig@mellanox.com>
parent b1f1a29d
......@@ -250,7 +250,8 @@ child item.
struct config_item cg_item;
struct list_head cg_children;
struct configfs_subsystem *cg_subsys;
struct config_group **default_groups;
struct list_head default_groups;
struct list_head group_entry;
};
void config_group_init(struct config_group *group);
......@@ -420,15 +421,15 @@ These automatic subgroups, or default groups, do not preclude other
children of the parent group. If ct_group_ops->make_group() exists,
other child groups can be created on the parent group directly.
A configfs subsystem specifies default groups by filling in the
NULL-terminated array default_groups on the config_group structure.
Each group in that array is populated in the configfs tree at the same
A configfs subsystem specifies default groups by adding them using the
configfs_add_default_group() function to the parent config_group
structure. Each added group is populated in the configfs tree at the same
time as the parent group. Similarly, they are removed at the same time
as the parent. No extra notification is provided. When a ->drop_item()
method call notifies the subsystem the parent group is going away, it
also means every default group child associated with that parent group.
As a consequence of this, default_groups cannot be removed directly via
As a consequence of this, default groups cannot be removed directly via
rmdir(2). They also are not considered when rmdir(2) on the parent
group is checking for children.
......
......@@ -49,8 +49,6 @@ struct cma_dev_group {
char name[IB_DEVICE_NAME_MAX];
struct config_group device_group;
struct config_group ports_group;
struct config_group *default_dev_group[2];
struct config_group **default_ports_group;
struct cma_dev_port_group *ports;
};
......@@ -158,7 +156,6 @@ static int make_cma_ports(struct cma_dev_group *cma_dev_group,
unsigned int i;
unsigned int ports_num;
struct cma_dev_port_group *ports;
struct config_group **ports_group;
int err;
ibdev = cma_get_ib_dev(cma_dev);
......@@ -169,9 +166,8 @@ static int make_cma_ports(struct cma_dev_group *cma_dev_group,
ports_num = ibdev->phys_port_cnt;
ports = kcalloc(ports_num, sizeof(*cma_dev_group->ports),
GFP_KERNEL);
ports_group = kcalloc(ports_num + 1, sizeof(*ports_group), GFP_KERNEL);
if (!ports || !ports_group) {
if (!ports) {
err = -ENOMEM;
goto free;
}
......@@ -185,18 +181,16 @@ static int make_cma_ports(struct cma_dev_group *cma_dev_group,
config_group_init_type_name(&ports[i].group,
port_str,
&cma_port_group_type);
ports_group[i] = &ports[i].group;
configfs_add_default_group(&ports[i].group,
&cma_dev_group->ports_group);
}
ports_group[i] = NULL;
cma_dev_group->default_ports_group = ports_group;
cma_dev_group->ports = ports;
return 0;
free:
kfree(ports);
kfree(ports_group);
cma_dev_group->ports = NULL;
cma_dev_group->default_ports_group = NULL;
return err;
}
......@@ -220,9 +214,7 @@ static void release_cma_ports_group(struct config_item *item)
ports_group);
kfree(cma_dev_group->ports);
kfree(cma_dev_group->default_ports_group);
cma_dev_group->ports = NULL;
cma_dev_group->default_ports_group = NULL;
};
static struct configfs_item_operations cma_ports_item_ops = {
......@@ -263,22 +255,17 @@ static struct config_group *make_cma_dev(struct config_group *group,
strncpy(cma_dev_group->name, name, sizeof(cma_dev_group->name));
err = make_cma_ports(cma_dev_group, cma_dev);
if (err)
goto fail;
cma_dev_group->ports_group.default_groups =
cma_dev_group->default_ports_group;
config_group_init_type_name(&cma_dev_group->ports_group, "ports",
&cma_ports_group_type);
cma_dev_group->device_group.default_groups
= cma_dev_group->default_dev_group;
cma_dev_group->default_dev_group[0] = &cma_dev_group->ports_group;
cma_dev_group->default_dev_group[1] = NULL;
err = make_cma_ports(cma_dev_group, cma_dev);
if (err)
goto fail;
config_group_init_type_name(&cma_dev_group->device_group, name,
&cma_device_group_type);
configfs_add_default_group(&cma_dev_group->ports_group,
&cma_dev_group->device_group);
cma_deref_dev(cma_dev);
return &cma_dev_group->device_group;
......
......@@ -771,21 +771,11 @@ static int lio_target_init_nodeacl(struct se_node_acl *se_nacl,
{
struct iscsi_node_acl *acl =
container_of(se_nacl, struct iscsi_node_acl, se_node_acl);
struct config_group *stats_cg = &se_nacl->acl_fabric_stat_group;
stats_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
GFP_KERNEL);
if (!stats_cg->default_groups) {
pr_err("Unable to allocate memory for"
" stats_cg->default_groups\n");
return -ENOMEM;
}
stats_cg->default_groups[0] = &acl->node_stat_grps.iscsi_sess_stats_group;
stats_cg->default_groups[1] = NULL;
config_group_init_type_name(&acl->node_stat_grps.iscsi_sess_stats_group,
"iscsi_sess_stats", &iscsi_stat_sess_cit);
configfs_add_default_group(&acl->node_stat_grps.iscsi_sess_stats_group,
&se_nacl->acl_fabric_stat_group);
return 0;
}
......@@ -793,17 +783,8 @@ static void lio_target_cleanup_nodeacl( struct se_node_acl *se_nacl)
{
struct iscsi_node_acl *acl = container_of(se_nacl,
struct iscsi_node_acl, se_node_acl);
struct config_item *df_item;
struct config_group *stats_cg;
int i;
stats_cg = &acl->se_node_acl.acl_fabric_stat_group;
for (i = 0; stats_cg->default_groups[i]; i++) {
df_item = &stats_cg->default_groups[i]->cg_item;
stats_cg->default_groups[i] = NULL;
config_item_put(df_item);
}
kfree(stats_cg->default_groups);
configfs_remove_default_groups(&acl->se_node_acl.acl_fabric_stat_group);
}
/* End items for lio_target_acl_cit */
......@@ -1260,42 +1241,37 @@ static struct se_wwn *lio_target_call_coreaddtiqn(
struct config_group *group,
const char *name)
{
struct config_group *stats_cg;
struct iscsi_tiqn *tiqn;
tiqn = iscsit_add_tiqn((unsigned char *)name);
if (IS_ERR(tiqn))
return ERR_CAST(tiqn);
/*
* Setup struct iscsi_wwn_stat_grps for se_wwn->fabric_stat_group.
*/
stats_cg = &tiqn->tiqn_wwn.fabric_stat_group;
stats_cg->default_groups = kmalloc(sizeof(struct config_group *) * 6,
GFP_KERNEL);
if (!stats_cg->default_groups) {
pr_err("Unable to allocate memory for"
" stats_cg->default_groups\n");
iscsit_del_tiqn(tiqn);
return ERR_PTR(-ENOMEM);
}
stats_cg->default_groups[0] = &tiqn->tiqn_stat_grps.iscsi_instance_group;
stats_cg->default_groups[1] = &tiqn->tiqn_stat_grps.iscsi_sess_err_group;
stats_cg->default_groups[2] = &tiqn->tiqn_stat_grps.iscsi_tgt_attr_group;
stats_cg->default_groups[3] = &tiqn->tiqn_stat_grps.iscsi_login_stats_group;
stats_cg->default_groups[4] = &tiqn->tiqn_stat_grps.iscsi_logout_stats_group;
stats_cg->default_groups[5] = NULL;
config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_instance_group,
"iscsi_instance", &iscsi_stat_instance_cit);
configfs_add_default_group(&tiqn->tiqn_stat_grps.iscsi_instance_group,
&tiqn->tiqn_wwn.fabric_stat_group);
config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_sess_err_group,
"iscsi_sess_err", &iscsi_stat_sess_err_cit);
configfs_add_default_group(&tiqn->tiqn_stat_grps.iscsi_sess_err_group,
&tiqn->tiqn_wwn.fabric_stat_group);
config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_tgt_attr_group,
"iscsi_tgt_attr", &iscsi_stat_tgt_attr_cit);
configfs_add_default_group(&tiqn->tiqn_stat_grps.iscsi_tgt_attr_group,
&tiqn->tiqn_wwn.fabric_stat_group);
config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_login_stats_group,
"iscsi_login_stats", &iscsi_stat_login_cit);
configfs_add_default_group(&tiqn->tiqn_stat_grps.iscsi_login_stats_group,
&tiqn->tiqn_wwn.fabric_stat_group);
config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_logout_stats_group,
"iscsi_logout_stats", &iscsi_stat_logout_cit);
configfs_add_default_group(&tiqn->tiqn_stat_grps.iscsi_logout_stats_group,
&tiqn->tiqn_wwn.fabric_stat_group);
pr_debug("LIO_Target_ConfigFS: REGISTER -> %s\n", tiqn->tiqn);
pr_debug("LIO_Target_ConfigFS: REGISTER -> Allocated Node:"
......@@ -1307,17 +1283,8 @@ static void lio_target_call_coredeltiqn(
struct se_wwn *wwn)
{
struct iscsi_tiqn *tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn);
struct config_item *df_item;
struct config_group *stats_cg;
int i;
stats_cg = &tiqn->tiqn_wwn.fabric_stat_group;
for (i = 0; stats_cg->default_groups[i]; i++) {
df_item = &stats_cg->default_groups[i]->cg_item;
stats_cg->default_groups[i] = NULL;
config_item_put(df_item);
}
kfree(stats_cg->default_groups);
configfs_remove_default_groups(&tiqn->tiqn_wwn.fabric_stat_group);
pr_debug("LIO_Target_ConfigFS: DEREGISTER -> %s\n",
tiqn->tiqn);
......
This diff is collapsed.
......@@ -22,7 +22,6 @@ struct target_fabric_configfs {
struct list_head tf_list;
struct config_group tf_group;
struct config_group tf_disc_group;
struct config_group *tf_default_groups[2];
const struct target_core_fabric_ops *tf_ops;
struct config_item_type tf_discovery_cit;
......
......@@ -407,19 +407,20 @@ static struct config_item_type target_stat_scsi_lu_cit = {
*/
void target_stat_setup_dev_default_groups(struct se_device *dev)
{
struct config_group *dev_stat_grp = &dev->dev_stat_grps.stat_group;
config_group_init_type_name(&dev->dev_stat_grps.scsi_dev_group,
"scsi_dev", &target_stat_scsi_dev_cit);
configfs_add_default_group(&dev->dev_stat_grps.scsi_dev_group,
&dev->dev_stat_grps.stat_group);
config_group_init_type_name(&dev->dev_stat_grps.scsi_tgt_dev_group,
"scsi_tgt_dev", &target_stat_scsi_tgt_dev_cit);
configfs_add_default_group(&dev->dev_stat_grps.scsi_tgt_dev_group,
&dev->dev_stat_grps.stat_group);
config_group_init_type_name(&dev->dev_stat_grps.scsi_lu_group,
"scsi_lu", &target_stat_scsi_lu_cit);
dev_stat_grp->default_groups[0] = &dev->dev_stat_grps.scsi_dev_group;
dev_stat_grp->default_groups[1] = &dev->dev_stat_grps.scsi_tgt_dev_group;
dev_stat_grp->default_groups[2] = &dev->dev_stat_grps.scsi_lu_group;
dev_stat_grp->default_groups[3] = NULL;
configfs_add_default_group(&dev->dev_stat_grps.scsi_lu_group,
&dev->dev_stat_grps.stat_group);
}
/*
......@@ -818,19 +819,20 @@ static struct config_item_type target_stat_scsi_transport_cit = {
*/
void target_stat_setup_port_default_groups(struct se_lun *lun)
{
struct config_group *port_stat_grp = &lun->port_stat_grps.stat_group;
config_group_init_type_name(&lun->port_stat_grps.scsi_port_group,
"scsi_port", &target_stat_scsi_port_cit);
configfs_add_default_group(&lun->port_stat_grps.scsi_port_group,
&lun->port_stat_grps.stat_group);
config_group_init_type_name(&lun->port_stat_grps.scsi_tgt_port_group,
"scsi_tgt_port", &target_stat_scsi_tgt_port_cit);
configfs_add_default_group(&lun->port_stat_grps.scsi_tgt_port_group,
&lun->port_stat_grps.stat_group);
config_group_init_type_name(&lun->port_stat_grps.scsi_transport_group,
"scsi_transport", &target_stat_scsi_transport_cit);
port_stat_grp->default_groups[0] = &lun->port_stat_grps.scsi_port_group;
port_stat_grp->default_groups[1] = &lun->port_stat_grps.scsi_tgt_port_group;
port_stat_grp->default_groups[2] = &lun->port_stat_grps.scsi_transport_group;
port_stat_grp->default_groups[3] = NULL;
configfs_add_default_group(&lun->port_stat_grps.scsi_transport_group,
&lun->port_stat_grps.stat_group);
}
/*
......@@ -1351,14 +1353,13 @@ static struct config_item_type target_stat_scsi_att_intr_port_cit = {
*/
void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *lacl)
{
struct config_group *ml_stat_grp = &lacl->ml_stat_grps.stat_group;
config_group_init_type_name(&lacl->ml_stat_grps.scsi_auth_intr_group,
"scsi_auth_intr", &target_stat_scsi_auth_intr_cit);
configfs_add_default_group(&lacl->ml_stat_grps.scsi_auth_intr_group,
&lacl->ml_stat_grps.stat_group);
config_group_init_type_name(&lacl->ml_stat_grps.scsi_att_intr_port_group,
"scsi_att_intr_port", &target_stat_scsi_att_intr_port_cit);
ml_stat_grp->default_groups[0] = &lacl->ml_stat_grps.scsi_auth_intr_group;
ml_stat_grp->default_groups[1] = &lacl->ml_stat_grps.scsi_att_intr_port_group;
ml_stat_grp->default_groups[2] = NULL;
configfs_add_default_group(&lacl->ml_stat_grps.scsi_att_intr_port_group,
&lacl->ml_stat_grps.stat_group);
}
......@@ -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);