diff options
Diffstat (limited to 'net/caif/cfrfml.c')
| -rw-r--r-- | net/caif/cfrfml.c | 44 | 
1 files changed, 19 insertions, 25 deletions
diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c index e2fb5fa7579..61d7617d924 100644 --- a/net/caif/cfrfml.c +++ b/net/caif/cfrfml.c @@ -1,6 +1,6 @@  /*   * 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   */ @@ -31,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) @@ -43,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_warn("Out of memory\n"); +	if (!this)  		return NULL; -	}  	cfsrvl_init(&this->serv, channel_id, dev_info, false);  	this->serv.release = cfrfml_release; @@ -72,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; @@ -187,13 +184,18 @@ out:  					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; @@ -289,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;  | 
