1af873fceSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
215c9ac0cSSjur Braendeland /*
315c9ac0cSSjur Braendeland * Copyright (C) ST-Ericsson AB 2010
426ee65e6Ssjur.brandeland@stericsson.com * Author: Sjur Brendeland
515c9ac0cSSjur Braendeland */
6b31fa5baSJoe Perches
7b31fa5baSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
8b31fa5baSJoe Perches
915c9ac0cSSjur Braendeland #include <linux/kernel.h>
1015c9ac0cSSjur Braendeland #include <linux/stddef.h>
116c579906SStephen Rothwell #include <linux/slab.h>
122aa40aefSSjur Braendeland #include <linux/netdevice.h>
13f3621440Ssjur.brandeland@stericsson.com #include <linux/module.h>
1415c9ac0cSSjur Braendeland #include <net/caif/caif_layer.h>
1515c9ac0cSSjur Braendeland #include <net/caif/cfpkt.h>
1615c9ac0cSSjur Braendeland #include <net/caif/cfcnfg.h>
1715c9ac0cSSjur Braendeland #include <net/caif/cfctrl.h>
1815c9ac0cSSjur Braendeland #include <net/caif/cfmuxl.h>
1915c9ac0cSSjur Braendeland #include <net/caif/cffrml.h>
2015c9ac0cSSjur Braendeland #include <net/caif/cfserl.h>
2115c9ac0cSSjur Braendeland #include <net/caif/cfsrvl.h>
22f3621440Ssjur.brandeland@stericsson.com #include <net/caif/caif_dev.h>
2315c9ac0cSSjur Braendeland
2415c9ac0cSSjur Braendeland #define container_obj(layr) container_of(layr, struct cfcnfg, layer)
2515c9ac0cSSjur Braendeland
2615c9ac0cSSjur Braendeland /* Information about CAIF physical interfaces held by Config Module in order
2715c9ac0cSSjur Braendeland * to manage physical interfaces
2815c9ac0cSSjur Braendeland */
2915c9ac0cSSjur Braendeland struct cfcnfg_phyinfo {
30f3621440Ssjur.brandeland@stericsson.com struct list_head node;
31f3621440Ssjur.brandeland@stericsson.com bool up;
32f3621440Ssjur.brandeland@stericsson.com
3315c9ac0cSSjur Braendeland /* Pointer to the layer below the MUX (framing layer) */
3415c9ac0cSSjur Braendeland struct cflayer *frm_layer;
3515c9ac0cSSjur Braendeland /* Pointer to the lowest actual physical layer */
3615c9ac0cSSjur Braendeland struct cflayer *phy_layer;
3715c9ac0cSSjur Braendeland /* Unique identifier of the physical interface */
3815c9ac0cSSjur Braendeland unsigned int id;
3915c9ac0cSSjur Braendeland /* Preference of the physical in interface */
4015c9ac0cSSjur Braendeland enum cfcnfg_phy_preference pref;
4115c9ac0cSSjur Braendeland
4215c9ac0cSSjur Braendeland /* Information about the physical device */
4315c9ac0cSSjur Braendeland struct dev_info dev_info;
442aa40aefSSjur Braendeland
452aa40aefSSjur Braendeland /* Interface index */
462aa40aefSSjur Braendeland int ifindex;
472aa40aefSSjur Braendeland
487c18d220Ssjur.brandeland@stericsson.com /* Protocol head room added for CAIF link layer */
497c18d220Ssjur.brandeland@stericsson.com int head_room;
502aa40aefSSjur Braendeland
512aa40aefSSjur Braendeland /* Use Start of frame checksum */
522aa40aefSSjur Braendeland bool use_fcs;
5315c9ac0cSSjur Braendeland };
5415c9ac0cSSjur Braendeland
5515c9ac0cSSjur Braendeland struct cfcnfg {
5615c9ac0cSSjur Braendeland struct cflayer layer;
5715c9ac0cSSjur Braendeland struct cflayer *ctrl;
5815c9ac0cSSjur Braendeland struct cflayer *mux;
59f3621440Ssjur.brandeland@stericsson.com struct list_head phys;
60f3621440Ssjur.brandeland@stericsson.com struct mutex lock;
6115c9ac0cSSjur Braendeland };
6215c9ac0cSSjur Braendeland
63e539d83cSSjur Braendeland static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id,
6415c9ac0cSSjur Braendeland enum cfctrl_srv serv, u8 phyid,
6515c9ac0cSSjur Braendeland struct cflayer *adapt_layer);
668d545c8fSSjur Braendeland static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id);
67e539d83cSSjur Braendeland static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
6815c9ac0cSSjur Braendeland struct cflayer *adapt_layer);
6915c9ac0cSSjur Braendeland static void cfctrl_resp_func(void);
7015c9ac0cSSjur Braendeland static void cfctrl_enum_resp(void);
7115c9ac0cSSjur Braendeland
cfcnfg_create(void)7215c9ac0cSSjur Braendeland struct cfcnfg *cfcnfg_create(void)
7315c9ac0cSSjur Braendeland {
7415c9ac0cSSjur Braendeland struct cfcnfg *this;
7515c9ac0cSSjur Braendeland struct cfctrl_rsp *resp;
76f3621440Ssjur.brandeland@stericsson.com
77f3621440Ssjur.brandeland@stericsson.com might_sleep();
78f3621440Ssjur.brandeland@stericsson.com
7915c9ac0cSSjur Braendeland /* Initiate this layer */
8049afa55bSJulia Lawall this = kzalloc(sizeof(struct cfcnfg), GFP_ATOMIC);
817ac2ed0cSJoe Perches if (!this)
8215c9ac0cSSjur Braendeland return NULL;
8315c9ac0cSSjur Braendeland this->mux = cfmuxl_create();
8415c9ac0cSSjur Braendeland if (!this->mux)
8515c9ac0cSSjur Braendeland goto out_of_mem;
8615c9ac0cSSjur Braendeland this->ctrl = cfctrl_create();
8715c9ac0cSSjur Braendeland if (!this->ctrl)
8815c9ac0cSSjur Braendeland goto out_of_mem;
8915c9ac0cSSjur Braendeland /* Initiate response functions */
9015c9ac0cSSjur Braendeland resp = cfctrl_get_respfuncs(this->ctrl);
9115c9ac0cSSjur Braendeland resp->enum_rsp = cfctrl_enum_resp;
9215c9ac0cSSjur Braendeland resp->linkerror_ind = cfctrl_resp_func;
93e539d83cSSjur Braendeland resp->linkdestroy_rsp = cfcnfg_linkdestroy_rsp;
9415c9ac0cSSjur Braendeland resp->sleep_rsp = cfctrl_resp_func;
9515c9ac0cSSjur Braendeland resp->wake_rsp = cfctrl_resp_func;
9615c9ac0cSSjur Braendeland resp->restart_rsp = cfctrl_resp_func;
9715c9ac0cSSjur Braendeland resp->radioset_rsp = cfctrl_resp_func;
98e539d83cSSjur Braendeland resp->linksetup_rsp = cfcnfg_linkup_rsp;
99e539d83cSSjur Braendeland resp->reject_rsp = cfcnfg_reject_rsp;
100f3621440Ssjur.brandeland@stericsson.com INIT_LIST_HEAD(&this->phys);
10115c9ac0cSSjur Braendeland
10215c9ac0cSSjur Braendeland cfmuxl_set_uplayer(this->mux, this->ctrl, 0);
10315c9ac0cSSjur Braendeland layer_set_dn(this->ctrl, this->mux);
10415c9ac0cSSjur Braendeland layer_set_up(this->ctrl, this);
105f3621440Ssjur.brandeland@stericsson.com mutex_init(&this->lock);
106f3621440Ssjur.brandeland@stericsson.com
10715c9ac0cSSjur Braendeland return this;
10815c9ac0cSSjur Braendeland out_of_mem:
109f3621440Ssjur.brandeland@stericsson.com synchronize_rcu();
110f3621440Ssjur.brandeland@stericsson.com
11115c9ac0cSSjur Braendeland kfree(this->mux);
11215c9ac0cSSjur Braendeland kfree(this->ctrl);
11315c9ac0cSSjur Braendeland kfree(this);
11415c9ac0cSSjur Braendeland return NULL;
11515c9ac0cSSjur Braendeland }
11615c9ac0cSSjur Braendeland
cfcnfg_remove(struct cfcnfg * cfg)11715c9ac0cSSjur Braendeland void cfcnfg_remove(struct cfcnfg *cfg)
11815c9ac0cSSjur Braendeland {
119f3621440Ssjur.brandeland@stericsson.com might_sleep();
12015c9ac0cSSjur Braendeland if (cfg) {
121f3621440Ssjur.brandeland@stericsson.com synchronize_rcu();
122f3621440Ssjur.brandeland@stericsson.com
12315c9ac0cSSjur Braendeland kfree(cfg->mux);
124c85c2951Ssjur.brandeland@stericsson.com cfctrl_remove(cfg->ctrl);
12515c9ac0cSSjur Braendeland kfree(cfg);
12615c9ac0cSSjur Braendeland }
12715c9ac0cSSjur Braendeland }
12815c9ac0cSSjur Braendeland
cfctrl_resp_func(void)12915c9ac0cSSjur Braendeland static void cfctrl_resp_func(void)
13015c9ac0cSSjur Braendeland {
13115c9ac0cSSjur Braendeland }
13215c9ac0cSSjur Braendeland
cfcnfg_get_phyinfo_rcu(struct cfcnfg * cnfg,u8 phyid)133f3621440Ssjur.brandeland@stericsson.com static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo_rcu(struct cfcnfg *cnfg,
134f3621440Ssjur.brandeland@stericsson.com u8 phyid)
135f3621440Ssjur.brandeland@stericsson.com {
136f3621440Ssjur.brandeland@stericsson.com struct cfcnfg_phyinfo *phy;
137f3621440Ssjur.brandeland@stericsson.com
138f3621440Ssjur.brandeland@stericsson.com list_for_each_entry_rcu(phy, &cnfg->phys, node)
139f3621440Ssjur.brandeland@stericsson.com if (phy->id == phyid)
140f3621440Ssjur.brandeland@stericsson.com return phy;
141f3621440Ssjur.brandeland@stericsson.com return NULL;
142f3621440Ssjur.brandeland@stericsson.com }
143f3621440Ssjur.brandeland@stericsson.com
cfctrl_enum_resp(void)14415c9ac0cSSjur Braendeland static void cfctrl_enum_resp(void)
14515c9ac0cSSjur Braendeland {
14615c9ac0cSSjur Braendeland }
14715c9ac0cSSjur Braendeland
cfcnfg_get_phyid(struct cfcnfg * cnfg,enum cfcnfg_phy_preference phy_pref)148bee925dbSsjur.brandeland@stericsson.com static struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg,
14915c9ac0cSSjur Braendeland enum cfcnfg_phy_preference phy_pref)
15015c9ac0cSSjur Braendeland {
15115c9ac0cSSjur Braendeland /* Try to match with specified preference */
152f3621440Ssjur.brandeland@stericsson.com struct cfcnfg_phyinfo *phy;
153f3621440Ssjur.brandeland@stericsson.com
154f3621440Ssjur.brandeland@stericsson.com list_for_each_entry_rcu(phy, &cnfg->phys, node) {
155f3621440Ssjur.brandeland@stericsson.com if (phy->up && phy->pref == phy_pref &&
156f3621440Ssjur.brandeland@stericsson.com phy->frm_layer != NULL)
157f3621440Ssjur.brandeland@stericsson.com
158f3621440Ssjur.brandeland@stericsson.com return &phy->dev_info;
15915c9ac0cSSjur Braendeland }
160f3621440Ssjur.brandeland@stericsson.com
16115c9ac0cSSjur Braendeland /* Otherwise just return something */
162f3621440Ssjur.brandeland@stericsson.com list_for_each_entry_rcu(phy, &cnfg->phys, node)
163f3621440Ssjur.brandeland@stericsson.com if (phy->up)
164f3621440Ssjur.brandeland@stericsson.com return &phy->dev_info;
16515c9ac0cSSjur Braendeland
16615c9ac0cSSjur Braendeland return NULL;
16715c9ac0cSSjur Braendeland }
16815c9ac0cSSjur Braendeland
cfcnfg_get_id_from_ifi(struct cfcnfg * cnfg,int ifi)169bee925dbSsjur.brandeland@stericsson.com static int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi)
17015c9ac0cSSjur Braendeland {
171f3621440Ssjur.brandeland@stericsson.com struct cfcnfg_phyinfo *phy;
172f3621440Ssjur.brandeland@stericsson.com
173f3621440Ssjur.brandeland@stericsson.com list_for_each_entry_rcu(phy, &cnfg->phys, node)
174f3621440Ssjur.brandeland@stericsson.com if (phy->ifindex == ifi && phy->up)
175f3621440Ssjur.brandeland@stericsson.com return phy->id;
176f2527ec4SAndré Carvalho de Matos return -ENODEV;
17715c9ac0cSSjur Braendeland }
17815c9ac0cSSjur Braendeland
caif_disconnect_client(struct net * net,struct cflayer * adap_layer)179bee925dbSsjur.brandeland@stericsson.com int caif_disconnect_client(struct net *net, struct cflayer *adap_layer)
18015c9ac0cSSjur Braendeland {
18154e90fb5Ssjur.brandeland@stericsson.com u8 channel_id;
182bee925dbSsjur.brandeland@stericsson.com struct cfcnfg *cfg = get_cfcnfg(net);
18301a85901SDan Carpenter
18415c9ac0cSSjur Braendeland caif_assert(adap_layer != NULL);
185f3621440Ssjur.brandeland@stericsson.com cfctrl_cancel_req(cfg->ctrl, adap_layer);
18654e90fb5Ssjur.brandeland@stericsson.com channel_id = adap_layer->id;
18754e90fb5Ssjur.brandeland@stericsson.com if (channel_id != 0) {
18854e90fb5Ssjur.brandeland@stericsson.com struct cflayer *servl;
18954e90fb5Ssjur.brandeland@stericsson.com servl = cfmuxl_remove_uplayer(cfg->mux, channel_id);
1907c18d220Ssjur.brandeland@stericsson.com cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer);
19154e90fb5Ssjur.brandeland@stericsson.com if (servl != NULL)
19254e90fb5Ssjur.brandeland@stericsson.com layer_set_up(servl, NULL);
19354e90fb5Ssjur.brandeland@stericsson.com } else
19454e90fb5Ssjur.brandeland@stericsson.com pr_debug("nothing to disconnect\n");
195f3621440Ssjur.brandeland@stericsson.com
196f3621440Ssjur.brandeland@stericsson.com /* Do RCU sync before initiating cleanup */
197f3621440Ssjur.brandeland@stericsson.com synchronize_rcu();
1988d545c8fSSjur Braendeland if (adap_layer->ctrlcmd != NULL)
1998d545c8fSSjur Braendeland adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0);
20054e90fb5Ssjur.brandeland@stericsson.com return 0;
20115c9ac0cSSjur Braendeland
20215c9ac0cSSjur Braendeland }
203bee925dbSsjur.brandeland@stericsson.com EXPORT_SYMBOL(caif_disconnect_client);
2045b208656SSjur Braendeland
cfcnfg_linkdestroy_rsp(struct cflayer * layer,u8 channel_id)2058d545c8fSSjur Braendeland static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id)
20615c9ac0cSSjur Braendeland {
20715c9ac0cSSjur Braendeland }
20815c9ac0cSSjur Braendeland
20973d6ac63SStephen Hemminger static const int protohead[CFCTRL_SRV_MASK] = {
2102aa40aefSSjur Braendeland [CFCTRL_SRV_VEI] = 4,
2112aa40aefSSjur Braendeland [CFCTRL_SRV_DATAGRAM] = 7,
2122aa40aefSSjur Braendeland [CFCTRL_SRV_UTIL] = 4,
2132aa40aefSSjur Braendeland [CFCTRL_SRV_RFM] = 3,
2142aa40aefSSjur Braendeland [CFCTRL_SRV_DBG] = 3,
2152aa40aefSSjur Braendeland };
2162aa40aefSSjur Braendeland
217bee925dbSsjur.brandeland@stericsson.com
caif_connect_req_to_link_param(struct cfcnfg * cnfg,struct caif_connect_request * s,struct cfctrl_link_param * l)218bee925dbSsjur.brandeland@stericsson.com static int caif_connect_req_to_link_param(struct cfcnfg *cnfg,
219bee925dbSsjur.brandeland@stericsson.com struct caif_connect_request *s,
220bee925dbSsjur.brandeland@stericsson.com struct cfctrl_link_param *l)
221bee925dbSsjur.brandeland@stericsson.com {
222bee925dbSsjur.brandeland@stericsson.com struct dev_info *dev_info;
223bee925dbSsjur.brandeland@stericsson.com enum cfcnfg_phy_preference pref;
224bee925dbSsjur.brandeland@stericsson.com int res;
225bee925dbSsjur.brandeland@stericsson.com
226bee925dbSsjur.brandeland@stericsson.com memset(l, 0, sizeof(*l));
227bee925dbSsjur.brandeland@stericsson.com /* In caif protocol low value is high priority */
228bee925dbSsjur.brandeland@stericsson.com l->priority = CAIF_PRIO_MAX - s->priority + 1;
229bee925dbSsjur.brandeland@stericsson.com
230bee925dbSsjur.brandeland@stericsson.com if (s->ifindex != 0) {
231bee925dbSsjur.brandeland@stericsson.com res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex);
232bee925dbSsjur.brandeland@stericsson.com if (res < 0)
233bee925dbSsjur.brandeland@stericsson.com return res;
234bee925dbSsjur.brandeland@stericsson.com l->phyid = res;
235bee925dbSsjur.brandeland@stericsson.com } else {
236bee925dbSsjur.brandeland@stericsson.com switch (s->link_selector) {
237bee925dbSsjur.brandeland@stericsson.com case CAIF_LINK_HIGH_BANDW:
238bee925dbSsjur.brandeland@stericsson.com pref = CFPHYPREF_HIGH_BW;
239bee925dbSsjur.brandeland@stericsson.com break;
240bee925dbSsjur.brandeland@stericsson.com case CAIF_LINK_LOW_LATENCY:
241bee925dbSsjur.brandeland@stericsson.com pref = CFPHYPREF_LOW_LAT;
242bee925dbSsjur.brandeland@stericsson.com break;
243bee925dbSsjur.brandeland@stericsson.com default:
244bee925dbSsjur.brandeland@stericsson.com return -EINVAL;
245bee925dbSsjur.brandeland@stericsson.com }
246bee925dbSsjur.brandeland@stericsson.com dev_info = cfcnfg_get_phyid(cnfg, pref);
247bee925dbSsjur.brandeland@stericsson.com if (dev_info == NULL)
248bee925dbSsjur.brandeland@stericsson.com return -ENODEV;
249bee925dbSsjur.brandeland@stericsson.com l->phyid = dev_info->id;
250bee925dbSsjur.brandeland@stericsson.com }
251bee925dbSsjur.brandeland@stericsson.com switch (s->protocol) {
252bee925dbSsjur.brandeland@stericsson.com case CAIFPROTO_AT:
253bee925dbSsjur.brandeland@stericsson.com l->linktype = CFCTRL_SRV_VEI;
254bee925dbSsjur.brandeland@stericsson.com l->endpoint = (s->sockaddr.u.at.type >> 2) & 0x3;
255bee925dbSsjur.brandeland@stericsson.com l->chtype = s->sockaddr.u.at.type & 0x3;
256bee925dbSsjur.brandeland@stericsson.com break;
257bee925dbSsjur.brandeland@stericsson.com case CAIFPROTO_DATAGRAM:
258bee925dbSsjur.brandeland@stericsson.com l->linktype = CFCTRL_SRV_DATAGRAM;
259bee925dbSsjur.brandeland@stericsson.com l->chtype = 0x00;
260bee925dbSsjur.brandeland@stericsson.com l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
261bee925dbSsjur.brandeland@stericsson.com break;
262bee925dbSsjur.brandeland@stericsson.com case CAIFPROTO_DATAGRAM_LOOP:
263bee925dbSsjur.brandeland@stericsson.com l->linktype = CFCTRL_SRV_DATAGRAM;
264bee925dbSsjur.brandeland@stericsson.com l->chtype = 0x03;
265bee925dbSsjur.brandeland@stericsson.com l->endpoint = 0x00;
266bee925dbSsjur.brandeland@stericsson.com l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
267bee925dbSsjur.brandeland@stericsson.com break;
268bee925dbSsjur.brandeland@stericsson.com case CAIFPROTO_RFM:
269bee925dbSsjur.brandeland@stericsson.com l->linktype = CFCTRL_SRV_RFM;
270bee925dbSsjur.brandeland@stericsson.com l->u.datagram.connid = s->sockaddr.u.rfm.connection_id;
271*df207b00SWolfram Sang strscpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume,
2723dc2fa47SXiongfeng Wang sizeof(l->u.rfm.volume));
273bee925dbSsjur.brandeland@stericsson.com break;
274bee925dbSsjur.brandeland@stericsson.com case CAIFPROTO_UTIL:
275bee925dbSsjur.brandeland@stericsson.com l->linktype = CFCTRL_SRV_UTIL;
276bee925dbSsjur.brandeland@stericsson.com l->endpoint = 0x00;
277bee925dbSsjur.brandeland@stericsson.com l->chtype = 0x00;
278*df207b00SWolfram Sang strscpy(l->u.utility.name, s->sockaddr.u.util.service,
2793dc2fa47SXiongfeng Wang sizeof(l->u.utility.name));
280bee925dbSsjur.brandeland@stericsson.com caif_assert(sizeof(l->u.utility.name) > 10);
281bee925dbSsjur.brandeland@stericsson.com l->u.utility.paramlen = s->param.size;
282bee925dbSsjur.brandeland@stericsson.com if (l->u.utility.paramlen > sizeof(l->u.utility.params))
283bee925dbSsjur.brandeland@stericsson.com l->u.utility.paramlen = sizeof(l->u.utility.params);
284bee925dbSsjur.brandeland@stericsson.com
285bee925dbSsjur.brandeland@stericsson.com memcpy(l->u.utility.params, s->param.data,
286bee925dbSsjur.brandeland@stericsson.com l->u.utility.paramlen);
287bee925dbSsjur.brandeland@stericsson.com
288bee925dbSsjur.brandeland@stericsson.com break;
289bee925dbSsjur.brandeland@stericsson.com case CAIFPROTO_DEBUG:
290bee925dbSsjur.brandeland@stericsson.com l->linktype = CFCTRL_SRV_DBG;
291bee925dbSsjur.brandeland@stericsson.com l->endpoint = s->sockaddr.u.dbg.service;
292bee925dbSsjur.brandeland@stericsson.com l->chtype = s->sockaddr.u.dbg.type;
293bee925dbSsjur.brandeland@stericsson.com break;
294bee925dbSsjur.brandeland@stericsson.com default:
295bee925dbSsjur.brandeland@stericsson.com return -EINVAL;
296bee925dbSsjur.brandeland@stericsson.com }
297bee925dbSsjur.brandeland@stericsson.com return 0;
298bee925dbSsjur.brandeland@stericsson.com }
299bee925dbSsjur.brandeland@stericsson.com
caif_connect_client(struct net * net,struct caif_connect_request * conn_req,struct cflayer * adap_layer,int * ifindex,int * proto_head,int * proto_tail)300bee925dbSsjur.brandeland@stericsson.com int caif_connect_client(struct net *net, struct caif_connect_request *conn_req,
301bee925dbSsjur.brandeland@stericsson.com struct cflayer *adap_layer, int *ifindex,
3023bffc475SSilviu-Mihai Popescu int *proto_head, int *proto_tail)
30315c9ac0cSSjur Braendeland {
30415c9ac0cSSjur Braendeland struct cflayer *frml;
305f3621440Ssjur.brandeland@stericsson.com struct cfcnfg_phyinfo *phy;
306f3621440Ssjur.brandeland@stericsson.com int err;
307bee925dbSsjur.brandeland@stericsson.com struct cfctrl_link_param param;
308bee925dbSsjur.brandeland@stericsson.com struct cfcnfg *cfg = get_cfcnfg(net);
309f3621440Ssjur.brandeland@stericsson.com
310f3621440Ssjur.brandeland@stericsson.com rcu_read_lock();
311bee925dbSsjur.brandeland@stericsson.com err = caif_connect_req_to_link_param(cfg, conn_req, ¶m);
312bee925dbSsjur.brandeland@stericsson.com if (err)
313bee925dbSsjur.brandeland@stericsson.com goto unlock;
314bee925dbSsjur.brandeland@stericsson.com
315bee925dbSsjur.brandeland@stericsson.com phy = cfcnfg_get_phyinfo_rcu(cfg, param.phyid);
316f3621440Ssjur.brandeland@stericsson.com if (!phy) {
317f3621440Ssjur.brandeland@stericsson.com err = -ENODEV;
318f3621440Ssjur.brandeland@stericsson.com goto unlock;
319f3621440Ssjur.brandeland@stericsson.com }
320f3621440Ssjur.brandeland@stericsson.com err = -EINVAL;
321f3621440Ssjur.brandeland@stericsson.com
32215c9ac0cSSjur Braendeland if (adap_layer == NULL) {
323b31fa5baSJoe Perches pr_err("adap_layer is zero\n");
324f3621440Ssjur.brandeland@stericsson.com goto unlock;
32515c9ac0cSSjur Braendeland }
32615c9ac0cSSjur Braendeland if (adap_layer->receive == NULL) {
327b31fa5baSJoe Perches pr_err("adap_layer->receive is NULL\n");
328f3621440Ssjur.brandeland@stericsson.com goto unlock;
32915c9ac0cSSjur Braendeland }
33015c9ac0cSSjur Braendeland if (adap_layer->ctrlcmd == NULL) {
331b31fa5baSJoe Perches pr_err("adap_layer->ctrlcmd == NULL\n");
332f3621440Ssjur.brandeland@stericsson.com goto unlock;
33315c9ac0cSSjur Braendeland }
334f3621440Ssjur.brandeland@stericsson.com
335f3621440Ssjur.brandeland@stericsson.com err = -ENODEV;
336f3621440Ssjur.brandeland@stericsson.com frml = phy->frm_layer;
33715c9ac0cSSjur Braendeland if (frml == NULL) {
338b31fa5baSJoe Perches pr_err("Specified PHY type does not exist!\n");
339f3621440Ssjur.brandeland@stericsson.com goto unlock;
34015c9ac0cSSjur Braendeland }
341bee925dbSsjur.brandeland@stericsson.com caif_assert(param.phyid == phy->id);
342f3621440Ssjur.brandeland@stericsson.com caif_assert(phy->frm_layer->id ==
343bee925dbSsjur.brandeland@stericsson.com param.phyid);
344f3621440Ssjur.brandeland@stericsson.com caif_assert(phy->phy_layer->id ==
345bee925dbSsjur.brandeland@stericsson.com param.phyid);
3462aa40aefSSjur Braendeland
347f3621440Ssjur.brandeland@stericsson.com *ifindex = phy->ifindex;
3482aa40aefSSjur Braendeland *proto_tail = 2;
3497c18d220Ssjur.brandeland@stericsson.com *proto_head = protohead[param.linktype] + phy->head_room;
350f3621440Ssjur.brandeland@stericsson.com
351f3621440Ssjur.brandeland@stericsson.com rcu_read_unlock();
3522aa40aefSSjur Braendeland
35315c9ac0cSSjur Braendeland /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
354bee925dbSsjur.brandeland@stericsson.com cfctrl_enum_req(cfg->ctrl, param.phyid);
355bee925dbSsjur.brandeland@stericsson.com return cfctrl_linkup_request(cfg->ctrl, ¶m, adap_layer);
356f3621440Ssjur.brandeland@stericsson.com
357f3621440Ssjur.brandeland@stericsson.com unlock:
358f3621440Ssjur.brandeland@stericsson.com rcu_read_unlock();
359f3621440Ssjur.brandeland@stericsson.com return err;
36015c9ac0cSSjur Braendeland }
361bee925dbSsjur.brandeland@stericsson.com EXPORT_SYMBOL(caif_connect_client);
36215c9ac0cSSjur Braendeland
cfcnfg_reject_rsp(struct cflayer * layer,u8 channel_id,struct cflayer * adapt_layer)363e539d83cSSjur Braendeland static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
36415c9ac0cSSjur Braendeland struct cflayer *adapt_layer)
36515c9ac0cSSjur Braendeland {
36615c9ac0cSSjur Braendeland if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL)
36715c9ac0cSSjur Braendeland adapt_layer->ctrlcmd(adapt_layer,
36815c9ac0cSSjur Braendeland CAIF_CTRLCMD_INIT_FAIL_RSP, 0);
36915c9ac0cSSjur Braendeland }
37015c9ac0cSSjur Braendeland
37115c9ac0cSSjur Braendeland static void
cfcnfg_linkup_rsp(struct cflayer * layer,u8 channel_id,enum cfctrl_srv serv,u8 phyid,struct cflayer * adapt_layer)372e539d83cSSjur Braendeland cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
37315c9ac0cSSjur Braendeland u8 phyid, struct cflayer *adapt_layer)
37415c9ac0cSSjur Braendeland {
37515c9ac0cSSjur Braendeland struct cfcnfg *cnfg = container_obj(layer);
37615c9ac0cSSjur Braendeland struct cflayer *servicel = NULL;
37715c9ac0cSSjur Braendeland struct cfcnfg_phyinfo *phyinfo;
3782aa40aefSSjur Braendeland struct net_device *netdev;
3792aa40aefSSjur Braendeland
38054e90fb5Ssjur.brandeland@stericsson.com if (channel_id == 0) {
38154e90fb5Ssjur.brandeland@stericsson.com pr_warn("received channel_id zero\n");
38254e90fb5Ssjur.brandeland@stericsson.com if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL)
38354e90fb5Ssjur.brandeland@stericsson.com adapt_layer->ctrlcmd(adapt_layer,
38454e90fb5Ssjur.brandeland@stericsson.com CAIF_CTRLCMD_INIT_FAIL_RSP, 0);
38554e90fb5Ssjur.brandeland@stericsson.com return;
38654e90fb5Ssjur.brandeland@stericsson.com }
38754e90fb5Ssjur.brandeland@stericsson.com
388f3621440Ssjur.brandeland@stericsson.com rcu_read_lock();
389f3621440Ssjur.brandeland@stericsson.com
39015c9ac0cSSjur Braendeland if (adapt_layer == NULL) {
391b09edbd0SColin Ian King pr_debug("link setup response but no client exist, send linkdown back\n");
3928d545c8fSSjur Braendeland cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL);
393f3621440Ssjur.brandeland@stericsson.com goto unlock;
39415c9ac0cSSjur Braendeland }
39515c9ac0cSSjur Braendeland
39615c9ac0cSSjur Braendeland caif_assert(cnfg != NULL);
39715c9ac0cSSjur Braendeland caif_assert(phyid != 0);
398f3621440Ssjur.brandeland@stericsson.com
399f3621440Ssjur.brandeland@stericsson.com phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid);
400f3621440Ssjur.brandeland@stericsson.com if (phyinfo == NULL) {
401b09edbd0SColin Ian King pr_err("ERROR: Link Layer Device disappeared while connecting\n");
402f3621440Ssjur.brandeland@stericsson.com goto unlock;
403f3621440Ssjur.brandeland@stericsson.com }
404f3621440Ssjur.brandeland@stericsson.com
405f3621440Ssjur.brandeland@stericsson.com caif_assert(phyinfo != NULL);
40615c9ac0cSSjur Braendeland caif_assert(phyinfo->id == phyid);
40715c9ac0cSSjur Braendeland caif_assert(phyinfo->phy_layer != NULL);
40815c9ac0cSSjur Braendeland caif_assert(phyinfo->phy_layer->id == phyid);
40915c9ac0cSSjur Braendeland
410e539d83cSSjur Braendeland adapt_layer->id = channel_id;
41115c9ac0cSSjur Braendeland
41215c9ac0cSSjur Braendeland switch (serv) {
41315c9ac0cSSjur Braendeland case CFCTRL_SRV_VEI:
414e539d83cSSjur Braendeland servicel = cfvei_create(channel_id, &phyinfo->dev_info);
41515c9ac0cSSjur Braendeland break;
41615c9ac0cSSjur Braendeland case CFCTRL_SRV_DATAGRAM:
417f3621440Ssjur.brandeland@stericsson.com servicel = cfdgml_create(channel_id,
418f3621440Ssjur.brandeland@stericsson.com &phyinfo->dev_info);
41915c9ac0cSSjur Braendeland break;
42015c9ac0cSSjur Braendeland case CFCTRL_SRV_RFM:
4212aa40aefSSjur Braendeland netdev = phyinfo->dev_info.dev;
422a7da1f55SSjur Braendeland servicel = cfrfml_create(channel_id, &phyinfo->dev_info,
4232aa40aefSSjur Braendeland netdev->mtu);
42415c9ac0cSSjur Braendeland break;
42515c9ac0cSSjur Braendeland case CFCTRL_SRV_UTIL:
426e539d83cSSjur Braendeland servicel = cfutill_create(channel_id, &phyinfo->dev_info);
42715c9ac0cSSjur Braendeland break;
42815c9ac0cSSjur Braendeland case CFCTRL_SRV_VIDEO:
429e539d83cSSjur Braendeland servicel = cfvidl_create(channel_id, &phyinfo->dev_info);
43015c9ac0cSSjur Braendeland break;
43115c9ac0cSSjur Braendeland case CFCTRL_SRV_DBG:
432e539d83cSSjur Braendeland servicel = cfdbgl_create(channel_id, &phyinfo->dev_info);
43315c9ac0cSSjur Braendeland break;
43415c9ac0cSSjur Braendeland default:
435b09edbd0SColin Ian King pr_err("Protocol error. Link setup response - unknown channel type\n");
436f3621440Ssjur.brandeland@stericsson.com goto unlock;
43715c9ac0cSSjur Braendeland }
4387ac2ed0cSJoe Perches if (!servicel)
439f3621440Ssjur.brandeland@stericsson.com goto unlock;
44015c9ac0cSSjur Braendeland layer_set_dn(servicel, cnfg->mux);
441e539d83cSSjur Braendeland cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id);
44215c9ac0cSSjur Braendeland layer_set_up(servicel, adapt_layer);
44315c9ac0cSSjur Braendeland layer_set_dn(adapt_layer, servicel);
444f3621440Ssjur.brandeland@stericsson.com
445f3621440Ssjur.brandeland@stericsson.com rcu_read_unlock();
446f3621440Ssjur.brandeland@stericsson.com
44715c9ac0cSSjur Braendeland servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0);
448f3621440Ssjur.brandeland@stericsson.com return;
449f3621440Ssjur.brandeland@stericsson.com unlock:
450f3621440Ssjur.brandeland@stericsson.com rcu_read_unlock();
45115c9ac0cSSjur Braendeland }
45215c9ac0cSSjur Braendeland
453a2805dcaSPavel Skripkin int
cfcnfg_add_phy_layer(struct cfcnfg * cnfg,struct net_device * dev,struct cflayer * phy_layer,enum cfcnfg_phy_preference pref,struct cflayer * link_support,bool fcs,int head_room)4547c18d220Ssjur.brandeland@stericsson.com cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
4552aa40aefSSjur Braendeland struct net_device *dev, struct cflayer *phy_layer,
456bee925dbSsjur.brandeland@stericsson.com enum cfcnfg_phy_preference pref,
4577c18d220Ssjur.brandeland@stericsson.com struct cflayer *link_support,
4587c18d220Ssjur.brandeland@stericsson.com bool fcs, int head_room)
45915c9ac0cSSjur Braendeland {
46015c9ac0cSSjur Braendeland struct cflayer *frml;
4615bb20ed8SDan Carpenter struct cfcnfg_phyinfo *phyinfo = NULL;
462a2805dcaSPavel Skripkin int i, res = 0;
463f3621440Ssjur.brandeland@stericsson.com u8 phyid;
46415c9ac0cSSjur Braendeland
465f3621440Ssjur.brandeland@stericsson.com mutex_lock(&cnfg->lock);
46615c9ac0cSSjur Braendeland
467f3621440Ssjur.brandeland@stericsson.com /* CAIF protocol allow maximum 6 link-layers */
468f3621440Ssjur.brandeland@stericsson.com for (i = 0; i < 7; i++) {
469f3621440Ssjur.brandeland@stericsson.com phyid = (dev->ifindex + i) & 0x7;
470f3621440Ssjur.brandeland@stericsson.com if (phyid == 0)
471f3621440Ssjur.brandeland@stericsson.com continue;
472f3621440Ssjur.brandeland@stericsson.com if (cfcnfg_get_phyinfo_rcu(cnfg, phyid) == NULL)
473f3621440Ssjur.brandeland@stericsson.com goto got_phyid;
474f3621440Ssjur.brandeland@stericsson.com }
475f3621440Ssjur.brandeland@stericsson.com pr_warn("Too many CAIF Link Layers (max 6)\n");
476a2805dcaSPavel Skripkin res = -EEXIST;
4777c18d220Ssjur.brandeland@stericsson.com goto out;
47815c9ac0cSSjur Braendeland
479f3621440Ssjur.brandeland@stericsson.com got_phyid:
480f3621440Ssjur.brandeland@stericsson.com phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC);
481a2805dcaSPavel Skripkin if (!phyinfo) {
482a2805dcaSPavel Skripkin res = -ENOMEM;
4839fd2bc32SDongliang Mu goto out;
484a2805dcaSPavel Skripkin }
48515c9ac0cSSjur Braendeland
486f3621440Ssjur.brandeland@stericsson.com phy_layer->id = phyid;
487f3621440Ssjur.brandeland@stericsson.com phyinfo->pref = pref;
488f3621440Ssjur.brandeland@stericsson.com phyinfo->id = phyid;
489f3621440Ssjur.brandeland@stericsson.com phyinfo->dev_info.id = phyid;
490f3621440Ssjur.brandeland@stericsson.com phyinfo->dev_info.dev = dev;
491f3621440Ssjur.brandeland@stericsson.com phyinfo->phy_layer = phy_layer;
492f3621440Ssjur.brandeland@stericsson.com phyinfo->ifindex = dev->ifindex;
4937c18d220Ssjur.brandeland@stericsson.com phyinfo->head_room = head_room;
494f3621440Ssjur.brandeland@stericsson.com phyinfo->use_fcs = fcs;
4952aa40aefSSjur Braendeland
496f3621440Ssjur.brandeland@stericsson.com frml = cffrml_create(phyid, fcs);
497f3621440Ssjur.brandeland@stericsson.com
498a2805dcaSPavel Skripkin if (!frml) {
499a2805dcaSPavel Skripkin res = -ENOMEM;
5005bb20ed8SDan Carpenter goto out_err;
501a2805dcaSPavel Skripkin }
502f3621440Ssjur.brandeland@stericsson.com phyinfo->frm_layer = frml;
50315c9ac0cSSjur Braendeland layer_set_up(frml, cnfg->mux);
50415c9ac0cSSjur Braendeland
5057c18d220Ssjur.brandeland@stericsson.com if (link_support != NULL) {
5067c18d220Ssjur.brandeland@stericsson.com link_support->id = phyid;
5077c18d220Ssjur.brandeland@stericsson.com layer_set_dn(frml, link_support);
5087c18d220Ssjur.brandeland@stericsson.com layer_set_up(link_support, frml);
5097c18d220Ssjur.brandeland@stericsson.com layer_set_dn(link_support, phy_layer);
5107c18d220Ssjur.brandeland@stericsson.com layer_set_up(phy_layer, link_support);
51115c9ac0cSSjur Braendeland } else {
51215c9ac0cSSjur Braendeland layer_set_dn(frml, phy_layer);
51315c9ac0cSSjur Braendeland layer_set_up(phy_layer, frml);
51415c9ac0cSSjur Braendeland }
515f3621440Ssjur.brandeland@stericsson.com
516f3621440Ssjur.brandeland@stericsson.com list_add_rcu(&phyinfo->node, &cnfg->phys);
5177c18d220Ssjur.brandeland@stericsson.com out:
5185bb20ed8SDan Carpenter mutex_unlock(&cnfg->lock);
519a2805dcaSPavel Skripkin return res;
5205bb20ed8SDan Carpenter
5215bb20ed8SDan Carpenter out_err:
5225bb20ed8SDan Carpenter kfree(phyinfo);
523f3621440Ssjur.brandeland@stericsson.com mutex_unlock(&cnfg->lock);
524a2805dcaSPavel Skripkin return res;
52515c9ac0cSSjur Braendeland }
52615c9ac0cSSjur Braendeland EXPORT_SYMBOL(cfcnfg_add_phy_layer);
52715c9ac0cSSjur Braendeland
cfcnfg_set_phy_state(struct cfcnfg * cnfg,struct cflayer * phy_layer,bool up)528f3621440Ssjur.brandeland@stericsson.com int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer,
529f3621440Ssjur.brandeland@stericsson.com bool up)
530f3621440Ssjur.brandeland@stericsson.com {
531f3621440Ssjur.brandeland@stericsson.com struct cfcnfg_phyinfo *phyinfo;
532f3621440Ssjur.brandeland@stericsson.com
533f3621440Ssjur.brandeland@stericsson.com rcu_read_lock();
534f3621440Ssjur.brandeland@stericsson.com phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phy_layer->id);
535f3621440Ssjur.brandeland@stericsson.com if (phyinfo == NULL) {
536f3621440Ssjur.brandeland@stericsson.com rcu_read_unlock();
537f3621440Ssjur.brandeland@stericsson.com return -ENODEV;
538f3621440Ssjur.brandeland@stericsson.com }
539f3621440Ssjur.brandeland@stericsson.com
540f3621440Ssjur.brandeland@stericsson.com if (phyinfo->up == up) {
541f3621440Ssjur.brandeland@stericsson.com rcu_read_unlock();
542f3621440Ssjur.brandeland@stericsson.com return 0;
543f3621440Ssjur.brandeland@stericsson.com }
544f3621440Ssjur.brandeland@stericsson.com phyinfo->up = up;
545f3621440Ssjur.brandeland@stericsson.com
546f3621440Ssjur.brandeland@stericsson.com if (up) {
547f3621440Ssjur.brandeland@stericsson.com cffrml_hold(phyinfo->frm_layer);
548f3621440Ssjur.brandeland@stericsson.com cfmuxl_set_dnlayer(cnfg->mux, phyinfo->frm_layer,
549f3621440Ssjur.brandeland@stericsson.com phy_layer->id);
550f3621440Ssjur.brandeland@stericsson.com } else {
551f3621440Ssjur.brandeland@stericsson.com cfmuxl_remove_dnlayer(cnfg->mux, phy_layer->id);
552f3621440Ssjur.brandeland@stericsson.com cffrml_put(phyinfo->frm_layer);
553f3621440Ssjur.brandeland@stericsson.com }
554f3621440Ssjur.brandeland@stericsson.com
555f3621440Ssjur.brandeland@stericsson.com rcu_read_unlock();
556f3621440Ssjur.brandeland@stericsson.com return 0;
557f3621440Ssjur.brandeland@stericsson.com }
558f3621440Ssjur.brandeland@stericsson.com EXPORT_SYMBOL(cfcnfg_set_phy_state);
559f3621440Ssjur.brandeland@stericsson.com
cfcnfg_del_phy_layer(struct cfcnfg * cnfg,struct cflayer * phy_layer)56015c9ac0cSSjur Braendeland int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer)
56115c9ac0cSSjur Braendeland {
56215c9ac0cSSjur Braendeland struct cflayer *frml, *frml_dn;
56315c9ac0cSSjur Braendeland u16 phyid;
564f3621440Ssjur.brandeland@stericsson.com struct cfcnfg_phyinfo *phyinfo;
56515c9ac0cSSjur Braendeland
566f3621440Ssjur.brandeland@stericsson.com might_sleep();
567f3621440Ssjur.brandeland@stericsson.com
568f3621440Ssjur.brandeland@stericsson.com mutex_lock(&cnfg->lock);
569f3621440Ssjur.brandeland@stericsson.com
570f3621440Ssjur.brandeland@stericsson.com phyid = phy_layer->id;
571f3621440Ssjur.brandeland@stericsson.com phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid);
572f3621440Ssjur.brandeland@stericsson.com
573bee925dbSsjur.brandeland@stericsson.com if (phyinfo == NULL) {
574bee925dbSsjur.brandeland@stericsson.com mutex_unlock(&cnfg->lock);
575f3621440Ssjur.brandeland@stericsson.com return 0;
576bee925dbSsjur.brandeland@stericsson.com }
577f3621440Ssjur.brandeland@stericsson.com caif_assert(phyid == phyinfo->id);
578f3621440Ssjur.brandeland@stericsson.com caif_assert(phy_layer == phyinfo->phy_layer);
579f3621440Ssjur.brandeland@stericsson.com caif_assert(phy_layer->id == phyid);
580f3621440Ssjur.brandeland@stericsson.com caif_assert(phyinfo->frm_layer->id == phyid);
581f3621440Ssjur.brandeland@stericsson.com
582bee925dbSsjur.brandeland@stericsson.com list_del_rcu(&phyinfo->node);
583bee925dbSsjur.brandeland@stericsson.com synchronize_rcu();
584bee925dbSsjur.brandeland@stericsson.com
585cb3cb423Ssjur.brandeland@stericsson.com /* Fail if reference count is not zero */
586cb3cb423Ssjur.brandeland@stericsson.com if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) {
587cb3cb423Ssjur.brandeland@stericsson.com pr_info("Wait for device inuse\n");
588bee925dbSsjur.brandeland@stericsson.com list_add_rcu(&phyinfo->node, &cnfg->phys);
589cb3cb423Ssjur.brandeland@stericsson.com mutex_unlock(&cnfg->lock);
590cb3cb423Ssjur.brandeland@stericsson.com return -EAGAIN;
591cb3cb423Ssjur.brandeland@stericsson.com }
592cb3cb423Ssjur.brandeland@stericsson.com
593f3621440Ssjur.brandeland@stericsson.com frml = phyinfo->frm_layer;
59415c9ac0cSSjur Braendeland frml_dn = frml->dn;
59515c9ac0cSSjur Braendeland cffrml_set_uplayer(frml, NULL);
59615c9ac0cSSjur Braendeland cffrml_set_dnlayer(frml, NULL);
59715c9ac0cSSjur Braendeland if (phy_layer != frml_dn) {
59815c9ac0cSSjur Braendeland layer_set_up(frml_dn, NULL);
59915c9ac0cSSjur Braendeland layer_set_dn(frml_dn, NULL);
60015c9ac0cSSjur Braendeland }
60115c9ac0cSSjur Braendeland layer_set_up(phy_layer, NULL);
602f3621440Ssjur.brandeland@stericsson.com
603f3621440Ssjur.brandeland@stericsson.com if (phyinfo->phy_layer != frml_dn)
604f3621440Ssjur.brandeland@stericsson.com kfree(frml_dn);
605f3621440Ssjur.brandeland@stericsson.com
606cb3cb423Ssjur.brandeland@stericsson.com cffrml_free(frml);
607f3621440Ssjur.brandeland@stericsson.com kfree(phyinfo);
608f3621440Ssjur.brandeland@stericsson.com mutex_unlock(&cnfg->lock);
609f3621440Ssjur.brandeland@stericsson.com
61015c9ac0cSSjur Braendeland return 0;
61115c9ac0cSSjur Braendeland }
61215c9ac0cSSjur Braendeland EXPORT_SYMBOL(cfcnfg_del_phy_layer);
613