This patch allows the CAN controller driver to define the number
of echo skb's used for the local loopback (echo), as suggested by
Kurt, via:
struct net_device *alloc_candev(int sizeof_priv,
unsigned int echo_skb_max);
The drivers have been adapted accordingly. Please test and comment
and check if the value of echo_skb_max is OK for your driver.
Kurt, feel free to add your signed-off-by here!
Signed-off-by: Wolfgang Grandegger <[email protected]>
---
kernel/2.6/drivers/net/can/at91_can.c | 2 -
kernel/2.6/drivers/net/can/cc770/cc770.c | 3 +-
kernel/2.6/drivers/net/can/cc770/cc770.h | 8 +++--
kernel/2.6/drivers/net/can/dev.c | 32 +++++++++++++++++-----
kernel/2.6/drivers/net/can/ems_usb.c | 4 +-
kernel/2.6/drivers/net/can/esd_pci331.c | 4 ++
kernel/2.6/drivers/net/can/mcp251x.c | 4 ++
kernel/2.6/drivers/net/can/mscan/mscan.c | 3 +-
kernel/2.6/drivers/net/can/sja1000/sja1000.c | 3 +-
kernel/2.6/drivers/net/can/sja1000/sja1000.h | 2 +
kernel/2.6/drivers/net/can/softing/softing_main.c | 12 ++++----
kernel/2.6/include/linux/can/dev.h | 16 +++++------
kernel/2.6/include/socketcan/can/dev.h | 16 +++++------
13 files changed, 71 insertions(+), 38 deletions(-)
Index: trunk/kernel/2.6/drivers/net/can/dev.c
===================================================================
--- trunk.orig/kernel/2.6/drivers/net/can/dev.c
+++ trunk/kernel/2.6/drivers/net/can/dev.c
@@ -272,7 +272,7 @@ static void can_flush_echo_skb(struct ne
#endif
int i;
- for (i = 0; i < CAN_ECHO_SKB_MAX; i++) {
+ for (i = 0; i < priv->echo_skb_max; i++) {
if (priv->echo_skb[i]) {
kfree_skb(priv->echo_skb[i]);
priv->echo_skb[i] = NULL;
@@ -289,10 +289,13 @@ static void can_flush_echo_skb(struct ne
* of the device driver. The driver must protect access to
* priv->echo_skb, if necessary.
*/
-void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx)
+void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
+ unsigned int idx)
{
struct can_priv *priv = netdev_priv(dev);
+ BUG_ON(idx >= priv->echo_skb_max);
+
/* check flag whether this packet has to be looped back */
if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) {
kfree_skb(skb);
@@ -338,10 +341,12 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb);
* is handled in the device driver. The driver must protect
* access to priv->echo_skb, if necessary.
*/
-void can_get_echo_skb(struct net_device *dev, int idx)
+void can_get_echo_skb(struct net_device *dev, unsigned int idx)
{
struct can_priv *priv = netdev_priv(dev);
+ BUG_ON(idx >= priv->echo_skb_max);
+
if (priv->echo_skb[idx]) {
netif_rx(priv->echo_skb[idx]);
priv->echo_skb[idx] = NULL;
@@ -354,10 +359,12 @@ EXPORT_SYMBOL_GPL(can_get_echo_skb);
*
* The function is typically called when TX failed.
*/
-void can_free_echo_skb(struct net_device *dev, int idx)
+void can_free_echo_skb(struct net_device *dev, unsigned int idx)
{
struct can_priv *priv = netdev_priv(dev);
+ BUG_ON(idx >= priv->echo_skb_max);
+
if (priv->echo_skb[idx]) {
kfree_skb(priv->echo_skb[idx]);
priv->echo_skb[idx] = NULL;
@@ -492,17 +499,30 @@ static void can_setup(struct net_device
/*
* Allocate and setup space for the CAN network device
*/
-struct net_device *alloc_candev(int sizeof_priv)
+struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max)
{
struct net_device *dev;
struct can_priv *priv;
+ int size;
- dev = alloc_netdev(sizeof_priv, "can%d", can_setup);
+ if (echo_skb_max)
+ size = ALIGN(sizeof_priv, struct sk_buff *) +
+ echo_skb_max * sizeof(struct sk_buff *);
+ else
+ size = sizeof_priv;
+
+ dev = alloc_netdev(size, "can%d", can_setup);
if (!dev)
return NULL;
priv = netdev_priv(dev);
+ if (echo_skb_max) {
+ priv->echo_skb_max = echo_skb_max;
+ priv->echo_skb = (void *)priv +
+ ALIGN(sizeof_priv, struct sk_buff *);
+ }
+
priv->state = CAN_STATE_STOPPED;
init_timer(&priv->restart_timer);
Index: trunk/kernel/2.6/include/linux/can/dev.h
===================================================================
--- trunk.orig/kernel/2.6/include/linux/can/dev.h
+++ trunk/kernel/2.6/include/linux/can/dev.h
@@ -32,8 +32,6 @@ enum can_mode {
/*
* CAN common private data
*/
-#define CAN_ECHO_SKB_MAX 4
-
struct can_priv {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
struct net_device_stats net_stats;
@@ -50,12 +48,13 @@ struct can_priv {
int restart_ms;
struct timer_list restart_timer;
- struct sk_buff *echo_skb[CAN_ECHO_SKB_MAX];
-
int (*do_set_bittiming)(struct net_device *dev);
int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
int (*do_get_state)(const struct net_device *dev,
enum can_state *state);
+
+ unsigned int echo_skb_max;
+ struct sk_buff **echo_skb;
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
@@ -72,7 +71,7 @@ struct can_priv {
struct net_device_stats *can_get_stats(struct net_device *dev);
#endif
-struct net_device *alloc_candev(int sizeof_priv);
+struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max);
void free_candev(struct net_device *dev);
int open_candev(struct net_device *dev);
@@ -84,8 +83,9 @@ void unregister_candev(struct net_device
int can_restart_now(struct net_device *dev);
void can_bus_off(struct net_device *dev);
-void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx);
-void can_get_echo_skb(struct net_device *dev, int idx);
-void can_free_echo_skb(struct net_device *dev, int idx);
+void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
+ unsigned int idx);
+void can_get_echo_skb(struct net_device *dev, unsigned int idx);
+void can_free_echo_skb(struct net_device *dev, unsigned int idx);
#endif /* CAN_DEV_H */
Index: trunk/kernel/2.6/drivers/net/can/at91_can.c
===================================================================
--- trunk.orig/kernel/2.6/drivers/net/can/at91_can.c
+++ trunk/kernel/2.6/drivers/net/can/at91_can.c
@@ -1094,7 +1094,7 @@ static int __init at91_can_probe(struct
goto exit_release;
}
- dev = alloc_candev(sizeof(struct at91_priv));
+ dev = alloc_candev(sizeof(struct at91_priv), AT91_MB_TX_NUM);
if (!dev) {
err = -ENOMEM;
goto exit_iounmap;
Index: trunk/kernel/2.6/drivers/net/can/cc770/cc770.c
===================================================================
--- trunk.orig/kernel/2.6/drivers/net/can/cc770/cc770.c
+++ trunk/kernel/2.6/drivers/net/can/cc770/cc770.c
@@ -862,7 +862,8 @@ struct net_device *alloc_cc770dev(int si
struct net_device *dev;
struct cc770_priv *priv;
- dev = alloc_candev(sizeof(struct cc770_priv) + sizeof_priv);
+ dev = alloc_candev(sizeof(struct cc770_priv) + sizeof_priv,
+ CC770_ECHO_SKB_MAX);
if (!dev)
return NULL;
Index: trunk/kernel/2.6/drivers/net/can/ems_usb.c
===================================================================
--- trunk.orig/kernel/2.6/drivers/net/can/ems_usb.c
+++ trunk/kernel/2.6/drivers/net/can/ems_usb.c
@@ -226,7 +226,7 @@ MODULE_DEVICE_TABLE(usb, ems_usb_table);
#define CPC_HEADER_SIZE 4
#define MAX_RX_URBS 10
-#define MAX_TX_URBS CAN_ECHO_SKB_MAX
+#define MAX_TX_URBS 4
struct ems_usb;
@@ -1018,7 +1018,7 @@ static int ems_usb_probe(struct usb_inte
struct ems_usb *dev;
int i, err;
- netdev = alloc_candev(sizeof(struct ems_usb));
+ netdev = alloc_candev(sizeof(struct ems_usb), MAX_TX_URBS);
if (!netdev) {
dev_err(ND2D(netdev), "Couldn't alloc candev\n");
return -ENOMEM;
Index: trunk/kernel/2.6/drivers/net/can/esd_pci331.c
===================================================================
--- trunk.orig/kernel/2.6/drivers/net/can/esd_pci331.c
+++ trunk/kernel/2.6/drivers/net/can/esd_pci331.c
@@ -99,6 +99,8 @@ MODULE_SUPPORTED_DEVICE("esd CAN-PCI/331
#define ESD331_I20_BOARD2 20
#define ESD331_I20_FAST 21
+#define ESD331_ECHO_SKB_MAX 1
+
static struct pci_device_id esd331_pci_tbl[] = {
{PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_PCI331},
@@ -785,7 +787,7 @@ static struct net_device *__devinit esd3
struct esd331_priv *priv;
int err;
- dev = alloc_candev(sizeof(*priv));
+ dev = alloc_candev(sizeof(*priv), ESD331_ECHO_SKB_MAX);
if (dev == NULL)
return ERR_PTR(-ENOMEM);
Index: trunk/kernel/2.6/drivers/net/can/mcp251x.c
===================================================================
--- trunk.orig/kernel/2.6/drivers/net/can/mcp251x.c
+++ trunk/kernel/2.6/drivers/net/can/mcp251x.c
@@ -150,6 +150,8 @@
#define SPI_TRANSFER_BUF_LEN (2*(6 + CAN_FRAME_MAX_DATA_LEN))
#define CAN_FRAME_MAX_BITS 128
+#define TX_ECHO_SKB_MAX 1
+
#define DEVICE_NAME "mcp251x"
static int mcp251x_enable_dma; /* Enable SPI DMA. Default: 0 (Off) */
@@ -946,7 +948,7 @@ static struct net_device *alloc_mcp251x_
struct net_device *net;
struct mcp251x_priv *priv;
- net = alloc_candev(sizeof_priv);
+ net = alloc_candev(sizeof_priv, TX_ECHO_SKB_MAX);
if (!net)
return NULL;
Index: trunk/kernel/2.6/drivers/net/can/mscan/mscan.c
===================================================================
--- trunk.orig/kernel/2.6/drivers/net/can/mscan/mscan.c
+++ trunk/kernel/2.6/drivers/net/can/mscan/mscan.c
@@ -46,6 +46,7 @@ RCSID("$Id: mscan.c 1059 2009-09-16 08:4
#define MSCAN_INIT_MODE (MSCAN_INITRQ | MSCAN_SLPRQ)
#define MSCAN_POWEROFF_MODE (MSCAN_CSWAI | MSCAN_SLPRQ)
#define MSCAN_SET_MODE_RETRIES 255
+#define MSCAN_ECHO_SKB_MAX 3
#define BTR0_BRP_MASK 0x3f
#define BTR0_SJW_SHIFT 6
@@ -729,7 +730,7 @@ struct net_device *alloc_mscandev(void)
struct mscan_priv *priv;
int i;
- dev = alloc_candev(sizeof(struct mscan_priv));
+ dev = alloc_candev(sizeof(struct mscan_priv), MSCAN_ECHO_SKB_MAX);
if (!dev)
return NULL;
priv = netdev_priv(dev);
Index: trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.c
===================================================================
--- trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.c
+++ trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.c
@@ -600,7 +600,8 @@ struct net_device *alloc_sja1000dev(int
struct net_device *dev;
struct sja1000_priv *priv;
- dev = alloc_candev(sizeof(struct sja1000_priv) + sizeof_priv);
+ dev = alloc_candev(sizeof(struct sja1000_priv) + sizeof_priv,
+ SJA1000_ECHO_SKB_MAX);
if (!dev)
return NULL;
Index: trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.h
===================================================================
--- trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.h
+++ trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.h
@@ -50,6 +50,8 @@
#include <socketcan/can/dev.h>
#include <socketcan/can/platform/sja1000.h>
+#define SJA1000_ECHO_SKB_MAX 1 /* the SJA1000 has one TX buffer object */
+
#define SJA1000_MAX_IRQ 20 /* max. number of interrupts handled in ISR */
/* SJA1000 registers - manual section 6.4 (Pelican Mode) */
Index: trunk/kernel/2.6/drivers/net/can/softing/softing_main.c
===================================================================
--- trunk.orig/kernel/2.6/drivers/net/can/softing/softing_main.c
+++ trunk/kernel/2.6/drivers/net/can/softing/softing_main.c
@@ -33,6 +33,8 @@
#error This driver does not support Kernel versions < 2.6.23
#endif
+#define TX_ECHO_SKB_MAX 4
+
/*
* test is a specific CAN netdev
* is online (ie. up 'n running, not sleeping, not busoff
@@ -74,7 +76,7 @@ static netdev_tx_t netdev_start_xmit(str
goto xmit_done;
if (card->tx.pending >= TXMAX)
goto xmit_done;
- if (priv->tx.pending >= CAN_ECHO_SKB_MAX)
+ if (priv->tx.pending >= TX_ECHO_SKB_MAX)
goto xmit_done;
fifo_wr = card->dpram.tx->wr;
if (fifo_wr == card->dpram.tx->rd)
@@ -112,7 +114,7 @@ static netdev_tx_t netdev_start_xmit(str
++priv->tx.pending;
can_put_echo_skb(skb, dev, priv->tx.echo_put);
++priv->tx.echo_put;
- if (priv->tx.echo_put >= CAN_ECHO_SKB_MAX)
+ if (priv->tx.echo_put >= TX_ECHO_SKB_MAX)
priv->tx.echo_put = 0;
/* can_put_echo_skb() saves the skb, safe to return TX_OK */
ret = NETDEV_TX_OK;
@@ -324,7 +326,7 @@ static int softing_dev_svc_once(struct s
skb->tstamp = ktime;
can_get_echo_skb(bus->netdev, bus->tx.echo_get);
++bus->tx.echo_get;
- if (bus->tx.echo_get >= CAN_ECHO_SKB_MAX)
+ if (bus->tx.echo_get >= TX_ECHO_SKB_MAX)
bus->tx.echo_get = 0;
if (bus->tx.pending)
--bus->tx.pending;
@@ -367,7 +369,7 @@ static void softing_dev_svc(unsigned lon
if (!canif_is_active(bus->netdev))
/* it makes no sense to wake dead busses */
continue;
- if (bus->tx.pending >= CAN_ECHO_SKB_MAX)
+ if (bus->tx.pending >= TX_ECHO_SKB_MAX)
continue;
netif_wake_queue(bus->netdev);
}
@@ -632,7 +634,7 @@ static struct softing_priv *mk_netdev(st
struct net_device *ndev;
struct softing_priv *priv;
- ndev = alloc_candev(sizeof(*priv));
+ ndev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX);
if (!ndev) {
dev_alert(card->dev, "alloc_candev failed\n");
return 0;
Index: trunk/kernel/2.6/drivers/net/can/cc770/cc770.h
===================================================================
--- trunk.orig/kernel/2.6/drivers/net/can/cc770/cc770.h
+++ trunk/kernel/2.6/drivers/net/can/cc770/cc770.h
@@ -188,6 +188,8 @@ struct cc770_regs {
#define CC770_IO_SIZE 0x100
#define CC770_MAX_IRQ 20 /* max. number of interrupts handled in ISR */
+#define CC770_ECHO_SKB_MAX 1
+
#define cc770_read_reg(priv, member) \
priv->read_reg(priv, offsetof(struct cc770_regs, member))
@@ -197,9 +199,9 @@ struct cc770_regs {
/*
* Message objects and flags used by this driver
*/
-#define CC770_OBJ_FLAG_RX 0x01
-#define CC770_OBJ_FLAG_RTR 0x02
-#define CC770_OBJ_FLAG_EFF 0x04
+#define CC770_OBJ_FLAG_RX 0x01
+#define CC770_OBJ_FLAG_RTR 0x02
+#define CC770_OBJ_FLAG_EFF 0x04
enum {
CC770_OBJ_RX0 = 0, /* for receiving normal messages */
Index: trunk/kernel/2.6/include/socketcan/can/dev.h
===================================================================
--- trunk.orig/kernel/2.6/include/socketcan/can/dev.h
+++ trunk/kernel/2.6/include/socketcan/can/dev.h
@@ -32,8 +32,6 @@ enum can_mode {
/*
* CAN common private data
*/
-#define CAN_ECHO_SKB_MAX 4
-
struct can_priv {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
struct net_device_stats net_stats;
@@ -50,12 +48,13 @@ struct can_priv {
int restart_ms;
struct timer_list restart_timer;
- struct sk_buff *echo_skb[CAN_ECHO_SKB_MAX];
-
int (*do_set_bittiming)(struct net_device *dev);
int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
int (*do_get_state)(const struct net_device *dev,
enum can_state *state);
+
+ unsigned int echo_skb_max;
+ struct sk_buff **echo_skb;
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
@@ -72,7 +71,7 @@ struct can_priv {
struct net_device_stats *can_get_stats(struct net_device *dev);
#endif
-struct net_device *alloc_candev(int sizeof_priv);
+struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max);
void free_candev(struct net_device *dev);
int open_candev(struct net_device *dev);
@@ -84,8 +83,9 @@ void unregister_candev(struct net_device
int can_restart_now(struct net_device *dev);
void can_bus_off(struct net_device *dev);
-void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx);
-void can_get_echo_skb(struct net_device *dev, int idx);
-void can_free_echo_skb(struct net_device *dev, int idx);
+void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
+ unsigned int idx);
+void can_get_echo_skb(struct net_device *dev, unsigned int idx);
+void can_free_echo_skb(struct net_device *dev, unsigned int idx);
#endif /* CAN_DEV_H */
_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core