提交 4dd820c0 编写于 作者: S Sjur Brændeland 提交者: David S. Miller

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: NSjur Brændeland <sjur.brandeland@stericsson.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 73d6ac63
...@@ -120,25 +120,12 @@ static int transmit(struct cflayer *layer, struct cfpkt *pkt) ...@@ -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;
} }
......
...@@ -519,43 +519,14 @@ static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk, ...@@ -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 */
......
...@@ -108,10 +108,5 @@ static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) ...@@ -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;
} }
...@@ -120,7 +120,6 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt) ...@@ -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) ...@@ -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,
......
...@@ -184,7 +184,6 @@ static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt) ...@@ -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) ...@@ -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,
......
...@@ -179,15 +179,10 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt) ...@@ -179,15 +179,10 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt)
static int cfserl_transmit(struct cflayer *layer, struct cfpkt *newpkt) static int cfserl_transmit(struct cflayer *layer, struct cfpkt *newpkt)
{ {
struct cfserl *layr = container_obj(layer); struct cfserl *layr = container_obj(layer);
int ret;
u8 tmp8 = CFSERL_STX; u8 tmp8 = CFSERL_STX;
if (layr->usestx) if (layr->usestx)
cfpkt_add_head(newpkt, &tmp8, 1); cfpkt_add_head(newpkt, &tmp8, 1);
ret = layer->dn->transmit(layer->dn, newpkt); return layer->dn->transmit(layer->dn, newpkt);
if (ret < 0)
cfpkt_extr_head(newpkt, &tmp8, 1);
return ret;
} }
static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
......
...@@ -100,10 +100,5 @@ static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt) ...@@ -100,10 +100,5 @@ static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt)
*/ */
info->hdr_len = 1; info->hdr_len = 1;
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;
} }
...@@ -96,8 +96,5 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt) ...@@ -96,8 +96,5 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt)
info->channel_id = service->layer.id; info->channel_id = service->layer.id;
info->hdr_len = 1; info->hdr_len = 1;
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)
cfpkt_extr_head(pkt, &tmp, 1);
return ret;
} }
...@@ -60,8 +60,5 @@ static int cfvidl_transmit(struct cflayer *layr, struct cfpkt *pkt) ...@@ -60,8 +60,5 @@ static int cfvidl_transmit(struct cflayer *layr, struct cfpkt *pkt)
info = cfpkt_info(pkt); info = cfpkt_info(pkt);
info->channel_id = service->layer.id; info->channel_id = service->layer.id;
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)
cfpkt_extr_head(pkt, &videoheader, 4);
return ret;
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册