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

Commit 4dd820c0 authored by Sjur Brændeland's avatar Sjur Brændeland Committed by David S. Miller
Browse files

caif: Don't resend if dev_queue_xmit fails.



If CAIF Link Layer returns an error, we no longer try to re-build the
CAIF packet and resend it. Instead, we simply return any transmission
errors to the socket client.

Signed-off-by: default avatarSjur Brændeland <sjur.brandeland@stericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 73d6ac63
Loading
Loading
Loading
Loading
+4 −17
Original line number Original line Diff line number Diff line
@@ -120,25 +120,12 @@ static int transmit(struct cflayer *layer, struct cfpkt *pkt)
{
{
	struct caif_device_entry *caifd =
	struct caif_device_entry *caifd =
	    container_of(layer, struct caif_device_entry, layer);
	    container_of(layer, struct caif_device_entry, layer);
	struct sk_buff *skb, *skb2;
	struct sk_buff *skb;
	int ret = -EINVAL;

	skb = cfpkt_tonative(pkt);
	skb = cfpkt_tonative(pkt);
	skb->dev = caifd->netdev;
	skb->dev = caifd->netdev;
	/*
	 * Don't allow SKB to be destroyed upon error, but signal resend
	 * notification to clients. We can't rely on the return value as
	 * congestion (NET_XMIT_CN) sometimes drops the packet, sometimes don't.
	 */
	if (netif_queue_stopped(caifd->netdev))
		return -EAGAIN;
	skb2 = skb_get(skb);


	ret = dev_queue_xmit(skb2);
	dev_queue_xmit(skb);

	if (!ret)
		kfree_skb(skb);
	else
		return -EAGAIN;


	return 0;
	return 0;
}
}
+3 −32
Original line number Original line Diff line number Diff line
@@ -519,43 +519,14 @@ static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk,
			int noblock, long timeo)
			int noblock, long timeo)
{
{
	struct cfpkt *pkt;
	struct cfpkt *pkt;
	int ret, loopcnt = 0;


	pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb);
	pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb);
	memset(cfpkt_info(pkt), 0, sizeof(struct caif_payload_info));
	memset(cfpkt_info(pkt), 0, sizeof(struct caif_payload_info));
	do {

		ret = -ETIMEDOUT;


		/* Slight paranoia, probably not needed. */
	if (cf_sk->layer.dn == NULL)
		if (unlikely(loopcnt++ > 1000)) {
		return -EINVAL;
			pr_warn("transmit retries failed, error = %d\n", ret);
			break;
		}


		if (cf_sk->layer.dn != NULL)
	return cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt);
			ret = cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt);
		if (likely(ret >= 0))
			break;
		/* if transmit return -EAGAIN, then retry */
		if (noblock && ret == -EAGAIN)
			break;
		timeo = caif_wait_for_flow_on(cf_sk, 0, timeo, &ret);
		if (signal_pending(current)) {
			ret = sock_intr_errno(timeo);
			break;
		}
		if (ret)
			break;
		if (cf_sk->sk.sk_state != CAIF_CONNECTED ||
			sock_flag(&cf_sk->sk, SOCK_DEAD) ||
			(cf_sk->sk.sk_shutdown & RCV_SHUTDOWN)) {
			ret = -EPIPE;
			cf_sk->sk.sk_err = EPIPE;
			break;
		}
	} while (ret == -EAGAIN);
	return ret;
}
}


/* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */
/* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */
+1 −6
Original line number Original line Diff line number Diff line
@@ -108,10 +108,5 @@ static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt)
	 */
	 */
	info->hdr_len = 4;
	info->hdr_len = 4;
	info->dev_info = &service->dev_info;
	info->dev_info = &service->dev_info;
	ret = layr->dn->transmit(layr->dn, pkt);
	return layr->dn->transmit(layr->dn, pkt);
	if (ret < 0) {
		u32 tmp32;
		cfpkt_extr_head(pkt, &tmp32, 4);
	}
	return ret;
}
}
+1 −7
Original line number Original line Diff line number Diff line
@@ -120,7 +120,6 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
	int tmp;
	int tmp;
	u16 chks;
	u16 chks;
	u16 len;
	u16 len;
	int ret;
	struct cffrml *this = container_obj(layr);
	struct cffrml *this = container_obj(layr);
	if (this->dofcs) {
	if (this->dofcs) {
		chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
		chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
@@ -137,12 +136,7 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
		pr_err("Packet is erroneous!\n");
		pr_err("Packet is erroneous!\n");
		return -EPROTO;
		return -EPROTO;
	}
	}
	ret = layr->dn->transmit(layr->dn, pkt);
	return layr->dn->transmit(layr->dn, pkt);
	if (ret < 0) {
		/* Remove header on faulty packet. */
		cfpkt_extr_head(pkt, &tmp, 2);
	}
	return ret;
}
}


static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
+1 −6
Original line number Original line Diff line number Diff line
@@ -184,7 +184,6 @@ static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt)


static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt)
static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt)
{
{
	int ret;
	struct cfmuxl *muxl = container_obj(layr);
	struct cfmuxl *muxl = container_obj(layr);
	u8 linkid;
	u8 linkid;
	struct cflayer *dn;
	struct cflayer *dn;
@@ -198,11 +197,7 @@ static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt)
	info->hdr_len += 1;
	info->hdr_len += 1;
	linkid = info->channel_id;
	linkid = info->channel_id;
	cfpkt_add_head(pkt, &linkid, 1);
	cfpkt_add_head(pkt, &linkid, 1);
	ret = dn->transmit(dn, pkt);
	return dn->transmit(dn, pkt);
	/* Remove MUX protocol header upon error. */
	if (ret < 0)
		cfpkt_extr_head(pkt, &linkid, 1);
	return ret;
}
}


static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
Loading