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
);