Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * System Trace Module (STM) master/channel allocation policy management
0004  * Copyright (c) 2014, Intel Corporation.
0005  *
0006  * A master/channel allocation policy allows mapping string identifiers to
0007  * master and channel ranges, where allocation can be done.
0008  */
0009 
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011 
0012 #include <linux/types.h>
0013 #include <linux/module.h>
0014 #include <linux/device.h>
0015 #include <linux/configfs.h>
0016 #include <linux/slab.h>
0017 #include <linux/stm.h>
0018 #include "stm.h"
0019 
0020 /*
0021  * STP Master/Channel allocation policy configfs layout.
0022  */
0023 
0024 struct stp_policy {
0025     struct config_group group;
0026     struct stm_device   *stm;
0027 };
0028 
0029 struct stp_policy_node {
0030     struct config_group group;
0031     struct stp_policy   *policy;
0032     unsigned int        first_master;
0033     unsigned int        last_master;
0034     unsigned int        first_channel;
0035     unsigned int        last_channel;
0036     /* this is the one that's exposed to the attributes */
0037     unsigned char       priv[];
0038 };
0039 
0040 void *stp_policy_node_priv(struct stp_policy_node *pn)
0041 {
0042     if (!pn)
0043         return NULL;
0044 
0045     return pn->priv;
0046 }
0047 
0048 static struct configfs_subsystem stp_policy_subsys;
0049 
0050 void stp_policy_node_get_ranges(struct stp_policy_node *policy_node,
0051                 unsigned int *mstart, unsigned int *mend,
0052                 unsigned int *cstart, unsigned int *cend)
0053 {
0054     *mstart = policy_node->first_master;
0055     *mend   = policy_node->last_master;
0056     *cstart = policy_node->first_channel;
0057     *cend   = policy_node->last_channel;
0058 }
0059 
0060 static inline struct stp_policy *to_stp_policy(struct config_item *item)
0061 {
0062     return item ?
0063         container_of(to_config_group(item), struct stp_policy, group) :
0064         NULL;
0065 }
0066 
0067 static inline struct stp_policy_node *
0068 to_stp_policy_node(struct config_item *item)
0069 {
0070     return item ?
0071         container_of(to_config_group(item), struct stp_policy_node,
0072                  group) :
0073         NULL;
0074 }
0075 
0076 void *to_pdrv_policy_node(struct config_item *item)
0077 {
0078     struct stp_policy_node *node = to_stp_policy_node(item);
0079 
0080     return stp_policy_node_priv(node);
0081 }
0082 EXPORT_SYMBOL_GPL(to_pdrv_policy_node);
0083 
0084 static ssize_t
0085 stp_policy_node_masters_show(struct config_item *item, char *page)
0086 {
0087     struct stp_policy_node *policy_node = to_stp_policy_node(item);
0088     ssize_t count;
0089 
0090     count = sprintf(page, "%u %u\n", policy_node->first_master,
0091             policy_node->last_master);
0092 
0093     return count;
0094 }
0095 
0096 static ssize_t
0097 stp_policy_node_masters_store(struct config_item *item, const char *page,
0098                   size_t count)
0099 {
0100     struct stp_policy_node *policy_node = to_stp_policy_node(item);
0101     unsigned int first, last;
0102     struct stm_device *stm;
0103     char *p = (char *)page;
0104     ssize_t ret = -ENODEV;
0105 
0106     if (sscanf(p, "%u %u", &first, &last) != 2)
0107         return -EINVAL;
0108 
0109     mutex_lock(&stp_policy_subsys.su_mutex);
0110     stm = policy_node->policy->stm;
0111     if (!stm)
0112         goto unlock;
0113 
0114     /* must be within [sw_start..sw_end], which is an inclusive range */
0115     if (first > last || first < stm->data->sw_start ||
0116         last > stm->data->sw_end) {
0117         ret = -ERANGE;
0118         goto unlock;
0119     }
0120 
0121     ret = count;
0122     policy_node->first_master = first;
0123     policy_node->last_master = last;
0124 
0125 unlock:
0126     mutex_unlock(&stp_policy_subsys.su_mutex);
0127 
0128     return ret;
0129 }
0130 
0131 static ssize_t
0132 stp_policy_node_channels_show(struct config_item *item, char *page)
0133 {
0134     struct stp_policy_node *policy_node = to_stp_policy_node(item);
0135     ssize_t count;
0136 
0137     count = sprintf(page, "%u %u\n", policy_node->first_channel,
0138             policy_node->last_channel);
0139 
0140     return count;
0141 }
0142 
0143 static ssize_t
0144 stp_policy_node_channels_store(struct config_item *item, const char *page,
0145                    size_t count)
0146 {
0147     struct stp_policy_node *policy_node = to_stp_policy_node(item);
0148     unsigned int first, last;
0149     struct stm_device *stm;
0150     char *p = (char *)page;
0151     ssize_t ret = -ENODEV;
0152 
0153     if (sscanf(p, "%u %u", &first, &last) != 2)
0154         return -EINVAL;
0155 
0156     mutex_lock(&stp_policy_subsys.su_mutex);
0157     stm = policy_node->policy->stm;
0158     if (!stm)
0159         goto unlock;
0160 
0161     if (first > INT_MAX || last > INT_MAX || first > last ||
0162         last >= stm->data->sw_nchannels) {
0163         ret = -ERANGE;
0164         goto unlock;
0165     }
0166 
0167     ret = count;
0168     policy_node->first_channel = first;
0169     policy_node->last_channel = last;
0170 
0171 unlock:
0172     mutex_unlock(&stp_policy_subsys.su_mutex);
0173 
0174     return ret;
0175 }
0176 
0177 static void stp_policy_node_release(struct config_item *item)
0178 {
0179     struct stp_policy_node *node = to_stp_policy_node(item);
0180 
0181     kfree(node);
0182 }
0183 
0184 static struct configfs_item_operations stp_policy_node_item_ops = {
0185     .release        = stp_policy_node_release,
0186 };
0187 
0188 CONFIGFS_ATTR(stp_policy_node_, masters);
0189 CONFIGFS_ATTR(stp_policy_node_, channels);
0190 
0191 static struct configfs_attribute *stp_policy_node_attrs[] = {
0192     &stp_policy_node_attr_masters,
0193     &stp_policy_node_attr_channels,
0194     NULL,
0195 };
0196 
0197 static const struct config_item_type stp_policy_type;
0198 static const struct config_item_type stp_policy_node_type;
0199 
0200 const struct config_item_type *
0201 get_policy_node_type(struct configfs_attribute **attrs)
0202 {
0203     struct config_item_type *type;
0204     struct configfs_attribute **merged;
0205 
0206     type = kmemdup(&stp_policy_node_type, sizeof(stp_policy_node_type),
0207                GFP_KERNEL);
0208     if (!type)
0209         return NULL;
0210 
0211     merged = memcat_p(stp_policy_node_attrs, attrs);
0212     if (!merged) {
0213         kfree(type);
0214         return NULL;
0215     }
0216 
0217     type->ct_attrs = merged;
0218 
0219     return type;
0220 }
0221 
0222 static struct config_group *
0223 stp_policy_node_make(struct config_group *group, const char *name)
0224 {
0225     const struct config_item_type *type = &stp_policy_node_type;
0226     struct stp_policy_node *policy_node, *parent_node;
0227     const struct stm_protocol_driver *pdrv;
0228     struct stp_policy *policy;
0229 
0230     if (group->cg_item.ci_type == &stp_policy_type) {
0231         policy = container_of(group, struct stp_policy, group);
0232     } else {
0233         parent_node = container_of(group, struct stp_policy_node,
0234                        group);
0235         policy = parent_node->policy;
0236     }
0237 
0238     if (!policy->stm)
0239         return ERR_PTR(-ENODEV);
0240 
0241     pdrv = policy->stm->pdrv;
0242     policy_node =
0243         kzalloc(offsetof(struct stp_policy_node, priv[pdrv->priv_sz]),
0244             GFP_KERNEL);
0245     if (!policy_node)
0246         return ERR_PTR(-ENOMEM);
0247 
0248     if (pdrv->policy_node_init)
0249         pdrv->policy_node_init((void *)policy_node->priv);
0250 
0251     if (policy->stm->pdrv_node_type)
0252         type = policy->stm->pdrv_node_type;
0253 
0254     config_group_init_type_name(&policy_node->group, name, type);
0255 
0256     policy_node->policy = policy;
0257 
0258     /* default values for the attributes */
0259     policy_node->first_master = policy->stm->data->sw_start;
0260     policy_node->last_master = policy->stm->data->sw_end;
0261     policy_node->first_channel = 0;
0262     policy_node->last_channel = policy->stm->data->sw_nchannels - 1;
0263 
0264     return &policy_node->group;
0265 }
0266 
0267 static void
0268 stp_policy_node_drop(struct config_group *group, struct config_item *item)
0269 {
0270     config_item_put(item);
0271 }
0272 
0273 static struct configfs_group_operations stp_policy_node_group_ops = {
0274     .make_group = stp_policy_node_make,
0275     .drop_item  = stp_policy_node_drop,
0276 };
0277 
0278 static const struct config_item_type stp_policy_node_type = {
0279     .ct_item_ops    = &stp_policy_node_item_ops,
0280     .ct_group_ops   = &stp_policy_node_group_ops,
0281     .ct_attrs   = stp_policy_node_attrs,
0282     .ct_owner   = THIS_MODULE,
0283 };
0284 
0285 /*
0286  * Root group: policies.
0287  */
0288 static ssize_t stp_policy_device_show(struct config_item *item,
0289                       char *page)
0290 {
0291     struct stp_policy *policy = to_stp_policy(item);
0292     ssize_t count;
0293 
0294     count = sprintf(page, "%s\n",
0295             (policy && policy->stm) ?
0296             policy->stm->data->name :
0297             "<none>");
0298 
0299     return count;
0300 }
0301 
0302 CONFIGFS_ATTR_RO(stp_policy_, device);
0303 
0304 static ssize_t stp_policy_protocol_show(struct config_item *item,
0305                     char *page)
0306 {
0307     struct stp_policy *policy = to_stp_policy(item);
0308     ssize_t count;
0309 
0310     count = sprintf(page, "%s\n",
0311             (policy && policy->stm) ?
0312             policy->stm->pdrv->name :
0313             "<none>");
0314 
0315     return count;
0316 }
0317 
0318 CONFIGFS_ATTR_RO(stp_policy_, protocol);
0319 
0320 static struct configfs_attribute *stp_policy_attrs[] = {
0321     &stp_policy_attr_device,
0322     &stp_policy_attr_protocol,
0323     NULL,
0324 };
0325 
0326 void stp_policy_unbind(struct stp_policy *policy)
0327 {
0328     struct stm_device *stm = policy->stm;
0329 
0330     /*
0331      * stp_policy_release() will not call here if the policy is already
0332      * unbound; other users should not either, as no link exists between
0333      * this policy and anything else in that case
0334      */
0335     if (WARN_ON_ONCE(!policy->stm))
0336         return;
0337 
0338     lockdep_assert_held(&stm->policy_mutex);
0339 
0340     stm->policy = NULL;
0341     policy->stm = NULL;
0342 
0343     /*
0344      * Drop the reference on the protocol driver and lose the link.
0345      */
0346     stm_put_protocol(stm->pdrv);
0347     stm->pdrv = NULL;
0348     stm_put_device(stm);
0349 }
0350 
0351 static void stp_policy_release(struct config_item *item)
0352 {
0353     struct stp_policy *policy = to_stp_policy(item);
0354     struct stm_device *stm = policy->stm;
0355 
0356     /* a policy *can* be unbound and still exist in configfs tree */
0357     if (!stm)
0358         return;
0359 
0360     mutex_lock(&stm->policy_mutex);
0361     stp_policy_unbind(policy);
0362     mutex_unlock(&stm->policy_mutex);
0363 
0364     kfree(policy);
0365 }
0366 
0367 static struct configfs_item_operations stp_policy_item_ops = {
0368     .release        = stp_policy_release,
0369 };
0370 
0371 static struct configfs_group_operations stp_policy_group_ops = {
0372     .make_group = stp_policy_node_make,
0373 };
0374 
0375 static const struct config_item_type stp_policy_type = {
0376     .ct_item_ops    = &stp_policy_item_ops,
0377     .ct_group_ops   = &stp_policy_group_ops,
0378     .ct_attrs   = stp_policy_attrs,
0379     .ct_owner   = THIS_MODULE,
0380 };
0381 
0382 static struct config_group *
0383 stp_policy_make(struct config_group *group, const char *name)
0384 {
0385     const struct config_item_type *pdrv_node_type;
0386     const struct stm_protocol_driver *pdrv;
0387     char *devname, *proto, *p;
0388     struct config_group *ret;
0389     struct stm_device *stm;
0390     int err;
0391 
0392     devname = kasprintf(GFP_KERNEL, "%s", name);
0393     if (!devname)
0394         return ERR_PTR(-ENOMEM);
0395 
0396     /*
0397      * node must look like <device_name>.<policy_name>, where
0398      * <device_name> is the name of an existing stm device; may
0399      *               contain dots;
0400      * <policy_name> is an arbitrary string; may not contain dots
0401      * <device_name>:<protocol_name>.<policy_name>
0402      */
0403     p = strrchr(devname, '.');
0404     if (!p) {
0405         kfree(devname);
0406         return ERR_PTR(-EINVAL);
0407     }
0408 
0409     *p = '\0';
0410 
0411     /*
0412      * look for ":<protocol_name>":
0413      *  + no protocol suffix: fall back to whatever is available;
0414      *  + unknown protocol: fail the whole thing
0415      */
0416     proto = strrchr(devname, ':');
0417     if (proto)
0418         *proto++ = '\0';
0419 
0420     stm = stm_find_device(devname);
0421     if (!stm) {
0422         kfree(devname);
0423         return ERR_PTR(-ENODEV);
0424     }
0425 
0426     err = stm_lookup_protocol(proto, &pdrv, &pdrv_node_type);
0427     kfree(devname);
0428 
0429     if (err) {
0430         stm_put_device(stm);
0431         return ERR_PTR(-ENODEV);
0432     }
0433 
0434     mutex_lock(&stm->policy_mutex);
0435     if (stm->policy) {
0436         ret = ERR_PTR(-EBUSY);
0437         goto unlock_policy;
0438     }
0439 
0440     stm->policy = kzalloc(sizeof(*stm->policy), GFP_KERNEL);
0441     if (!stm->policy) {
0442         ret = ERR_PTR(-ENOMEM);
0443         goto unlock_policy;
0444     }
0445 
0446     config_group_init_type_name(&stm->policy->group, name,
0447                     &stp_policy_type);
0448 
0449     stm->pdrv = pdrv;
0450     stm->pdrv_node_type = pdrv_node_type;
0451     stm->policy->stm = stm;
0452     ret = &stm->policy->group;
0453 
0454 unlock_policy:
0455     mutex_unlock(&stm->policy_mutex);
0456 
0457     if (IS_ERR(ret)) {
0458         /*
0459          * pdrv and stm->pdrv at this point can be quite different,
0460          * and only one of them needs to be 'put'
0461          */
0462         stm_put_protocol(pdrv);
0463         stm_put_device(stm);
0464     }
0465 
0466     return ret;
0467 }
0468 
0469 static struct configfs_group_operations stp_policy_root_group_ops = {
0470     .make_group = stp_policy_make,
0471 };
0472 
0473 static const struct config_item_type stp_policy_root_type = {
0474     .ct_group_ops   = &stp_policy_root_group_ops,
0475     .ct_owner   = THIS_MODULE,
0476 };
0477 
0478 static struct configfs_subsystem stp_policy_subsys = {
0479     .su_group = {
0480         .cg_item = {
0481             .ci_namebuf = "stp-policy",
0482             .ci_type    = &stp_policy_root_type,
0483         },
0484     },
0485 };
0486 
0487 /*
0488  * Lock the policy mutex from the outside
0489  */
0490 static struct stp_policy_node *
0491 __stp_policy_node_lookup(struct stp_policy *policy, char *s)
0492 {
0493     struct stp_policy_node *policy_node, *ret = NULL;
0494     struct list_head *head = &policy->group.cg_children;
0495     struct config_item *item;
0496     char *start, *end = s;
0497 
0498     if (list_empty(head))
0499         return NULL;
0500 
0501 next:
0502     for (;;) {
0503         start = strsep(&end, "/");
0504         if (!start)
0505             break;
0506 
0507         if (!*start)
0508             continue;
0509 
0510         list_for_each_entry(item, head, ci_entry) {
0511             policy_node = to_stp_policy_node(item);
0512 
0513             if (!strcmp(start,
0514                     policy_node->group.cg_item.ci_name)) {
0515                 ret = policy_node;
0516 
0517                 if (!end)
0518                     goto out;
0519 
0520                 head = &policy_node->group.cg_children;
0521                 goto next;
0522             }
0523         }
0524         break;
0525     }
0526 
0527 out:
0528     return ret;
0529 }
0530 
0531 
0532 struct stp_policy_node *
0533 stp_policy_node_lookup(struct stm_device *stm, char *s)
0534 {
0535     struct stp_policy_node *policy_node = NULL;
0536 
0537     mutex_lock(&stp_policy_subsys.su_mutex);
0538 
0539     mutex_lock(&stm->policy_mutex);
0540     if (stm->policy)
0541         policy_node = __stp_policy_node_lookup(stm->policy, s);
0542     mutex_unlock(&stm->policy_mutex);
0543 
0544     if (policy_node)
0545         config_item_get(&policy_node->group.cg_item);
0546     else
0547         mutex_unlock(&stp_policy_subsys.su_mutex);
0548 
0549     return policy_node;
0550 }
0551 
0552 void stp_policy_node_put(struct stp_policy_node *policy_node)
0553 {
0554     lockdep_assert_held(&stp_policy_subsys.su_mutex);
0555 
0556     mutex_unlock(&stp_policy_subsys.su_mutex);
0557     config_item_put(&policy_node->group.cg_item);
0558 }
0559 
0560 int __init stp_configfs_init(void)
0561 {
0562     config_group_init(&stp_policy_subsys.su_group);
0563     mutex_init(&stp_policy_subsys.su_mutex);
0564     return configfs_register_subsystem(&stp_policy_subsys);
0565 }
0566 
0567 void __exit stp_configfs_exit(void)
0568 {
0569     configfs_unregister_subsystem(&stp_policy_subsys);
0570 }