diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/rpmsg/Kconfig | 14 | ||||
-rw-r--r-- | drivers/rpmsg/Makefile | 4 | ||||
-rw-r--r-- | drivers/rpmsg/omaprpc/Makefile | 29 | ||||
-rw-r--r-- | drivers/rpmsg/omaprpc/omap_rpc.c (renamed from drivers/staging/omaprpc/omap_rpc.c) | 668 | ||||
-rw-r--r-- | drivers/rpmsg/omaprpc/omap_rpc_dmabuf.c | 449 | ||||
-rw-r--r-- | drivers/rpmsg/omaprpc/omap_rpc_internal.h (renamed from drivers/staging/omaprpc/omap_rpc_internal.h) | 107 | ||||
-rw-r--r-- | drivers/rpmsg/omaprpc/omap_rpc_ion.c | 382 | ||||
-rw-r--r-- | drivers/rpmsg/omaprpc/omap_rpc_rproc.c | 93 | ||||
-rw-r--r-- | drivers/rpmsg/omaprpc/omap_rpc_tiler.c | 59 | ||||
-rw-r--r-- | drivers/staging/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/omaprpc/Kconfig | 15 | ||||
-rw-r--r-- | drivers/staging/omaprpc/Makefile | 17 | ||||
-rw-r--r-- | drivers/staging/omaprpc/omap_rpc.h | 287 | ||||
-rw-r--r-- | drivers/staging/omaprpc/omap_rpc_dmabuf.c | 436 | ||||
-rw-r--r-- | drivers/staging/omaprpc/omap_rpc_ion.c | 346 | ||||
-rw-r--r-- | drivers/staging/omaprpc/omap_rpc_rproc.c | 103 | ||||
-rw-r--r-- | drivers/staging/omaprpc/omap_rpc_tiler.c | 62 |
18 files changed, 1454 insertions, 1620 deletions
diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig index 4625ed6..aa8413f 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig @@ -28,6 +28,20 @@ config RPMSG_OMX If unsure, say N. +config RPC_OMAP + tristate "OMAP Remote Procedure Call driver" + default y + depends on RPMSG + depends on REMOTEPROC || REMOTE_PROC + depends on OMAP_REMOTEPROC || OMAP_REMOTE_PROC + depends on (TI_TILER && ION_OMAP) || (DMA_SHARED_BUFFER && DRM_OMAP) + ---help--- + An rpmsg driver that exposes the Remote Procedure Call API to + user space, in order to allow applications to distribute + remote calls to more power-efficient remote processors on OMAP4+ systems. + + If unsure, say N. + config RPMSG_RESMGR tristate "rpmsg resource manager" default y diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile index 1b0e04b..56d1a1f 100644 --- a/drivers/rpmsg/Makefile +++ b/drivers/rpmsg/Makefile @@ -1,6 +1,8 @@ obj-$(CONFIG_RPMSG) += virtio_rpmsg_bus.o +obj-$(CONFIG_RPMSG_RESMGR) += rpmsg_resmgr.o obj-$(CONFIG_RPMSG_OMX) += rpmsg_omx.o +obj-$(CONFIG_RPC_OMAP) += omaprpc/ + obj-$(CONFIG_RPMSG_CLIENT_SAMPLE) += rpmsg_client_sample.o obj-$(CONFIG_RPMSG_SERVER_SAMPLE) += rpmsg_server_sample.o -obj-$(CONFIG_RPMSG_RESMGR) += rpmsg_resmgr.o diff --git a/drivers/rpmsg/omaprpc/Makefile b/drivers/rpmsg/omaprpc/Makefile new file mode 100644 index 0000000..c64e4f2 --- /dev/null +++ b/drivers/rpmsg/omaprpc/Makefile @@ -0,0 +1,29 @@ +# +# OMAP Remote Procedure Call Driver. +# +# Copyright(c) 2012 Texas Instruments. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published by +# the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see <http://www.gnu.org/licenses/>. + +obj-$(CONFIG_RPC_OMAP) += omaprpc.o +omaprpc-y := omap_rpc.o \ + omap_rpc_tiler.o \ + omap_rpc_rproc.o + +ifeq ($(CONFIG_ION_OMAP),y) +omaprpc-y += omap_rpc_ion.o +else +ifeq ($(CONFIG_DMA_SHARED_BUFFER),y) +omaprpc-y += omap_rpc_dmabuf.o +endif +endif diff --git a/drivers/staging/omaprpc/omap_rpc.c b/drivers/rpmsg/omaprpc/omap_rpc.c index ba80875..5f22838 100644 --- a/drivers/staging/omaprpc/omap_rpc.c +++ b/drivers/rpmsg/omaprpc/omap_rpc.c @@ -3,34 +3,19 @@ * * Copyright(c) 2012 Texas Instruments. All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Texas Instruments nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. */ - #include "omap_rpc_internal.h" static struct class *omaprpc_class; @@ -43,17 +28,76 @@ static struct idr omaprpc_services = IDR_INIT(omaprpc_services); /* could also use DEFINE_SPINLOCK(omaprpc_services_lock); */ static spinlock_t omaprpc_services_lock = - __SPIN_LOCK_UNLOCKED(omaprpc_services_lock); +__SPIN_LOCK_UNLOCKED(omaprpc_services_lock); /* could also use LIST_HEAD(omaprpc_services_list); */ static struct list_head omaprpc_services_list = - LIST_HEAD_INIT(omaprpc_services_list); +LIST_HEAD_INIT(omaprpc_services_list); -#if defined(OMAPRPC_PERF_MEASUREMENT) static struct timeval start_time; static struct timeval end_time; static long usec_elapsed; -#endif +unsigned int omaprpc_debug; +EXPORT_SYMBOL(omaprpc_debug); +MODULE_PARM_DESC(debug, "Used to enable debug messages"); +module_param_named(debug, omaprpc_debug, int, 0600); + +static void omaprpc_print_msg(struct omaprpc_instance_t *rpc, + char *prefix, char buffer[512]) +{ + u32 sp = 0, p = 0; + struct omaprpc_msg_header_t *hdr = + (struct omaprpc_msg_header_t *)buffer; + struct omaprpc_instance_handle_t *hdl = NULL; + struct omaprpc_instance_info_t *info = NULL; + struct omaprpc_packet_t *packet = NULL; + struct omaprpc_parameter_t *param = NULL; + OMAPRPC_PRINT(OMAPRPC_ZONE_VERBOSE, rpc->rpcserv->dev, + "%s HDR: type %d flags: %d len: %d\n", + prefix, hdr->msg_type, hdr->msg_flags, hdr->msg_len); + switch (hdr->msg_type) { + case OMAPRPC_MSG_INSTANCE_CREATED: + case OMAPRPC_MSG_INSTANCE_DESTROYED: + hdl = OMAPRPC_PAYLOAD(buffer, omaprpc_instance_handle_t); + OMAPRPC_PRINT(OMAPRPC_ZONE_VERBOSE, + rpc->rpcserv->dev, + "%s endpoint:%d status:%d\n", + prefix, hdl->endpoint_address, hdl->status); + break; + case OMAPRPC_MSG_INSTANCE_INFO: + info = OMAPRPC_PAYLOAD(buffer, omaprpc_instance_info_t); + OMAPRPC_PRINT(OMAPRPC_ZONE_VERBOSE, + rpc->rpcserv->dev, + "%s (info not yet implemented)\n", prefix); + break; + case OMAPRPC_MSG_CALL_FUNCTION: + packet = OMAPRPC_PAYLOAD(buffer, omaprpc_packet_t); + OMAPRPC_PRINT(OMAPRPC_ZONE_VERBOSE, + rpc->rpcserv->dev, + "%s PACKET: desc:%04x msg_id:%04x pool_id:%04x" + " job_id:%04x func:0x%08x result:%d size:%u\n", + prefix, + packet->desc, + packet->msg_id, + packet->pool_id, + packet->job_id, + packet->fxn_idx, + packet->result, packet->data_size); + sp = sizeof(struct omaprpc_parameter_t); + param = (struct omaprpc_parameter_t *)packet->data; + for (p = 0; p < (packet->data_size / sp); p++) { + OMAPRPC_PRINT(OMAPRPC_ZONE_VERBOSE, + rpc->rpcserv->dev, + "%s PARAM[%u] size:%zu data:%zu (0x%08x)", + prefix, p, + param[p].size, + param[p].data, param[p].data); + } + break; + default: + break; + } +} static void omaprpc_fxn_del(struct omaprpc_instance_t *rpc) { @@ -62,7 +106,7 @@ static void omaprpc_fxn_del(struct omaprpc_instance_t *rpc) struct omaprpc_call_function_list_t *pos, *n; mutex_lock(&rpc->lock); - list_for_each_entry_safe(pos, n, &rpc->fxn_list, list) { + list_for_each_entry_safe(pos, n, &rpc->fxn_list, list) { list_del(&pos->list); kfree(pos->function); kfree(pos); @@ -71,18 +115,17 @@ static void omaprpc_fxn_del(struct omaprpc_instance_t *rpc) } } -static struct omaprpc_call_function_t *omaprpc_fxn_get( - struct omaprpc_instance_t *rpc, - u16 msgId) +static struct omaprpc_call_function_t *omaprpc_fxn_get(struct omaprpc_instance_t + *rpc, u16 msgId) { struct omaprpc_call_function_t *function = NULL; struct omaprpc_call_function_list_t *pos, *n; mutex_lock(&rpc->lock); list_for_each_entry_safe(pos, n, &rpc->fxn_list, list) { - OMAPRPC_INFO(rpc->rpcserv->dev, - "Looking for msg %u, found msg %u\n", - msgId, pos->msgId); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "Looking for msg %u, found msg %u\n", + msgId, pos->msgId); if (pos->msgId == msgId) { function = pos->function; list_del(&pos->list); @@ -95,25 +138,23 @@ static struct omaprpc_call_function_t *omaprpc_fxn_get( } static int omaprpc_fxn_add(struct omaprpc_instance_t *rpc, - struct omaprpc_call_function_t *function, - u16 msgId) + struct omaprpc_call_function_t *function, u16 msgId) { struct omaprpc_call_function_list_t *fxn = NULL; fxn = (struct omaprpc_call_function_list_t *) - kmalloc(sizeof(struct omaprpc_call_function_list_t), - GFP_KERNEL); + kmalloc(sizeof(struct omaprpc_call_function_list_t), GFP_KERNEL); if (fxn) { fxn->function = function; fxn->msgId = msgId; mutex_lock(&rpc->lock); list_add(&fxn->list, &rpc->fxn_list); mutex_unlock(&rpc->lock); - OMAPRPC_INFO(rpc->rpcserv->dev, - "Added msg id %u to list", msgId); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "Added msg id %u to list", msgId); } else { OMAPRPC_ERR(rpc->rpcserv->dev, - "Failed to add function %p to list with id %d\n", - function, msgId); + "Failed to add function %p to list with id %d\n", + function, msgId); return -ENOMEM; } return 0; @@ -121,10 +162,7 @@ static int omaprpc_fxn_add(struct omaprpc_instance_t *rpc, /* This is the callback from the remote core to this side */ static void omaprpc_cb(struct rpmsg_channel *rpdev, - void *data, - int len, - void *priv, - u32 src) + void *data, int len, void *priv, u32 src) { struct omaprpc_msg_header_t *hdr = data; struct omaprpc_instance_t *rpc = priv; @@ -134,13 +172,16 @@ static void omaprpc_cb(struct rpmsg_channel *rpdev, char *skbdata; u32 expected = 0; - OMAPRPC_INFO(rpc->rpcserv->dev, - "OMAPRPC: incoming msg src %d len %d msg_type %d msg_len %d\n", - src, len, hdr->msg_type, hdr->msg_len); -#if defined(OMAPRPC_VERY_VERBOSE) - print_hex_dump(KERN_DEBUG, "OMAPRPC: RX: ", - DUMP_PREFIX_NONE, 16, 1, data, len, true); -#endif + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "OMAPRPC: <== incoming msg src %d len %d msg_type %d msg_len %d\n", + src, len, hdr->msg_type, hdr->msg_len); + + if (omaprpc_debug & OMAPRPC_ZONE_VERBOSE) { + print_hex_dump(KERN_DEBUG, "OMAPRPC: RX: ", + DUMP_PREFIX_NONE, 16, 1, data, len, true); + omaprpc_print_msg(rpc, "RX:", buf); + } + expected = sizeof(struct omaprpc_msg_header_t); switch (hdr->msg_type) { case OMAPRPC_MSG_INSTANCE_CREATED: @@ -154,8 +195,8 @@ static void omaprpc_cb(struct rpmsg_channel *rpdev, if (len < expected) { OMAPRPC_ERR(rpc->rpcserv->dev, - "OMAPRPC: truncated message detected! Was %u bytes long" - " expected %u\n", len, expected); + "OMAPRPC: truncated message detected! Was %u bytes long" + " expected %u\n", len, expected); rpc->state = OMAPRPC_STATE_FAULT; return; } @@ -165,15 +206,13 @@ static void omaprpc_cb(struct rpmsg_channel *rpdev, hdl = OMAPRPC_PAYLOAD(buf, omaprpc_instance_handle_t); if (hdl->status) { OMAPRPC_ERR(rpc->rpcserv->dev, - "OMAPRPC: Failed to connect to remote core! " - "Status=%d\n", - hdl->status); + "OMAPRPC: Failed to connect to remote core! " + "Status=%d\n", hdl->status); rpc->state = OMAPRPC_STATE_FAULT; } else { - OMAPRPC_INFO(rpc->rpcserv->dev, "OMAPRPC: " - "Created addr %d status %d\n", - hdl->endpoint_address, - hdl->status); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "OMAPRPC: Created addr %d status %d\n", + hdl->endpoint_address, hdl->status); /* only save the address if it connected. */ rpc->dst = hdl->endpoint_address; rpc->state = OMAPRPC_STATE_CONNECTED; @@ -187,14 +226,14 @@ static void omaprpc_cb(struct rpmsg_channel *rpdev, case OMAPRPC_MSG_INSTANCE_DESTROYED: hdl = OMAPRPC_PAYLOAD(buf, omaprpc_instance_handle_t); if (hdr->msg_len < sizeof(*hdl)) { - OMAPRPC_ERR(rpc->rpcserv->dev, "OMAPRPC: disconnect " - "message was incorrect size!\n"); + OMAPRPC_ERR(rpc->rpcserv->dev, + "OMAPRPC: disconnect message was incorrect size!\n"); rpc->state = OMAPRPC_STATE_FAULT; break; } - OMAPRPC_INFO(rpc->rpcserv->dev, - "OMAPRPC: endpoint %d disconnected!\n", - hdl->endpoint_address); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "OMAPRPC: endpoint %d disconnected!\n", + hdl->endpoint_address); rpc->state = OMAPRPC_STATE_DISCONNECTED; rpc->dst = 0; rpc->transisioning = 0; @@ -206,27 +245,32 @@ static void omaprpc_cb(struct rpmsg_channel *rpdev, case OMAPRPC_MSG_CALL_FUNCTION: case OMAPRPC_MSG_FUNCTION_RETURN: -#if defined(OMAPRPC_PERF_MEASUREMENT) - do_gettimeofday(&end_time); - usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * - 1000000 + end_time.tv_usec - start_time.tv_usec; - OMAPRPC_INFO(rpc->rpcserv->dev, - "write to callback took %lu usec\n", usec_elapsed); -#endif + if (omaprpc_debug & OMAPRPC_ZONE_PERF) { + do_gettimeofday(&end_time); + usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * + 1000000 + end_time.tv_usec - start_time.tv_usec; + OMAPRPC_PRINT(OMAPRPC_ZONE_PERF, rpc->rpcserv->dev, + "write to callback took %lu usec\n", + usec_elapsed); + } + skb = alloc_skb(hdr->msg_len, GFP_KERNEL); if (!skb) { OMAPRPC_ERR(rpc->rpcserv->dev, - "OMAPRPC: alloc_skb err: %u\n", hdr->msg_len); + "OMAPRPC: alloc_skb err: %u\n", + hdr->msg_len); break; } skbdata = skb_put(skb, hdr->msg_len); memcpy(skbdata, hdr->msg_data, hdr->msg_len); mutex_lock(&rpc->lock); -#if defined(OMAPRPC_PERF_MEASUREMENT) - /* capture the time delay between callback and read */ - do_gettimeofday(&start_time); -#endif + + if (omaprpc_debug & OMAPRPC_ZONE_PERF) { + /* capture the time delay between callback and read */ + do_gettimeofday(&start_time); + } + skb_queue_tail(&rpc->queue, skb); mutex_unlock(&rpc->lock); /* wake up any blocking processes, waiting for new data */ @@ -234,7 +278,7 @@ static void omaprpc_cb(struct rpmsg_channel *rpdev, break; default: dev_warn(rpc->rpcserv->dev, - "OMAPRPC: unexpected msg type: %d\n", hdr->msg_type); + "OMAPRPC: unexpected msg type: %d\n", hdr->msg_type); break; } } @@ -245,7 +289,7 @@ static int omaprpc_connect(struct omaprpc_instance_t *rpc, struct omaprpc_service_t *rpcserv = rpc->rpcserv; char kbuf[512]; struct omaprpc_msg_header_t *hdr = - (struct omaprpc_msg_header_t *)&kbuf[0]; + (struct omaprpc_msg_header_t *)&kbuf[0]; int ret = 0; u32 len = 0; @@ -267,16 +311,16 @@ static int omaprpc_connect(struct omaprpc_instance_t *rpc, /* indicate that we are waiting for a completion */ rpc->transisioning = 1; - /* send a conn req to the remote RPC connection service. use - * the new local address that was just allocated by ->open */ + /* + * send a conn req to the remote RPC connection service. use + * the new local address that was just allocated by ->open + */ ret = rpmsg_send_offchannel(rpcserv->rpdev, rpc->ept->addr, - rpcserv->rpdev->dst, - (char *)kbuf, - len); + rpcserv->rpdev->dst, (char *)kbuf, len); if (ret > 0) { OMAPRPC_ERR(rpcserv->dev, - "OMAPRPC: rpmsg_send failed: %d\n", ret); + "OMAPRPC: rpmsg_send failed: %d\n", ret); return ret; } @@ -291,7 +335,7 @@ static int omaprpc_connect(struct omaprpc_instance_t *rpc, if (ret > 0) { OMAPRPC_ERR(rpcserv->dev, - "OMAPRPC: premature wakeup: %d\n", ret); + "OMAPRPC: premature wakeup: %d\n", ret); return -EIO; } @@ -299,37 +343,39 @@ static int omaprpc_connect(struct omaprpc_instance_t *rpc, } static long omaprpc_ioctl(struct file *filp, - unsigned int cmd, - unsigned long arg) + unsigned int cmd, unsigned long arg) { struct omaprpc_instance_t *rpc = filp->private_data; struct omaprpc_service_t *rpcserv = rpc->rpcserv; struct omaprpc_create_instance_t connect; int ret = 0; - OMAPRPC_INFO(rpcserv->dev, "OMAPRPC: %s: cmd %d, arg 0x%lx\n", - __func__, cmd, arg); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpcserv->dev, + "OMAPRPC: %s: cmd %d, arg 0x%lx\n", __func__, cmd, arg); - /* if the magic was not present, tell the caller - that we are not a typewritter[sic]! */ + /* + * if the magic was not present, tell the caller + *that we are not a typewritter[sic]! + */ if (_IOC_TYPE(cmd) != OMAPRPC_IOC_MAGIC) return -ENOTTY; - /* if the number of the command is larger than what - we support, also tell the caller that we are not a typewriter[sic]! */ + /* + * if the number of the command is larger than what + * we support, also tell the caller that we are not a typewriter[sic]! + */ if (_IOC_NR(cmd) > OMAPRPC_IOC_MAXNR) return -ENOTTY; switch (cmd) { case OMAPRPC_IOC_CREATE: /* copy the connection buffer from the user */ - ret = copy_from_user(&connect, (char __user *) arg, + ret = copy_from_user(&connect, (char __user *)arg, sizeof(connect)); if (ret) { OMAPRPC_ERR(rpcserv->dev, - "OMAPRPC: %s: %d: copy_from_user fail: %d\n", - __func__, - _IOC_NR(cmd), ret); + "OMAPRPC: %s: %d: copy_from_user fail: %d\n", + __func__, _IOC_NR(cmd), ret); ret = -EFAULT; } else { /* make sure user input is null terminated */ @@ -342,51 +388,51 @@ static long omaprpc_ioctl(struct file *filp, break; #if defined(OMAPRPC_USE_ION) case OMAPRPC_IOC_IONREGISTER: - { - struct ion_fd_data data; - if (copy_from_user(&data, (char __user *) arg, sizeof(data))) { - ret = -EFAULT; - OMAPRPC_ERR(rpcserv->dev, - "OMAPRPC: %s: %d: copy_from_user fail: %d\n", - __func__, - _IOC_NR(cmd), ret); - } - data.handle = ion_import_fd(rpc->ion_client, data.fd); - if (IS_ERR(data.handle)) - data.handle = NULL; - if (copy_to_user((char __user *)arg, &data, sizeof(data))) { - ret = -EFAULT; - OMAPRPC_ERR(rpcserv->dev, - "OMAPRPC: %s: %d: copy_to_user fail: %d\n", - __func__, - _IOC_NR(cmd), ret); + { + struct ion_fd_data data; + if (copy_from_user + (&data, (char __user *)arg, sizeof(data))) { + ret = -EFAULT; + OMAPRPC_ERR(rpcserv->dev, + "OMAPRPC: %s: %d: copy_from_user fail: %d\n", + __func__, _IOC_NR(cmd), ret); + } + data.handle = ion_import_fd(rpc->ion_client, data.fd); + if (IS_ERR(data.handle)) + data.handle = NULL; + if (copy_to_user + ((char __user *)arg, &data, sizeof(data))) { + ret = -EFAULT; + OMAPRPC_ERR(rpcserv->dev, + "OMAPRPC: %s: %d: copy_to_user fail: %d\n", + __func__, _IOC_NR(cmd), ret); + } + break; } - break; - } case OMAPRPC_IOC_IONUNREGISTER: - { - struct ion_fd_data data; - if (copy_from_user(&data, (char __user *) arg, sizeof(data))) { - ret = -EFAULT; - OMAPRPC_ERR(rpcserv->dev, - "OMAPRPC: %s: %d: copy_from_user fail: %d\n", - __func__, - _IOC_NR(cmd), ret); - } - ion_free(rpc->ion_client, data.handle); - if (copy_to_user((char __user *)arg, &data, sizeof(data))) { - ret = -EFAULT; - OMAPRPC_ERR(rpcserv->dev, - "OMAPRPC: %s: %d: copy_to_user fail: %d\n", - __func__, - _IOC_NR(cmd), ret); + { + struct ion_fd_data data; + if (copy_from_user + (&data, (char __user *)arg, sizeof(data))) { + ret = -EFAULT; + OMAPRPC_ERR(rpcserv->dev, + "OMAPRPC: %s: %d: copy_from_user fail: %d\n", + __func__, _IOC_NR(cmd), ret); + } + ion_free(rpc->ion_client, data.handle); + if (copy_to_user + ((char __user *)arg, &data, sizeof(data))) { + ret = -EFAULT; + OMAPRPC_ERR(rpcserv->dev, + "OMAPRPC: %s: %d: copy_to_user fail: %d\n", + __func__, _IOC_NR(cmd), ret); + } + break; } - break; - } #endif default: OMAPRPC_ERR(rpcserv->dev, - "OMAPRPC: unhandled ioctl cmd: %d\n", cmd); + "OMAPRPC: unhandled ioctl cmd: %d\n", cmd); break; } @@ -401,8 +447,10 @@ static int omaprpc_open(struct inode *inode, struct file *filp) /* get the service pointer out of the inode */ rpcserv = container_of(inode->i_cdev, struct omaprpc_service_t, cdev); - /* Return EBUSY if we are down and if non-blocking or waiting for - something */ + /* + * Return EBUSY if we are down and if non-blocking or waiting for + * something + */ if (rpcserv->state == OMAPRPC_SERVICE_STATE_DOWN) if ((filp->f_flags & O_NONBLOCK) || wait_for_completion_interruptible(&rpcserv->comp)) @@ -437,8 +485,10 @@ static int omaprpc_open(struct inode *inode, struct file *filp) INIT_LIST_HEAD(&rpc->dma_list); #endif - /* assign a new, unique, local address and associate the instance - with it */ + /* + * assign a new, unique, local address and + * associate the instance with it + */ rpc->ept = rpmsg_create_ept(rpcserv->rpdev, omaprpc_cb, rpc, RPMSG_ADDR_ANY); if (!rpc->ept) { @@ -449,9 +499,9 @@ static int omaprpc_open(struct inode *inode, struct file *filp) #if defined(OMAPRPC_USE_ION) /* get a handle to the ion client for RPC buffers */ rpc->ion_client = ion_client_create(omap_ion_device, - (1 << ION_HEAP_TYPE_CARVEOUT) | - (1 << OMAP_ION_HEAP_TYPE_TILER), - "rpmsg-rpc"); + (1 << ION_HEAP_TYPE_CARVEOUT) | + (1 << OMAP_ION_HEAP_TYPE_TILER), + "rpmsg-rpc"); #endif /* remember rpc in filp's private data */ @@ -462,8 +512,8 @@ static int omaprpc_open(struct inode *inode, struct file *filp) list_add(&rpc->list, &rpcserv->instance_list); mutex_unlock(&rpcserv->lock); - OMAPRPC_INFO(rpcserv->dev, - "OMAPRPC: local addr assigned: 0x%x\n", rpc->ept->addr); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpcserv->dev, + "OMAPRPC: local addr assigned: 0x%x\n", rpc->ept->addr); return 0; } @@ -485,17 +535,16 @@ static int omaprpc_release(struct inode *inode, struct file *filp) if (rpc == NULL || rpcserv == NULL) return 0; - OMAPRPC_INFO(rpcserv->dev, - "Releasing Instance %p, in state %d\n", - rpc, rpc->state); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpcserv->dev, + "Releasing Instance %p, in state %d\n", rpc, rpc->state); /* if we are in a normal state */ if (rpc->state != OMAPRPC_STATE_FAULT) { /* if we have connected already */ if (rpc->state == OMAPRPC_STATE_CONNECTED) { struct omaprpc_msg_header_t *hdr = - (struct omaprpc_msg_header_t *)&kbuf[0]; + (struct omaprpc_msg_header_t *)&kbuf[0]; struct omaprpc_instance_handle_t *handle = - OMAPRPC_PAYLOAD(kbuf, omaprpc_instance_handle_t); + OMAPRPC_PAYLOAD(kbuf, omaprpc_instance_handle_t); /* Format a disconnect message */ hdr->msg_type = OMAPRPC_MSG_DESTROY_INSTANCE; @@ -503,11 +552,12 @@ static int omaprpc_release(struct inode *inode, struct file *filp) /* end point address */ handle->endpoint_address = rpc->dst; handle->status = 0; - len = sizeof(struct omaprpc_msg_header_t)+hdr->msg_len; + len = + sizeof(struct omaprpc_msg_header_t) + hdr->msg_len; - OMAPRPC_INFO(rpcserv->dev, - "OMAPRPC: Disconnecting from RPC service at %d\n", - rpc->dst); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpcserv->dev, + "OMAPRPC: Disconnecting from RPC service at %d\n", + rpc->dst); /* send the msg to the remote RPC connection service */ ret = rpmsg_send_offchannel(rpcserv->rpdev, @@ -516,13 +566,15 @@ static int omaprpc_release(struct inode *inode, struct file *filp) (char *)kbuf, len); if (ret) { OMAPRPC_ERR(rpcserv->dev, - "OMAPRPC: rpmsg_send failed: %d\n", - ret); + "OMAPRPC: rpmsg_send failed: %d\n", + ret); return ret; } - /* @TODO Should we wait for a message to come back? - For now, no. */ + /* + * TODO: Should we wait for a message to come back? + * For now, no. + */ wait_for_completion(&rpc->reply_arrived); } @@ -533,7 +585,6 @@ static int omaprpc_release(struct inode *inode, struct file *filp) rpc->ept = NULL; } } - #if defined(OMAPRPC_USE_ION) if (rpc->ion_client) { /* Destroy our local client to ion */ @@ -549,13 +600,12 @@ static int omaprpc_release(struct inode *inode, struct file *filp) list_del(&rpc->list); mutex_unlock(&rpcserv->lock); - OMAPRPC_INFO(rpcserv->dev, - "OMAPRPC: Instance %p has been deleted!\n", - rpc); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpcserv->dev, + "OMAPRPC: Instance %p has been deleted!\n", rpc); if (list_empty(&rpcserv->instance_list)) { - OMAPRPC_INFO(rpcserv->dev, - "OMAPRPC: All instances have been removed!\n"); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpcserv->dev, + "OMAPRPC: All instances have been removed!\n"); } /* Delete the instance memory */ @@ -567,9 +617,7 @@ static int omaprpc_release(struct inode *inode, struct file *filp) } static ssize_t omaprpc_read(struct file *filp, - char __user *buf, - size_t len, - loff_t *offp) + char __user *buf, size_t len, loff_t *offp) { struct omaprpc_instance_t *rpc = filp->private_data; struct omaprpc_packet_t *packet = NULL; @@ -622,8 +670,9 @@ static ssize_t omaprpc_read(struct file *filp, } /* otherwise block, and wait for data */ if (wait_event_interruptible(rpc->readq, - (!skb_queue_empty(&rpc->queue) || - rpc->state == OMAPRPC_STATE_FAULT))) { + (!skb_queue_empty(&rpc->queue) || + rpc->state == + OMAPRPC_STATE_FAULT))) { ret = -ERESTARTSYS; goto failure; } @@ -646,20 +695,19 @@ static ssize_t omaprpc_read(struct file *filp, if (!skb) { mutex_unlock(&rpc->lock); OMAPRPC_ERR(rpc->rpcserv->dev, - "OMAPRPC: skb was NULL when dequeued, " - "possible race condition!\n"); + "OMAPRPC: skb was NULL when dequeued, " + "possible race condition!\n"); ret = -EIO; goto failure; } -#if defined(OMAPRPC_PERF_MEASUREMENT) - do_gettimeofday(&end_time); - usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * - 1000000 + end_time.tv_usec - start_time.tv_usec; - OMAPRPC_INFO(rpc->rpcserv->dev, - "callback to read took %lu usec\n", - usec_elapsed); -#endif + if (omaprpc_debug & OMAPRPC_ZONE_PERF) { + do_gettimeofday(&end_time); + usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * + 1000000 + end_time.tv_usec - start_time.tv_usec; + OMAPRPC_PRINT(OMAPRPC_ZONE_PERF, rpc->rpcserv->dev, + "callback to read took %lu usec\n", usec_elapsed); + } /* unlock the instances */ mutex_unlock(&rpc->lock); @@ -671,8 +719,10 @@ static ssize_t omaprpc_read(struct file *filp, function = omaprpc_fxn_get(rpc, packet->msg_id); if (function) { if (function->num_translations > 0) { - /* Untranslate the PA pointers back to the ARM ION - handles */ + /* + * Untranslate the PA pointers back + * to the ARM ION handles + */ ret = omaprpc_xlate_buffers(rpc, function, OMAPRPC_RPA_TO_UVA); @@ -686,7 +736,7 @@ static ssize_t omaprpc_read(struct file *filp, /* copy the kernel buffer to the user side */ if (copy_to_user(buf, &returned, use)) { OMAPRPC_ERR(rpc->rpcserv->dev, - "OMAPRPC: %s: copy_to_user fail\n", __func__); + "OMAPRPC: %s: copy_to_user fail\n", __func__); ret = -EFAULT; } else { ret = use; @@ -698,9 +748,8 @@ failure: } static ssize_t omaprpc_write(struct file *filp, - const char __user *ubuf, - size_t len, - loff_t *offp) + const char __user *ubuf, + size_t len, loff_t *offp) { struct omaprpc_instance_t *rpc = filp->private_data; struct omaprpc_service_t *rpcserv = rpc->rpcserv; @@ -719,8 +768,8 @@ static ssize_t omaprpc_write(struct file *filp, /* over OMAPRPC_MAX_TRANSLATIONS! too many! */ if (len > (sizeof(struct omaprpc_call_function_t) + - OMAPRPC_MAX_TRANSLATIONS * - sizeof(struct omaprpc_param_translation_t))) { + OMAPRPC_MAX_TRANSLATIONS * + sizeof(struct omaprpc_param_translation_t))) { ret = -ENOTSUPP; goto failure; } @@ -731,9 +780,9 @@ static ssize_t omaprpc_write(struct file *filp, goto failure; } - OMAPRPC_INFO(rpcserv->dev, - "OMAPRPC: Allocating local function call copy for %u bytes\n", - len); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpcserv->dev, + "OMAPRPC: Allocating local function call copy for %u bytes\n", + len); function = kzalloc(len, GFP_KERNEL); if (function == NULL) { @@ -764,7 +813,10 @@ static ssize_t omaprpc_write(struct file *filp, packet->fxn_idx = OMAPRPC_SET_FXN_IDX(function->func_index); packet->result = 0; packet->data_size = sizeof(struct omaprpc_parameter_t) * - function->num_params; + function->num_params; + + /* compute the parameter pointer changes last since this will cause the + cache operations */ parameters = (struct omaprpc_parameter_t *)packet->data; for (param = 0; param < function->num_params; param++) { parameters[param].size = function->params[param].size; @@ -772,15 +824,19 @@ static ssize_t omaprpc_write(struct file *filp, /* internally the buffer translations takes care of the offsets */ void *reserved = - (void *)function->params[param].reserved; + (void *)function->params[param].reserved; parameters[param].data = - (size_t)omaprpc_buffer_lookup(rpc, - rpc->core, - (virt_addr_t)function->params[param].data, - (virt_addr_t)function->params[param].base, - reserved); + (size_t) omaprpc_buffer_lookup(rpc, + rpc->core, + (virt_addr_t) + function-> + params[param].data, + (virt_addr_t) + function-> + params[param].base, + reserved); } else if (function->params[param].type == - OMAPRPC_PARAM_TYPE_ATOMIC) { + OMAPRPC_PARAM_TYPE_ATOMIC) { parameters[param].data = function->params[param].data; } else { ret = -ENOTSUPP; @@ -793,9 +849,9 @@ static ssize_t omaprpc_write(struct file *filp, /* failed to provide the translation data */ if (function->num_translations > 0 && - len < (sizeof(struct omaprpc_call_function_t)+ - (function->num_translations* - sizeof(struct omaprpc_param_translation_t)))) { + len < (sizeof(struct omaprpc_call_function_t) + + (function->num_translations * + sizeof(struct omaprpc_param_translation_t)))) { ret = -ENXIO; goto failure; } @@ -807,17 +863,12 @@ static ssize_t omaprpc_write(struct file *filp, ret = omaprpc_xlate_buffers(rpc, function, OMAPRPC_UVA_TO_RPA); if (ret < 0) { OMAPRPC_ERR(rpcserv->dev, - "OMAPRPC: ERROR: Failed to translate all " - "pointers for remote core!\n"); + "OMAPRPC: ERROR: Failed to translate all " + "pointers for remote core!\n"); goto failure; } } -#if defined(OMAPRPC_VERY_VERBOSE) /* Very Verbose Debugging Code */ - print_hex_dump(KERN_DEBUG, "OMAPRPC: TX: ", - DUMP_PREFIX_NONE, 16, 1, kbuf, use, true); -#endif - /* save the function data */ ret = omaprpc_fxn_add(rpc, function, rpc->msgId); if (ret < 0) { @@ -826,38 +877,45 @@ static ssize_t omaprpc_write(struct file *filp, goto failure; } -#if defined(OMAPRPC_PERF_MEASUREMENT) - /* capture the time delay between write and callback */ - do_gettimeofday(&start_time); -#endif + /* dump the packet for debugging */ + if (omaprpc_debug & OMAPRPC_ZONE_VERBOSE) { + print_hex_dump(KERN_DEBUG, "OMAPRPC: TX: ", + DUMP_PREFIX_NONE, 16, 1, kbuf, use, true); + omaprpc_print_msg(rpc, "TX:", kbuf); + } + + if (omaprpc_debug & OMAPRPC_ZONE_PERF) { + /* capture the time delay between write and callback */ + do_gettimeofday(&start_time); + } /* Send the msg */ ret = rpmsg_send_offchannel(rpcserv->rpdev, - rpc->ept->addr, - rpc->dst, - kbuf, use); + rpc->ept->addr, rpc->dst, kbuf, use); if (ret) { OMAPRPC_ERR(rpcserv->dev, - "OMAPRPC: rpmsg_send failed: %d\n", ret); - /* remove the function data that we just saved*/ + "OMAPRPC: rpmsg_send failed: %d\n", ret); + /* remove the function data that we just saved */ omaprpc_fxn_get(rpc, rpc->msgId); /* unwind */ omaprpc_xlate_buffers(rpc, function, OMAPRPC_RPA_TO_UVA); goto failure; } - OMAPRPC_INFO(rpcserv->dev, - "OMAPRPC: Send msg to remote endpoint %u\n", rpc->dst); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpcserv->dev, + "OMAPRPC: ==> Sent msg to remote endpoint %u\n", + rpc->dst); failure: if (ret >= 0) ret = len; else kfree(function); - return ret; /* return the length of the data written to us */ + /* return the length of the data written to us */ + return ret; } static unsigned int omaprpc_poll(struct file *filp, - struct poll_table_struct *wait) + struct poll_table_struct *wait) { struct omaprpc_instance_t *rpc = filp->private_data; unsigned int mask = 0; @@ -870,7 +928,7 @@ static unsigned int omaprpc_poll(struct file *filp, poll_wait(filp, &rpc->readq, wait); if (rpc->state == OMAPRPC_STATE_FAULT) { mutex_unlock(&rpc->lock); - return -ENXIO; /* The remote service died somehow */ + return -ENXIO; /* The remote service died somehow */ } /* if the queue is not empty set the poll bit correctly */ @@ -887,20 +945,20 @@ static unsigned int omaprpc_poll(struct file *filp, } static const struct file_operations omaprpc_fops = { - .owner = THIS_MODULE, - .open = omaprpc_open, - .release = omaprpc_release, + .owner = THIS_MODULE, + .open = omaprpc_open, + .release = omaprpc_release, .unlocked_ioctl = omaprpc_ioctl, - .read = omaprpc_read, - .write = omaprpc_write, - .poll = omaprpc_poll, + .read = omaprpc_read, + .write = omaprpc_write, + .poll = omaprpc_poll, }; static int omaprpc_device_create(struct rpmsg_channel *rpdev) { char kbuf[512]; struct omaprpc_msg_header_t *hdr = - (struct omaprpc_msg_header_t *)&kbuf[0]; + (struct omaprpc_msg_header_t *)&kbuf[0]; int ret = 0; u32 len = 0; @@ -923,11 +981,11 @@ static int omaprpc_probe(struct rpmsg_channel *rpdev) int ret, major, minor; struct omaprpc_service_t *rpcserv = NULL, *tmp; - OMAPRPC_INFO(&rpdev->dev, - "OMAPRPC: Probing service with src %u dst %u\n", - rpdev->src, rpdev->dst); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, &rpdev->dev, + "OMAPRPC: Probing service with src %u dst %u\n", + rpdev->src, rpdev->dst); -again: /* SMP systems could race device probes */ +again: /* SMP systems could race device probes */ /* allocate the memory for an integer ID */ if (!idr_pre_get(&omaprpc_services, GFP_KERNEL)) { @@ -941,17 +999,20 @@ again: /* SMP systems could race device probes */ if (ret == -EAGAIN) { spin_unlock(&omaprpc_services_lock); OMAPRPC_ERR(&rpdev->dev, - "OMAPRPC: Race to the new idr memory! (ret=%d)\n", ret); + "OMAPRPC: Race to the new idr memory! (ret=%d)\n", + ret); goto again; - } else if (ret != 0) { /* probably -ENOSPC */ + } else if (ret != 0) { /* probably -ENOSPC */ spin_unlock(&omaprpc_services_lock); OMAPRPC_ERR(&rpdev->dev, - "OMAPRPC: failed to idr_get_new: %d\n", ret); + "OMAPRPC: failed to idr_get_new: %d\n", ret); return ret; } - /* look for an already created rpc service and use that if the minor - number matches */ + /* + * look for an already created rpc service + * and use that if the minor number matches + */ list_for_each_entry(tmp, &omaprpc_services_list, list) { if (tmp->minor == minor) { rpcserv = tmp; @@ -973,9 +1034,11 @@ again: /* SMP systems could race device probes */ goto rem_idr; } - /* Replace the pointer for the minor number, it shouldn't have existed - (or was associated with NULL previously) so this is really an - assignment */ + /* + * Replace the pointer for the minor number, it shouldn't have existed + * (or was associated with NULL previously) so this is really an + * assignment + */ spin_lock(&omaprpc_services_lock); idr_replace(&omaprpc_services, rpcserv, minor); spin_unlock(&omaprpc_services_lock); @@ -1009,7 +1072,7 @@ again: /* SMP systems could race device probes */ ret = omaprpc_device_create(rpdev); if (ret) { OMAPRPC_ERR(&rpdev->dev, - "OMAPRPC: failed to query channel info: %d\n", ret); + "OMAPRPC: failed to query channel info: %d\n", ret); goto clean_cdev; } @@ -1018,16 +1081,18 @@ serv_up: rpcserv->minor = minor; rpcserv->state = OMAPRPC_SERVICE_STATE_UP; - /* Associate the service with the sysfs entry, this will be allow - container_of to get the service pointer */ + /* + * Associate the service with the sysfs + * entry, this will be allow container_of to get the service pointer + */ dev_set_drvdata(&rpdev->dev, rpcserv); /* Signal that the driver setup is complete */ complete_all(&rpcserv->comp); - OMAPRPC_INFO(&rpdev->dev, - "OMAPRPC: new RPC connection srv channel: %u -> %u!\n", - rpdev->src, rpdev->dst); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, &rpdev->dev, + "OMAPRPC: new RPC connection srv channel: %u -> %u!\n", + rpdev->src, rpdev->dst); return 0; clean_cdev: @@ -1056,9 +1121,9 @@ static void __devexit omaprpc_remove(struct rpmsg_channel *rpdev) return; } - OMAPRPC_INFO(rpcserv->dev, - "OMAPRPC: removing rpmsg omaprpc driver %u.%u\n", - major, rpcserv->minor); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpcserv->dev, + "OMAPRPC: removing rpmsg omaprpc driver %u.%u\n", + major, rpcserv->minor); spin_lock(&omaprpc_services_lock); idr_remove(&omaprpc_services, rpcserv->minor); @@ -1072,8 +1137,8 @@ static void __devexit omaprpc_remove(struct rpmsg_channel *rpdev) cdev_del(&rpcserv->cdev); list_del(&rpcserv->list); mutex_unlock(&rpcserv->lock); - OMAPRPC_INFO(&rpdev->dev, - "OMAPRPC: no instances, removed driver!\n"); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, &rpdev->dev, + "OMAPRPC: no instances, removed driver!\n"); kfree(rpcserv); return; } @@ -1086,31 +1151,30 @@ static void __devexit omaprpc_remove(struct rpmsg_channel *rpdev) init_completion(&rpcserv->comp); rpcserv->state = OMAPRPC_SERVICE_STATE_DOWN; list_for_each_entry(rpc, &rpcserv->instance_list, list) { - OMAPRPC_INFO(rpcserv->dev, "Instance %p in state %d\n", - rpc, rpc->state); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpcserv->dev, + "Instance %p in state %d\n", rpc, rpc->state); /* set rpc instance to fault state */ rpc->state = OMAPRPC_STATE_FAULT; /* complete any on-going transactions */ if ((rpc->state == OMAPRPC_STATE_CONNECTED || - rpc->state == OMAPRPC_STATE_DISCONNECTED) && - rpc->transisioning) { - /* we were in the middle of connecting or - disconnecting */ + rpc->state == OMAPRPC_STATE_DISCONNECTED) && + rpc->transisioning) { + /* + * we were in the middle of + * connecting or disconnecting + */ complete_all(&rpc->reply_arrived); } /* wake up anyone waiting on a read */ wake_up_interruptible(&rpc->readq); } mutex_unlock(&rpcserv->lock); - OMAPRPC_INFO(&rpdev->dev, - "OMAPRPC: removed rpmsg omaprpc driver.\n"); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, &rpdev->dev, + "OMAPRPC: removed rpmsg omaprpc driver.\n"); } static void omaprpc_driver_cb(struct rpmsg_channel *rpdev, - void *data, - int len, - void *priv, - u32 src) + void *data, int len, void *priv, u32 src) { struct omaprpc_service_t *rpcserv = dev_get_drvdata(&rpdev->dev); @@ -1118,6 +1182,7 @@ static void omaprpc_driver_cb(struct rpmsg_channel *rpdev, struct omaprpc_channel_info_t *info; char *buf = (char *)data; u32 expected = 0; + int major = 0; expected = sizeof(struct omaprpc_msg_header_t); switch (hdr->msg_type) { @@ -1127,7 +1192,7 @@ static void omaprpc_driver_cb(struct rpmsg_channel *rpdev, } if (len < expected) { - dev_err(&rpdev->dev, + OMAPRPC_ERR(&rpdev->dev, "OMAPRPC driver: truncated message detected! " "Was %u bytes long, expected %u\n", len, expected); return; @@ -1135,61 +1200,72 @@ static void omaprpc_driver_cb(struct rpmsg_channel *rpdev, switch (hdr->msg_type) { case OMAPRPC_MSG_CHAN_INFO: - { - int major = MAJOR(omaprpc_dev); + major = MAJOR(omaprpc_dev); info = OMAPRPC_PAYLOAD(buf, omaprpc_channel_info_t); info->name[sizeof(info->name) - 1] = '\0'; if (rpcserv->dev) { OMAPRPC_ERR(&rpdev->dev, - "OMAPRPC: device already created!\n"); + "OMAPRPC: device already created!\n"); break; } - OMAPRPC_INFO(&rpdev->dev, - "OMAPRPC: creating device: %s\n", info->name); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, &rpdev->dev, + "OMAPRPC: creating device: %s\n", + info->name); /* Create the /dev sysfs entry */ rpcserv->dev = device_create(omaprpc_class, &rpdev->dev, - MKDEV(major, rpcserv->minor), - NULL, - info->name); + MKDEV(major, + rpcserv->minor), + NULL, info->name); if (IS_ERR(rpcserv->dev)) { int ret = PTR_ERR(rpcserv->dev); dev_err(&rpdev->dev, "OMAPRPC: device_create failed: %d\n", ret); - /* @TODO is this cleanup enough? At this point probe has - succeded */ + /* TODO: + * is this cleanup enough? + * At this point probe has succeded + */ /* - * Failed to create sysfs entry, delete character device + * Failed to create sysfs entry, delete + * character device */ cdev_del(&rpcserv->cdev); dev_set_drvdata(&rpdev->dev, NULL); - /* Remove the minor number from our integer ID pool */ + /* + * Remove the minor number from our integer + * ID pool + */ spin_lock(&omaprpc_services_lock); idr_remove(&omaprpc_services, rpcserv->minor); spin_unlock(&omaprpc_services_lock); - /* Delete the allocated memory for the service */ + /* Delete the allocated memory for the service + */ kfree(rpcserv); } break; - } + default: + OMAPRPC_ERR(&rpdev->dev, "OMAPRPC: Unrecognized code %u\n", + hdr->msg_type); + break; } } static struct rpmsg_device_id omaprpc_id_table[] = { - { .name = "omaprpc" }, - { }, + {.name = "omaprpc"}, + {}, }; + MODULE_DEVICE_TABLE(rpmsg, omaprpc_id_table); static struct rpmsg_driver omaprpc_driver = { - .drv.name = KBUILD_MODNAME, - .drv.owner = THIS_MODULE, - .id_table = omaprpc_id_table, - .probe = omaprpc_probe, - .remove = __devexit_p(omaprpc_remove), - .callback = omaprpc_driver_cb, + .drv.name = KBUILD_MODNAME, + .drv.owner = THIS_MODULE, + .id_table = omaprpc_id_table, + .probe = omaprpc_probe, + .remove = __devexit_p(omaprpc_remove), + .callback = omaprpc_driver_cb, }; static int __init omaprpc_init(void) @@ -1197,7 +1273,7 @@ static int __init omaprpc_init(void) int ret; ret = alloc_chrdev_region(&omaprpc_dev, 0, OMAPRPC_CORE_REMOTE_MAX, - KBUILD_MODNAME); + KBUILD_MODNAME); if (ret) { pr_err("OMAPRPC: alloc_chrdev_region failed: %d\n", ret); return ret; @@ -1211,13 +1287,15 @@ static int __init omaprpc_init(void) } ret = register_rpmsg_driver(&omaprpc_driver); - pr_err("OMAPRPC: Registration of OMAPRPC rpmsg service returned %d!\n", - ret); + pr_err("OMAPRPC: Registration of OMAPRPC rpmsg service returned %d! ", + ret); + pr_err("OMAPRPC: debug=%d\n", omaprpc_debug); return ret; unreg_region: unregister_chrdev_region(omaprpc_dev, OMAPRPC_CORE_REMOTE_MAX); return ret; } + module_init(omaprpc_init); static void __exit omaprpc_fini(void) @@ -1235,10 +1313,10 @@ static void __exit omaprpc_fini(void) class_destroy(omaprpc_class); unregister_chrdev_region(omaprpc_dev, OMAPRPC_CORE_REMOTE_MAX); } + module_exit(omaprpc_fini); MODULE_AUTHOR("Erik Rainey <erik.rainey@ti.com>"); MODULE_DESCRIPTION("OMAP Remote Procedure Call Driver"); MODULE_ALIAS("rpmsg:omaprpc"); MODULE_LICENSE("GPL v2"); - diff --git a/drivers/rpmsg/omaprpc/omap_rpc_dmabuf.c b/drivers/rpmsg/omaprpc/omap_rpc_dmabuf.c new file mode 100644 index 0000000..7f2a79f --- /dev/null +++ b/drivers/rpmsg/omaprpc/omap_rpc_dmabuf.c @@ -0,0 +1,449 @@ +/* + * OMAP Remote Procedure Call Driver. + * + * Copyright(c) 2012 Texas Instruments. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "omap_rpc_internal.h" + +static void omaprpc_dma_clear(struct omaprpc_instance_t *rpc) +{ + struct dma_info_t *pos, *n; + mutex_lock(&rpc->lock); + list_for_each_entry_safe(pos, n, &rpc->dma_list, list) { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "Removing Pinning for FD %u\n", pos->fd); + list_del((struct list_head *)pos); + dma_buf_unmap_attachment(pos->attach, pos->sgt, + DMA_BIDIRECTIONAL); + dma_buf_detach(pos->dbuf, pos->attach); + dma_buf_put(pos->dbuf); + kfree(pos); + } + mutex_unlock(&rpc->lock); + return; +} + +static int omaprpc_dma_add(struct omaprpc_instance_t *rpc, + struct dma_info_t *dma) +{ + if (dma) { + mutex_lock(&rpc->lock); + list_add(&dma->list, &rpc->dma_list); + mutex_unlock(&rpc->lock); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, + "Added FD %u to list", dma->fd); + } + return 0; +} + +static phys_addr_t omaprpc_pin_buffer(struct omaprpc_instance_t *rpc, + void *reserved) +{ + struct dma_info_t *dma = kmalloc(sizeof(struct dma_info_t), GFP_KERNEL); + if (dma == NULL) + return 0; + + dma->fd = (int)reserved; + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, "Pining with FD %u\n", dma->fd); + dma->dbuf = dma_buf_get((int)reserved); + if (!(IS_ERR(dma->dbuf))) { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, "DMA_BUF=%p\n", dma->dbuf); + dma->attach = dma_buf_attach(dma->dbuf, rpc->rpcserv->dev); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, "attach=%p\n", dma->attach); + dma->sgt = dma_buf_map_attachment(dma->attach, + DMA_BIDIRECTIONAL); + omaprpc_dma_add(rpc, dma); + return sg_dma_address(dma->sgt->sgl); + } else + kfree(dma); + return 0; +} + +static phys_addr_t omaprpc_dma_find(struct omaprpc_instance_t *rpc, + void *reserved) +{ + phys_addr_t addr = 0; + struct list_head *pos = NULL; + struct dma_info_t *node = NULL; + int fd = (int)reserved; + mutex_lock(&rpc->lock); + list_for_each(pos, &rpc->dma_list) { + node = (struct dma_info_t *)pos; + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "Looking for FD %u, found FD %u\n", fd, node->fd); + if (node->fd == fd) { + addr = sg_dma_address(node->sgt->sgl); + break; + } + } + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "Returning Addr %p for FD %u\n", (void *)addr, fd); + mutex_unlock(&rpc->lock); + return addr; +} + +phys_addr_t omaprpc_buffer_lookup(struct omaprpc_instance_t *rpc, + uint32_t core, + virt_addr_t uva, + virt_addr_t buva, + void *reserved) +{ + phys_addr_t lpa = 0, rpa = 0; + /* User VA - Base User VA = User Offset assuming not tiler 2D */ + /* For Tiler2D offset is corrected later */ + long uoff = uva - buva; + + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "CORE=%u BUVA=%p UVA=%p Uoff=%ld [0x%016lx] Hdl=%p\n", + core, (void *)buva, (void *)uva, uoff, (ulong) uoff, + reserved); + + if (uoff < 0) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Offsets calculation for BUVA=%p from UVA=%p is a " + "negative number. Bad parameters!\n", + (void *)buva, (void *)uva); + rpa = 0; + } else { + /* find the base of the dma buf from the list */ + lpa = omaprpc_dma_find(rpc, reserved); + if (lpa == 0) { + /* wasn't in the list, convert the pointer */ + lpa = omaprpc_pin_buffer(rpc, reserved); + } + + /* recalculate the offset in the user buffer + (accounts for tiler 2D) */ + uoff = omaprpc_recalc_off(lpa, uoff); + + /* offset the lpa by the offset in the user buffer */ + lpa += uoff; + + /* convert the local physical address to remote physical + address */ + rpa = rpmsg_local_to_remote_pa(core, lpa); + } + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "ARM VA %p == ARM PA %p => REMOTE[%u] PA %p (RESV %p)\n", + (void *)uva, (void *)lpa, core, (void *)rpa, reserved); + return rpa; +} + +int omaprpc_xlate_buffers(struct omaprpc_instance_t *rpc, + struct omaprpc_call_function_t *function, + int direction) +{ + int idx = 0, start = 0, inc = 1, limit = 0, ret = 0; + uint32_t ptr_idx = 0, pri_offset = 0, sec_offset = 0, pg_offset = 0, + size = 0; + + /* @NOTE not all the parameters are pointers so this may be sparse */ + uint8_t *base_ptrs[OMAPRPC_MAX_PARAMETERS]; + struct dma_buf *dbufs[OMAPRPC_MAX_PARAMETERS]; + + if (function->num_translations == 0) + return 0; + + limit = function->num_translations; + memset(base_ptrs, 0, sizeof(base_ptrs)); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "Operating on %d pointers\n", function->num_translations); + /* we may have a failure during translation, in which case we need to + unwind the whole operation from here */ + + for (idx = start; idx != limit; idx += inc) { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "#### Starting Translation %d of %d by %d\n", + idx, limit, inc); + /* conveinence variables */ + ptr_idx = function->translations[idx].index; + sec_offset = function->translations[idx].offset; + + /* if the pointer index for this translation is invalid */ + if (ptr_idx >= OMAPRPC_MAX_PARAMETERS) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Invalid parameter pointer index %u\n", + ptr_idx); + goto unwind; + } else if (function->params[ptr_idx].type != + OMAPRPC_PARAM_TYPE_PTR) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Parameter index %u is not a pointer " + "(type %u)\n", + ptr_idx, function->params[ptr_idx].type); + goto unwind; + } + + size = function->params[ptr_idx].size; + + if (sec_offset >= (size - sizeof(virt_addr_t))) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Offset is larger than data area! " + "(sec_offset=%u size=%u)\n", sec_offset, + size); + goto unwind; + } + + if (function->params[ptr_idx].data == 0) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Supplied user pointer is NULL!\n"); + goto unwind; + } + + /* if the KVA pointer has not been mapped */ + if (base_ptrs[ptr_idx] == NULL) { + size_t start = (pri_offset + sec_offset) & PAGE_MASK; + size_t end = PAGE_SIZE; + int ret = 0; + + /* compute the secondary offset */ + pri_offset = function->params[ptr_idx].data - + function->params[ptr_idx].base; + + /* acquire a handle to the dma buf */ + dbufs[ptr_idx] = dma_buf_get((int)function-> + params[ptr_idx].reserved); + + /* map the dma buf into cpu memory? */ + ret = dma_buf_begin_cpu_access(dbufs[ptr_idx], + start, + end, DMA_BIDIRECTIONAL); + if (ret < 0) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "OMAPRPC: Failed to acquire cpu access " + "to the DMA Buf! ret=%d\n", ret); + dma_buf_put(dbufs[ptr_idx]); + goto unwind; + } + + /* caluculate the base pointer for the region. */ + base_ptrs[ptr_idx] = dma_buf_kmap(dbufs[ptr_idx], + ((pri_offset + + sec_offset) >> + PAGE_SHIFT)); + + /* calculate the new offset within that page */ + pg_offset = + ((pri_offset + sec_offset) & (PAGE_SIZE - 1)); + + if (base_ptrs[ptr_idx] != NULL) { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, + "KMap'd base_ptr[%u]=%p dbuf=%p into " + "kernel from %zu for %zu bytes, " + "PG_OFFSET=%u\n", + ptr_idx, + base_ptrs[ptr_idx], + dbufs[ptr_idx], + start, end, pg_offset); + } + } + + /* if the KVA pointer is not NULL */ + if (base_ptrs[ptr_idx] != NULL) { + if (direction == OMAPRPC_UVA_TO_RPA) { + /* get the kernel virtual pointer to the + pointer to translate */ + virt_addr_t kva = + (virt_addr_t) & + ((base_ptrs[ptr_idx])[pg_offset]); + virt_addr_t uva = 0; + virt_addr_t buva = + (virt_addr_t) function->translations[idx]. + base; + phys_addr_t rpa = 0; + void *reserved = + (void *)function->translations[idx]. + reserved; + + /* make sure we won't cause an unalign mem + access */ + if ((kva & 0x3) > 0) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "ERROR: KVA %p is unaligned!\n", + (void *)kva); + return -EADDRNOTAVAIL; + } + /* load the user's VA */ + uva = *(virt_addr_t *) kva; + if (uva == 0) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "ERROR: Failed to access user " + "buffer to translate pointer" + "\n"); + print_hex_dump(KERN_DEBUG, + "OMAPRPC: KMAP: ", + DUMP_PREFIX_NONE, 16, 1, + base_ptrs[ptr_idx], + PAGE_SIZE, true); + goto unwind; + } + + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, + "Replacing UVA %p at KVA %p PTRIDX:%u " + "PG_OFFSET:%u IDX:%d RESV:%p\n", + (void *)uva, (void *)kva, ptr_idx, + pg_offset, idx, reserved); + + /* calc the new RPA (remote physical address) */ + rpa = omaprpc_buffer_lookup(rpc, rpc->core, + uva, buva, + reserved); + /* save the old value */ + function->translations[idx].reserved = + (size_t) uva; + /* replace with new RPA */ + *(phys_addr_t *) kva = rpa; + + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, + "Replaced UVA %p with RPA %p at KVA %p\n", + (void *)uva, (void *)rpa, + (void *)kva); + + if (rpa == 0) { + /* need to unwind all operations.. */ + direction = OMAPRPC_RPA_TO_UVA; + start = idx - 1; + inc = -1; + limit = -1; + ret = -ENODATA; + /* + * TODO: unmap the parameter + * base pointer + */ + goto restart; + } + } else if (direction == OMAPRPC_RPA_TO_UVA) { + /* address of the pointer in memory */ + virt_addr_t kva = 0; + virt_addr_t uva = 0; + phys_addr_t rpa = 0; + kva = (virt_addr_t) + &((base_ptrs[ptr_idx])[pg_offset]); + /* + * make sure we won't cause an + * unalign mem access + */ + if ((kva & 0x3) > 0) + return -EADDRNOTAVAIL; + /* get what was there for debugging */ + rpa = *(phys_addr_t *) kva; + /* convienence value of uva */ + uva = (virt_addr_t) + function->translations[idx].reserved; + /* + * replace the translated value with the + * remember version + */ + *(virt_addr_t *) kva = uva; + + /* + * TODO: DMA_BUF requires unmapping the + * data from the TILER. + */ + + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, + "Replaced RPA %p with UVA %p at KVA %p\n", + (void *)rpa, (void *)uva, + (void *)kva); + + if (uva == 0) { + /* need to unwind all operations.. */ + direction = OMAPRPC_RPA_TO_UVA; + start = idx - 1; + inc = -1; + limit = -1; + ret = -ENODATA; + /* @TODO unmap the parameter base + pointer */ + goto restart; + } + } + } else { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Failed to map UVA to KVA " + "to do translation!\n"); + /* + * we can arrive here from multiple points, but the + * action is the same from everywhere + */ +unwind: + if (direction == OMAPRPC_UVA_TO_RPA) { + /* + * we've encountered an error which needs to + * unwind all the operations + */ + OMAPRPC_ERR(rpc->rpcserv->dev, + "Unwinding UVA to RPA translations!\n"); + direction = OMAPRPC_RPA_TO_UVA; + start = idx - 1; + inc = -1; + limit = -1; + ret = -ENOBUFS; + goto restart; + } else if (direction == OMAPRPC_RPA_TO_UVA) { + /* + * there was a problem restoring the pointer, + * there's nothing to do but to continue + * processing + */ + continue; + } + } +restart: + if (base_ptrs[ptr_idx]) { + size_t start = (pri_offset + sec_offset) & PAGE_MASK; + size_t end = PAGE_SIZE; + + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "Unkmaping base_ptrs[%u]=%p from dbuf=%p %zu " + "for %zu bytes\n", + ptr_idx, + base_ptrs[ptr_idx], + dbufs[ptr_idx], start, end); + /* + * unmap the page in case this pointer needs to + * move to a different adddress + */ + dma_buf_kunmap(dbufs[ptr_idx], + ((pri_offset + + sec_offset) >> PAGE_SHIFT), + base_ptrs[ptr_idx]); + /* end access to this page */ + dma_buf_end_cpu_access(dbufs[ptr_idx], + start, end, DMA_BIDIRECTIONAL); + base_ptrs[ptr_idx] = NULL; + dma_buf_put(dbufs[ptr_idx]); + dbufs[ptr_idx] = NULL; + pg_offset = 0; + } + } + if (direction == OMAPRPC_RPA_TO_UVA) { + /* + * we're done translating everything, unpin all the translations + * and the parameters + */ + omaprpc_dma_clear(rpc); + } + return ret; +} diff --git a/drivers/staging/omaprpc/omap_rpc_internal.h b/drivers/rpmsg/omaprpc/omap_rpc_internal.h index 6e61d49..5f32c36 100644 --- a/drivers/staging/omaprpc/omap_rpc_internal.h +++ b/drivers/rpmsg/omaprpc/omap_rpc_internal.h @@ -3,31 +3,17 @@ * * Copyright(c) 2012 Texas Instruments. All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Texas Instruments nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef _OMAP_RPC_INTERNAL_H_ @@ -52,7 +38,7 @@ #if defined(CONFIG_RPMSG) || defined(CONFIG_RPMSG_MODULE) #include <linux/rpmsg.h> #else -#error "OMAP RPC requireds RPMSG" +#error "OMAP RPC requires RPMSG" #endif #if defined(CONFIG_RPC_OMAP) || defined(CONFIG_RPC_OMAP_MODULE) @@ -82,38 +68,37 @@ extern struct ion_device *omap_ion_device; #undef OMAPRPC_USE_TILER #endif -#if defined(CONFIG_DMA_SHARED_BUFFER) \ -|| defined(CONFIG_DMA_SHARED_BUFFER_MODULE) -#define OMAPRPC_USE_DMABUF -#undef OMAPRPC_USE_RPROC_LOOKUP /* genernic linux does not support yet. */ -#else -#undef OMAPRPC_USE_DMABUF -#endif - #if defined(CONFIG_ION_OMAP) || defined(CONFIG_ION_OMAP_MODULE) #define OMAPRPC_USE_ION -#define OMAPRPC_USE_RPROC_LOOKUP /* android supports this. */ +#undef OMAPRPC_USE_DMABUF +#define OMAPRPC_USE_RPROC_LOOKUP /* android supports this. */ #if defined(CONFIG_PVR_SGX) || defined(CONFIG_PVR_SGX_MODULE) #define OMAPRPC_USE_PVR #else #undef OMAPRPC_USE_PVR #endif -#else +#elif defined(CONFIG_DMA_SHARED_BUFFER) \ +|| defined(CONFIG_DMA_SHARED_BUFFER_MODULE) #undef OMAPRPC_USE_ION +#define OMAPRPC_USE_DMABUF +/* genernic linux does not support it. */ +#undef OMAPRPC_USE_RPROC_LOOKUP +#else +#error "OMAP RPC requires either ION_OMAP or DMA_SHARED_BUFFER" #endif -/* Testing and debugging defines, leave undef'd in production */ -#undef OMAPRPC_DEBUGGING -#undef OMAPRPC_VERY_VERBOSE -#undef OMAPRPC_PERF_MEASUREMENT +#define OMAPRPC_ZONE_INFO (0x1) +#define OMAPRPC_ZONE_PERF (0x2) +#define OMAPRPC_ZONE_VERBOSE (0x4) -#if defined(OMAPRPC_DEBUGGING) -#define OMAPRPC_INFO(dev, fmt, ...) dev_info(dev, fmt, ## __VA_ARGS__) -#define OMAPRPC_ERR(dev, fmt, ...) dev_err(dev, fmt, ## __VA_ARGS__) -#else -#define OMAPRPC_INFO(dev, fmt, ...) -#define OMAPRPC_ERR(dev, fmt, ...) dev_err(dev, fmt, ## __VA_ARGS__) -#endif +extern unsigned int omaprpc_debug; + +#define OMAPRPC_PRINT(flag, dev, fmt, ...) { \ + if ((flag) & omaprpc_debug) \ + dev_info((dev), (fmt), ## __VA_ARGS__); \ +} + +#define OMAPRPC_ERR(dev, fmt, ...) dev_err((dev), (fmt), ## __VA_ARGS__) #ifdef CONFIG_PHYS_ADDR_T_64BIT typedef u64 virt_addr_t; @@ -126,6 +111,10 @@ enum omaprpc_service_state_e { OMAPRPC_SERVICE_STATE_UP, }; +/** + * struct omaprpc_service_t - The per-service (endpoint) data. Contains the + * list of instances. + */ struct omaprpc_service_t { struct list_head list; struct cdev cdev; @@ -141,12 +130,19 @@ struct omaprpc_service_t { #endif }; +/** + * struct omaprpc_call_function_list_t - The list of all outstanding function + * calls in this instance. + */ struct omaprpc_call_function_list_t { struct list_head list; struct omaprpc_call_function_t *function; u16 msgId; }; +/** + * struct omaprpc_instance_t - The per-instance data structure (per user). + */ struct omaprpc_instance_t { struct list_head list; struct omaprpc_service_t *rpcserv; @@ -169,6 +165,10 @@ struct omaprpc_instance_t { }; #if defined(OMAPRPC_USE_DMABUF) +/** + * struct dma_info_t - The DMA Info structure tracks the dma_buf relevant + * variables. + */ struct dma_info_t { struct list_head list; int fd; @@ -179,13 +179,13 @@ struct dma_info_t { #endif /*! - * A Wrapper function to translate local physical addresses to the remote core + * A wrapper function to translate local physical addresses to the remote core * memory maps. Initialially we can only use an internal static table until * rproc support querying. */ #if defined(OMAPRPC_USE_RPROC_LOOKUP) phys_addr_t rpmsg_local_to_remote_pa(struct omaprpc_instance_t *rpc, - phys_addr_t pa); + phys_addr_t pa); #else phys_addr_t rpmsg_local_to_remote_pa(uint32_t core, phys_addr_t pa); #endif @@ -195,17 +195,16 @@ phys_addr_t rpmsg_local_to_remote_pa(uint32_t core, phys_addr_t pa); * structure and the translation structures. */ int omaprpc_xlate_buffers(struct omaprpc_instance_t *rpc, - struct omaprpc_call_function_t *function, - int direction); + struct omaprpc_call_function_t *function, + int direction); /*! * Converts a buffer to a remote core address. */ phys_addr_t omaprpc_buffer_lookup(struct omaprpc_instance_t *rpc, - uint32_t core, - virt_addr_t uva, - virt_addr_t buva, - void *reserved); + uint32_t core, + virt_addr_t uva, + virt_addr_t buva, void *reserved); /*! * Used to recalculate the offset of a buffer and handles cases where Tiler @@ -213,6 +212,4 @@ phys_addr_t omaprpc_buffer_lookup(struct omaprpc_instance_t *rpc, */ long omaprpc_recalc_off(phys_addr_t lpa, long uoff); - #endif - diff --git a/drivers/rpmsg/omaprpc/omap_rpc_ion.c b/drivers/rpmsg/omaprpc/omap_rpc_ion.c new file mode 100644 index 0000000..6354a4a --- /dev/null +++ b/drivers/rpmsg/omaprpc/omap_rpc_ion.c @@ -0,0 +1,382 @@ +/* + * OMAP Remote Procedure Call Driver. + * + * Copyright(c) 2012 Texas Instruments. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "omap_rpc_internal.h" + +static uint8_t *omaprpc_map_parameter(struct omaprpc_instance_t *rpc, + struct omaprpc_param_t *param) +{ + uint32_t pri_offset = 0; + uint8_t *kva = NULL; + uint8_t *bkva = NULL; + + /* calc any primary offset if present */ + pri_offset = param->data - param->base; + + bkva = (uint8_t *) ion_map_kernel(rpc->ion_client, + (struct ion_handle *)param->reserved); + + /* + * set the kernel VA equal to the base kernel + * VA plus the primary offset + */ + kva = &bkva[pri_offset]; + + /* + * in ION case, secondary offset is ignored here + * because the entire region is mapped. + */ + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "Mapped UVA:%p to KVA:%p+OFF:%08x SIZE:%08x " + "(MKVA:%p to END:%p)\n", + (void *)param->data, + (void *)kva, pri_offset, param->size, + (void *)bkva, (void *)&bkva[param->size]); + + return kva; + +} + +static void omaprpc_unmap_parameter(struct omaprpc_instance_t *rpc, + struct omaprpc_param_t *param, + uint8_t *ptr, uint32_t sec_offset) +{ + ion_unmap_kernel(rpc->ion_client, (struct ion_handle *)param->reserved); +} + +phys_addr_t omaprpc_buffer_lookup(struct omaprpc_instance_t *rpc, + uint32_t core, virt_addr_t uva, + virt_addr_t buva, void *reserved) +{ + phys_addr_t lpa = 0, rpa = 0; + /* User VA - Base User VA = User Offset assuming not tiler 2D */ + /* For Tiler2D offset is corrected later */ + long uoff = uva - buva; + + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "CORE=%u BUVA=%p UVA=%p Uoff=%ld [0x%016lx] Hdl=%p\n", + core, (void *)buva, (void *)uva, uoff, (ulong) uoff, + reserved); + + if (uoff < 0) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Offsets calculation for BUVA=%p from UVA=%p is a " + "negative number. Bad parameters!\n", + (void *)buva, (void *)uva); + rpa = 0; + goto to_end; + } + + if (reserved) { + struct ion_handle *handle; + ion_phys_addr_t paddr; + size_t len; + + /* is it an ion handle? */ + handle = (struct ion_handle *)reserved; + if (!ion_phys(rpc->ion_client, handle, &paddr, &len)) { + lpa = (phys_addr_t) paddr; + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "Handle %p is an ION Handle to ARM PA %p " + "(Uoff=%ld) (len=%zu)\n", reserved, (void *)lpa, + uoff, len); + if ((long)len < uoff) { + /* if the offset is larger than the length, + * there is a potential security issue. + */ + pr_err("Offset %ld too large, must be < %zu\n", + uoff, len); + rpa = 0; + goto to_end; + } + /* recalculate for 2d strides */ + uoff = omaprpc_recalc_off(lpa, uoff); + lpa += uoff; + goto to_va; + } else { + /* is it an pvr buffer wrapping an ion handle? */ + + /* + * TODO: need to support 2 ion handles + * per 1 pvr handle (NV12 case) + */ + struct ion_buffer *ion_buffer = NULL; + int num_handles = 1; + handle = NULL; + if (omap_ion_share_fd_to_buffers((int)reserved, + &ion_buffer, + &num_handles) < 0) { + goto to_va; + } + if (ion_buffer) { + handle = ion_import(rpc->ion_client, + ion_buffer); + } + if (handle && !ion_phys(rpc->ion_client, handle, + &paddr, &len)) { + lpa = (phys_addr_t) paddr; + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, + "FD %d is an PVR Handle to ARM PA %p " + "(Uoff=%ld)\n", (int)reserved, + (void *)lpa, uoff); + if ((long)len < uoff) { + /* if the offset is larger than the + * length there is a security issue. + */ + pr_err( + "Offset %ld too large, must be < %zu\n", + uoff, len); + rpa = 0; + goto to_end; + } + uoff = omaprpc_recalc_off(lpa, uoff); + lpa += uoff; + goto to_va; + } + /* + * TODO: need to do some buffer tracking and call + * ion_free when it is no longer being used. this + * will make sure the buffer is not freed while + * we are still using it + */ + if (handle) + ion_free(rpc->ion_client, handle); + } + } + +to_va: + /* convert the local physical address to remote physical address */ + rpa = rpmsg_local_to_remote_pa(rpc, lpa); +to_end: + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "ARM VA %p == ARM PA %p => REMOTE[%u] PA %p (RESV %p)\n", + (void *)uva, (void *)lpa, core, (void *)rpa, reserved); + return rpa; +} + +int omaprpc_xlate_buffers(struct omaprpc_instance_t *rpc, + struct omaprpc_call_function_t *function, + int direction) +{ + int idx = 0, start = 0, inc = 1, limit = 0, ret = 0; + uint32_t ptr_idx = 0, offset = 0, size = 0; + /* not all the parameters are pointers so this may be sparse */ + uint8_t *base_ptrs[OMAPRPC_MAX_PARAMETERS]; + + if (function->num_translations == 0) + return 0; + + limit = function->num_translations; + memset(base_ptrs, 0, sizeof(base_ptrs)); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, rpc->rpcserv->dev, + "Operating on %d pointers\n", function->num_translations); + /* + * we may have a failure during translation, in which case we + * need to unwind the whole operation from here + */ +restart: + for (idx = start; idx != limit; idx += inc) { + /* conveinence variables */ + ptr_idx = function->translations[idx].index; + offset = function->translations[idx].offset; + + /* if the pointer index for this translation is invalid */ + if (ptr_idx >= OMAPRPC_MAX_PARAMETERS) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Invalid parameter pointer index %u\n", + ptr_idx); + goto unwind; + } else if (function->params[ptr_idx].type != + OMAPRPC_PARAM_TYPE_PTR) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Parameter index %u is not a pointer (type %u)" + "\n", ptr_idx, + function->params[ptr_idx].type); + goto unwind; + } + + size = function->params[ptr_idx].size; + + if (offset >= (size - sizeof(virt_addr_t))) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Offset is larger than data area! " + "(offset=%u size=%u)\n", offset, size); + goto unwind; + } + + if (function->params[ptr_idx].data == 0) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Supplied user pointer is NULL!\n"); + goto unwind; + } + + /* if the KVA pointer has not been mapped */ + if (base_ptrs[ptr_idx] == NULL) { + /* + * map the UVA pointer to KVA space, the offset could + * potentially be modified due to the mapping + */ + base_ptrs[ptr_idx] = omaprpc_map_parameter(rpc, + &function-> + params + [ptr_idx]); + } + + /* if the KVA pointer is not NULL */ + if (base_ptrs[ptr_idx] != NULL) { + if (direction == OMAPRPC_UVA_TO_RPA) { + /* + * get the kernel virtual pointer to + * the pointer to translate + */ + virt_addr_t kva = (virt_addr_t) + &((base_ptrs[ptr_idx])[offset]); + virt_addr_t uva = 0; + virt_addr_t buva = (virt_addr_t) + function->translations[idx].base; + phys_addr_t rpa = 0; + void *reserved = (void *) + function->translations[idx].reserved; + + /* + * make sure we won't cause + * an unalign mem access + */ + if ((kva & 0x3) > 0) { + OMAPRPC_ERR(rpc->rpcserv->dev, + "ERROR: KVA %p is unaligned!\n", + (void *)kva); + return -EADDRNOTAVAIL; + } + /* load the user's VA */ + uva = *(virt_addr_t *) kva; + + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, + "Replacing UVA %p at KVA %p PTRIDX:%u " + "OFFSET:%u IDX:%d\n", + (void *)uva, (void *)kva, ptr_idx, + offset, idx); + + /* calc the new RPA (remote physical address) */ + rpa = omaprpc_buffer_lookup(rpc, rpc->core, + uva, buva, + reserved); + /* save the old value */ + function->translations[idx].reserved = uva; + /* replace with new RPA */ + *(phys_addr_t *) kva = rpa; + + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, + "Replaced UVA %p with RPA %p at KVA %p\n", + (void *)uva, (void *)rpa, + (void *)kva); + + if (rpa == 0) { + /* need to unwind all operations.. */ + direction = OMAPRPC_RPA_TO_UVA; + start = idx - 1; + inc = -1; + limit = -1; + ret = -ENODATA; + goto restart; + } + } else if (direction == OMAPRPC_RPA_TO_UVA) { + /* address of the pointer in memory */ + virt_addr_t kva = (virt_addr_t) & + ((base_ptrs[ptr_idx])[offset]); + virt_addr_t uva = 0; + phys_addr_t rpa = 0; + /* + * make sure we won't cause + * an unalign mem access + */ + if ((kva & 0x3) > 0) + return -EADDRNOTAVAIL; + /* get what was there for debugging */ + rpa = *(phys_addr_t *) kva; + /* convienence value of uva */ + uva = (virt_addr_t) + function->translations[idx].reserved; + /* + * replace the translated value + * with the remember version + */ + *(virt_addr_t *) kva = uva; + + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, + rpc->rpcserv->dev, + "Replaced RPA %p with UVA %p at KVA %p\n", + (void *)rpa, (void *)uva, + (void *)kva); + + if (uva == 0) { + /* need to unwind all operations.. */ + direction = OMAPRPC_RPA_TO_UVA; + start = idx - 1; + inc = -1; + limit = -1; + ret = -ENODATA; + goto restart; + } + } + } else { + OMAPRPC_ERR(rpc->rpcserv->dev, + "Failed to map UVA to KVA to do translation!" + "\n"); + /* + * we can arrive here from multiple points, + * but the action is the same from everywhere + */ +unwind: + if (direction == OMAPRPC_UVA_TO_RPA) { + /* + * we've encountered an error which + * needs to unwind all the operations + */ + OMAPRPC_ERR(rpc->rpcserv->dev, + "Unwinding UVA to RPA translations!\n"); + direction = OMAPRPC_RPA_TO_UVA; + start = idx - 1; + inc = -1; + limit = -1; + ret = -ENOBUFS; + goto restart; + } else if (direction == OMAPRPC_RPA_TO_UVA) { + /* + *there was a problem restoring the pointer, + * there's nothing to do but to continue + * processing + */ + continue; + } + } + } + /* unmap all the pointers that were mapped and not freed yet */ + for (idx = 0; idx < OMAPRPC_MAX_PARAMETERS; idx++) { + if (base_ptrs[idx]) { + omaprpc_unmap_parameter(rpc, + &function->params[idx], + base_ptrs[idx], 0); + base_ptrs[idx] = NULL; + } + } + return ret; +} diff --git a/drivers/rpmsg/omaprpc/omap_rpc_rproc.c b/drivers/rpmsg/omaprpc/omap_rpc_rproc.c new file mode 100644 index 0000000..8edf338 --- /dev/null +++ b/drivers/rpmsg/omaprpc/omap_rpc_rproc.c @@ -0,0 +1,93 @@ +/* + * OMAP Remote Procedure Call Driver. + * + * Copyright(c) 2012 Texas Instruments. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "omap_rpc_internal.h" + +#if defined(OMAPRPC_USE_RPROC_LOOKUP) + +phys_addr_t rpmsg_local_to_remote_pa(struct omaprpc_instance_t *rpc, + phys_addr_t pa) +{ + int ret; + struct rproc *rproc; + u64 da; + phys_addr_t rpa; + + if (mutex_lock_interruptible(&rpc->rpcserv->lock)) + return 0; + + rproc = rpmsg_get_rproc_handle(rpc->rpcserv->rpdev); + if (!rproc) + pr_err("error getting rproc id %p\n", + rpc->rpcserv->rpdev); + else { + ret = rproc_pa_to_da(rproc, pa, &da); + if (ret) { + pr_err("error from rproc_pa_to_da %d\n", ret); + da = 0; + } + } + /*Revisit if remote address size increases */ + rpa = (phys_addr_t) da; + + mutex_unlock(&rpc->rpcserv->lock); + return rpa; + +} + +#else + +struct remote_mmu_region_t { + phys_addr_t tiler_start; + phys_addr_t tiler_end; + phys_addr_t ion_1d_start; + phys_addr_t ion_1d_end; + phys_addr_t ion_1d_va; +}; + +static struct remote_mmu_region_t regions[OMAPRPC_CORE_REMOTE_MAX] = { + /* Tesla */ + {0x60000000, 0x80000000, 0xBA300000, 0xBFD00000, 0x88000000}, + /* SIMCOP */ + {0x60000000, 0x80000000, 0xBA300000, 0xBFD00000, 0x88000000}, + /* MCU0 */ + {0x60000000, 0x80000000, 0xBA300000, 0xBFD00000, 0x88000000}, + /* MCU1 */ + {0x60000000, 0x80000000, 0xBA300000, 0xBFD00000, 0x88000000}, + /* EVE */ + {0x60000000, 0x80000000, 0xBA300000, 0xBFD00000, 0x88000000}, +}; + +static u32 numCores = sizeof(regions) / sizeof(regions[0]); + +phys_addr_t rpmsg_local_to_remote_pa(uint32_t core, phys_addr_t pa) +{ + if (core < numCores) { + if (regions[core].tiler_start <= pa && + pa < regions[core].tiler_end) + return pa; + else if (regions[core].ion_1d_start <= pa && + pa < regions[core].ion_1d_end) + return (pa - regions[core].ion_1d_start) + + regions[core].ion_1d_va; + } + return 0; +} + +#endif + diff --git a/drivers/rpmsg/omaprpc/omap_rpc_tiler.c b/drivers/rpmsg/omaprpc/omap_rpc_tiler.c new file mode 100644 index 0000000..d36fe1e --- /dev/null +++ b/drivers/rpmsg/omaprpc/omap_rpc_tiler.c @@ -0,0 +1,59 @@ +/* + * OMAP Remote Procedure Call Driver. + * + * Copyright(c) 2012 Texas Instruments. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "omap_rpc_internal.h" + +/** + * tiler_stride_from_region() - Returns the stride value as seen by remote cores + * based on the local address given to the function. This stride value is valid + * for non-local cores only. + * @localphys: The local physical address. + **/ +static inline long tiler_stride_from_region(phys_addr_t localphys) +{ + /* + * The physical address range decoding of local addresses is as follows: + * + * 0x60000000 - 0x67FFFFFF : 8-bit region + * 0x68000000 - 0x6FFFFFFF : 16-bit region + * 0x70000000 - 0x77FFFFFF : 32-bit region + * 0x77000000 - 0x7FFFFFFF : Page mode region + */ + switch (localphys & 0xf8000000) { /* Mask out the lower bits */ + case 0x60000000: /* 8-bit */ + return 0x4000; /* 16 KB of stride */ + case 0x68000000: /* 16-bit */ + case 0x70000000: /* 32-bit */ + return 0x8000; /* 32 KB of stride */ + default: + return 0; + } +} + +/** + * omaprpc_recalc_off() - Recalculated the unsigned offset in a buffer due to + * it's location in the TILER. + * @lpa: local physical address + * @uoff: unsigned offset + */ +long omaprpc_recalc_off(phys_addr_t lpa, long uoff) +{ + long stride = tiler_stride_from_region(lpa); + return (stride != 0) ? (stride * (uoff / PAGE_SIZE)) + + (uoff & (PAGE_SIZE - 1)) : uoff; +} diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index eb6a319..8f6cae55 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -164,6 +164,4 @@ source "drivers/staging/nvec/Kconfig" source "drivers/staging/thermal_framework/Kconfig" -source "drivers/staging/omaprpc/Kconfig" - endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 3b39915..1f7892c 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -73,4 +73,3 @@ obj-$(CONFIG_DRM_PSB) += gma500/ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_THERMAL_FRAMEWORK) += thermal_framework/ -obj-$(CONFIG_RPC_OMAP) += omaprpc/ diff --git a/drivers/staging/omaprpc/Kconfig b/drivers/staging/omaprpc/Kconfig deleted file mode 100644 index 73b8043..0000000 --- a/drivers/staging/omaprpc/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ - -config RPC_OMAP - tristate "OMAP Remote Procedure Call driver" - default y - depends on RPMSG - depends on (TI_TILER && ION_OMAP) || (DMA_SHARED_BUFFER && DRM_OMAP) - depends on REMOTEPROC || REMOTE_PROC - depends on OMAP_REMOTEPROC || OMAP_REMOTE_PROC - ---help--- - An rpmsg driver that exposes the Remote Procedure Call API to - user space, in order to allow applications to distribute - remote calls to more power-efficient remote processors on OMAP4+ systems. - - If unsure, say N. - diff --git a/drivers/staging/omaprpc/Makefile b/drivers/staging/omaprpc/Makefile deleted file mode 100644 index a02ed9e..0000000 --- a/drivers/staging/omaprpc/Makefile +++ /dev/null @@ -1,17 +0,0 @@ - -obj-$(CONFIG_RPC_OMAP) += omaprpc.o -omaprpc-y := omap_rpc.o \ - omap_rpc_tiler.o \ - omap_rpc_rproc.o - -ifeq ($(CONFIG_ION_OMAP),y) -omaprpc-y += omap_rpc_ion.o -endif - -ifeq ($(CONFIG_DMA_SHARED_BUFFER),y) -omaprpc-y += omap_rpc_dmabuf.o -endif - - - - diff --git a/drivers/staging/omaprpc/omap_rpc.h b/drivers/staging/omaprpc/omap_rpc.h deleted file mode 100644 index 5a5000e..0000000 --- a/drivers/staging/omaprpc/omap_rpc.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * OMAP Remote Procedure Call Driver. - * - * Copyright(c) 2011 Texas Instruments. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Texas Instruments nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _OMAP_RPC_H_ -#define _OMAP_RPC_H_ - -#include <linux/ioctl.h> - -#if defined(CONFIG_ION_OMAP) -#include <linux/ion.h> -#endif - -#define OMAPRPC_IOC_MAGIC 'O' - -#define OMAPRPC_IOC_CREATE _IOW(OMAPRPC_IOC_MAGIC, 1, char *) -#define OMAPRPC_IOC_DESTROY _IO(OMAPRPC_IOC_MAGIC, 2) -#define OMAPRPC_IOC_IONREGISTER _IOWR(OMAPRPC_IOC_MAGIC, 3, \ - struct ion_fd_data) -#define OMAPRPC_IOC_IONUNREGISTER _IOWR(OMAPRPC_IOC_MAGIC, 4, \ - struct ion_fd_data) - -#define OMAPRPC_IOC_MAXNR (4) - -struct omaprpc_create_instance_t { - char name[48]; -}; - -struct omaprpc_channel_info_t { - char name[64]; -}; - -enum omaprpc_info_type_e { - /** The number of functions in the service instance */ - OMAPRPC_INFO_NUMFUNCS, - /** The symbol name of the function */ - OMAPRPC_INFO_FUNC_NAME, - /** The number of times a function has been called */ - OMAPRPC_INFO_NUM_CALLS, - /** The performance information releated to the function */ - OMAPRPC_INFO_FUNC_PERF, - - /** @hidden used to define the maximum info type */ - OMAPRPC_INFO_MAX -}; - -struct omaprpc_query_instance_t { - uint32_t info_type; /**< @see omaprpc_info_type_e */ - uint32_t func_index; /**< The index to querty */ -}; - -struct omaprpc_func_perf_t { - uint32_t clocks_per_sec; - uint32_t clock_cycles; -}; - -/** These core are specific to OMAP processors */ -enum omaprpc_core_e { - OMAPRPC_CORE_DSP = 0, /**< DSP Co-processor */ - OMAPRPC_CORE_SIMCOP, /**< Video/Imaging Co-processor */ - OMAPRPC_CORE_MCU0, /**< Cortex M3/M4 [0] */ - OMAPRPC_CORE_MCU1, /**< Cortex M3/M4 [1] */ - OMAPRPC_CORE_EVE, /**< Imaging Accelerator */ - OMAPRPC_CORE_REMOTE_MAX -}; - -struct omaprpc_instance_info_t { - uint32_t info_type; - uint32_t func_index; - union info { - uint32_t num_funcs; - uint32_t num_calls; - uint32_t core_index; /**< @see omaprpc_core_e */ - char func_name[64]; - struct omaprpc_func_perf_t perf; - } info; -}; - -enum omaprpc_cache_ops_e { - OMAPRPC_CACHEOP_NONE = 0, - OMAPRPC_CACHEOP_FLUSH, - OMAPRPC_CACHEOP_INVALIDATE, - - OMAPRPC_CACHEOP_MAX, -}; - -struct omaprpc_param_translation_t { - /** The parameter index which indicates which is the base pointer */ - uint32_t index; - /** The offset from the base address to the pointer to translate */ - ptrdiff_t offset; - /** The base user virtual address of the pointer to translate - (used to calc translated pointer offset). */ - size_t base; - /** The enumeration of desired cache operations for efficiency */ - uint32_t cacheOps; - /** Reserved field */ - size_t reserved; -}; - -enum omaprpc_param_e { - OMAPRPC_PARAM_TYPE_UNKNOWN = 0, - /** An atomic data type, 1 byte to architecture limit sized bytes */ - OMAPRPC_PARAM_TYPE_ATOMIC, - /** A pointer to shared memory. The reserved field must contain the - handle to the memory */ - OMAPRPC_PARAM_TYPE_PTR, - /** \hidden (Unsupported) A structure type. Will be architecure width - aligned in memory. */ - OMAPRPC_PARAM_TYPE_STRUCT, -}; - -struct omaprpc_param_t { - uint32_t type; /**< @see omaprpc_param_e */ - size_t size; /**< The size of the data */ - size_t data; /**< Either the pointer to the data or the data - itself, @see .type */ - size_t base; /**< If a pointer is in data, this is the base - pointer (if data has an offset from base). */ - size_t reserved; /**< Shared Memory Handle - (used only with pointers) */ -}; - -#define OMAPRPC_MAX_PARAMETERS (10) - -struct omaprpc_call_function_t { - /** The function to call */ - uint32_t func_index; - /** The number of parameters in the array. */ - uint32_t num_params; - /** The array of parameters */ - struct omaprpc_param_t params[OMAPRPC_MAX_PARAMETERS]; - /** The number of translations needed in the offsets array */ - uint32_t num_translations; - /** An indeterminate lenght array of offsets within payload_data to - pointers which need translation */ - struct omaprpc_param_translation_t translations[0]; -}; - -#define OMAPRPC_MAX_TRANSLATIONS (1024) - -struct omaprpc_function_return_t { - uint32_t func_index; - uint32_t status; -}; - -#ifdef __KERNEL__ - -/** The applicable types of messages that the HOST may send the SERVICE. - * (@see omx_msg_types must duplicate these for now since they went and shoved - * it so far down RCM that it's impossible to use it without this) - */ -enum omaprpc_msg_type_e { - /** Ask the ServiceMgr to create a new instance of the service. - * No secondary data is needed. */ - OMAPRPC_MSG_CREATE_INSTANCE = 0, - /** The return message from OMAPRPC_CREATE_INSTANCE, - * contains the new endpoint address in the omaprpc_instance_handle_t */ - OMAPRPC_MSG_INSTANCE_CREATED = 1, - /** Ask the Service Instance to send information about the Service */ - OMAPRPC_MSG_QUERY_INSTANCE = 2, - /** The return message from OMAPRPC_QUERY_INSTANCE, - * which contains the information about the instance */ - OMAPRPC_MSG_INSTANCE_INFO = 3, - /** Ask the Service Mgr to destroy an instance */ - OMAPRPC_MSG_DESTROY_INSTANCE = 4, - /** Ask the Service Instance to call a particular function */ - OMAPRPC_MSG_CALL_FUNCTION = 5, - /** The return message from OMAPRPC_DESTROY_INSTANCE. - * contains the old endpoint address in the omaprpc_instance_handle_t */ - OMAPRPC_MSG_INSTANCE_DESTROYED = 6, - /** Returned from either the ServiceMgr or Service Instance - * when an error occurs */ - OMAPRPC_MSG_ERROR = 7, - /** The return values from a function call */ - OMAPRPC_MSG_FUNCTION_RETURN = 8, - /** Ask Service for channel information*/ - OMAPRPC_MSG_QUERY_CHAN_INFO = 9, - /** The return message from OMAPRPC_MSG_QUERY_CHAN_INFO*/ - OMAPRPC_MSG_CHAN_INFO = 10, - - /** \hidden used to define the max msg enum, not an actual message */ - OMAPRPC_MSG_MAX -}; - -enum omaprpc_state { - /** No errors, just not initialized */ - OMAPRPC_STATE_DISCONNECTED, - /** No errors, initialized remote DVP KGM */ - OMAPRPC_STATE_CONNECTED, - /** Some error has been detected. Disconnected. */ - OMAPRPC_STATE_FAULT, - - /* \hidden Last item in enum */ - OMAPRPC_STATE_MAX -}; - -/** \brief The generic OMAPRPC message header. - * (actually a copy of omx_msg_hdr which is a copy of an RCM header) */ -struct omaprpc_msg_header_t { - uint32_t msg_type; /**< @see omaprpc_msg_type_e */ - uint32_t msg_flags; /**< Unused */ - uint32_t msg_len; /**< The length of the message data in bytes */ - uint8_t msg_data[0]; -} __packed; - -struct omaprpc_instance_handle_t { - uint32_t endpoint_address; - uint32_t status; -} __packed; - -struct omaprpc_error_t { - uint32_t endpoint_address; - uint32_t status; -} __packed; - -struct omaprpc_parameter_t { - size_t size; - size_t data; -} __packed; - -#define OMAPRPC_NUM_PARAMETERS(size) \ - (size/sizeof(struct omaprpc_parameter_t)) - -#define OMAPRPC_PAYLOAD(ptr, type) \ - ((struct type *)&(ptr)[sizeof(struct omaprpc_msg_header_t)]) - -enum _omaprpc_translation_direction_e { - OMAPRPC_UVA_TO_RPA, - OMAPRPC_RPA_TO_UVA, -}; - -#endif /* __KERNEL__ */ - -#define OMAPRPC_DESC_EXEC_SYNC (0x0100) -#define OMAPRPC_DESC_EXEC_ASYNC (0x0200) -#define OMAPRPC_DESC_SYM_ADD (0x0300) -#define OMAPRPC_DESC_SYM_IDX (0x0400) -#define OMAPRPC_DESC_CMD (0x0500) -#define OMAPRPC_DESC_TYPE_MASK (0x0F00) -#define OMAPRPC_JOBID_DISCRETE (0) -#define OMAPRPC_POOLID_DEFAULT (0x8000) - -#define OMAPRPC_SET_FXN_IDX(idx) (idx | 0x80000000) -#define OMAPRPC_FXN_MASK(idx) (idx & 0x7FFFFFFF) - -/** This is actually a frankensteined structure of RCM */ -struct omaprpc_packet_t { - uint16_t desc; /**< @see RcmClient_Packet.desc */ - uint16_t msg_id; /**< @see RcmClient_Packet.msgId */ - uint16_t pool_id; /**< @see RcmClient_Message.poolId */ - uint16_t job_id; /**< @see RcmClient_Message.jobId */ - uint32_t fxn_idx; /**< @see RcmClient_Message.fxnIdx */ - int32_t result; /**< @see RcmClient_Message.result */ - uint32_t data_size; /**< @see RcmClient_Message.data_size */ - uint8_t data[0]; /**< @see RcmClient_Message.data pointer */ -} __packed; - -#endif /* _OMAP_RPC_H_ */ diff --git a/drivers/staging/omaprpc/omap_rpc_dmabuf.c b/drivers/staging/omaprpc/omap_rpc_dmabuf.c deleted file mode 100644 index 0f0e0c6..0000000 --- a/drivers/staging/omaprpc/omap_rpc_dmabuf.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - * OMAP Remote Procedure Call Driver. - * - * Copyright(c) 2012 Texas Instruments. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Texas Instruments nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "omap_rpc_internal.h" - -static struct dma_info_t *omaprpc_dma_sub(struct omaprpc_instance_t *rpc, - int fd) -{ - struct dma_info_t *pos, *n; - mutex_lock(&rpc->lock); - list_for_each_entry_safe(pos, n, &rpc->dma_list, list) { - OMAPRPC_INFO(rpc->rpcserv->dev, - "Looking for FD %u, found FD %u\n", fd, pos->fd); - if (pos->fd == fd) { - list_del((struct list_head *)pos); - break; - } else - pos = NULL; - } - mutex_unlock(&rpc->lock); - return pos; -} - -static int omaprpc_dma_add(struct omaprpc_instance_t *rpc, - struct dma_info_t *dma) -{ - if (dma) { - mutex_lock(&rpc->lock); - list_add(&dma->list, &rpc->dma_list); - mutex_unlock(&rpc->lock); - OMAPRPC_INFO(rpc->rpcserv->dev, "Added FD %u to list", dma->fd); - } - return 0; -} - -phys_addr_t omaprpc_pin_buffer(struct omaprpc_instance_t *rpc, void *reserved) -{ - struct dma_info_t *dma = kmalloc(sizeof(struct dma_info_t), GFP_KERNEL); - if (dma == NULL) - return 0; - - dma->fd = (int)reserved; - OMAPRPC_INFO(rpc->rpcserv->dev, "Pining with FD %u\n", dma->fd); - dma->dbuf = dma_buf_get((int)reserved); - if (!(IS_ERR(dma->dbuf))) { - OMAPRPC_INFO(rpc->rpcserv->dev, "DMA_BUF=%p\n", dma->dbuf); - dma->attach = dma_buf_attach(dma->dbuf, rpc->rpcserv->dev); - OMAPRPC_INFO(rpc->rpcserv->dev, "attach=%p\n", dma->attach); - dma->sgt = dma_buf_map_attachment(dma->attach, - DMA_BIDIRECTIONAL); - omaprpc_dma_add(rpc, dma); - return sg_dma_address(dma->sgt->sgl); - } else - kfree(dma); - return 0; -} - -phys_addr_t omaprpc_dma_find(struct omaprpc_instance_t *rpc, void *reserved) -{ - phys_addr_t addr = 0; - struct list_head *pos = NULL; - struct dma_info_t *node = NULL; - int fd = (int)reserved; - mutex_lock(&rpc->lock); - list_for_each(pos, &rpc->dma_list) { - node = (struct dma_info_t *)pos; - OMAPRPC_INFO(rpc->rpcserv->dev, - "Looking for FD %u, found FD %u\n", fd, node->fd); - if (node->fd == fd) { - addr = sg_dma_address(node->sgt->sgl); - break; - } - } - OMAPRPC_INFO(rpc->rpcserv->dev, - "Returning Addr %p for FD %u\n", (void *)addr, fd); - mutex_unlock(&rpc->lock); - return addr; -} - -void omaprpc_unpin_buffer(struct omaprpc_instance_t *rpc, void *reserved) -{ - struct dma_info_t *dma = omaprpc_dma_sub(rpc, (int)reserved); - if (dma == NULL) - return; - dma_buf_unmap_attachment(dma->attach, dma->sgt, DMA_BIDIRECTIONAL); - dma_buf_detach(dma->dbuf, dma->attach); - dma_buf_put(dma->dbuf); - kfree(dma); -} - -phys_addr_t omaprpc_buffer_lookup(struct omaprpc_instance_t *rpc, - uint32_t core, - virt_addr_t uva, - virt_addr_t buva, - void *reserved) -{ - phys_addr_t lpa = 0, rpa = 0; - /* User VA - Base User VA = User Offset assuming not tiler 2D*/ - /* For Tiler2D offset is corrected later*/ - long uoff = uva - buva; - - OMAPRPC_INFO(rpc->rpcserv->dev, - "CORE=%u BUVA=%p UVA=%p Uoff=%ld [0x%016lx] Hdl=%p\n", - core, (void *)buva, (void *)uva, uoff, (ulong)uoff, reserved); - - if (uoff < 0) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Offsets calculation for BUVA=%p from UVA=%p is a " - "negative number. Bad parameters!\n", - (void *)buva, (void *)uva); - rpa = 0; - } else { - /* find the base of the dam buf from the list */ - lpa = omaprpc_dma_find(rpc, reserved); - if (lpa == 0) { - /* wasn't in the list, convert the pointer */ - lpa = omaprpc_pin_buffer(rpc, reserved); - } - - /* recalculate the offset in the user buffer - (accounts for tiler 2D) */ - uoff += omaprpc_recalc_off(lpa, uoff); - - /* offset the lpa by the offset in the user buffer */ - lpa += uoff; - - /* convert the local physical address to remote physical - address */ - rpa = rpmsg_local_to_remote_pa(core, lpa); - } - OMAPRPC_INFO(rpc->rpcserv->dev, - "ARM VA %p == ARM PA %p => REMOTE[%u] PA %p (RESV %p)\n", - (void *)uva, (void *)lpa, core, (void *)rpa, reserved); - return rpa; -} - -int omaprpc_xlate_buffers(struct omaprpc_instance_t *rpc, - struct omaprpc_call_function_t *function, - int direction) -{ - int idx = 0, start = 0, inc = 1, limit = 0, ret = 0; - uint32_t ptr_idx = 0, pri_offset = 0, sec_offset = 0, pg_offset = 0, - size = 0; - - /* @NOTE not all the parameters are pointers so this may be sparse */ - uint8_t *base_ptrs[OMAPRPC_MAX_PARAMETERS]; - struct dma_buf *dbufs[OMAPRPC_MAX_PARAMETERS]; - - if (function->num_translations == 0) - return 0; - - limit = function->num_translations; - memset(base_ptrs, 0, sizeof(base_ptrs)); - OMAPRPC_INFO(rpc->rpcserv->dev, - "Operating on %d pointers\n", function->num_translations); - /* we may have a failure during translation, in which case we need to - unwind the whole operation from here */ - - for (idx = start; idx != limit; idx += inc) { - OMAPRPC_INFO(rpc->rpcserv->dev, - "#### Starting Translation %d of %d by %d\n", - idx, limit, inc); - /* conveinence variables */ - ptr_idx = function->translations[idx].index; - sec_offset = function->translations[idx].offset; - - /* if the pointer index for this translation is invalid */ - if (ptr_idx >= OMAPRPC_MAX_PARAMETERS) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Invalid parameter pointer index %u\n", - ptr_idx); - goto unwind; - } else if (function->params[ptr_idx].type != - OMAPRPC_PARAM_TYPE_PTR) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Parameter index %u is not a pointer " - "(type %u)\n", - ptr_idx, function->params[ptr_idx].type); - goto unwind; - } - - size = function->params[ptr_idx].size; - - if (sec_offset >= (size - sizeof(virt_addr_t))) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Offset is larger than data area! " - "(sec_offset=%u size=%u)\n", sec_offset, size); - goto unwind; - } - - if (function->params[ptr_idx].data == 0) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Supplied user pointer is NULL!\n"); - goto unwind; - } - - /* if the KVA pointer has not been mapped */ - if (base_ptrs[ptr_idx] == NULL) { - size_t start = (pri_offset + sec_offset) & PAGE_MASK; - size_t end = PAGE_SIZE; - int ret = 0; - - /* compute the secondary offset */ - pri_offset = function->params[ptr_idx].data - - function->params[ptr_idx].base; - - /* acquire a handle to the dma buf */ - dbufs[ptr_idx] = dma_buf_get( - (int)function->params[ptr_idx].reserved); - - /* map the dma buf into cpu memory? */ - ret = dma_buf_begin_cpu_access(dbufs[ptr_idx], - start, - end, - DMA_BIDIRECTIONAL); - if (ret < 0) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "OMAPRPC: Failed to acquire cpu access " - "to the DMA Buf! ret=%d\n", ret); - dma_buf_put(dbufs[ptr_idx]); - goto unwind; - } - - /* caluculate the base pointer for the region. */ - base_ptrs[ptr_idx] = dma_buf_kmap(dbufs[ptr_idx], - ((pri_offset + sec_offset)>>PAGE_SHIFT)); - - /* calculate the new offset within that page */ - pg_offset = ((pri_offset + sec_offset) & (PAGE_SIZE-1)); - - if (base_ptrs[ptr_idx] != NULL) { - OMAPRPC_INFO(rpc->rpcserv->dev, - "KMap'd base_ptr[%u]=%p dbuf=%p into " - "kernel from %zu for %zu bytes, " - "PG_OFFSET=%u\n", - ptr_idx, - base_ptrs[ptr_idx], - dbufs[ptr_idx], - start, - end, - pg_offset); - } - } - - /* if the KVA pointer is not NULL */ - if (base_ptrs[ptr_idx] != NULL) { - if (direction == OMAPRPC_UVA_TO_RPA) { - /* get the kernel virtual pointer to the - pointer to translate */ - virt_addr_t kva = - (virt_addr_t)&((base_ptrs[ptr_idx])[pg_offset]); - virt_addr_t uva = 0; - virt_addr_t buva = - (virt_addr_t)function->translations[idx].base; - phys_addr_t rpa = 0; - void *reserved = - (void *)function->translations[idx].reserved; - - /* make sure we won't cause an unalign mem - access */ - if ((kva & 0x3) > 0) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "ERROR: KVA %p is unaligned!\n", - (void *)kva); - return -EADDRNOTAVAIL; - } - /* load the user's VA */ - uva = *(virt_addr_t *)kva; - if (uva == 0) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "ERROR: Failed to access user " - "buffer to translate pointer" - "\n"); - print_hex_dump(KERN_DEBUG, - "OMAPRPC: KMAP: ", - DUMP_PREFIX_NONE, 16, 1, - base_ptrs[ptr_idx], PAGE_SIZE, - true); - goto unwind; - } - - OMAPRPC_INFO(rpc->rpcserv->dev, - "Replacing UVA %p at KVA %p PTRIDX:%u " - "PG_OFFSET:%u IDX:%d RESV:%p\n", - (void *)uva, (void *)kva, ptr_idx, - pg_offset, idx, reserved); - - /* calc the new RPA (remote physical address) */ - rpa = omaprpc_buffer_lookup(rpc, rpc->core, - uva, buva, reserved); - /* save the old value */ - function->translations[idx].reserved = - (size_t)uva; - /* replace with new RPA */ - *(phys_addr_t *)kva = rpa; - - OMAPRPC_INFO(rpc->rpcserv->dev, - "Replaced UVA %p with RPA %p at KVA %p\n", - (void *)uva, (void *)rpa, (void *)kva); - - if (rpa == 0) { - /* need to unwind all operations.. */ - direction = OMAPRPC_RPA_TO_UVA; - start = idx-1; - inc = -1; - limit = -1; - ret = -ENODATA; - /* @TODO unmap the parameter base - pointer */ - goto restart; - } - } else if (direction == OMAPRPC_RPA_TO_UVA) { - /* address of the pointer in memory */ - virt_addr_t kva = 0; - virt_addr_t uva = 0; - phys_addr_t rpa = 0; - kva = (virt_addr_t) - &((base_ptrs[ptr_idx])[pg_offset]); - /* make sure we won't cause an unalign mem - access */ - if ((kva & 0x3) > 0) - return -EADDRNOTAVAIL; - /* get what was there for debugging */ - rpa = *(phys_addr_t *)kva; - /* convienence value of uva */ - uva = (virt_addr_t) - function->translations[idx].reserved; - /* replace the translated value with the - remember version */ - *(virt_addr_t *)kva = uva; - - /* @TODO DMA_BUF requires unmapping the data - from the TILER. */ - - OMAPRPC_INFO(rpc->rpcserv->dev, - "Replaced RPA %p with UVA %p at KVA %p\n", - (void *)rpa, (void *)uva, (void *)kva); - - if (uva == 0) { - /* need to unwind all operations.. */ - direction = OMAPRPC_RPA_TO_UVA; - start = idx-1; - inc = -1; - limit = -1; - ret = -ENODATA; - /* @TODO unmap the parameter base - pointer */ - goto restart; - } - } - } else { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Failed to map UVA to KVA to do translation!\n"); - /* we can arrive here from multiple points, but the - action is the same from everywhere */ -unwind: - if (direction == OMAPRPC_UVA_TO_RPA) { - /* we've encountered an error which needs to - unwind all the operations */ - OMAPRPC_ERR(rpc->rpcserv->dev, - "Unwinding UVA to RPA translations!\n"); - direction = OMAPRPC_RPA_TO_UVA; - start = idx-1; - inc = -1; - limit = -1; - ret = -ENOBUFS; - goto restart; - } else if (direction == OMAPRPC_RPA_TO_UVA) { - /* there was a problem restoring the pointer, - there's nothing to do but to continue - processing */ - continue; - } - } -restart: - if (base_ptrs[ptr_idx]) { - size_t start = (pri_offset + sec_offset) & PAGE_MASK; - size_t end = PAGE_SIZE; - - OMAPRPC_INFO(rpc->rpcserv->dev, - "Unkmaping base_ptrs[%u]=%p from dbuf=%p %zu " - "for %zu bytes\n", - ptr_idx, - base_ptrs[ptr_idx], - dbufs[ptr_idx], - start, - end); - /* unmap the page in case this pointer needs to move to - a different adddress */ - dma_buf_kunmap(dbufs[ptr_idx], - ((pri_offset + sec_offset)>>PAGE_SHIFT), - base_ptrs[ptr_idx]); - /* end access to this page */ - dma_buf_end_cpu_access(dbufs[ptr_idx], - start, - end, - DMA_BIDIRECTIONAL); - base_ptrs[ptr_idx] = NULL; - dma_buf_put(dbufs[ptr_idx]); - dbufs[ptr_idx] = NULL; - pg_offset = 0; - } - } - return ret; -} - - diff --git a/drivers/staging/omaprpc/omap_rpc_ion.c b/drivers/staging/omaprpc/omap_rpc_ion.c deleted file mode 100644 index 8c3e7fc..0000000 --- a/drivers/staging/omaprpc/omap_rpc_ion.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * OMAP Remote Procedure Call Driver. - * - * Copyright(c) 2012 Texas Instruments. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Texas Instruments nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "omap_rpc_internal.h" - -uint8_t *omaprpc_map_parameter(struct omaprpc_instance_t *rpc, - struct omaprpc_param_t *param) -{ - uint32_t pri_offset = 0; - uint8_t *kva = NULL; - uint8_t *bkva = NULL; - - /* calc any primary offset if present */ - pri_offset = param->data - param->base; - - bkva = (uint8_t *)ion_map_kernel(rpc->ion_client, - (struct ion_handle *)param->reserved); - - /* set the kernel VA equal to the base kernel VA plus the primary - offset */ - kva = &bkva[pri_offset]; - - /* in ION case, secondary offset is ignored here because the entire - region is mapped. */ - OMAPRPC_INFO(rpc->rpcserv->dev, - "Mapped UVA:%p to KVA:%p+OFF:%08x SIZE:%08x " - "(MKVA:%p to END:%p)\n", - (void *)param->data, - (void *)kva, pri_offset, param->size, - (void *)bkva, (void *)&bkva[param->size]); - - return kva; - -} - -void omaprpc_unmap_parameter(struct omaprpc_instance_t *rpc, - struct omaprpc_param_t *param, - uint8_t *ptr, - uint32_t sec_offset) -{ - ion_unmap_kernel(rpc->ion_client, (struct ion_handle *)param->reserved); -} - -phys_addr_t omaprpc_buffer_lookup(struct omaprpc_instance_t *rpc, - uint32_t core, virt_addr_t uva, - virt_addr_t buva, void *reserved) -{ - phys_addr_t lpa = 0, rpa = 0; - /* User VA - Base User VA = User Offset assuming not tiler 2D*/ - /* For Tiler2D offset is corrected later*/ - long uoff = uva - buva; - - OMAPRPC_INFO(rpc->rpcserv->dev, - "CORE=%u BUVA=%p UVA=%p Uoff=%ld [0x%016lx] Hdl=%p\n", - core, (void *)buva, (void *)uva, uoff, (ulong)uoff, reserved); - - if (uoff < 0) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Offsets calculation for BUVA=%p from UVA=%p is a " - "negative number. Bad parameters!\n", - (void *)buva, (void *)uva); - rpa = 0; - goto to_end; - } - -#if defined(OMAPRPC_USE_ION) - if (reserved) { - struct ion_handle *handle; - ion_phys_addr_t paddr; - size_t unused; - - /* is it an ion handle? */ - handle = (struct ion_handle *)reserved; - if (!ion_phys(rpc->ion_client, handle, &paddr, &unused)) { - lpa = (phys_addr_t)paddr; - OMAPRPC_INFO(rpc->rpcserv->dev, - "Handle %p is an ION Handle to ARM PA %p " - "(Uoff=%ld)\n", reserved, (void *)lpa, uoff); - uoff = omaprpc_recalc_off(lpa, uoff); - lpa += uoff; - goto to_va; - } else { - /* is it an pvr buffer wrapping an ion handle? */ - - /* @TODO need to support 2 ion handles per 1 pvr handle - (NV12 case) */ - struct ion_buffer *ion_buffer = NULL; - int num_handles = 1; - handle = NULL; - if (omap_ion_share_fd_to_buffers((int)reserved, - &ion_buffer, &num_handles) < 0) { - goto to_va; - } - if (ion_buffer) { - handle = ion_import(rpc->ion_client, - ion_buffer); - } - if (handle && !ion_phys(rpc->ion_client, handle, - &paddr, &unused)) { - lpa = (phys_addr_t)paddr; - OMAPRPC_INFO(rpc->rpcserv->dev, - "FD %d is an PVR Handle to ARM PA %p " - "(Uoff=%ld)\n", (int)reserved, - (void *)lpa, uoff); - uoff = omaprpc_recalc_off(lpa, uoff); - lpa += uoff; - goto to_va; - } - /* @TODO need to do some buffer tracking and call - * ion_free when it is no longer being used. this - * will make sure the buffer is not freed while - * we are still using it */ - if (handle) - ion_free(rpc->ion_client, handle); - } - } -#endif - - /* Ask the TILER to convert from virtual to physical */ - lpa = (phys_addr_t)tiler_virt2phys(uva); -to_va: - - /* convert the local physical address to remote physical address */ - rpa = rpmsg_local_to_remote_pa(rpc, lpa); -to_end: - OMAPRPC_INFO(rpc->rpcserv->dev, - "ARM VA %p == ARM PA %p => REMOTE[%u] PA %p (RESV %p)\n", - (void *)uva, (void *)lpa, core, (void *)rpa, reserved); - return rpa; -} - -int omaprpc_xlate_buffers(struct omaprpc_instance_t *rpc, - struct omaprpc_call_function_t *function, - int direction) -{ - int idx = 0, start = 0, inc = 1, limit = 0, ret = 0; - uint32_t ptr_idx = 0, offset = 0, size = 0; - /* @NOTE not all the parameters are pointers so this may be sparse */ - uint8_t *base_ptrs[OMAPRPC_MAX_PARAMETERS]; - - if (function->num_translations == 0) - return 0; - - limit = function->num_translations; - memset(base_ptrs, 0, sizeof(base_ptrs)); - OMAPRPC_INFO(rpc->rpcserv->dev, "Operating on %d pointers\n", - function->num_translations); - /* we may have a failure during translation, in which case we need to - unwind the whole operation from here */ -restart: - for (idx = start; idx != limit; idx += inc) { - /* conveinence variables */ - ptr_idx = function->translations[idx].index; - offset = function->translations[idx].offset; - - /* if the pointer index for this translation is invalid */ - if (ptr_idx >= OMAPRPC_MAX_PARAMETERS) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Invalid parameter pointer index %u\n", - ptr_idx); - goto unwind; - } else if (function->params[ptr_idx].type != - OMAPRPC_PARAM_TYPE_PTR) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Parameter index %u is not a pointer (type %u)" - "\n", ptr_idx, function->params[ptr_idx].type); - goto unwind; - } - - size = function->params[ptr_idx].size; - - if (offset >= (size - sizeof(virt_addr_t))) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Offset is larger than data area! " - "(offset=%u size=%u)\n", offset, size); - goto unwind; - } - - if (function->params[ptr_idx].data == 0) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Supplied user pointer is NULL!\n"); - goto unwind; - } - - /* if the KVA pointer has not been mapped */ - if (base_ptrs[ptr_idx] == NULL) { - /* map the UVA pointer to KVA space, the offset could - potentially be modified due to the mapping */ - base_ptrs[ptr_idx] = omaprpc_map_parameter(rpc, - &function->params[ptr_idx]); - } - - /* if the KVA pointer is not NULL */ - if (base_ptrs[ptr_idx] != NULL) { - if (direction == OMAPRPC_UVA_TO_RPA) { - /* get the kernel virtual pointer to the pointer - to translate */ - virt_addr_t kva = (virt_addr_t) - &((base_ptrs[ptr_idx])[offset]); - virt_addr_t uva = 0; - virt_addr_t buva = (virt_addr_t) - function->translations[idx].base; - phys_addr_t rpa = 0; - void *reserved = (void *) - function->translations[idx].reserved; - - /* make sure we won't cause an unalign mem - access */ - if ((kva & 0x3) > 0) { - OMAPRPC_ERR(rpc->rpcserv->dev, - "ERROR: KVA %p is unaligned!\n", - (void *)kva); - return -EADDRNOTAVAIL; - } - /* load the user's VA */ - uva = *(virt_addr_t *)kva; - - OMAPRPC_INFO(rpc->rpcserv->dev, - "Replacing UVA %p at KVA %p PTRIDX:%u " - "OFFSET:%u IDX:%d\n", - (void *)uva, (void *)kva, ptr_idx, - offset, idx); - - /* calc the new RPA (remote physical address) */ - rpa = omaprpc_buffer_lookup(rpc, rpc->core, - uva, buva, reserved); - /* save the old value */ - function->translations[idx].reserved = uva; - /* replace with new RPA */ - *(phys_addr_t *)kva = rpa; - - OMAPRPC_INFO(rpc->rpcserv->dev, - "Replaced UVA %p with RPA %p at KVA %p\n", - (void *)uva, (void *)rpa, (void *)kva); - - if (rpa == 0) { - /* need to unwind all operations.. */ - direction = OMAPRPC_RPA_TO_UVA; - start = idx-1; - inc = -1; - limit = -1; - ret = -ENODATA; - goto restart; - } - } else if (direction == OMAPRPC_RPA_TO_UVA) { - /* address of the pointer in memory */ - virt_addr_t kva = (virt_addr_t)& - ((base_ptrs[ptr_idx])[offset]); - virt_addr_t uva = 0; - phys_addr_t rpa = 0; - /* make sure we won't cause an unalign mem - access */ - if ((kva & 0x3) > 0) - return -EADDRNOTAVAIL; - /* get what was there for debugging */ - rpa = *(phys_addr_t *)kva; - /* convienence value of uva */ - uva = (virt_addr_t) - function->translations[idx].reserved; - /* replace the translated value with the - remember version */ - *(virt_addr_t *)kva = uva; - - OMAPRPC_INFO(rpc->rpcserv->dev, - "Replaced RPA %p with UVA %p at KVA %p", - "\n", (void *)rpa, (void *)uva, - (void *)kva); - - if (uva == 0) { - /* need to unwind all operations.. */ - direction = OMAPRPC_RPA_TO_UVA; - start = idx-1; - inc = -1; - limit = -1; - ret = -ENODATA; - goto restart; - } - } - } else { - OMAPRPC_ERR(rpc->rpcserv->dev, - "Failed to map UVA to KVA to do translation!" - "\n"); - /* we can arrive here from multiple points, but - the action is the same from everywhere */ -unwind: - if (direction == OMAPRPC_UVA_TO_RPA) { - /* we've encountered an error which needs to - unwind all the operations */ - OMAPRPC_ERR(rpc->rpcserv->dev, - "Unwinding UVA to RPA translations!\n"); - direction = OMAPRPC_RPA_TO_UVA; - start = idx-1; - inc = -1; - limit = -1; - ret = -ENOBUFS; - goto restart; - } else if (direction == OMAPRPC_RPA_TO_UVA) { - /* there was a problem restoring the pointer, - there's nothing to do but to continue - processing */ - continue; - } - } - } - /* unmap all the pointers that were mapped and not freed yet */ - for (idx = 0; idx < OMAPRPC_MAX_PARAMETERS; idx++) { - if (base_ptrs[idx]) { - omaprpc_unmap_parameter(rpc, - &function->params[idx], - base_ptrs[idx], 0); - base_ptrs[idx] = NULL; - } - } - return ret; -} - - diff --git a/drivers/staging/omaprpc/omap_rpc_rproc.c b/drivers/staging/omaprpc/omap_rpc_rproc.c deleted file mode 100644 index 33fd0aa..0000000 --- a/drivers/staging/omaprpc/omap_rpc_rproc.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * OMAP Remote Procedure Call Driver. - * - * Copyright(c) 2012 Texas Instruments. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Texas Instruments nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "omap_rpc_internal.h" - -#if defined(OMAPRPC_USE_RPROC_LOOKUP) - -phys_addr_t rpmsg_local_to_remote_pa(struct omaprpc_instance_t *rpc, - phys_addr_t pa) -{ - int ret; - struct rproc *rproc; - u64 da; - phys_addr_t rpa; - - if (mutex_lock_interruptible(&rpc->rpcserv->lock)) - return 0; - - rproc = rpmsg_get_rproc_handle(rpc->rpcserv->rpdev); - ret = rproc_pa_to_da(rproc, pa, &da); - if (ret) { - pr_err("error from rproc_pa_to_da %d\n", ret); - da = 0; - } - - /*Revisit if remote address size increases */ - rpa = (phys_addr_t)da; - - mutex_unlock(&rpc->rpcserv->lock); - return rpa; - -} - -#else - -struct remote_mmu_region_t { - phys_addr_t tiler_start; - phys_addr_t tiler_end; - phys_addr_t ion_1d_start; - phys_addr_t ion_1d_end; - phys_addr_t ion_1d_va; -} ; - -static struct remote_mmu_region_t regions[OMAPRPC_CORE_REMOTE_MAX] = { - /* Tesla */ - {0x60000000, 0x80000000, 0xBA300000, 0xBFD00000, 0x88000000}, - /* SIMCOP */ - {0x60000000, 0x80000000, 0xBA300000, 0xBFD00000, 0x88000000}, - /* MCU0 */ - {0x60000000, 0x80000000, 0xBA300000, 0xBFD00000, 0x88000000}, - /* MCU1 */ - {0x60000000, 0x80000000, 0xBA300000, 0xBFD00000, 0x88000000}, - /* EVE */ - {0x60000000, 0x80000000, 0xBA300000, 0xBFD00000, 0x88000000}, -}; -static u32 numCores = sizeof(regions)/sizeof(regions[0]); - -phys_addr_t rpmsg_local_to_remote_pa(uint32_t core, phys_addr_t pa) -{ - if (core < numCores) { - if (regions[core].tiler_start <= pa && - pa < regions[core].tiler_end) - return pa; - else if (regions[core].ion_1d_start <= pa && - pa < regions[core].ion_1d_end) - return (pa - regions[core].ion_1d_start) + - regions[core].ion_1d_va; - } - return 0; -} - -#endif - - diff --git a/drivers/staging/omaprpc/omap_rpc_tiler.c b/drivers/staging/omaprpc/omap_rpc_tiler.c deleted file mode 100644 index 8528bed..0000000 --- a/drivers/staging/omaprpc/omap_rpc_tiler.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * OMAP Remote Procedure Call Driver. - * - * Copyright(c) 2012 Texas Instruments. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Texas Instruments nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "omap_rpc_internal.h" - -static inline long tiler_stride(phys_addr_t lpa) -{ - /* - * The access mode decoding is as follows: - * - * 0x60000000 - 0x67FFFFFF : 8-bit - * 0x68000000 - 0x6FFFFFFF : 16-bit - * 0x70000000 - 0x77FFFFFF : 32-bit - * 0x77000000 - 0x7FFFFFFF : Page mode - */ - switch (lpa & 0xf8000000) { /* Mask out the lower bits */ - case 0x60000000: /* 8-bit */ - return 0x4000; /* 16 KB of stride */ - case 0x68000000: /* 16-bit */ - case 0x70000000: /* 32-bit */ - return 0x8000; /* 32 KB of stride */ - default: - return 0; - } -} - -long omaprpc_recalc_off(phys_addr_t lpa, long uoff) -{ - long stride = tiler_stride(lpa); - return (stride != 0) ? (stride*(uoff/PAGE_SIZE)) + - (uoff & (PAGE_SIZE-1)) : uoff; -} - |