cfcnfg.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  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/kernel.h>
  7. #include <linux/stddef.h>
  8. #include <linux/slab.h>
  9. #include <net/caif/caif_layer.h>
  10. #include <net/caif/cfpkt.h>
  11. #include <net/caif/cfcnfg.h>
  12. #include <net/caif/cfctrl.h>
  13. #include <net/caif/cfmuxl.h>
  14. #include <net/caif/cffrml.h>
  15. #include <net/caif/cfserl.h>
  16. #include <net/caif/cfsrvl.h>
  17. #include <linux/module.h>
  18. #include <asm/atomic.h>
  19. #define MAX_PHY_LAYERS 7
  20. #define PHY_NAME_LEN 20
  21. #define container_obj(layr) container_of(layr, struct cfcnfg, layer)
  22. /* Information about CAIF physical interfaces held by Config Module in order
  23. * to manage physical interfaces
  24. */
  25. struct cfcnfg_phyinfo {
  26. /* Pointer to the layer below the MUX (framing layer) */
  27. struct cflayer *frm_layer;
  28. /* Pointer to the lowest actual physical layer */
  29. struct cflayer *phy_layer;
  30. /* Unique identifier of the physical interface */
  31. unsigned int id;
  32. /* Preference of the physical in interface */
  33. enum cfcnfg_phy_preference pref;
  34. /* Reference count, number of channels using the device */
  35. int phy_ref_count;
  36. /* Information about the physical device */
  37. struct dev_info dev_info;
  38. };
  39. struct cfcnfg {
  40. struct cflayer layer;
  41. struct cflayer *ctrl;
  42. struct cflayer *mux;
  43. u8 last_phyid;
  44. struct cfcnfg_phyinfo phy_layers[MAX_PHY_LAYERS];
  45. };
  46. static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id,
  47. enum cfctrl_srv serv, u8 phyid,
  48. struct cflayer *adapt_layer);
  49. static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id,
  50. struct cflayer *client_layer);
  51. static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
  52. struct cflayer *adapt_layer);
  53. static void cfctrl_resp_func(void);
  54. static void cfctrl_enum_resp(void);
  55. struct cfcnfg *cfcnfg_create(void)
  56. {
  57. struct cfcnfg *this;
  58. struct cfctrl_rsp *resp;
  59. /* Initiate this layer */
  60. this = kmalloc(sizeof(struct cfcnfg), GFP_ATOMIC);
  61. if (!this) {
  62. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  63. return NULL;
  64. }
  65. memset(this, 0, sizeof(struct cfcnfg));
  66. this->mux = cfmuxl_create();
  67. if (!this->mux)
  68. goto out_of_mem;
  69. this->ctrl = cfctrl_create();
  70. if (!this->ctrl)
  71. goto out_of_mem;
  72. /* Initiate response functions */
  73. resp = cfctrl_get_respfuncs(this->ctrl);
  74. resp->enum_rsp = cfctrl_enum_resp;
  75. resp->linkerror_ind = cfctrl_resp_func;
  76. resp->linkdestroy_rsp = cfcnfg_linkdestroy_rsp;
  77. resp->sleep_rsp = cfctrl_resp_func;
  78. resp->wake_rsp = cfctrl_resp_func;
  79. resp->restart_rsp = cfctrl_resp_func;
  80. resp->radioset_rsp = cfctrl_resp_func;
  81. resp->linksetup_rsp = cfcnfg_linkup_rsp;
  82. resp->reject_rsp = cfcnfg_reject_rsp;
  83. this->last_phyid = 1;
  84. cfmuxl_set_uplayer(this->mux, this->ctrl, 0);
  85. layer_set_dn(this->ctrl, this->mux);
  86. layer_set_up(this->ctrl, this);
  87. return this;
  88. out_of_mem:
  89. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  90. kfree(this->mux);
  91. kfree(this->ctrl);
  92. kfree(this);
  93. return NULL;
  94. }
  95. EXPORT_SYMBOL(cfcnfg_create);
  96. void cfcnfg_remove(struct cfcnfg *cfg)
  97. {
  98. if (cfg) {
  99. kfree(cfg->mux);
  100. kfree(cfg->ctrl);
  101. kfree(cfg);
  102. }
  103. }
  104. static void cfctrl_resp_func(void)
  105. {
  106. }
  107. static void cfctrl_enum_resp(void)
  108. {
  109. }
  110. struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg,
  111. enum cfcnfg_phy_preference phy_pref)
  112. {
  113. u16 i;
  114. /* Try to match with specified preference */
  115. for (i = 1; i < MAX_PHY_LAYERS; i++) {
  116. if (cnfg->phy_layers[i].id == i &&
  117. cnfg->phy_layers[i].pref == phy_pref &&
  118. cnfg->phy_layers[i].frm_layer != NULL) {
  119. caif_assert(cnfg->phy_layers != NULL);
  120. caif_assert(cnfg->phy_layers[i].id == i);
  121. return &cnfg->phy_layers[i].dev_info;
  122. }
  123. }
  124. /* Otherwise just return something */
  125. for (i = 1; i < MAX_PHY_LAYERS; i++) {
  126. if (cnfg->phy_layers[i].id == i) {
  127. caif_assert(cnfg->phy_layers != NULL);
  128. caif_assert(cnfg->phy_layers[i].id == i);
  129. return &cnfg->phy_layers[i].dev_info;
  130. }
  131. }
  132. return NULL;
  133. }
  134. static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo(struct cfcnfg *cnfg,
  135. u8 phyid)
  136. {
  137. int i;
  138. /* Try to match with specified preference */
  139. for (i = 0; i < MAX_PHY_LAYERS; i++)
  140. if (cnfg->phy_layers[i].frm_layer != NULL &&
  141. cnfg->phy_layers[i].id == phyid)
  142. return &cnfg->phy_layers[i];
  143. return NULL;
  144. }
  145. int cfcnfg_get_named(struct cfcnfg *cnfg, char *name)
  146. {
  147. int i;
  148. /* Try to match with specified name */
  149. for (i = 0; i < MAX_PHY_LAYERS; i++) {
  150. if (cnfg->phy_layers[i].frm_layer != NULL
  151. && strcmp(cnfg->phy_layers[i].phy_layer->name,
  152. name) == 0)
  153. return cnfg->phy_layers[i].frm_layer->id;
  154. }
  155. return 0;
  156. }
  157. /*
  158. * NOTE: What happens on destroy failure:
  159. * 1a) No response - Too early
  160. * This will not happen because enumerate has already
  161. * completed.
  162. * 1b) No response - FATAL
  163. * Not handled, but this should be a CAIF PROTOCOL ERROR
  164. * Modem error, response is really expected - this
  165. * case is not really handled.
  166. * 2) O/E-bit indicate error
  167. * Ignored - this link is destroyed anyway.
  168. * 3) Not able to match on request
  169. * Not handled, but this should be a CAIF PROTOCOL ERROR
  170. * 4) Link-Error - (no response)
  171. * Not handled, but this should be a CAIF PROTOCOL ERROR
  172. */
  173. int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer)
  174. {
  175. u8 channel_id = 0;
  176. int ret = 0;
  177. struct cfcnfg_phyinfo *phyinfo = NULL;
  178. u8 phyid = 0;
  179. caif_assert(adap_layer != NULL);
  180. channel_id = adap_layer->id;
  181. if (channel_id == 0) {
  182. pr_err("CAIF: %s():adap_layer->id is 0\n", __func__);
  183. ret = -ENOTCONN;
  184. goto end;
  185. }
  186. if (adap_layer->dn == NULL) {
  187. pr_err("CAIF: %s():adap_layer->dn is NULL\n", __func__);
  188. ret = -ENODEV;
  189. goto end;
  190. }
  191. if (adap_layer->dn != NULL)
  192. phyid = cfsrvl_getphyid(adap_layer->dn);
  193. phyinfo = cfcnfg_get_phyinfo(cnfg, phyid);
  194. if (phyinfo == NULL) {
  195. pr_warning("CAIF: %s(): No interface to send disconnect to\n",
  196. __func__);
  197. ret = -ENODEV;
  198. goto end;
  199. }
  200. if (phyinfo->id != phyid
  201. || phyinfo->phy_layer->id != phyid
  202. || phyinfo->frm_layer->id != phyid) {
  203. pr_err("CAIF: %s(): Inconsistency in phy registration\n",
  204. __func__);
  205. ret = -EINVAL;
  206. goto end;
  207. }
  208. ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer);
  209. end:
  210. if (phyinfo != NULL && --phyinfo->phy_ref_count == 0 &&
  211. phyinfo->phy_layer != NULL &&
  212. phyinfo->phy_layer->modemcmd != NULL) {
  213. phyinfo->phy_layer->modemcmd(phyinfo->phy_layer,
  214. _CAIF_MODEMCMD_PHYIF_USELESS);
  215. }
  216. return ret;
  217. }
  218. EXPORT_SYMBOL(cfcnfg_disconn_adapt_layer);
  219. static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id,
  220. struct cflayer *client_layer)
  221. {
  222. struct cfcnfg *cnfg = container_obj(layer);
  223. struct cflayer *servl;
  224. /*
  225. * 1) Remove service from the MUX layer. The MUX must
  226. * guarante that no more payload sent "upwards" (receive)
  227. */
  228. servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id);
  229. if (servl == NULL) {
  230. pr_err("CAIF: %s(): PROTOCOL ERROR "
  231. "- Error removing service_layer Channel_Id(%d)",
  232. __func__, channel_id);
  233. return;
  234. }
  235. caif_assert(channel_id == servl->id);
  236. if (servl != client_layer && servl->up != client_layer) {
  237. pr_err("CAIF: %s(): Error removing service_layer "
  238. "Channel_Id(%d) %p %p",
  239. __func__, channel_id, (void *) servl,
  240. (void *) client_layer);
  241. return;
  242. }
  243. /*
  244. * 2) DEINIT_RSP must guarantee that no more packets are transmitted
  245. * from client (adap_layer) when it returns.
  246. */
  247. if (servl->ctrlcmd == NULL) {
  248. pr_err("CAIF: %s(): Error servl->ctrlcmd == NULL", __func__);
  249. return;
  250. }
  251. servl->ctrlcmd(servl, CAIF_CTRLCMD_DEINIT_RSP, 0);
  252. /* 3) It is now safe to destroy the service layer. */
  253. cfservl_destroy(servl);
  254. }
  255. /*
  256. * NOTE: What happens on linksetup failure:
  257. * 1a) No response - Too early
  258. * This will not happen because enumerate is secured
  259. * before using interface.
  260. * 1b) No response - FATAL
  261. * Not handled, but this should be a CAIF PROTOCOL ERROR
  262. * Modem error, response is really expected - this case is
  263. * not really handled.
  264. * 2) O/E-bit indicate error
  265. * Handled in cnfg_reject_rsp
  266. * 3) Not able to match on request
  267. * Not handled, but this should be a CAIF PROTOCOL ERROR
  268. * 4) Link-Error - (no response)
  269. * Not handled, but this should be a CAIF PROTOCOL ERROR
  270. */
  271. int
  272. cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
  273. struct cfctrl_link_param *param,
  274. struct cflayer *adap_layer)
  275. {
  276. struct cflayer *frml;
  277. if (adap_layer == NULL) {
  278. pr_err("CAIF: %s(): adap_layer is zero", __func__);
  279. return -EINVAL;
  280. }
  281. if (adap_layer->receive == NULL) {
  282. pr_err("CAIF: %s(): adap_layer->receive is NULL", __func__);
  283. return -EINVAL;
  284. }
  285. if (adap_layer->ctrlcmd == NULL) {
  286. pr_err("CAIF: %s(): adap_layer->ctrlcmd == NULL", __func__);
  287. return -EINVAL;
  288. }
  289. frml = cnfg->phy_layers[param->phyid].frm_layer;
  290. if (frml == NULL) {
  291. pr_err("CAIF: %s(): Specified PHY type does not exist!",
  292. __func__);
  293. return -ENODEV;
  294. }
  295. caif_assert(param->phyid == cnfg->phy_layers[param->phyid].id);
  296. caif_assert(cnfg->phy_layers[param->phyid].frm_layer->id ==
  297. param->phyid);
  298. caif_assert(cnfg->phy_layers[param->phyid].phy_layer->id ==
  299. param->phyid);
  300. /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
  301. cfctrl_enum_req(cnfg->ctrl, param->phyid);
  302. cfctrl_linkup_request(cnfg->ctrl, param, adap_layer);
  303. return 0;
  304. }
  305. EXPORT_SYMBOL(cfcnfg_add_adaptation_layer);
  306. static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
  307. struct cflayer *adapt_layer)
  308. {
  309. if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL)
  310. adapt_layer->ctrlcmd(adapt_layer,
  311. CAIF_CTRLCMD_INIT_FAIL_RSP, 0);
  312. }
  313. static void
  314. cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
  315. u8 phyid, struct cflayer *adapt_layer)
  316. {
  317. struct cfcnfg *cnfg = container_obj(layer);
  318. struct cflayer *servicel = NULL;
  319. struct cfcnfg_phyinfo *phyinfo;
  320. if (adapt_layer == NULL) {
  321. pr_err("CAIF: %s(): PROTOCOL ERROR "
  322. "- LinkUp Request/Response did not match\n", __func__);
  323. return;
  324. }
  325. caif_assert(cnfg != NULL);
  326. caif_assert(phyid != 0);
  327. phyinfo = &cnfg->phy_layers[phyid];
  328. caif_assert(phyinfo != NULL);
  329. caif_assert(phyinfo->id == phyid);
  330. caif_assert(phyinfo->phy_layer != NULL);
  331. caif_assert(phyinfo->phy_layer->id == phyid);
  332. if (phyinfo != NULL &&
  333. phyinfo->phy_ref_count++ == 0 &&
  334. phyinfo->phy_layer != NULL &&
  335. phyinfo->phy_layer->modemcmd != NULL) {
  336. caif_assert(phyinfo->phy_layer->id == phyid);
  337. phyinfo->phy_layer->modemcmd(phyinfo->phy_layer,
  338. _CAIF_MODEMCMD_PHYIF_USEFULL);
  339. }
  340. adapt_layer->id = channel_id;
  341. switch (serv) {
  342. case CFCTRL_SRV_VEI:
  343. servicel = cfvei_create(channel_id, &phyinfo->dev_info);
  344. break;
  345. case CFCTRL_SRV_DATAGRAM:
  346. servicel = cfdgml_create(channel_id, &phyinfo->dev_info);
  347. break;
  348. case CFCTRL_SRV_RFM:
  349. servicel = cfrfml_create(channel_id, &phyinfo->dev_info);
  350. break;
  351. case CFCTRL_SRV_UTIL:
  352. servicel = cfutill_create(channel_id, &phyinfo->dev_info);
  353. break;
  354. case CFCTRL_SRV_VIDEO:
  355. servicel = cfvidl_create(channel_id, &phyinfo->dev_info);
  356. break;
  357. case CFCTRL_SRV_DBG:
  358. servicel = cfdbgl_create(channel_id, &phyinfo->dev_info);
  359. break;
  360. default:
  361. pr_err("CAIF: %s(): Protocol error. "
  362. "Link setup response - unknown channel type\n",
  363. __func__);
  364. return;
  365. }
  366. if (!servicel) {
  367. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  368. return;
  369. }
  370. layer_set_dn(servicel, cnfg->mux);
  371. cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id);
  372. layer_set_up(servicel, adapt_layer);
  373. layer_set_dn(adapt_layer, servicel);
  374. servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0);
  375. }
  376. void
  377. cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
  378. void *dev, struct cflayer *phy_layer, u16 *phyid,
  379. enum cfcnfg_phy_preference pref,
  380. bool fcs, bool stx)
  381. {
  382. struct cflayer *frml;
  383. struct cflayer *phy_driver = NULL;
  384. int i;
  385. if (cnfg->phy_layers[cnfg->last_phyid].frm_layer == NULL) {
  386. *phyid = cnfg->last_phyid;
  387. /* range: * 1..(MAX_PHY_LAYERS-1) */
  388. cnfg->last_phyid =
  389. (cnfg->last_phyid % (MAX_PHY_LAYERS - 1)) + 1;
  390. } else {
  391. *phyid = 0;
  392. for (i = 1; i < MAX_PHY_LAYERS; i++) {
  393. if (cnfg->phy_layers[i].frm_layer == NULL) {
  394. *phyid = i;
  395. break;
  396. }
  397. }
  398. }
  399. if (*phyid == 0) {
  400. pr_err("CAIF: %s(): No Available PHY ID\n", __func__);
  401. return;
  402. }
  403. switch (phy_type) {
  404. case CFPHYTYPE_FRAG:
  405. phy_driver =
  406. cfserl_create(CFPHYTYPE_FRAG, *phyid, stx);
  407. if (!phy_driver) {
  408. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  409. return;
  410. }
  411. break;
  412. case CFPHYTYPE_CAIF:
  413. phy_driver = NULL;
  414. break;
  415. default:
  416. pr_err("CAIF: %s(): %d", __func__, phy_type);
  417. return;
  418. break;
  419. }
  420. phy_layer->id = *phyid;
  421. cnfg->phy_layers[*phyid].pref = pref;
  422. cnfg->phy_layers[*phyid].id = *phyid;
  423. cnfg->phy_layers[*phyid].dev_info.id = *phyid;
  424. cnfg->phy_layers[*phyid].dev_info.dev = dev;
  425. cnfg->phy_layers[*phyid].phy_layer = phy_layer;
  426. cnfg->phy_layers[*phyid].phy_ref_count = 0;
  427. phy_layer->type = phy_type;
  428. frml = cffrml_create(*phyid, fcs);
  429. if (!frml) {
  430. pr_warning("CAIF: %s(): Out of memory\n", __func__);
  431. return;
  432. }
  433. cnfg->phy_layers[*phyid].frm_layer = frml;
  434. cfmuxl_set_dnlayer(cnfg->mux, frml, *phyid);
  435. layer_set_up(frml, cnfg->mux);
  436. if (phy_driver != NULL) {
  437. phy_driver->id = *phyid;
  438. layer_set_dn(frml, phy_driver);
  439. layer_set_up(phy_driver, frml);
  440. layer_set_dn(phy_driver, phy_layer);
  441. layer_set_up(phy_layer, phy_driver);
  442. } else {
  443. layer_set_dn(frml, phy_layer);
  444. layer_set_up(phy_layer, frml);
  445. }
  446. }
  447. EXPORT_SYMBOL(cfcnfg_add_phy_layer);
  448. int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer)
  449. {
  450. struct cflayer *frml, *frml_dn;
  451. u16 phyid;
  452. phyid = phy_layer->id;
  453. caif_assert(phyid == cnfg->phy_layers[phyid].id);
  454. caif_assert(phy_layer == cnfg->phy_layers[phyid].phy_layer);
  455. caif_assert(phy_layer->id == phyid);
  456. caif_assert(cnfg->phy_layers[phyid].frm_layer->id == phyid);
  457. memset(&cnfg->phy_layers[phy_layer->id], 0,
  458. sizeof(struct cfcnfg_phyinfo));
  459. frml = cfmuxl_remove_dnlayer(cnfg->mux, phy_layer->id);
  460. frml_dn = frml->dn;
  461. cffrml_set_uplayer(frml, NULL);
  462. cffrml_set_dnlayer(frml, NULL);
  463. kfree(frml);
  464. if (phy_layer != frml_dn) {
  465. layer_set_up(frml_dn, NULL);
  466. layer_set_dn(frml_dn, NULL);
  467. kfree(frml_dn);
  468. }
  469. layer_set_up(phy_layer, NULL);
  470. return 0;
  471. }
  472. EXPORT_SYMBOL(cfcnfg_del_phy_layer);