Commit 8df9ffb8 authored by Marc Kleine-Budde's avatar Marc Kleine-Budde

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: default avatarOleksij Rempel <o.rempel@pengutronix.de>
Acked-by: default avatarOliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent ffd956ee
...@@ -746,6 +746,8 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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); ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment