Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 #include <linux/interconnect-provider.h>
0004 #include <linux/device.h>
0005 #include <linux/export.h>
0006 
0007 /**
0008  * of_icc_bulk_get() - get interconnect paths
0009  * @dev: the device requesting the path
0010  * @num_paths: the number of icc_bulk_data
0011  * @paths: the table with the paths we want to get
0012  *
0013  * Returns 0 on success or negative errno otherwise.
0014  */
0015 int __must_check of_icc_bulk_get(struct device *dev, int num_paths,
0016                  struct icc_bulk_data *paths)
0017 {
0018     int ret, i;
0019 
0020     for (i = 0; i < num_paths; i++) {
0021         paths[i].path = of_icc_get(dev, paths[i].name);
0022         if (IS_ERR(paths[i].path)) {
0023             ret = PTR_ERR(paths[i].path);
0024             if (ret != -EPROBE_DEFER)
0025                 dev_err(dev, "of_icc_get() failed on path %s (%d)\n",
0026                     paths[i].name, ret);
0027             paths[i].path = NULL;
0028             goto err;
0029         }
0030     }
0031 
0032     return 0;
0033 
0034 err:
0035     icc_bulk_put(i, paths);
0036 
0037     return ret;
0038 }
0039 EXPORT_SYMBOL_GPL(of_icc_bulk_get);
0040 
0041 /**
0042  * icc_bulk_put() - put a list of interconnect paths
0043  * @num_paths: the number of icc_bulk_data
0044  * @paths: the icc_bulk_data table with the paths being put
0045  */
0046 void icc_bulk_put(int num_paths, struct icc_bulk_data *paths)
0047 {
0048     while (--num_paths >= 0) {
0049         icc_put(paths[num_paths].path);
0050         paths[num_paths].path = NULL;
0051     }
0052 }
0053 EXPORT_SYMBOL_GPL(icc_bulk_put);
0054 
0055 /**
0056  * icc_bulk_set_bw() - set bandwidth to a set of paths
0057  * @num_paths: the number of icc_bulk_data
0058  * @paths: the icc_bulk_data table containing the paths and bandwidth
0059  *
0060  * Returns 0 on success or negative errno otherwise.
0061  */
0062 int icc_bulk_set_bw(int num_paths, const struct icc_bulk_data *paths)
0063 {
0064     int ret = 0;
0065     int i;
0066 
0067     for (i = 0; i < num_paths; i++) {
0068         ret = icc_set_bw(paths[i].path, paths[i].avg_bw, paths[i].peak_bw);
0069         if (ret) {
0070             pr_err("icc_set_bw() failed on path %s (%d)\n", paths[i].name, ret);
0071             return ret;
0072         }
0073     }
0074 
0075     return ret;
0076 }
0077 EXPORT_SYMBOL_GPL(icc_bulk_set_bw);
0078 
0079 /**
0080  * icc_bulk_enable() - enable a previously disabled set of paths
0081  * @num_paths: the number of icc_bulk_data
0082  * @paths: the icc_bulk_data table containing the paths and bandwidth
0083  *
0084  * Returns 0 on success or negative errno otherwise.
0085  */
0086 int icc_bulk_enable(int num_paths, const struct icc_bulk_data *paths)
0087 {
0088     int ret, i;
0089 
0090     for (i = 0; i < num_paths; i++) {
0091         ret = icc_enable(paths[i].path);
0092         if (ret) {
0093             pr_err("icc_enable() failed on path %s (%d)\n", paths[i].name, ret);
0094             goto err;
0095         }
0096     }
0097 
0098     return 0;
0099 
0100 err:
0101     icc_bulk_disable(i, paths);
0102 
0103     return ret;
0104 }
0105 EXPORT_SYMBOL_GPL(icc_bulk_enable);
0106 
0107 /**
0108  * icc_bulk_disable() - disable a set of interconnect paths
0109  * @num_paths: the number of icc_bulk_data
0110  * @paths: the icc_bulk_data table containing the paths and bandwidth
0111  */
0112 void icc_bulk_disable(int num_paths, const struct icc_bulk_data *paths)
0113 {
0114     while (--num_paths >= 0)
0115         icc_disable(paths[num_paths].path);
0116 }
0117 EXPORT_SYMBOL_GPL(icc_bulk_disable);
0118 
0119 struct icc_bulk_devres {
0120     struct icc_bulk_data *paths;
0121     int num_paths;
0122 };
0123 
0124 static void devm_icc_bulk_release(struct device *dev, void *res)
0125 {
0126     struct icc_bulk_devres *devres = res;
0127 
0128     icc_bulk_put(devres->num_paths, devres->paths);
0129 }
0130 
0131 /**
0132  * devm_of_icc_bulk_get() - resource managed of_icc_bulk_get
0133  * @dev: the device requesting the path
0134  * @num_paths: the number of icc_bulk_data
0135  * @paths: the table with the paths we want to get
0136  *
0137  * Returns 0 on success or negative errno otherwise.
0138  */
0139 int devm_of_icc_bulk_get(struct device *dev, int num_paths, struct icc_bulk_data *paths)
0140 {
0141     struct icc_bulk_devres *devres;
0142     int ret;
0143 
0144     devres = devres_alloc(devm_icc_bulk_release, sizeof(*devres), GFP_KERNEL);
0145     if (!devres)
0146         return -ENOMEM;
0147 
0148     ret = of_icc_bulk_get(dev, num_paths, paths);
0149     if (!ret) {
0150         devres->paths = paths;
0151         devres->num_paths = num_paths;
0152         devres_add(dev, devres);
0153     } else {
0154         devres_free(devres);
0155     }
0156 
0157     return ret;
0158 }
0159 EXPORT_SYMBOL_GPL(devm_of_icc_bulk_get);