0001
0002
0003
0004
0005
0006
0007 #include <linux/configfs.h>
0008
0009 #include "coresight-config.h"
0010 #include "coresight-syscfg-configfs.h"
0011
0012
0013 static inline struct config_item_type *cscfg_create_ci_type(void)
0014 {
0015 struct config_item_type *ci_type;
0016
0017 ci_type = devm_kzalloc(cscfg_device(), sizeof(*ci_type), GFP_KERNEL);
0018 if (ci_type)
0019 ci_type->ct_owner = THIS_MODULE;
0020
0021 return ci_type;
0022 }
0023
0024
0025
0026
0027 static ssize_t cscfg_cfg_description_show(struct config_item *item, char *page)
0028 {
0029 struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
0030 struct cscfg_fs_config, group);
0031
0032 return scnprintf(page, PAGE_SIZE, "%s", fs_config->config_desc->description);
0033 }
0034 CONFIGFS_ATTR_RO(cscfg_cfg_, description);
0035
0036 static ssize_t cscfg_cfg_feature_refs_show(struct config_item *item, char *page)
0037 {
0038 struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
0039 struct cscfg_fs_config, group);
0040 const struct cscfg_config_desc *config_desc = fs_config->config_desc;
0041 ssize_t ch_used = 0;
0042 int i;
0043
0044 for (i = 0; i < config_desc->nr_feat_refs; i++)
0045 ch_used += scnprintf(page + ch_used, PAGE_SIZE - ch_used,
0046 "%s\n", config_desc->feat_ref_names[i]);
0047 return ch_used;
0048 }
0049 CONFIGFS_ATTR_RO(cscfg_cfg_, feature_refs);
0050
0051
0052 static ssize_t cscfg_cfg_values_show(struct config_item *item, char *page)
0053 {
0054 const struct cscfg_feature_desc *feat_desc;
0055 const struct cscfg_config_desc *config_desc;
0056 struct cscfg_fs_preset *fs_preset;
0057 int i, j, val_idx, preset_idx;
0058 ssize_t used = 0;
0059
0060 fs_preset = container_of(to_config_group(item), struct cscfg_fs_preset, group);
0061 config_desc = fs_preset->config_desc;
0062
0063 if (!config_desc->nr_presets)
0064 return 0;
0065
0066 preset_idx = fs_preset->preset_num - 1;
0067
0068
0069 val_idx = config_desc->nr_total_params * preset_idx;
0070
0071
0072
0073
0074
0075 for (i = 0; i < config_desc->nr_feat_refs; i++) {
0076 feat_desc = cscfg_get_named_feat_desc(config_desc->feat_ref_names[i]);
0077 for (j = 0; j < feat_desc->nr_params; j++) {
0078 used += scnprintf(page + used, PAGE_SIZE - used,
0079 "%s.%s = 0x%llx ",
0080 feat_desc->name,
0081 feat_desc->params_desc[j].name,
0082 config_desc->presets[val_idx++]);
0083 }
0084 }
0085 used += scnprintf(page + used, PAGE_SIZE - used, "\n");
0086
0087 return used;
0088 }
0089 CONFIGFS_ATTR_RO(cscfg_cfg_, values);
0090
0091 static ssize_t cscfg_cfg_enable_show(struct config_item *item, char *page)
0092 {
0093 struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
0094 struct cscfg_fs_config, group);
0095
0096 return scnprintf(page, PAGE_SIZE, "%d\n", fs_config->active);
0097 }
0098
0099 static ssize_t cscfg_cfg_enable_store(struct config_item *item,
0100 const char *page, size_t count)
0101 {
0102 struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
0103 struct cscfg_fs_config, group);
0104 int err;
0105 bool val;
0106
0107 err = kstrtobool(page, &val);
0108 if (!err)
0109 err = cscfg_config_sysfs_activate(fs_config->config_desc, val);
0110 if (!err) {
0111 fs_config->active = val;
0112 if (val)
0113 cscfg_config_sysfs_set_preset(fs_config->preset);
0114 }
0115 return err ? err : count;
0116 }
0117 CONFIGFS_ATTR(cscfg_cfg_, enable);
0118
0119 static ssize_t cscfg_cfg_preset_show(struct config_item *item, char *page)
0120 {
0121 struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
0122 struct cscfg_fs_config, group);
0123
0124 return scnprintf(page, PAGE_SIZE, "%d\n", fs_config->preset);
0125 }
0126
0127 static ssize_t cscfg_cfg_preset_store(struct config_item *item,
0128 const char *page, size_t count)
0129 {
0130 struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
0131 struct cscfg_fs_config, group);
0132 int preset, err;
0133
0134 err = kstrtoint(page, 0, &preset);
0135 if (!err) {
0136
0137
0138
0139
0140 if ((preset < 1) || (preset > fs_config->config_desc->nr_presets))
0141 err = -EINVAL;
0142 }
0143
0144 if (!err) {
0145
0146 fs_config->preset = preset;
0147
0148 if (fs_config->active)
0149 cscfg_config_sysfs_set_preset(fs_config->preset);
0150 }
0151 return err ? err : count;
0152 }
0153 CONFIGFS_ATTR(cscfg_cfg_, preset);
0154
0155 static struct configfs_attribute *cscfg_config_view_attrs[] = {
0156 &cscfg_cfg_attr_description,
0157 &cscfg_cfg_attr_feature_refs,
0158 &cscfg_cfg_attr_enable,
0159 &cscfg_cfg_attr_preset,
0160 NULL,
0161 };
0162
0163 static struct config_item_type cscfg_config_view_type = {
0164 .ct_owner = THIS_MODULE,
0165 .ct_attrs = cscfg_config_view_attrs,
0166 };
0167
0168 static struct configfs_attribute *cscfg_config_preset_attrs[] = {
0169 &cscfg_cfg_attr_values,
0170 NULL,
0171 };
0172
0173 static struct config_item_type cscfg_config_preset_type = {
0174 .ct_owner = THIS_MODULE,
0175 .ct_attrs = cscfg_config_preset_attrs,
0176 };
0177
0178 static int cscfg_add_preset_groups(struct cscfg_fs_config *cfg_view)
0179 {
0180 int preset_num;
0181 struct cscfg_fs_preset *cfg_fs_preset;
0182 struct cscfg_config_desc *config_desc = cfg_view->config_desc;
0183 char name[CONFIGFS_ITEM_NAME_LEN];
0184
0185 if (!config_desc->nr_presets)
0186 return 0;
0187
0188 for (preset_num = 1; preset_num <= config_desc->nr_presets; preset_num++) {
0189 cfg_fs_preset = devm_kzalloc(cscfg_device(),
0190 sizeof(struct cscfg_fs_preset), GFP_KERNEL);
0191
0192 if (!cfg_fs_preset)
0193 return -ENOMEM;
0194
0195 snprintf(name, CONFIGFS_ITEM_NAME_LEN, "preset%d", preset_num);
0196 cfg_fs_preset->preset_num = preset_num;
0197 cfg_fs_preset->config_desc = cfg_view->config_desc;
0198 config_group_init_type_name(&cfg_fs_preset->group, name,
0199 &cscfg_config_preset_type);
0200 configfs_add_default_group(&cfg_fs_preset->group, &cfg_view->group);
0201 }
0202 return 0;
0203 }
0204
0205 static struct config_group *cscfg_create_config_group(struct cscfg_config_desc *config_desc)
0206 {
0207 struct cscfg_fs_config *cfg_view;
0208 struct device *dev = cscfg_device();
0209 int err;
0210
0211 if (!dev)
0212 return ERR_PTR(-EINVAL);
0213
0214 cfg_view = devm_kzalloc(dev, sizeof(struct cscfg_fs_config), GFP_KERNEL);
0215 if (!cfg_view)
0216 return ERR_PTR(-ENOMEM);
0217
0218 cfg_view->config_desc = config_desc;
0219 config_group_init_type_name(&cfg_view->group, config_desc->name, &cscfg_config_view_type);
0220
0221
0222 err = cscfg_add_preset_groups(cfg_view);
0223 if (err)
0224 return ERR_PTR(err);
0225
0226 return &cfg_view->group;
0227 }
0228
0229
0230
0231 static ssize_t cscfg_feat_description_show(struct config_item *item, char *page)
0232 {
0233 struct cscfg_fs_feature *fs_feat = container_of(to_config_group(item),
0234 struct cscfg_fs_feature, group);
0235
0236 return scnprintf(page, PAGE_SIZE, "%s", fs_feat->feat_desc->description);
0237 }
0238 CONFIGFS_ATTR_RO(cscfg_feat_, description);
0239
0240 static ssize_t cscfg_feat_matches_show(struct config_item *item, char *page)
0241 {
0242 struct cscfg_fs_feature *fs_feat = container_of(to_config_group(item),
0243 struct cscfg_fs_feature, group);
0244 u32 match_flags = fs_feat->feat_desc->match_flags;
0245 int used = 0;
0246
0247 if (match_flags & CS_CFG_MATCH_CLASS_SRC_ALL)
0248 used = scnprintf(page, PAGE_SIZE, "SRC_ALL ");
0249
0250 if (match_flags & CS_CFG_MATCH_CLASS_SRC_ETM4)
0251 used += scnprintf(page + used, PAGE_SIZE - used, "SRC_ETMV4 ");
0252
0253 used += scnprintf(page + used, PAGE_SIZE - used, "\n");
0254 return used;
0255 }
0256 CONFIGFS_ATTR_RO(cscfg_feat_, matches);
0257
0258 static ssize_t cscfg_feat_nr_params_show(struct config_item *item, char *page)
0259 {
0260 struct cscfg_fs_feature *fs_feat = container_of(to_config_group(item),
0261 struct cscfg_fs_feature, group);
0262
0263 return scnprintf(page, PAGE_SIZE, "%d\n", fs_feat->feat_desc->nr_params);
0264 }
0265 CONFIGFS_ATTR_RO(cscfg_feat_, nr_params);
0266
0267
0268 static struct configfs_attribute *cscfg_feature_view_attrs[] = {
0269 &cscfg_feat_attr_description,
0270 &cscfg_feat_attr_matches,
0271 &cscfg_feat_attr_nr_params,
0272 NULL,
0273 };
0274
0275 static struct config_item_type cscfg_feature_view_type = {
0276 .ct_owner = THIS_MODULE,
0277 .ct_attrs = cscfg_feature_view_attrs,
0278 };
0279
0280 static ssize_t cscfg_param_value_show(struct config_item *item, char *page)
0281 {
0282 struct cscfg_fs_param *param_item = container_of(to_config_group(item),
0283 struct cscfg_fs_param, group);
0284 u64 value = param_item->feat_desc->params_desc[param_item->param_idx].value;
0285
0286 return scnprintf(page, PAGE_SIZE, "0x%llx\n", value);
0287 }
0288
0289 static ssize_t cscfg_param_value_store(struct config_item *item,
0290 const char *page, size_t size)
0291 {
0292 struct cscfg_fs_param *param_item = container_of(to_config_group(item),
0293 struct cscfg_fs_param, group);
0294 struct cscfg_feature_desc *feat_desc = param_item->feat_desc;
0295 int param_idx = param_item->param_idx;
0296 u64 value;
0297 int err;
0298
0299 err = kstrtoull(page, 0, &value);
0300 if (!err)
0301 err = cscfg_update_feat_param_val(feat_desc, param_idx, value);
0302
0303 return err ? err : size;
0304 }
0305 CONFIGFS_ATTR(cscfg_param_, value);
0306
0307 static struct configfs_attribute *cscfg_param_view_attrs[] = {
0308 &cscfg_param_attr_value,
0309 NULL,
0310 };
0311
0312 static struct config_item_type cscfg_param_view_type = {
0313 .ct_owner = THIS_MODULE,
0314 .ct_attrs = cscfg_param_view_attrs,
0315 };
0316
0317
0318
0319
0320
0321
0322 static int cscfg_create_params_group_items(struct cscfg_feature_desc *feat_desc,
0323 struct config_group *params_group)
0324 {
0325 struct device *dev = cscfg_device();
0326 struct cscfg_fs_param *param_item;
0327 int i;
0328
0329
0330 for (i = 0; i < feat_desc->nr_params; i++) {
0331 param_item = devm_kzalloc(dev, sizeof(struct cscfg_fs_param), GFP_KERNEL);
0332 if (!param_item)
0333 return -ENOMEM;
0334 param_item->feat_desc = feat_desc;
0335 param_item->param_idx = i;
0336 config_group_init_type_name(¶m_item->group,
0337 feat_desc->params_desc[i].name,
0338 &cscfg_param_view_type);
0339 configfs_add_default_group(¶m_item->group, params_group);
0340 }
0341 return 0;
0342 }
0343
0344 static struct config_group *cscfg_create_feature_group(struct cscfg_feature_desc *feat_desc)
0345 {
0346 struct cscfg_fs_feature *feat_view;
0347 struct config_item_type *params_group_type;
0348 struct config_group *params_group = NULL;
0349 struct device *dev = cscfg_device();
0350 int item_err;
0351
0352 if (!dev)
0353 return ERR_PTR(-EINVAL);
0354
0355 feat_view = devm_kzalloc(dev, sizeof(struct cscfg_fs_feature), GFP_KERNEL);
0356 if (!feat_view)
0357 return ERR_PTR(-ENOMEM);
0358
0359 if (feat_desc->nr_params) {
0360 params_group = devm_kzalloc(dev, sizeof(struct config_group), GFP_KERNEL);
0361 if (!params_group)
0362 return ERR_PTR(-ENOMEM);
0363
0364 params_group_type = cscfg_create_ci_type();
0365 if (!params_group_type)
0366 return ERR_PTR(-ENOMEM);
0367 }
0368
0369 feat_view->feat_desc = feat_desc;
0370 config_group_init_type_name(&feat_view->group,
0371 feat_desc->name,
0372 &cscfg_feature_view_type);
0373 if (params_group) {
0374 config_group_init_type_name(params_group, "params", params_group_type);
0375 configfs_add_default_group(params_group, &feat_view->group);
0376 item_err = cscfg_create_params_group_items(feat_desc, params_group);
0377 if (item_err)
0378 return ERR_PTR(item_err);
0379 }
0380 return &feat_view->group;
0381 }
0382
0383 static struct config_item_type cscfg_configs_type = {
0384 .ct_owner = THIS_MODULE,
0385 };
0386
0387 static struct config_group cscfg_configs_grp = {
0388 .cg_item = {
0389 .ci_namebuf = "configurations",
0390 .ci_type = &cscfg_configs_type,
0391 },
0392 };
0393
0394
0395 int cscfg_configfs_add_config(struct cscfg_config_desc *config_desc)
0396 {
0397 struct config_group *new_group;
0398 int err;
0399
0400 new_group = cscfg_create_config_group(config_desc);
0401 if (IS_ERR(new_group))
0402 return PTR_ERR(new_group);
0403 err = configfs_register_group(&cscfg_configs_grp, new_group);
0404 if (!err)
0405 config_desc->fs_group = new_group;
0406 return err;
0407 }
0408
0409 void cscfg_configfs_del_config(struct cscfg_config_desc *config_desc)
0410 {
0411 if (config_desc->fs_group) {
0412 configfs_unregister_group(config_desc->fs_group);
0413 config_desc->fs_group = NULL;
0414 }
0415 }
0416
0417 static struct config_item_type cscfg_features_type = {
0418 .ct_owner = THIS_MODULE,
0419 };
0420
0421 static struct config_group cscfg_features_grp = {
0422 .cg_item = {
0423 .ci_namebuf = "features",
0424 .ci_type = &cscfg_features_type,
0425 },
0426 };
0427
0428
0429 int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc)
0430 {
0431 struct config_group *new_group;
0432 int err;
0433
0434 new_group = cscfg_create_feature_group(feat_desc);
0435 if (IS_ERR(new_group))
0436 return PTR_ERR(new_group);
0437 err = configfs_register_group(&cscfg_features_grp, new_group);
0438 if (!err)
0439 feat_desc->fs_group = new_group;
0440 return err;
0441 }
0442
0443 void cscfg_configfs_del_feature(struct cscfg_feature_desc *feat_desc)
0444 {
0445 if (feat_desc->fs_group) {
0446 configfs_unregister_group(feat_desc->fs_group);
0447 feat_desc->fs_group = NULL;
0448 }
0449 }
0450
0451 int cscfg_configfs_init(struct cscfg_manager *cscfg_mgr)
0452 {
0453 struct configfs_subsystem *subsys;
0454 struct config_item_type *ci_type;
0455
0456 if (!cscfg_mgr)
0457 return -EINVAL;
0458
0459 ci_type = cscfg_create_ci_type();
0460 if (!ci_type)
0461 return -ENOMEM;
0462
0463 subsys = &cscfg_mgr->cfgfs_subsys;
0464 config_item_set_name(&subsys->su_group.cg_item, CSCFG_FS_SUBSYS_NAME);
0465 subsys->su_group.cg_item.ci_type = ci_type;
0466
0467 config_group_init(&subsys->su_group);
0468 mutex_init(&subsys->su_mutex);
0469
0470
0471 config_group_init(&cscfg_configs_grp);
0472 configfs_add_default_group(&cscfg_configs_grp, &subsys->su_group);
0473
0474 config_group_init(&cscfg_features_grp);
0475 configfs_add_default_group(&cscfg_features_grp, &subsys->su_group);
0476
0477 return configfs_register_subsystem(subsys);
0478 }
0479
0480 void cscfg_configfs_release(struct cscfg_manager *cscfg_mgr)
0481 {
0482 configfs_unregister_subsystem(&cscfg_mgr->cfgfs_subsys);
0483 }