Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9cd292ef authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "net: qrtr: Attempt to linearize skb for forwarding"

parents 9aac63fd 3f23e2d4
Loading
Loading
Loading
Loading
+26 −1
Original line number Diff line number Diff line
@@ -545,8 +545,13 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
	hdr->size = cpu_to_le32(len);
	hdr->confirm_rx = !!confirm_rx;

	skb_put_padto(skb, ALIGN(len, 4) + sizeof(*hdr));
	qrtr_log_tx_msg(node, hdr, skb);
	rc = skb_put_padto(skb, ALIGN(len, 4) + sizeof(*hdr));
	if (rc) {
		pr_err("%s: failed to pad size %lu to %lu rc:%d\n", __func__,
		       len, ALIGN(len, 4) + sizeof(*hdr), rc);
		return rc;
	}

	mutex_lock(&node->ep_lock);
	if (node->ep)
@@ -803,6 +808,24 @@ static struct sk_buff *qrtr_alloc_ctrl_packet(struct qrtr_ctrl_pkt **pkt)
static struct qrtr_sock *qrtr_port_lookup(int port);
static void qrtr_port_put(struct qrtr_sock *ipc);

/* Prepare skb for forwarding by allocating enough linear memory to align and
 * add the header since qrtr transports do not support fragmented skbs
 */
static void qrtr_skb_align_linearize(struct sk_buff *skb)
{
	int nhead = ALIGN(skb->len, 4) + sizeof(struct qrtr_hdr_v1);
	int rc;

	if (!skb_is_nonlinear(skb))
		return;

	rc = pskb_expand_head(skb, nhead, 0, GFP_KERNEL);
	skb_condense(skb);
	if (rc)
		pr_err("%s: failed:%d to allocate linear skb size:%d\n",
		       __func__, rc, nhead);
}

static bool qrtr_must_forward(struct qrtr_node *src,
			      struct qrtr_node *dst, u32 type)
{
@@ -833,6 +856,7 @@ static void qrtr_fwd_ctrl_pkt(struct sk_buff *skb)
	struct qrtr_node *src;
	struct qrtr_cb *cb = (struct qrtr_cb *)skb->cb;

	qrtr_skb_align_linearize(skb);
	src = qrtr_node_lookup(cb->src_node);
	down_read(&qrtr_node_lock);
	list_for_each_entry(node, &qrtr_all_epts, item) {
@@ -867,6 +891,7 @@ static void qrtr_fwd_pkt(struct sk_buff *skb, struct qrtr_cb *cb)
	struct sockaddr_qrtr to = {AF_QIPCRTR, cb->dst_node, cb->dst_port};
	struct qrtr_node *node;

	qrtr_skb_align_linearize(skb);
	node = qrtr_node_lookup(cb->dst_node);
	if (!node)
		return;