mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 13:44:15 +08:00
can: make use of preallocated can_ml_priv for per device struct can_dev_rcv_lists
This patch removes the old method of allocating the per device protocol specific memory via a netdevice_notifier. This had the drawback, that the allocation can fail, leading to a lot of null pointer checks in the code. This also makes the live cycle management of this memory quite complicated. This patch switches from the allocating the struct can_dev_rcv_lists in a NETDEV_REGISTER call to using the dev->ml_priv, which is allocated by the driver since the previous patch. Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Acked-by: Oliver Hartkopp <socketcan@hartkopp.net> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
parent
ffd956eef6
commit
8df9ffb888
@ -746,6 +746,8 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
|
|||||||
priv = netdev_priv(dev);
|
priv = netdev_priv(dev);
|
||||||
priv->dev = dev;
|
priv->dev = dev;
|
||||||
|
|
||||||
|
dev->ml_priv = (void *)priv + ALIGN(sizeof_priv, NETDEV_ALIGN);
|
||||||
|
|
||||||
if (echo_skb_max) {
|
if (echo_skb_max) {
|
||||||
priv->echo_skb_max = echo_skb_max;
|
priv->echo_skb_max = echo_skb_max;
|
||||||
priv->echo_skb = (void *)priv +
|
priv->echo_skb = (void *)priv +
|
||||||
|
@ -536,6 +536,7 @@ static struct slcan *slc_alloc(void)
|
|||||||
|
|
||||||
dev->base_addr = i;
|
dev->base_addr = i;
|
||||||
sl = netdev_priv(dev);
|
sl = netdev_priv(dev);
|
||||||
|
dev->ml_priv = (void *)sl + ALIGN(sizeof(*sl), NETDEV_ALIGN);
|
||||||
|
|
||||||
/* Initialize channel control data */
|
/* Initialize channel control data */
|
||||||
sl->magic = SLCAN_MAGIC;
|
sl->magic = SLCAN_MAGIC;
|
||||||
|
@ -153,6 +153,7 @@ static void vcan_setup(struct net_device *dev)
|
|||||||
dev->addr_len = 0;
|
dev->addr_len = 0;
|
||||||
dev->tx_queue_len = 0;
|
dev->tx_queue_len = 0;
|
||||||
dev->flags = IFF_NOARP;
|
dev->flags = IFF_NOARP;
|
||||||
|
dev->ml_priv = netdev_priv(dev);
|
||||||
|
|
||||||
/* set flags according to driver capabilities */
|
/* set flags according to driver capabilities */
|
||||||
if (echo)
|
if (echo)
|
||||||
|
@ -147,6 +147,7 @@ static void vxcan_setup(struct net_device *dev)
|
|||||||
dev->flags = (IFF_NOARP|IFF_ECHO);
|
dev->flags = (IFF_NOARP|IFF_ECHO);
|
||||||
dev->netdev_ops = &vxcan_netdev_ops;
|
dev->netdev_ops = &vxcan_netdev_ops;
|
||||||
dev->needs_free_netdev = true;
|
dev->needs_free_netdev = true;
|
||||||
|
dev->ml_priv = netdev_priv(dev) + ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* forward declaration for rtnl_create_link() */
|
/* forward declaration for rtnl_create_link() */
|
||||||
|
@ -55,7 +55,6 @@ struct can_dev_rcv_lists {
|
|||||||
struct hlist_head rx[RX_MAX];
|
struct hlist_head rx[RX_MAX];
|
||||||
struct hlist_head rx_sff[CAN_SFF_RCV_ARRAY_SZ];
|
struct hlist_head rx_sff[CAN_SFF_RCV_ARRAY_SZ];
|
||||||
struct hlist_head rx_eff[CAN_EFF_RCV_ARRAY_SZ];
|
struct hlist_head rx_eff[CAN_EFF_RCV_ARRAY_SZ];
|
||||||
int remove_on_zero_entries;
|
|
||||||
int entries;
|
int entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -302,10 +302,12 @@ EXPORT_SYMBOL(can_send);
|
|||||||
static struct can_dev_rcv_lists *can_dev_rcv_lists_find(struct net *net,
|
static struct can_dev_rcv_lists *can_dev_rcv_lists_find(struct net *net,
|
||||||
struct net_device *dev)
|
struct net_device *dev)
|
||||||
{
|
{
|
||||||
if (!dev)
|
if (dev) {
|
||||||
|
struct can_ml_priv *ml_priv = dev->ml_priv;
|
||||||
|
return &ml_priv->dev_rcv_lists;
|
||||||
|
} else {
|
||||||
return net->can.rx_alldev_list;
|
return net->can.rx_alldev_list;
|
||||||
else
|
}
|
||||||
return (struct can_dev_rcv_lists *)dev->ml_priv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -561,12 +563,6 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
|
|||||||
if (rcv_lists_stats->rcv_entries > 0)
|
if (rcv_lists_stats->rcv_entries > 0)
|
||||||
rcv_lists_stats->rcv_entries--;
|
rcv_lists_stats->rcv_entries--;
|
||||||
|
|
||||||
/* remove device structure requested by NETDEV_UNREGISTER */
|
|
||||||
if (dev_rcv_lists->remove_on_zero_entries && !dev_rcv_lists->entries) {
|
|
||||||
kfree(dev_rcv_lists);
|
|
||||||
dev->ml_priv = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
spin_unlock(&net->can.rcvlists_lock);
|
spin_unlock(&net->can.rcvlists_lock);
|
||||||
|
|
||||||
@ -788,41 +784,14 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
|
|||||||
void *ptr)
|
void *ptr)
|
||||||
{
|
{
|
||||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||||
struct can_dev_rcv_lists *dev_rcv_lists;
|
|
||||||
|
|
||||||
if (dev->type != ARPHRD_CAN)
|
if (dev->type != ARPHRD_CAN)
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
case NETDEV_REGISTER:
|
case NETDEV_REGISTER:
|
||||||
|
WARN(!dev->ml_priv,
|
||||||
/* create new dev_rcv_lists for this device */
|
"No CAN mid layer private allocated, please fix your driver and use alloc_candev()!\n");
|
||||||
dev_rcv_lists = kzalloc(sizeof(*dev_rcv_lists), GFP_KERNEL);
|
|
||||||
if (!dev_rcv_lists)
|
|
||||||
return NOTIFY_DONE;
|
|
||||||
BUG_ON(dev->ml_priv);
|
|
||||||
dev->ml_priv = dev_rcv_lists;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NETDEV_UNREGISTER:
|
|
||||||
spin_lock(&dev_net(dev)->can.rcvlists_lock);
|
|
||||||
|
|
||||||
dev_rcv_lists = dev->ml_priv;
|
|
||||||
if (dev_rcv_lists) {
|
|
||||||
if (dev_rcv_lists->entries)
|
|
||||||
dev_rcv_lists->remove_on_zero_entries = 1;
|
|
||||||
else {
|
|
||||||
kfree(dev_rcv_lists);
|
|
||||||
dev->ml_priv = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pr_err("can: notifier: receive list not found for dev %s\n",
|
|
||||||
dev->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock(&dev_net(dev)->can.rcvlists_lock);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user