Loading Documentation/devicetree/bindings/net/qrtr-fifo-xprt.txt 0 → 100644 +25 −0 Original line number Diff line number Diff line Qualcomm Technologies, Inc. IPC Router FIFO Transport Required properties: - compatible: should be "qcom,ipcr-fifo-xprt" - reg: the irq register to raise an interrupt - interrupts: the receiving interrupt line - qcom,ipc-shm: reference to shared memory phandle Example: fifo_vipc_irq@176 { compatible = "qcom,ipcr-fifo-xprt"; reg = <0x176>; interrupts = <0x0 0x142 0x1>; qcom,ipc-shm = <&ipc-shm>; }; ipc-shm: shared-buffer@85af7000 { compatible = "qcom,hypervisor-shared-memory"; phandle = <0x1e4>; reg = <0x0 0x85af7000 0x0 0x9000>; label = "ipc_shm"; qcom,tx-is-first; }; arch/arm64/boot/dts/qcom/kona.dtsi +7 −0 Original line number Diff line number Diff line Loading @@ -3389,6 +3389,13 @@ mhi,brstmode = <2>; }; }; mhi_devices { mhi_qrtr { mhi,chan = "IPCR"; qcom,net-id = <0>; }; }; }; }; Loading drivers/soc/qcom/qmi_encdec.c +3 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2015, 2019 The Linux Foundation. All rights reserved. * Copyright (C) 2017 Linaro Ltd. */ #include <linux/slab.h> Loading Loading @@ -534,8 +534,8 @@ static int qmi_decode_string_elem(struct qmi_elem_info *ei_array, decoded_bytes += rc; } if (string_len > temp_ei->elem_len) { pr_err("%s: String len %d > Max Len %d\n", if (string_len >= temp_ei->elem_len) { pr_err("%s: String len %d >= Max Len %d\n", __func__, string_len, temp_ei->elem_len); return -ETOOSMALL; } else if (string_len > tlv_len) { Loading drivers/soc/qcom/qmi_interface.c +42 −14 Original line number Diff line number Diff line Loading @@ -347,6 +347,13 @@ int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout) ret = wait_for_completion_timeout(&txn->completion, timeout); mutex_lock(&txn->lock); if (txn->result == -ENETRESET) { mutex_unlock(&txn->lock); return txn->result; } mutex_unlock(&txn->lock); mutex_lock(&qmi->txn_lock); mutex_lock(&txn->lock); idr_remove(&qmi->txns, txn->id); Loading Loading @@ -446,17 +453,18 @@ static void qmi_handle_net_reset(struct qmi_handle *qmi) if (IS_ERR(sock)) return; mutex_lock(&qmi->sock_lock); sock_release(qmi->sock); qmi->sock = NULL; mutex_unlock(&qmi->sock_lock); qmi_recv_del_server(qmi, -1, -1); if (qmi->ops.net_reset) qmi->ops.net_reset(qmi); mutex_lock(&qmi->sock_lock); /* Already qmi_handle_release() started */ if (!qmi->sock) { sock_release(sock); return; } sock_release(qmi->sock); qmi->sock = sock; qmi->sq = sq; mutex_unlock(&qmi->sock_lock); Loading Loading @@ -570,16 +578,21 @@ static void qmi_data_ready_work(struct work_struct *work) static void qmi_data_ready(struct sock *sk) { struct qmi_handle *qmi = sk->sk_user_data; struct qmi_handle *qmi = NULL; /* * This will be NULL if we receive data while being in * qmi_handle_release() */ if (!qmi) read_lock_bh(&sk->sk_callback_lock); qmi = sk->sk_user_data; if (!qmi) { read_unlock_bh(&sk->sk_callback_lock); return; } queue_work(qmi->wq, &qmi->work); read_unlock_bh(&sk->sk_callback_lock); } static struct socket *qmi_sock_create(struct qmi_handle *qmi, Loading @@ -602,6 +615,7 @@ static struct socket *qmi_sock_create(struct qmi_handle *qmi, sock->sk->sk_user_data = qmi; sock->sk->sk_data_ready = qmi_data_ready; sock->sk->sk_error_report = qmi_data_ready; sock->sk->sk_sndtimeo = HZ * 10; return sock; } Loading Loading @@ -682,21 +696,35 @@ EXPORT_SYMBOL(qmi_handle_init); */ void qmi_handle_release(struct qmi_handle *qmi) { struct socket *sock = qmi->sock; struct socket *sock; struct qmi_service *svc, *tmp; sock->sk->sk_user_data = NULL; cancel_work_sync(&qmi->work); qmi_recv_del_server(qmi, -1, -1); struct qmi_txn *txn; int txn_id; mutex_lock(&qmi->sock_lock); sock = qmi->sock; write_lock_bh(&sock->sk->sk_callback_lock); sock->sk->sk_user_data = NULL; write_unlock_bh(&sock->sk->sk_callback_lock); sock_release(sock); qmi->sock = NULL; mutex_unlock(&qmi->sock_lock); cancel_work_sync(&qmi->work); qmi_recv_del_server(qmi, -1, -1); destroy_workqueue(qmi->wq); mutex_lock(&qmi->txn_lock); idr_for_each_entry(&qmi->txns, txn, txn_id) { mutex_lock(&txn->lock); idr_remove(&qmi->txns, txn->id); txn->result = -ENETRESET; complete(&txn->completion); mutex_unlock(&txn->lock); } mutex_unlock(&qmi->txn_lock); idr_destroy(&qmi->txns); kfree(qmi->recv_buf); Loading Loading @@ -761,7 +789,7 @@ static ssize_t qmi_send_message(struct qmi_handle *qmi, if (qmi->sock) { ret = kernel_sendmsg(qmi->sock, &msghdr, &iv, 1, len); if (ret < 0) pr_err("failed to send QMI message\n"); pr_info("failed to send QMI message %d\n", ret); } else { ret = -EPIPE; } Loading drivers/soc/qcom/smp2p.c +15 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <linux/soc/qcom/smem.h> #include <linux/soc/qcom/smem_state.h> #include <linux/spinlock.h> #include <linux/pm_wakeup.h> #include <linux/ipc_logging.h> Loading Loading @@ -160,6 +161,7 @@ struct qcom_smp2p { struct regmap *ipc_regmap; int ipc_offset; int ipc_bit; struct wakeup_source ws; struct mbox_client mbox_client; struct mbox_chan *mbox_chan; Loading Loading @@ -297,6 +299,14 @@ static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p) } } static irqreturn_t qcom_smp2p_isr(int irq, void *data) { struct qcom_smp2p *smp2p = data; __pm_stay_awake(&smp2p->ws); return IRQ_WAKE_THREAD; } /** * qcom_smp2p_intr() - interrupt handler for incoming notifications * @irq: unused Loading @@ -321,7 +331,7 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data) if (IS_ERR(in)) { dev_err(smp2p->dev, "Unable to acquire remote smp2p item\n"); return IRQ_HANDLED; goto out; } smp2p->in = in; Loading @@ -340,6 +350,8 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data) qcom_smp2p_do_ssr_ack(smp2p); } out: __pm_relax(&smp2p->ws); return IRQ_HANDLED; } Loading Loading @@ -636,12 +648,13 @@ static int qcom_smp2p_probe(struct platform_device *pdev) list_add(&entry->node, &smp2p->outbound); } } wakeup_source_init(&smp2p->ws, "smp2p"); /* Kick the outgoing edge after allocating entries */ qcom_smp2p_kick(smp2p); ret = devm_request_threaded_irq(&pdev->dev, smp2p->irq, NULL, qcom_smp2p_intr, qcom_smp2p_isr, qcom_smp2p_intr, IRQF_NO_SUSPEND | IRQF_ONESHOT, "smp2p", (void *)smp2p); if (ret) { Loading Loading
Documentation/devicetree/bindings/net/qrtr-fifo-xprt.txt 0 → 100644 +25 −0 Original line number Diff line number Diff line Qualcomm Technologies, Inc. IPC Router FIFO Transport Required properties: - compatible: should be "qcom,ipcr-fifo-xprt" - reg: the irq register to raise an interrupt - interrupts: the receiving interrupt line - qcom,ipc-shm: reference to shared memory phandle Example: fifo_vipc_irq@176 { compatible = "qcom,ipcr-fifo-xprt"; reg = <0x176>; interrupts = <0x0 0x142 0x1>; qcom,ipc-shm = <&ipc-shm>; }; ipc-shm: shared-buffer@85af7000 { compatible = "qcom,hypervisor-shared-memory"; phandle = <0x1e4>; reg = <0x0 0x85af7000 0x0 0x9000>; label = "ipc_shm"; qcom,tx-is-first; };
arch/arm64/boot/dts/qcom/kona.dtsi +7 −0 Original line number Diff line number Diff line Loading @@ -3389,6 +3389,13 @@ mhi,brstmode = <2>; }; }; mhi_devices { mhi_qrtr { mhi,chan = "IPCR"; qcom,net-id = <0>; }; }; }; }; Loading
drivers/soc/qcom/qmi_encdec.c +3 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2015, 2019 The Linux Foundation. All rights reserved. * Copyright (C) 2017 Linaro Ltd. */ #include <linux/slab.h> Loading Loading @@ -534,8 +534,8 @@ static int qmi_decode_string_elem(struct qmi_elem_info *ei_array, decoded_bytes += rc; } if (string_len > temp_ei->elem_len) { pr_err("%s: String len %d > Max Len %d\n", if (string_len >= temp_ei->elem_len) { pr_err("%s: String len %d >= Max Len %d\n", __func__, string_len, temp_ei->elem_len); return -ETOOSMALL; } else if (string_len > tlv_len) { Loading
drivers/soc/qcom/qmi_interface.c +42 −14 Original line number Diff line number Diff line Loading @@ -347,6 +347,13 @@ int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout) ret = wait_for_completion_timeout(&txn->completion, timeout); mutex_lock(&txn->lock); if (txn->result == -ENETRESET) { mutex_unlock(&txn->lock); return txn->result; } mutex_unlock(&txn->lock); mutex_lock(&qmi->txn_lock); mutex_lock(&txn->lock); idr_remove(&qmi->txns, txn->id); Loading Loading @@ -446,17 +453,18 @@ static void qmi_handle_net_reset(struct qmi_handle *qmi) if (IS_ERR(sock)) return; mutex_lock(&qmi->sock_lock); sock_release(qmi->sock); qmi->sock = NULL; mutex_unlock(&qmi->sock_lock); qmi_recv_del_server(qmi, -1, -1); if (qmi->ops.net_reset) qmi->ops.net_reset(qmi); mutex_lock(&qmi->sock_lock); /* Already qmi_handle_release() started */ if (!qmi->sock) { sock_release(sock); return; } sock_release(qmi->sock); qmi->sock = sock; qmi->sq = sq; mutex_unlock(&qmi->sock_lock); Loading Loading @@ -570,16 +578,21 @@ static void qmi_data_ready_work(struct work_struct *work) static void qmi_data_ready(struct sock *sk) { struct qmi_handle *qmi = sk->sk_user_data; struct qmi_handle *qmi = NULL; /* * This will be NULL if we receive data while being in * qmi_handle_release() */ if (!qmi) read_lock_bh(&sk->sk_callback_lock); qmi = sk->sk_user_data; if (!qmi) { read_unlock_bh(&sk->sk_callback_lock); return; } queue_work(qmi->wq, &qmi->work); read_unlock_bh(&sk->sk_callback_lock); } static struct socket *qmi_sock_create(struct qmi_handle *qmi, Loading @@ -602,6 +615,7 @@ static struct socket *qmi_sock_create(struct qmi_handle *qmi, sock->sk->sk_user_data = qmi; sock->sk->sk_data_ready = qmi_data_ready; sock->sk->sk_error_report = qmi_data_ready; sock->sk->sk_sndtimeo = HZ * 10; return sock; } Loading Loading @@ -682,21 +696,35 @@ EXPORT_SYMBOL(qmi_handle_init); */ void qmi_handle_release(struct qmi_handle *qmi) { struct socket *sock = qmi->sock; struct socket *sock; struct qmi_service *svc, *tmp; sock->sk->sk_user_data = NULL; cancel_work_sync(&qmi->work); qmi_recv_del_server(qmi, -1, -1); struct qmi_txn *txn; int txn_id; mutex_lock(&qmi->sock_lock); sock = qmi->sock; write_lock_bh(&sock->sk->sk_callback_lock); sock->sk->sk_user_data = NULL; write_unlock_bh(&sock->sk->sk_callback_lock); sock_release(sock); qmi->sock = NULL; mutex_unlock(&qmi->sock_lock); cancel_work_sync(&qmi->work); qmi_recv_del_server(qmi, -1, -1); destroy_workqueue(qmi->wq); mutex_lock(&qmi->txn_lock); idr_for_each_entry(&qmi->txns, txn, txn_id) { mutex_lock(&txn->lock); idr_remove(&qmi->txns, txn->id); txn->result = -ENETRESET; complete(&txn->completion); mutex_unlock(&txn->lock); } mutex_unlock(&qmi->txn_lock); idr_destroy(&qmi->txns); kfree(qmi->recv_buf); Loading Loading @@ -761,7 +789,7 @@ static ssize_t qmi_send_message(struct qmi_handle *qmi, if (qmi->sock) { ret = kernel_sendmsg(qmi->sock, &msghdr, &iv, 1, len); if (ret < 0) pr_err("failed to send QMI message\n"); pr_info("failed to send QMI message %d\n", ret); } else { ret = -EPIPE; } Loading
drivers/soc/qcom/smp2p.c +15 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <linux/soc/qcom/smem.h> #include <linux/soc/qcom/smem_state.h> #include <linux/spinlock.h> #include <linux/pm_wakeup.h> #include <linux/ipc_logging.h> Loading Loading @@ -160,6 +161,7 @@ struct qcom_smp2p { struct regmap *ipc_regmap; int ipc_offset; int ipc_bit; struct wakeup_source ws; struct mbox_client mbox_client; struct mbox_chan *mbox_chan; Loading Loading @@ -297,6 +299,14 @@ static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p) } } static irqreturn_t qcom_smp2p_isr(int irq, void *data) { struct qcom_smp2p *smp2p = data; __pm_stay_awake(&smp2p->ws); return IRQ_WAKE_THREAD; } /** * qcom_smp2p_intr() - interrupt handler for incoming notifications * @irq: unused Loading @@ -321,7 +331,7 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data) if (IS_ERR(in)) { dev_err(smp2p->dev, "Unable to acquire remote smp2p item\n"); return IRQ_HANDLED; goto out; } smp2p->in = in; Loading @@ -340,6 +350,8 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data) qcom_smp2p_do_ssr_ack(smp2p); } out: __pm_relax(&smp2p->ws); return IRQ_HANDLED; } Loading Loading @@ -636,12 +648,13 @@ static int qcom_smp2p_probe(struct platform_device *pdev) list_add(&entry->node, &smp2p->outbound); } } wakeup_source_init(&smp2p->ws, "smp2p"); /* Kick the outgoing edge after allocating entries */ qcom_smp2p_kick(smp2p); ret = devm_request_threaded_irq(&pdev->dev, smp2p->irq, NULL, qcom_smp2p_intr, qcom_smp2p_isr, qcom_smp2p_intr, IRQF_NO_SUSPEND | IRQF_ONESHOT, "smp2p", (void *)smp2p); if (ret) { Loading