Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'rpmsg-v4.14' of git://github.com/andersson/remoteproc

Pull rpmsg updates from Bjorn Andersson:
"This extends the Qualcomm GLINK implementation to support the
additional features used for communicating with modem and DSP
coprocessors in modern Qualcomm platforms.

In addition to this there's support for placing virtio RPMSG buffers
in non-System RAM"

* tag 'rpmsg-v4.14' of git://github.com/andersson/remoteproc: (29 commits)
rpmsg: glink: initialize ret to zero to ensure error status check is correct
rpmsg: glink: fix null pointer dereference on a null intent
dt-bindings: soc: qcom: Extend GLINK to cover SMEM
remoteproc: qcom: adsp: Allow defining GLINK edge
rpmsg: glink: Export symbols from common code
rpmsg: glink: Release idr lock before returning on error
rpmsg: glink: Handle remote rx done command
rpmsg: glink: Request for intents when unavailable
rpmsg: glink: Use the intents passed by remote
rpmsg: glink: Receive and store the remote intent buffers
rpmsg: glink: Add announce_create ops and preallocate intents
rpmsg: glink: Add rx done command
rpmsg: glink: Make RX FIFO peak accessor to take an offset
rpmsg: glink: Use the local intents when receiving data
rpmsg: glink: Add support for TX intents
rpmsg: glink: Fix idr_lock from mutex to spinlock
rpmsg: glink: Add support for transport version negotiation
rpmsg: glink: Introduce glink smem based transport
rpmsg: glink: Do a mbox_free_channel in remove
rpmsg: glink: Return -EAGAIN when there is no FIFO space
...

