Hello,

> If you return with NETDEV_TX_BUSY, you should *not* free the skb and
> therefore *not* increment "stats->tx_dropped". In contrast, if you
> return with NETDEV_TX_OK, the *driver* must take care of the skb. Do you
> realized the difference and problem now?
> 
> Wolfgang.

So I added a dev_kfree_skb(skb) to the first "dropping" condition where
NETDEV_TX_OK is returned.

In the busy case just stats->tx_fifo_errors is incremented.
(Is it appropriate there?, no other driver seems to use that)


Now it is:

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
static int esd331_start_xmit(struct sk_buff *skb, struct net_device *dev)
#else
static netdev_tx_t esd331_start_xmit(struct sk_buff *skb,
                                        struct net_device *dev)
#endif
{
        struct esd331_priv *priv = netdev_priv(dev);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
        struct net_device_stats *stats = can_get_stats(dev);
#else
        struct net_device_stats *stats = &dev->stats;
#endif
        struct can_frame *cf = (struct can_frame *)skb->data;
        struct esd331_can_msg msg;
        int i;

        if ((cf->can_id & CAN_EFF_FLAG) && (priv->board->eff_supp == 0)) {
                stats->tx_errors++;
                stats->tx_dropped++;
                dev_kfree_skb(skb);
                return NETDEV_TX_OK;
        }

        memset(&msg, 0, sizeof(msg));
        if (cf->can_id & CAN_EFF_FLAG) {
                msg.cmmd = ESD331_I20_EX_BCAN;
                msg.id = cpu_to_be16((cf->can_id & CAN_EFF_MASK) >> 16);
                msg.x2 = cpu_to_be16(cf->can_id & CAN_EFF_MASK);
        } else {
                msg.cmmd = ESD331_I20_BCAN;
                msg.id = cpu_to_be16(cf->can_id & CAN_EFF_MASK);
        }
        msg.x1 = cpu_to_be16(cf->can_dlc);
        msg.net = priv->boards_net;
        msg.len = cpu_to_be16((cf->can_id & CAN_RTR_FLAG) ?
                                cf->can_dlc | ESD331_RTR_FLAG : cf->can_dlc);

        for (i = 0; i < cf->can_dlc; i++)
                msg.data[i] = cf->data[i];

        can_put_echo_skb(skb, dev, 0);
        if (esd331_write(&msg, priv->board)) {
                stats->tx_fifo_errors++;
                return NETDEV_TX_BUSY;
        }

        netif_stop_queue(dev);
        dev->trans_start = jiffies;

        return NETDEV_TX_OK;
}

_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core

Reply via email to