mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 20:54:10 +08:00
caif: Restructure how link caif link layer enroll
Enrolling CAIF link layers are refactored. 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
200c5a3b38
commit
7c18d2205e
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <net/caif/caif_layer.h>
|
#include <net/caif/caif_layer.h>
|
||||||
#include <net/caif/cfcnfg.h>
|
#include <net/caif/cfcnfg.h>
|
||||||
|
#include <net/caif/caif_device.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>
|
#include <linux/net.h>
|
||||||
@ -104,4 +105,24 @@ void caif_client_register_refcnt(struct cflayer *adapt_layer,
|
|||||||
*/
|
*/
|
||||||
void caif_free_client(struct cflayer *adap_layer);
|
void caif_free_client(struct cflayer *adap_layer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct caif_enroll_dev - Enroll a net-device as a CAIF Link layer
|
||||||
|
* @dev: Network device to enroll.
|
||||||
|
* @caifdev: Configuration information from CAIF Link Layer
|
||||||
|
* @link_support: Link layer support layer
|
||||||
|
* @head_room: Head room needed by link support layer
|
||||||
|
* @layer: Lowest layer in CAIF stack
|
||||||
|
* @rcv_fun: Receive function for CAIF stack.
|
||||||
|
*
|
||||||
|
* This function enroll a CAIF link layer into CAIF Stack and
|
||||||
|
* expects the interface to be able to handle CAIF payload.
|
||||||
|
* The link_support layer is used to add any Link Layer specific
|
||||||
|
* framing.
|
||||||
|
*/
|
||||||
|
void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
|
||||||
|
struct cflayer *link_support, int head_room,
|
||||||
|
struct cflayer **layer, int (**rcv_func)(
|
||||||
|
struct sk_buff *, struct net_device *,
|
||||||
|
struct packet_type *, struct net_device *));
|
||||||
|
|
||||||
#endif /* CAIF_DEV_H_ */
|
#endif /* CAIF_DEV_H_ */
|
||||||
|
@ -72,15 +72,16 @@ void cfcnfg_remove(struct cfcnfg *cfg);
|
|||||||
* @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.
|
||||||
* @pref: The phy (link layer) preference.
|
* @pref: The phy (link layer) preference.
|
||||||
|
* @link_support: Protocol implementation for link layer specific protocol.
|
||||||
* @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 eXtention is used.
|
* @head_room: Head space needed by link specific protocol.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
|
cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
|
||||||
struct net_device *dev, struct cflayer *phy_layer,
|
struct net_device *dev, struct cflayer *phy_layer,
|
||||||
enum cfcnfg_phy_preference pref,
|
enum cfcnfg_phy_preference pref,
|
||||||
bool fcs, bool stx);
|
struct cflayer *link_support,
|
||||||
|
bool fcs, int head_room);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cfcnfg_del_phy_layer - Deletes an phy layer from the CAIF stack.
|
* cfcnfg_del_phy_layer - Deletes an phy layer from the CAIF stack.
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#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>
|
||||||
|
#include <net/caif/cfserl.h>
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
@ -53,7 +54,8 @@ struct cfcnfg *get_cfcnfg(struct net *net)
|
|||||||
struct caif_net *caifn;
|
struct caif_net *caifn;
|
||||||
BUG_ON(!net);
|
BUG_ON(!net);
|
||||||
caifn = net_generic(net, caif_net_id);
|
caifn = net_generic(net, caif_net_id);
|
||||||
BUG_ON(!caifn);
|
if (!caifn)
|
||||||
|
return NULL;
|
||||||
return caifn->cfg;
|
return caifn->cfg;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(get_cfcnfg);
|
EXPORT_SYMBOL(get_cfcnfg);
|
||||||
@ -63,7 +65,8 @@ static struct caif_device_entry_list *caif_device_list(struct net *net)
|
|||||||
struct caif_net *caifn;
|
struct caif_net *caifn;
|
||||||
BUG_ON(!net);
|
BUG_ON(!net);
|
||||||
caifn = net_generic(net, caif_net_id);
|
caifn = net_generic(net, caif_net_id);
|
||||||
BUG_ON(!caifn);
|
if (!caifn)
|
||||||
|
return NULL;
|
||||||
return &caifn->caifdevs;
|
return &caifn->caifdevs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +95,8 @@ static struct caif_device_entry *caif_device_alloc(struct net_device *dev)
|
|||||||
struct caif_device_entry *caifd;
|
struct caif_device_entry *caifd;
|
||||||
|
|
||||||
caifdevs = caif_device_list(dev_net(dev));
|
caifdevs = caif_device_list(dev_net(dev));
|
||||||
BUG_ON(!caifdevs);
|
if (!caifdevs)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
caifd = kzalloc(sizeof(*caifd), GFP_KERNEL);
|
caifd = kzalloc(sizeof(*caifd), GFP_KERNEL);
|
||||||
if (!caifd)
|
if (!caifd)
|
||||||
@ -112,7 +116,9 @@ static struct caif_device_entry *caif_get(struct net_device *dev)
|
|||||||
struct caif_device_entry_list *caifdevs =
|
struct caif_device_entry_list *caifdevs =
|
||||||
caif_device_list(dev_net(dev));
|
caif_device_list(dev_net(dev));
|
||||||
struct caif_device_entry *caifd;
|
struct caif_device_entry *caifd;
|
||||||
BUG_ON(!caifdevs);
|
if (!caifdevs)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
list_for_each_entry_rcu(caifd, &caifdevs->list, list) {
|
list_for_each_entry_rcu(caifd, &caifdevs->list, list) {
|
||||||
if (caifd->netdev == dev)
|
if (caifd->netdev == dev)
|
||||||
return caifd;
|
return caifd;
|
||||||
@ -129,6 +135,8 @@ static int transmit(struct cflayer *layer, struct cfpkt *pkt)
|
|||||||
|
|
||||||
skb = cfpkt_tonative(pkt);
|
skb = cfpkt_tonative(pkt);
|
||||||
skb->dev = caifd->netdev;
|
skb->dev = caifd->netdev;
|
||||||
|
skb_reset_network_header(skb);
|
||||||
|
skb->protocol = htons(ETH_P_CAIF);
|
||||||
|
|
||||||
err = dev_queue_xmit(skb);
|
err = dev_queue_xmit(skb);
|
||||||
if (err > 0)
|
if (err > 0)
|
||||||
@ -172,7 +180,10 @@ static int receive(struct sk_buff *skb, struct net_device *dev,
|
|||||||
|
|
||||||
/* Release reference to stack upwards */
|
/* Release reference to stack upwards */
|
||||||
caifd_put(caifd);
|
caifd_put(caifd);
|
||||||
return 0;
|
|
||||||
|
if (err != 0)
|
||||||
|
err = NET_RX_DROP;
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct packet_type caif_packet_type __read_mostly = {
|
static struct packet_type caif_packet_type __read_mostly = {
|
||||||
@ -203,6 +214,55 @@ static void dev_flowctrl(struct net_device *dev, int on)
|
|||||||
caifd_put(caifd);
|
caifd_put(caifd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
|
||||||
|
struct cflayer *link_support, int head_room,
|
||||||
|
struct cflayer **layer, int (**rcv_func)(
|
||||||
|
struct sk_buff *, struct net_device *,
|
||||||
|
struct packet_type *, struct net_device *))
|
||||||
|
{
|
||||||
|
struct caif_device_entry *caifd;
|
||||||
|
enum cfcnfg_phy_preference pref;
|
||||||
|
struct cfcnfg *cfg = get_cfcnfg(dev_net(dev));
|
||||||
|
struct caif_device_entry_list *caifdevs;
|
||||||
|
|
||||||
|
caifdevs = caif_device_list(dev_net(dev));
|
||||||
|
if (!cfg || !caifdevs)
|
||||||
|
return;
|
||||||
|
caifd = caif_device_alloc(dev);
|
||||||
|
if (!caifd)
|
||||||
|
return;
|
||||||
|
*layer = &caifd->layer;
|
||||||
|
|
||||||
|
switch (caifdev->link_select) {
|
||||||
|
case CAIF_LINK_HIGH_BANDW:
|
||||||
|
pref = CFPHYPREF_HIGH_BW;
|
||||||
|
break;
|
||||||
|
case CAIF_LINK_LOW_LATENCY:
|
||||||
|
pref = CFPHYPREF_LOW_LAT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pref = CFPHYPREF_HIGH_BW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mutex_lock(&caifdevs->lock);
|
||||||
|
list_add_rcu(&caifd->list, &caifdevs->list);
|
||||||
|
|
||||||
|
strncpy(caifd->layer.name, dev->name,
|
||||||
|
sizeof(caifd->layer.name) - 1);
|
||||||
|
caifd->layer.name[sizeof(caifd->layer.name) - 1] = 0;
|
||||||
|
caifd->layer.transmit = transmit;
|
||||||
|
cfcnfg_add_phy_layer(cfg,
|
||||||
|
dev,
|
||||||
|
&caifd->layer,
|
||||||
|
pref,
|
||||||
|
link_support,
|
||||||
|
caifdev->use_fcs,
|
||||||
|
head_room);
|
||||||
|
mutex_unlock(&caifdevs->lock);
|
||||||
|
if (rcv_func)
|
||||||
|
*rcv_func = receive;
|
||||||
|
}
|
||||||
|
|
||||||
/* notify Caif of device events */
|
/* notify Caif of device events */
|
||||||
static int caif_device_notify(struct notifier_block *me, unsigned long what,
|
static int caif_device_notify(struct notifier_block *me, unsigned long what,
|
||||||
void *arg)
|
void *arg)
|
||||||
@ -210,62 +270,40 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
|
|||||||
struct net_device *dev = arg;
|
struct net_device *dev = arg;
|
||||||
struct caif_device_entry *caifd = NULL;
|
struct caif_device_entry *caifd = NULL;
|
||||||
struct caif_dev_common *caifdev;
|
struct caif_dev_common *caifdev;
|
||||||
enum cfcnfg_phy_preference pref;
|
|
||||||
enum cfcnfg_phy_type phy_type;
|
|
||||||
struct cfcnfg *cfg;
|
struct cfcnfg *cfg;
|
||||||
|
struct cflayer *layer, *link_support;
|
||||||
|
int head_room = 0;
|
||||||
struct caif_device_entry_list *caifdevs;
|
struct caif_device_entry_list *caifdevs;
|
||||||
|
|
||||||
if (dev->type != ARPHRD_CAIF)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cfg = get_cfcnfg(dev_net(dev));
|
cfg = get_cfcnfg(dev_net(dev));
|
||||||
if (cfg == NULL)
|
caifdevs = caif_device_list(dev_net(dev));
|
||||||
|
if (!cfg || !caifdevs)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
caifdevs = caif_device_list(dev_net(dev));
|
caifd = caif_get(dev);
|
||||||
|
if (caifd == NULL && dev->type != ARPHRD_CAIF)
|
||||||
|
return 0;
|
||||||
|
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case NETDEV_REGISTER:
|
case NETDEV_REGISTER:
|
||||||
caifd = caif_device_alloc(dev);
|
if (caifd != NULL)
|
||||||
if (!caifd)
|
break;
|
||||||
return 0;
|
|
||||||
|
|
||||||
caifdev = netdev_priv(dev);
|
caifdev = netdev_priv(dev);
|
||||||
caifdev->flowctrl = dev_flowctrl;
|
|
||||||
|
|
||||||
caifd->layer.transmit = transmit;
|
link_support = NULL;
|
||||||
|
if (caifdev->use_frag) {
|
||||||
if (caifdev->use_frag)
|
head_room = 1;
|
||||||
phy_type = CFPHYTYPE_FRAG;
|
link_support = cfserl_create(dev->ifindex,
|
||||||
else
|
CFPHYTYPE_FRAG, caifdev->use_stx);
|
||||||
phy_type = CFPHYTYPE_CAIF;
|
if (!link_support) {
|
||||||
|
pr_warn("Out of memory\n");
|
||||||
switch (caifdev->link_select) {
|
break;
|
||||||
case CAIF_LINK_HIGH_BANDW:
|
}
|
||||||
pref = CFPHYPREF_HIGH_BW;
|
|
||||||
break;
|
|
||||||
case CAIF_LINK_LOW_LATENCY:
|
|
||||||
pref = CFPHYPREF_LOW_LAT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pref = CFPHYPREF_HIGH_BW;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
strncpy(caifd->layer.name, dev->name,
|
caif_enroll_dev(dev, caifdev, link_support, head_room,
|
||||||
sizeof(caifd->layer.name) - 1);
|
&layer, NULL);
|
||||||
caifd->layer.name[sizeof(caifd->layer.name) - 1] = 0;
|
caifdev->flowctrl = dev_flowctrl;
|
||||||
|
|
||||||
mutex_lock(&caifdevs->lock);
|
|
||||||
list_add_rcu(&caifd->list, &caifdevs->list);
|
|
||||||
|
|
||||||
cfcnfg_add_phy_layer(cfg,
|
|
||||||
phy_type,
|
|
||||||
dev,
|
|
||||||
&caifd->layer,
|
|
||||||
pref,
|
|
||||||
caifdev->use_fcs,
|
|
||||||
caifdev->use_stx);
|
|
||||||
mutex_unlock(&caifdevs->lock);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NETDEV_UP:
|
case NETDEV_UP:
|
||||||
@ -371,17 +409,14 @@ 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;
|
struct cfcnfg *cfg = get_cfcnfg(net);
|
||||||
|
|
||||||
|
if (!cfg || !caifdevs)
|
||||||
|
return;
|
||||||
|
|
||||||
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);
|
||||||
|
@ -45,8 +45,8 @@ struct cfcnfg_phyinfo {
|
|||||||
/* Interface index */
|
/* Interface index */
|
||||||
int ifindex;
|
int ifindex;
|
||||||
|
|
||||||
/* Use Start of frame extension */
|
/* Protocol head room added for CAIF link layer */
|
||||||
bool use_stx;
|
int head_room;
|
||||||
|
|
||||||
/* Use Start of frame checksum */
|
/* Use Start of frame checksum */
|
||||||
bool use_fcs;
|
bool use_fcs;
|
||||||
@ -187,11 +187,11 @@ int caif_disconnect_client(struct net *net, struct cflayer *adap_layer)
|
|||||||
if (channel_id != 0) {
|
if (channel_id != 0) {
|
||||||
struct cflayer *servl;
|
struct cflayer *servl;
|
||||||
servl = cfmuxl_remove_uplayer(cfg->mux, channel_id);
|
servl = cfmuxl_remove_uplayer(cfg->mux, channel_id);
|
||||||
|
cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer);
|
||||||
if (servl != NULL)
|
if (servl != NULL)
|
||||||
layer_set_up(servl, NULL);
|
layer_set_up(servl, NULL);
|
||||||
} else
|
} else
|
||||||
pr_debug("nothing to disconnect\n");
|
pr_debug("nothing to disconnect\n");
|
||||||
cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer);
|
|
||||||
|
|
||||||
/* Do RCU sync before initiating cleanup */
|
/* Do RCU sync before initiating cleanup */
|
||||||
synchronize_rcu();
|
synchronize_rcu();
|
||||||
@ -350,9 +350,7 @@ int caif_connect_client(struct net *net, struct caif_connect_request *conn_req,
|
|||||||
|
|
||||||
*ifindex = phy->ifindex;
|
*ifindex = phy->ifindex;
|
||||||
*proto_tail = 2;
|
*proto_tail = 2;
|
||||||
*proto_head =
|
*proto_head = protohead[param.linktype] + phy->head_room;
|
||||||
|
|
||||||
protohead[param.linktype] + (phy->use_stx ? 1 : 0);
|
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
@ -460,13 +458,13 @@ unlock:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
|
cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
|
||||||
struct net_device *dev, struct cflayer *phy_layer,
|
struct net_device *dev, struct cflayer *phy_layer,
|
||||||
enum cfcnfg_phy_preference pref,
|
enum cfcnfg_phy_preference pref,
|
||||||
bool fcs, bool stx)
|
struct cflayer *link_support,
|
||||||
|
bool fcs, int head_room)
|
||||||
{
|
{
|
||||||
struct cflayer *frml;
|
struct cflayer *frml;
|
||||||
struct cflayer *phy_driver = NULL;
|
|
||||||
struct cfcnfg_phyinfo *phyinfo = NULL;
|
struct cfcnfg_phyinfo *phyinfo = NULL;
|
||||||
int i;
|
int i;
|
||||||
u8 phyid;
|
u8 phyid;
|
||||||
@ -482,26 +480,13 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
|
|||||||
goto got_phyid;
|
goto got_phyid;
|
||||||
}
|
}
|
||||||
pr_warn("Too many CAIF Link Layers (max 6)\n");
|
pr_warn("Too many CAIF Link Layers (max 6)\n");
|
||||||
goto out_err;
|
goto out;
|
||||||
|
|
||||||
got_phyid:
|
got_phyid:
|
||||||
phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC);
|
phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC);
|
||||||
if (!phyinfo)
|
if (!phyinfo)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
switch (phy_type) {
|
|
||||||
case CFPHYTYPE_FRAG:
|
|
||||||
phy_driver =
|
|
||||||
cfserl_create(CFPHYTYPE_FRAG, phyid, stx);
|
|
||||||
if (!phy_driver)
|
|
||||||
goto out_err;
|
|
||||||
break;
|
|
||||||
case CFPHYTYPE_CAIF:
|
|
||||||
phy_driver = NULL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
phy_layer->id = phyid;
|
phy_layer->id = phyid;
|
||||||
phyinfo->pref = pref;
|
phyinfo->pref = pref;
|
||||||
phyinfo->id = phyid;
|
phyinfo->id = phyid;
|
||||||
@ -509,7 +494,7 @@ got_phyid:
|
|||||||
phyinfo->dev_info.dev = dev;
|
phyinfo->dev_info.dev = dev;
|
||||||
phyinfo->phy_layer = phy_layer;
|
phyinfo->phy_layer = phy_layer;
|
||||||
phyinfo->ifindex = dev->ifindex;
|
phyinfo->ifindex = dev->ifindex;
|
||||||
phyinfo->use_stx = stx;
|
phyinfo->head_room = head_room;
|
||||||
phyinfo->use_fcs = fcs;
|
phyinfo->use_fcs = fcs;
|
||||||
|
|
||||||
frml = cffrml_create(phyid, fcs);
|
frml = cffrml_create(phyid, fcs);
|
||||||
@ -519,23 +504,23 @@ got_phyid:
|
|||||||
phyinfo->frm_layer = frml;
|
phyinfo->frm_layer = frml;
|
||||||
layer_set_up(frml, cnfg->mux);
|
layer_set_up(frml, cnfg->mux);
|
||||||
|
|
||||||
if (phy_driver != NULL) {
|
if (link_support != NULL) {
|
||||||
phy_driver->id = phyid;
|
link_support->id = phyid;
|
||||||
layer_set_dn(frml, phy_driver);
|
layer_set_dn(frml, link_support);
|
||||||
layer_set_up(phy_driver, frml);
|
layer_set_up(link_support, frml);
|
||||||
layer_set_dn(phy_driver, phy_layer);
|
layer_set_dn(link_support, phy_layer);
|
||||||
layer_set_up(phy_layer, phy_driver);
|
layer_set_up(phy_layer, link_support);
|
||||||
} else {
|
} else {
|
||||||
layer_set_dn(frml, phy_layer);
|
layer_set_dn(frml, phy_layer);
|
||||||
layer_set_up(phy_layer, frml);
|
layer_set_up(phy_layer, frml);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add_rcu(&phyinfo->node, &cnfg->phys);
|
list_add_rcu(&phyinfo->node, &cnfg->phys);
|
||||||
|
out:
|
||||||
mutex_unlock(&cnfg->lock);
|
mutex_unlock(&cnfg->lock);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
kfree(phy_driver);
|
|
||||||
kfree(phyinfo);
|
kfree(phyinfo);
|
||||||
mutex_unlock(&cnfg->lock);
|
mutex_unlock(&cnfg->lock);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user