root/drivers/hwtracing/stm/policy.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. stp_policy_node_priv
  2. stp_policy_node_get_ranges
  3. stp_policy_node_name
  4. to_stp_policy
  5. to_stp_policy_node
  6. to_pdrv_policy_node
  7. stp_policy_node_masters_show
  8. stp_policy_node_masters_store
  9. stp_policy_node_channels_show
  10. stp_policy_node_channels_store
  11. stp_policy_node_release
  12. get_policy_node_type
  13. stp_policy_node_make
  14. stp_policy_node_drop
  15. stp_policy_device_show
  16. stp_policy_protocol_show
  17. stp_policy_unbind
  18. stp_policy_release
  19. stp_policy_make
  20. __stp_policy_node_lookup
  21. stp_policy_node_lookup
  22. stp_policy_node_put
  23. stp_configfs_init
  24. stp_configfs_exit

   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         /* this is the one that's exposed to the attributes */
  37         unsigned char           priv[0];
  38 };
  39 
  40 void *stp_policy_node_priv(struct stp_policy_node *pn)
  41 {
  42         if (!pn)
  43                 return NULL;
  44 
  45         return pn->priv;
  46 }
  47 
  48 static struct configfs_subsystem stp_policy_subsys;
  49 
  50 void stp_policy_node_get_ranges(struct stp_policy_node *policy_node,
  51                                 unsigned int *mstart, unsigned int *mend,
  52                                 unsigned int *cstart, unsigned int *cend)
  53 {
  54         *mstart = policy_node->first_master;
  55         *mend   = policy_node->last_master;
  56         *cstart = policy_node->first_channel;
  57         *cend   = policy_node->last_channel;
  58 }
  59 
  60 static inline char *stp_policy_node_name(struct stp_policy_node *policy_node)
  61 {
  62         return policy_node->group.cg_item.ci_name ? : "<none>";
  63 }
  64 
  65 static inline struct stp_policy *to_stp_policy(struct config_item *item)
  66 {
  67         return item ?
  68                 container_of(to_config_group(item), struct stp_policy, group) :
  69                 NULL;
  70 }
  71 
  72 static inline struct stp_policy_node *
  73 to_stp_policy_node(struct config_item *item)
  74 {
  75         return item ?
  76                 container_of(to_config_group(item), struct stp_policy_node,
  77                              group) :
  78                 NULL;
  79 }
  80 
  81 void *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 }
  87 EXPORT_SYMBOL_GPL(to_pdrv_policy_node);
  88 
  89 static ssize_t
  90 stp_policy_node_masters_show(struct config_item *item, char *page)
  91 {
  92         struct stp_policy_node *policy_node = to_stp_policy_node(item);
  93         ssize_t count;
  94 
  95         count = sprintf(page, "%u %u\n", policy_node->first_master,
  96                         policy_node->last_master);
  97 
  98         return count;
  99 }
 100 
 101 static ssize_t
 102 stp_policy_node_masters_store(struct config_item *item, const char *page,
 103                               size_t count)
 104 {
 105         struct stp_policy_node *policy_node = to_stp_policy_node(item);
 106         unsigned int first, last;
 107         struct stm_device *stm;
 108         char *p = (char *)page;
 109         ssize_t ret = -ENODEV;
 110 
 111         if (sscanf(p, "%u %u", &first, &last) != 2)
 112                 return -EINVAL;
 113 
 114         mutex_lock(&stp_policy_subsys.su_mutex);
 115         stm = policy_node->policy->stm;
 116         if (!stm)
 117                 goto unlock;
 118 
 119         /* must be within [sw_start..sw_end], which is an inclusive range */
 120         if (first > last || first < stm->data->sw_start ||
 121             last > stm->data->sw_end) {
 122                 ret = -ERANGE;
 123                 goto unlock;
 124         }
 125 
 126         ret = count;
 127         policy_node->first_master = first;
 128         policy_node->last_master = last;
 129 
 130 unlock:
 131         mutex_unlock(&stp_policy_subsys.su_mutex);
 132 
 133         return ret;
 134 }
 135 
 136 static ssize_t
 137 stp_policy_node_channels_show(struct config_item *item, char *page)
 138 {
 139         struct stp_policy_node *policy_node = to_stp_policy_node(item);
 140         ssize_t count;
 141 
 142         count = sprintf(page, "%u %u\n", policy_node->first_channel,
 143                         policy_node->last_channel);
 144 
 145         return count;
 146 }
 147 
 148 static ssize_t
 149 stp_policy_node_channels_store(struct config_item *item, const char *page,
 150                                size_t count)
 151 {
 152         struct stp_policy_node *policy_node = to_stp_policy_node(item);
 153         unsigned int first, last;
 154         struct stm_device *stm;
 155         char *p = (char *)page;
 156         ssize_t ret = -ENODEV;
 157 
 158         if (sscanf(p, "%u %u", &first, &last) != 2)
 159                 return -EINVAL;
 160 
 161         mutex_lock(&stp_policy_subsys.su_mutex);
 162         stm = policy_node->policy->stm;
 163         if (!stm)
 164                 goto unlock;
 165 
 166         if (first > INT_MAX || last > INT_MAX || first > last ||
 167             last >= stm->data->sw_nchannels) {
 168                 ret = -ERANGE;
 169                 goto unlock;
 170         }
 171 
 172         ret = count;
 173         policy_node->first_channel = first;
 174         policy_node->last_channel = last;
 175 
 176 unlock:
 177         mutex_unlock(&stp_policy_subsys.su_mutex);
 178 
 179         return ret;
 180 }
 181 
 182 static void stp_policy_node_release(struct config_item *item)
 183 {
 184         struct stp_policy_node *node = to_stp_policy_node(item);
 185 
 186         kfree(node);
 187 }
 188 
 189 static struct configfs_item_operations stp_policy_node_item_ops = {
 190         .release                = stp_policy_node_release,
 191 };
 192 
 193 CONFIGFS_ATTR(stp_policy_node_, masters);
 194 CONFIGFS_ATTR(stp_policy_node_, channels);
 195 
 196 static struct configfs_attribute *stp_policy_node_attrs[] = {
 197         &stp_policy_node_attr_masters,
 198         &stp_policy_node_attr_channels,
 199         NULL,
 200 };
 201 
 202 static const struct config_item_type stp_policy_type;
 203 static const struct config_item_type stp_policy_node_type;
 204 
 205 const struct config_item_type *
 206 get_policy_node_type(struct configfs_attribute **attrs)
 207 {
 208         struct config_item_type *type;
 209         struct configfs_attribute **merged;
 210 
 211         type = kmemdup(&stp_policy_node_type, sizeof(stp_policy_node_type),
 212                        GFP_KERNEL);
 213         if (!type)
 214                 return NULL;
 215 
 216         merged = memcat_p(stp_policy_node_attrs, attrs);
 217         if (!merged) {
 218                 kfree(type);
 219                 return NULL;
 220         }
 221 
 222         type->ct_attrs = merged;
 223 
 224         return type;
 225 }
 226 
 227 static struct config_group *
 228 stp_policy_node_make(struct config_group *group, const char *name)
 229 {
 230         const struct config_item_type *type = &stp_policy_node_type;
 231         struct stp_policy_node *policy_node, *parent_node;
 232         const struct stm_protocol_driver *pdrv;
 233         struct stp_policy *policy;
 234 
 235         if (group->cg_item.ci_type == &stp_policy_type) {
 236                 policy = container_of(group, struct stp_policy, group);
 237         } else {
 238                 parent_node = container_of(group, struct stp_policy_node,
 239                                            group);
 240                 policy = parent_node->policy;
 241         }
 242 
 243         if (!policy->stm)
 244                 return ERR_PTR(-ENODEV);
 245 
 246         pdrv = policy->stm->pdrv;
 247         policy_node =
 248                 kzalloc(offsetof(struct stp_policy_node, priv[pdrv->priv_sz]),
 249                         GFP_KERNEL);
 250         if (!policy_node)
 251                 return ERR_PTR(-ENOMEM);
 252 
 253         if (pdrv->policy_node_init)
 254                 pdrv->policy_node_init((void *)policy_node->priv);
 255 
 256         if (policy->stm->pdrv_node_type)
 257                 type = policy->stm->pdrv_node_type;
 258 
 259         config_group_init_type_name(&policy_node->group, name, type);
 260 
 261         policy_node->policy = policy;
 262 
 263         /* default values for the attributes */
 264         policy_node->first_master = policy->stm->data->sw_start;
 265         policy_node->last_master = policy->stm->data->sw_end;
 266         policy_node->first_channel = 0;
 267         policy_node->last_channel = policy->stm->data->sw_nchannels - 1;
 268 
 269         return &policy_node->group;
 270 }
 271 
 272 static void
 273 stp_policy_node_drop(struct config_group *group, struct config_item *item)
 274 {
 275         config_item_put(item);
 276 }
 277 
 278 static struct configfs_group_operations stp_policy_node_group_ops = {
 279         .make_group     = stp_policy_node_make,
 280         .drop_item      = stp_policy_node_drop,
 281 };
 282 
 283 static const struct config_item_type stp_policy_node_type = {
 284         .ct_item_ops    = &stp_policy_node_item_ops,
 285         .ct_group_ops   = &stp_policy_node_group_ops,
 286         .ct_attrs       = stp_policy_node_attrs,
 287         .ct_owner       = THIS_MODULE,
 288 };
 289 
 290 /*
 291  * Root group: policies.
 292  */
 293 static ssize_t stp_policy_device_show(struct config_item *item,
 294                                       char *page)
 295 {
 296         struct stp_policy *policy = to_stp_policy(item);
 297         ssize_t count;
 298 
 299         count = sprintf(page, "%s\n",
 300                         (policy && policy->stm) ?
 301                         policy->stm->data->name :
 302                         "<none>");
 303 
 304         return count;
 305 }
 306 
 307 CONFIGFS_ATTR_RO(stp_policy_, device);
 308 
 309 static ssize_t stp_policy_protocol_show(struct config_item *item,
 310                                         char *page)
 311 {
 312         struct stp_policy *policy = to_stp_policy(item);
 313         ssize_t count;
 314 
 315         count = sprintf(page, "%s\n",
 316                         (policy && policy->stm) ?
 317                         policy->stm->pdrv->name :
 318                         "<none>");
 319 
 320         return count;
 321 }
 322 
 323 CONFIGFS_ATTR_RO(stp_policy_, protocol);
 324 
 325 static struct configfs_attribute *stp_policy_attrs[] = {
 326         &stp_policy_attr_device,
 327         &stp_policy_attr_protocol,
 328         NULL,
 329 };
 330 
 331 void stp_policy_unbind(struct stp_policy *policy)
 332 {
 333         struct stm_device *stm = policy->stm;
 334 
 335         /*
 336          * stp_policy_release() will not call here if the policy is already
 337          * unbound; other users should not either, as no link exists between
 338          * this policy and anything else in that case
 339          */
 340         if (WARN_ON_ONCE(!policy->stm))
 341                 return;
 342 
 343         lockdep_assert_held(&stm->policy_mutex);
 344 
 345         stm->policy = NULL;
 346         policy->stm = NULL;
 347 
 348         /*
 349          * Drop the reference on the protocol driver and lose the link.
 350          */
 351         stm_put_protocol(stm->pdrv);
 352         stm->pdrv = NULL;
 353         stm_put_device(stm);
 354 }
 355 
 356 static void stp_policy_release(struct config_item *item)
 357 {
 358         struct stp_policy *policy = to_stp_policy(item);
 359         struct stm_device *stm = policy->stm;
 360 
 361         /* a policy *can* be unbound and still exist in configfs tree */
 362         if (!stm)
 363                 return;
 364 
 365         mutex_lock(&stm->policy_mutex);
 366         stp_policy_unbind(policy);
 367         mutex_unlock(&stm->policy_mutex);
 368 
 369         kfree(policy);
 370 }
 371 
 372 static struct configfs_item_operations stp_policy_item_ops = {
 373         .release                = stp_policy_release,
 374 };
 375 
 376 static struct configfs_group_operations stp_policy_group_ops = {
 377         .make_group     = stp_policy_node_make,
 378 };
 379 
 380 static const struct config_item_type stp_policy_type = {
 381         .ct_item_ops    = &stp_policy_item_ops,
 382         .ct_group_ops   = &stp_policy_group_ops,
 383         .ct_attrs       = stp_policy_attrs,
 384         .ct_owner       = THIS_MODULE,
 385 };
 386 
 387 static struct config_group *
 388 stp_policy_make(struct config_group *group, const char *name)
 389 {
 390         const struct config_item_type *pdrv_node_type;
 391         const struct stm_protocol_driver *pdrv;
 392         char *devname, *proto, *p;
 393         struct config_group *ret;
 394         struct stm_device *stm;
 395         int err;
 396 
 397         devname = kasprintf(GFP_KERNEL, "%s", name);
 398         if (!devname)
 399                 return ERR_PTR(-ENOMEM);
 400 
 401         /*
 402          * node must look like <device_name>.<policy_name>, where
 403          * <device_name> is the name of an existing stm device; may
 404          *               contain dots;
 405          * <policy_name> is an arbitrary string; may not contain dots
 406          * <device_name>:<protocol_name>.<policy_name>
 407          */
 408         p = strrchr(devname, '.');
 409         if (!p) {
 410                 kfree(devname);
 411                 return ERR_PTR(-EINVAL);
 412         }
 413 
 414         *p = '\0';
 415 
 416         /*
 417          * look for ":<protocol_name>":
 418          *  + no protocol suffix: fall back to whatever is available;
 419          *  + unknown protocol: fail the whole thing
 420          */
 421         proto = strrchr(devname, ':');
 422         if (proto)
 423                 *proto++ = '\0';
 424 
 425         stm = stm_find_device(devname);
 426         if (!stm) {
 427                 kfree(devname);
 428                 return ERR_PTR(-ENODEV);
 429         }
 430 
 431         err = stm_lookup_protocol(proto, &pdrv, &pdrv_node_type);
 432         kfree(devname);
 433 
 434         if (err) {
 435                 stm_put_device(stm);
 436                 return ERR_PTR(-ENODEV);
 437         }
 438 
 439         mutex_lock(&stm->policy_mutex);
 440         if (stm->policy) {
 441                 ret = ERR_PTR(-EBUSY);
 442                 goto unlock_policy;
 443         }
 444 
 445         stm->policy = kzalloc(sizeof(*stm->policy), GFP_KERNEL);
 446         if (!stm->policy) {
 447                 ret = ERR_PTR(-ENOMEM);
 448                 goto unlock_policy;
 449         }
 450 
 451         config_group_init_type_name(&stm->policy->group, name,
 452                                     &stp_policy_type);
 453 
 454         stm->pdrv = pdrv;
 455         stm->pdrv_node_type = pdrv_node_type;
 456         stm->policy->stm = stm;
 457         ret = &stm->policy->group;
 458 
 459 unlock_policy:
 460         mutex_unlock(&stm->policy_mutex);
 461 
 462         if (IS_ERR(ret)) {
 463                 /*
 464                  * pdrv and stm->pdrv at this point can be quite different,
 465                  * and only one of them needs to be 'put'
 466                  */
 467                 stm_put_protocol(pdrv);
 468                 stm_put_device(stm);
 469         }
 470 
 471         return ret;
 472 }
 473 
 474 static struct configfs_group_operations stp_policy_root_group_ops = {
 475         .make_group     = stp_policy_make,
 476 };
 477 
 478 static const struct config_item_type stp_policy_root_type = {
 479         .ct_group_ops   = &stp_policy_root_group_ops,
 480         .ct_owner       = THIS_MODULE,
 481 };
 482 
 483 static struct configfs_subsystem stp_policy_subsys = {
 484         .su_group = {
 485                 .cg_item = {
 486                         .ci_namebuf     = "stp-policy",
 487                         .ci_type        = &stp_policy_root_type,
 488                 },
 489         },
 490 };
 491 
 492 /*
 493  * Lock the policy mutex from the outside
 494  */
 495 static struct stp_policy_node *
 496 __stp_policy_node_lookup(struct stp_policy *policy, char *s)
 497 {
 498         struct stp_policy_node *policy_node, *ret = NULL;
 499         struct list_head *head = &policy->group.cg_children;
 500         struct config_item *item;
 501         char *start, *end = s;
 502 
 503         if (list_empty(head))
 504                 return NULL;
 505 
 506 next:
 507         for (;;) {
 508                 start = strsep(&end, "/");
 509                 if (!start)
 510                         break;
 511 
 512                 if (!*start)
 513                         continue;
 514 
 515                 list_for_each_entry(item, head, ci_entry) {
 516                         policy_node = to_stp_policy_node(item);
 517 
 518                         if (!strcmp(start,
 519                                     policy_node->group.cg_item.ci_name)) {
 520                                 ret = policy_node;
 521 
 522                                 if (!end)
 523                                         goto out;
 524 
 525                                 head = &policy_node->group.cg_children;
 526                                 goto next;
 527                         }
 528                 }
 529                 break;
 530         }
 531 
 532 out:
 533         return ret;
 534 }
 535 
 536 
 537 struct stp_policy_node *
 538 stp_policy_node_lookup(struct stm_device *stm, char *s)
 539 {
 540         struct stp_policy_node *policy_node = NULL;
 541 
 542         mutex_lock(&stp_policy_subsys.su_mutex);
 543 
 544         mutex_lock(&stm->policy_mutex);
 545         if (stm->policy)
 546                 policy_node = __stp_policy_node_lookup(stm->policy, s);
 547         mutex_unlock(&stm->policy_mutex);
 548 
 549         if (policy_node)
 550                 config_item_get(&policy_node->group.cg_item);
 551         else
 552                 mutex_unlock(&stp_policy_subsys.su_mutex);
 553 
 554         return policy_node;
 555 }
 556 
 557 void stp_policy_node_put(struct stp_policy_node *policy_node)
 558 {
 559         lockdep_assert_held(&stp_policy_subsys.su_mutex);
 560 
 561         mutex_unlock(&stp_policy_subsys.su_mutex);
 562         config_item_put(&policy_node->group.cg_item);
 563 }
 564 
 565 int __init stp_configfs_init(void)
 566 {
 567         config_group_init(&stp_policy_subsys.su_group);
 568         mutex_init(&stp_policy_subsys.su_mutex);
 569         return configfs_register_subsystem(&stp_policy_subsys);
 570 }
 571 
 572 void __exit stp_configfs_exit(void)
 573 {
 574         configfs_unregister_subsystem(&stp_policy_subsys);
 575 }

/* [<][>][^][v][top][bottom][index][help] */