From: wolf Date: Tue, 22 Sep 2009 08:08:15 +0000 (+0000) Subject: can: make the number of echo skb's configurable X-Git-Url: http://rtime.felk.cvut.cz/gitweb/socketcan-devel.git/commitdiff_plain/2cd1eea1a68de60cdd0cb26c4c708f3098f28286 can: make the number of echo skb's configurable 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 check if the value of echo_skb_max is OK for your driver. Signed-off-by: Kurt Van Dijck Signed-off-by: Wolfgang Grandegger git-svn-id: svn://svn.berlios.de//socketcan/trunk@1061 030b6a49-0b11-0410-94ab-b0dab22257f2 --- diff --git a/kernel/2.6/drivers/net/can/at91_can.c b/kernel/2.6/drivers/net/can/at91_can.c index 37c9107..35aa90c 100644 --- a/kernel/2.6/drivers/net/can/at91_can.c +++ b/kernel/2.6/drivers/net/can/at91_can.c @@ -1094,7 +1094,7 @@ static int __init at91_can_probe(struct platform_device *pdev) 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; diff --git a/kernel/2.6/drivers/net/can/cc770/cc770.c b/kernel/2.6/drivers/net/can/cc770/cc770.c index e6eee6b..c113067 100644 --- a/kernel/2.6/drivers/net/can/cc770/cc770.c +++ b/kernel/2.6/drivers/net/can/cc770/cc770.c @@ -862,7 +862,8 @@ struct net_device *alloc_cc770dev(int sizeof_priv) 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; diff --git a/kernel/2.6/drivers/net/can/cc770/cc770.h b/kernel/2.6/drivers/net/can/cc770/cc770.h index 1855c53..ded17c4 100644 --- a/kernel/2.6/drivers/net/can/cc770/cc770.h +++ b/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 */ diff --git a/kernel/2.6/drivers/net/can/dev.c b/kernel/2.6/drivers/net/can/dev.c index cc13c96..fd3d06e 100644 --- a/kernel/2.6/drivers/net/can/dev.c +++ b/kernel/2.6/drivers/net/can/dev.c @@ -272,7 +272,7 @@ static void can_flush_echo_skb(struct net_device *dev) #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 net_device *dev) * 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 *dev) /* * 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, sizeof(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, sizeof(struct sk_buff *)); + } + priv->state = CAN_STATE_STOPPED; init_timer(&priv->restart_timer); diff --git a/kernel/2.6/drivers/net/can/ems_usb.c b/kernel/2.6/drivers/net/can/ems_usb.c index 7fb9275..2b106cb 100644 --- a/kernel/2.6/drivers/net/can/ems_usb.c +++ b/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_interface *intf, 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; diff --git a/kernel/2.6/drivers/net/can/esd_pci331.c b/kernel/2.6/drivers/net/can/esd_pci331.c index 16aac28..5fe879d 100644 --- a/kernel/2.6/drivers/net/can/esd_pci331.c +++ b/kernel/2.6/drivers/net/can/esd_pci331.c @@ -99,6 +99,8 @@ MODULE_SUPPORTED_DEVICE("esd CAN-PCI/331, CAN-CPCI/331, CAN-PMC/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 esd331_pci_add_chan(struct pci_dev *pdev, 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); diff --git a/kernel/2.6/drivers/net/can/mcp251x.c b/kernel/2.6/drivers/net/can/mcp251x.c index 80e1a33..b08c923 100644 --- a/kernel/2.6/drivers/net/can/mcp251x.c +++ b/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_netdev(int sizeof_priv, 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; diff --git a/kernel/2.6/drivers/net/can/mscan/mscan.c b/kernel/2.6/drivers/net/can/mscan/mscan.c index fa5d907..894518e 100644 --- a/kernel/2.6/drivers/net/can/mscan/mscan.c +++ b/kernel/2.6/drivers/net/can/mscan/mscan.c @@ -46,6 +46,7 @@ RCSID("$Id$"); #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); diff --git a/kernel/2.6/drivers/net/can/sja1000/sja1000.c b/kernel/2.6/drivers/net/can/sja1000/sja1000.c index 54f65e7..994de09 100644 --- a/kernel/2.6/drivers/net/can/sja1000/sja1000.c +++ b/kernel/2.6/drivers/net/can/sja1000/sja1000.c @@ -600,7 +600,8 @@ struct net_device *alloc_sja1000dev(int sizeof_priv) 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; diff --git a/kernel/2.6/drivers/net/can/sja1000/sja1000.h b/kernel/2.6/drivers/net/can/sja1000/sja1000.h index 7a35f4c..02aeb18 100644 --- a/kernel/2.6/drivers/net/can/sja1000/sja1000.h +++ b/kernel/2.6/drivers/net/can/sja1000/sja1000.h @@ -50,6 +50,8 @@ #include #include +#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) */ diff --git a/kernel/2.6/drivers/net/can/softing/softing_main.c b/kernel/2.6/drivers/net/can/softing/softing_main.c index a9a45c3..cb1fd75 100644 --- a/kernel/2.6/drivers/net/can/softing/softing_main.c +++ b/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(struct sk_buff *skb, 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(struct sk_buff *skb, ++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 softing *card) 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 long param) 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(struct softing *card, u16 chip_id) 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; diff --git a/kernel/2.6/include/linux/can/dev.h b/kernel/2.6/include/linux/can/dev.h index fbe3741..6d693b1 100644 --- a/kernel/2.6/include/linux/can/dev.h +++ b/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 *dev); 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 */ diff --git a/kernel/2.6/include/socketcan/can/dev.h b/kernel/2.6/include/socketcan/can/dev.h index 933a575..617037c 100644 --- a/kernel/2.6/include/socketcan/can/dev.h +++ b/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 *dev); 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 */