aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwtracing
diff options
context:
space:
mode:
authorAlexander Shishkin <alexander.shishkin@linux.intel.com>2018-10-05 08:42:54 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-10-11 06:12:54 -0400
commitc7fd62bc69d0224877a49383e606f0fe52cba741 (patch)
tree493d702a25c3993b827457fcbb5d254ea5693d97 /drivers/hwtracing
parente967b8bdd462def829b1722ea2f0babdc9806bc2 (diff)
stm class: Introduce framing protocol drivers
At the moment, the stm class applies a certain STP framing pattern to the data as it is written to the underlying STM device. In order to allow different framing patterns (aka protocols), this patch introduces the concept of STP protocol drivers, defines data structures and APIs for the protocol drivers to use. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Tested-by: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hwtracing')
-rw-r--r--drivers/hwtracing/stm/core.c140
-rw-r--r--drivers/hwtracing/stm/policy.c145
-rw-r--r--drivers/hwtracing/stm/stm.h51
3 files changed, 318 insertions, 18 deletions
diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index 17198e79df3e..915af2541dcd 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -316,11 +316,26 @@ static int stm_output_assign(struct stm_device *stm, unsigned int width,
316 output->master = midx; 316 output->master = midx;
317 output->channel = cidx; 317 output->channel = cidx;
318 output->nr_chans = width; 318 output->nr_chans = width;
319 if (stm->pdrv->output_open) {
320 void *priv = stp_policy_node_priv(policy_node);
321
322 if (WARN_ON_ONCE(!priv))
323 goto unlock;
324
325 /* configfs subsys mutex is held by the caller */
326 ret = stm->pdrv->output_open(priv, output);
327 if (ret)
328 goto unlock;
329 }
330
319 stm_output_claim(stm, output); 331 stm_output_claim(stm, output);
320 dev_dbg(&stm->dev, "assigned %u:%u (+%u)\n", midx, cidx, width); 332 dev_dbg(&stm->dev, "assigned %u:%u (+%u)\n", midx, cidx, width);
321 333
322 ret = 0; 334 ret = 0;
323unlock: 335unlock:
336 if (ret)
337 output->nr_chans = 0;
338
324 spin_unlock(&output->lock); 339 spin_unlock(&output->lock);
325 spin_unlock(&stm->mc_lock); 340 spin_unlock(&stm->mc_lock);
326 341
@@ -333,6 +348,8 @@ static void stm_output_free(struct stm_device *stm, struct stm_output *output)
333 spin_lock(&output->lock); 348 spin_lock(&output->lock);
334 if (output->nr_chans) 349 if (output->nr_chans)
335 stm_output_disclaim(stm, output); 350 stm_output_disclaim(stm, output);
351 if (stm->pdrv && stm->pdrv->output_close)
352 stm->pdrv->output_close(output);
336 spin_unlock(&output->lock); 353 spin_unlock(&output->lock);
337 spin_unlock(&stm->mc_lock); 354 spin_unlock(&stm->mc_lock);
338} 355}
@@ -349,6 +366,127 @@ static int major_match(struct device *dev, const void *data)
349 return MAJOR(dev->devt) == major; 366 return MAJOR(dev->devt) == major;
350} 367}
351 368
369/*
370 * Framing protocol management
371 * Modules can implement STM protocol drivers and (un-)register them
372 * with the STM class framework.
373 */
374static struct list_head stm_pdrv_head;
375static struct mutex stm_pdrv_mutex;
376
377struct stm_pdrv_entry {
378 struct list_head entry;
379 const struct stm_protocol_driver *pdrv;
380 const struct config_item_type *node_type;
381};
382
383static const struct stm_pdrv_entry *
384__stm_lookup_protocol(const char *name)
385{
386 struct stm_pdrv_entry *pe;
387
388 /*
389 * If no name is given (NULL or ""), fall back to "p_basic".
390 */
391 if (!name || !*name)
392 name = "p_basic";
393
394 list_for_each_entry(pe, &stm_pdrv_head, entry) {
395 if (!strcmp(name, pe->pdrv->name))
396 return pe;
397 }
398
399 return NULL;
400}
401
402int stm_register_protocol(const struct stm_protocol_driver *pdrv)
403{
404 struct stm_pdrv_entry *pe = NULL;
405 int ret = -ENOMEM;
406
407 mutex_lock(&stm_pdrv_mutex);
408
409 if (__stm_lookup_protocol(pdrv->name)) {
410 ret = -EEXIST;
411 goto unlock;
412 }
413
414 pe = kzalloc(sizeof(*pe), GFP_KERNEL);
415 if (!pe)
416 goto unlock;
417
418 if (pdrv->policy_attr) {
419 pe->node_type = get_policy_node_type(pdrv->policy_attr);
420 if (!pe->node_type)
421 goto unlock;
422 }
423
424 list_add_tail(&pe->entry, &stm_pdrv_head);
425 pe->pdrv = pdrv;
426
427 ret = 0;
428unlock:
429 mutex_unlock(&stm_pdrv_mutex);
430
431 if (ret)
432 kfree(pe);
433
434 return ret;
435}
436EXPORT_SYMBOL_GPL(stm_register_protocol);
437
438void stm_unregister_protocol(const struct stm_protocol_driver *pdrv)
439{
440 struct stm_pdrv_entry *pe, *iter;
441
442 mutex_lock(&stm_pdrv_mutex);
443
444 list_for_each_entry_safe(pe, iter, &stm_pdrv_head, entry) {
445 if (pe->pdrv == pdrv) {
446 list_del(&pe->entry);
447
448 if (pe->node_type) {
449 kfree(pe->node_type->ct_attrs);
450 kfree(pe->node_type);
451 }
452 kfree(pe);
453 break;
454 }
455 }
456
457 mutex_unlock(&stm_pdrv_mutex);
458}
459EXPORT_SYMBOL_GPL(stm_unregister_protocol);
460
461static bool stm_get_protocol(const struct stm_protocol_driver *pdrv)
462{
463 return try_module_get(pdrv->owner);
464}
465
466void stm_put_protocol(const struct stm_protocol_driver *pdrv)
467{
468 module_put(pdrv->owner);
469}
470
471int stm_lookup_protocol(const char *name,
472 const struct stm_protocol_driver **pdrv,
473 const struct config_item_type **node_type)
474{
475 const struct stm_pdrv_entry *pe;
476
477 mutex_lock(&stm_pdrv_mutex);
478
479 pe = __stm_lookup_protocol(name);
480 if (pe && pe->pdrv && stm_get_protocol(pe->pdrv)) {
481 *pdrv = pe->pdrv;
482 *node_type = pe->node_type;
483 }
484
485 mutex_unlock(&stm_pdrv_mutex);
486
487 return pe ? 0 : -ENOENT;
488}
489
352static int stm_char_open(struct inode *inode, struct file *file) 490static int stm_char_open(struct inode *inode, struct file *file)
353{ 491{
354 struct stm_file *stmf; 492 struct stm_file *stmf;
@@ -1176,6 +1314,8 @@ static int __init stm_core_init(void)
1176 goto err_src; 1314 goto err_src;
1177 1315
1178 init_srcu_struct(&stm_source_srcu); 1316 init_srcu_struct(&stm_source_srcu);
1317 INIT_LIST_HEAD(&stm_pdrv_head);
1318 mutex_init(&stm_pdrv_mutex);
1179 1319
1180 stm_core_up++; 1320 stm_core_up++;
1181 1321
diff --git a/drivers/hwtracing/stm/policy.c b/drivers/hwtracing/stm/policy.c
index a505f055f464..8bc90432ae69 100644
--- a/drivers/hwtracing/stm/policy.c
+++ b/drivers/hwtracing/stm/policy.c
@@ -33,8 +33,18 @@ struct stp_policy_node {
33 unsigned int last_master; 33 unsigned int last_master;
34 unsigned int first_channel; 34 unsigned int first_channel;
35 unsigned int last_channel; 35 unsigned int last_channel;
36 /* this is the one that's exposed to the attributes */
37 unsigned char priv[0];
36}; 38};
37 39
40void *stp_policy_node_priv(struct stp_policy_node *pn)
41{
42 if (!pn)
43 return NULL;
44
45 return pn->priv;
46}
47
38static struct configfs_subsystem stp_policy_subsys; 48static struct configfs_subsystem stp_policy_subsys;
39 49
40void stp_policy_node_get_ranges(struct stp_policy_node *policy_node, 50void stp_policy_node_get_ranges(struct stp_policy_node *policy_node,
@@ -68,6 +78,14 @@ to_stp_policy_node(struct config_item *item)
68 NULL; 78 NULL;
69} 79}
70 80
81void *to_pdrv_policy_node(struct config_item *item)
82{
83 struct stp_policy_node *node = to_stp_policy_node(item);
84
85 return stp_policy_node_priv(node);
86}
87EXPORT_SYMBOL_GPL(to_pdrv_policy_node);
88
71static ssize_t 89static ssize_t
72stp_policy_node_masters_show(struct config_item *item, char *page) 90stp_policy_node_masters_show(struct config_item *item, char *page)
73{ 91{
@@ -163,7 +181,9 @@ unlock:
163 181
164static void stp_policy_node_release(struct config_item *item) 182static void stp_policy_node_release(struct config_item *item)
165{ 183{
166 kfree(to_stp_policy_node(item)); 184 struct stp_policy_node *node = to_stp_policy_node(item);
185
186 kfree(node);
167} 187}
168 188
169static struct configfs_item_operations stp_policy_node_item_ops = { 189static struct configfs_item_operations stp_policy_node_item_ops = {
@@ -182,10 +202,61 @@ static struct configfs_attribute *stp_policy_node_attrs[] = {
182static const struct config_item_type stp_policy_type; 202static const struct config_item_type stp_policy_type;
183static const struct config_item_type stp_policy_node_type; 203static const struct config_item_type stp_policy_node_type;
184 204
205/* lifted from arch/x86/events/core.c */
206static struct configfs_attribute **merge_attr(struct configfs_attribute **a, struct configfs_attribute **b)
207{
208 struct configfs_attribute **new;
209 int j, i;
210
211 for (j = 0; a[j]; j++)
212 ;
213 for (i = 0; b[i]; i++)
214 j++;
215 j++;
216
217 new = kmalloc_array(j, sizeof(struct configfs_attribute *),
218 GFP_KERNEL);
219 if (!new)
220 return NULL;
221
222 j = 0;
223 for (i = 0; a[i]; i++)
224 new[j++] = a[i];
225 for (i = 0; b[i]; i++)
226 new[j++] = b[i];
227 new[j] = NULL;
228
229 return new;
230}
231
232const struct config_item_type *
233get_policy_node_type(struct configfs_attribute **attrs)
234{
235 struct config_item_type *type;
236 struct configfs_attribute **merged;
237
238 type = kmemdup(&stp_policy_node_type, sizeof(stp_policy_node_type),
239 GFP_KERNEL);
240 if (!type)
241 return NULL;
242
243 merged = merge_attr(stp_policy_node_attrs, attrs);
244 if (!merged) {
245 kfree(type);
246 return NULL;
247 }
248
249 type->ct_attrs = merged;
250
251 return type;
252}
253
185static struct config_group * 254static struct config_group *
186stp_policy_node_make(struct config_group *group, const char *name) 255stp_policy_node_make(struct config_group *group, const char *name)
187{ 256{
257 const struct config_item_type *type = &stp_policy_node_type;
188 struct stp_policy_node *policy_node, *parent_node; 258 struct stp_policy_node *policy_node, *parent_node;
259 const struct stm_protocol_driver *pdrv;
189 struct stp_policy *policy; 260 struct stp_policy *policy;
190 261
191 if (group->cg_item.ci_type == &stp_policy_type) { 262 if (group->cg_item.ci_type == &stp_policy_type) {
@@ -199,12 +270,20 @@ stp_policy_node_make(struct config_group *group, const char *name)
199 if (!policy->stm) 270 if (!policy->stm)
200 return ERR_PTR(-ENODEV); 271 return ERR_PTR(-ENODEV);
201 272
202 policy_node = kzalloc(sizeof(struct stp_policy_node), GFP_KERNEL); 273 pdrv = policy->stm->pdrv;
274 policy_node =
275 kzalloc(offsetof(struct stp_policy_node, priv[pdrv->priv_sz]),
276 GFP_KERNEL);
203 if (!policy_node) 277 if (!policy_node)
204 return ERR_PTR(-ENOMEM); 278 return ERR_PTR(-ENOMEM);
205 279
206 config_group_init_type_name(&policy_node->group, name, 280 if (pdrv->policy_node_init)
207 &stp_policy_node_type); 281 pdrv->policy_node_init((void *)policy_node->priv);
282
283 if (policy->stm->pdrv_node_type)
284 type = policy->stm->pdrv_node_type;
285
286 config_group_init_type_name(&policy_node->group, name, type);
208 287
209 policy_node->policy = policy; 288 policy_node->policy = policy;
210 289
@@ -254,8 +333,25 @@ static ssize_t stp_policy_device_show(struct config_item *item,
254 333
255CONFIGFS_ATTR_RO(stp_policy_, device); 334CONFIGFS_ATTR_RO(stp_policy_, device);
256 335
336static ssize_t stp_policy_protocol_show(struct config_item *item,
337 char *page)
338{
339 struct stp_policy *policy = to_stp_policy(item);
340 ssize_t count;
341
342 count = sprintf(page, "%s\n",
343 (policy && policy->stm) ?
344 policy->stm->pdrv->name :
345 "<none>");
346
347 return count;
348}
349
350CONFIGFS_ATTR_RO(stp_policy_, protocol);
351
257static struct configfs_attribute *stp_policy_attrs[] = { 352static struct configfs_attribute *stp_policy_attrs[] = {
258 &stp_policy_attr_device, 353 &stp_policy_attr_device,
354 &stp_policy_attr_protocol,
259 NULL, 355 NULL,
260}; 356};
261 357
@@ -276,6 +372,7 @@ void stp_policy_unbind(struct stp_policy *policy)
276 stm->policy = NULL; 372 stm->policy = NULL;
277 policy->stm = NULL; 373 policy->stm = NULL;
278 374
375 stm_put_protocol(stm->pdrv);
279 stm_put_device(stm); 376 stm_put_device(stm);
280} 377}
281 378
@@ -313,9 +410,12 @@ static const struct config_item_type stp_policy_type = {
313static struct config_group * 410static struct config_group *
314stp_policy_make(struct config_group *group, const char *name) 411stp_policy_make(struct config_group *group, const char *name)
315{ 412{
413 const struct config_item_type *pdrv_node_type;
414 const struct stm_protocol_driver *pdrv;
415 char *devname, *proto, *p;
316 struct config_group *ret; 416 struct config_group *ret;
317 struct stm_device *stm; 417 struct stm_device *stm;
318 char *devname, *p; 418 int err;
319 419
320 devname = kasprintf(GFP_KERNEL, "%s", name); 420 devname = kasprintf(GFP_KERNEL, "%s", name);
321 if (!devname) 421 if (!devname)
@@ -326,6 +426,7 @@ stp_policy_make(struct config_group *group, const char *name)
326 * <device_name> is the name of an existing stm device; may 426 * <device_name> is the name of an existing stm device; may
327 * contain dots; 427 * contain dots;
328 * <policy_name> is an arbitrary string; may not contain dots 428 * <policy_name> is an arbitrary string; may not contain dots
429 * <device_name>:<protocol_name>.<policy_name>
329 */ 430 */
330 p = strrchr(devname, '.'); 431 p = strrchr(devname, '.');
331 if (!p) { 432 if (!p) {
@@ -335,11 +436,29 @@ stp_policy_make(struct config_group *group, const char *name)
335 436
336 *p = '\0'; 437 *p = '\0';
337 438
439 /*
440 * look for ":<protocol_name>":
441 * + no protocol suffix: fall back to whatever is available;
442 * + unknown protocol: fail the whole thing
443 */
444 proto = strrchr(devname, ':');
445 if (proto)
446 *proto++ = '\0';
447
338 stm = stm_find_device(devname); 448 stm = stm_find_device(devname);
449 if (!stm) {
450 kfree(devname);
451 return ERR_PTR(-ENODEV);
452 }
453
454 err = stm_lookup_protocol(proto, &pdrv, &pdrv_node_type);
339 kfree(devname); 455 kfree(devname);
340 456
341 if (!stm) 457 /* We don't have any protocol drivers yet */
458 if (err != -ENOENT) {
459 stm_put_device(stm);
342 return ERR_PTR(-ENODEV); 460 return ERR_PTR(-ENODEV);
461 }
343 462
344 mutex_lock(&stm->policy_mutex); 463 mutex_lock(&stm->policy_mutex);
345 if (stm->policy) { 464 if (stm->policy) {
@@ -349,21 +468,27 @@ stp_policy_make(struct config_group *group, const char *name)
349 468
350 stm->policy = kzalloc(sizeof(*stm->policy), GFP_KERNEL); 469 stm->policy = kzalloc(sizeof(*stm->policy), GFP_KERNEL);
351 if (!stm->policy) { 470 if (!stm->policy) {
352 ret = ERR_PTR(-ENOMEM); 471 mutex_unlock(&stm->policy_mutex);
353 goto unlock_policy; 472 stm_put_protocol(pdrv);
473 stm_put_device(stm);
474 return ERR_PTR(-ENOMEM);
354 } 475 }
355 476
356 config_group_init_type_name(&stm->policy->group, name, 477 config_group_init_type_name(&stm->policy->group, name,
357 &stp_policy_type); 478 &stp_policy_type);
358 stm->policy->stm = stm;
359 479
480 stm->pdrv = pdrv;
481 stm->pdrv_node_type = pdrv_node_type;
482 stm->policy->stm = stm;
360 ret = &stm->policy->group; 483 ret = &stm->policy->group;
361 484
362unlock_policy: 485unlock_policy:
363 mutex_unlock(&stm->policy_mutex); 486 mutex_unlock(&stm->policy_mutex);
364 487
365 if (IS_ERR(ret)) 488 if (IS_ERR(ret)) {
489 stm_put_protocol(stm->pdrv);
366 stm_put_device(stm); 490 stm_put_device(stm);
491 }
367 492
368 return ret; 493 return ret;
369} 494}
diff --git a/drivers/hwtracing/stm/stm.h b/drivers/hwtracing/stm/stm.h
index e5df08ae59cf..ed7f3d07fa47 100644
--- a/drivers/hwtracing/stm/stm.h
+++ b/drivers/hwtracing/stm/stm.h
@@ -10,20 +10,17 @@
10#ifndef _STM_STM_H_ 10#ifndef _STM_STM_H_
11#define _STM_STM_H_ 11#define _STM_STM_H_
12 12
13#include <linux/configfs.h>
14
13struct stp_policy; 15struct stp_policy;
14struct stp_policy_node; 16struct stp_policy_node;
17struct stm_protocol_driver;
15 18
16struct stp_policy_node *
17stp_policy_node_lookup(struct stm_device *stm, char *s);
18void stp_policy_node_put(struct stp_policy_node *policy_node);
19void stp_policy_unbind(struct stp_policy *policy);
20
21void stp_policy_node_get_ranges(struct stp_policy_node *policy_node,
22 unsigned int *mstart, unsigned int *mend,
23 unsigned int *cstart, unsigned int *cend);
24int stp_configfs_init(void); 19int stp_configfs_init(void);
25void stp_configfs_exit(void); 20void stp_configfs_exit(void);
26 21
22void *stp_policy_node_priv(struct stp_policy_node *pn);
23
27struct stp_master { 24struct stp_master {
28 unsigned int nr_free; 25 unsigned int nr_free;
29 unsigned long chan_map[0]; 26 unsigned long chan_map[0];
@@ -40,6 +37,9 @@ struct stm_device {
40 struct mutex link_mutex; 37 struct mutex link_mutex;
41 spinlock_t link_lock; 38 spinlock_t link_lock;
42 struct list_head link_list; 39 struct list_head link_list;
40 /* framing protocol in use */
41 const struct stm_protocol_driver *pdrv;
42 const struct config_item_type *pdrv_node_type;
43 /* master allocation */ 43 /* master allocation */
44 spinlock_t mc_lock; 44 spinlock_t mc_lock;
45 struct stp_master *masters[0]; 45 struct stp_master *masters[0];
@@ -48,11 +48,24 @@ struct stm_device {
48#define to_stm_device(_d) \ 48#define to_stm_device(_d) \
49 container_of((_d), struct stm_device, dev) 49 container_of((_d), struct stm_device, dev)
50 50
51struct stp_policy_node *
52stp_policy_node_lookup(struct stm_device *stm, char *s);
53void stp_policy_node_put(struct stp_policy_node *policy_node);
54void stp_policy_unbind(struct stp_policy *policy);
55
56void stp_policy_node_get_ranges(struct stp_policy_node *policy_node,
57 unsigned int *mstart, unsigned int *mend,
58 unsigned int *cstart, unsigned int *cend);
59
60const struct config_item_type *
61get_policy_node_type(struct configfs_attribute **attrs);
62
51struct stm_output { 63struct stm_output {
52 spinlock_t lock; 64 spinlock_t lock;
53 unsigned int master; 65 unsigned int master;
54 unsigned int channel; 66 unsigned int channel;
55 unsigned int nr_chans; 67 unsigned int nr_chans;
68 void *pdrv_private;
56}; 69};
57 70
58struct stm_file { 71struct stm_file {
@@ -76,4 +89,26 @@ struct stm_source_device {
76#define to_stm_source_device(_d) \ 89#define to_stm_source_device(_d) \
77 container_of((_d), struct stm_source_device, dev) 90 container_of((_d), struct stm_source_device, dev)
78 91
92void *to_pdrv_policy_node(struct config_item *item);
93
94struct stm_protocol_driver {
95 struct module *owner;
96 const char *name;
97 ssize_t (*write)(struct stm_data *data,
98 struct stm_output *output, unsigned int chan,
99 const char *buf, size_t count);
100 void (*policy_node_init)(void *arg);
101 int (*output_open)(void *priv, struct stm_output *output);
102 void (*output_close)(struct stm_output *output);
103 ssize_t priv_sz;
104 struct configfs_attribute **policy_attr;
105};
106
107int stm_register_protocol(const struct stm_protocol_driver *pdrv);
108void stm_unregister_protocol(const struct stm_protocol_driver *pdrv);
109int stm_lookup_protocol(const char *name,
110 const struct stm_protocol_driver **pdrv,
111 const struct config_item_type **type);
112void stm_put_protocol(const struct stm_protocol_driver *pdrv);
113
79#endif /* _STM_STM_H_ */ 114#endif /* _STM_STM_H_ */