0001
0002
0003
0004
0005
0006
0007 #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
0008
0009 #include <linux/kernel.h>
0010 #include <linux/stddef.h>
0011 #include <linux/slab.h>
0012 #include <linux/netdevice.h>
0013 #include <linux/module.h>
0014 #include <net/caif/caif_layer.h>
0015 #include <net/caif/cfpkt.h>
0016 #include <net/caif/cfcnfg.h>
0017 #include <net/caif/cfctrl.h>
0018 #include <net/caif/cfmuxl.h>
0019 #include <net/caif/cffrml.h>
0020 #include <net/caif/cfserl.h>
0021 #include <net/caif/cfsrvl.h>
0022 #include <net/caif/caif_dev.h>
0023
0024 #define container_obj(layr) container_of(layr, struct cfcnfg, layer)
0025
0026
0027
0028
0029 struct cfcnfg_phyinfo {
0030 struct list_head node;
0031 bool up;
0032
0033
0034 struct cflayer *frm_layer;
0035
0036 struct cflayer *phy_layer;
0037
0038 unsigned int id;
0039
0040 enum cfcnfg_phy_preference pref;
0041
0042
0043 struct dev_info dev_info;
0044
0045
0046 int ifindex;
0047
0048
0049 int head_room;
0050
0051
0052 bool use_fcs;
0053 };
0054
0055 struct cfcnfg {
0056 struct cflayer layer;
0057 struct cflayer *ctrl;
0058 struct cflayer *mux;
0059 struct list_head phys;
0060 struct mutex lock;
0061 };
0062
0063 static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id,
0064 enum cfctrl_srv serv, u8 phyid,
0065 struct cflayer *adapt_layer);
0066 static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id);
0067 static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
0068 struct cflayer *adapt_layer);
0069 static void cfctrl_resp_func(void);
0070 static void cfctrl_enum_resp(void);
0071
0072 struct cfcnfg *cfcnfg_create(void)
0073 {
0074 struct cfcnfg *this;
0075 struct cfctrl_rsp *resp;
0076
0077 might_sleep();
0078
0079
0080 this = kzalloc(sizeof(struct cfcnfg), GFP_ATOMIC);
0081 if (!this)
0082 return NULL;
0083 this->mux = cfmuxl_create();
0084 if (!this->mux)
0085 goto out_of_mem;
0086 this->ctrl = cfctrl_create();
0087 if (!this->ctrl)
0088 goto out_of_mem;
0089
0090 resp = cfctrl_get_respfuncs(this->ctrl);
0091 resp->enum_rsp = cfctrl_enum_resp;
0092 resp->linkerror_ind = cfctrl_resp_func;
0093 resp->linkdestroy_rsp = cfcnfg_linkdestroy_rsp;
0094 resp->sleep_rsp = cfctrl_resp_func;
0095 resp->wake_rsp = cfctrl_resp_func;
0096 resp->restart_rsp = cfctrl_resp_func;
0097 resp->radioset_rsp = cfctrl_resp_func;
0098 resp->linksetup_rsp = cfcnfg_linkup_rsp;
0099 resp->reject_rsp = cfcnfg_reject_rsp;
0100 INIT_LIST_HEAD(&this->phys);
0101
0102 cfmuxl_set_uplayer(this->mux, this->ctrl, 0);
0103 layer_set_dn(this->ctrl, this->mux);
0104 layer_set_up(this->ctrl, this);
0105 mutex_init(&this->lock);
0106
0107 return this;
0108 out_of_mem:
0109 synchronize_rcu();
0110
0111 kfree(this->mux);
0112 kfree(this->ctrl);
0113 kfree(this);
0114 return NULL;
0115 }
0116
0117 void cfcnfg_remove(struct cfcnfg *cfg)
0118 {
0119 might_sleep();
0120 if (cfg) {
0121 synchronize_rcu();
0122
0123 kfree(cfg->mux);
0124 cfctrl_remove(cfg->ctrl);
0125 kfree(cfg);
0126 }
0127 }
0128
0129 static void cfctrl_resp_func(void)
0130 {
0131 }
0132
0133 static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo_rcu(struct cfcnfg *cnfg,
0134 u8 phyid)
0135 {
0136 struct cfcnfg_phyinfo *phy;
0137
0138 list_for_each_entry_rcu(phy, &cnfg->phys, node)
0139 if (phy->id == phyid)
0140 return phy;
0141 return NULL;
0142 }
0143
0144 static void cfctrl_enum_resp(void)
0145 {
0146 }
0147
0148 static struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg,
0149 enum cfcnfg_phy_preference phy_pref)
0150 {
0151
0152 struct cfcnfg_phyinfo *phy;
0153
0154 list_for_each_entry_rcu(phy, &cnfg->phys, node) {
0155 if (phy->up && phy->pref == phy_pref &&
0156 phy->frm_layer != NULL)
0157
0158 return &phy->dev_info;
0159 }
0160
0161
0162 list_for_each_entry_rcu(phy, &cnfg->phys, node)
0163 if (phy->up)
0164 return &phy->dev_info;
0165
0166 return NULL;
0167 }
0168
0169 static int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi)
0170 {
0171 struct cfcnfg_phyinfo *phy;
0172
0173 list_for_each_entry_rcu(phy, &cnfg->phys, node)
0174 if (phy->ifindex == ifi && phy->up)
0175 return phy->id;
0176 return -ENODEV;
0177 }
0178
0179 int caif_disconnect_client(struct net *net, struct cflayer *adap_layer)
0180 {
0181 u8 channel_id;
0182 struct cfcnfg *cfg = get_cfcnfg(net);
0183
0184 caif_assert(adap_layer != NULL);
0185 cfctrl_cancel_req(cfg->ctrl, adap_layer);
0186 channel_id = adap_layer->id;
0187 if (channel_id != 0) {
0188 struct cflayer *servl;
0189 servl = cfmuxl_remove_uplayer(cfg->mux, channel_id);
0190 cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer);
0191 if (servl != NULL)
0192 layer_set_up(servl, NULL);
0193 } else
0194 pr_debug("nothing to disconnect\n");
0195
0196
0197 synchronize_rcu();
0198 if (adap_layer->ctrlcmd != NULL)
0199 adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0);
0200 return 0;
0201
0202 }
0203 EXPORT_SYMBOL(caif_disconnect_client);
0204
0205 static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id)
0206 {
0207 }
0208
0209 static const int protohead[CFCTRL_SRV_MASK] = {
0210 [CFCTRL_SRV_VEI] = 4,
0211 [CFCTRL_SRV_DATAGRAM] = 7,
0212 [CFCTRL_SRV_UTIL] = 4,
0213 [CFCTRL_SRV_RFM] = 3,
0214 [CFCTRL_SRV_DBG] = 3,
0215 };
0216
0217
0218 static int caif_connect_req_to_link_param(struct cfcnfg *cnfg,
0219 struct caif_connect_request *s,
0220 struct cfctrl_link_param *l)
0221 {
0222 struct dev_info *dev_info;
0223 enum cfcnfg_phy_preference pref;
0224 int res;
0225
0226 memset(l, 0, sizeof(*l));
0227
0228 l->priority = CAIF_PRIO_MAX - s->priority + 1;
0229
0230 if (s->ifindex != 0) {
0231 res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex);
0232 if (res < 0)
0233 return res;
0234 l->phyid = res;
0235 } else {
0236 switch (s->link_selector) {
0237 case CAIF_LINK_HIGH_BANDW:
0238 pref = CFPHYPREF_HIGH_BW;
0239 break;
0240 case CAIF_LINK_LOW_LATENCY:
0241 pref = CFPHYPREF_LOW_LAT;
0242 break;
0243 default:
0244 return -EINVAL;
0245 }
0246 dev_info = cfcnfg_get_phyid(cnfg, pref);
0247 if (dev_info == NULL)
0248 return -ENODEV;
0249 l->phyid = dev_info->id;
0250 }
0251 switch (s->protocol) {
0252 case CAIFPROTO_AT:
0253 l->linktype = CFCTRL_SRV_VEI;
0254 l->endpoint = (s->sockaddr.u.at.type >> 2) & 0x3;
0255 l->chtype = s->sockaddr.u.at.type & 0x3;
0256 break;
0257 case CAIFPROTO_DATAGRAM:
0258 l->linktype = CFCTRL_SRV_DATAGRAM;
0259 l->chtype = 0x00;
0260 l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
0261 break;
0262 case CAIFPROTO_DATAGRAM_LOOP:
0263 l->linktype = CFCTRL_SRV_DATAGRAM;
0264 l->chtype = 0x03;
0265 l->endpoint = 0x00;
0266 l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
0267 break;
0268 case CAIFPROTO_RFM:
0269 l->linktype = CFCTRL_SRV_RFM;
0270 l->u.datagram.connid = s->sockaddr.u.rfm.connection_id;
0271 strlcpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume,
0272 sizeof(l->u.rfm.volume));
0273 break;
0274 case CAIFPROTO_UTIL:
0275 l->linktype = CFCTRL_SRV_UTIL;
0276 l->endpoint = 0x00;
0277 l->chtype = 0x00;
0278 strlcpy(l->u.utility.name, s->sockaddr.u.util.service,
0279 sizeof(l->u.utility.name));
0280 caif_assert(sizeof(l->u.utility.name) > 10);
0281 l->u.utility.paramlen = s->param.size;
0282 if (l->u.utility.paramlen > sizeof(l->u.utility.params))
0283 l->u.utility.paramlen = sizeof(l->u.utility.params);
0284
0285 memcpy(l->u.utility.params, s->param.data,
0286 l->u.utility.paramlen);
0287
0288 break;
0289 case CAIFPROTO_DEBUG:
0290 l->linktype = CFCTRL_SRV_DBG;
0291 l->endpoint = s->sockaddr.u.dbg.service;
0292 l->chtype = s->sockaddr.u.dbg.type;
0293 break;
0294 default:
0295 return -EINVAL;
0296 }
0297 return 0;
0298 }
0299
0300 int caif_connect_client(struct net *net, struct caif_connect_request *conn_req,
0301 struct cflayer *adap_layer, int *ifindex,
0302 int *proto_head, int *proto_tail)
0303 {
0304 struct cflayer *frml;
0305 struct cfcnfg_phyinfo *phy;
0306 int err;
0307 struct cfctrl_link_param param;
0308 struct cfcnfg *cfg = get_cfcnfg(net);
0309
0310 rcu_read_lock();
0311 err = caif_connect_req_to_link_param(cfg, conn_req, ¶m);
0312 if (err)
0313 goto unlock;
0314
0315 phy = cfcnfg_get_phyinfo_rcu(cfg, param.phyid);
0316 if (!phy) {
0317 err = -ENODEV;
0318 goto unlock;
0319 }
0320 err = -EINVAL;
0321
0322 if (adap_layer == NULL) {
0323 pr_err("adap_layer is zero\n");
0324 goto unlock;
0325 }
0326 if (adap_layer->receive == NULL) {
0327 pr_err("adap_layer->receive is NULL\n");
0328 goto unlock;
0329 }
0330 if (adap_layer->ctrlcmd == NULL) {
0331 pr_err("adap_layer->ctrlcmd == NULL\n");
0332 goto unlock;
0333 }
0334
0335 err = -ENODEV;
0336 frml = phy->frm_layer;
0337 if (frml == NULL) {
0338 pr_err("Specified PHY type does not exist!\n");
0339 goto unlock;
0340 }
0341 caif_assert(param.phyid == phy->id);
0342 caif_assert(phy->frm_layer->id ==
0343 param.phyid);
0344 caif_assert(phy->phy_layer->id ==
0345 param.phyid);
0346
0347 *ifindex = phy->ifindex;
0348 *proto_tail = 2;
0349 *proto_head = protohead[param.linktype] + phy->head_room;
0350
0351 rcu_read_unlock();
0352
0353
0354 cfctrl_enum_req(cfg->ctrl, param.phyid);
0355 return cfctrl_linkup_request(cfg->ctrl, ¶m, adap_layer);
0356
0357 unlock:
0358 rcu_read_unlock();
0359 return err;
0360 }
0361 EXPORT_SYMBOL(caif_connect_client);
0362
0363 static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
0364 struct cflayer *adapt_layer)
0365 {
0366 if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL)
0367 adapt_layer->ctrlcmd(adapt_layer,
0368 CAIF_CTRLCMD_INIT_FAIL_RSP, 0);
0369 }
0370
0371 static void
0372 cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
0373 u8 phyid, struct cflayer *adapt_layer)
0374 {
0375 struct cfcnfg *cnfg = container_obj(layer);
0376 struct cflayer *servicel = NULL;
0377 struct cfcnfg_phyinfo *phyinfo;
0378 struct net_device *netdev;
0379
0380 if (channel_id == 0) {
0381 pr_warn("received channel_id zero\n");
0382 if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL)
0383 adapt_layer->ctrlcmd(adapt_layer,
0384 CAIF_CTRLCMD_INIT_FAIL_RSP, 0);
0385 return;
0386 }
0387
0388 rcu_read_lock();
0389
0390 if (adapt_layer == NULL) {
0391 pr_debug("link setup response but no client exist, send linkdown back\n");
0392 cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL);
0393 goto unlock;
0394 }
0395
0396 caif_assert(cnfg != NULL);
0397 caif_assert(phyid != 0);
0398
0399 phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid);
0400 if (phyinfo == NULL) {
0401 pr_err("ERROR: Link Layer Device disappeared while connecting\n");
0402 goto unlock;
0403 }
0404
0405 caif_assert(phyinfo != NULL);
0406 caif_assert(phyinfo->id == phyid);
0407 caif_assert(phyinfo->phy_layer != NULL);
0408 caif_assert(phyinfo->phy_layer->id == phyid);
0409
0410 adapt_layer->id = channel_id;
0411
0412 switch (serv) {
0413 case CFCTRL_SRV_VEI:
0414 servicel = cfvei_create(channel_id, &phyinfo->dev_info);
0415 break;
0416 case CFCTRL_SRV_DATAGRAM:
0417 servicel = cfdgml_create(channel_id,
0418 &phyinfo->dev_info);
0419 break;
0420 case CFCTRL_SRV_RFM:
0421 netdev = phyinfo->dev_info.dev;
0422 servicel = cfrfml_create(channel_id, &phyinfo->dev_info,
0423 netdev->mtu);
0424 break;
0425 case CFCTRL_SRV_UTIL:
0426 servicel = cfutill_create(channel_id, &phyinfo->dev_info);
0427 break;
0428 case CFCTRL_SRV_VIDEO:
0429 servicel = cfvidl_create(channel_id, &phyinfo->dev_info);
0430 break;
0431 case CFCTRL_SRV_DBG:
0432 servicel = cfdbgl_create(channel_id, &phyinfo->dev_info);
0433 break;
0434 default:
0435 pr_err("Protocol error. Link setup response - unknown channel type\n");
0436 goto unlock;
0437 }
0438 if (!servicel)
0439 goto unlock;
0440 layer_set_dn(servicel, cnfg->mux);
0441 cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id);
0442 layer_set_up(servicel, adapt_layer);
0443 layer_set_dn(adapt_layer, servicel);
0444
0445 rcu_read_unlock();
0446
0447 servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0);
0448 return;
0449 unlock:
0450 rcu_read_unlock();
0451 }
0452
0453 int
0454 cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
0455 struct net_device *dev, struct cflayer *phy_layer,
0456 enum cfcnfg_phy_preference pref,
0457 struct cflayer *link_support,
0458 bool fcs, int head_room)
0459 {
0460 struct cflayer *frml;
0461 struct cfcnfg_phyinfo *phyinfo = NULL;
0462 int i, res = 0;
0463 u8 phyid;
0464
0465 mutex_lock(&cnfg->lock);
0466
0467
0468 for (i = 0; i < 7; i++) {
0469 phyid = (dev->ifindex + i) & 0x7;
0470 if (phyid == 0)
0471 continue;
0472 if (cfcnfg_get_phyinfo_rcu(cnfg, phyid) == NULL)
0473 goto got_phyid;
0474 }
0475 pr_warn("Too many CAIF Link Layers (max 6)\n");
0476 res = -EEXIST;
0477 goto out;
0478
0479 got_phyid:
0480 phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC);
0481 if (!phyinfo) {
0482 res = -ENOMEM;
0483 goto out;
0484 }
0485
0486 phy_layer->id = phyid;
0487 phyinfo->pref = pref;
0488 phyinfo->id = phyid;
0489 phyinfo->dev_info.id = phyid;
0490 phyinfo->dev_info.dev = dev;
0491 phyinfo->phy_layer = phy_layer;
0492 phyinfo->ifindex = dev->ifindex;
0493 phyinfo->head_room = head_room;
0494 phyinfo->use_fcs = fcs;
0495
0496 frml = cffrml_create(phyid, fcs);
0497
0498 if (!frml) {
0499 res = -ENOMEM;
0500 goto out_err;
0501 }
0502 phyinfo->frm_layer = frml;
0503 layer_set_up(frml, cnfg->mux);
0504
0505 if (link_support != NULL) {
0506 link_support->id = phyid;
0507 layer_set_dn(frml, link_support);
0508 layer_set_up(link_support, frml);
0509 layer_set_dn(link_support, phy_layer);
0510 layer_set_up(phy_layer, link_support);
0511 } else {
0512 layer_set_dn(frml, phy_layer);
0513 layer_set_up(phy_layer, frml);
0514 }
0515
0516 list_add_rcu(&phyinfo->node, &cnfg->phys);
0517 out:
0518 mutex_unlock(&cnfg->lock);
0519 return res;
0520
0521 out_err:
0522 kfree(phyinfo);
0523 mutex_unlock(&cnfg->lock);
0524 return res;
0525 }
0526 EXPORT_SYMBOL(cfcnfg_add_phy_layer);
0527
0528 int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer,
0529 bool up)
0530 {
0531 struct cfcnfg_phyinfo *phyinfo;
0532
0533 rcu_read_lock();
0534 phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phy_layer->id);
0535 if (phyinfo == NULL) {
0536 rcu_read_unlock();
0537 return -ENODEV;
0538 }
0539
0540 if (phyinfo->up == up) {
0541 rcu_read_unlock();
0542 return 0;
0543 }
0544 phyinfo->up = up;
0545
0546 if (up) {
0547 cffrml_hold(phyinfo->frm_layer);
0548 cfmuxl_set_dnlayer(cnfg->mux, phyinfo->frm_layer,
0549 phy_layer->id);
0550 } else {
0551 cfmuxl_remove_dnlayer(cnfg->mux, phy_layer->id);
0552 cffrml_put(phyinfo->frm_layer);
0553 }
0554
0555 rcu_read_unlock();
0556 return 0;
0557 }
0558 EXPORT_SYMBOL(cfcnfg_set_phy_state);
0559
0560 int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer)
0561 {
0562 struct cflayer *frml, *frml_dn;
0563 u16 phyid;
0564 struct cfcnfg_phyinfo *phyinfo;
0565
0566 might_sleep();
0567
0568 mutex_lock(&cnfg->lock);
0569
0570 phyid = phy_layer->id;
0571 phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid);
0572
0573 if (phyinfo == NULL) {
0574 mutex_unlock(&cnfg->lock);
0575 return 0;
0576 }
0577 caif_assert(phyid == phyinfo->id);
0578 caif_assert(phy_layer == phyinfo->phy_layer);
0579 caif_assert(phy_layer->id == phyid);
0580 caif_assert(phyinfo->frm_layer->id == phyid);
0581
0582 list_del_rcu(&phyinfo->node);
0583 synchronize_rcu();
0584
0585
0586 if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) {
0587 pr_info("Wait for device inuse\n");
0588 list_add_rcu(&phyinfo->node, &cnfg->phys);
0589 mutex_unlock(&cnfg->lock);
0590 return -EAGAIN;
0591 }
0592
0593 frml = phyinfo->frm_layer;
0594 frml_dn = frml->dn;
0595 cffrml_set_uplayer(frml, NULL);
0596 cffrml_set_dnlayer(frml, NULL);
0597 if (phy_layer != frml_dn) {
0598 layer_set_up(frml_dn, NULL);
0599 layer_set_dn(frml_dn, NULL);
0600 }
0601 layer_set_up(phy_layer, NULL);
0602
0603 if (phyinfo->phy_layer != frml_dn)
0604 kfree(frml_dn);
0605
0606 cffrml_free(frml);
0607 kfree(phyinfo);
0608 mutex_unlock(&cnfg->lock);
0609
0610 return 0;
0611 }
0612 EXPORT_SYMBOL(cfcnfg_del_phy_layer);