diff options
author | sjur.brandeland@stericsson.com <sjur.brandeland@stericsson.com> | 2011-05-12 22:44:05 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-15 17:45:55 -0400 |
commit | bee925db9a77a5736596dcf6f91d0879f5ee915b (patch) | |
tree | 57a3b499d5b8ec3cb9d36be674e165fa1e7eed42 /net/caif/cfcnfg.c | |
parent | b3ccfbe4098a5542177d0f34e8979f32e7d606e1 (diff) |
caif: prepare support for namespaces
Use struct net to reference CAIF configuration object instead of static variables.
Refactor functions caif_connect_client, caif_disconnect_client and squach
files cfcnfg.c and caif_config_utils.
Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/caif/cfcnfg.c')
-rw-r--r-- | net/caif/cfcnfg.c | 146 |
1 files changed, 116 insertions, 30 deletions
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index 3f4f31fca2c1..e857d8995ca3 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c | |||
@@ -150,7 +150,7 @@ static void cfctrl_enum_resp(void) | |||
150 | { | 150 | { |
151 | } | 151 | } |
152 | 152 | ||
153 | struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, | 153 | static struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, |
154 | enum cfcnfg_phy_preference phy_pref) | 154 | enum cfcnfg_phy_preference phy_pref) |
155 | { | 155 | { |
156 | /* Try to match with specified preference */ | 156 | /* Try to match with specified preference */ |
@@ -171,7 +171,7 @@ struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, | |||
171 | return NULL; | 171 | return NULL; |
172 | } | 172 | } |
173 | 173 | ||
174 | int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) | 174 | static int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) |
175 | { | 175 | { |
176 | struct cfcnfg_phyinfo *phy; | 176 | struct cfcnfg_phyinfo *phy; |
177 | 177 | ||
@@ -181,11 +181,12 @@ int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) | |||
181 | return -ENODEV; | 181 | return -ENODEV; |
182 | } | 182 | } |
183 | 183 | ||
184 | int cfcnfg_disconn_adapt_layer(struct cfcnfg *cfg, struct cflayer *adap_layer) | 184 | int caif_disconnect_client(struct net *net, struct cflayer *adap_layer) |
185 | { | 185 | { |
186 | u8 channel_id = 0; | 186 | u8 channel_id = 0; |
187 | int ret = 0; | 187 | int ret = 0; |
188 | struct cflayer *servl = NULL; | 188 | struct cflayer *servl = NULL; |
189 | struct cfcnfg *cfg = get_cfcnfg(net); | ||
189 | 190 | ||
190 | caif_assert(adap_layer != NULL); | 191 | caif_assert(adap_layer != NULL); |
191 | 192 | ||
@@ -217,14 +218,7 @@ end: | |||
217 | return ret; | 218 | return ret; |
218 | 219 | ||
219 | } | 220 | } |
220 | EXPORT_SYMBOL(cfcnfg_disconn_adapt_layer); | 221 | EXPORT_SYMBOL(caif_disconnect_client); |
221 | |||
222 | void cfcnfg_release_adap_layer(struct cflayer *adap_layer) | ||
223 | { | ||
224 | if (adap_layer->dn) | ||
225 | cfsrvl_put(adap_layer->dn); | ||
226 | } | ||
227 | EXPORT_SYMBOL(cfcnfg_release_adap_layer); | ||
228 | 222 | ||
229 | static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) | 223 | static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) |
230 | { | 224 | { |
@@ -238,19 +232,109 @@ static const int protohead[CFCTRL_SRV_MASK] = { | |||
238 | [CFCTRL_SRV_DBG] = 3, | 232 | [CFCTRL_SRV_DBG] = 3, |
239 | }; | 233 | }; |
240 | 234 | ||
241 | int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, | 235 | |
242 | struct cfctrl_link_param *param, | 236 | static int caif_connect_req_to_link_param(struct cfcnfg *cnfg, |
243 | struct cflayer *adap_layer, | 237 | struct caif_connect_request *s, |
244 | int *ifindex, | 238 | struct cfctrl_link_param *l) |
239 | { | ||
240 | struct dev_info *dev_info; | ||
241 | enum cfcnfg_phy_preference pref; | ||
242 | int res; | ||
243 | |||
244 | memset(l, 0, sizeof(*l)); | ||
245 | /* In caif protocol low value is high priority */ | ||
246 | l->priority = CAIF_PRIO_MAX - s->priority + 1; | ||
247 | |||
248 | if (s->ifindex != 0) { | ||
249 | res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex); | ||
250 | if (res < 0) | ||
251 | return res; | ||
252 | l->phyid = res; | ||
253 | } else { | ||
254 | switch (s->link_selector) { | ||
255 | case CAIF_LINK_HIGH_BANDW: | ||
256 | pref = CFPHYPREF_HIGH_BW; | ||
257 | break; | ||
258 | case CAIF_LINK_LOW_LATENCY: | ||
259 | pref = CFPHYPREF_LOW_LAT; | ||
260 | break; | ||
261 | default: | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | dev_info = cfcnfg_get_phyid(cnfg, pref); | ||
265 | if (dev_info == NULL) | ||
266 | return -ENODEV; | ||
267 | l->phyid = dev_info->id; | ||
268 | } | ||
269 | switch (s->protocol) { | ||
270 | case CAIFPROTO_AT: | ||
271 | l->linktype = CFCTRL_SRV_VEI; | ||
272 | l->endpoint = (s->sockaddr.u.at.type >> 2) & 0x3; | ||
273 | l->chtype = s->sockaddr.u.at.type & 0x3; | ||
274 | break; | ||
275 | case CAIFPROTO_DATAGRAM: | ||
276 | l->linktype = CFCTRL_SRV_DATAGRAM; | ||
277 | l->chtype = 0x00; | ||
278 | l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; | ||
279 | break; | ||
280 | case CAIFPROTO_DATAGRAM_LOOP: | ||
281 | l->linktype = CFCTRL_SRV_DATAGRAM; | ||
282 | l->chtype = 0x03; | ||
283 | l->endpoint = 0x00; | ||
284 | l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; | ||
285 | break; | ||
286 | case CAIFPROTO_RFM: | ||
287 | l->linktype = CFCTRL_SRV_RFM; | ||
288 | l->u.datagram.connid = s->sockaddr.u.rfm.connection_id; | ||
289 | strncpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume, | ||
290 | sizeof(l->u.rfm.volume)-1); | ||
291 | l->u.rfm.volume[sizeof(l->u.rfm.volume)-1] = 0; | ||
292 | break; | ||
293 | case CAIFPROTO_UTIL: | ||
294 | l->linktype = CFCTRL_SRV_UTIL; | ||
295 | l->endpoint = 0x00; | ||
296 | l->chtype = 0x00; | ||
297 | strncpy(l->u.utility.name, s->sockaddr.u.util.service, | ||
298 | sizeof(l->u.utility.name)-1); | ||
299 | l->u.utility.name[sizeof(l->u.utility.name)-1] = 0; | ||
300 | caif_assert(sizeof(l->u.utility.name) > 10); | ||
301 | l->u.utility.paramlen = s->param.size; | ||
302 | if (l->u.utility.paramlen > sizeof(l->u.utility.params)) | ||
303 | l->u.utility.paramlen = sizeof(l->u.utility.params); | ||
304 | |||
305 | memcpy(l->u.utility.params, s->param.data, | ||
306 | l->u.utility.paramlen); | ||
307 | |||
308 | break; | ||
309 | case CAIFPROTO_DEBUG: | ||
310 | l->linktype = CFCTRL_SRV_DBG; | ||
311 | l->endpoint = s->sockaddr.u.dbg.service; | ||
312 | l->chtype = s->sockaddr.u.dbg.type; | ||
313 | break; | ||
314 | default: | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | int caif_connect_client(struct net *net, struct caif_connect_request *conn_req, | ||
321 | struct cflayer *adap_layer, int *ifindex, | ||
245 | int *proto_head, | 322 | int *proto_head, |
246 | int *proto_tail) | 323 | int *proto_tail) |
247 | { | 324 | { |
248 | struct cflayer *frml; | 325 | struct cflayer *frml; |
249 | struct cfcnfg_phyinfo *phy; | 326 | struct cfcnfg_phyinfo *phy; |
250 | int err; | 327 | int err; |
328 | struct cfctrl_link_param param; | ||
329 | struct cfcnfg *cfg = get_cfcnfg(net); | ||
330 | caif_assert(cfg != NULL); | ||
251 | 331 | ||
252 | rcu_read_lock(); | 332 | rcu_read_lock(); |
253 | phy = cfcnfg_get_phyinfo_rcu(cnfg, param->phyid); | 333 | err = caif_connect_req_to_link_param(cfg, conn_req, ¶m); |
334 | if (err) | ||
335 | goto unlock; | ||
336 | |||
337 | phy = cfcnfg_get_phyinfo_rcu(cfg, param.phyid); | ||
254 | if (!phy) { | 338 | if (!phy) { |
255 | err = -ENODEV; | 339 | err = -ENODEV; |
256 | goto unlock; | 340 | goto unlock; |
@@ -276,28 +360,29 @@ int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, | |||
276 | pr_err("Specified PHY type does not exist!\n"); | 360 | pr_err("Specified PHY type does not exist!\n"); |
277 | goto unlock; | 361 | goto unlock; |
278 | } | 362 | } |
279 | caif_assert(param->phyid == phy->id); | 363 | caif_assert(param.phyid == phy->id); |
280 | caif_assert(phy->frm_layer->id == | 364 | caif_assert(phy->frm_layer->id == |
281 | param->phyid); | 365 | param.phyid); |
282 | caif_assert(phy->phy_layer->id == | 366 | caif_assert(phy->phy_layer->id == |
283 | param->phyid); | 367 | param.phyid); |
284 | 368 | ||
285 | *ifindex = phy->ifindex; | 369 | *ifindex = phy->ifindex; |
286 | *proto_tail = 2; | 370 | *proto_tail = 2; |
287 | *proto_head = | 371 | *proto_head = |
288 | protohead[param->linktype] + (phy->use_stx ? 1 : 0); | 372 | |
373 | protohead[param.linktype] + (phy->use_stx ? 1 : 0); | ||
289 | 374 | ||
290 | rcu_read_unlock(); | 375 | rcu_read_unlock(); |
291 | 376 | ||
292 | /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ | 377 | /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ |
293 | cfctrl_enum_req(cnfg->ctrl, param->phyid); | 378 | cfctrl_enum_req(cfg->ctrl, param.phyid); |
294 | return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer); | 379 | return cfctrl_linkup_request(cfg->ctrl, ¶m, adap_layer); |
295 | 380 | ||
296 | unlock: | 381 | unlock: |
297 | rcu_read_unlock(); | 382 | rcu_read_unlock(); |
298 | return err; | 383 | return err; |
299 | } | 384 | } |
300 | EXPORT_SYMBOL(cfcnfg_add_adaptation_layer); | 385 | EXPORT_SYMBOL(caif_connect_client); |
301 | 386 | ||
302 | static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, | 387 | static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, |
303 | struct cflayer *adapt_layer) | 388 | struct cflayer *adapt_layer) |
@@ -389,7 +474,7 @@ unlock: | |||
389 | void | 474 | void |
390 | cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, | 475 | cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, |
391 | struct net_device *dev, struct cflayer *phy_layer, | 476 | struct net_device *dev, struct cflayer *phy_layer, |
392 | u16 *phy_id, enum cfcnfg_phy_preference pref, | 477 | enum cfcnfg_phy_preference pref, |
393 | bool fcs, bool stx) | 478 | bool fcs, bool stx) |
394 | { | 479 | { |
395 | struct cflayer *frml; | 480 | struct cflayer *frml; |
@@ -512,23 +597,26 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) | |||
512 | phyid = phy_layer->id; | 597 | phyid = phy_layer->id; |
513 | phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid); | 598 | phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid); |
514 | 599 | ||
515 | if (phyinfo == NULL) | 600 | if (phyinfo == NULL) { |
601 | mutex_unlock(&cnfg->lock); | ||
516 | return 0; | 602 | return 0; |
603 | } | ||
517 | caif_assert(phyid == phyinfo->id); | 604 | caif_assert(phyid == phyinfo->id); |
518 | caif_assert(phy_layer == phyinfo->phy_layer); | 605 | caif_assert(phy_layer == phyinfo->phy_layer); |
519 | caif_assert(phy_layer->id == phyid); | 606 | caif_assert(phy_layer->id == phyid); |
520 | caif_assert(phyinfo->frm_layer->id == phyid); | 607 | caif_assert(phyinfo->frm_layer->id == phyid); |
521 | 608 | ||
609 | list_del_rcu(&phyinfo->node); | ||
610 | synchronize_rcu(); | ||
611 | |||
522 | /* Fail if reference count is not zero */ | 612 | /* Fail if reference count is not zero */ |
523 | if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) { | 613 | if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) { |
524 | pr_info("Wait for device inuse\n"); | 614 | pr_info("Wait for device inuse\n"); |
615 | list_add_rcu(&phyinfo->node, &cnfg->phys); | ||
525 | mutex_unlock(&cnfg->lock); | 616 | mutex_unlock(&cnfg->lock); |
526 | return -EAGAIN; | 617 | return -EAGAIN; |
527 | } | 618 | } |
528 | 619 | ||
529 | list_del_rcu(&phyinfo->node); | ||
530 | synchronize_rcu(); | ||
531 | |||
532 | frml = phyinfo->frm_layer; | 620 | frml = phyinfo->frm_layer; |
533 | frml_dn = frml->dn; | 621 | frml_dn = frml->dn; |
534 | cffrml_set_uplayer(frml, NULL); | 622 | cffrml_set_uplayer(frml, NULL); |
@@ -539,8 +627,6 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) | |||
539 | } | 627 | } |
540 | layer_set_up(phy_layer, NULL); | 628 | layer_set_up(phy_layer, NULL); |
541 | 629 | ||
542 | |||
543 | |||
544 | if (phyinfo->phy_layer != frml_dn) | 630 | if (phyinfo->phy_layer != frml_dn) |
545 | kfree(frml_dn); | 631 | kfree(frml_dn); |
546 | 632 | ||