cregit-Linux how code gets into the kernel

Release 4.14 drivers/rpmsg/qcom_glink_smem.c

Directory: drivers/rpmsg
/*
 * Copyright (c) 2016, Linaro Ltd
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only 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.
 */

#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <linux/rpmsg.h>
#include <linux/idr.h>
#include <linux/circ_buf.h>
#include <linux/soc/qcom/smem.h>
#include <linux/sizes.h>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/workqueue.h>
#include <linux/list.h>

#include <linux/delay.h>
#include <linux/rpmsg.h>
#include <linux/rpmsg/qcom_glink.h>

#include "qcom_glink_native.h"


#define FIFO_FULL_RESERVE 8

#define FIFO_ALIGNMENT 8

#define TX_BLOCKED_CMD_RESERVE 8 
/* size of struct read_notif_request */


#define SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR	478

#define SMEM_GLINK_NATIVE_XPRT_FIFO_0		479

#define SMEM_GLINK_NATIVE_XPRT_FIFO_1		480


struct glink_smem_pipe {
	
struct qcom_glink_pipe native;

	
__le32 *tail;
	
__le32 *head;

	
void *fifo;

	
int remote_pid;
};


#define to_smem_pipe(p) container_of(p, struct glink_smem_pipe, native)


static size_t glink_smem_rx_avail(struct qcom_glink_pipe *np) { struct glink_smem_pipe *pipe = to_smem_pipe(np); size_t len; void *fifo; u32 head; u32 tail; if (!pipe->fifo) { fifo = qcom_smem_get(pipe->remote_pid, SMEM_GLINK_NATIVE_XPRT_FIFO_1, &len); if (IS_ERR(fifo)) { pr_err("failed to acquire RX fifo handle: %ld\n", PTR_ERR(fifo)); return 0; } pipe->fifo = fifo; pipe->native.length = len; } head = le32_to_cpu(*pipe->head); tail = le32_to_cpu(*pipe->tail); if (head < tail) return pipe->native.length - tail + head; else return head - tail; }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson136100.00%1100.00%
Total136100.00%1100.00%


static void glink_smem_rx_peak(struct qcom_glink_pipe *np, void *data, unsigned int offset, size_t count) { struct glink_smem_pipe *pipe = to_smem_pipe(np); size_t len; u32 tail; tail = le32_to_cpu(*pipe->tail); tail += offset; if (tail >= pipe->native.length) tail -= pipe->native.length; len = min_t(size_t, count, pipe->native.length - tail); if (len) { __ioread32_copy(data, pipe->fifo + tail, len / sizeof(u32)); } if (len != count) { __ioread32_copy(data + len, pipe->fifo, (count - len) / sizeof(u32)); } }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson141100.00%2100.00%
Total141100.00%2100.00%


static void glink_smem_rx_advance(struct qcom_glink_pipe *np, size_t count) { struct glink_smem_pipe *pipe = to_smem_pipe(np); u32 tail; tail = le32_to_cpu(*pipe->tail); tail += count; if (tail > pipe->native.length) tail -= pipe->native.length; *pipe->tail = cpu_to_le32(tail); }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson69100.00%1100.00%
Total69100.00%1100.00%


static size_t glink_smem_tx_avail(struct qcom_glink_pipe *np) { struct glink_smem_pipe *pipe = to_smem_pipe(np); u32 head; u32 tail; u32 avail; head = le32_to_cpu(*pipe->head); tail = le32_to_cpu(*pipe->tail); if (tail <= head) avail = pipe->native.length - head + tail; else avail = tail - head; if (avail < (FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE)) avail = 0; else avail -= FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE; return avail; }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson99100.00%1100.00%
Total99100.00%1100.00%


static unsigned int glink_smem_tx_write_one(struct glink_smem_pipe *pipe, unsigned int head, const void *data, size_t count) { size_t len; len = min_t(size_t, count, pipe->native.length - head); if (len) memcpy(pipe->fifo + head, data, len); if (len != count) memcpy(pipe->fifo, data + len, count - len); head += count; if (head >= pipe->native.length) head -= pipe->native.length; return head; }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson107100.00%1100.00%
Total107100.00%1100.00%


static void glink_smem_tx_write(struct qcom_glink_pipe *glink_pipe, const void *hdr, size_t hlen, const void *data, size_t dlen) { struct glink_smem_pipe *pipe = to_smem_pipe(glink_pipe); unsigned int head; head = le32_to_cpu(*pipe->head); head = glink_smem_tx_write_one(pipe, head, hdr, hlen); head = glink_smem_tx_write_one(pipe, head, data, dlen); /* Ensure head is always aligned to 8 bytes */ head = ALIGN(head, 8); if (head >= pipe->native.length) head -= pipe->native.length; *pipe->head = cpu_to_le32(head); }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson115100.00%1100.00%
Total115100.00%1100.00%


