Merge "net: qrtr: Fix duplicate server announcement in qrtr"

This commit is contained in:
qctecmdr 2022-12-04 21:31:44 -08:00 committed by Gerrit - the friendly Code Review server
commit fa7e8805be
3 changed files with 54 additions and 19 deletions

View File

@ -743,15 +743,23 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
size_t len = skb->len; size_t len = skb->len;
int rc, confirm_rx; int rc, confirm_rx;
mutex_lock(&node->ep_lock);
if (!atomic_read(&node->hello_sent) && type != QRTR_TYPE_HELLO) { if (!atomic_read(&node->hello_sent) && type != QRTR_TYPE_HELLO) {
kfree_skb(skb); kfree_skb(skb);
mutex_unlock(&node->ep_lock);
return 0; return 0;
} }
if (atomic_read(&node->hello_sent) && type == QRTR_TYPE_HELLO) { if (atomic_read(&node->hello_sent) && type == QRTR_TYPE_HELLO) {
kfree_skb(skb); kfree_skb(skb);
mutex_unlock(&node->ep_lock);
return 0; return 0;
} }
if (!atomic_read(&node->hello_sent) && type == QRTR_TYPE_HELLO)
atomic_inc(&node->hello_sent);
mutex_unlock(&node->ep_lock);
/* If sk is null, this is a forwarded packet and should not wait */ /* If sk is null, this is a forwarded packet and should not wait */
if (!skb->sk) { if (!skb->sk) {
struct qrtr_cb *cb = (struct qrtr_cb *)skb->cb; struct qrtr_cb *cb = (struct qrtr_cb *)skb->cb;
@ -788,9 +796,10 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
else else
rc = skb_put_padto(skb, ALIGN(len, 4) + sizeof(*hdr)); rc = skb_put_padto(skb, ALIGN(len, 4) + sizeof(*hdr));
if (rc) if (rc) {
pr_err("%s: failed to pad size %lu to %lu rc:%d\n", __func__, pr_err("%s: failed to pad size %lu to %lu rc:%d\n", __func__,
skb->len, ALIGN(skb->len, 4), rc); skb->len, ALIGN(skb->len, 4), rc);
}
if (!rc) { if (!rc) {
mutex_lock(&node->ep_lock); mutex_lock(&node->ep_lock);
@ -805,11 +814,9 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
* confirm_rx flag if we dropped this one */ * confirm_rx flag if we dropped this one */
if (rc && confirm_rx) if (rc && confirm_rx)
qrtr_tx_flow_failed(node, to->sq_node, to->sq_port); qrtr_tx_flow_failed(node, to->sq_node, to->sq_port);
if (type == QRTR_TYPE_HELLO) { if (rc && type == QRTR_TYPE_HELLO) {
if (!rc) atomic_dec(&node->hello_sent);
atomic_inc(&node->hello_sent); kthread_queue_work(&node->kworker, &node->say_hello);
else
kthread_queue_work(&node->kworker, &node->say_hello);
} }
return rc; return rc;
@ -1391,6 +1398,7 @@ static void qrtr_fwd_del_proc(struct qrtr_node *src, unsigned int nid)
struct qrtr_node *dst; struct qrtr_node *dst;
struct sk_buff *skb; struct sk_buff *skb;
down_read(&qrtr_epts_lock);
list_for_each_entry(dst, &qrtr_all_epts, item) { list_for_each_entry(dst, &qrtr_all_epts, item) {
if (!qrtr_must_forward(src, dst, QRTR_TYPE_DEL_PROC)) if (!qrtr_must_forward(src, dst, QRTR_TYPE_DEL_PROC))
continue; continue;
@ -1408,6 +1416,7 @@ static void qrtr_fwd_del_proc(struct qrtr_node *src, unsigned int nid)
to.sq_node = dst->nid; to.sq_node = dst->nid;
qrtr_node_enqueue(dst, skb, QRTR_TYPE_DEL_PROC, &from, &to, 0); qrtr_node_enqueue(dst, skb, QRTR_TYPE_DEL_PROC, &from, &to, 0);
} }
up_read(&qrtr_epts_lock);
} }
/** /**
@ -1637,17 +1646,6 @@ static int __qrtr_bind(struct socket *sock,
qrtr_reset_ports(); qrtr_reset_ports();
spin_unlock_irqrestore(&qrtr_port_lock, flags); spin_unlock_irqrestore(&qrtr_port_lock, flags);
if (port == QRTR_PORT_CTRL) {
struct qrtr_node *node;
down_write(&qrtr_epts_lock);
list_for_each_entry(node, &qrtr_all_epts, item) {
atomic_set(&node->hello_sent, 0);
atomic_set(&node->hello_rcvd, 0);
}
up_write(&qrtr_epts_lock);
}
/* unbind previous, if any */ /* unbind previous, if any */
if (!zapped) if (!zapped)
qrtr_port_remove(ipc); qrtr_port_remove(ipc);
@ -2123,6 +2121,18 @@ static int qrtr_release(struct socket *sock)
lock_sock(sk); lock_sock(sk);
ipc = qrtr_sk(sk); ipc = qrtr_sk(sk);
if (ipc->us.sq_port == QRTR_PORT_CTRL) {
struct qrtr_node *node;
down_write(&qrtr_epts_lock);
list_for_each_entry(node, &qrtr_all_epts, item) {
atomic_set(&node->hello_sent, 0);
atomic_set(&node->hello_rcvd, 0);
}
up_write(&qrtr_epts_lock);
}
sk->sk_shutdown = SHUTDOWN_MASK; sk->sk_shutdown = SHUTDOWN_MASK;
if (!sock_flag(sk, SOCK_DEAD)) if (!sock_flag(sk, SOCK_DEAD))
sk->sk_state_change(sk); sk->sk_state_change(sk);

View File

@ -64,6 +64,7 @@ struct gunyah_pipe {
* @label: label for gunyah resources * @label: label for gunyah resources
* @tx_dbl: doorbell for tx notifications. * @tx_dbl: doorbell for tx notifications.
* @rx_dbl: doorbell for rx notifications. * @rx_dbl: doorbell for rx notifications.
* @dbl_lock: lock to prevent read races.
* @tx_pipe: TX gunyah specific info. * @tx_pipe: TX gunyah specific info.
* @rx_pipe: RX gunyah specific info. * @rx_pipe: RX gunyah specific info.
*/ */
@ -84,6 +85,8 @@ struct qrtr_gunyah_dev {
void *tx_dbl; void *tx_dbl;
void *rx_dbl; void *rx_dbl;
struct work_struct work; struct work_struct work;
/* lock to protect dbl_running */
spinlock_t dbl_lock;
struct gunyah_pipe tx_pipe; struct gunyah_pipe tx_pipe;
struct gunyah_pipe rx_pipe; struct gunyah_pipe rx_pipe;
@ -359,7 +362,11 @@ static void qrtr_gunyah_read_new(struct qrtr_gunyah_dev *qdev)
gunyah_rx_peak(&qdev->rx_pipe, &hdr, 0, hdr_len); gunyah_rx_peak(&qdev->rx_pipe, &hdr, 0, hdr_len);
pkt_len = qrtr_peek_pkt_size((void *)&hdr); pkt_len = qrtr_peek_pkt_size((void *)&hdr);
if ((int)pkt_len < 0 || pkt_len > MAX_PKT_SZ) { if ((int)pkt_len < 0 || pkt_len > MAX_PKT_SZ) {
dev_err(qdev->dev, "invalid pkt_len %zu\n", pkt_len); /* Corrupted packet, reset the pipe and discard existing data */
rx_avail = gunyah_rx_avail(&qdev->rx_pipe);
dev_err(qdev->dev, "invalid pkt_len:%zu dropping:%zu bytes\n",
pkt_len, rx_avail);
gunyah_rx_advance(&qdev->rx_pipe, rx_avail);
return; return;
} }
@ -406,6 +413,9 @@ static void qrtr_gunyah_read_frag(struct qrtr_gunyah_dev *qdev)
static void qrtr_gunyah_read(struct qrtr_gunyah_dev *qdev) static void qrtr_gunyah_read(struct qrtr_gunyah_dev *qdev)
{ {
unsigned long flags;
spin_lock_irqsave(&qdev->dbl_lock, flags);
wake_up_all(&qdev->tx_avail_notify); wake_up_all(&qdev->tx_avail_notify);
while (gunyah_rx_avail(&qdev->rx_pipe)) { while (gunyah_rx_avail(&qdev->rx_pipe)) {
@ -417,6 +427,7 @@ static void qrtr_gunyah_read(struct qrtr_gunyah_dev *qdev)
if (gunyah_get_read_notify(qdev)) if (gunyah_get_read_notify(qdev))
qrtr_gunyah_kick(qdev); qrtr_gunyah_kick(qdev);
} }
spin_unlock_irqrestore(&qdev->dbl_lock, flags);
} }
static int qrtr_gunyah_share_mem(struct qrtr_gunyah_dev *qdev, gh_vmid_t self, static int qrtr_gunyah_share_mem(struct qrtr_gunyah_dev *qdev, gh_vmid_t self,
@ -696,6 +707,8 @@ static int qrtr_gunyah_probe(struct platform_device *pdev)
if (!qdev->ring.buf) if (!qdev->ring.buf)
return -ENOMEM; return -ENOMEM;
spin_lock_init(&qdev->dbl_lock);
ret = of_property_read_u32(node, "gunyah-label", &qdev->label); ret = of_property_read_u32(node, "gunyah-label", &qdev->label);
if (ret) { if (ret) {
dev_err(qdev->dev, "failed to read label info %d\n", ret); dev_err(qdev->dev, "failed to read label info %d\n", ret);

View File

@ -50,7 +50,7 @@ static void qcom_mhi_qrtr_ul_callback(struct mhi_device *mhi_dev,
} }
/* Send data over MHI */ /* Send data over MHI */
static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb) static int __qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
{ {
struct qrtr_mhi_dev *qdev = container_of(ep, struct qrtr_mhi_dev, ep); struct qrtr_mhi_dev *qdev = container_of(ep, struct qrtr_mhi_dev, ep);
int rc; int rc;
@ -81,6 +81,18 @@ static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
return rc; return rc;
} }
static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
{
int rc;
do {
rc = __qcom_mhi_qrtr_send(ep, skb);
usleep_range(1000, 2000);
} while (rc == -EAGAIN);
return rc;
}
static void qrtr_mhi_of_parse(struct mhi_device *mhi_dev, static void qrtr_mhi_of_parse(struct mhi_device *mhi_dev,
u32 *net_id, bool *rt) u32 *net_id, bool *rt)
{ {