cfctrl.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. /*
  2. * Copyright (C) ST-Ericsson AB 2010
  3. * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
  4. * License terms: GNU General Public License (GPL) version 2
  5. */
  6. #include <linux/stddef.h>
  7. #include <linux/spinlock.h>
  8. #include <linux/slab.h>
  9. #include <net/caif/caif_layer.h>
  10. #include <net/caif/cfpkt.h>
  11. #include <net/caif/cfctrl.h>
  12. #define container_obj(layr) container_of(layr, struct cfctrl, serv.layer)
  13. #define UTILITY_NAME_LENGTH 16
  14. #define CFPKT_CTRL_PKT_LEN 20
  15. #ifdef CAIF_NO_LOOP
  16. static int handle_loop(struct cfctrl *ctrl,
  17. int cmd, struct cfpkt *pkt){
  18. return CAIF_FAILURE;
  19. }
  20. #else
  21. static int handle_loop(struct cfctrl *ctrl,
  22. int cmd, struct cfpkt *pkt);
  23. #endif
  24. static int cfctrl_recv(struct cflayer *layr, struct cfpkt *pkt);
  25. static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
  26. int phyid);
  27. struct cflayer *cfctrl_create(void)
  28. {
  29. struct dev_info dev_info;
  30. struct cfctrl *this =
  31. kmalloc(sizeof(struct cfctrl), GFP_ATOMIC);
  32. if (!this) {
  33. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  34. return NULL;
  35. }
  36. caif_assert(offsetof(struct cfctrl, serv.layer) == 0);
  37. memset(&dev_info, 0, sizeof(dev_info));
  38. dev_info.id = 0xff;
  39. memset(this, 0, sizeof(*this));
  40. cfsrvl_init(&this->serv, 0, &dev_info);
  41. spin_lock_init(&this->info_list_lock);
  42. atomic_set(&this->req_seq_no, 1);
  43. atomic_set(&this->rsp_seq_no, 1);
  44. this->serv.layer.receive = cfctrl_recv;
  45. sprintf(this->serv.layer.name, "ctrl");
  46. this->serv.layer.ctrlcmd = cfctrl_ctrlcmd;
  47. spin_lock_init(&this->loop_linkid_lock);
  48. this->loop_linkid = 1;
  49. return &this->serv.layer;
  50. }
  51. static bool param_eq(struct cfctrl_link_param *p1, struct cfctrl_link_param *p2)
  52. {
  53. bool eq =
  54. p1->linktype == p2->linktype &&
  55. p1->priority == p2->priority &&
  56. p1->phyid == p2->phyid &&
  57. p1->endpoint == p2->endpoint && p1->chtype == p2->chtype;
  58. if (!eq)
  59. return false;
  60. switch (p1->linktype) {
  61. case CFCTRL_SRV_VEI:
  62. return true;
  63. case CFCTRL_SRV_DATAGRAM:
  64. return p1->u.datagram.connid == p2->u.datagram.connid;
  65. case CFCTRL_SRV_RFM:
  66. return
  67. p1->u.rfm.connid == p2->u.rfm.connid &&
  68. strcmp(p1->u.rfm.volume, p2->u.rfm.volume) == 0;
  69. case CFCTRL_SRV_UTIL:
  70. return
  71. p1->u.utility.fifosize_kb == p2->u.utility.fifosize_kb
  72. && p1->u.utility.fifosize_bufs ==
  73. p2->u.utility.fifosize_bufs
  74. && strcmp(p1->u.utility.name, p2->u.utility.name) == 0
  75. && p1->u.utility.paramlen == p2->u.utility.paramlen
  76. && memcmp(p1->u.utility.params, p2->u.utility.params,
  77. p1->u.utility.paramlen) == 0;
  78. case CFCTRL_SRV_VIDEO:
  79. return p1->u.video.connid == p2->u.video.connid;
  80. case CFCTRL_SRV_DBG:
  81. return true;
  82. case CFCTRL_SRV_DECM:
  83. return false;
  84. default:
  85. return false;
  86. }
  87. return false;
  88. }
  89. bool cfctrl_req_eq(struct cfctrl_request_info *r1,
  90. struct cfctrl_request_info *r2)
  91. {
  92. if (r1->cmd != r2->cmd)
  93. return false;
  94. if (r1->cmd == CFCTRL_CMD_LINK_SETUP)
  95. return param_eq(&r1->param, &r2->param);
  96. else
  97. return r1->channel_id == r2->channel_id;
  98. }
  99. /* Insert request at the end */
  100. void cfctrl_insert_req(struct cfctrl *ctrl,
  101. struct cfctrl_request_info *req)
  102. {
  103. struct cfctrl_request_info *p;
  104. spin_lock(&ctrl->info_list_lock);
  105. req->next = NULL;
  106. atomic_inc(&ctrl->req_seq_no);
  107. req->sequence_no = atomic_read(&ctrl->req_seq_no);
  108. if (ctrl->first_req == NULL) {
  109. ctrl->first_req = req;
  110. spin_unlock(&ctrl->info_list_lock);
  111. return;
  112. }
  113. p = ctrl->first_req;
  114. while (p->next != NULL)
  115. p = p->next;
  116. p->next = req;
  117. spin_unlock(&ctrl->info_list_lock);
  118. }
  119. /* Compare and remove request */
  120. struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl,
  121. struct cfctrl_request_info *req)
  122. {
  123. struct cfctrl_request_info *p;
  124. struct cfctrl_request_info *ret;
  125. spin_lock(&ctrl->info_list_lock);
  126. if (ctrl->first_req == NULL) {
  127. spin_unlock(&ctrl->info_list_lock);
  128. return NULL;
  129. }
  130. if (cfctrl_req_eq(req, ctrl->first_req)) {
  131. ret = ctrl->first_req;
  132. caif_assert(ctrl->first_req);
  133. atomic_set(&ctrl->rsp_seq_no,
  134. ctrl->first_req->sequence_no);
  135. ctrl->first_req = ctrl->first_req->next;
  136. spin_unlock(&ctrl->info_list_lock);
  137. return ret;
  138. }
  139. p = ctrl->first_req;
  140. while (p->next != NULL) {
  141. if (cfctrl_req_eq(req, p->next)) {
  142. pr_warning("CAIF: %s(): Requests are not "
  143. "received in order\n",
  144. __func__);
  145. ret = p->next;
  146. atomic_set(&ctrl->rsp_seq_no,
  147. p->next->sequence_no);
  148. p->next = p->next->next;
  149. spin_unlock(&ctrl->info_list_lock);
  150. return ret;
  151. }
  152. p = p->next;
  153. }
  154. spin_unlock(&ctrl->info_list_lock);
  155. pr_warning("CAIF: %s(): Request does not match\n",
  156. __func__);
  157. return NULL;
  158. }
  159. struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer)
  160. {
  161. struct cfctrl *this = container_obj(layer);
  162. return &this->res;
  163. }
  164. void cfctrl_set_dnlayer(struct cflayer *this, struct cflayer *dn)
  165. {
  166. this->dn = dn;
  167. }
  168. void cfctrl_set_uplayer(struct cflayer *this, struct cflayer *up)
  169. {
  170. this->up = up;
  171. }
  172. static void init_info(struct caif_payload_info *info, struct cfctrl *cfctrl)
  173. {
  174. info->hdr_len = 0;
  175. info->channel_id = cfctrl->serv.layer.id;
  176. info->dev_info = &cfctrl->serv.dev_info;
  177. }
  178. void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid)
  179. {
  180. struct cfctrl *cfctrl = container_obj(layer);
  181. int ret;
  182. struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
  183. if (!pkt) {
  184. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  185. return;
  186. }
  187. caif_assert(offsetof(struct cfctrl, serv.layer) == 0);
  188. init_info(cfpkt_info(pkt), cfctrl);
  189. cfpkt_info(pkt)->dev_info->id = physlinkid;
  190. cfctrl->serv.dev_info.id = physlinkid;
  191. cfpkt_addbdy(pkt, CFCTRL_CMD_ENUM);
  192. cfpkt_addbdy(pkt, physlinkid);
  193. ret =
  194. cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
  195. if (ret < 0) {
  196. pr_err("CAIF: %s(): Could not transmit enum message\n",
  197. __func__);
  198. cfpkt_destroy(pkt);
  199. }
  200. }
  201. int cfctrl_linkup_request(struct cflayer *layer,
  202. struct cfctrl_link_param *param,
  203. struct cflayer *user_layer)
  204. {
  205. struct cfctrl *cfctrl = container_obj(layer);
  206. u32 tmp32;
  207. u16 tmp16;
  208. u8 tmp8;
  209. struct cfctrl_request_info *req;
  210. int ret;
  211. char utility_name[16];
  212. struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
  213. if (!pkt) {
  214. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  215. return -ENOMEM;
  216. }
  217. cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP);
  218. cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype);
  219. cfpkt_addbdy(pkt, (param->priority << 3) + param->phyid);
  220. cfpkt_addbdy(pkt, param->endpoint & 0x03);
  221. switch (param->linktype) {
  222. case CFCTRL_SRV_VEI:
  223. break;
  224. case CFCTRL_SRV_VIDEO:
  225. cfpkt_addbdy(pkt, (u8) param->u.video.connid);
  226. break;
  227. case CFCTRL_SRV_DBG:
  228. break;
  229. case CFCTRL_SRV_DATAGRAM:
  230. tmp32 = cpu_to_le32(param->u.datagram.connid);
  231. cfpkt_add_body(pkt, &tmp32, 4);
  232. break;
  233. case CFCTRL_SRV_RFM:
  234. /* Construct a frame, convert DatagramConnectionID to network
  235. * format long and copy it out...
  236. */
  237. tmp32 = cpu_to_le32(param->u.rfm.connid);
  238. cfpkt_add_body(pkt, &tmp32, 4);
  239. /* Add volume name, including zero termination... */
  240. cfpkt_add_body(pkt, param->u.rfm.volume,
  241. strlen(param->u.rfm.volume) + 1);
  242. break;
  243. case CFCTRL_SRV_UTIL:
  244. tmp16 = cpu_to_le16(param->u.utility.fifosize_kb);
  245. cfpkt_add_body(pkt, &tmp16, 2);
  246. tmp16 = cpu_to_le16(param->u.utility.fifosize_bufs);
  247. cfpkt_add_body(pkt, &tmp16, 2);
  248. memset(utility_name, 0, sizeof(utility_name));
  249. strncpy(utility_name, param->u.utility.name,
  250. UTILITY_NAME_LENGTH - 1);
  251. cfpkt_add_body(pkt, utility_name, UTILITY_NAME_LENGTH);
  252. tmp8 = param->u.utility.paramlen;
  253. cfpkt_add_body(pkt, &tmp8, 1);
  254. cfpkt_add_body(pkt, param->u.utility.params,
  255. param->u.utility.paramlen);
  256. break;
  257. default:
  258. pr_warning("CAIF: %s():Request setup of bad link type = %d\n",
  259. __func__, param->linktype);
  260. return -EINVAL;
  261. }
  262. req = kmalloc(sizeof(*req), GFP_KERNEL);
  263. if (!req) {
  264. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  265. return -ENOMEM;
  266. }
  267. memset(req, 0, sizeof(*req));
  268. req->client_layer = user_layer;
  269. req->cmd = CFCTRL_CMD_LINK_SETUP;
  270. req->param = *param;
  271. cfctrl_insert_req(cfctrl, req);
  272. init_info(cfpkt_info(pkt), cfctrl);
  273. /*
  274. * NOTE:Always send linkup and linkdown request on the same
  275. * device as the payload. Otherwise old queued up payload
  276. * might arrive with the newly allocated channel ID.
  277. */
  278. cfpkt_info(pkt)->dev_info->id = param->phyid;
  279. ret =
  280. cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
  281. if (ret < 0) {
  282. pr_err("CAIF: %s(): Could not transmit linksetup request\n",
  283. __func__);
  284. cfpkt_destroy(pkt);
  285. return -ENODEV;
  286. }
  287. return 0;
  288. }
  289. int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid,
  290. struct cflayer *client)
  291. {
  292. int ret;
  293. struct cfctrl *cfctrl = container_obj(layer);
  294. struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
  295. if (!pkt) {
  296. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  297. return -ENOMEM;
  298. }
  299. cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY);
  300. cfpkt_addbdy(pkt, channelid);
  301. init_info(cfpkt_info(pkt), cfctrl);
  302. ret =
  303. cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
  304. if (ret < 0) {
  305. pr_err("CAIF: %s(): Could not transmit link-down request\n",
  306. __func__);
  307. cfpkt_destroy(pkt);
  308. }
  309. return ret;
  310. }
  311. void cfctrl_sleep_req(struct cflayer *layer)
  312. {
  313. int ret;
  314. struct cfctrl *cfctrl = container_obj(layer);
  315. struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
  316. if (!pkt) {
  317. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  318. return;
  319. }
  320. cfpkt_addbdy(pkt, CFCTRL_CMD_SLEEP);
  321. init_info(cfpkt_info(pkt), cfctrl);
  322. ret =
  323. cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
  324. if (ret < 0)
  325. cfpkt_destroy(pkt);
  326. }
  327. void cfctrl_wake_req(struct cflayer *layer)
  328. {
  329. int ret;
  330. struct cfctrl *cfctrl = container_obj(layer);
  331. struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
  332. if (!pkt) {
  333. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  334. return;
  335. }
  336. cfpkt_addbdy(pkt, CFCTRL_CMD_WAKE);
  337. init_info(cfpkt_info(pkt), cfctrl);
  338. ret =
  339. cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
  340. if (ret < 0)
  341. cfpkt_destroy(pkt);
  342. }
  343. void cfctrl_getstartreason_req(struct cflayer *layer)
  344. {
  345. int ret;
  346. struct cfctrl *cfctrl = container_obj(layer);
  347. struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
  348. if (!pkt) {
  349. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  350. return;
  351. }
  352. cfpkt_addbdy(pkt, CFCTRL_CMD_START_REASON);
  353. init_info(cfpkt_info(pkt), cfctrl);
  354. ret =
  355. cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
  356. if (ret < 0)
  357. cfpkt_destroy(pkt);
  358. }
  359. void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer)
  360. {
  361. struct cfctrl_request_info *p, *req;
  362. struct cfctrl *ctrl = container_obj(layr);
  363. spin_lock(&ctrl->info_list_lock);
  364. if (ctrl->first_req == NULL) {
  365. spin_unlock(&ctrl->info_list_lock);
  366. return;
  367. }
  368. if (ctrl->first_req->client_layer == adap_layer) {
  369. req = ctrl->first_req;
  370. ctrl->first_req = ctrl->first_req->next;
  371. kfree(req);
  372. }
  373. p = ctrl->first_req;
  374. while (p != NULL && p->next != NULL) {
  375. if (p->next->client_layer == adap_layer) {
  376. req = p->next;
  377. p->next = p->next->next;
  378. kfree(p->next);
  379. }
  380. p = p->next;
  381. }
  382. spin_unlock(&ctrl->info_list_lock);
  383. }
  384. static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
  385. {
  386. u8 cmdrsp;
  387. u8 cmd;
  388. int ret = -1;
  389. u16 tmp16;
  390. u8 len;
  391. u8 param[255];
  392. u8 linkid;
  393. struct cfctrl *cfctrl = container_obj(layer);
  394. struct cfctrl_request_info rsp, *req;
  395. cfpkt_extr_head(pkt, &cmdrsp, 1);
  396. cmd = cmdrsp & CFCTRL_CMD_MASK;
  397. if (cmd != CFCTRL_CMD_LINK_ERR
  398. && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) {
  399. if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE)
  400. cmdrsp |= CFCTRL_ERR_BIT;
  401. }
  402. switch (cmd) {
  403. case CFCTRL_CMD_LINK_SETUP:
  404. {
  405. enum cfctrl_srv serv;
  406. enum cfctrl_srv servtype;
  407. u8 endpoint;
  408. u8 physlinkid;
  409. u8 prio;
  410. u8 tmp;
  411. u32 tmp32;
  412. u8 *cp;
  413. int i;
  414. struct cfctrl_link_param linkparam;
  415. memset(&linkparam, 0, sizeof(linkparam));
  416. cfpkt_extr_head(pkt, &tmp, 1);
  417. serv = tmp & CFCTRL_SRV_MASK;
  418. linkparam.linktype = serv;
  419. servtype = tmp >> 4;
  420. linkparam.chtype = servtype;
  421. cfpkt_extr_head(pkt, &tmp, 1);
  422. physlinkid = tmp & 0x07;
  423. prio = tmp >> 3;
  424. linkparam.priority = prio;
  425. linkparam.phyid = physlinkid;
  426. cfpkt_extr_head(pkt, &endpoint, 1);
  427. linkparam.endpoint = endpoint & 0x03;
  428. switch (serv) {
  429. case CFCTRL_SRV_VEI:
  430. case CFCTRL_SRV_DBG:
  431. if (CFCTRL_ERR_BIT & cmdrsp)
  432. break;
  433. /* Link ID */
  434. cfpkt_extr_head(pkt, &linkid, 1);
  435. break;
  436. case CFCTRL_SRV_VIDEO:
  437. cfpkt_extr_head(pkt, &tmp, 1);
  438. linkparam.u.video.connid = tmp;
  439. if (CFCTRL_ERR_BIT & cmdrsp)
  440. break;
  441. /* Link ID */
  442. cfpkt_extr_head(pkt, &linkid, 1);
  443. break;
  444. case CFCTRL_SRV_DATAGRAM:
  445. cfpkt_extr_head(pkt, &tmp32, 4);
  446. linkparam.u.datagram.connid =
  447. le32_to_cpu(tmp32);
  448. if (CFCTRL_ERR_BIT & cmdrsp)
  449. break;
  450. /* Link ID */
  451. cfpkt_extr_head(pkt, &linkid, 1);
  452. break;
  453. case CFCTRL_SRV_RFM:
  454. /* Construct a frame, convert
  455. * DatagramConnectionID
  456. * to network format long and copy it out...
  457. */
  458. cfpkt_extr_head(pkt, &tmp32, 4);
  459. linkparam.u.rfm.connid =
  460. le32_to_cpu(tmp32);
  461. cp = (u8 *) linkparam.u.rfm.volume;
  462. for (cfpkt_extr_head(pkt, &tmp, 1);
  463. cfpkt_more(pkt) && tmp != '\0';
  464. cfpkt_extr_head(pkt, &tmp, 1))
  465. *cp++ = tmp;
  466. *cp = '\0';
  467. if (CFCTRL_ERR_BIT & cmdrsp)
  468. break;
  469. /* Link ID */
  470. cfpkt_extr_head(pkt, &linkid, 1);
  471. break;
  472. case CFCTRL_SRV_UTIL:
  473. /* Construct a frame, convert
  474. * DatagramConnectionID
  475. * to network format long and copy it out...
  476. */
  477. /* Fifosize KB */
  478. cfpkt_extr_head(pkt, &tmp16, 2);
  479. linkparam.u.utility.fifosize_kb =
  480. le16_to_cpu(tmp16);
  481. /* Fifosize bufs */
  482. cfpkt_extr_head(pkt, &tmp16, 2);
  483. linkparam.u.utility.fifosize_bufs =
  484. le16_to_cpu(tmp16);
  485. /* name */
  486. cp = (u8 *) linkparam.u.utility.name;
  487. caif_assert(sizeof(linkparam.u.utility.name)
  488. >= UTILITY_NAME_LENGTH);
  489. for (i = 0;
  490. i < UTILITY_NAME_LENGTH
  491. && cfpkt_more(pkt); i++) {
  492. cfpkt_extr_head(pkt, &tmp, 1);
  493. *cp++ = tmp;
  494. }
  495. /* Length */
  496. cfpkt_extr_head(pkt, &len, 1);
  497. linkparam.u.utility.paramlen = len;
  498. /* Param Data */
  499. cp = linkparam.u.utility.params;
  500. while (cfpkt_more(pkt) && len--) {
  501. cfpkt_extr_head(pkt, &tmp, 1);
  502. *cp++ = tmp;
  503. }
  504. if (CFCTRL_ERR_BIT & cmdrsp)
  505. break;
  506. /* Link ID */
  507. cfpkt_extr_head(pkt, &linkid, 1);
  508. /* Length */
  509. cfpkt_extr_head(pkt, &len, 1);
  510. /* Param Data */
  511. cfpkt_extr_head(pkt, &param, len);
  512. break;
  513. default:
  514. pr_warning("CAIF: %s(): Request setup "
  515. "- invalid link type (%d)",
  516. __func__, serv);
  517. goto error;
  518. }
  519. rsp.cmd = cmd;
  520. rsp.param = linkparam;
  521. req = cfctrl_remove_req(cfctrl, &rsp);
  522. if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) ||
  523. cfpkt_erroneous(pkt)) {
  524. pr_err("CAIF: %s(): Invalid O/E bit or parse "
  525. "error on CAIF control channel",
  526. __func__);
  527. cfctrl->res.reject_rsp(cfctrl->serv.layer.up,
  528. 0,
  529. req ? req->client_layer
  530. : NULL);
  531. } else {
  532. cfctrl->res.linksetup_rsp(cfctrl->serv.
  533. layer.up, linkid,
  534. serv, physlinkid,
  535. req ? req->
  536. client_layer : NULL);
  537. }
  538. if (req != NULL)
  539. kfree(req);
  540. }
  541. break;
  542. case CFCTRL_CMD_LINK_DESTROY:
  543. cfpkt_extr_head(pkt, &linkid, 1);
  544. cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid);
  545. break;
  546. case CFCTRL_CMD_LINK_ERR:
  547. pr_err("CAIF: %s(): Frame Error Indication received\n",
  548. __func__);
  549. cfctrl->res.linkerror_ind();
  550. break;
  551. case CFCTRL_CMD_ENUM:
  552. cfctrl->res.enum_rsp();
  553. break;
  554. case CFCTRL_CMD_SLEEP:
  555. cfctrl->res.sleep_rsp();
  556. break;
  557. case CFCTRL_CMD_WAKE:
  558. cfctrl->res.wake_rsp();
  559. break;
  560. case CFCTRL_CMD_LINK_RECONF:
  561. cfctrl->res.restart_rsp();
  562. break;
  563. case CFCTRL_CMD_RADIO_SET:
  564. cfctrl->res.radioset_rsp();
  565. break;
  566. default:
  567. pr_err("CAIF: %s(): Unrecognized Control Frame\n", __func__);
  568. goto error;
  569. break;
  570. }
  571. ret = 0;
  572. error:
  573. cfpkt_destroy(pkt);
  574. return ret;
  575. }
  576. static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
  577. int phyid)
  578. {
  579. struct cfctrl *this = container_obj(layr);
  580. switch (ctrl) {
  581. case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND:
  582. case CAIF_CTRLCMD_FLOW_OFF_IND:
  583. spin_lock(&this->info_list_lock);
  584. if (this->first_req != NULL) {
  585. pr_debug("CAIF: %s(): Received flow off in "
  586. "control layer", __func__);
  587. }
  588. spin_unlock(&this->info_list_lock);
  589. break;
  590. default:
  591. break;
  592. }
  593. }
  594. #ifndef CAIF_NO_LOOP
  595. static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt)
  596. {
  597. static int last_linkid;
  598. u8 linkid, linktype, tmp;
  599. switch (cmd) {
  600. case CFCTRL_CMD_LINK_SETUP:
  601. spin_lock(&ctrl->loop_linkid_lock);
  602. for (linkid = last_linkid + 1; linkid < 255; linkid++)
  603. if (!ctrl->loop_linkused[linkid])
  604. goto found;
  605. for (linkid = last_linkid - 1; linkid > 0; linkid--)
  606. if (!ctrl->loop_linkused[linkid])
  607. goto found;
  608. spin_unlock(&ctrl->loop_linkid_lock);
  609. pr_err("CAIF: %s(): Out of link-ids\n", __func__);
  610. return -EINVAL;
  611. found:
  612. if (!ctrl->loop_linkused[linkid])
  613. ctrl->loop_linkused[linkid] = 1;
  614. last_linkid = linkid;
  615. cfpkt_add_trail(pkt, &linkid, 1);
  616. spin_unlock(&ctrl->loop_linkid_lock);
  617. cfpkt_peek_head(pkt, &linktype, 1);
  618. if (linktype == CFCTRL_SRV_UTIL) {
  619. tmp = 0x01;
  620. cfpkt_add_trail(pkt, &tmp, 1);
  621. cfpkt_add_trail(pkt, &tmp, 1);
  622. }
  623. break;
  624. case CFCTRL_CMD_LINK_DESTROY:
  625. spin_lock(&ctrl->loop_linkid_lock);
  626. cfpkt_peek_head(pkt, &linkid, 1);
  627. ctrl->loop_linkused[linkid] = 0;
  628. spin_unlock(&ctrl->loop_linkid_lock);
  629. break;
  630. default:
  631. break;
  632. }
  633. return CAIF_SUCCESS;
  634. }
  635. #endif