diff options
author | sjur.brandeland@stericsson.com <sjur.brandeland@stericsson.com> | 2011-05-13 02:44:05 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-15 17:45:55 -0400 |
commit | bee925db9a77a5736596dcf6f91d0879f5ee915b (patch) | |
tree | 57a3b499d5b8ec3cb9d36be674e165fa1e7eed42 /net/caif | |
parent | b3ccfbe4098a5542177d0f34e8979f32e7d606e1 (diff) | |
download | lwn-bee925db9a77a5736596dcf6f91d0879f5ee915b.tar.gz lwn-bee925db9a77a5736596dcf6f91d0879f5ee915b.zip |
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')
-rw-r--r-- | net/caif/Makefile | 2 | ||||
-rw-r--r-- | net/caif/caif_config_util.c | 99 | ||||
-rw-r--r-- | net/caif/caif_dev.c | 77 | ||||
-rw-r--r-- | net/caif/caif_socket.c | 6 | ||||
-rw-r--r-- | net/caif/cfcnfg.c | 146 | ||||
-rw-r--r-- | net/caif/chnl_net.c | 12 |
6 files changed, 162 insertions, 180 deletions
diff --git a/net/caif/Makefile b/net/caif/Makefile index 9d38e406e4a4..ebcd4e7e6f47 100644 --- a/net/caif/Makefile +++ b/net/caif/Makefile @@ -5,7 +5,7 @@ caif-y := caif_dev.o \ cffrml.o cfveil.o cfdbgl.o\ cfserl.o cfdgml.o \ cfrfml.o cfvidl.o cfutill.o \ - cfsrvl.o cfpkt_skbuff.o caif_config_util.o + cfsrvl.o cfpkt_skbuff.o obj-$(CONFIG_CAIF) += caif.o obj-$(CONFIG_CAIF_NETDEV) += chnl_net.o diff --git a/net/caif/caif_config_util.c b/net/caif/caif_config_util.c deleted file mode 100644 index 9b63e4e3910e..000000000000 --- a/net/caif/caif_config_util.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) ST-Ericsson AB 2010 - * Author: Sjur Brendeland sjur.brandeland@stericsson.com - * License terms: GNU General Public License (GPL) version 2 - */ - -#include <linux/module.h> -#include <linux/spinlock.h> -#include <net/caif/cfctrl.h> -#include <net/caif/cfcnfg.h> -#include <net/caif/caif_dev.h> - -int caif_connect_req_to_link_param(struct cfcnfg *cnfg, - struct caif_connect_request *s, - struct cfctrl_link_param *l) -{ - struct dev_info *dev_info; - enum cfcnfg_phy_preference pref; - int res; - - memset(l, 0, sizeof(*l)); - /* In caif protocol low value is high priority */ - l->priority = CAIF_PRIO_MAX - s->priority + 1; - - if (s->ifindex != 0){ - res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex); - if (res < 0) - return res; - l->phyid = res; - } - else { - switch (s->link_selector) { - case CAIF_LINK_HIGH_BANDW: - pref = CFPHYPREF_HIGH_BW; - break; - case CAIF_LINK_LOW_LATENCY: - pref = CFPHYPREF_LOW_LAT; - break; - default: - return -EINVAL; - } - dev_info = cfcnfg_get_phyid(cnfg, pref); - if (dev_info == NULL) - return -ENODEV; - l->phyid = dev_info->id; - } - switch (s->protocol) { - case CAIFPROTO_AT: - l->linktype = CFCTRL_SRV_VEI; - if (s->sockaddr.u.at.type == CAIF_ATTYPE_PLAIN) - l->chtype = 0x02; - else - l->chtype = s->sockaddr.u.at.type; - l->endpoint = 0x00; - break; - case CAIFPROTO_DATAGRAM: - l->linktype = CFCTRL_SRV_DATAGRAM; - l->chtype = 0x00; - l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; - break; - case CAIFPROTO_DATAGRAM_LOOP: - l->linktype = CFCTRL_SRV_DATAGRAM; - l->chtype = 0x03; - l->endpoint = 0x00; - l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; - break; - case CAIFPROTO_RFM: - l->linktype = CFCTRL_SRV_RFM; - l->u.datagram.connid = s->sockaddr.u.rfm.connection_id; - strncpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume, - sizeof(l->u.rfm.volume)-1); - l->u.rfm.volume[sizeof(l->u.rfm.volume)-1] = 0; - break; - case CAIFPROTO_UTIL: - l->linktype = CFCTRL_SRV_UTIL; - l->endpoint = 0x00; - l->chtype = 0x00; - strncpy(l->u.utility.name, s->sockaddr.u.util.service, - sizeof(l->u.utility.name)-1); - l->u.utility.name[sizeof(l->u.utility.name)-1] = 0; - caif_assert(sizeof(l->u.utility.name) > 10); - l->u.utility.paramlen = s->param.size; - if (l->u.utility.paramlen > sizeof(l->u.utility.params)) - l->u.utility.paramlen = sizeof(l->u.utility.params); - - memcpy(l->u.utility.params, s->param.data, - l->u.utility.paramlen); - - break; - case CAIFPROTO_DEBUG: - l->linktype = CFCTRL_SRV_DBG; - l->endpoint = s->sockaddr.u.dbg.service; - l->chtype = s->sockaddr.u.dbg.type; - break; - default: - return -EINVAL; - } - return 0; -} diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 6d1d86be187b..0e651cf577cf 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -21,7 +21,6 @@ #include <net/net_namespace.h> #include <net/pkt_sched.h> #include <net/caif/caif_device.h> -#include <net/caif/caif_dev.h> #include <net/caif/caif_layer.h> #include <net/caif/cfpkt.h> #include <net/caif/cfcnfg.h> @@ -43,11 +42,21 @@ struct caif_device_entry_list { }; struct caif_net { + struct cfcnfg *cfg; struct caif_device_entry_list caifdevs; }; static int caif_net_id; -static struct cfcnfg *cfg; + +struct cfcnfg *get_cfcnfg(struct net *net) +{ + struct caif_net *caifn; + BUG_ON(!net); + caifn = net_generic(net, caif_net_id); + BUG_ON(!caifn); + return caifn->cfg; +} +EXPORT_SYMBOL(get_cfcnfg); static struct caif_device_entry_list *caif_device_list(struct net *net) { @@ -191,12 +200,17 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, struct caif_dev_common *caifdev; enum cfcnfg_phy_preference pref; enum cfcnfg_phy_type phy_type; + struct cfcnfg *cfg; struct caif_device_entry_list *caifdevs = caif_device_list(dev_net(dev)); if (dev->type != ARPHRD_CAIF) return 0; + cfg = get_cfcnfg(dev_net(dev)); + if (cfg == NULL) + return 0; + switch (what) { case NETDEV_REGISTER: caifd = caif_device_alloc(dev); @@ -235,7 +249,6 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, phy_type, dev, &caifd->layer, - 0, pref, caifdev->use_fcs, caifdev->use_stx); @@ -323,35 +336,20 @@ static struct notifier_block caif_device_notifier = { .priority = 0, }; -int caif_connect_client(struct caif_connect_request *conn_req, - struct cflayer *client_layer, int *ifindex, - int *headroom, int *tailroom) -{ - struct cfctrl_link_param param; - int ret; - - ret = caif_connect_req_to_link_param(cfg, conn_req, ¶m); - if (ret) - return ret; - /* Hook up the adaptation layer. */ - return cfcnfg_add_adaptation_layer(cfg, ¶m, - client_layer, ifindex, - headroom, tailroom); -} -EXPORT_SYMBOL(caif_connect_client); - -int caif_disconnect_client(struct cflayer *adap_layer) -{ - return cfcnfg_disconn_adapt_layer(cfg, adap_layer); -} -EXPORT_SYMBOL(caif_disconnect_client); - /* Per-namespace Caif devices handling */ static int caif_init_net(struct net *net) { struct caif_net *caifn = net_generic(net, caif_net_id); + BUG_ON(!caifn); INIT_LIST_HEAD(&caifn->caifdevs.list); mutex_init(&caifn->caifdevs.lock); + + caifn->cfg = cfcnfg_create(); + if (!caifn->cfg) { + pr_warn("can't create cfcnfg\n"); + return -ENOMEM; + } + return 0; } @@ -360,10 +358,17 @@ static void caif_exit_net(struct net *net) struct caif_device_entry *caifd, *tmp; struct caif_device_entry_list *caifdevs = caif_device_list(net); + struct cfcnfg *cfg; rtnl_lock(); mutex_lock(&caifdevs->lock); + cfg = get_cfcnfg(net); + if (cfg == NULL) { + mutex_unlock(&caifdevs->lock); + return; + } + list_for_each_entry_safe(caifd, tmp, &caifdevs->list, list) { int i = 0; list_del_rcu(&caifd->list); @@ -382,7 +387,7 @@ static void caif_exit_net(struct net *net) free_percpu(caifd->pcpu_refcnt); kfree(caifd); } - + cfcnfg_remove(cfg); mutex_unlock(&caifdevs->lock); rtnl_unlock(); @@ -400,32 +405,22 @@ static int __init caif_device_init(void) { int result; - cfg = cfcnfg_create(); - if (!cfg) { - pr_warn("can't create cfcnfg\n"); - goto err_cfcnfg_create_failed; - } result = register_pernet_device(&caif_net_ops); - if (result) { - kfree(cfg); - cfg = NULL; + if (result) return result; - } - dev_add_pack(&caif_packet_type); + register_netdevice_notifier(&caif_device_notifier); + dev_add_pack(&caif_packet_type); return result; -err_cfcnfg_create_failed: - return -ENODEV; } static void __exit caif_device_exit(void) { - dev_remove_pack(&caif_packet_type); unregister_pernet_device(&caif_net_ops); unregister_netdevice_notifier(&caif_device_notifier); - cfcnfg_remove(cfg); + dev_remove_pack(&caif_packet_type); } module_init(caif_device_init); diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 01f612df7df1..653db759eb7e 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -810,7 +810,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, sk->sk_state == CAIF_DISCONNECTED); if (sk->sk_shutdown & SHUTDOWN_MASK) { /* Allow re-connect after SHUTDOWN_IND */ - caif_disconnect_client(&cf_sk->layer); + caif_disconnect_client(sock_net(sk), &cf_sk->layer); break; } /* No reconnect on a seqpacket socket */ @@ -851,7 +851,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, dbfs_atomic_inc(&cnt.num_connect_req); cf_sk->layer.receive = caif_sktrecv_cb; - err = caif_connect_client(&cf_sk->conn_req, + err = caif_connect_client(sock_net(sk), &cf_sk->conn_req, &cf_sk->layer, &ifindex, &headroom, &tailroom); if (err < 0) { @@ -949,7 +949,7 @@ static int caif_release(struct socket *sock) if (cf_sk->sk.sk_socket->state == SS_CONNECTED || cf_sk->sk.sk_socket->state == SS_CONNECTING) - res = caif_disconnect_client(&cf_sk->layer); + res = caif_disconnect_client(sock_net(sk), &cf_sk->layer); cf_sk->sk.sk_socket->state = SS_DISCONNECTING; wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP); 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) { } -struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, +static struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, enum cfcnfg_phy_preference phy_pref) { /* Try to match with specified preference */ @@ -171,7 +171,7 @@ struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, return NULL; } -int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) +static int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) { struct cfcnfg_phyinfo *phy; @@ -181,11 +181,12 @@ int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) return -ENODEV; } -int cfcnfg_disconn_adapt_layer(struct cfcnfg *cfg, struct cflayer *adap_layer) +int caif_disconnect_client(struct net *net, struct cflayer *adap_layer) { u8 channel_id = 0; int ret = 0; struct cflayer *servl = NULL; + struct cfcnfg *cfg = get_cfcnfg(net); caif_assert(adap_layer != NULL); @@ -217,14 +218,7 @@ end: return ret; } -EXPORT_SYMBOL(cfcnfg_disconn_adapt_layer); - -void cfcnfg_release_adap_layer(struct cflayer *adap_layer) -{ - if (adap_layer->dn) - cfsrvl_put(adap_layer->dn); -} -EXPORT_SYMBOL(cfcnfg_release_adap_layer); +EXPORT_SYMBOL(caif_disconnect_client); static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) { @@ -238,19 +232,109 @@ static const int protohead[CFCTRL_SRV_MASK] = { [CFCTRL_SRV_DBG] = 3, }; -int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, - struct cfctrl_link_param *param, - struct cflayer *adap_layer, - int *ifindex, + +static int caif_connect_req_to_link_param(struct cfcnfg *cnfg, + struct caif_connect_request *s, + struct cfctrl_link_param *l) +{ + struct dev_info *dev_info; + enum cfcnfg_phy_preference pref; + int res; + + memset(l, 0, sizeof(*l)); + /* In caif protocol low value is high priority */ + l->priority = CAIF_PRIO_MAX - s->priority + 1; + + if (s->ifindex != 0) { + res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex); + if (res < 0) + return res; + l->phyid = res; + } else { + switch (s->link_selector) { + case CAIF_LINK_HIGH_BANDW: + pref = CFPHYPREF_HIGH_BW; + break; + case CAIF_LINK_LOW_LATENCY: + pref = CFPHYPREF_LOW_LAT; + break; + default: + return -EINVAL; + } + dev_info = cfcnfg_get_phyid(cnfg, pref); + if (dev_info == NULL) + return -ENODEV; + l->phyid = dev_info->id; + } + switch (s->protocol) { + case CAIFPROTO_AT: + l->linktype = CFCTRL_SRV_VEI; + l->endpoint = (s->sockaddr.u.at.type >> 2) & 0x3; + l->chtype = s->sockaddr.u.at.type & 0x3; + break; + case CAIFPROTO_DATAGRAM: + l->linktype = CFCTRL_SRV_DATAGRAM; + l->chtype = 0x00; + l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; + break; + case CAIFPROTO_DATAGRAM_LOOP: + l->linktype = CFCTRL_SRV_DATAGRAM; + l->chtype = 0x03; + l->endpoint = 0x00; + l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; + break; + case CAIFPROTO_RFM: + l->linktype = CFCTRL_SRV_RFM; + l->u.datagram.connid = s->sockaddr.u.rfm.connection_id; + strncpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume, + sizeof(l->u.rfm.volume)-1); + l->u.rfm.volume[sizeof(l->u.rfm.volume)-1] = 0; + break; + case CAIFPROTO_UTIL: + l->linktype = CFCTRL_SRV_UTIL; + l->endpoint = 0x00; + l->chtype = 0x00; + strncpy(l->u.utility.name, s->sockaddr.u.util.service, + sizeof(l->u.utility.name)-1); + l->u.utility.name[sizeof(l->u.utility.name)-1] = 0; + caif_assert(sizeof(l->u.utility.name) > 10); + l->u.utility.paramlen = s->param.size; + if (l->u.utility.paramlen > sizeof(l->u.utility.params)) + l->u.utility.paramlen = sizeof(l->u.utility.params); + + memcpy(l->u.utility.params, s->param.data, + l->u.utility.paramlen); + + break; + case CAIFPROTO_DEBUG: + l->linktype = CFCTRL_SRV_DBG; + l->endpoint = s->sockaddr.u.dbg.service; + l->chtype = s->sockaddr.u.dbg.type; + break; + default: + return -EINVAL; + } + return 0; +} + +int caif_connect_client(struct net *net, struct caif_connect_request *conn_req, + struct cflayer *adap_layer, int *ifindex, int *proto_head, int *proto_tail) { struct cflayer *frml; struct cfcnfg_phyinfo *phy; int err; + struct cfctrl_link_param param; + struct cfcnfg *cfg = get_cfcnfg(net); + caif_assert(cfg != NULL); rcu_read_lock(); - phy = cfcnfg_get_phyinfo_rcu(cnfg, param->phyid); + err = caif_connect_req_to_link_param(cfg, conn_req, ¶m); + if (err) + goto unlock; + + phy = cfcnfg_get_phyinfo_rcu(cfg, param.phyid); if (!phy) { err = -ENODEV; goto unlock; @@ -276,28 +360,29 @@ int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, pr_err("Specified PHY type does not exist!\n"); goto unlock; } - caif_assert(param->phyid == phy->id); + caif_assert(param.phyid == phy->id); caif_assert(phy->frm_layer->id == - param->phyid); + param.phyid); caif_assert(phy->phy_layer->id == - param->phyid); + param.phyid); *ifindex = phy->ifindex; *proto_tail = 2; *proto_head = - protohead[param->linktype] + (phy->use_stx ? 1 : 0); + + protohead[param.linktype] + (phy->use_stx ? 1 : 0); rcu_read_unlock(); /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ - cfctrl_enum_req(cnfg->ctrl, param->phyid); - return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer); + cfctrl_enum_req(cfg->ctrl, param.phyid); + return cfctrl_linkup_request(cfg->ctrl, ¶m, adap_layer); unlock: rcu_read_unlock(); return err; } -EXPORT_SYMBOL(cfcnfg_add_adaptation_layer); +EXPORT_SYMBOL(caif_connect_client); static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, struct cflayer *adapt_layer) @@ -389,7 +474,7 @@ unlock: void cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, struct net_device *dev, struct cflayer *phy_layer, - u16 *phy_id, enum cfcnfg_phy_preference pref, + enum cfcnfg_phy_preference pref, bool fcs, bool stx) { struct cflayer *frml; @@ -512,23 +597,26 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) phyid = phy_layer->id; phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid); - if (phyinfo == NULL) + if (phyinfo == NULL) { + mutex_unlock(&cnfg->lock); return 0; + } caif_assert(phyid == phyinfo->id); caif_assert(phy_layer == phyinfo->phy_layer); caif_assert(phy_layer->id == phyid); caif_assert(phyinfo->frm_layer->id == phyid); + list_del_rcu(&phyinfo->node); + synchronize_rcu(); + /* Fail if reference count is not zero */ if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) { pr_info("Wait for device inuse\n"); + list_add_rcu(&phyinfo->node, &cnfg->phys); mutex_unlock(&cnfg->lock); return -EAGAIN; } - list_del_rcu(&phyinfo->node); - synchronize_rcu(); - frml = phyinfo->frm_layer; frml_dn = frml->dn; cffrml_set_uplayer(frml, NULL); @@ -539,8 +627,6 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) } layer_set_up(phy_layer, NULL); - - if (phyinfo->phy_layer != frml_dn) kfree(frml_dn); diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 9ef8f1660ee1..1a3398a89aee 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -20,7 +20,6 @@ #include <linux/caif/if_caif.h> #include <net/rtnetlink.h> #include <net/caif/caif_layer.h> -#include <net/caif/cfcnfg.h> #include <net/caif/cfpkt.h> #include <net/caif/caif_dev.h> @@ -270,8 +269,9 @@ static int chnl_net_open(struct net_device *dev) if (priv->state != CAIF_CONNECTING) { priv->state = CAIF_CONNECTING; - result = caif_connect_client(&priv->conn_req, &priv->chnl, - &llifindex, &headroom, &tailroom); + result = caif_connect_client(dev_net(dev), &priv->conn_req, + &priv->chnl, &llifindex, + &headroom, &tailroom); if (result != 0) { pr_debug("err: " "Unable to register and open device," @@ -327,7 +327,7 @@ static int chnl_net_open(struct net_device *dev) if (result == 0) { pr_debug("connect timeout\n"); - caif_disconnect_client(&priv->chnl); + caif_disconnect_client(dev_net(dev), &priv->chnl); priv->state = CAIF_DISCONNECTED; pr_debug("state disconnected\n"); result = -ETIMEDOUT; @@ -343,7 +343,7 @@ static int chnl_net_open(struct net_device *dev) return 0; error: - caif_disconnect_client(&priv->chnl); + caif_disconnect_client(dev_net(dev), &priv->chnl); priv->state = CAIF_DISCONNECTED; pr_debug("state disconnected\n"); return result; @@ -357,7 +357,7 @@ static int chnl_net_stop(struct net_device *dev) ASSERT_RTNL(); priv = netdev_priv(dev); priv->state = CAIF_DISCONNECTED; - caif_disconnect_client(&priv->chnl); + caif_disconnect_client(dev_net(dev), &priv->chnl); return 0; } |