/* * Common close function for cleanup before the device gets closed. * * This function should be called in the close function of the device * driver. */ void close_candev(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); del_timer_sync(&priv->restart_timer); can_flush_echo_skb(dev); }
/* * CAN device restart for bus-off recovery */ void can_restart(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct sk_buff *skb; struct can_frame *cf; int err; BUG_ON(netif_carrier_ok(dev)); /* * No synchronization needed because the device is bus-off and * no messages can come in or go out. */ can_flush_echo_skb(dev); /* send restart message upstream */ skb = dev_alloc_skb(sizeof(struct can_frame)); if (skb == NULL) { err = -ENOMEM; goto restart; } skb->dev = dev; skb->protocol = htons(ETH_P_CAN); cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); memset(cf, 0, sizeof(struct can_frame)); cf->can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED; cf->can_dlc = CAN_ERR_DLC; netif_rx(skb); dev->last_rx = jiffies; stats->rx_packets++; stats->rx_bytes += cf->can_dlc; restart: dev_dbg(dev->dev.parent, "restarted\n"); priv->can_stats.restarts++; /* Now restart the device */ err = priv->do_set_mode(dev, CAN_MODE_START); netif_carrier_on(dev); if (err) dev_err(dev->dev.parent, "Error %d during restart", err); }
/* * CAN device restart for bus-off recovery */ void can_restart(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct sk_buff *skb; struct can_frame *cf; int err; BUG_ON(netif_carrier_ok(dev)); /* * No synchronization needed because the device is bus-off and * no messages can come in or go out. */ can_flush_echo_skb(dev); /* send restart message upstream */ skb = alloc_can_err_skb(dev, &cf); if (skb == NULL) { err = -ENOMEM; goto restart; } cf->can_id |= CAN_ERR_RESTARTED; netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; restart: dev_dbg(dev->dev.parent, "restarted\n"); priv->can_stats.restarts++; /* Now restart the device */ err = priv->do_set_mode(dev, CAN_MODE_START); netif_carrier_on(dev); if (err) dev_err(dev->dev.parent, "Error %d during restart", err); }
void can_restart(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct sk_buff *skb; struct can_frame *cf; int err; BUG_ON(netif_carrier_ok(dev)); can_flush_echo_skb(dev); skb = alloc_can_err_skb(dev, &cf); if (skb == NULL) { err = -ENOMEM; goto restart; } cf->can_id |= CAN_ERR_RESTARTED; netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; restart: netdev_dbg(dev, "restarted\n"); priv->can_stats.restarts++; err = priv->do_set_mode(dev, CAN_MODE_START); netif_carrier_on(dev); if (err) netdev_err(dev, "Error %d during restart", err); }