if (unlikely(new_state == priv->state)) {
netdev_warn(dev, "%s: oops, state did not change", __func__); return;
}
netdev_dbg(dev, "Controller changed from %s State (%d) into %s State (%d).\n",
can_get_state_str(priv->state), priv->state,
can_get_state_str(new_state), new_state);
int can_restart_now(struct net_device *dev)
{ struct can_priv *priv = netdev_priv(dev);
/* A manual restart is only permitted if automatic restart is * disabled and the device is in the bus-off state
*/ if (priv->restart_ms) return -EINVAL; if (priv->state != CAN_STATE_BUS_OFF) return -EBUSY;
cancel_delayed_work_sync(&priv->restart_work);
return can_restart(dev);
}
/* CAN bus-off * * This functions should be called when the device goes bus-off to * tell the netif layer that no more packets can be sent or received. * If enabled, a timer is started to trigger bus-off recovery.
*/ void can_bus_off(struct net_device *dev)
{ struct can_priv *priv = netdev_priv(dev);
if (priv->restart_ms)
netdev_info(dev, "bus-off, scheduling restart in %d ms\n",
priv->restart_ms); else
netdev_info(dev, "bus-off\n");
netif_carrier_off(dev);
if (priv->restart_ms)
schedule_delayed_work(&priv->restart_work,
msecs_to_jiffies(priv->restart_ms));
}
EXPORT_SYMBOL_GPL(can_bus_off);
/* Allocate and setup space for the CAN network device */ struct net_device *alloc_candev_mqs(int sizeof_priv, unsignedint echo_skb_max, unsignedint txqs, unsignedint rxqs)
{ struct can_ml_priv *can_ml; struct net_device *dev; struct can_priv *priv; int size;
/* We put the driver's priv, the CAN mid layer priv and the * echo skb into the netdevice's priv. The memory layout for * the netdev_priv is like this: * * +-------------------------+ * | driver's priv | * +-------------------------+ * | struct can_ml_priv | * +-------------------------+ * | array of struct sk_buff | * +-------------------------+
*/
/* Free space of the CAN network device */ void free_candev(struct net_device *dev)
{
free_netdev(dev);
}
EXPORT_SYMBOL_GPL(free_candev);
/* changing MTU and control mode for CAN/CANFD devices */ int can_change_mtu(struct net_device *dev, int new_mtu)
{ struct can_priv *priv = netdev_priv(dev);
u32 ctrlmode_static = can_get_static_ctrlmode(priv);
/* Do not allow changing the MTU while running */ if (dev->flags & IFF_UP) return -EBUSY;
/* allow change of MTU according to the CANFD ability of the device */ switch (new_mtu) { case CAN_MTU: /* 'CANFD-only' controllers can not switch to CAN_MTU */ if (ctrlmode_static & CAN_CTRLMODE_FD) return -EINVAL;
priv->ctrlmode &= ~CAN_CTRLMODE_FD; break;
case CANFD_MTU: /* check for potential CANFD ability */ if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD) &&
!(ctrlmode_static & CAN_CTRLMODE_FD)) return -EINVAL;
/* Common open function when the device gets opened. * * This function should be called in the open function of the device * driver.
*/ int open_candev(struct net_device *dev)
{ struct can_priv *priv = netdev_priv(dev);
if (!priv->bittiming.bitrate) {
netdev_err(dev, "bit-timing not yet defined\n"); return -EINVAL;
}
/* For CAN FD the data bitrate has to be >= the arbitration bitrate */ if ((priv->ctrlmode & CAN_CTRLMODE_FD) &&
(!priv->fd.data_bittiming.bitrate ||
priv->fd.data_bittiming.bitrate < priv->bittiming.bitrate)) {
netdev_err(dev, "incorrect/missing data bit-timing\n"); return -EINVAL;
}
/* Switch carrier on if device was stopped while in bus-off state */ if (!netif_carrier_ok(dev))
netif_carrier_on(dev);
return 0;
}
EXPORT_SYMBOL_GPL(open_candev);
#ifdef CONFIG_OF /* Common function that can be used to understand the limitation of * a transceiver when it provides no means to determine these limitations * at runtime.
*/ void of_can_transceiver(struct net_device *dev)
{ struct device_node *dn; struct can_priv *priv = netdev_priv(dev); struct device_node *np = dev->dev.parent->of_node; int ret;
dn = of_get_child_by_name(np, "can-transceiver"); if (!dn) return;
ret = of_property_read_u32(dn, "max-bitrate", &priv->bitrate_max);
of_node_put(dn); if ((ret && ret != -EINVAL) || (!ret && !priv->bitrate_max))
netdev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit.\n");
}
EXPORT_SYMBOL_GPL(of_can_transceiver); #endif
/* 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);
/* Disabling termination by default is the safe choice: Else if many * bus participants enable it, no communication is possible at all.
*/
gpio = devm_gpiod_get_optional(dev, "termination", GPIOD_OUT_LOW); if (IS_ERR(gpio)) return dev_err_probe(dev, PTR_ERR(gpio), "Cannot get termination-gpios\n");
if (!gpio) return 0;
ret = device_property_read_u32(dev, "termination-ohms", &term); if (ret) {
netdev_err(ndev, "Cannot get termination-ohms: %pe\n",
ERR_PTR(ret)); return ret;
}
if (term > U16_MAX) {
netdev_err(ndev, "Invalid termination-ohms value (%u > %u)\n",
term, U16_MAX); return -EINVAL;
}
staticbool
can_bittiming_const_valid(conststruct can_bittiming_const *btc)
{ if (!btc) returntrue;
if (!btc->sjw_max) returnfalse;
returntrue;
}
/* Register the CAN network device */ int register_candev(struct net_device *dev)
{ struct can_priv *priv = netdev_priv(dev); int err;
/* Ensure termination_const, termination_const_cnt and * do_set_termination consistency. All must be either set or * unset.
*/ if ((!priv->termination_const != !priv->termination_const_cnt) ||
(!priv->termination_const != !priv->do_set_termination)) return -EINVAL;
if (!priv->bitrate_const != !priv->bitrate_const_cnt) return -EINVAL;
if (!priv->fd.data_bitrate_const != !priv->fd.data_bitrate_const_cnt) return -EINVAL;
/* We only support either fixed bit rates or bit timing const. */ if ((priv->bitrate_const || priv->fd.data_bitrate_const) &&
(priv->bittiming_const || priv->fd.data_bittiming_const)) return -EINVAL;
if (!can_bittiming_const_valid(priv->bittiming_const) ||
!can_bittiming_const_valid(priv->fd.data_bittiming_const)) return -EINVAL;
if (!priv->termination_const) {
err = can_get_termination(dev); if (err) return err;
}
/* Unregister the CAN network device */ void unregister_candev(struct net_device *dev)
{
unregister_netdev(dev);
}
EXPORT_SYMBOL_GPL(unregister_candev);
/* Test if a network device is a candev based device * and return the can_priv* if so.
*/ struct can_priv *safe_candev_priv(struct net_device *dev)
{ if (dev->type != ARPHRD_CAN || dev->rtnl_link_ops != &can_link_ops) return NULL;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.