summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2018-10-08 03:02:38 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2019-09-04 07:29:14 -0400
commitffd956eef69b212a724b1cc4cdc61828f3ad9104 (patch)
treec5366f9a90ed84c736c32ddc03c854299f456cc9
parent3f15035606934a499975e4a5879a9499f072c179 (diff)
can: introduce CAN midlayer private and allocate it automatically
This patch introduces the CAN midlayer private structure ("struct can_ml_priv") which should be used to hold protocol specific per device data structures. For now it's only member is "struct can_dev_rcv_lists". The CAN midlayer private is allocated via alloc_netdev()'s private and assigned to "struct net_device::ml_priv" during device creation. This is done transparently for CAN drivers using alloc_candev(). The slcan, vcan and vxcan drivers which are not using alloc_candev() have been adopted manually. The memory layout of the netdev_priv allocated via alloc_candev() will looke like this: +-------------------------+ | driver's priv | +-------------------------+ | struct can_ml_priv | +-------------------------+ | array of struct sk_buff | +-------------------------+ Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r--drivers/net/can/dev.c22
-rw-r--r--drivers/net/can/slcan.c5
-rw-r--r--drivers/net/can/vcan.c6
-rw-r--r--drivers/net/can/vxcan.c3
-rw-r--r--include/linux/can/can-ml.h66
-rw-r--r--net/can/af_can.c1
-rw-r--r--net/can/af_can.h15
-rw-r--r--net/can/proc.c1
8 files changed, 96 insertions, 23 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 483d270664cc..9e688dc29521 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -12,6 +12,7 @@
12#include <linux/if_arp.h> 12#include <linux/if_arp.h>
13#include <linux/workqueue.h> 13#include <linux/workqueue.h>
14#include <linux/can.h> 14#include <linux/can.h>
15#include <linux/can/can-ml.h>
15#include <linux/can/dev.h> 16#include <linux/can/dev.h>
16#include <linux/can/skb.h> 17#include <linux/can/skb.h>
17#include <linux/can/netlink.h> 18#include <linux/can/netlink.h>
@@ -718,11 +719,24 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
718 struct can_priv *priv; 719 struct can_priv *priv;
719 int size; 720 int size;
720 721
722 /* We put the driver's priv, the CAN mid layer priv and the
723 * echo skb into the netdevice's priv. The memory layout for
724 * the netdev_priv is like this:
725 *
726 * +-------------------------+
727 * | driver's priv |
728 * +-------------------------+
729 * | struct can_ml_priv |
730 * +-------------------------+
731 * | array of struct sk_buff |
732 * +-------------------------+
733 */
734
735 size = ALIGN(sizeof_priv, NETDEV_ALIGN) + sizeof(struct can_ml_priv);
736
721 if (echo_skb_max) 737 if (echo_skb_max)
722 size = ALIGN(sizeof_priv, sizeof(struct sk_buff *)) + 738 size = ALIGN(size, sizeof(struct sk_buff *)) +
723 echo_skb_max * sizeof(struct sk_buff *); 739 echo_skb_max * sizeof(struct sk_buff *);
724 else
725 size = sizeof_priv;
726 740
727 dev = alloc_netdev_mqs(size, "can%d", NET_NAME_UNKNOWN, can_setup, 741 dev = alloc_netdev_mqs(size, "can%d", NET_NAME_UNKNOWN, can_setup,
728 txqs, rxqs); 742 txqs, rxqs);
@@ -735,7 +749,7 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
735 if (echo_skb_max) { 749 if (echo_skb_max) {
736 priv->echo_skb_max = echo_skb_max; 750 priv->echo_skb_max = echo_skb_max;
737 priv->echo_skb = (void *)priv + 751 priv->echo_skb = (void *)priv +
738 ALIGN(sizeof_priv, sizeof(struct sk_buff *)); 752 (size - echo_skb_max * sizeof(struct sk_buff *));
739 } 753 }
740 754
741 priv->state = CAN_STATE_STOPPED; 755 priv->state = CAN_STATE_STOPPED;
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index aa97dbc797b6..5b2e95425e69 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -55,6 +55,7 @@
55#include <linux/workqueue.h> 55#include <linux/workqueue.h>
56#include <linux/can.h> 56#include <linux/can.h>
57#include <linux/can/skb.h> 57#include <linux/can/skb.h>
58#include <linux/can/can-ml.h>
58 59
59MODULE_ALIAS_LDISC(N_SLCAN); 60MODULE_ALIAS_LDISC(N_SLCAN);
60MODULE_DESCRIPTION("serial line CAN interface"); 61MODULE_DESCRIPTION("serial line CAN interface");
@@ -514,6 +515,7 @@ static struct slcan *slc_alloc(void)
514 char name[IFNAMSIZ]; 515 char name[IFNAMSIZ];
515 struct net_device *dev = NULL; 516 struct net_device *dev = NULL;
516 struct slcan *sl; 517 struct slcan *sl;
518 int size;
517 519
518 for (i = 0; i < maxdev; i++) { 520 for (i = 0; i < maxdev; i++) {
519 dev = slcan_devs[i]; 521 dev = slcan_devs[i];
@@ -527,7 +529,8 @@ static struct slcan *slc_alloc(void)
527 return NULL; 529 return NULL;
528 530
529 sprintf(name, "slcan%d", i); 531 sprintf(name, "slcan%d", i);
530 dev = alloc_netdev(sizeof(*sl), name, NET_NAME_UNKNOWN, slc_setup); 532 size = ALIGN(sizeof(*sl), NETDEV_ALIGN) + sizeof(struct can_ml_priv);
533 dev = alloc_netdev(size, name, NET_NAME_UNKNOWN, slc_setup);
531 if (!dev) 534 if (!dev)
532 return NULL; 535 return NULL;
533 536
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c
index daf27133887b..6973ae09a37a 100644
--- a/drivers/net/can/vcan.c
+++ b/drivers/net/can/vcan.c
@@ -46,6 +46,7 @@
46#include <linux/if_arp.h> 46#include <linux/if_arp.h>
47#include <linux/if_ether.h> 47#include <linux/if_ether.h>
48#include <linux/can.h> 48#include <linux/can.h>
49#include <linux/can/can-ml.h>
49#include <linux/can/dev.h> 50#include <linux/can/dev.h>
50#include <linux/can/skb.h> 51#include <linux/can/skb.h>
51#include <linux/slab.h> 52#include <linux/slab.h>
@@ -162,8 +163,9 @@ static void vcan_setup(struct net_device *dev)
162} 163}
163 164
164static struct rtnl_link_ops vcan_link_ops __read_mostly = { 165static struct rtnl_link_ops vcan_link_ops __read_mostly = {
165 .kind = DRV_NAME, 166 .kind = DRV_NAME,
166 .setup = vcan_setup, 167 .priv_size = sizeof(struct can_ml_priv),
168 .setup = vcan_setup,
167}; 169};
168 170
169static __init int vcan_init_module(void) 171static __init int vcan_init_module(void)
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
index b2106292230e..4c3eed796432 100644
--- a/drivers/net/can/vxcan.c
+++ b/drivers/net/can/vxcan.c
@@ -18,6 +18,7 @@
18#include <linux/can/dev.h> 18#include <linux/can/dev.h>
19#include <linux/can/skb.h> 19#include <linux/can/skb.h>
20#include <linux/can/vxcan.h> 20#include <linux/can/vxcan.h>
21#include <linux/can/can-ml.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
22#include <net/rtnetlink.h> 23#include <net/rtnetlink.h>
23 24
@@ -281,7 +282,7 @@ static struct net *vxcan_get_link_net(const struct net_device *dev)
281 282
282static struct rtnl_link_ops vxcan_link_ops = { 283static struct rtnl_link_ops vxcan_link_ops = {
283 .kind = DRV_NAME, 284 .kind = DRV_NAME,
284 .priv_size = sizeof(struct vxcan_priv), 285 .priv_size = ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN) + sizeof(struct can_ml_priv),
285 .setup = vxcan_setup, 286 .setup = vxcan_setup,
286 .newlink = vxcan_newlink, 287 .newlink = vxcan_newlink,
287 .dellink = vxcan_dellink, 288 .dellink = vxcan_dellink,
diff --git a/include/linux/can/can-ml.h b/include/linux/can/can-ml.h
new file mode 100644
index 000000000000..0a9d778de8af
--- /dev/null
+++ b/include/linux/can/can-ml.h
@@ -0,0 +1,66 @@
1/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
2/* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
3 * Copyright (c) 2017 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Volkswagen nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * Alternatively, provided that this notice is retained in full, this
20 * software may be distributed under the terms of the GNU General
21 * Public License ("GPL") version 2, in which case the provisions of the
22 * GPL apply INSTEAD OF those given above.
23 *
24 * The provided data structures and external interfaces from this code
25 * are not restricted to be used by modules with a GPL compatible license.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38 * DAMAGE.
39 *
40 */
41
42#ifndef CAN_ML_H
43#define CAN_ML_H
44
45#include <linux/can.h>
46#include <linux/list.h>
47
48#define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS)
49#define CAN_EFF_RCV_HASH_BITS 10
50#define CAN_EFF_RCV_ARRAY_SZ (1 << CAN_EFF_RCV_HASH_BITS)
51
52enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_MAX };
53
54struct can_dev_rcv_lists {
55 struct hlist_head rx[RX_MAX];
56 struct hlist_head rx_sff[CAN_SFF_RCV_ARRAY_SZ];
57 struct hlist_head rx_eff[CAN_EFF_RCV_ARRAY_SZ];
58 int remove_on_zero_entries;
59 int entries;
60};
61
62struct can_ml_priv {
63 struct can_dev_rcv_lists dev_rcv_lists;
64};
65
66#endif /* CAN_ML_H */
diff --git a/net/can/af_can.c b/net/can/af_can.c
index d65b19003a24..723299daa04e 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -58,6 +58,7 @@
58#include <linux/can.h> 58#include <linux/can.h>
59#include <linux/can/core.h> 59#include <linux/can/core.h>
60#include <linux/can/skb.h> 60#include <linux/can/skb.h>
61#include <linux/can/can-ml.h>
61#include <linux/ratelimit.h> 62#include <linux/ratelimit.h>
62#include <net/net_namespace.h> 63#include <net/net_namespace.h>
63#include <net/sock.h> 64#include <net/sock.h>
diff --git a/net/can/af_can.h b/net/can/af_can.h
index 25d22e534506..7c2d9161e224 100644
--- a/net/can/af_can.h
+++ b/net/can/af_can.h
@@ -60,21 +60,6 @@ struct receiver {
60 struct rcu_head rcu; 60 struct rcu_head rcu;
61}; 61};
62 62
63#define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS)
64#define CAN_EFF_RCV_HASH_BITS 10
65#define CAN_EFF_RCV_ARRAY_SZ (1 << CAN_EFF_RCV_HASH_BITS)
66
67enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_MAX };
68
69/* per device receive filters linked at dev->ml_priv */
70struct can_dev_rcv_lists {
71 struct hlist_head rx[RX_MAX];
72 struct hlist_head rx_sff[CAN_SFF_RCV_ARRAY_SZ];
73 struct hlist_head rx_eff[CAN_EFF_RCV_ARRAY_SZ];
74 int remove_on_zero_entries;
75 int entries;
76};
77
78/* statistic structures */ 63/* statistic structures */
79 64
80/* can be reset e.g. by can_init_stats() */ 65/* can be reset e.g. by can_init_stats() */
diff --git a/net/can/proc.c b/net/can/proc.c
index 560fa3c132bf..e6881bfc3ed1 100644
--- a/net/can/proc.c
+++ b/net/can/proc.c
@@ -45,6 +45,7 @@
45#include <linux/list.h> 45#include <linux/list.h>
46#include <linux/rcupdate.h> 46#include <linux/rcupdate.h>
47#include <linux/if_arp.h> 47#include <linux/if_arp.h>
48#include <linux/can/can-ml.h>
48#include <linux/can/core.h> 49#include <linux/can/core.h>
49 50
50#include "af_can.h" 51#include "af_can.h"