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>
This commit is contained in:
parent
b3ccfbe409
commit
bee925db9a
@ -11,6 +11,7 @@
|
|||||||
#include <net/caif/cfcnfg.h>
|
#include <net/caif/cfcnfg.h>
|
||||||
#include <linux/caif/caif_socket.h>
|
#include <linux/caif/caif_socket.h>
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
|
#include <linux/net.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct caif_param - CAIF parameters.
|
* struct caif_param - CAIF parameters.
|
||||||
@ -62,16 +63,18 @@ struct caif_connect_request {
|
|||||||
* E.g. CAIF Socket will call this function for each socket it connects
|
* E.g. CAIF Socket will call this function for each socket it connects
|
||||||
* and have one client_layer instance for each socket.
|
* and have one client_layer instance for each socket.
|
||||||
*/
|
*/
|
||||||
int caif_connect_client(struct caif_connect_request *conn_req,
|
int caif_connect_client(struct net *net,
|
||||||
|
struct caif_connect_request *conn_req,
|
||||||
struct cflayer *client_layer, int *ifindex,
|
struct cflayer *client_layer, int *ifindex,
|
||||||
int *headroom, int *tailroom);
|
int *headroom, int *tailroom);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* caif_disconnect_client - Disconnects a client from the CAIF stack.
|
* caif_disconnect_client - Disconnects a client from the CAIF stack.
|
||||||
*
|
*
|
||||||
* @client_layer: Client layer to be removed.
|
* @client_layer: Client layer to be disconnected.
|
||||||
*/
|
*/
|
||||||
int caif_disconnect_client(struct cflayer *client_layer);
|
int caif_disconnect_client(struct net *net, struct cflayer *client_layer);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* caif_client_register_refcnt - register ref-count functions provided by client.
|
* caif_client_register_refcnt - register ref-count functions provided by client.
|
||||||
@ -90,21 +93,6 @@ int caif_disconnect_client(struct cflayer *client_layer);
|
|||||||
void caif_client_register_refcnt(struct cflayer *adapt_layer,
|
void caif_client_register_refcnt(struct cflayer *adapt_layer,
|
||||||
void (*hold)(struct cflayer *lyr),
|
void (*hold)(struct cflayer *lyr),
|
||||||
void (*put)(struct cflayer *lyr));
|
void (*put)(struct cflayer *lyr));
|
||||||
/**
|
|
||||||
* caif_connect_req_to_link_param - Translate configuration parameters
|
|
||||||
* from socket format to internal format.
|
|
||||||
* @cnfg: Pointer to configuration handler
|
|
||||||
* @con_req: Configuration parameters supplied in function
|
|
||||||
* caif_connect_client
|
|
||||||
* @channel_setup_param: Parameters supplied to the CAIF Core stack for
|
|
||||||
* setting up channels.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
int caif_connect_req_to_link_param(struct cfcnfg *cnfg,
|
|
||||||
struct caif_connect_request *con_req,
|
|
||||||
struct cfctrl_link_param *setup_param);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* caif_free_client - Free memory used to manage the client in the CAIF Stack.
|
* caif_free_client - Free memory used to manage the client in the CAIF Stack.
|
||||||
*
|
*
|
||||||
|
@ -45,6 +45,12 @@ enum cfcnfg_phy_preference {
|
|||||||
CFPHYPREF_LOOP
|
CFPHYPREF_LOOP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cfcnfg_create() - Get the CAIF configuration object given network.
|
||||||
|
* @net: Network for the CAIF configuration object.
|
||||||
|
*/
|
||||||
|
struct cfcnfg *get_cfcnfg(struct net *net);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cfcnfg_create() - Create the CAIF configuration object.
|
* cfcnfg_create() - Create the CAIF configuration object.
|
||||||
*/
|
*/
|
||||||
@ -65,17 +71,15 @@ void cfcnfg_remove(struct cfcnfg *cfg);
|
|||||||
* @dev: Pointer to link layer device
|
* @dev: Pointer to link layer device
|
||||||
* @phy_layer: Specify the physical layer. The transmit function
|
* @phy_layer: Specify the physical layer. The transmit function
|
||||||
* MUST be set in the structure.
|
* MUST be set in the structure.
|
||||||
* @phyid: The assigned physical ID for this layer, used in
|
|
||||||
* cfcnfg_add_adapt_layer to specify PHY for the link.
|
|
||||||
* @pref: The phy (link layer) preference.
|
* @pref: The phy (link layer) preference.
|
||||||
* @fcs: Specify if checksum is used in CAIF Framing Layer.
|
* @fcs: Specify if checksum is used in CAIF Framing Layer.
|
||||||
* @stx: Specify if Start Of Frame extension is used.
|
* @stx: Specify if Start Of Frame eXtention is used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
|
cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
|
||||||
struct net_device *dev, struct cflayer *phy_layer,
|
struct net_device *dev, struct cflayer *phy_layer,
|
||||||
u16 *phyid, enum cfcnfg_phy_preference pref,
|
enum cfcnfg_phy_preference pref,
|
||||||
bool fcs, bool stx);
|
bool fcs, bool stx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,65 +91,6 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
|
|||||||
*/
|
*/
|
||||||
int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer);
|
int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer);
|
||||||
|
|
||||||
/**
|
|
||||||
* cfcnfg_disconn_adapt_layer - Disconnects an adaptation layer.
|
|
||||||
*
|
|
||||||
* @cnfg: Pointer to a CAIF configuration object, created by
|
|
||||||
* cfcnfg_create().
|
|
||||||
* @adap_layer: Adaptation layer to be removed.
|
|
||||||
*/
|
|
||||||
int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg,
|
|
||||||
struct cflayer *adap_layer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cfcnfg_release_adap_layer - Used by client to release the adaptation layer.
|
|
||||||
*
|
|
||||||
* @adap_layer: Adaptation layer.
|
|
||||||
*/
|
|
||||||
void cfcnfg_release_adap_layer(struct cflayer *adap_layer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cfcnfg_add_adaptation_layer - Add an adaptation layer to the CAIF stack.
|
|
||||||
*
|
|
||||||
* The adaptation Layer is where the interface to application or higher-level
|
|
||||||
* driver functionality is implemented.
|
|
||||||
*
|
|
||||||
* @cnfg: Pointer to a CAIF configuration object, created by
|
|
||||||
* cfcnfg_create().
|
|
||||||
* @param: Link setup parameters.
|
|
||||||
* @adap_layer: Specify the adaptation layer; the receive and
|
|
||||||
* flow-control functions MUST be set in the structure.
|
|
||||||
* @ifindex: Link layer interface index used for this connection.
|
|
||||||
* @proto_head: Protocol head-space needed by CAIF protocol,
|
|
||||||
* excluding link layer.
|
|
||||||
* @proto_tail: Protocol tail-space needed by CAIF protocol,
|
|
||||||
* excluding link layer.
|
|
||||||
*/
|
|
||||||
int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
|
|
||||||
struct cfctrl_link_param *param,
|
|
||||||
struct cflayer *adap_layer,
|
|
||||||
int *ifindex,
|
|
||||||
int *proto_head,
|
|
||||||
int *proto_tail);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cfcnfg_get_phyid() - Get physical ID, given type.
|
|
||||||
* Returns one of the physical interfaces matching the given type.
|
|
||||||
* Zero if no match is found.
|
|
||||||
* @cnfg: Configuration object
|
|
||||||
* @phy_pref: Caif Link Layer preference
|
|
||||||
*/
|
|
||||||
struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg,
|
|
||||||
enum cfcnfg_phy_preference phy_pref);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cfcnfg_get_id_from_ifi() - Get the Physical Identifier of ifindex,
|
|
||||||
* it matches caif physical id with the kernel interface id.
|
|
||||||
* @cnfg: Configuration object
|
|
||||||
* @ifi: ifindex obtained from socket.c bindtodevice.
|
|
||||||
*/
|
|
||||||
int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cfcnfg_set_phy_state() - Set the state of the physical interface device.
|
* cfcnfg_set_phy_state() - Set the state of the physical interface device.
|
||||||
* @cnfg: Configuration object
|
* @cnfg: Configuration object
|
||||||
|
@ -5,7 +5,7 @@ caif-y := caif_dev.o \
|
|||||||
cffrml.o cfveil.o cfdbgl.o\
|
cffrml.o cfveil.o cfdbgl.o\
|
||||||
cfserl.o cfdgml.o \
|
cfserl.o cfdgml.o \
|
||||||
cfrfml.o cfvidl.o cfutill.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) += caif.o
|
||||||
obj-$(CONFIG_CAIF_NETDEV) += chnl_net.o
|
obj-$(CONFIG_CAIF_NETDEV) += chnl_net.o
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -21,7 +21,6 @@
|
|||||||
#include <net/net_namespace.h>
|
#include <net/net_namespace.h>
|
||||||
#include <net/pkt_sched.h>
|
#include <net/pkt_sched.h>
|
||||||
#include <net/caif/caif_device.h>
|
#include <net/caif/caif_device.h>
|
||||||
#include <net/caif/caif_dev.h>
|
|
||||||
#include <net/caif/caif_layer.h>
|
#include <net/caif/caif_layer.h>
|
||||||
#include <net/caif/cfpkt.h>
|
#include <net/caif/cfpkt.h>
|
||||||
#include <net/caif/cfcnfg.h>
|
#include <net/caif/cfcnfg.h>
|
||||||
@ -43,11 +42,21 @@ struct caif_device_entry_list {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct caif_net {
|
struct caif_net {
|
||||||
|
struct cfcnfg *cfg;
|
||||||
struct caif_device_entry_list caifdevs;
|
struct caif_device_entry_list caifdevs;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int caif_net_id;
|
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)
|
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;
|
struct caif_dev_common *caifdev;
|
||||||
enum cfcnfg_phy_preference pref;
|
enum cfcnfg_phy_preference pref;
|
||||||
enum cfcnfg_phy_type phy_type;
|
enum cfcnfg_phy_type phy_type;
|
||||||
|
struct cfcnfg *cfg;
|
||||||
struct caif_device_entry_list *caifdevs =
|
struct caif_device_entry_list *caifdevs =
|
||||||
caif_device_list(dev_net(dev));
|
caif_device_list(dev_net(dev));
|
||||||
|
|
||||||
if (dev->type != ARPHRD_CAIF)
|
if (dev->type != ARPHRD_CAIF)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
cfg = get_cfcnfg(dev_net(dev));
|
||||||
|
if (cfg == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case NETDEV_REGISTER:
|
case NETDEV_REGISTER:
|
||||||
caifd = caif_device_alloc(dev);
|
caifd = caif_device_alloc(dev);
|
||||||
@ -235,7 +249,6 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
|
|||||||
phy_type,
|
phy_type,
|
||||||
dev,
|
dev,
|
||||||
&caifd->layer,
|
&caifd->layer,
|
||||||
0,
|
|
||||||
pref,
|
pref,
|
||||||
caifdev->use_fcs,
|
caifdev->use_fcs,
|
||||||
caifdev->use_stx);
|
caifdev->use_stx);
|
||||||
@ -323,35 +336,20 @@ static struct notifier_block caif_device_notifier = {
|
|||||||
.priority = 0,
|
.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 */
|
/* Per-namespace Caif devices handling */
|
||||||
static int caif_init_net(struct net *net)
|
static int caif_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct caif_net *caifn = net_generic(net, caif_net_id);
|
struct caif_net *caifn = net_generic(net, caif_net_id);
|
||||||
|
BUG_ON(!caifn);
|
||||||
INIT_LIST_HEAD(&caifn->caifdevs.list);
|
INIT_LIST_HEAD(&caifn->caifdevs.list);
|
||||||
mutex_init(&caifn->caifdevs.lock);
|
mutex_init(&caifn->caifdevs.lock);
|
||||||
|
|
||||||
|
caifn->cfg = cfcnfg_create();
|
||||||
|
if (!caifn->cfg) {
|
||||||
|
pr_warn("can't create cfcnfg\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,10 +358,17 @@ static void caif_exit_net(struct net *net)
|
|||||||
struct caif_device_entry *caifd, *tmp;
|
struct caif_device_entry *caifd, *tmp;
|
||||||
struct caif_device_entry_list *caifdevs =
|
struct caif_device_entry_list *caifdevs =
|
||||||
caif_device_list(net);
|
caif_device_list(net);
|
||||||
|
struct cfcnfg *cfg;
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
mutex_lock(&caifdevs->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) {
|
list_for_each_entry_safe(caifd, tmp, &caifdevs->list, list) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
list_del_rcu(&caifd->list);
|
list_del_rcu(&caifd->list);
|
||||||
@ -382,7 +387,7 @@ static void caif_exit_net(struct net *net)
|
|||||||
free_percpu(caifd->pcpu_refcnt);
|
free_percpu(caifd->pcpu_refcnt);
|
||||||
kfree(caifd);
|
kfree(caifd);
|
||||||
}
|
}
|
||||||
|
cfcnfg_remove(cfg);
|
||||||
|
|
||||||
mutex_unlock(&caifdevs->lock);
|
mutex_unlock(&caifdevs->lock);
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
@ -400,32 +405,22 @@ static int __init caif_device_init(void)
|
|||||||
{
|
{
|
||||||
int result;
|
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);
|
result = register_pernet_device(&caif_net_ops);
|
||||||
|
|
||||||
if (result) {
|
if (result)
|
||||||
kfree(cfg);
|
|
||||||
cfg = NULL;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
dev_add_pack(&caif_packet_type);
|
|
||||||
register_netdevice_notifier(&caif_device_notifier);
|
register_netdevice_notifier(&caif_device_notifier);
|
||||||
|
dev_add_pack(&caif_packet_type);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
err_cfcnfg_create_failed:
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit caif_device_exit(void)
|
static void __exit caif_device_exit(void)
|
||||||
{
|
{
|
||||||
dev_remove_pack(&caif_packet_type);
|
|
||||||
unregister_pernet_device(&caif_net_ops);
|
unregister_pernet_device(&caif_net_ops);
|
||||||
unregister_netdevice_notifier(&caif_device_notifier);
|
unregister_netdevice_notifier(&caif_device_notifier);
|
||||||
cfcnfg_remove(cfg);
|
dev_remove_pack(&caif_packet_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(caif_device_init);
|
module_init(caif_device_init);
|
||||||
|
@ -810,7 +810,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr,
|
|||||||
sk->sk_state == CAIF_DISCONNECTED);
|
sk->sk_state == CAIF_DISCONNECTED);
|
||||||
if (sk->sk_shutdown & SHUTDOWN_MASK) {
|
if (sk->sk_shutdown & SHUTDOWN_MASK) {
|
||||||
/* Allow re-connect after SHUTDOWN_IND */
|
/* Allow re-connect after SHUTDOWN_IND */
|
||||||
caif_disconnect_client(&cf_sk->layer);
|
caif_disconnect_client(sock_net(sk), &cf_sk->layer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* No reconnect on a seqpacket socket */
|
/* 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);
|
dbfs_atomic_inc(&cnt.num_connect_req);
|
||||||
cf_sk->layer.receive = caif_sktrecv_cb;
|
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);
|
&cf_sk->layer, &ifindex, &headroom, &tailroom);
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
@ -949,7 +949,7 @@ static int caif_release(struct socket *sock)
|
|||||||
|
|
||||||
if (cf_sk->sk.sk_socket->state == SS_CONNECTED ||
|
if (cf_sk->sk.sk_socket->state == SS_CONNECTED ||
|
||||||
cf_sk->sk.sk_socket->state == SS_CONNECTING)
|
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;
|
cf_sk->sk.sk_socket->state = SS_DISCONNECTING;
|
||||||
wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP);
|
wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP);
|
||||||
|
@ -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)
|
enum cfcnfg_phy_preference phy_pref)
|
||||||
{
|
{
|
||||||
/* Try to match with specified preference */
|
/* Try to match with specified preference */
|
||||||
@ -171,7 +171,7 @@ struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg,
|
|||||||
return NULL;
|
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;
|
struct cfcnfg_phyinfo *phy;
|
||||||
|
|
||||||
@ -181,11 +181,12 @@ int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi)
|
|||||||
return -ENODEV;
|
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;
|
u8 channel_id = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct cflayer *servl = NULL;
|
struct cflayer *servl = NULL;
|
||||||
|
struct cfcnfg *cfg = get_cfcnfg(net);
|
||||||
|
|
||||||
caif_assert(adap_layer != NULL);
|
caif_assert(adap_layer != NULL);
|
||||||
|
|
||||||
@ -217,14 +218,7 @@ end:
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfcnfg_disconn_adapt_layer);
|
EXPORT_SYMBOL(caif_disconnect_client);
|
||||||
|
|
||||||
void cfcnfg_release_adap_layer(struct cflayer *adap_layer)
|
|
||||||
{
|
|
||||||
if (adap_layer->dn)
|
|
||||||
cfsrvl_put(adap_layer->dn);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(cfcnfg_release_adap_layer);
|
|
||||||
|
|
||||||
static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id)
|
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,
|
[CFCTRL_SRV_DBG] = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
|
|
||||||
struct cfctrl_link_param *param,
|
static int caif_connect_req_to_link_param(struct cfcnfg *cnfg,
|
||||||
struct cflayer *adap_layer,
|
struct caif_connect_request *s,
|
||||||
int *ifindex,
|
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_head,
|
||||||
int *proto_tail)
|
int *proto_tail)
|
||||||
{
|
{
|
||||||
struct cflayer *frml;
|
struct cflayer *frml;
|
||||||
struct cfcnfg_phyinfo *phy;
|
struct cfcnfg_phyinfo *phy;
|
||||||
int err;
|
int err;
|
||||||
|
struct cfctrl_link_param param;
|
||||||
|
struct cfcnfg *cfg = get_cfcnfg(net);
|
||||||
|
caif_assert(cfg != NULL);
|
||||||
|
|
||||||
rcu_read_lock();
|
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) {
|
if (!phy) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
@ -276,28 +360,29 @@ int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
|
|||||||
pr_err("Specified PHY type does not exist!\n");
|
pr_err("Specified PHY type does not exist!\n");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
caif_assert(param->phyid == phy->id);
|
caif_assert(param.phyid == phy->id);
|
||||||
caif_assert(phy->frm_layer->id ==
|
caif_assert(phy->frm_layer->id ==
|
||||||
param->phyid);
|
param.phyid);
|
||||||
caif_assert(phy->phy_layer->id ==
|
caif_assert(phy->phy_layer->id ==
|
||||||
param->phyid);
|
param.phyid);
|
||||||
|
|
||||||
*ifindex = phy->ifindex;
|
*ifindex = phy->ifindex;
|
||||||
*proto_tail = 2;
|
*proto_tail = 2;
|
||||||
*proto_head =
|
*proto_head =
|
||||||
protohead[param->linktype] + (phy->use_stx ? 1 : 0);
|
|
||||||
|
protohead[param.linktype] + (phy->use_stx ? 1 : 0);
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
/* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
|
/* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
|
||||||
cfctrl_enum_req(cnfg->ctrl, param->phyid);
|
cfctrl_enum_req(cfg->ctrl, param.phyid);
|
||||||
return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer);
|
return cfctrl_linkup_request(cfg->ctrl, ¶m, adap_layer);
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfcnfg_add_adaptation_layer);
|
EXPORT_SYMBOL(caif_connect_client);
|
||||||
|
|
||||||
static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
|
static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
|
||||||
struct cflayer *adapt_layer)
|
struct cflayer *adapt_layer)
|
||||||
@ -389,7 +474,7 @@ unlock:
|
|||||||
void
|
void
|
||||||
cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
|
cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
|
||||||
struct net_device *dev, struct cflayer *phy_layer,
|
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)
|
bool fcs, bool stx)
|
||||||
{
|
{
|
||||||
struct cflayer *frml;
|
struct cflayer *frml;
|
||||||
@ -512,23 +597,26 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer)
|
|||||||
phyid = phy_layer->id;
|
phyid = phy_layer->id;
|
||||||
phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid);
|
phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid);
|
||||||
|
|
||||||
if (phyinfo == NULL)
|
if (phyinfo == NULL) {
|
||||||
|
mutex_unlock(&cnfg->lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
caif_assert(phyid == phyinfo->id);
|
caif_assert(phyid == phyinfo->id);
|
||||||
caif_assert(phy_layer == phyinfo->phy_layer);
|
caif_assert(phy_layer == phyinfo->phy_layer);
|
||||||
caif_assert(phy_layer->id == phyid);
|
caif_assert(phy_layer->id == phyid);
|
||||||
caif_assert(phyinfo->frm_layer->id == phyid);
|
caif_assert(phyinfo->frm_layer->id == phyid);
|
||||||
|
|
||||||
|
list_del_rcu(&phyinfo->node);
|
||||||
|
synchronize_rcu();
|
||||||
|
|
||||||
/* Fail if reference count is not zero */
|
/* Fail if reference count is not zero */
|
||||||
if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) {
|
if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) {
|
||||||
pr_info("Wait for device inuse\n");
|
pr_info("Wait for device inuse\n");
|
||||||
|
list_add_rcu(&phyinfo->node, &cnfg->phys);
|
||||||
mutex_unlock(&cnfg->lock);
|
mutex_unlock(&cnfg->lock);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_del_rcu(&phyinfo->node);
|
|
||||||
synchronize_rcu();
|
|
||||||
|
|
||||||
frml = phyinfo->frm_layer;
|
frml = phyinfo->frm_layer;
|
||||||
frml_dn = frml->dn;
|
frml_dn = frml->dn;
|
||||||
cffrml_set_uplayer(frml, NULL);
|
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);
|
layer_set_up(phy_layer, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (phyinfo->phy_layer != frml_dn)
|
if (phyinfo->phy_layer != frml_dn)
|
||||||
kfree(frml_dn);
|
kfree(frml_dn);
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include <linux/caif/if_caif.h>
|
#include <linux/caif/if_caif.h>
|
||||||
#include <net/rtnetlink.h>
|
#include <net/rtnetlink.h>
|
||||||
#include <net/caif/caif_layer.h>
|
#include <net/caif/caif_layer.h>
|
||||||
#include <net/caif/cfcnfg.h>
|
|
||||||
#include <net/caif/cfpkt.h>
|
#include <net/caif/cfpkt.h>
|
||||||
#include <net/caif/caif_dev.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) {
|
if (priv->state != CAIF_CONNECTING) {
|
||||||
priv->state = CAIF_CONNECTING;
|
priv->state = CAIF_CONNECTING;
|
||||||
result = caif_connect_client(&priv->conn_req, &priv->chnl,
|
result = caif_connect_client(dev_net(dev), &priv->conn_req,
|
||||||
&llifindex, &headroom, &tailroom);
|
&priv->chnl, &llifindex,
|
||||||
|
&headroom, &tailroom);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
pr_debug("err: "
|
pr_debug("err: "
|
||||||
"Unable to register and open device,"
|
"Unable to register and open device,"
|
||||||
@ -327,7 +327,7 @@ static int chnl_net_open(struct net_device *dev)
|
|||||||
|
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
pr_debug("connect timeout\n");
|
pr_debug("connect timeout\n");
|
||||||
caif_disconnect_client(&priv->chnl);
|
caif_disconnect_client(dev_net(dev), &priv->chnl);
|
||||||
priv->state = CAIF_DISCONNECTED;
|
priv->state = CAIF_DISCONNECTED;
|
||||||
pr_debug("state disconnected\n");
|
pr_debug("state disconnected\n");
|
||||||
result = -ETIMEDOUT;
|
result = -ETIMEDOUT;
|
||||||
@ -343,7 +343,7 @@ static int chnl_net_open(struct net_device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
caif_disconnect_client(&priv->chnl);
|
caif_disconnect_client(dev_net(dev), &priv->chnl);
|
||||||
priv->state = CAIF_DISCONNECTED;
|
priv->state = CAIF_DISCONNECTED;
|
||||||
pr_debug("state disconnected\n");
|
pr_debug("state disconnected\n");
|
||||||
return result;
|
return result;
|
||||||
@ -357,7 +357,7 @@ static int chnl_net_stop(struct net_device *dev)
|
|||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
priv = netdev_priv(dev);
|
priv = netdev_priv(dev);
|
||||||
priv->state = CAIF_DISCONNECTED;
|
priv->state = CAIF_DISCONNECTED;
|
||||||
caif_disconnect_client(&priv->chnl);
|
caif_disconnect_client(dev_net(dev), &priv->chnl);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user