+2211 -972
+4 -3
Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt
··· 63 63 64 64 65 65 = SUBNODES 66 - The adsp node may have an subnode named "smd-edge" that describes the SMD edge, 67 - channels and devices related to the ADSP. See ../soc/qcom/qcom,smd.txt for 68 - details on how to describe the SMD edge. 66 + The adsp node may have an subnode named either "smd-edge" or "glink-edge" that 67 + describes the communication edge, channels and devices related to the ADSP. 68 + See ../soc/qcom/qcom,smd.txt and ../soc/qcom/qcom,glink.txt for details on how 69 + to describe these. 69 70 70 71 71 72 = EXAMPLE
+5
Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
··· 90 90 Value type: <phandle> 91 91 Definition: reference to the reserved-memory for the region 92 92 93 + The Hexagon node may also have an subnode named either "smd-edge" or 94 + "glink-edge" that describes the communication edge, channels and devices 95 + related to the Hexagon. See ../soc/qcom/qcom,smd.txt and 96 + ../soc/qcom/qcom,glink.txt for details on how to describe these. 97 + 93 98 = EXAMPLE 94 99 The following example describes the resources needed to boot control the 95 100 Hexagon, as it is found on MSM8974 boards.
+7 -6
Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
··· 1 - Qualcomm RPM GLINK binding 1 + Qualcomm GLINK edge binding 2 2 3 - This binding describes the Qualcomm RPM GLINK, a fifo based mechanism for 4 - communication with the Resource Power Management system on various Qualcomm 5 - platforms. 3 + This binding describes a Qualcomm GLINK edge, a fifo based mechanism for 4 + communication between subsystem-pairs on various Qualcomm platforms. Two types 5 + of edges can be described by the binding; the GLINK RPM edge and a SMEM based 6 + edge. 6 7 7 8 - compatible: 8 - Usage: required 9 + Usage: required for glink-rpm 9 10 Value type: <stringlist> 10 11 Definition: must be "qcom,glink-rpm" 11 12 ··· 17 16 signal this processor about communication related events 18 17 19 18 - qcom,rpm-msg-ram: 20 - Usage: required 19 + Usage: required for glink-rpm 21 20 Value type: <prop-encoded-array> 22 21 Definition: handle to RPM message memory resource 23 22
+1
drivers/remoteproc/Kconfig
··· 92 92 depends on OF && ARCH_QCOM 93 93 depends on QCOM_SMEM 94 94 depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n) 95 + depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n 95 96 select MFD_SYSCON 96 97 select QCOM_MDT_LOADER 97 98 select QCOM_RPROC_COMMON
+3
drivers/remoteproc/qcom_adsp_pil.c
··· 72 72 void *mem_region; 73 73 size_t mem_size; 74 74 75 + struct qcom_rproc_glink glink_subdev; 75 76 struct qcom_rproc_subdev smd_subdev; 76 77 struct qcom_rproc_ssr ssr_subdev; 77 78 }; ··· 401 400 goto free_rproc; 402 401 } 403 402 403 + qcom_add_glink_subdev(rproc, &adsp->glink_subdev); 404 404 qcom_add_smd_subdev(rproc, &adsp->smd_subdev); 405 405 qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name); 406 406 ··· 424 422 qcom_smem_state_put(adsp->state); 425 423 rproc_del(adsp->rproc); 426 424 425 + qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev); 427 426 qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev); 428 427 qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); 429 428 rproc_free(adsp->rproc);
+49
drivers/remoteproc/qcom_common.c
··· 20 20 #include <linux/module.h> 21 21 #include <linux/notifier.h> 22 22 #include <linux/remoteproc.h> 23 + #include <linux/rpmsg/qcom_glink.h> 23 24 #include <linux/rpmsg/qcom_smd.h> 24 25 25 26 #include "remoteproc_internal.h" 26 27 #include "qcom_common.h" 27 28 29 + #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev) 28 30 #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev) 29 31 #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev) 30 32 ··· 50 48 return &table; 51 49 } 52 50 EXPORT_SYMBOL_GPL(qcom_mdt_find_rsc_table); 51 + 52 + static int glink_subdev_probe(struct rproc_subdev *subdev) 53 + { 54 + struct qcom_rproc_glink *glink = to_glink_subdev(subdev); 55 + 56 + glink->edge = qcom_glink_smem_register(glink->dev, glink->node); 57 + 58 + return IS_ERR(glink->edge) ? PTR_ERR(glink->edge) : 0; 59 + } 60 + 61 + static void glink_subdev_remove(struct rproc_subdev *subdev) 62 + { 63 + struct qcom_rproc_glink *glink = to_glink_subdev(subdev); 64 + 65 + qcom_glink_smem_unregister(glink->edge); 66 + glink->edge = NULL; 67 + } 68 + 69 + /** 70 + * qcom_add_glink_subdev() - try to add a GLINK subdevice to rproc 71 + * @rproc: rproc handle to parent the subdevice 72 + * @glink: reference to a GLINK subdev context 73 + */ 74 + void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink) 75 + { 76 + struct device *dev = &rproc->dev; 77 + 78 + glink->node = of_get_child_by_name(dev->parent->of_node, "glink-edge"); 79 + if (!glink->node) 80 + return; 81 + 82 + glink->dev = dev; 83 + rproc_add_subdev(rproc, &glink->subdev, glink_subdev_probe, glink_subdev_remove); 84 + } 85 + EXPORT_SYMBOL_GPL(qcom_add_glink_subdev); 86 + 87 + /** 88 + * qcom_remove_glink_subdev() - remove a GLINK subdevice from rproc 89 + * @rproc: rproc handle 90 + * @glink: reference to a GLINK subdev context 91 + */ 92 + void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink) 93 + { 94 + rproc_remove_subdev(rproc, &glink->subdev); 95 + of_node_put(glink->node); 96 + } 97 + EXPORT_SYMBOL_GPL(qcom_remove_glink_subdev); 53 98 54 99 static int smd_subdev_probe(struct rproc_subdev *subdev) 55 100 {
+11
drivers/remoteproc/qcom_common.h
··· 4 4 #include <linux/remoteproc.h> 5 5 #include "remoteproc_internal.h" 6 6 7 + struct qcom_rproc_glink { 8 + struct rproc_subdev subdev; 9 + 10 + struct device *dev; 11 + struct device_node *node; 12 + struct qcom_glink *edge; 13 + }; 14 + 7 15 struct qcom_rproc_subdev { 8 16 struct rproc_subdev subdev; 9 17 ··· 29 21 struct resource_table *qcom_mdt_find_rsc_table(struct rproc *rproc, 30 22 const struct firmware *fw, 31 23 int *tablesz); 24 + 25 + void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink); 26 + void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink); 32 27 33 28 void qcom_add_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd); 34 29 void qcom_remove_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd);
+15 -1
drivers/rpmsg/Kconfig
··· 13 13 in /dev. They make it possible for user-space programs to send and 14 14 receive rpmsg packets. 15 15 16 + config RPMSG_QCOM_GLINK_NATIVE 17 + tristate 18 + select RPMSG 19 + 16 20 config RPMSG_QCOM_GLINK_RPM 17 21 tristate "Qualcomm RPM Glink driver" 18 - select RPMSG 22 + select RPMSG_QCOM_GLINK_NATIVE 19 23 depends on HAS_IOMEM 20 24 depends on MAILBOX 21 25 help 22 26 Say y here to enable support for the GLINK RPM communication driver, 23 27 which serves as a channel for communication with the RPM in GLINK 24 28 enabled systems. 29 + 30 + config RPMSG_QCOM_GLINK_SMEM 31 + tristate "Qualcomm SMEM Glink driver" 32 + select RPMSG_QCOM_GLINK_NATIVE 33 + depends on MAILBOX 34 + depends on QCOM_SMEM 35 + help 36 + Say y here to enable support for the GLINK SMEM communication driver, 37 + which provides support for using the GLINK communication protocol 38 + over SMEM. 25 39 26 40 config RPMSG_QCOM_SMD 27 41 tristate "Qualcomm Shared Memory Driver (SMD)"
+2
drivers/rpmsg/Makefile
··· 1 1 obj-$(CONFIG_RPMSG) += rpmsg_core.o 2 2 obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o 3 3 obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o 4 + obj-$(CONFIG_RPMSG_QCOM_GLINK_NATIVE) += qcom_glink_native.o 5 + obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o 4 6 obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o 5 7 obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
+1
drivers/rpmsg/qcom_smd.c
··· 1368 1368 1369 1369 edge->dev.parent = parent; 1370 1370 edge->dev.release = qcom_smd_edge_release; 1371 + edge->dev.of_node = node; 1371 1372 edge->dev.groups = qcom_smd_edge_groups; 1372 1373 dev_set_name(&edge->dev, "%s:%s", dev_name(parent), node->name); 1373 1374 ret = device_register(&edge->dev);
+36 -11
drivers/rpmsg/virtio_rpmsg_bus.c
··· 45 45 * @rbufs: kernel address of rx buffers 46 46 * @sbufs: kernel address of tx buffers 47 47 * @num_bufs: total number of buffers for rx and tx 48 + * @buf_size: size of one rx or tx buffer 48 49 * @last_sbuf: index of last tx buffer used 49 50 * @bufs_dma: dma base addr of the buffers 50 51 * @tx_lock: protects svq, sbufs and sleepers, to allow concurrent senders. ··· 66 65 struct virtqueue *rvq, *svq; 67 66 void *rbufs, *sbufs; 68 67 unsigned int num_bufs; 68 + unsigned int buf_size; 69 69 int last_sbuf; 70 70 dma_addr_t bufs_dma; 71 71 struct mutex tx_lock; ··· 160 158 * processor. 161 159 */ 162 160 #define MAX_RPMSG_NUM_BUFS (512) 163 - #define RPMSG_BUF_SIZE (512) 161 + #define MAX_RPMSG_BUF_SIZE (512) 164 162 165 163 /* 166 164 * Local addresses are dynamically allocated on-demand. ··· 193 191 .trysendto = virtio_rpmsg_trysendto, 194 192 .trysend_offchannel = virtio_rpmsg_trysend_offchannel, 195 193 }; 194 + 195 + /** 196 + * rpmsg_sg_init - initialize scatterlist according to cpu address location 197 + * @sg: scatterlist to fill 198 + * @cpu_addr: virtual address of the buffer 199 + * @len: buffer length 200 + * 201 + * An internal function filling scatterlist according to virtual address 202 + * location (in vmalloc or in kernel). 203 + */ 204 + static void 205 + rpmsg_sg_init(struct scatterlist *sg, void *cpu_addr, unsigned int len) 206 + { 207 + if (is_vmalloc_addr(cpu_addr)) { 208 + sg_init_table(sg, 1); 209 + sg_set_page(sg, vmalloc_to_page(cpu_addr), len, 210 + offset_in_page(cpu_addr)); 211 + } else { 212 + WARN_ON(!virt_addr_valid(cpu_addr)); 213 + sg_init_one(sg, cpu_addr, len); 214 + } 215 + } 196 216 197 217 /** 198 218 * __ept_release() - deallocate an rpmsg endpoint ··· 459 435 * (half of our buffers are used for sending messages) 460 436 */ 461 437 if (vrp->last_sbuf < vrp->num_bufs / 2) 462 - ret = vrp->sbufs + RPMSG_BUF_SIZE * vrp->last_sbuf++; 438 + ret = vrp->sbufs + vrp->buf_size * vrp->last_sbuf++; 463 439 /* or recycle a used one */ 464 440 else 465 441 ret = virtqueue_get_buf(vrp->svq, &len); ··· 585 561 * messaging), or to improve the buffer allocator, to support 586 562 * variable-length buffer sizes. 587 563 */ 588 - if (len > RPMSG_BUF_SIZE - sizeof(struct rpmsg_hdr)) { 564 + if (len > vrp->buf_size - sizeof(struct rpmsg_hdr)) { 589 565 dev_err(dev, "message is too big (%d)\n", len); 590 566 return -EMSGSIZE; 591 567 } ··· 634 610 msg, sizeof(*msg) + msg->len, true); 635 611 #endif 636 612 637 - sg_init_one(&sg, msg, sizeof(*msg) + len); 613 + rpmsg_sg_init(&sg, msg, sizeof(*msg) + len); 638 614 639 615 mutex_lock(&vrp->tx_lock); 640 616 ··· 656 632 mutex_unlock(&vrp->tx_lock); 657 633 return err; 658 634 } 659 - EXPORT_SYMBOL(rpmsg_send_offchannel_raw); 660 635 661 636 static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) 662 637 { ··· 725 702 * We currently use fixed-sized buffers, so trivially sanitize 726 703 * the reported payload length. 727 704 */ 728 - if (len > RPMSG_BUF_SIZE || 705 + if (len > vrp->buf_size || 729 706 msg->len > (len - sizeof(struct rpmsg_hdr))) { 730 707 dev_warn(dev, "inbound msg too big: (%d, %d)\n", len, msg->len); 731 708 return -EINVAL; ··· 758 735 dev_warn(dev, "msg received with no recipient\n"); 759 736 760 737 /* publish the real size of the buffer */ 761 - sg_init_one(&sg, msg, RPMSG_BUF_SIZE); 738 + rpmsg_sg_init(&sg, msg, vrp->buf_size); 762 739 763 740 /* add the buffer back to the remote processor's virtqueue */ 764 741 err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, msg, GFP_KERNEL); ··· 915 892 else 916 893 vrp->num_bufs = MAX_RPMSG_NUM_BUFS; 917 894 918 - total_buf_space = vrp->num_bufs * RPMSG_BUF_SIZE; 895 + vrp->buf_size = MAX_RPMSG_BUF_SIZE; 896 + 897 + total_buf_space = vrp->num_bufs * vrp->buf_size; 919 898 920 899 /* allocate coherent memory for the buffers */ 921 900 bufs_va = dma_alloc_coherent(vdev->dev.parent->parent, ··· 940 915 /* set up the receive buffers */ 941 916 for (i = 0; i < vrp->num_bufs / 2; i++) { 942 917 struct scatterlist sg; 943 - void *cpu_addr = vrp->rbufs + i * RPMSG_BUF_SIZE; 918 + void *cpu_addr = vrp->rbufs + i * vrp->buf_size; 944 919 945 - sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE); 920 + rpmsg_sg_init(&sg, cpu_addr, vrp->buf_size); 946 921 947 922 err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, cpu_addr, 948 923 GFP_KERNEL); ··· 1007 982 static void rpmsg_remove(struct virtio_device *vdev) 1008 983 { 1009 984 struct virtproc_info *vrp = vdev->priv; 1010 - size_t total_buf_space = vrp->num_bufs * RPMSG_BUF_SIZE; 985 + size_t total_buf_space = vrp->num_bufs * vrp->buf_size; 1011 986 int ret; 1012 987 1013 988 vdev->config->reset(vdev);
+27
include/linux/rpmsg/qcom_glink.h
··· 1 + #ifndef _LINUX_RPMSG_QCOM_GLINK_H 2 + #define _LINUX_RPMSG_QCOM_GLINK_H 3 + 4 + #include <linux/device.h> 5 + 6 + struct qcom_glink; 7 + 8 + #if IS_ENABLED(CONFIG_RPMSG_QCOM_GLINK_SMEM) 9 + 10 + struct qcom_glink *qcom_glink_smem_register(struct device *parent, 11 + struct device_node *node); 12 + void qcom_glink_smem_unregister(struct qcom_glink *glink); 13 + 14 + #else 15 + 16 + static inline struct qcom_glink * 17 + qcom_glink_smem_register(struct device *parent, 18 + struct device_node *node) 19 + { 20 + return NULL; 21 + } 22 + 23 + static inline void qcom_glink_smem_unregister(struct qcom_glink *glink) {} 24 + 25 + #endif 26 + 27 + #endif