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