static void qcom_glink_smem_release(struct device *dev) { kfree(dev); }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson16100.00%1100.00%
Total16100.00%1100.00%


struct qcom_glink *qcom_glink_smem_register(struct device *parent, struct device_node *node) { struct glink_smem_pipe *rx_pipe; struct glink_smem_pipe *tx_pipe; struct qcom_glink *glink; struct device *dev; u32 remote_pid; __le32 *descs; size_t size; int ret; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return ERR_PTR(-ENOMEM); dev->parent = parent; dev->of_node = node; dev->release = qcom_glink_smem_release; dev_set_name(dev, "%s:%s", node->parent->name, node->name); ret = device_register(dev); if (ret) { pr_err("failed to register glink edge\n"); return ERR_PTR(ret); } ret = of_property_read_u32(dev->of_node, "qcom,remote-pid", &remote_pid); if (ret) { dev_err(dev, "failed to parse qcom,remote-pid\n"); goto err_put_dev; } rx_pipe = devm_kzalloc(dev, sizeof(*rx_pipe), GFP_KERNEL); tx_pipe = devm_kzalloc(dev, sizeof(*tx_pipe), GFP_KERNEL); if (!rx_pipe || !tx_pipe) { ret = -ENOMEM; goto err_put_dev; } ret = qcom_smem_alloc(remote_pid, SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR, 32); if (ret && ret != -EEXIST) { dev_err(dev, "failed to allocate glink descriptors\n"); goto err_put_dev; } descs = qcom_smem_get(remote_pid, SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR, &size); if (IS_ERR(descs)) { dev_err(dev, "failed to acquire xprt descriptor\n"); ret = PTR_ERR(descs); goto err_put_dev; } if (size != 32) { dev_err(dev, "glink descriptor of invalid size\n"); ret = -EINVAL; goto err_put_dev; } tx_pipe->tail = &descs[0]; tx_pipe->head = &descs[1]; rx_pipe->tail = &descs[2]; rx_pipe->head = &descs[3]; ret = qcom_smem_alloc(remote_pid, SMEM_GLINK_NATIVE_XPRT_FIFO_0, SZ_16K); if (ret && ret != -EEXIST) { dev_err(dev, "failed to allocate TX fifo\n"); goto err_put_dev; } tx_pipe->fifo = qcom_smem_get(remote_pid, SMEM_GLINK_NATIVE_XPRT_FIFO_0, &tx_pipe->native.length); if (IS_ERR(tx_pipe->fifo)) { dev_err(dev, "failed to acquire TX fifo\n"); ret = PTR_ERR(tx_pipe->fifo); goto err_put_dev; } rx_pipe->native.avail = glink_smem_rx_avail; rx_pipe->native.peak = glink_smem_rx_peak; rx_pipe->native.advance = glink_smem_rx_advance; rx_pipe->remote_pid = remote_pid; tx_pipe->native.avail = glink_smem_tx_avail; tx_pipe->native.write = glink_smem_tx_write; tx_pipe->remote_pid = remote_pid; *rx_pipe->tail = 0; *tx_pipe->head = 0; glink = qcom_glink_native_probe(dev, GLINK_FEATURE_INTENT_REUSE, &rx_pipe->native, &tx_pipe->native, false); if (IS_ERR(glink)) { ret = PTR_ERR(glink); goto err_put_dev; } return glink; err_put_dev: put_device(dev); return ERR_PTR(ret); }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson54399.27%133.33%
R Sricharan40.73%266.67%
Total547100.00%3100.00%

EXPORT_SYMBOL_GPL(qcom_glink_smem_register);
void qcom_glink_smem_unregister(struct qcom_glink *glink) { qcom_glink_native_remove(glink); qcom_glink_native_unregister(glink); }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson20100.00%1100.00%
Total20100.00%1100.00%

EXPORT_SYMBOL_GPL(qcom_glink_smem_unregister); MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@linaro.org>"); MODULE_DESCRIPTION("Qualcomm GLINK SMEM driver"); MODULE_LICENSE("GPL v2");

Overall Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson139199.71%250.00%
R Sricharan40.29%250.00%
Total1395100.00%4100.00%
Directory: drivers/rpmsg
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.