diff options
author | Marc Kleine-Budde <mkl@pengutronix.de> | 2018-10-08 03:02:38 -0400 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2019-09-04 07:29:14 -0400 |
commit | ffd956eef69b212a724b1cc4cdc61828f3ad9104 (patch) | |
tree | c5366f9a90ed84c736c32ddc03c854299f456cc9 | |
parent | 3f15035606934a499975e4a5879a9499f072c179 (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.c | 22 | ||||
-rw-r--r-- | drivers/net/can/slcan.c | 5 | ||||
-rw-r--r-- | drivers/net/can/vcan.c | 6 | ||||
-rw-r--r-- | drivers/net/can/vxcan.c | 3 | ||||
-rw-r--r-- | include/linux/can/can-ml.h | 66 | ||||
-rw-r--r-- | net/can/af_can.c | 1 | ||||
-rw-r--r-- | net/can/af_can.h | 15 | ||||
-rw-r--r-- | net/can/proc.c | 1 |
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 | ||
59 | MODULE_ALIAS_LDISC(N_SLCAN); | 60 | MODULE_ALIAS_LDISC(N_SLCAN); |
60 | MODULE_DESCRIPTION("serial line CAN interface"); | 61 | MODULE_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 | ||
164 | static struct rtnl_link_ops vcan_link_ops __read_mostly = { | 165 | static 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 | ||
169 | static __init int vcan_init_module(void) | 171 | static __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 | ||
282 | static struct rtnl_link_ops vxcan_link_ops = { | 283 | static 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 | |||
52 | enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_MAX }; | ||
53 | |||
54 | struct 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 | |||
62 | struct 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 | |||
67 | enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_MAX }; | ||
68 | |||
69 | /* per device receive filters linked at dev->ml_priv */ | ||
70 | struct 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" |