]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/hwtracing/stm/policy.c
Merge branch 'for-linus-3' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[mirror_ubuntu-artful-kernel.git] / drivers / hwtracing / stm / policy.c
1 /*
2 * System Trace Module (STM) master/channel allocation policy management
3 * Copyright (c) 2014, Intel Corporation.
4 *
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.
8 *
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
12 * more details.
13 *
14 * A master/channel allocation policy allows mapping string identifiers to
15 * master and channel ranges, where allocation can be done.
16 */
17
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
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>
26 #include "stm.h"
27
28 /*
29 * STP Master/Channel allocation policy configfs layout.
30 */
31
32 struct stp_policy {
33 struct config_group group;
34 struct stm_device *stm;
35 };
36
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;
44 };
45
46 static struct configfs_subsystem stp_policy_subsys;
47
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)
51 {
52 *mstart = policy_node->first_master;
53 *mend = policy_node->last_master;
54 *cstart = policy_node->first_channel;
55 *cend = policy_node->last_channel;
56 }
57
58 static inline char *stp_policy_node_name(struct stp_policy_node *policy_node)
59 {
60 return policy_node->group.cg_item.ci_name ? : "<none>";
61 }
62
63 static inline struct stp_policy *to_stp_policy(struct config_item *item)
64 {
65 return item ?
66 container_of(to_config_group(item), struct stp_policy, group) :
67 NULL;
68 }
69
70 static inline struct stp_policy_node *
71 to_stp_policy_node(struct config_item *item)
72 {
73 return item ?
74 container_of(to_config_group(item), struct stp_policy_node,
75 group) :
76 NULL;
77 }
78
79 static ssize_t stp_policy_node_masters_show(struct stp_policy_node *policy_node,
80 char *page)
81 {
82 ssize_t count;
83
84 count = sprintf(page, "%u %u\n", policy_node->first_master,
85 policy_node->last_master);
86
87 return count;
88 }
89
90 static ssize_t
91 stp_policy_node_masters_store(struct stp_policy_node *policy_node,
92 const char *page, size_t count)
93 {
94 unsigned int first, last;
95 struct stm_device *stm;
96 char *p = (char *)page;
97 ssize_t ret = -ENODEV;
98
99 if (sscanf(p, "%u %u", &first, &last) != 2)
100 return -EINVAL;
101
102 mutex_lock(&stp_policy_subsys.su_mutex);
103 stm = policy_node->policy->stm;
104 if (!stm)
105 goto unlock;
106
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) {
111 ret = -ERANGE;
112 goto unlock;
113 }
114
115 ret = count;
116 policy_node->first_master = first;
117 policy_node->last_master = last;
118
119 unlock:
120 mutex_unlock(&stp_policy_subsys.su_mutex);
121
122 return ret;
123 }
124
125 static ssize_t
126 stp_policy_node_channels_show(struct stp_policy_node *policy_node, char *page)
127 {
128 ssize_t count;
129
130 count = sprintf(page, "%u %u\n", policy_node->first_channel,
131 policy_node->last_channel);
132
133 return count;
134 }
135
136 static ssize_t
137 stp_policy_node_channels_store(struct stp_policy_node *policy_node,
138 const char *page, size_t count)
139 {
140 unsigned int first, last;
141 struct stm_device *stm;
142 char *p = (char *)page;
143 ssize_t ret = -ENODEV;
144
145 if (sscanf(p, "%u %u", &first, &last) != 2)
146 return -EINVAL;
147
148 mutex_lock(&stp_policy_subsys.su_mutex);
149 stm = policy_node->policy->stm;
150 if (!stm)
151 goto unlock;
152
153 if (first > INT_MAX || last > INT_MAX || first > last ||
154 last >= stm->data->sw_nchannels) {
155 ret = -ERANGE;
156 goto unlock;
157 }
158
159 ret = count;
160 policy_node->first_channel = first;
161 policy_node->last_channel = last;
162
163 unlock:
164 mutex_unlock(&stp_policy_subsys.su_mutex);
165
166 return ret;
167 }
168
169 static void stp_policy_node_release(struct config_item *item)
170 {
171 kfree(to_stp_policy_node(item));
172 }
173
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);
178 };
179
180 static ssize_t stp_policy_node_attr_show(struct config_item *item,
181 struct configfs_attribute *attr,
182 char *page)
183 {
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);
187 ssize_t count = 0;
188
189 if (pn_attr->show)
190 count = pn_attr->show(policy_node, page);
191
192 return count;
193 }
194
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)
198 {
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;
203
204 if (pn_attr->store)
205 count = pn_attr->store(policy_node, page, len);
206
207 return count;
208 }
209
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,
214 };
215
216 static struct stp_policy_node_attribute stp_policy_node_attr_range = {
217 .attr = {
218 .ca_owner = THIS_MODULE,
219 .ca_name = "masters",
220 .ca_mode = S_IRUGO | S_IWUSR,
221 },
222 .show = stp_policy_node_masters_show,
223 .store = stp_policy_node_masters_store,
224 };
225
226 static struct stp_policy_node_attribute stp_policy_node_attr_channels = {
227 .attr = {
228 .ca_owner = THIS_MODULE,
229 .ca_name = "channels",
230 .ca_mode = S_IRUGO | S_IWUSR,
231 },
232 .show = stp_policy_node_channels_show,
233 .store = stp_policy_node_channels_store,
234 };
235
236 static struct configfs_attribute *stp_policy_node_attrs[] = {
237 &stp_policy_node_attr_range.attr,
238 &stp_policy_node_attr_channels.attr,
239 NULL,
240 };
241
242 static struct config_item_type stp_policy_type;
243 static struct config_item_type stp_policy_node_type;
244
245 static struct config_group *
246 stp_policy_node_make(struct config_group *group, const char *name)
247 {
248 struct stp_policy_node *policy_node, *parent_node;
249 struct stp_policy *policy;
250
251 if (group->cg_item.ci_type == &stp_policy_type) {
252 policy = container_of(group, struct stp_policy, group);
253 } else {
254 parent_node = container_of(group, struct stp_policy_node,
255 group);
256 policy = parent_node->policy;
257 }
258
259 if (!policy->stm)
260 return ERR_PTR(-ENODEV);
261
262 policy_node = kzalloc(sizeof(struct stp_policy_node), GFP_KERNEL);
263 if (!policy_node)
264 return ERR_PTR(-ENOMEM);
265
266 config_group_init_type_name(&policy_node->group, name,
267 &stp_policy_node_type);
268
269 policy_node->policy = policy;
270
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;
276
277 return &policy_node->group;
278 }
279
280 static void
281 stp_policy_node_drop(struct config_group *group, struct config_item *item)
282 {
283 config_item_put(item);
284 }
285
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,
289 };
290
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,
296 };
297
298 /*
299 * Root group: policies.
300 */
301 static struct configfs_attribute stp_policy_attr_device = {
302 .ca_owner = THIS_MODULE,
303 .ca_name = "device",
304 .ca_mode = S_IRUGO,
305 };
306
307 static struct configfs_attribute *stp_policy_attrs[] = {
308 &stp_policy_attr_device,
309 NULL,
310 };
311
312 static ssize_t stp_policy_attr_show(struct config_item *item,
313 struct configfs_attribute *attr,
314 char *page)
315 {
316 struct stp_policy *policy = to_stp_policy(item);
317 ssize_t count;
318
319 count = sprintf(page, "%s\n",
320 (policy && policy->stm) ?
321 policy->stm->data->name :
322 "<none>");
323
324 return count;
325 }
326
327 void stp_policy_unbind(struct stp_policy *policy)
328 {
329 struct stm_device *stm = policy->stm;
330
331 if (WARN_ON_ONCE(!policy->stm))
332 return;
333
334 mutex_lock(&stm->policy_mutex);
335 stm->policy = NULL;
336 mutex_unlock(&stm->policy_mutex);
337
338 policy->stm = NULL;
339
340 stm_put_device(stm);
341 }
342
343 static void stp_policy_release(struct config_item *item)
344 {
345 struct stp_policy *policy = to_stp_policy(item);
346
347 stp_policy_unbind(policy);
348 kfree(policy);
349 }
350
351 static struct configfs_item_operations stp_policy_item_ops = {
352 .release = stp_policy_release,
353 .show_attribute = stp_policy_attr_show,
354 };
355
356 static struct configfs_group_operations stp_policy_group_ops = {
357 .make_group = stp_policy_node_make,
358 };
359
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,
365 };
366
367 static struct config_group *
368 stp_policies_make(struct config_group *group, const char *name)
369 {
370 struct config_group *ret;
371 struct stm_device *stm;
372 char *devname, *p;
373
374 devname = kasprintf(GFP_KERNEL, "%s", name);
375 if (!devname)
376 return ERR_PTR(-ENOMEM);
377
378 /*
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
382 */
383 p = strchr(devname, '.');
384 if (!p) {
385 kfree(devname);
386 return ERR_PTR(-EINVAL);
387 }
388
389 *p++ = '\0';
390
391 stm = stm_find_device(devname);
392 kfree(devname);
393
394 if (!stm)
395 return ERR_PTR(-ENODEV);
396
397 mutex_lock(&stm->policy_mutex);
398 if (stm->policy) {
399 ret = ERR_PTR(-EBUSY);
400 goto unlock_policy;
401 }
402
403 stm->policy = kzalloc(sizeof(*stm->policy), GFP_KERNEL);
404 if (!stm->policy) {
405 ret = ERR_PTR(-ENOMEM);
406 goto unlock_policy;
407 }
408
409 config_group_init_type_name(&stm->policy->group, name,
410 &stp_policy_type);
411 stm->policy->stm = stm;
412
413 ret = &stm->policy->group;
414
415 unlock_policy:
416 mutex_unlock(&stm->policy_mutex);
417
418 if (IS_ERR(ret))
419 stm_put_device(stm);
420
421 return ret;
422 }
423
424 static struct configfs_group_operations stp_policies_group_ops = {
425 .make_group = stp_policies_make,
426 };
427
428 static struct config_item_type stp_policies_type = {
429 .ct_group_ops = &stp_policies_group_ops,
430 .ct_owner = THIS_MODULE,
431 };
432
433 static struct configfs_subsystem stp_policy_subsys = {
434 .su_group = {
435 .cg_item = {
436 .ci_namebuf = "stp-policy",
437 .ci_type = &stp_policies_type,
438 },
439 },
440 };
441
442 /*
443 * Lock the policy mutex from the outside
444 */
445 static struct stp_policy_node *
446 __stp_policy_node_lookup(struct stp_policy *policy, char *s)
447 {
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;
452
453 if (list_empty(head))
454 return NULL;
455
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);
459
460 next:
461 for (;;) {
462 start = strsep(&end, "/");
463 if (!start)
464 break;
465
466 if (!*start)
467 continue;
468
469 list_for_each_entry(item, head, ci_entry) {
470 policy_node = to_stp_policy_node(item);
471
472 if (!strcmp(start,
473 policy_node->group.cg_item.ci_name)) {
474 ret = policy_node;
475
476 if (!end)
477 goto out;
478
479 head = &policy_node->group.cg_children;
480 goto next;
481 }
482 }
483 break;
484 }
485
486 out:
487 return ret;
488 }
489
490
491 struct stp_policy_node *
492 stp_policy_node_lookup(struct stm_device *stm, char *s)
493 {
494 struct stp_policy_node *policy_node = NULL;
495
496 mutex_lock(&stp_policy_subsys.su_mutex);
497
498 mutex_lock(&stm->policy_mutex);
499 if (stm->policy)
500 policy_node = __stp_policy_node_lookup(stm->policy, s);
501 mutex_unlock(&stm->policy_mutex);
502
503 if (policy_node)
504 config_item_get(&policy_node->group.cg_item);
505 mutex_unlock(&stp_policy_subsys.su_mutex);
506
507 return policy_node;
508 }
509
510 void stp_policy_node_put(struct stp_policy_node *policy_node)
511 {
512 config_item_put(&policy_node->group.cg_item);
513 }
514
515 int __init stp_configfs_init(void)
516 {
517 int err;
518
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);
522
523 return err;
524 }
525
526 void __exit stp_configfs_exit(void)
527 {
528 configfs_unregister_subsystem(&stp_policy_subsys);
529 }