diff options
Diffstat (limited to 'net/caif/cfrfml.c')
| -rw-r--r-- | net/caif/cfrfml.c | 54 |
1 files changed, 23 insertions, 31 deletions
diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c index 9a699242d10..61d7617d924 100644 --- a/net/caif/cfrfml.c +++ b/net/caif/cfrfml.c @@ -1,9 +1,11 @@ /* * Copyright (C) ST-Ericsson AB 2010 - * Author: Sjur Brendeland/sjur.brandeland@stericsson.com + * Author: Sjur Brendeland * License terms: GNU General Public License (GPL) version 2 */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ + #include <linux/stddef.h> #include <linux/spinlock.h> #include <linux/slab.h> @@ -29,9 +31,9 @@ struct cfrfml { spinlock_t sync; }; -static void cfrfml_release(struct kref *kref) +static void cfrfml_release(struct cflayer *layer) { - struct cfsrvl *srvl = container_of(kref, struct cfsrvl, ref); + struct cfsrvl *srvl = container_of(layer, struct cfsrvl, layer); struct cfrfml *rfml = container_obj(&srvl->layer); if (rfml->incomplete_frm) @@ -41,16 +43,13 @@ static void cfrfml_release(struct kref *kref) } struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info, - int mtu_size) + int mtu_size) { int tmp; - struct cfrfml *this = - kzalloc(sizeof(struct cfrfml), GFP_ATOMIC); + struct cfrfml *this = kzalloc(sizeof(struct cfrfml), GFP_ATOMIC); - if (!this) { - pr_warning("CAIF: %s(): Out of memory\n", __func__); + if (!this) return NULL; - } cfsrvl_init(&this->serv, channel_id, dev_info, false); this->serv.release = cfrfml_release; @@ -70,7 +69,7 @@ struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info, } static struct cfpkt *rfm_append(struct cfrfml *rfml, char *seghead, - struct cfpkt *pkt, int *err) + struct cfpkt *pkt, int *err) { struct cfpkt *tmppkt; *err = -EPROTO; @@ -178,22 +177,25 @@ out: cfpkt_destroy(rfml->incomplete_frm); rfml->incomplete_frm = NULL; - pr_info("CAIF: %s(): " - "Connection error %d triggered on RFM link\n", - __func__, err); + pr_info("Connection error %d triggered on RFM link\n", err); /* Trigger connection error upon failure.*/ layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, rfml->serv.dev_info.id); } spin_unlock(&rfml->sync); + + if (unlikely(err == -EAGAIN)) + /* It is not possible to recover after drop of a fragment */ + err = -EIO; + return err; } static int cfrfml_transmit_segment(struct cfrfml *rfml, struct cfpkt *pkt) { - caif_assert(cfpkt_getlen(pkt) >= rfml->fragment_size); + caif_assert(cfpkt_getlen(pkt) < rfml->fragment_size + RFM_HEAD_SIZE); /* Add info for MUX-layer to route the packet out. */ cfpkt_info(pkt)->channel_id = rfml->serv.layer.id; @@ -221,7 +223,7 @@ static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt) caif_assert(layr->dn->transmit != NULL); if (!cfsrvl_ready(&rfml->serv, &err)) - return err; + goto out; err = -EPROTO; if (cfpkt_getlen(pkt) <= RFM_HEAD_SIZE-1) @@ -254,8 +256,11 @@ static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt) err = cfrfml_transmit_segment(rfml, frontpkt); - if (err != 0) + if (err != 0) { + frontpkt = NULL; goto out; + } + frontpkt = rearpkt; rearpkt = NULL; @@ -280,9 +285,7 @@ static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt) out: if (err != 0) { - pr_info("CAIF: %s(): " - "Connection error %d triggered on RFM link\n", - __func__, err); + pr_info("Connection error %d triggered on RFM link\n", err); /* Trigger connection error upon failure.*/ layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, @@ -291,19 +294,8 @@ out: if (rearpkt) cfpkt_destroy(rearpkt); - if (frontpkt && frontpkt != pkt) { - + if (frontpkt) cfpkt_destroy(frontpkt); - /* - * Socket layer will free the original packet, - * but this packet may already be sent and - * freed. So we have to return 0 in this case - * to avoid socket layer to re-free this packet. - * The return of shutdown indication will - * cause connection to be invalidated anyhow. - */ - err = 0; - } } return err; |
