aboutsummaryrefslogtreecommitdiffstats
path: root/net/caif/cfctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/caif/cfctrl.c')
-rw-r--r--net/caif/cfctrl.c95
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
33struct cflayer *cfctrl_create(void) 33struct 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
130static 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 */
145struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, 133struct 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
237void cfctrl_linkup_request(struct cflayer *layer, 225int 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
319int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, 315int 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
390void 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
395static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) 422static 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;
637found: 666found:
638 if (!ctrl->loop_linkused[linkid]) 667 if (!ctrl->loop_linkused[linkid])