summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2018-10-08 09:02:38 +0200
committerMarc Kleine-Budde <mkl@pengutronix.de>2019-09-04 13:29:14 +0200
commitffd956eef69b212a724b1cc4cdc61828f3ad9104 (patch)
treec5366f9a90ed84c736c32ddc03c854299f456cc9 /drivers
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>
Diffstat (limited to 'drivers')
-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
4 files changed, 28 insertions, 8 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 @@
#include <linux/if_arp.h>
#include <linux/workqueue.h>
#include <linux/can.h>
+#include <linux/can/can-ml.h>
#include <linux/can/dev.h>
#include <linux/can/skb.h>
#include <linux/can/netlink.h>
@@ -718,11 +719,24 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
struct can_priv *priv;
int size;
+ /* We put the driver's priv, the CAN mid layer priv and the
+ * echo skb into the netdevice's priv. The memory layout for
+ * the netdev_priv is like this:
+ *
+ * +-------------------------+
+ * | driver's priv |
+ * +-------------------------+
+ * | struct can_ml_priv |
+ * +-------------------------+
+ * | array of struct sk_buff |
+ * +-------------------------+
+ */
+
+ size = ALIGN(sizeof_priv, NETDEV_ALIGN) + sizeof(struct can_ml_priv);
+
if (echo_skb_max)
- size = ALIGN(sizeof_priv, sizeof(struct sk_buff *)) +
+ size = ALIGN(size, sizeof(struct sk_buff *)) +
echo_skb_max * sizeof(struct sk_buff *);
- else
- size = sizeof_priv;
dev = alloc_netdev_mqs(size, "can%d", NET_NAME_UNKNOWN, can_setup,
txqs, rxqs);
@@ -735,7 +749,7 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
if (echo_skb_max) {
priv->echo_skb_max = echo_skb_max;
priv->echo_skb = (void *)priv +
- ALIGN(sizeof_priv, sizeof(struct sk_buff *));
+ (size - echo_skb_max * sizeof(struct sk_buff *));
}
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 @@
#include <linux/workqueue.h>
#include <linux/can.h>
#include <linux/can/skb.h>
+#include <linux/can/can-ml.h>
MODULE_ALIAS_LDISC(N_SLCAN);
MODULE_DESCRIPTION("serial line CAN interface");
@@ -514,6 +515,7 @@ static struct slcan *slc_alloc(void)
char name[IFNAMSIZ];
struct net_device *dev = NULL;
struct slcan *sl;
+ int size;
for (i = 0; i < maxdev; i++) {
dev = slcan_devs[i];
@@ -527,7 +529,8 @@ static struct slcan *slc_alloc(void)
return NULL;
sprintf(name, "slcan%d", i);
- dev = alloc_netdev(sizeof(*sl), name, NET_NAME_UNKNOWN, slc_setup);
+ size = ALIGN(sizeof(*sl), NETDEV_ALIGN) + sizeof(struct can_ml_priv);
+ dev = alloc_netdev(size, name, NET_NAME_UNKNOWN, slc_setup);
if (!dev)
return NULL;
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 @@
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/can.h>
+#include <linux/can/can-ml.h>
#include <linux/can/dev.h>
#include <linux/can/skb.h>
#include <linux/slab.h>
@@ -162,8 +163,9 @@ static void vcan_setup(struct net_device *dev)
}
static struct rtnl_link_ops vcan_link_ops __read_mostly = {
- .kind = DRV_NAME,
- .setup = vcan_setup,
+ .kind = DRV_NAME,
+ .priv_size = sizeof(struct can_ml_priv),
+ .setup = vcan_setup,
};
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 @@
#include <linux/can/dev.h>
#include <linux/can/skb.h>
#include <linux/can/vxcan.h>
+#include <linux/can/can-ml.h>
#include <linux/slab.h>
#include <net/rtnetlink.h>
@@ -281,7 +282,7 @@ static struct net *vxcan_get_link_net(const struct net_device *dev)
static struct rtnl_link_ops vxcan_link_ops = {
.kind = DRV_NAME,
- .priv_size = sizeof(struct vxcan_priv),
+ .priv_size = ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN) + sizeof(struct can_ml_priv),
.setup = vxcan_setup,
.newlink = vxcan_newlink,
.dellink = vxcan_dellink,