summaryrefslogtreecommitdiffstats
path: root/net/caif
diff options
context:
space:
mode:
Diffstat (limited to 'net/caif')
-rw-r--r--net/caif/Makefile2
-rw-r--r--net/caif/caif_config_util.c99
-rw-r--r--net/caif/caif_dev.c77
-rw-r--r--net/caif/caif_socket.c6
-rw-r--r--net/caif/cfcnfg.c146
-rw-r--r--net/caif/chnl_net.c12
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, &param);
- if (ret)
- return ret;
- /* Hook up the adaptation layer. */
- return cfcnfg_add_adaptation_layer(cfg, &param,
- 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, &param);
+ 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, &param, 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;
}