diff options
Diffstat (limited to 'net/caif/cfctrl.c')
-rw-r--r-- | net/caif/cfctrl.c | 95 |
1 files changed, 62 insertions, 33 deletions
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index 11f80140f3cb..a521d32cfe56 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c | |||
@@ -32,6 +32,7 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
32 | 32 | ||
33 | struct cflayer *cfctrl_create(void) | 33 | struct cflayer *cfctrl_create(void) |
34 | { | 34 | { |
35 | struct dev_info dev_info; | ||
35 | struct cfctrl *this = | 36 | struct cfctrl *this = |
36 | kmalloc(sizeof(struct cfctrl), GFP_ATOMIC); | 37 | kmalloc(sizeof(struct cfctrl), GFP_ATOMIC); |
37 | if (!this) { | 38 | if (!this) { |
@@ -39,12 +40,13 @@ struct cflayer *cfctrl_create(void) | |||
39 | return NULL; | 40 | return NULL; |
40 | } | 41 | } |
41 | caif_assert(offsetof(struct cfctrl, serv.layer) == 0); | 42 | caif_assert(offsetof(struct cfctrl, serv.layer) == 0); |
43 | memset(&dev_info, 0, sizeof(dev_info)); | ||
44 | dev_info.id = 0xff; | ||
42 | memset(this, 0, sizeof(*this)); | 45 | memset(this, 0, sizeof(*this)); |
46 | cfsrvl_init(&this->serv, 0, &dev_info); | ||
43 | spin_lock_init(&this->info_list_lock); | 47 | spin_lock_init(&this->info_list_lock); |
44 | atomic_set(&this->req_seq_no, 1); | 48 | atomic_set(&this->req_seq_no, 1); |
45 | atomic_set(&this->rsp_seq_no, 1); | 49 | atomic_set(&this->rsp_seq_no, 1); |
46 | this->serv.dev_info.id = 0xff; | ||
47 | this->serv.layer.id = 0; | ||
48 | this->serv.layer.receive = cfctrl_recv; | 50 | this->serv.layer.receive = cfctrl_recv; |
49 | sprintf(this->serv.layer.name, "ctrl"); | 51 | sprintf(this->serv.layer.name, "ctrl"); |
50 | this->serv.layer.ctrlcmd = cfctrl_ctrlcmd; | 52 | this->serv.layer.ctrlcmd = cfctrl_ctrlcmd; |
@@ -127,20 +129,6 @@ void cfctrl_insert_req(struct cfctrl *ctrl, | |||
127 | spin_unlock(&ctrl->info_list_lock); | 129 | spin_unlock(&ctrl->info_list_lock); |
128 | } | 130 | } |
129 | 131 | ||
130 | static void cfctrl_insert_req2(struct cfctrl *ctrl, enum cfctrl_cmd cmd, | ||
131 | u8 linkid, struct cflayer *user_layer) | ||
132 | { | ||
133 | struct cfctrl_request_info *req = kmalloc(sizeof(*req), GFP_KERNEL); | ||
134 | if (!req) { | ||
135 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
136 | return; | ||
137 | } | ||
138 | req->client_layer = user_layer; | ||
139 | req->cmd = cmd; | ||
140 | req->channel_id = linkid; | ||
141 | cfctrl_insert_req(ctrl, req); | ||
142 | } | ||
143 | |||
144 | /* Compare and remove request */ | 132 | /* Compare and remove request */ |
145 | struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, | 133 | struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, |
146 | struct cfctrl_request_info *req) | 134 | struct cfctrl_request_info *req) |
@@ -234,7 +222,7 @@ void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid) | |||
234 | } | 222 | } |
235 | } | 223 | } |
236 | 224 | ||
237 | void cfctrl_linkup_request(struct cflayer *layer, | 225 | int cfctrl_linkup_request(struct cflayer *layer, |
238 | struct cfctrl_link_param *param, | 226 | struct cfctrl_link_param *param, |
239 | struct cflayer *user_layer) | 227 | struct cflayer *user_layer) |
240 | { | 228 | { |
@@ -248,7 +236,7 @@ void cfctrl_linkup_request(struct cflayer *layer, | |||
248 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | 236 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); |
249 | if (!pkt) { | 237 | if (!pkt) { |
250 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | 238 | pr_warning("CAIF: %s(): Out of memory\n", __func__); |
251 | return; | 239 | return -ENOMEM; |
252 | } | 240 | } |
253 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP); | 241 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP); |
254 | cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype); | 242 | cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype); |
@@ -294,11 +282,12 @@ void cfctrl_linkup_request(struct cflayer *layer, | |||
294 | default: | 282 | default: |
295 | pr_warning("CAIF: %s():Request setup of bad link type = %d\n", | 283 | pr_warning("CAIF: %s():Request setup of bad link type = %d\n", |
296 | __func__, param->linktype); | 284 | __func__, param->linktype); |
285 | return -EINVAL; | ||
297 | } | 286 | } |
298 | req = kmalloc(sizeof(*req), GFP_KERNEL); | 287 | req = kmalloc(sizeof(*req), GFP_KERNEL); |
299 | if (!req) { | 288 | if (!req) { |
300 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | 289 | pr_warning("CAIF: %s(): Out of memory\n", __func__); |
301 | return; | 290 | return -ENOMEM; |
302 | } | 291 | } |
303 | memset(req, 0, sizeof(*req)); | 292 | memset(req, 0, sizeof(*req)); |
304 | req->client_layer = user_layer; | 293 | req->client_layer = user_layer; |
@@ -306,6 +295,11 @@ void cfctrl_linkup_request(struct cflayer *layer, | |||
306 | req->param = *param; | 295 | req->param = *param; |
307 | cfctrl_insert_req(cfctrl, req); | 296 | cfctrl_insert_req(cfctrl, req); |
308 | init_info(cfpkt_info(pkt), cfctrl); | 297 | init_info(cfpkt_info(pkt), cfctrl); |
298 | /* | ||
299 | * NOTE:Always send linkup and linkdown request on the same | ||
300 | * device as the payload. Otherwise old queued up payload | ||
301 | * might arrive with the newly allocated channel ID. | ||
302 | */ | ||
309 | cfpkt_info(pkt)->dev_info->id = param->phyid; | 303 | cfpkt_info(pkt)->dev_info->id = param->phyid; |
310 | ret = | 304 | ret = |
311 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | 305 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); |
@@ -313,7 +307,9 @@ void cfctrl_linkup_request(struct cflayer *layer, | |||
313 | pr_err("CAIF: %s(): Could not transmit linksetup request\n", | 307 | pr_err("CAIF: %s(): Could not transmit linksetup request\n", |
314 | __func__); | 308 | __func__); |
315 | cfpkt_destroy(pkt); | 309 | cfpkt_destroy(pkt); |
310 | return -ENODEV; | ||
316 | } | 311 | } |
312 | return 0; | ||
317 | } | 313 | } |
318 | 314 | ||
319 | int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, | 315 | int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, |
@@ -326,7 +322,6 @@ int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, | |||
326 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | 322 | pr_warning("CAIF: %s(): Out of memory\n", __func__); |
327 | return -ENOMEM; | 323 | return -ENOMEM; |
328 | } | 324 | } |
329 | cfctrl_insert_req2(cfctrl, CFCTRL_CMD_LINK_DESTROY, channelid, client); | ||
330 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY); | 325 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY); |
331 | cfpkt_addbdy(pkt, channelid); | 326 | cfpkt_addbdy(pkt, channelid); |
332 | init_info(cfpkt_info(pkt), cfctrl); | 327 | init_info(cfpkt_info(pkt), cfctrl); |
@@ -392,6 +387,38 @@ void cfctrl_getstartreason_req(struct cflayer *layer) | |||
392 | } | 387 | } |
393 | 388 | ||
394 | 389 | ||
390 | void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) | ||
391 | { | ||
392 | struct cfctrl_request_info *p, *req; | ||
393 | struct cfctrl *ctrl = container_obj(layr); | ||
394 | spin_lock(&ctrl->info_list_lock); | ||
395 | |||
396 | if (ctrl->first_req == NULL) { | ||
397 | spin_unlock(&ctrl->info_list_lock); | ||
398 | return; | ||
399 | } | ||
400 | |||
401 | if (ctrl->first_req->client_layer == adap_layer) { | ||
402 | |||
403 | req = ctrl->first_req; | ||
404 | ctrl->first_req = ctrl->first_req->next; | ||
405 | kfree(req); | ||
406 | } | ||
407 | |||
408 | p = ctrl->first_req; | ||
409 | while (p != NULL && p->next != NULL) { | ||
410 | if (p->next->client_layer == adap_layer) { | ||
411 | |||
412 | req = p->next; | ||
413 | p->next = p->next->next; | ||
414 | kfree(p->next); | ||
415 | } | ||
416 | p = p->next; | ||
417 | } | ||
418 | |||
419 | spin_unlock(&ctrl->info_list_lock); | ||
420 | } | ||
421 | |||
395 | static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | 422 | static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) |
396 | { | 423 | { |
397 | u8 cmdrsp; | 424 | u8 cmdrsp; |
@@ -409,11 +436,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
409 | cmd = cmdrsp & CFCTRL_CMD_MASK; | 436 | cmd = cmdrsp & CFCTRL_CMD_MASK; |
410 | if (cmd != CFCTRL_CMD_LINK_ERR | 437 | if (cmd != CFCTRL_CMD_LINK_ERR |
411 | && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) { | 438 | && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) { |
412 | if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE) { | 439 | if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE) |
413 | pr_info("CAIF: %s() CAIF Protocol error:" | 440 | cmdrsp |= CFCTRL_ERR_BIT; |
414 | "Response bit not set\n", __func__); | ||
415 | goto error; | ||
416 | } | ||
417 | } | 441 | } |
418 | 442 | ||
419 | switch (cmd) { | 443 | switch (cmd) { |
@@ -451,12 +475,16 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
451 | switch (serv) { | 475 | switch (serv) { |
452 | case CFCTRL_SRV_VEI: | 476 | case CFCTRL_SRV_VEI: |
453 | case CFCTRL_SRV_DBG: | 477 | case CFCTRL_SRV_DBG: |
478 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
479 | break; | ||
454 | /* Link ID */ | 480 | /* Link ID */ |
455 | cfpkt_extr_head(pkt, &linkid, 1); | 481 | cfpkt_extr_head(pkt, &linkid, 1); |
456 | break; | 482 | break; |
457 | case CFCTRL_SRV_VIDEO: | 483 | case CFCTRL_SRV_VIDEO: |
458 | cfpkt_extr_head(pkt, &tmp, 1); | 484 | cfpkt_extr_head(pkt, &tmp, 1); |
459 | linkparam.u.video.connid = tmp; | 485 | linkparam.u.video.connid = tmp; |
486 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
487 | break; | ||
460 | /* Link ID */ | 488 | /* Link ID */ |
461 | cfpkt_extr_head(pkt, &linkid, 1); | 489 | cfpkt_extr_head(pkt, &linkid, 1); |
462 | break; | 490 | break; |
@@ -465,6 +493,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
465 | cfpkt_extr_head(pkt, &tmp32, 4); | 493 | cfpkt_extr_head(pkt, &tmp32, 4); |
466 | linkparam.u.datagram.connid = | 494 | linkparam.u.datagram.connid = |
467 | le32_to_cpu(tmp32); | 495 | le32_to_cpu(tmp32); |
496 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
497 | break; | ||
468 | /* Link ID */ | 498 | /* Link ID */ |
469 | cfpkt_extr_head(pkt, &linkid, 1); | 499 | cfpkt_extr_head(pkt, &linkid, 1); |
470 | break; | 500 | break; |
@@ -483,6 +513,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
483 | *cp++ = tmp; | 513 | *cp++ = tmp; |
484 | *cp = '\0'; | 514 | *cp = '\0'; |
485 | 515 | ||
516 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
517 | break; | ||
486 | /* Link ID */ | 518 | /* Link ID */ |
487 | cfpkt_extr_head(pkt, &linkid, 1); | 519 | cfpkt_extr_head(pkt, &linkid, 1); |
488 | 520 | ||
@@ -519,6 +551,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
519 | cfpkt_extr_head(pkt, &tmp, 1); | 551 | cfpkt_extr_head(pkt, &tmp, 1); |
520 | *cp++ = tmp; | 552 | *cp++ = tmp; |
521 | } | 553 | } |
554 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
555 | break; | ||
522 | /* Link ID */ | 556 | /* Link ID */ |
523 | cfpkt_extr_head(pkt, &linkid, 1); | 557 | cfpkt_extr_head(pkt, &linkid, 1); |
524 | /* Length */ | 558 | /* Length */ |
@@ -560,13 +594,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
560 | break; | 594 | break; |
561 | case CFCTRL_CMD_LINK_DESTROY: | 595 | case CFCTRL_CMD_LINK_DESTROY: |
562 | cfpkt_extr_head(pkt, &linkid, 1); | 596 | cfpkt_extr_head(pkt, &linkid, 1); |
563 | rsp.cmd = cmd; | 597 | cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid); |
564 | rsp.channel_id = linkid; | ||
565 | req = cfctrl_remove_req(cfctrl, &rsp); | ||
566 | cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid, | ||
567 | req ? req->client_layer : NULL); | ||
568 | if (req != NULL) | ||
569 | kfree(req); | ||
570 | break; | 598 | break; |
571 | case CFCTRL_CMD_LINK_ERR: | 599 | case CFCTRL_CMD_LINK_ERR: |
572 | pr_err("CAIF: %s(): Frame Error Indication received\n", | 600 | pr_err("CAIF: %s(): Frame Error Indication received\n", |
@@ -608,7 +636,7 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
608 | case CAIF_CTRLCMD_FLOW_OFF_IND: | 636 | case CAIF_CTRLCMD_FLOW_OFF_IND: |
609 | spin_lock(&this->info_list_lock); | 637 | spin_lock(&this->info_list_lock); |
610 | if (this->first_req != NULL) { | 638 | if (this->first_req != NULL) { |
611 | pr_warning("CAIF: %s(): Received flow off in " | 639 | pr_debug("CAIF: %s(): Received flow off in " |
612 | "control layer", __func__); | 640 | "control layer", __func__); |
613 | } | 641 | } |
614 | spin_unlock(&this->info_list_lock); | 642 | spin_unlock(&this->info_list_lock); |
@@ -633,6 +661,7 @@ static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt) | |||
633 | if (!ctrl->loop_linkused[linkid]) | 661 | if (!ctrl->loop_linkused[linkid]) |
634 | goto found; | 662 | goto found; |
635 | spin_unlock(&ctrl->loop_linkid_lock); | 663 | spin_unlock(&ctrl->loop_linkid_lock); |
664 | pr_err("CAIF: %s(): Out of link-ids\n", __func__); | ||
636 | return -EINVAL; | 665 | return -EINVAL; |
637 | found: | 666 | found: |
638 | if (!ctrl->loop_linkused[linkid]) | 667 | if (!ctrl->loop_linkused[linkid]) |