aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2018-10-08 03:02:39 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2019-09-04 07:29:15 -0400
commit8df9ffb888c021fa68f9075d545f2ec5eca37200 (patch)
treec783503e0599f77685c82925a36bfa3f0a2a9794
parentffd956eef69b212a724b1cc4cdc61828f3ad9104 (diff)
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>
-rw-r--r--drivers/net/can/dev.c2
-rw-r--r--drivers/net/can/slcan.c1
-rw-r--r--drivers/net/can/vcan.c1
-rw-r--r--drivers/net/can/vxcan.c1
-rw-r--r--include/linux/can/can-ml.h1
-rw-r--r--net/can/af_can.c45
6 files changed, 12 insertions, 39 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 9e688dc29521..b429550c4cc2 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -746,6 +746,8 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
746 priv = netdev_priv(dev); 746 priv = netdev_priv(dev);
747 priv->dev = dev; 747 priv->dev = dev;
748 748
749 dev->ml_priv = (void *)priv + ALIGN(sizeof_priv, NETDEV_ALIGN);
750
749 if (echo_skb_max) { 751 if (echo_skb_max) {
750 priv->echo_skb_max = echo_skb_max; 752 priv->echo_skb_max = echo_skb_max;
751 priv->echo_skb = (void *)priv + 753 priv->echo_skb = (void *)priv +
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 5b2e95425e69..bb6032211043 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -536,6 +536,7 @@ static struct slcan *slc_alloc(void)
536 536
537 dev->base_addr = i; 537 dev->base_addr = i;
538 sl = netdev_priv(dev); 538 sl = netdev_priv(dev);
539 dev->ml_priv = (void *)sl + ALIGN(sizeof(*sl), NETDEV_ALIGN);
539 540
540 /* Initialize channel control data */ 541 /* Initialize channel control data */
541 sl->magic = SLCAN_MAGIC; 542 sl->magic = SLCAN_MAGIC;
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c
index 6973ae09a37a..39ca14b0585d 100644
--- a/drivers/net/can/vcan.c
+++ b/drivers/net/can/vcan.c
@@ -153,6 +153,7 @@ static void vcan_setup(struct net_device *dev)
153 dev->addr_len = 0; 153 dev->addr_len = 0;
154 dev->tx_queue_len = 0; 154 dev->tx_queue_len = 0;
155 dev->flags = IFF_NOARP; 155 dev->flags = IFF_NOARP;
156 dev->ml_priv = netdev_priv(dev);
156 157
157 /* set flags according to driver capabilities */ 158 /* set flags according to driver capabilities */
158 if (echo) 159 if (echo)
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
index 4c3eed796432..d6ba9426be4d 100644
--- a/drivers/net/can/vxcan.c
+++ b/drivers/net/can/vxcan.c
@@ -147,6 +147,7 @@ static void vxcan_setup(struct net_device *dev)
147 dev->flags = (IFF_NOARP|IFF_ECHO); 147 dev->flags = (IFF_NOARP|IFF_ECHO);
148 dev->netdev_ops = &vxcan_netdev_ops; 148 dev->netdev_ops = &vxcan_netdev_ops;
149 dev->needs_free_netdev = true; 149 dev->needs_free_netdev = true;
150 dev->ml_priv = netdev_priv(dev) + ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN);
150} 151}
151 152
152/* forward declaration for rtnl_create_link() */ 153/* forward declaration for rtnl_create_link() */
diff --git a/include/linux/can/can-ml.h b/include/linux/can/can-ml.h
index 0a9d778de8af..79ccf6bfa232 100644
--- a/include/linux/can/can-ml.h
+++ b/include/linux/can/can-ml.h
@@ -55,7 +55,6 @@ struct can_dev_rcv_lists {
55 struct hlist_head rx[RX_MAX]; 55 struct hlist_head rx[RX_MAX];
56 struct hlist_head rx_sff[CAN_SFF_RCV_ARRAY_SZ]; 56 struct hlist_head rx_sff[CAN_SFF_RCV_ARRAY_SZ];
57 struct hlist_head rx_eff[CAN_EFF_RCV_ARRAY_SZ]; 57 struct hlist_head rx_eff[CAN_EFF_RCV_ARRAY_SZ];
58 int remove_on_zero_entries;
59 int entries; 58 int entries;
60}; 59};
61 60
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 723299daa04e..6ed85e2f72f0 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -302,10 +302,12 @@ EXPORT_SYMBOL(can_send);
302static struct can_dev_rcv_lists *can_dev_rcv_lists_find(struct net *net, 302static struct can_dev_rcv_lists *can_dev_rcv_lists_find(struct net *net,
303 struct net_device *dev) 303 struct net_device *dev)
304{ 304{
305 if (!dev) 305 if (dev) {
306 struct can_ml_priv *ml_priv = dev->ml_priv;
307 return &ml_priv->dev_rcv_lists;
308 } else {
306 return net->can.rx_alldev_list; 309 return net->can.rx_alldev_list;
307 else 310 }
308 return (struct can_dev_rcv_lists *)dev->ml_priv;
309} 311}
310 312
311/** 313/**
@@ -561,12 +563,6 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
561 if (rcv_lists_stats->rcv_entries > 0) 563 if (rcv_lists_stats->rcv_entries > 0)
562 rcv_lists_stats->rcv_entries--; 564 rcv_lists_stats->rcv_entries--;
563 565
564 /* remove device structure requested by NETDEV_UNREGISTER */
565 if (dev_rcv_lists->remove_on_zero_entries && !dev_rcv_lists->entries) {
566 kfree(dev_rcv_lists);
567 dev->ml_priv = NULL;
568 }
569
570 out: 566 out:
571 spin_unlock(&net->can.rcvlists_lock); 567 spin_unlock(&net->can.rcvlists_lock);
572 568
@@ -788,41 +784,14 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
788 void *ptr) 784 void *ptr)
789{ 785{
790 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 786 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
791 struct can_dev_rcv_lists *dev_rcv_lists;
792 787
793 if (dev->type != ARPHRD_CAN) 788 if (dev->type != ARPHRD_CAN)
794 return NOTIFY_DONE; 789 return NOTIFY_DONE;
795 790
796 switch (msg) { 791 switch (msg) {
797 case NETDEV_REGISTER: 792 case NETDEV_REGISTER:
798 793 WARN(!dev->ml_priv,
799 /* create new dev_rcv_lists for this device */ 794 "No CAN mid layer private allocated, please fix your driver and use alloc_candev()!\n");
800 dev_rcv_lists = kzalloc(sizeof(*dev_rcv_lists), GFP_KERNEL);
801 if (!dev_rcv_lists)
802 return NOTIFY_DONE;
803 BUG_ON(dev->ml_priv);
804 dev->ml_priv = dev_rcv_lists;
805
806 break;
807
808 case NETDEV_UNREGISTER:
809 spin_lock(&dev_net(dev)->can.rcvlists_lock);
810
811 dev_rcv_lists = dev->ml_priv;
812 if (dev_rcv_lists) {
813 if (dev_rcv_lists->entries)
814 dev_rcv_lists->remove_on_zero_entries = 1;
815 else {
816 kfree(dev_rcv_lists);
817 dev->ml_priv = NULL;
818 }
819 } else {
820 pr_err("can: notifier: receive list not found for dev %s\n",
821 dev->name);
822 }
823
824 spin_unlock(&dev_net(dev)->can.rcvlists_lock);
825
826 break; 795 break;
827 } 796 }
828 797