Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2021-2022 NVIDIA Corporation
0004  *
0005  * Author: Dipen Patel <dipenp@nvidia.com>
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/err.h>
0011 #include <linux/slab.h>
0012 #include <linux/of.h>
0013 #include <linux/of_device.h>
0014 #include <linux/mutex.h>
0015 #include <linux/uaccess.h>
0016 #include <linux/hte.h>
0017 #include <linux/delay.h>
0018 #include <linux/debugfs.h>
0019 
0020 #define HTE_TS_NAME_LEN     10
0021 
0022 /* Global list of the HTE devices */
0023 static DEFINE_SPINLOCK(hte_lock);
0024 static LIST_HEAD(hte_devices);
0025 
0026 enum {
0027     HTE_TS_REGISTERED,
0028     HTE_TS_REQ,
0029     HTE_TS_DISABLE,
0030     HTE_TS_QUEUE_WK,
0031 };
0032 
0033 /**
0034  * struct hte_ts_info - Information related to requested timestamp.
0035  *
0036  * @xlated_id: Timestamp ID as understood between HTE subsys and HTE provider,
0037  * See xlate callback API.
0038  * @flags: Flags holding state information.
0039  * @hte_cb_flags: Callback related flags.
0040  * @seq: Timestamp sequence counter.
0041  * @line_name: HTE allocated line name.
0042  * @free_attr_name: If set, free the attr name.
0043  * @cb: A nonsleeping callback function provided by clients.
0044  * @tcb: A secondary sleeping callback function provided by clients.
0045  * @dropped_ts: Dropped timestamps.
0046  * @slock: Spin lock to synchronize between disable/enable,
0047  * request/release APIs.
0048  * @cb_work: callback workqueue, used when tcb is specified.
0049  * @req_mlock: Lock during timestamp request/release APIs.
0050  * @ts_dbg_root: Root for the debug fs.
0051  * @gdev: HTE abstract device that this timestamp information belongs to.
0052  * @cl_data: Client specific data.
0053  */
0054 struct hte_ts_info {
0055     u32 xlated_id;
0056     unsigned long flags;
0057     unsigned long hte_cb_flags;
0058     u64 seq;
0059     char *line_name;
0060     bool free_attr_name;
0061     hte_ts_cb_t cb;
0062     hte_ts_sec_cb_t tcb;
0063     atomic_t dropped_ts;
0064     spinlock_t slock;
0065     struct work_struct cb_work;
0066     struct mutex req_mlock;
0067     struct dentry *ts_dbg_root;
0068     struct hte_device *gdev;
0069     void *cl_data;
0070 };
0071 
0072 /**
0073  * struct hte_device - HTE abstract device
0074  * @nlines: Number of entities this device supports.
0075  * @ts_req: Total number of entities requested.
0076  * @sdev: Device used at various debug prints.
0077  * @dbg_root: Root directory for debug fs.
0078  * @list: List node to store hte_device for each provider.
0079  * @chip: HTE chip providing this HTE device.
0080  * @owner: helps prevent removal of modules when in use.
0081  * @ei: Timestamp information.
0082  */
0083 struct hte_device {
0084     u32 nlines;
0085     atomic_t ts_req;
0086     struct device *sdev;
0087     struct dentry *dbg_root;
0088     struct list_head list;
0089     struct hte_chip *chip;
0090     struct module *owner;
0091     struct hte_ts_info ei[];
0092 };
0093 
0094 #ifdef CONFIG_DEBUG_FS
0095 
0096 static struct dentry *hte_root;
0097 
0098 static int __init hte_subsys_dbgfs_init(void)
0099 {
0100     /* creates /sys/kernel/debug/hte/ */
0101     hte_root = debugfs_create_dir("hte", NULL);
0102 
0103     return 0;
0104 }
0105 subsys_initcall(hte_subsys_dbgfs_init);
0106 
0107 static void hte_chip_dbgfs_init(struct hte_device *gdev)
0108 {
0109     const struct hte_chip *chip = gdev->chip;
0110     const char *name = chip->name ? chip->name : dev_name(chip->dev);
0111 
0112     gdev->dbg_root = debugfs_create_dir(name, hte_root);
0113 
0114     debugfs_create_atomic_t("ts_requested", 0444, gdev->dbg_root,
0115                 &gdev->ts_req);
0116     debugfs_create_u32("total_ts", 0444, gdev->dbg_root,
0117                &gdev->nlines);
0118 }
0119 
0120 static void hte_ts_dbgfs_init(const char *name, struct hte_ts_info *ei)
0121 {
0122     if (!ei->gdev->dbg_root || !name)
0123         return;
0124 
0125     ei->ts_dbg_root = debugfs_create_dir(name, ei->gdev->dbg_root);
0126 
0127     debugfs_create_atomic_t("dropped_timestamps", 0444, ei->ts_dbg_root,
0128                 &ei->dropped_ts);
0129 }
0130 
0131 #else
0132 
0133 static void hte_chip_dbgfs_init(struct hte_device *gdev)
0134 {
0135 }
0136 
0137 static void hte_ts_dbgfs_init(const char *name, struct hte_ts_info *ei)
0138 {
0139 }
0140 
0141 #endif
0142 
0143 /**
0144  * hte_ts_put() - Release and disable timestamp for the given desc.
0145  *
0146  * @desc: timestamp descriptor.
0147  *
0148  * Context: debugfs_remove_recursive() function call may use sleeping locks,
0149  *      not suitable from atomic context.
0150  * Returns: 0 on success or a negative error code on failure.
0151  */
0152 int hte_ts_put(struct hte_ts_desc *desc)
0153 {
0154     int ret = 0;
0155     unsigned long flag;
0156     struct hte_device *gdev;
0157     struct hte_ts_info *ei;
0158 
0159     if (!desc)
0160         return -EINVAL;
0161 
0162     ei = desc->hte_data;
0163 
0164     if (!ei || !ei->gdev)
0165         return -EINVAL;
0166 
0167     gdev = ei->gdev;
0168 
0169     mutex_lock(&ei->req_mlock);
0170 
0171     if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) &&
0172         !test_bit(HTE_TS_REGISTERED, &ei->flags))) {
0173         dev_info(gdev->sdev, "id:%d is not requested\n",
0174              desc->attr.line_id);
0175         ret = -EINVAL;
0176         goto unlock;
0177     }
0178 
0179     if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) &&
0180         test_bit(HTE_TS_REGISTERED, &ei->flags))) {
0181         dev_info(gdev->sdev, "id:%d is registered but not requested\n",
0182              desc->attr.line_id);
0183         ret = -EINVAL;
0184         goto unlock;
0185     }
0186 
0187     if (test_bit(HTE_TS_REQ, &ei->flags) &&
0188         !test_bit(HTE_TS_REGISTERED, &ei->flags)) {
0189         clear_bit(HTE_TS_REQ, &ei->flags);
0190         desc->hte_data = NULL;
0191         ret = 0;
0192         goto mod_put;
0193     }
0194 
0195     ret = gdev->chip->ops->release(gdev->chip, desc, ei->xlated_id);
0196     if (ret) {
0197         dev_err(gdev->sdev, "id: %d free failed\n",
0198             desc->attr.line_id);
0199         goto unlock;
0200     }
0201 
0202     kfree(ei->line_name);
0203     if (ei->free_attr_name)
0204         kfree_const(desc->attr.name);
0205 
0206     debugfs_remove_recursive(ei->ts_dbg_root);
0207 
0208     spin_lock_irqsave(&ei->slock, flag);
0209 
0210     if (test_bit(HTE_TS_QUEUE_WK, &ei->flags)) {
0211         spin_unlock_irqrestore(&ei->slock, flag);
0212         flush_work(&ei->cb_work);
0213         spin_lock_irqsave(&ei->slock, flag);
0214     }
0215 
0216     atomic_dec(&gdev->ts_req);
0217     atomic_set(&ei->dropped_ts, 0);
0218 
0219     ei->seq = 1;
0220     ei->flags = 0;
0221     desc->hte_data = NULL;
0222 
0223     spin_unlock_irqrestore(&ei->slock, flag);
0224 
0225     ei->cb = NULL;
0226     ei->tcb = NULL;
0227     ei->cl_data = NULL;
0228 
0229 mod_put:
0230     module_put(gdev->owner);
0231 unlock:
0232     mutex_unlock(&ei->req_mlock);
0233     dev_dbg(gdev->sdev, "release id: %d\n", desc->attr.line_id);
0234 
0235     return ret;
0236 }
0237 EXPORT_SYMBOL_GPL(hte_ts_put);
0238 
0239 static int hte_ts_dis_en_common(struct hte_ts_desc *desc, bool en)
0240 {
0241     u32 ts_id;
0242     struct hte_device *gdev;
0243     struct hte_ts_info *ei;
0244     int ret;
0245     unsigned long flag;
0246 
0247     if (!desc)
0248         return -EINVAL;
0249 
0250     ei = desc->hte_data;
0251 
0252     if (!ei || !ei->gdev)
0253         return -EINVAL;
0254 
0255     gdev = ei->gdev;
0256     ts_id = desc->attr.line_id;
0257 
0258     mutex_lock(&ei->req_mlock);
0259 
0260     if (!test_bit(HTE_TS_REGISTERED, &ei->flags)) {
0261         dev_dbg(gdev->sdev, "id:%d is not registered", ts_id);
0262         ret = -EUSERS;
0263         goto out;
0264     }
0265 
0266     spin_lock_irqsave(&ei->slock, flag);
0267 
0268     if (en) {
0269         if (!test_bit(HTE_TS_DISABLE, &ei->flags)) {
0270             ret = 0;
0271             goto out_unlock;
0272         }
0273 
0274         spin_unlock_irqrestore(&ei->slock, flag);
0275         ret = gdev->chip->ops->enable(gdev->chip, ei->xlated_id);
0276         if (ret) {
0277             dev_warn(gdev->sdev, "id: %d enable failed\n",
0278                  ts_id);
0279             goto out;
0280         }
0281 
0282         spin_lock_irqsave(&ei->slock, flag);
0283         clear_bit(HTE_TS_DISABLE, &ei->flags);
0284     } else {
0285         if (test_bit(HTE_TS_DISABLE, &ei->flags)) {
0286             ret = 0;
0287             goto out_unlock;
0288         }
0289 
0290         spin_unlock_irqrestore(&ei->slock, flag);
0291         ret = gdev->chip->ops->disable(gdev->chip, ei->xlated_id);
0292         if (ret) {
0293             dev_warn(gdev->sdev, "id: %d disable failed\n",
0294                  ts_id);
0295             goto out;
0296         }
0297 
0298         spin_lock_irqsave(&ei->slock, flag);
0299         set_bit(HTE_TS_DISABLE, &ei->flags);
0300     }
0301 
0302 out_unlock:
0303     spin_unlock_irqrestore(&ei->slock, flag);
0304 out:
0305     mutex_unlock(&ei->req_mlock);
0306     return ret;
0307 }
0308 
0309 /**
0310  * hte_disable_ts() - Disable timestamp on given descriptor.
0311  *
0312  * The API does not release any resources associated with desc.
0313  *
0314  * @desc: ts descriptor, this is the same as returned by the request API.
0315  *
0316  * Context: Holds mutex lock, not suitable from atomic context.
0317  * Returns: 0 on success or a negative error code on failure.
0318  */
0319 int hte_disable_ts(struct hte_ts_desc *desc)
0320 {
0321     return hte_ts_dis_en_common(desc, false);
0322 }
0323 EXPORT_SYMBOL_GPL(hte_disable_ts);
0324 
0325 /**
0326  * hte_enable_ts() - Enable timestamp on given descriptor.
0327  *
0328  * @desc: ts descriptor, this is the same as returned by the request API.
0329  *
0330  * Context: Holds mutex lock, not suitable from atomic context.
0331  * Returns: 0 on success or a negative error code on failure.
0332  */
0333 int hte_enable_ts(struct hte_ts_desc *desc)
0334 {
0335     return hte_ts_dis_en_common(desc, true);
0336 }
0337 EXPORT_SYMBOL_GPL(hte_enable_ts);
0338 
0339 static void hte_do_cb_work(struct work_struct *w)
0340 {
0341     unsigned long flag;
0342     struct hte_ts_info *ei = container_of(w, struct hte_ts_info, cb_work);
0343 
0344     if (unlikely(!ei->tcb))
0345         return;
0346 
0347     ei->tcb(ei->cl_data);
0348 
0349     spin_lock_irqsave(&ei->slock, flag);
0350     clear_bit(HTE_TS_QUEUE_WK, &ei->flags);
0351     spin_unlock_irqrestore(&ei->slock, flag);
0352 }
0353 
0354 static int __hte_req_ts(struct hte_ts_desc *desc, hte_ts_cb_t cb,
0355             hte_ts_sec_cb_t tcb, void *data)
0356 {
0357     int ret;
0358     struct hte_device *gdev;
0359     struct hte_ts_info *ei = desc->hte_data;
0360 
0361     gdev = ei->gdev;
0362     /*
0363      * There is a chance that multiple consumers requesting same entity,
0364      * lock here.
0365      */
0366     mutex_lock(&ei->req_mlock);
0367 
0368     if (test_bit(HTE_TS_REGISTERED, &ei->flags) ||
0369         !test_bit(HTE_TS_REQ, &ei->flags)) {
0370         dev_dbg(gdev->chip->dev, "id:%u req failed\n",
0371             desc->attr.line_id);
0372         ret = -EUSERS;
0373         goto unlock;
0374     }
0375 
0376     ei->cb = cb;
0377     ei->tcb = tcb;
0378     if (tcb)
0379         INIT_WORK(&ei->cb_work, hte_do_cb_work);
0380 
0381     ret = gdev->chip->ops->request(gdev->chip, desc, ei->xlated_id);
0382     if (ret < 0) {
0383         dev_err(gdev->chip->dev, "ts request failed\n");
0384         goto unlock;
0385     }
0386 
0387     ei->cl_data = data;
0388     ei->seq = 1;
0389 
0390     atomic_inc(&gdev->ts_req);
0391 
0392     ei->line_name = NULL;
0393     if (!desc->attr.name) {
0394         ei->line_name = kzalloc(HTE_TS_NAME_LEN, GFP_KERNEL);
0395         if (ei->line_name)
0396             scnprintf(ei->line_name, HTE_TS_NAME_LEN, "ts_%u",
0397                   desc->attr.line_id);
0398     }
0399 
0400     hte_ts_dbgfs_init(desc->attr.name == NULL ?
0401               ei->line_name : desc->attr.name, ei);
0402     set_bit(HTE_TS_REGISTERED, &ei->flags);
0403 
0404     dev_dbg(gdev->chip->dev, "id: %u, xlated id:%u",
0405         desc->attr.line_id, ei->xlated_id);
0406 
0407     ret = 0;
0408 
0409 unlock:
0410     mutex_unlock(&ei->req_mlock);
0411 
0412     return ret;
0413 }
0414 
0415 static int hte_bind_ts_info_locked(struct hte_ts_info *ei,
0416                    struct hte_ts_desc *desc, u32 x_id)
0417 {
0418     int ret = 0;
0419 
0420     mutex_lock(&ei->req_mlock);
0421 
0422     if (test_bit(HTE_TS_REQ, &ei->flags)) {
0423         dev_dbg(ei->gdev->chip->dev, "id:%u is already requested\n",
0424             desc->attr.line_id);
0425         ret = -EUSERS;
0426         goto out;
0427     }
0428 
0429     set_bit(HTE_TS_REQ, &ei->flags);
0430     desc->hte_data = ei;
0431     ei->xlated_id = x_id;
0432 
0433 out:
0434     mutex_unlock(&ei->req_mlock);
0435 
0436     return ret;
0437 }
0438 
0439 static struct hte_device *of_node_to_htedevice(struct device_node *np)
0440 {
0441     struct hte_device *gdev;
0442 
0443     spin_lock(&hte_lock);
0444 
0445     list_for_each_entry(gdev, &hte_devices, list)
0446         if (gdev->chip && gdev->chip->dev &&
0447             gdev->chip->dev->of_node == np) {
0448             spin_unlock(&hte_lock);
0449             return gdev;
0450         }
0451 
0452     spin_unlock(&hte_lock);
0453 
0454     return ERR_PTR(-ENODEV);
0455 }
0456 
0457 static struct hte_device *hte_find_dev_from_linedata(struct hte_ts_desc *desc)
0458 {
0459     struct hte_device *gdev;
0460 
0461     spin_lock(&hte_lock);
0462 
0463     list_for_each_entry(gdev, &hte_devices, list)
0464         if (gdev->chip && gdev->chip->match_from_linedata) {
0465             if (!gdev->chip->match_from_linedata(gdev->chip, desc))
0466                 continue;
0467             spin_unlock(&hte_lock);
0468             return gdev;
0469         }
0470 
0471     spin_unlock(&hte_lock);
0472 
0473     return ERR_PTR(-ENODEV);
0474 }
0475 
0476 /**
0477  * of_hte_req_count - Return the number of entities to timestamp.
0478  *
0479  * The function returns the total count of the requested entities to timestamp
0480  * by parsing device tree.
0481  *
0482  * @dev: The HTE consumer.
0483  *
0484  * Returns: Positive number on success, -ENOENT if no entries,
0485  * -EINVAL for other errors.
0486  */
0487 int of_hte_req_count(struct device *dev)
0488 {
0489     int count;
0490 
0491     if (!dev || !dev->of_node)
0492         return -EINVAL;
0493 
0494     count = of_count_phandle_with_args(dev->of_node, "timestamps",
0495                        "#timestamp-cells");
0496 
0497     return count ? count : -ENOENT;
0498 }
0499 EXPORT_SYMBOL_GPL(of_hte_req_count);
0500 
0501 static inline struct hte_device *hte_get_dev(struct hte_ts_desc *desc)
0502 {
0503     return hte_find_dev_from_linedata(desc);
0504 }
0505 
0506 static struct hte_device *hte_of_get_dev(struct device *dev,
0507                      struct hte_ts_desc *desc,
0508                      int index,
0509                      struct of_phandle_args *args,
0510                      bool *free_name)
0511 {
0512     int ret;
0513     struct device_node *np;
0514     char *temp;
0515 
0516     if (!dev->of_node)
0517         return ERR_PTR(-EINVAL);
0518 
0519     np = dev->of_node;
0520 
0521     if (!of_find_property(np, "timestamp-names", NULL)) {
0522         /* Let hte core construct it during request time */
0523         desc->attr.name = NULL;
0524     } else {
0525         ret = of_property_read_string_index(np, "timestamp-names",
0526                             index, &desc->attr.name);
0527         if (ret) {
0528             pr_err("can't parse \"timestamp-names\" property\n");
0529             return ERR_PTR(ret);
0530         }
0531         *free_name = false;
0532         if (desc->attr.name) {
0533             temp = skip_spaces(desc->attr.name);
0534             if (!*temp)
0535                 desc->attr.name = NULL;
0536         }
0537     }
0538 
0539     ret = of_parse_phandle_with_args(np, "timestamps", "#timestamp-cells",
0540                      index, args);
0541     if (ret) {
0542         pr_err("%s(): can't parse \"timestamps\" property\n",
0543                __func__);
0544         return ERR_PTR(ret);
0545     }
0546 
0547     of_node_put(args->np);
0548 
0549     return of_node_to_htedevice(args->np);
0550 }
0551 
0552 /**
0553  * hte_ts_get() - The function to initialize and obtain HTE desc.
0554  *
0555  * The function initializes the consumer provided HTE descriptor. If consumer
0556  * has device tree node, index is used to parse the line id and other details.
0557  * The function needs to be called before using any request APIs.
0558  *
0559  * @dev: HTE consumer/client device, used in case of parsing device tree node.
0560  * @desc: Pre-allocated timestamp descriptor.
0561  * @index: The index will be used as an index to parse line_id from the
0562  * device tree node if node is present.
0563  *
0564  * Context: Holds mutex lock.
0565  * Returns: Returns 0 on success or negative error code on failure.
0566  */
0567 int hte_ts_get(struct device *dev, struct hte_ts_desc *desc, int index)
0568 {
0569     struct hte_device *gdev;
0570     struct hte_ts_info *ei;
0571     const struct fwnode_handle *fwnode;
0572     struct of_phandle_args args;
0573     u32 xlated_id;
0574     int ret;
0575     bool free_name = false;
0576 
0577     if (!desc)
0578         return -EINVAL;
0579 
0580     fwnode = dev ? dev_fwnode(dev) : NULL;
0581 
0582     if (is_of_node(fwnode))
0583         gdev = hte_of_get_dev(dev, desc, index, &args, &free_name);
0584     else
0585         gdev = hte_get_dev(desc);
0586 
0587     if (IS_ERR(gdev)) {
0588         pr_err("%s() no hte dev found\n", __func__);
0589         return PTR_ERR(gdev);
0590     }
0591 
0592     if (!try_module_get(gdev->owner))
0593         return -ENODEV;
0594 
0595     if (!gdev->chip) {
0596         pr_err("%s(): requested id does not have provider\n",
0597                __func__);
0598         ret = -ENODEV;
0599         goto put;
0600     }
0601 
0602     if (is_of_node(fwnode)) {
0603         if (!gdev->chip->xlate_of)
0604             ret = -EINVAL;
0605         else
0606             ret = gdev->chip->xlate_of(gdev->chip, &args,
0607                            desc, &xlated_id);
0608     } else {
0609         if (!gdev->chip->xlate_plat)
0610             ret = -EINVAL;
0611         else
0612             ret = gdev->chip->xlate_plat(gdev->chip, desc,
0613                              &xlated_id);
0614     }
0615 
0616     if (ret < 0)
0617         goto put;
0618 
0619     ei = &gdev->ei[xlated_id];
0620 
0621     ret = hte_bind_ts_info_locked(ei, desc, xlated_id);
0622     if (ret)
0623         goto put;
0624 
0625     ei->free_attr_name = free_name;
0626 
0627     return 0;
0628 
0629 put:
0630     module_put(gdev->owner);
0631     return ret;
0632 }
0633 EXPORT_SYMBOL_GPL(hte_ts_get);
0634 
0635 static void __devm_hte_release_ts(void *res)
0636 {
0637     hte_ts_put(res);
0638 }
0639 
0640 /**
0641  * hte_request_ts_ns() - The API to request and enable hardware timestamp in
0642  * nanoseconds.
0643  *
0644  * The entity is provider specific for example, GPIO lines, signals, buses
0645  * etc...The API allocates necessary resources and enables the timestamp.
0646  *
0647  * @desc: Pre-allocated and initialized timestamp descriptor.
0648  * @cb: Callback to push the timestamp data to consumer.
0649  * @tcb: Optional callback. If its provided, subsystem initializes
0650  * workqueue. It is called when cb returns HTE_RUN_SECOND_CB.
0651  * @data: Client data, used during cb and tcb callbacks.
0652  *
0653  * Context: Holds mutex lock.
0654  * Returns: Returns 0 on success or negative error code on failure.
0655  */
0656 int hte_request_ts_ns(struct hte_ts_desc *desc, hte_ts_cb_t cb,
0657               hte_ts_sec_cb_t tcb, void *data)
0658 {
0659     int ret;
0660     struct hte_ts_info *ei;
0661 
0662     if (!desc || !desc->hte_data || !cb)
0663         return -EINVAL;
0664 
0665     ei = desc->hte_data;
0666     if (!ei || !ei->gdev)
0667         return -EINVAL;
0668 
0669     ret = __hte_req_ts(desc, cb, tcb, data);
0670     if (ret < 0) {
0671         dev_err(ei->gdev->chip->dev,
0672             "failed to request id: %d\n", desc->attr.line_id);
0673         return ret;
0674     }
0675 
0676     return 0;
0677 }
0678 EXPORT_SYMBOL_GPL(hte_request_ts_ns);
0679 
0680 /**
0681  * devm_hte_request_ts_ns() - Resource managed API to request and enable
0682  * hardware timestamp in nanoseconds.
0683  *
0684  * The entity is provider specific for example, GPIO lines, signals, buses
0685  * etc...The API allocates necessary resources and enables the timestamp. It
0686  * deallocates and disables automatically when the consumer exits.
0687  *
0688  * @dev: HTE consumer/client device.
0689  * @desc: Pre-allocated and initialized timestamp descriptor.
0690  * @cb: Callback to push the timestamp data to consumer.
0691  * @tcb: Optional callback. If its provided, subsystem initializes
0692  * workqueue. It is called when cb returns HTE_RUN_SECOND_CB.
0693  * @data: Client data, used during cb and tcb callbacks.
0694  *
0695  * Context: Holds mutex lock.
0696  * Returns: Returns 0 on success or negative error code on failure.
0697  */
0698 int devm_hte_request_ts_ns(struct device *dev, struct hte_ts_desc *desc,
0699                hte_ts_cb_t cb, hte_ts_sec_cb_t tcb,
0700                void *data)
0701 {
0702     int err;
0703 
0704     if (!dev)
0705         return -EINVAL;
0706 
0707     err = hte_request_ts_ns(desc, cb, tcb, data);
0708     if (err)
0709         return err;
0710 
0711     err = devm_add_action_or_reset(dev, __devm_hte_release_ts, desc);
0712     if (err)
0713         return err;
0714 
0715     return 0;
0716 }
0717 EXPORT_SYMBOL_GPL(devm_hte_request_ts_ns);
0718 
0719 /**
0720  * hte_init_line_attr() - Initialize line attributes.
0721  *
0722  * Zeroes out line attributes and initializes with provided arguments.
0723  * The function needs to be called before calling any consumer facing
0724  * functions.
0725  *
0726  * @desc: Pre-allocated timestamp descriptor.
0727  * @line_id: line id.
0728  * @edge_flags: edge flags related to line_id.
0729  * @name: name of the line.
0730  * @data: line data related to line_id.
0731  *
0732  * Context: Any.
0733  * Returns: 0 on success or negative error code for the failure.
0734  */
0735 int hte_init_line_attr(struct hte_ts_desc *desc, u32 line_id,
0736                unsigned long edge_flags, const char *name, void *data)
0737 {
0738     if (!desc)
0739         return -EINVAL;
0740 
0741     memset(&desc->attr, 0, sizeof(desc->attr));
0742 
0743     desc->attr.edge_flags = edge_flags;
0744     desc->attr.line_id = line_id;
0745     desc->attr.line_data = data;
0746     if (name) {
0747         name =  kstrdup_const(name, GFP_KERNEL);
0748         if (!name)
0749             return -ENOMEM;
0750     }
0751 
0752     desc->attr.name = name;
0753 
0754     return 0;
0755 }
0756 EXPORT_SYMBOL_GPL(hte_init_line_attr);
0757 
0758 /**
0759  * hte_get_clk_src_info() - Get the clock source information for a ts
0760  * descriptor.
0761  *
0762  * @desc: ts descriptor, same as returned from request API.
0763  * @ci: The API fills this structure with the clock information data.
0764  *
0765  * Context: Any context.
0766  * Returns: 0 on success else negative error code on failure.
0767  */
0768 int hte_get_clk_src_info(const struct hte_ts_desc *desc,
0769              struct hte_clk_info *ci)
0770 {
0771     struct hte_chip *chip;
0772     struct hte_ts_info *ei;
0773 
0774     if (!desc || !desc->hte_data || !ci) {
0775         pr_debug("%s:%d\n", __func__, __LINE__);
0776         return -EINVAL;
0777     }
0778 
0779     ei = desc->hte_data;
0780     if (!ei->gdev || !ei->gdev->chip)
0781         return -EINVAL;
0782 
0783     chip = ei->gdev->chip;
0784     if (!chip->ops->get_clk_src_info)
0785         return -EOPNOTSUPP;
0786 
0787     return chip->ops->get_clk_src_info(chip, ci);
0788 }
0789 EXPORT_SYMBOL_GPL(hte_get_clk_src_info);
0790 
0791 /**
0792  * hte_push_ts_ns() - Push timestamp data in nanoseconds.
0793  *
0794  * It is used by the provider to push timestamp data.
0795  *
0796  * @chip: The HTE chip, used during the registration.
0797  * @xlated_id: entity id understood by both subsystem and provider, this is
0798  * obtained from xlate callback during request API.
0799  * @data: timestamp data.
0800  *
0801  * Returns: 0 on success or a negative error code on failure.
0802  */
0803 int hte_push_ts_ns(const struct hte_chip *chip, u32 xlated_id,
0804            struct hte_ts_data *data)
0805 {
0806     enum hte_return ret;
0807     int st = 0;
0808     struct hte_ts_info *ei;
0809     unsigned long flag;
0810 
0811     if (!chip || !data || !chip->gdev)
0812         return -EINVAL;
0813 
0814     if (xlated_id >= chip->nlines)
0815         return -EINVAL;
0816 
0817     ei = &chip->gdev->ei[xlated_id];
0818 
0819     spin_lock_irqsave(&ei->slock, flag);
0820 
0821     /* timestamp sequence counter */
0822     data->seq = ei->seq++;
0823 
0824     if (!test_bit(HTE_TS_REGISTERED, &ei->flags) ||
0825         test_bit(HTE_TS_DISABLE, &ei->flags)) {
0826         dev_dbg(chip->dev, "Unknown timestamp push\n");
0827         atomic_inc(&ei->dropped_ts);
0828         st = -EINVAL;
0829         goto unlock;
0830     }
0831 
0832     ret = ei->cb(data, ei->cl_data);
0833     if (ret == HTE_RUN_SECOND_CB && ei->tcb) {
0834         queue_work(system_unbound_wq, &ei->cb_work);
0835         set_bit(HTE_TS_QUEUE_WK, &ei->flags);
0836     }
0837 
0838 unlock:
0839     spin_unlock_irqrestore(&ei->slock, flag);
0840 
0841     return st;
0842 }
0843 EXPORT_SYMBOL_GPL(hte_push_ts_ns);
0844 
0845 static int hte_register_chip(struct hte_chip *chip)
0846 {
0847     struct hte_device *gdev;
0848     u32 i;
0849 
0850     if (!chip || !chip->dev || !chip->dev->of_node)
0851         return -EINVAL;
0852 
0853     if (!chip->ops || !chip->ops->request || !chip->ops->release) {
0854         dev_err(chip->dev, "Driver needs to provide ops\n");
0855         return -EINVAL;
0856     }
0857 
0858     gdev = kzalloc(struct_size(gdev, ei, chip->nlines), GFP_KERNEL);
0859     if (!gdev)
0860         return -ENOMEM;
0861 
0862     gdev->chip = chip;
0863     chip->gdev = gdev;
0864     gdev->nlines = chip->nlines;
0865     gdev->sdev = chip->dev;
0866 
0867     for (i = 0; i < chip->nlines; i++) {
0868         gdev->ei[i].gdev = gdev;
0869         mutex_init(&gdev->ei[i].req_mlock);
0870         spin_lock_init(&gdev->ei[i].slock);
0871     }
0872 
0873     if (chip->dev->driver)
0874         gdev->owner = chip->dev->driver->owner;
0875     else
0876         gdev->owner = THIS_MODULE;
0877 
0878     of_node_get(chip->dev->of_node);
0879 
0880     INIT_LIST_HEAD(&gdev->list);
0881 
0882     spin_lock(&hte_lock);
0883     list_add_tail(&gdev->list, &hte_devices);
0884     spin_unlock(&hte_lock);
0885 
0886     hte_chip_dbgfs_init(gdev);
0887 
0888     dev_dbg(chip->dev, "Added hte chip\n");
0889 
0890     return 0;
0891 }
0892 
0893 static int hte_unregister_chip(struct hte_chip *chip)
0894 {
0895     struct hte_device *gdev;
0896 
0897     if (!chip)
0898         return -EINVAL;
0899 
0900     gdev = chip->gdev;
0901 
0902     spin_lock(&hte_lock);
0903     list_del(&gdev->list);
0904     spin_unlock(&hte_lock);
0905 
0906     gdev->chip = NULL;
0907 
0908     of_node_put(chip->dev->of_node);
0909     debugfs_remove_recursive(gdev->dbg_root);
0910     kfree(gdev);
0911 
0912     dev_dbg(chip->dev, "Removed hte chip\n");
0913 
0914     return 0;
0915 }
0916 
0917 static void _hte_devm_unregister_chip(void *chip)
0918 {
0919     hte_unregister_chip(chip);
0920 }
0921 
0922 /**
0923  * devm_hte_register_chip() - Resource managed API to register HTE chip.
0924  *
0925  * It is used by the provider to register itself with the HTE subsystem.
0926  * The unregistration is done automatically when the provider exits.
0927  *
0928  * @chip: the HTE chip to add to subsystem.
0929  *
0930  * Returns: 0 on success or a negative error code on failure.
0931  */
0932 int devm_hte_register_chip(struct hte_chip *chip)
0933 {
0934     int err;
0935 
0936     err = hte_register_chip(chip);
0937     if (err)
0938         return err;
0939 
0940     err = devm_add_action_or_reset(chip->dev, _hte_devm_unregister_chip,
0941                        chip);
0942     if (err)
0943         return err;
0944 
0945     return 0;
0946 }
0947 EXPORT_SYMBOL_GPL(devm_hte_register_chip);