1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * System Trace Module (STM) master/channel allocation policy management 4 * Copyright (c) 2014, Intel Corporation. 5 * 6 * A master/channel allocation policy allows mapping string identifiers to 7 * master and channel ranges, where allocation can be done. 8 */ 9 10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 12 #include <linux/types.h> 13 #include <linux/module.h> 14 #include <linux/device.h> 15 #include <linux/configfs.h> 16 #include <linux/slab.h> 17 #include <linux/stm.h> 18 #include "stm.h" 19 20 /* 21 * STP Master/Channel allocation policy configfs layout. 22 */ 23 24 struct stp_policy { 25 struct config_group group; 26 struct stm_device *stm; 27 }; 28 29 struct stp_policy_node { 30 struct config_group group; 31 struct stp_policy *policy; 32 unsigned int first_master; 33 unsigned int last_master; 34 unsigned int first_channel; 35 unsigned int last_channel; 36 }; 37 38 static struct configfs_subsystem stp_policy_subsys; 39 40 void stp_policy_node_get_ranges(struct stp_policy_node *policy_node, 41 unsigned int *mstart, unsigned int *mend, 42 unsigned int *cstart, unsigned int *cend) 43 { 44 *mstart = policy_node->first_master; 45 *mend = policy_node->last_master; 46 *cstart = policy_node->first_channel; 47 *cend = policy_node->last_channel; 48 } 49 50 static inline char *stp_policy_node_name(struct stp_policy_node *policy_node) 51 { 52 return policy_node->group.cg_item.ci_name ? : "<none>"; 53 } 54 55 static inline struct stp_policy *to_stp_policy(struct config_item *item) 56 { 57 return item ? 58 container_of(to_config_group(item), struct stp_policy, group) : 59 NULL; 60 } 61 62 static inline struct stp_policy_node * 63 to_stp_policy_node(struct config_item *item) 64 { 65 return item ? 66 container_of(to_config_group(item), struct stp_policy_node, 67 group) : 68 NULL; 69 } 70 71 static ssize_t 72 stp_policy_node_masters_show(struct config_item *item, char *page) 73 { 74 struct stp_policy_node *policy_node = to_stp_policy_node(item); 75 ssize_t count; 76 77 count = sprintf(page, "%u %u\n", policy_node->first_master, 78 policy_node->last_master); 79 80 return count; 81 } 82 83 static ssize_t 84 stp_policy_node_masters_store(struct config_item *item, const char *page, 85 size_t count) 86 { 87 struct stp_policy_node *policy_node = to_stp_policy_node(item); 88 unsigned int first, last; 89 struct stm_device *stm; 90 char *p = (char *)page; 91 ssize_t ret = -ENODEV; 92 93 if (sscanf(p, "%u %u", &first, &last) != 2) 94 return -EINVAL; 95 96 mutex_lock(&stp_policy_subsys.su_mutex); 97 stm = policy_node->policy->stm; 98 if (!stm) 99 goto unlock; 100 101 /* must be within [sw_start..sw_end], which is an inclusive range */ 102 if (first > last || first < stm->data->sw_start || 103 last > stm->data->sw_end) { 104 ret = -ERANGE; 105 goto unlock; 106 } 107 108 ret = count; 109 policy_node->first_master = first; 110 policy_node->last_master = last; 111 112 unlock: 113 mutex_unlock(&stp_policy_subsys.su_mutex); 114 115 return ret; 116 } 117 118 static ssize_t 119 stp_policy_node_channels_show(struct config_item *item, char *page) 120 { 121 struct stp_policy_node *policy_node = to_stp_policy_node(item); 122 ssize_t count; 123 124 count = sprintf(page, "%u %u\n", policy_node->first_channel, 125 policy_node->last_channel); 126 127 return count; 128 } 129 130 static ssize_t 131 stp_policy_node_channels_store(struct config_item *item, const char *page, 132 size_t count) 133 { 134 struct stp_policy_node *policy_node = to_stp_policy_node(item); 135 unsigned int first, last; 136 struct stm_device *stm; 137 char *p = (char *)page; 138 ssize_t ret = -ENODEV; 139 140 if (sscanf(p, "%u %u", &first, &last) != 2) 141 return -EINVAL; 142 143 mutex_lock(&stp_policy_subsys.su_mutex); 144 stm = policy_node->policy->stm; 145 if (!stm) 146 goto unlock; 147 148 if (first > INT_MAX || last > INT_MAX || first > last || 149 last >= stm->data->sw_nchannels) { 150 ret = -ERANGE; 151 goto unlock; 152 } 153 154 ret = count; 155 policy_node->first_channel = first; 156 policy_node->last_channel = last; 157 158 unlock: 159 mutex_unlock(&stp_policy_subsys.su_mutex); 160 161 return ret; 162 } 163 164 static void stp_policy_node_release(struct config_item *item) 165 { 166 kfree(to_stp_policy_node(item)); 167 } 168 169 static struct configfs_item_operations stp_policy_node_item_ops = { 170 .release = stp_policy_node_release, 171 }; 172 173 CONFIGFS_ATTR(stp_policy_node_, masters); 174 CONFIGFS_ATTR(stp_policy_node_, channels); 175 176 static struct configfs_attribute *stp_policy_node_attrs[] = { 177 &stp_policy_node_attr_masters, 178 &stp_policy_node_attr_channels, 179 NULL, 180 }; 181 182 static const struct config_item_type stp_policy_type; 183 static const struct config_item_type stp_policy_node_type; 184 185 static struct config_group * 186 stp_policy_node_make(struct config_group *group, const char *name) 187 { 188 struct stp_policy_node *policy_node, *parent_node; 189 struct stp_policy *policy; 190 191 if (group->cg_item.ci_type == &stp_policy_type) { 192 policy = container_of(group, struct stp_policy, group); 193 } else { 194 parent_node = container_of(group, struct stp_policy_node, 195 group); 196 policy = parent_node->policy; 197 } 198 199 if (!policy->stm) 200 return ERR_PTR(-ENODEV); 201 202 policy_node = kzalloc(sizeof(struct stp_policy_node), GFP_KERNEL); 203 if (!policy_node) 204 return ERR_PTR(-ENOMEM); 205 206 config_group_init_type_name(&policy_node->group, name, 207 &stp_policy_node_type); 208 209 policy_node->policy = policy; 210 211 /* default values for the attributes */ 212 policy_node->first_master = policy->stm->data->sw_start; 213 policy_node->last_master = policy->stm->data->sw_end; 214 policy_node->first_channel = 0; 215 policy_node->last_channel = policy->stm->data->sw_nchannels - 1; 216 217 return &policy_node->group; 218 } 219 220 static void 221 stp_policy_node_drop(struct config_group *group, struct config_item *item) 222 { 223 config_item_put(item); 224 } 225 226 static struct configfs_group_operations stp_policy_node_group_ops = { 227 .make_group = stp_policy_node_make, 228 .drop_item = stp_policy_node_drop, 229 }; 230 231 static const struct config_item_type stp_policy_node_type = { 232 .ct_item_ops = &stp_policy_node_item_ops, 233 .ct_group_ops = &stp_policy_node_group_ops, 234 .ct_attrs = stp_policy_node_attrs, 235 .ct_owner = THIS_MODULE, 236 }; 237 238 /* 239 * Root group: policies. 240 */ 241 static ssize_t stp_policy_device_show(struct config_item *item, 242 char *page) 243 { 244 struct stp_policy *policy = to_stp_policy(item); 245 ssize_t count; 246 247 count = sprintf(page, "%s\n", 248 (policy && policy->stm) ? 249 policy->stm->data->name : 250 "<none>"); 251 252 return count; 253 } 254 255 CONFIGFS_ATTR_RO(stp_policy_, device); 256 257 static struct configfs_attribute *stp_policy_attrs[] = { 258 &stp_policy_attr_device, 259 NULL, 260 }; 261 262 void stp_policy_unbind(struct stp_policy *policy) 263 { 264 struct stm_device *stm = policy->stm; 265 266 /* 267 * stp_policy_release() will not call here if the policy is already 268 * unbound; other users should not either, as no link exists between 269 * this policy and anything else in that case 270 */ 271 if (WARN_ON_ONCE(!policy->stm)) 272 return; 273 274 lockdep_assert_held(&stm->policy_mutex); 275 276 stm->policy = NULL; 277 policy->stm = NULL; 278 279 stm_put_device(stm); 280 } 281 282 static void stp_policy_release(struct config_item *item) 283 { 284 struct stp_policy *policy = to_stp_policy(item); 285 struct stm_device *stm = policy->stm; 286 287 /* a policy *can* be unbound and still exist in configfs tree */ 288 if (!stm) 289 return; 290 291 mutex_lock(&stm->policy_mutex); 292 stp_policy_unbind(policy); 293 mutex_unlock(&stm->policy_mutex); 294 295 kfree(policy); 296 } 297 298 static struct configfs_item_operations stp_policy_item_ops = { 299 .release = stp_policy_release, 300 }; 301 302 static struct configfs_group_operations stp_policy_group_ops = { 303 .make_group = stp_policy_node_make, 304 }; 305 306 static const struct config_item_type stp_policy_type = { 307 .ct_item_ops = &stp_policy_item_ops, 308 .ct_group_ops = &stp_policy_group_ops, 309 .ct_attrs = stp_policy_attrs, 310 .ct_owner = THIS_MODULE, 311 }; 312 313 static struct config_group * 314 stp_policies_make(struct config_group *group, const char *name) 315 { 316 struct config_group *ret; 317 struct stm_device *stm; 318 char *devname, *p; 319 320 devname = kasprintf(GFP_KERNEL, "%s", name); 321 if (!devname) 322 return ERR_PTR(-ENOMEM); 323 324 /* 325 * node must look like <device_name>.<policy_name>, where 326 * <device_name> is the name of an existing stm device; may 327 * contain dots; 328 * <policy_name> is an arbitrary string; may not contain dots 329 */ 330 p = strrchr(devname, '.'); 331 if (!p) { 332 kfree(devname); 333 return ERR_PTR(-EINVAL); 334 } 335 336 *p = '\0'; 337 338 stm = stm_find_device(devname); 339 kfree(devname); 340 341 if (!stm) 342 return ERR_PTR(-ENODEV); 343 344 mutex_lock(&stm->policy_mutex); 345 if (stm->policy) { 346 ret = ERR_PTR(-EBUSY); 347 goto unlock_policy; 348 } 349 350 stm->policy = kzalloc(sizeof(*stm->policy), GFP_KERNEL); 351 if (!stm->policy) { 352 ret = ERR_PTR(-ENOMEM); 353 goto unlock_policy; 354 } 355 356 config_group_init_type_name(&stm->policy->group, name, 357 &stp_policy_type); 358 stm->policy->stm = stm; 359 360 ret = &stm->policy->group; 361 362 unlock_policy: 363 mutex_unlock(&stm->policy_mutex); 364 365 if (IS_ERR(ret)) 366 stm_put_device(stm); 367 368 return ret; 369 } 370 371 static struct configfs_group_operations stp_policies_group_ops = { 372 .make_group = stp_policies_make, 373 }; 374 375 static const struct config_item_type stp_policies_type = { 376 .ct_group_ops = &stp_policies_group_ops, 377 .ct_owner = THIS_MODULE, 378 }; 379 380 static struct configfs_subsystem stp_policy_subsys = { 381 .su_group = { 382 .cg_item = { 383 .ci_namebuf = "stp-policy", 384 .ci_type = &stp_policies_type, 385 }, 386 }, 387 }; 388 389 /* 390 * Lock the policy mutex from the outside 391 */ 392 static struct stp_policy_node * 393 __stp_policy_node_lookup(struct stp_policy *policy, char *s) 394 { 395 struct stp_policy_node *policy_node, *ret; 396 struct list_head *head = &policy->group.cg_children; 397 struct config_item *item; 398 char *start, *end = s; 399 400 if (list_empty(head)) 401 return NULL; 402 403 /* return the first entry if everything else fails */ 404 item = list_entry(head->next, struct config_item, ci_entry); 405 ret = to_stp_policy_node(item); 406 407 next: 408 for (;;) { 409 start = strsep(&end, "/"); 410 if (!start) 411 break; 412 413 if (!*start) 414 continue; 415 416 list_for_each_entry(item, head, ci_entry) { 417 policy_node = to_stp_policy_node(item); 418 419 if (!strcmp(start, 420 policy_node->group.cg_item.ci_name)) { 421 ret = policy_node; 422 423 if (!end) 424 goto out; 425 426 head = &policy_node->group.cg_children; 427 goto next; 428 } 429 } 430 break; 431 } 432 433 out: 434 return ret; 435 } 436 437 438 struct stp_policy_node * 439 stp_policy_node_lookup(struct stm_device *stm, char *s) 440 { 441 struct stp_policy_node *policy_node = NULL; 442 443 mutex_lock(&stp_policy_subsys.su_mutex); 444 445 mutex_lock(&stm->policy_mutex); 446 if (stm->policy) 447 policy_node = __stp_policy_node_lookup(stm->policy, s); 448 mutex_unlock(&stm->policy_mutex); 449 450 if (policy_node) 451 config_item_get(&policy_node->group.cg_item); 452 mutex_unlock(&stp_policy_subsys.su_mutex); 453 454 return policy_node; 455 } 456 457 void stp_policy_node_put(struct stp_policy_node *policy_node) 458 { 459 config_item_put(&policy_node->group.cg_item); 460 } 461 462 int __init stp_configfs_init(void) 463 { 464 int err; 465 466 config_group_init(&stp_policy_subsys.su_group); 467 mutex_init(&stp_policy_subsys.su_mutex); 468 err = configfs_register_subsystem(&stp_policy_subsys); 469 470 return err; 471 } 472 473 void __exit stp_configfs_exit(void) 474 { 475 configfs_unregister_subsystem(&stp_policy_subsys); 476 } 477