aboutsummaryrefslogtreecommitdiffstats
path: root/net/caif
diff options
context:
space:
mode:
authorsjur.brandeland@stericsson.com <sjur.brandeland@stericsson.com>2011-05-12 22:44:06 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-15 17:45:56 -0400
commitc85c2951d4da1236e32f1858db418221e624aba5 (patch)
tree8f70d7ab3dbe05ea6f812f9bfb8d341425a29193 /net/caif
parentbee925db9a77a5736596dcf6f91d0879f5ee915b (diff)
caif: Handle dev_queue_xmit errors.
Do proper handling of dev_queue_xmit errors in order to avoid double free of skb and leaks in error conditions. In cfctrl pending requests are removed when CAIF Link layer goes down. Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/caif')
-rw-r--r--net/caif/caif_dev.c7
-rw-r--r--net/caif/caif_socket.c8
-rw-r--r--net/caif/cfcnfg.c2
-rw-r--r--net/caif/cfctrl.c121
-rw-r--r--net/caif/cffrml.c17
-rw-r--r--net/caif/cfveil.c8
6 files changed, 117 insertions, 46 deletions
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index 0e651cf577cf..366ca0fb7a29 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -118,6 +118,7 @@ static struct caif_device_entry *caif_get(struct net_device *dev)
118 118
119static int transmit(struct cflayer *layer, struct cfpkt *pkt) 119static int transmit(struct cflayer *layer, struct cfpkt *pkt)
120{ 120{
121 int err;
121 struct caif_device_entry *caifd = 122 struct caif_device_entry *caifd =
122 container_of(layer, struct caif_device_entry, layer); 123 container_of(layer, struct caif_device_entry, layer);
123 struct sk_buff *skb; 124 struct sk_buff *skb;
@@ -125,9 +126,11 @@ static int transmit(struct cflayer *layer, struct cfpkt *pkt)
125 skb = cfpkt_tonative(pkt); 126 skb = cfpkt_tonative(pkt);
126 skb->dev = caifd->netdev; 127 skb->dev = caifd->netdev;
127 128
128 dev_queue_xmit(skb); 129 err = dev_queue_xmit(skb);
130 if (err > 0)
131 err = -EIO;
129 132
130 return 0; 133 return err;
131} 134}
132 135
133/* 136/*
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 653db759eb7e..7baae11a6126 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -604,7 +604,9 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock,
604 goto err; 604 goto err;
605 ret = transmit_skb(skb, cf_sk, noblock, timeo); 605 ret = transmit_skb(skb, cf_sk, noblock, timeo);
606 if (ret < 0) 606 if (ret < 0)
607 goto err; 607 /* skb is already freed */
608 return ret;
609
608 return len; 610 return len;
609err: 611err:
610 kfree_skb(skb); 612 kfree_skb(skb);
@@ -933,9 +935,9 @@ static int caif_release(struct socket *sock)
933 * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock, 935 * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock,
934 * this ensures no packets when sock is dead. 936 * this ensures no packets when sock is dead.
935 */ 937 */
936 spin_lock(&sk->sk_receive_queue.lock); 938 spin_lock_bh(&sk->sk_receive_queue.lock);
937 sock_set_flag(sk, SOCK_DEAD); 939 sock_set_flag(sk, SOCK_DEAD);
938 spin_unlock(&sk->sk_receive_queue.lock); 940 spin_unlock_bh(&sk->sk_receive_queue.lock);
939 sock->sk = NULL; 941 sock->sk = NULL;
940 942
941 dbfs_atomic_inc(&cnt.num_disconnect); 943 dbfs_atomic_inc(&cnt.num_disconnect);
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index e857d8995ca3..423009918f79 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -126,7 +126,7 @@ void cfcnfg_remove(struct cfcnfg *cfg)
126 synchronize_rcu(); 126 synchronize_rcu();
127 127
128 kfree(cfg->mux); 128 kfree(cfg->mux);
129 kfree(cfg->ctrl); 129 cfctrl_remove(cfg->ctrl);
130 kfree(cfg); 130 kfree(cfg);
131 } 131 }
132} 132}
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c
index 397a2c099e2c..0c00a6015dda 100644
--- a/net/caif/cfctrl.c
+++ b/net/caif/cfctrl.c
@@ -17,7 +17,6 @@
17#define UTILITY_NAME_LENGTH 16 17#define UTILITY_NAME_LENGTH 16
18#define CFPKT_CTRL_PKT_LEN 20 18#define CFPKT_CTRL_PKT_LEN 20
19 19
20
21#ifdef CAIF_NO_LOOP 20#ifdef CAIF_NO_LOOP
22static int handle_loop(struct cfctrl *ctrl, 21static int handle_loop(struct cfctrl *ctrl,
23 int cmd, struct cfpkt *pkt){ 22 int cmd, struct cfpkt *pkt){
@@ -51,13 +50,29 @@ struct cflayer *cfctrl_create(void)
51 this->serv.layer.receive = cfctrl_recv; 50 this->serv.layer.receive = cfctrl_recv;
52 sprintf(this->serv.layer.name, "ctrl"); 51 sprintf(this->serv.layer.name, "ctrl");
53 this->serv.layer.ctrlcmd = cfctrl_ctrlcmd; 52 this->serv.layer.ctrlcmd = cfctrl_ctrlcmd;
53#ifndef CAIF_NO_LOOP
54 spin_lock_init(&this->loop_linkid_lock); 54 spin_lock_init(&this->loop_linkid_lock);
55 this->loop_linkid = 1;
56#endif
55 spin_lock_init(&this->info_list_lock); 57 spin_lock_init(&this->info_list_lock);
56 INIT_LIST_HEAD(&this->list); 58 INIT_LIST_HEAD(&this->list);
57 this->loop_linkid = 1;
58 return &this->serv.layer; 59 return &this->serv.layer;
59} 60}
60 61
62void cfctrl_remove(struct cflayer *layer)
63{
64 struct cfctrl_request_info *p, *tmp;
65 struct cfctrl *ctrl = container_obj(layer);
66
67 spin_lock_bh(&ctrl->info_list_lock);
68 list_for_each_entry_safe(p, tmp, &ctrl->list, list) {
69 list_del(&p->list);
70 kfree(p);
71 }
72 spin_unlock_bh(&ctrl->info_list_lock);
73 kfree(layer);
74}
75
61static bool param_eq(const struct cfctrl_link_param *p1, 76static bool param_eq(const struct cfctrl_link_param *p1,
62 const struct cfctrl_link_param *p2) 77 const struct cfctrl_link_param *p2)
63{ 78{
@@ -116,11 +131,11 @@ static bool cfctrl_req_eq(const struct cfctrl_request_info *r1,
116static void cfctrl_insert_req(struct cfctrl *ctrl, 131static void cfctrl_insert_req(struct cfctrl *ctrl,
117 struct cfctrl_request_info *req) 132 struct cfctrl_request_info *req)
118{ 133{
119 spin_lock(&ctrl->info_list_lock); 134 spin_lock_bh(&ctrl->info_list_lock);
120 atomic_inc(&ctrl->req_seq_no); 135 atomic_inc(&ctrl->req_seq_no);
121 req->sequence_no = atomic_read(&ctrl->req_seq_no); 136 req->sequence_no = atomic_read(&ctrl->req_seq_no);
122 list_add_tail(&req->list, &ctrl->list); 137 list_add_tail(&req->list, &ctrl->list);
123 spin_unlock(&ctrl->info_list_lock); 138 spin_unlock_bh(&ctrl->info_list_lock);
124} 139}
125 140
126/* Compare and remove request */ 141/* Compare and remove request */
@@ -129,7 +144,6 @@ static struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl,
129{ 144{
130 struct cfctrl_request_info *p, *tmp, *first; 145 struct cfctrl_request_info *p, *tmp, *first;
131 146
132 spin_lock(&ctrl->info_list_lock);
133 first = list_first_entry(&ctrl->list, struct cfctrl_request_info, list); 147 first = list_first_entry(&ctrl->list, struct cfctrl_request_info, list);
134 148
135 list_for_each_entry_safe(p, tmp, &ctrl->list, list) { 149 list_for_each_entry_safe(p, tmp, &ctrl->list, list) {
@@ -145,7 +159,6 @@ static struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl,
145 } 159 }
146 p = NULL; 160 p = NULL;
147out: 161out:
148 spin_unlock(&ctrl->info_list_lock);
149 return p; 162 return p;
150} 163}
151 164
@@ -179,10 +192,6 @@ void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid)
179 cfpkt_addbdy(pkt, physlinkid); 192 cfpkt_addbdy(pkt, physlinkid);
180 ret = 193 ret =
181 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); 194 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
182 if (ret < 0) {
183 pr_err("Could not transmit enum message\n");
184 cfpkt_destroy(pkt);
185 }
186} 195}
187 196
188int cfctrl_linkup_request(struct cflayer *layer, 197int cfctrl_linkup_request(struct cflayer *layer,
@@ -196,14 +205,23 @@ int cfctrl_linkup_request(struct cflayer *layer,
196 struct cfctrl_request_info *req; 205 struct cfctrl_request_info *req;
197 int ret; 206 int ret;
198 char utility_name[16]; 207 char utility_name[16];
199 struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); 208 struct cfpkt *pkt;
209
210 if (cfctrl_cancel_req(layer, user_layer) > 0) {
211 /* Slight Paranoia, check if already connecting */
212 pr_err("Duplicate connect request for same client\n");
213 WARN_ON(1);
214 return -EALREADY;
215 }
216
217 pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
200 if (!pkt) { 218 if (!pkt) {
201 pr_warn("Out of memory\n"); 219 pr_warn("Out of memory\n");
202 return -ENOMEM; 220 return -ENOMEM;
203 } 221 }
204 cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP); 222 cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP);
205 cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype); 223 cfpkt_addbdy(pkt, (param->chtype << 4) | param->linktype);
206 cfpkt_addbdy(pkt, (param->priority << 3) + param->phyid); 224 cfpkt_addbdy(pkt, (param->priority << 3) | param->phyid);
207 cfpkt_addbdy(pkt, param->endpoint & 0x03); 225 cfpkt_addbdy(pkt, param->endpoint & 0x03);
208 226
209 switch (param->linktype) { 227 switch (param->linktype) {
@@ -266,9 +284,13 @@ int cfctrl_linkup_request(struct cflayer *layer,
266 ret = 284 ret =
267 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); 285 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
268 if (ret < 0) { 286 if (ret < 0) {
269 pr_err("Could not transmit linksetup request\n"); 287 int count;
270 cfpkt_destroy(pkt); 288
271 return -ENODEV; 289 count = cfctrl_cancel_req(&cfctrl->serv.layer,
290 user_layer);
291 if (count != 1)
292 pr_err("Could not remove request (%d)", count);
293 return -ENODEV;
272 } 294 }
273 return 0; 295 return 0;
274} 296}
@@ -288,28 +310,29 @@ int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid,
288 init_info(cfpkt_info(pkt), cfctrl); 310 init_info(cfpkt_info(pkt), cfctrl);
289 ret = 311 ret =
290 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); 312 cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
291 if (ret < 0) { 313#ifndef CAIF_NO_LOOP
292 pr_err("Could not transmit link-down request\n"); 314 cfctrl->loop_linkused[channelid] = 0;
293 cfpkt_destroy(pkt); 315#endif
294 }
295 return ret; 316 return ret;
296} 317}
297 318
298void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) 319int cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer)
299{ 320{
300 struct cfctrl_request_info *p, *tmp; 321 struct cfctrl_request_info *p, *tmp;
301 struct cfctrl *ctrl = container_obj(layr); 322 struct cfctrl *ctrl = container_obj(layr);
302 spin_lock(&ctrl->info_list_lock); 323 int found = 0;
324 spin_lock_bh(&ctrl->info_list_lock);
303 325
304 list_for_each_entry_safe(p, tmp, &ctrl->list, list) { 326 list_for_each_entry_safe(p, tmp, &ctrl->list, list) {
305 if (p->client_layer == adap_layer) { 327 if (p->client_layer == adap_layer) {
306 pr_debug("cancel req :%d\n", p->sequence_no);
307 list_del(&p->list); 328 list_del(&p->list);
308 kfree(p); 329 kfree(p);
330 found++;
309 } 331 }
310 } 332 }
311 333
312 spin_unlock(&ctrl->info_list_lock); 334 spin_unlock_bh(&ctrl->info_list_lock);
335 return found;
313} 336}
314 337
315static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) 338static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
@@ -461,6 +484,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
461 484
462 rsp.cmd = cmd; 485 rsp.cmd = cmd;
463 rsp.param = linkparam; 486 rsp.param = linkparam;
487 spin_lock_bh(&cfctrl->info_list_lock);
464 req = cfctrl_remove_req(cfctrl, &rsp); 488 req = cfctrl_remove_req(cfctrl, &rsp);
465 489
466 if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) || 490 if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) ||
@@ -480,6 +504,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
480 504
481 if (req != NULL) 505 if (req != NULL)
482 kfree(req); 506 kfree(req);
507
508 spin_unlock_bh(&cfctrl->info_list_lock);
483 } 509 }
484 break; 510 break;
485 case CFCTRL_CMD_LINK_DESTROY: 511 case CFCTRL_CMD_LINK_DESTROY:
@@ -523,12 +549,29 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
523 switch (ctrl) { 549 switch (ctrl) {
524 case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: 550 case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND:
525 case CAIF_CTRLCMD_FLOW_OFF_IND: 551 case CAIF_CTRLCMD_FLOW_OFF_IND:
526 spin_lock(&this->info_list_lock); 552 spin_lock_bh(&this->info_list_lock);
527 if (!list_empty(&this->list)) { 553 if (!list_empty(&this->list)) {
528 pr_debug("Received flow off in control layer\n"); 554 pr_debug("Received flow off in control layer\n");
529 } 555 }
530 spin_unlock(&this->info_list_lock); 556 spin_unlock_bh(&this->info_list_lock);
531 break; 557 break;
558 case _CAIF_CTRLCMD_PHYIF_DOWN_IND: {
559 struct cfctrl_request_info *p, *tmp;
560
561 /* Find all connect request and report failure */
562 spin_lock_bh(&this->info_list_lock);
563 list_for_each_entry_safe(p, tmp, &this->list, list) {
564 if (p->param.phyid == phyid) {
565 list_del(&p->list);
566 p->client_layer->ctrlcmd(p->client_layer,
567 CAIF_CTRLCMD_INIT_FAIL_RSP,
568 phyid);
569 kfree(p);
570 }
571 }
572 spin_unlock_bh(&this->info_list_lock);
573 break;
574 }
532 default: 575 default:
533 break; 576 break;
534 } 577 }
@@ -538,27 +581,33 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
538static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt) 581static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt)
539{ 582{
540 static int last_linkid; 583 static int last_linkid;
584 static int dec;
541 u8 linkid, linktype, tmp; 585 u8 linkid, linktype, tmp;
542 switch (cmd) { 586 switch (cmd) {
543 case CFCTRL_CMD_LINK_SETUP: 587 case CFCTRL_CMD_LINK_SETUP:
544 spin_lock(&ctrl->loop_linkid_lock); 588 spin_lock_bh(&ctrl->loop_linkid_lock);
545 for (linkid = last_linkid + 1; linkid < 255; linkid++) 589 if (!dec) {
546 if (!ctrl->loop_linkused[linkid]) 590 for (linkid = last_linkid + 1; linkid < 255; linkid++)
547 goto found; 591 if (!ctrl->loop_linkused[linkid])
592 goto found;
593 }
594 dec = 1;
548 for (linkid = last_linkid - 1; linkid > 0; linkid--) 595 for (linkid = last_linkid - 1; linkid > 0; linkid--)
549 if (!ctrl->loop_linkused[linkid]) 596 if (!ctrl->loop_linkused[linkid])
550 goto found; 597 goto found;
551 spin_unlock(&ctrl->loop_linkid_lock); 598 spin_unlock_bh(&ctrl->loop_linkid_lock);
552 pr_err("Out of link-ids\n"); 599
553 return -EINVAL;
554found: 600found:
601 if (linkid < 10)
602 dec = 0;
603
555 if (!ctrl->loop_linkused[linkid]) 604 if (!ctrl->loop_linkused[linkid])
556 ctrl->loop_linkused[linkid] = 1; 605 ctrl->loop_linkused[linkid] = 1;
557 606
558 last_linkid = linkid; 607 last_linkid = linkid;
559 608
560 cfpkt_add_trail(pkt, &linkid, 1); 609 cfpkt_add_trail(pkt, &linkid, 1);
561 spin_unlock(&ctrl->loop_linkid_lock); 610 spin_unlock_bh(&ctrl->loop_linkid_lock);
562 cfpkt_peek_head(pkt, &linktype, 1); 611 cfpkt_peek_head(pkt, &linktype, 1);
563 if (linktype == CFCTRL_SRV_UTIL) { 612 if (linktype == CFCTRL_SRV_UTIL) {
564 tmp = 0x01; 613 tmp = 0x01;
@@ -568,10 +617,10 @@ found:
568 break; 617 break;
569 618
570 case CFCTRL_CMD_LINK_DESTROY: 619 case CFCTRL_CMD_LINK_DESTROY:
571 spin_lock(&ctrl->loop_linkid_lock); 620 spin_lock_bh(&ctrl->loop_linkid_lock);
572 cfpkt_peek_head(pkt, &linkid, 1); 621 cfpkt_peek_head(pkt, &linkid, 1);
573 ctrl->loop_linkused[linkid] = 0; 622 ctrl->loop_linkused[linkid] = 0;
574 spin_unlock(&ctrl->loop_linkid_lock); 623 spin_unlock_bh(&ctrl->loop_linkid_lock);
575 break; 624 break;
576 default: 625 default:
577 break; 626 break;
diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c
index 4f4f756c49ac..04204b202718 100644
--- a/net/caif/cffrml.c
+++ b/net/caif/cffrml.c
@@ -33,7 +33,6 @@ static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
33static u32 cffrml_rcv_error; 33static u32 cffrml_rcv_error;
34static u32 cffrml_rcv_checsum_error; 34static u32 cffrml_rcv_checsum_error;
35struct cflayer *cffrml_create(u16 phyid, bool use_fcs) 35struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
36
37{ 36{
38 struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC); 37 struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC);
39 if (!this) { 38 if (!this) {
@@ -128,6 +127,13 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
128 cfpkt_destroy(pkt); 127 cfpkt_destroy(pkt);
129 return -EPROTO; 128 return -EPROTO;
130 } 129 }
130
131 if (layr->up == NULL) {
132 pr_err("Layr up is missing!\n");
133 cfpkt_destroy(pkt);
134 return -EINVAL;
135 }
136
131 return layr->up->receive(layr->up, pkt); 137 return layr->up->receive(layr->up, pkt);
132} 138}
133 139
@@ -150,15 +156,22 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
150 cfpkt_info(pkt)->hdr_len += 2; 156 cfpkt_info(pkt)->hdr_len += 2;
151 if (cfpkt_erroneous(pkt)) { 157 if (cfpkt_erroneous(pkt)) {
152 pr_err("Packet is erroneous!\n"); 158 pr_err("Packet is erroneous!\n");
159 cfpkt_destroy(pkt);
153 return -EPROTO; 160 return -EPROTO;
154 } 161 }
162
163 if (layr->dn == NULL) {
164 cfpkt_destroy(pkt);
165 return -ENODEV;
166
167 }
155 return layr->dn->transmit(layr->dn, pkt); 168 return layr->dn->transmit(layr->dn, pkt);
156} 169}
157 170
158static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, 171static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
159 int phyid) 172 int phyid)
160{ 173{
161 if (layr->up->ctrlcmd) 174 if (layr->up && layr->up->ctrlcmd)
162 layr->up->ctrlcmd(layr->up, ctrl, layr->id); 175 layr->up->ctrlcmd(layr->up, ctrl, layr->id);
163} 176}
164 177
diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c
index 1a588cd818ea..3ec83fbc2887 100644
--- a/net/caif/cfveil.c
+++ b/net/caif/cfveil.c
@@ -82,13 +82,14 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt)
82 int ret; 82 int ret;
83 struct cfsrvl *service = container_obj(layr); 83 struct cfsrvl *service = container_obj(layr);
84 if (!cfsrvl_ready(service, &ret)) 84 if (!cfsrvl_ready(service, &ret))
85 return ret; 85 goto err;
86 caif_assert(layr->dn != NULL); 86 caif_assert(layr->dn != NULL);
87 caif_assert(layr->dn->transmit != NULL); 87 caif_assert(layr->dn->transmit != NULL);
88 88
89 if (cfpkt_add_head(pkt, &tmp, 1) < 0) { 89 if (cfpkt_add_head(pkt, &tmp, 1) < 0) {
90 pr_err("Packet is erroneous!\n"); 90 pr_err("Packet is erroneous!\n");
91 return -EPROTO; 91 ret = -EPROTO;
92 goto err;
92 } 93 }
93 94
94 /* Add info-> for MUX-layer to route the packet out. */ 95 /* Add info-> for MUX-layer to route the packet out. */
@@ -97,4 +98,7 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt)
97 info->hdr_len = 1; 98 info->hdr_len = 1;
98 info->dev_info = &service->dev_info; 99 info->dev_info = &service->dev_info;
99 return layr->dn->transmit(layr->dn, pkt); 100 return layr->dn->transmit(layr->dn, pkt);
101err:
102 cfpkt_destroy(pkt);
103 return ret;
100} 104}