diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/rpmsg/omap_rpmsg_resmgr.c | 18 | ||||
-rw-r--r-- | drivers/rpmsg/rpmsg_resmgr.c | 58 |
2 files changed, 76 insertions, 0 deletions
diff --git a/drivers/rpmsg/omap_rpmsg_resmgr.c b/drivers/rpmsg/omap_rpmsg_resmgr.c index c856eeee73f7..a0e712430db4 100644 --- a/drivers/rpmsg/omap_rpmsg_resmgr.c +++ b/drivers/rpmsg/omap_rpmsg_resmgr.c @@ -570,6 +570,21 @@ static int _device_bandwidth(struct device *rdev, void *handle, return 0; } +static unsigned long _get_max_freq(void *handle) +{ + struct rprm_gen_device_handle *obj = handle; + struct opp *opp; + unsigned long maxfreq = ULONG_MAX; + + rcu_read_lock(); + opp = opp_find_freq_floor(obj->dev, &maxfreq); + if (IS_ERR(opp)) + maxfreq = 0; + rcu_read_unlock(); + + return maxfreq; +} + static int rprm_iva_request(void **handle, void *data, size_t len) { static struct device *dev; @@ -664,6 +679,7 @@ static struct rprm_res_ops iva_ops = { .latency = _device_latency, .bandwidth = _device_bandwidth, .scale = _device_scale, + .get_max_freq = _get_max_freq, }; static struct rprm_res_ops iva_seq0_ops = { @@ -682,6 +698,7 @@ static struct rprm_res_ops fdif_ops = { .latency = _device_latency, .bandwidth = _device_bandwidth, .scale = _device_scale, + .get_max_freq = _get_max_freq, }; static struct rprm_res_ops sl2if_ops = { @@ -694,6 +711,7 @@ static struct rprm_res_ops iss_ops = { .release = rprm_iss_release, .latency = _device_latency, .bandwidth = _device_bandwidth, + .get_max_freq = _get_max_freq, }; static struct rprm_res omap_res[] = { diff --git a/drivers/rpmsg/rpmsg_resmgr.c b/drivers/rpmsg/rpmsg_resmgr.c index 7320b284fd0f..19840d28d024 100644 --- a/drivers/rpmsg/rpmsg_resmgr.c +++ b/drivers/rpmsg/rpmsg_resmgr.c @@ -321,6 +321,51 @@ err_module: return ret; } +static int _request_data(struct device *dev, struct rprm_elem *e, + u32 type, char data[], int len) +{ + int ret = 0; + unsigned long freq; + + switch (type) { + case RPRM_MAX_FREQ: + if (len != sizeof freq) { + ret = -EINVAL; + break; + } + if (e->res->ops->get_max_freq) { + freq = e->res->ops->get_max_freq(e->handle); + memcpy(data, &freq, len); + } else + ret = -EINVAL; + break; + default: + dev_err(dev, "%s: invalid data request %d!\n", __func__, type); + ret = -EINVAL; + } + return ret; +} + +static int rprm_req_data(struct rprm *rprm, u32 res_id, u32 type, + char data[], int len) +{ + int ret = 0; + struct rprm_elem *e; + struct device *dev = &rprm->rpdev->dev; + + mutex_lock(&rprm->lock); + e = idr_find(&rprm->id_list, res_id); + if (!e) { + ret = -ENOENT; + goto out; + } + + ret = _request_data(dev, e, type, data, len); +out: + mutex_unlock(&rprm->lock); + return ret; +} + static void rprm_cb(struct rpmsg_channel *rpdev, void *data, int len, void *priv, u32 src) { @@ -330,6 +375,7 @@ static void rprm_cb(struct rpmsg_channel *rpdev, void *data, int len, struct rprm_request *req; struct rprm_release *rel; struct rprm_constraint *c; + struct rprm_request_data *rd; char ack_msg[MAX_MSG]; struct rprm_ack *ack = (void *)ack_msg; struct rprm_request_ack *rack = (void *)ack->data; @@ -413,6 +459,18 @@ static void rprm_cb(struct rpmsg_channel *rpdev, void *data, int len, len = sizeof *c; memcpy(ack->data, c, len); break; + case RPRM_REQ_DATA: + len -= sizeof(*rd); + if (len < 0) { + dev_err(dev, "Bad request data message\n"); + ret = -EINVAL; + break; + } + rd = (void *)msg->data; + ret = rprm_req_data(rprm, rd->res_id, rd->type, ack->data, len); + if (ret) + dev_err(dev, "request data failed! ret %d\n", ret); + break; default: dev_err(dev, "Unknow action %d\n", msg->action); ret = -EINVAL; |