mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 23:51:37 +00:00
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 Van Dijck, with the function: struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max); The CAN drivers have been adapted accordingly. For the ems_usb driver, as suggested by Sebastian Haas, the number of echo skb's has been increased to 10, which improves the transmission performance a lot. Signed-off-by: Wolfgang Grandegger <wg@grandegger.com> Signed-off-by: Kurt Van Dijck <kurt.van.dijck@eia.be> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
61321bbd62
commit
a6e4bc5304
@ -1087,7 +1087,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;
|
||||
|
@ -245,7 +245,7 @@ static void can_flush_echo_skb(struct net_device *dev)
|
||||
struct net_device_stats *stats = &dev->stats;
|
||||
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;
|
||||
@ -262,10 +262,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);
|
||||
@ -311,10 +314,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;
|
||||
@ -327,10 +332,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;
|
||||
@ -445,17 +452,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);
|
||||
|
@ -565,7 +565,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;
|
||||
|
||||
|
@ -50,6 +50,8 @@
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/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) */
|
||||
|
@ -74,10 +74,6 @@ MODULE_VERSION(HECC_MODULE_VERSION);
|
||||
#define HECC_MB_TX_SHIFT 2 /* as per table above */
|
||||
#define HECC_MAX_TX_MBOX BIT(HECC_MB_TX_SHIFT)
|
||||
|
||||
#if (HECC_MAX_TX_MBOX > CAN_ECHO_SKB_MAX)
|
||||
#error "HECC: MAX TX mailboxes should be equal or less than CAN_ECHO_SKB_MAX"
|
||||
#endif
|
||||
|
||||
#define HECC_TX_PRIO_SHIFT (HECC_MB_TX_SHIFT)
|
||||
#define HECC_TX_PRIO_MASK (MAX_TX_PRIO << HECC_MB_TX_SHIFT)
|
||||
#define HECC_TX_MB_MASK (HECC_MAX_TX_MBOX - 1)
|
||||
@ -902,7 +898,7 @@ static int ti_hecc_probe(struct platform_device *pdev)
|
||||
goto probe_exit_free_region;
|
||||
}
|
||||
|
||||
ndev = alloc_candev(sizeof(struct ti_hecc_priv));
|
||||
ndev = alloc_candev(sizeof(struct ti_hecc_priv), HECC_MAX_TX_MBOX);
|
||||
if (!ndev) {
|
||||
dev_err(&pdev->dev, "alloc_candev failed\n");
|
||||
err = -ENOMEM;
|
||||
|
@ -232,7 +232,7 @@ MODULE_DEVICE_TABLE(usb, ems_usb_table);
|
||||
#define INTR_IN_BUFFER_SIZE 4
|
||||
|
||||
#define MAX_RX_URBS 10
|
||||
#define MAX_TX_URBS CAN_ECHO_SKB_MAX
|
||||
#define MAX_TX_URBS 10
|
||||
|
||||
struct ems_usb;
|
||||
|
||||
@ -1012,7 +1012,7 @@ static int ems_usb_probe(struct usb_interface *intf,
|
||||
struct ems_usb *dev;
|
||||
int i, err = -ENOMEM;
|
||||
|
||||
netdev = alloc_candev(sizeof(struct ems_usb));
|
||||
netdev = alloc_candev(sizeof(struct ems_usb), MAX_TX_URBS);
|
||||
if (!netdev) {
|
||||
dev_err(netdev->dev.parent, "Couldn't alloc candev\n");
|
||||
return -ENOMEM;
|
||||
|
@ -29,8 +29,6 @@ enum can_mode {
|
||||
/*
|
||||
* CAN common private data
|
||||
*/
|
||||
#define CAN_ECHO_SKB_MAX 4
|
||||
|
||||
struct can_priv {
|
||||
struct can_device_stats can_stats;
|
||||
|
||||
@ -44,15 +42,16 @@ 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;
|
||||
};
|
||||
|
||||
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);
|
||||
@ -64,8 +63,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 */
|
||||
|
Loading…
Reference in New Issue
Block a user