2 * System Trace Module (STM) master/channel allocation policy management
3 * Copyright (c) 2014, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * A master/channel allocation policy allows mapping string identifiers to
15 * master and channel ranges, where allocation can be done.
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20 #include <linux/types.h>
21 #include <linux/module.h>
22 #include <linux/device.h>
23 #include <linux/configfs.h>
24 #include <linux/slab.h>
25 #include <linux/stm.h>
29 * STP Master/Channel allocation policy configfs layout.
33 struct config_group group;
34 struct stm_device *stm;
37 struct stp_policy_node {
38 struct config_group group;
39 struct stp_policy *policy;
40 unsigned int first_master;
41 unsigned int last_master;
42 unsigned int first_channel;
43 unsigned int last_channel;
46 static struct configfs_subsystem stp_policy_subsys;
48 void stp_policy_node_get_ranges(struct stp_policy_node *policy_node,
49 unsigned int *mstart, unsigned int *mend,
50 unsigned int *cstart, unsigned int *cend)
52 *mstart = policy_node->first_master;
53 *mend = policy_node->last_master;
54 *cstart = policy_node->first_channel;
55 *cend = policy_node->last_channel;
58 static inline char *stp_policy_node_name(struct stp_policy_node *policy_node)
60 return policy_node->group.cg_item.ci_name ? : "<none>";
63 static inline struct stp_policy *to_stp_policy(struct config_item *item)
66 container_of(to_config_group(item), struct stp_policy, group) :
70 static inline struct stp_policy_node *
71 to_stp_policy_node(struct config_item *item)
74 container_of(to_config_group(item), struct stp_policy_node,
79 static ssize_t stp_policy_node_masters_show(struct stp_policy_node *policy_node,
84 count = sprintf(page, "%u %u\n", policy_node->first_master,
85 policy_node->last_master);
91 stp_policy_node_masters_store(struct stp_policy_node *policy_node,
92 const char *page, size_t count)
94 unsigned int first, last;
95 struct stm_device *stm;
96 char *p = (char *)page;
97 ssize_t ret = -ENODEV;
99 if (sscanf(p, "%u %u", &first, &last) != 2)
102 mutex_lock(&stp_policy_subsys.su_mutex);
103 stm = policy_node->policy->stm;
107 /* must be within [sw_start..sw_end], which is an inclusive range */
108 if (first > INT_MAX || last > INT_MAX || first > last ||
109 first < stm->data->sw_start ||
110 last > stm->data->sw_end) {
116 policy_node->first_master = first;
117 policy_node->last_master = last;
120 mutex_unlock(&stp_policy_subsys.su_mutex);
126 stp_policy_node_channels_show(struct stp_policy_node *policy_node, char *page)
130 count = sprintf(page, "%u %u\n", policy_node->first_channel,
131 policy_node->last_channel);
137 stp_policy_node_channels_store(struct stp_policy_node *policy_node,
138 const char *page, size_t count)
140 unsigned int first, last;
141 struct stm_device *stm;
142 char *p = (char *)page;
143 ssize_t ret = -ENODEV;
145 if (sscanf(p, "%u %u", &first, &last) != 2)
148 mutex_lock(&stp_policy_subsys.su_mutex);
149 stm = policy_node->policy->stm;
153 if (first > INT_MAX || last > INT_MAX || first > last ||
154 last >= stm->data->sw_nchannels) {
160 policy_node->first_channel = first;
161 policy_node->last_channel = last;
164 mutex_unlock(&stp_policy_subsys.su_mutex);
169 static void stp_policy_node_release(struct config_item *item)
171 kfree(to_stp_policy_node(item));
174 struct stp_policy_node_attribute {
175 struct configfs_attribute attr;
176 ssize_t (*show)(struct stp_policy_node *, char *);
177 ssize_t (*store)(struct stp_policy_node *, const char *, size_t);
180 static ssize_t stp_policy_node_attr_show(struct config_item *item,
181 struct configfs_attribute *attr,
184 struct stp_policy_node *policy_node = to_stp_policy_node(item);
185 struct stp_policy_node_attribute *pn_attr =
186 container_of(attr, struct stp_policy_node_attribute, attr);
190 count = pn_attr->show(policy_node, page);
195 static ssize_t stp_policy_node_attr_store(struct config_item *item,
196 struct configfs_attribute *attr,
197 const char *page, size_t len)
199 struct stp_policy_node *policy_node = to_stp_policy_node(item);
200 struct stp_policy_node_attribute *pn_attr =
201 container_of(attr, struct stp_policy_node_attribute, attr);
202 ssize_t count = -EINVAL;
205 count = pn_attr->store(policy_node, page, len);
210 static struct configfs_item_operations stp_policy_node_item_ops = {
211 .release = stp_policy_node_release,
212 .show_attribute = stp_policy_node_attr_show,
213 .store_attribute = stp_policy_node_attr_store,
216 static struct stp_policy_node_attribute stp_policy_node_attr_range = {
218 .ca_owner = THIS_MODULE,
219 .ca_name = "masters",
220 .ca_mode = S_IRUGO | S_IWUSR,
222 .show = stp_policy_node_masters_show,
223 .store = stp_policy_node_masters_store,
226 static struct stp_policy_node_attribute stp_policy_node_attr_channels = {
228 .ca_owner = THIS_MODULE,
229 .ca_name = "channels",
230 .ca_mode = S_IRUGO | S_IWUSR,
232 .show = stp_policy_node_channels_show,
233 .store = stp_policy_node_channels_store,
236 static struct configfs_attribute *stp_policy_node_attrs[] = {
237 &stp_policy_node_attr_range.attr,
238 &stp_policy_node_attr_channels.attr,
242 static struct config_item_type stp_policy_type;
243 static struct config_item_type stp_policy_node_type;
245 static struct config_group *
246 stp_policy_node_make(struct config_group *group, const char *name)
248 struct stp_policy_node *policy_node, *parent_node;
249 struct stp_policy *policy;
251 if (group->cg_item.ci_type == &stp_policy_type) {
252 policy = container_of(group, struct stp_policy, group);
254 parent_node = container_of(group, struct stp_policy_node,
256 policy = parent_node->policy;
260 return ERR_PTR(-ENODEV);
262 policy_node = kzalloc(sizeof(struct stp_policy_node), GFP_KERNEL);
264 return ERR_PTR(-ENOMEM);
266 config_group_init_type_name(&policy_node->group, name,
267 &stp_policy_node_type);
269 policy_node->policy = policy;
271 /* default values for the attributes */
272 policy_node->first_master = policy->stm->data->sw_start;
273 policy_node->last_master = policy->stm->data->sw_end;
274 policy_node->first_channel = 0;
275 policy_node->last_channel = policy->stm->data->sw_nchannels - 1;
277 return &policy_node->group;
281 stp_policy_node_drop(struct config_group *group, struct config_item *item)
283 config_item_put(item);
286 static struct configfs_group_operations stp_policy_node_group_ops = {
287 .make_group = stp_policy_node_make,
288 .drop_item = stp_policy_node_drop,
291 static struct config_item_type stp_policy_node_type = {
292 .ct_item_ops = &stp_policy_node_item_ops,
293 .ct_group_ops = &stp_policy_node_group_ops,
294 .ct_attrs = stp_policy_node_attrs,
295 .ct_owner = THIS_MODULE,
299 * Root group: policies.
301 static struct configfs_attribute stp_policy_attr_device = {
302 .ca_owner = THIS_MODULE,
307 static struct configfs_attribute *stp_policy_attrs[] = {
308 &stp_policy_attr_device,
312 static ssize_t stp_policy_attr_show(struct config_item *item,
313 struct configfs_attribute *attr,
316 struct stp_policy *policy = to_stp_policy(item);
319 count = sprintf(page, "%s\n",
320 (policy && policy->stm) ?
321 policy->stm->data->name :
327 void stp_policy_unbind(struct stp_policy *policy)
329 struct stm_device *stm = policy->stm;
331 if (WARN_ON_ONCE(!policy->stm))
334 mutex_lock(&stm->policy_mutex);
336 mutex_unlock(&stm->policy_mutex);
343 static void stp_policy_release(struct config_item *item)
345 struct stp_policy *policy = to_stp_policy(item);
347 stp_policy_unbind(policy);
351 static struct configfs_item_operations stp_policy_item_ops = {
352 .release = stp_policy_release,
353 .show_attribute = stp_policy_attr_show,
356 static struct configfs_group_operations stp_policy_group_ops = {
357 .make_group = stp_policy_node_make,
360 static struct config_item_type stp_policy_type = {
361 .ct_item_ops = &stp_policy_item_ops,
362 .ct_group_ops = &stp_policy_group_ops,
363 .ct_attrs = stp_policy_attrs,
364 .ct_owner = THIS_MODULE,
367 static struct config_group *
368 stp_policies_make(struct config_group *group, const char *name)
370 struct config_group *ret;
371 struct stm_device *stm;
374 devname = kasprintf(GFP_KERNEL, "%s", name);
376 return ERR_PTR(-ENOMEM);
379 * node must look like <device_name>.<policy_name>, where
380 * <device_name> is the name of an existing stm device and
381 * <policy_name> is an arbitrary string
383 p = strchr(devname, '.');
386 return ERR_PTR(-EINVAL);
391 stm = stm_find_device(devname);
395 return ERR_PTR(-ENODEV);
397 mutex_lock(&stm->policy_mutex);
399 ret = ERR_PTR(-EBUSY);
403 stm->policy = kzalloc(sizeof(*stm->policy), GFP_KERNEL);
405 ret = ERR_PTR(-ENOMEM);
409 config_group_init_type_name(&stm->policy->group, name,
411 stm->policy->stm = stm;
413 ret = &stm->policy->group;
416 mutex_unlock(&stm->policy_mutex);
424 static struct configfs_group_operations stp_policies_group_ops = {
425 .make_group = stp_policies_make,
428 static struct config_item_type stp_policies_type = {
429 .ct_group_ops = &stp_policies_group_ops,
430 .ct_owner = THIS_MODULE,
433 static struct configfs_subsystem stp_policy_subsys = {
436 .ci_namebuf = "stp-policy",
437 .ci_type = &stp_policies_type,
443 * Lock the policy mutex from the outside
445 static struct stp_policy_node *
446 __stp_policy_node_lookup(struct stp_policy *policy, char *s)
448 struct stp_policy_node *policy_node, *ret;
449 struct list_head *head = &policy->group.cg_children;
450 struct config_item *item;
451 char *start, *end = s;
453 if (list_empty(head))
456 /* return the first entry if everything else fails */
457 item = list_entry(head->next, struct config_item, ci_entry);
458 ret = to_stp_policy_node(item);
462 start = strsep(&end, "/");
469 list_for_each_entry(item, head, ci_entry) {
470 policy_node = to_stp_policy_node(item);
473 policy_node->group.cg_item.ci_name)) {
479 head = &policy_node->group.cg_children;
491 struct stp_policy_node *
492 stp_policy_node_lookup(struct stm_device *stm, char *s)
494 struct stp_policy_node *policy_node = NULL;
496 mutex_lock(&stp_policy_subsys.su_mutex);
498 mutex_lock(&stm->policy_mutex);
500 policy_node = __stp_policy_node_lookup(stm->policy, s);
501 mutex_unlock(&stm->policy_mutex);
504 config_item_get(&policy_node->group.cg_item);
505 mutex_unlock(&stp_policy_subsys.su_mutex);
510 void stp_policy_node_put(struct stp_policy_node *policy_node)
512 config_item_put(&policy_node->group.cg_item);
515 int __init stp_configfs_init(void)
519 config_group_init(&stp_policy_subsys.su_group);
520 mutex_init(&stp_policy_subsys.su_mutex);
521 err = configfs_register_subsystem(&stp_policy_subsys);
526 void __exit stp_configfs_exit(void)
528 configfs_unregister_subsystem(&stp_policy_subsys);