diff options
author | sjur.brandeland@stericsson.com <sjur.brandeland@stericsson.com> | 2011-05-12 22:44:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-15 17:45:56 -0400 |
commit | c85c2951d4da1236e32f1858db418221e624aba5 (patch) | |
tree | 8f70d7ab3dbe05ea6f812f9bfb8d341425a29193 /net/caif | |
parent | bee925db9a77a5736596dcf6f91d0879f5ee915b (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.c | 7 | ||||
-rw-r--r-- | net/caif/caif_socket.c | 8 | ||||
-rw-r--r-- | net/caif/cfcnfg.c | 2 | ||||
-rw-r--r-- | net/caif/cfctrl.c | 121 | ||||
-rw-r--r-- | net/caif/cffrml.c | 17 | ||||
-rw-r--r-- | net/caif/cfveil.c | 8 |
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 | ||
119 | static int transmit(struct cflayer *layer, struct cfpkt *pkt) | 119 | static 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; |
609 | err: | 611 | err: |
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 |
22 | static int handle_loop(struct cfctrl *ctrl, | 21 | static 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 | ||
62 | void 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 | |||
61 | static bool param_eq(const struct cfctrl_link_param *p1, | 76 | static 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, | |||
116 | static void cfctrl_insert_req(struct cfctrl *ctrl, | 131 | static 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; |
147 | out: | 161 | out: |
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 | ||
188 | int cfctrl_linkup_request(struct cflayer *layer, | 197 | int 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 | ||
298 | void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) | 319 | int 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 | ||
315 | static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | 338 | static 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, | |||
538 | static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt) | 581 | static 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; | ||
554 | found: | 600 | found: |
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, | |||
33 | static u32 cffrml_rcv_error; | 33 | static u32 cffrml_rcv_error; |
34 | static u32 cffrml_rcv_checsum_error; | 34 | static u32 cffrml_rcv_checsum_error; |
35 | struct cflayer *cffrml_create(u16 phyid, bool use_fcs) | 35 | struct 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 | ||
158 | static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | 171 | static 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); |
101 | err: | ||
102 | cfpkt_destroy(pkt); | ||
103 | return ret; | ||
100 | } | 104 | } |