// SPDX-License-Identifier: GPL-2.0-only/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix * Copyright (C) 2006 Andrey Volkov, Varma Electronics * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com> */ #include <linux/can.h>#include <linux/can/can-ml.h>#include <linux/can/dev.h>#include <linux/can/skb.h>#include <linux/gpio/consumer.h>#include <linux/if_arp.h>#include <linux/kernel.h>#include <linux/netdevice.h>#include <linux/of.h>#include <linux/slab.h>#include <linux/workqueue.h> static void can_update_state_error_stats(struct net_device *dev, enum can_state new_state){ struct can_priv *priv = netdev_priv(dev); if (new_state <= priv->state) return; switch (new_state) { case CAN_STATE_ERROR_WARNING: priv->can_stats.error_warning++; break; case CAN_STATE_ERROR_PASSIVE: priv->can_stats.error_passive++; break; case CAN_STATE_BUS_OFF: priv->can_stats.bus_off++; break; default: break; }} static int can_tx_state_to_frame(struct net_device *dev, enum can_state state){ switch (state) { case CAN_STATE_ERROR_ACTIVE: return CAN_ERR_CRTL_ACTIVE; case CAN_STATE_ERROR_WARNING: return CAN_ERR_CRTL_TX_WARNING; case CAN_STATE_ERROR_PASSIVE: return CAN_ERR_CRTL_TX_PASSIVE; default: return 0; }} static int can_rx_state_to_frame(struct net_device *dev, enum can_state state){ switch (state) { case CAN_STATE_ERROR_ACTIVE: return CAN_ERR_CRTL_ACTIVE; case CAN_STATE_ERROR_WARNING: return CAN_ERR_CRTL_RX_WARNING; case CAN_STATE_ERROR_PASSIVE: return CAN_ERR_CRTL_RX_PASSIVE; default: return 0; }} const char *can_get_state_str(const enum can_state state){ switch (state) { case CAN_STATE_ERROR_ACTIVE: return "Error Active"; case CAN_STATE_ERROR_WARNING: return "Error Warning"; case CAN_STATE_ERROR_PASSIVE: return "Error Passive"; case CAN_STATE_BUS_OFF: return "Bus Off"; case CAN_STATE_STOPPED: return "Stopped"; case CAN_STATE_SLEEPING: return "Sleeping"; default: return "<unknown>"; }}EXPORT_SYMBOL_GPL(can_get_state_str); const char *can_get_ctrlmode_str(u32 ctrlmode){ switch (ctrlmode & ~(ctrlmode - 1)) { case 0: return "(none)"; case CAN_CTRLMODE_LOOPBACK: return "LOOPBACK"; case CAN_CTRLMODE_LISTENONLY: return "LISTEN-ONLY"; case CAN_CTRLMODE_3_SAMPLES: return "TRIPLE-SAMPLING"; case CAN_CTRLMODE_ONE_SHOT: return "ONE-SHOT"; case CAN_CTRLMODE_BERR_REPORTING: return "BERR-REPORTING"; case CAN_CTRLMODE_FD: return "FD"; case CAN_CTRLMODE_PRESUME_ACK: return "PRESUME-ACK"; case CAN_CTRLMODE_FD_NON_ISO: return "FD-NON-ISO"; case CAN_CTRLMODE_CC_LEN8_DLC: return "CC-LEN8-DLC"; case CAN_CTRLMODE_TDC_AUTO: return "TDC-AUTO"; case CAN_CTRLMODE_TDC_MANUAL: return "TDC-MANUAL"; case CAN_CTRLMODE_RESTRICTED: return "RESTRICTED"; case CAN_CTRLMODE_XL: return "XL"; case CAN_CTRLMODE_XL_TDC_AUTO: return "XL-TDC-AUTO"; case CAN_CTRLMODE_XL_TDC_MANUAL: return "XL-TDC-MANUAL"; case CAN_CTRLMODE_XL_TMS: return "TMS"; default: return "<unknown>"; }}EXPORT_SYMBOL_GPL(can_get_ctrlmode_str); static enum can_state can_state_err_to_state(u16 err){ if (err < CAN_ERROR_WARNING_THRESHOLD) return CAN_STATE_ERROR_ACTIVE; if (err < CAN_ERROR_PASSIVE_THRESHOLD) return CAN_STATE_ERROR_WARNING; if (err < CAN_BUS_OFF_THRESHOLD) return CAN_STATE_ERROR_PASSIVE; return CAN_STATE_BUS_OFF;} void can_state_get_by_berr_counter(const struct net_device *dev, const struct can_berr_counter *bec, enum can_state *tx_state, enum can_state *rx_state){ *tx_state = can_state_err_to_state(bec->txerr); *rx_state = can_state_err_to_state(bec->rxerr);}EXPORT_SYMBOL_GPL(can_state_get_by_berr_counter); void can_change_state(struct net_device *dev, struct can_frame *cf, enum can_state tx_state, enum can_state rx_state){ struct can_priv *priv = netdev_priv(dev); enum can_state new_state = max(tx_state, rx_state); 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); can_update_state_error_stats(dev, new_state); priv->state = new_state; if (!cf) return; if (unlikely(new_state == CAN_STATE_BUS_OFF)) { cf->can_id |= CAN_ERR_BUSOFF; return; } cf->can_id |= CAN_ERR_CRTL; cf->data[1] |= tx_state >= rx_state ? can_tx_state_to_frame(dev, tx_state) : 0; cf->data[1] |= tx_state <= rx_state ? can_rx_state_to_frame(dev, rx_state) : 0;}EXPORT_SYMBOL_GPL(can_change_state); /* CAN device restart for bus-off recovery */static int can_restart(struct net_device *dev){ struct can_priv *priv = netdev_priv(dev); struct sk_buff *skb; struct can_frame *cf; int err; if (!priv->do_set_mode) return -EOPNOTSUPP; if (netif_carrier_ok(dev)) netdev_err(dev, "Attempt to restart for bus-off recovery, but carrier is OK?\n"); /* 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) { cf->can_id |= CAN_ERR_RESTARTED; netif_rx(skb); } /* Now restart the device */ netif_carrier_on(dev); err = priv->do_set_mode(dev, CAN_MODE_START); if (err) { netdev_err(dev, "Restart failed, error %pe\n", ERR_PTR(err)); netif_carrier_off(dev); return err; } else { netdev_dbg(dev, "Restarted\n"); priv->can_stats.restarts++; } return 0;} static void can_restart_work(struct work_struct *work){ struct delayed_work *dwork = to_delayed_work(work); struct can_priv *priv = container_of(dwork, struct can_priv, restart_work); can_restart(priv->dev);} 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); void can_setup(struct net_device *dev){ dev->type = ARPHRD_CAN; dev->mtu = CAN_MTU; dev->min_mtu = CAN_MTU; dev->max_mtu = CAN_MTU; dev->hard_header_len = 0; dev->addr_len = 0; dev->tx_queue_len = 10; /* New-style flags. */ dev->flags = IFF_NOARP; dev->features = NETIF_F_HW_CSUM;} /* Allocate and setup space for the CAN network device */struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max, unsigned int txqs, unsigned int 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 | * +-------------------------+ */ size = ALIGN(sizeof_priv, NETDEV_ALIGN) + sizeof(struct can_ml_priv); if (echo_skb_max) size = ALIGN(size, sizeof(struct sk_buff *)) + echo_skb_max * sizeof(struct sk_buff *); dev = alloc_netdev_mqs(size, "can%d", NET_NAME_UNKNOWN, can_setup, txqs, rxqs); if (!dev) return NULL; priv = netdev_priv(dev); priv->dev = dev; can_ml = (void *)priv + ALIGN(sizeof_priv, NETDEV_ALIGN); can_set_ml_priv(dev, can_ml); can_set_cap(dev, CAN_CAP_CC); if (echo_skb_max) { priv->echo_skb_max = echo_skb_max; priv->echo_skb = (void *)priv + (size - echo_skb_max * sizeof(struct sk_buff *)); } priv->state = CAN_STATE_STOPPED; INIT_DELAYED_WORK(&priv->restart_work, can_restart_work); return dev;}EXPORT_SYMBOL_GPL(alloc_candev_mqs); /* Free space of the CAN network device */void free_candev(struct net_device *dev){ free_netdev(dev);}EXPORT_SYMBOL_GPL(free_candev); void can_set_default_mtu(struct net_device *dev){ struct can_priv *priv = netdev_priv(dev); if (priv->ctrlmode & CAN_CTRLMODE_XL) { if (can_is_canxl_dev_mtu(dev->mtu)) return; dev->mtu = CANXL_MTU; dev->min_mtu = CANXL_MIN_MTU; dev->max_mtu = CANXL_MAX_MTU; } else if (priv->ctrlmode & CAN_CTRLMODE_FD) { dev->mtu = CANFD_MTU; dev->min_mtu = CANFD_MTU; dev->max_mtu = CANFD_MTU; } else { dev->mtu = CAN_MTU; dev->min_mtu = CAN_MTU; dev->max_mtu = CAN_MTU; }} void can_set_cap_info(struct net_device *dev){ struct can_priv *priv = netdev_priv(dev); u32 can_cap; if (can_dev_in_xl_only_mode(priv)) { /* XL only mode => no CC/FD capability */ can_cap = CAN_CAP_XL; } else { /* mixed mode => CC + FD/XL capability */ can_cap = CAN_CAP_CC; if (priv->ctrlmode & CAN_CTRLMODE_FD) can_cap |= CAN_CAP_FD; if (priv->ctrlmode & CAN_CTRLMODE_XL) can_cap |= CAN_CAP_XL; } if (priv->ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_RESTRICTED)) can_cap |= CAN_CAP_RO; can_set_cap(dev, can_cap);} /* helper to define static CAN controller features at device creation time */int can_set_static_ctrlmode(struct net_device *dev, u32 static_mode){ struct can_priv *priv = netdev_priv(dev); /* alloc_candev() succeeded => netdev_priv() is valid at this point */ if (priv->ctrlmode_supported & static_mode) { netdev_warn(dev, "Controller features can not be supported and static at the same time\n"); return -EINVAL; } priv->ctrlmode = static_mode; /* override MTU which was set by default in can_setup()? */ can_set_default_mtu(dev); can_set_cap_info(dev); return 0;}EXPORT_SYMBOL_GPL(can_set_static_ctrlmode); /* generic implementation of netdev_ops::ndo_hwtstamp_get for CAN devices * supporting hardware timestamps */int can_hwtstamp_get(struct net_device *netdev, struct kernel_hwtstamp_config *cfg){ cfg->tx_type = HWTSTAMP_TX_ON; cfg->rx_filter = HWTSTAMP_FILTER_ALL; return 0;}EXPORT_SYMBOL(can_hwtstamp_get); /* generic implementation of netdev_ops::ndo_hwtstamp_set for CAN devices * supporting hardware timestamps */int can_hwtstamp_set(struct net_device *netdev, struct kernel_hwtstamp_config *cfg, struct netlink_ext_ack *extack){ if (cfg->tx_type == HWTSTAMP_TX_ON && cfg->rx_filter == HWTSTAMP_FILTER_ALL) return 0; NL_SET_ERR_MSG_MOD(extack, "Only TX on and RX all packets filter supported"); return -ERANGE;}EXPORT_SYMBOL(can_hwtstamp_set); /* generic implementation of ethtool_ops::get_ts_info for CAN devices * supporting hardware timestamps */int can_ethtool_op_get_ts_info_hwts(struct net_device *dev, struct kernel_ethtool_ts_info *info){ info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; info->tx_types = BIT(HWTSTAMP_TX_ON); info->rx_filters = BIT(HWTSTAMP_FILTER_ALL); return 0;}EXPORT_SYMBOL(can_ethtool_op_get_ts_info_hwts); /* 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);Lines 1–500 of 689. Load more
// SPDX-License-Identifier: GPL-2.0-only /* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix * Copyright (C) 2006 Andrey Volkov, Varma Electronics * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com> */ #include <linux/can.h> #include <linux/can/can-ml.h> #include <linux/can/dev.h> #include <linux/can/skb.h> #include <linux/gpio/consumer.h> #include <linux/if_arp.h> #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/of.h> #include <linux/slab.h> #include <linux/workqueue.h> static void can_update_state_error_stats(struct net_device *dev, enum can_state new_state) { struct can_priv *priv = netdev_priv(dev); if (new_state <= priv->state) return; switch (new_state) { case CAN_STATE_ERROR_WARNING: priv->can_stats.error_warning++; break; case CAN_STATE_ERROR_PASSIVE: priv->can_stats.error_passive++; break; case CAN_STATE_BUS_OFF: priv->can_stats.bus_off++; break; default: break; } } static int can_tx_state_to_frame(struct net_device *dev, enum can_state state) { switch (state) { case CAN_STATE_ERROR_ACTIVE: return CAN_ERR_CRTL_ACTIVE; case CAN_STATE_ERROR_WARNING: return CAN_ERR_CRTL_TX_WARNING; case CAN_STATE_ERROR_PASSIVE: return CAN_ERR_CRTL_TX_PASSIVE; default: return 0; } } static int can_rx_state_to_frame(struct net_device *dev, enum can_state state) { switch (state) { case CAN_STATE_ERROR_ACTIVE: return CAN_ERR_CRTL_ACTIVE; case CAN_STATE_ERROR_WARNING: return CAN_ERR_CRTL_RX_WARNING; case CAN_STATE_ERROR_PASSIVE: return CAN_ERR_CRTL_RX_PASSIVE; default: return 0; } } const char *can_get_state_str(const enum can_state state) { switch (state) { case CAN_STATE_ERROR_ACTIVE: return "Error Active"; case CAN_STATE_ERROR_WARNING: return "Error Warning"; case CAN_STATE_ERROR_PASSIVE: return "Error Passive"; case CAN_STATE_BUS_OFF: return "Bus Off"; case CAN_STATE_STOPPED: return "Stopped"; case CAN_STATE_SLEEPING: return "Sleeping"; default: return "<unknown>"; } } EXPORT_SYMBOL_GPL(can_get_state_str); const char *can_get_ctrlmode_str(u32 ctrlmode) { switch (ctrlmode & ~(ctrlmode - 1)) { case 0: return "(none)"; case CAN_CTRLMODE_LOOPBACK: return "LOOPBACK"; case CAN_CTRLMODE_LISTENONLY: return "LISTEN-ONLY"; case CAN_CTRLMODE_3_SAMPLES: return "TRIPLE-SAMPLING"; case CAN_CTRLMODE_ONE_SHOT: return "ONE-SHOT"; case CAN_CTRLMODE_BERR_REPORTING: return "BERR-REPORTING"; case CAN_CTRLMODE_FD: return "FD"; case CAN_CTRLMODE_PRESUME_ACK: return "PRESUME-ACK"; case CAN_CTRLMODE_FD_NON_ISO: return "FD-NON-ISO"; case CAN_CTRLMODE_CC_LEN8_DLC: return "CC-LEN8-DLC"; case CAN_CTRLMODE_TDC_AUTO: return "TDC-AUTO"; case CAN_CTRLMODE_TDC_MANUAL: return "TDC-MANUAL"; case CAN_CTRLMODE_RESTRICTED: return "RESTRICTED"; case CAN_CTRLMODE_XL: return "XL"; case CAN_CTRLMODE_XL_TDC_AUTO: return "XL-TDC-AUTO"; case CAN_CTRLMODE_XL_TDC_MANUAL: return "XL-TDC-MANUAL"; case CAN_CTRLMODE_XL_TMS: return "TMS"; default: return "<unknown>"; } } EXPORT_SYMBOL_GPL(can_get_ctrlmode_str); static enum can_state can_state_err_to_state(u16 err) { if (err < CAN_ERROR_WARNING_THRESHOLD) return CAN_STATE_ERROR_ACTIVE; if (err < CAN_ERROR_PASSIVE_THRESHOLD) return CAN_STATE_ERROR_WARNING; if (err < CAN_BUS_OFF_THRESHOLD) return CAN_STATE_ERROR_PASSIVE; return CAN_STATE_BUS_OFF; } void can_state_get_by_berr_counter(const struct net_device *dev, const struct can_berr_counter *bec, enum can_state *tx_state, enum can_state *rx_state) { *tx_state = can_state_err_to_state(bec->txerr); *rx_state = can_state_err_to_state(bec->rxerr); } EXPORT_SYMBOL_GPL(can_state_get_by_berr_counter); void can_change_state(struct net_device *dev, struct can_frame *cf, enum can_state tx_state, enum can_state rx_state) { struct can_priv *priv = netdev_priv(dev); enum can_state new_state = max(tx_state, rx_state); 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); can_update_state_error_stats(dev, new_state); priv->state = new_state; if (!cf) return; if (unlikely(new_state == CAN_STATE_BUS_OFF)) { cf->can_id |= CAN_ERR_BUSOFF; return; } cf->can_id |= CAN_ERR_CRTL; cf->data[1] |= tx_state >= rx_state ? can_tx_state_to_frame(dev, tx_state) : 0; cf->data[1] |= tx_state <= rx_state ? can_rx_state_to_frame(dev, rx_state) : 0; } EXPORT_SYMBOL_GPL(can_change_state); /* CAN device restart for bus-off recovery */ static int can_restart(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); struct sk_buff *skb; struct can_frame *cf; int err; if (!priv->do_set_mode) return -EOPNOTSUPP; if (netif_carrier_ok(dev)) netdev_err(dev, "Attempt to restart for bus-off recovery, but carrier is OK?\n"); /* 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) { cf->can_id |= CAN_ERR_RESTARTED; netif_rx(skb); } /* Now restart the device */ netif_carrier_on(dev); err = priv->do_set_mode(dev, CAN_MODE_START); if (err) { netdev_err(dev, "Restart failed, error %pe\n", ERR_PTR(err)); netif_carrier_off(dev); return err; } else { netdev_dbg(dev, "Restarted\n"); priv->can_stats.restarts++; } return 0; } static void can_restart_work(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); struct can_priv *priv = container_of(dwork, struct can_priv, restart_work); can_restart(priv->dev); } 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); void can_setup(struct net_device *dev) { dev->type = ARPHRD_CAN; dev->mtu = CAN_MTU; dev->min_mtu = CAN_MTU; dev->max_mtu = CAN_MTU; dev->hard_header_len = 0; dev->addr_len = 0; dev->tx_queue_len = 10; /* New-style flags. */ dev->flags = IFF_NOARP; dev->features = NETIF_F_HW_CSUM; } /* Allocate and setup space for the CAN network device */ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max, unsigned int txqs, unsigned int 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 | * +-------------------------+ */ size = ALIGN(sizeof_priv, NETDEV_ALIGN) + sizeof(struct can_ml_priv); if (echo_skb_max) size = ALIGN(size, sizeof(struct sk_buff *)) + echo_skb_max * sizeof(struct sk_buff *); dev = alloc_netdev_mqs(size, "can%d", NET_NAME_UNKNOWN, can_setup, txqs, rxqs); if (!dev) return NULL; priv = netdev_priv(dev); priv->dev = dev; can_ml = (void *)priv + ALIGN(sizeof_priv, NETDEV_ALIGN); can_set_ml_priv(dev, can_ml); can_set_cap(dev, CAN_CAP_CC); if (echo_skb_max) { priv->echo_skb_max = echo_skb_max; priv->echo_skb = (void *)priv + (size - echo_skb_max * sizeof(struct sk_buff *)); } priv->state = CAN_STATE_STOPPED; INIT_DELAYED_WORK(&priv->restart_work, can_restart_work); return dev; } EXPORT_SYMBOL_GPL(alloc_candev_mqs); /* Free space of the CAN network device */ void free_candev(struct net_device *dev) { free_netdev(dev); } EXPORT_SYMBOL_GPL(free_candev); void can_set_default_mtu(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); if (priv->ctrlmode & CAN_CTRLMODE_XL) { if (can_is_canxl_dev_mtu(dev->mtu)) return; dev->mtu = CANXL_MTU; dev->min_mtu = CANXL_MIN_MTU; dev->max_mtu = CANXL_MAX_MTU; } else if (priv->ctrlmode & CAN_CTRLMODE_FD) { dev->mtu = CANFD_MTU; dev->min_mtu = CANFD_MTU; dev->max_mtu = CANFD_MTU; } else { dev->mtu = CAN_MTU; dev->min_mtu = CAN_MTU; dev->max_mtu = CAN_MTU; } } void can_set_cap_info(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); u32 can_cap; if (can_dev_in_xl_only_mode(priv)) { /* XL only mode => no CC/FD capability */ can_cap = CAN_CAP_XL; } else { /* mixed mode => CC + FD/XL capability */ can_cap = CAN_CAP_CC; if (priv->ctrlmode & CAN_CTRLMODE_FD) can_cap |= CAN_CAP_FD; if (priv->ctrlmode & CAN_CTRLMODE_XL) can_cap |= CAN_CAP_XL; } if (priv->ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_RESTRICTED)) can_cap |= CAN_CAP_RO; can_set_cap(dev, can_cap); } /* helper to define static CAN controller features at device creation time */ int can_set_static_ctrlmode(struct net_device *dev, u32 static_mode) { struct can_priv *priv = netdev_priv(dev); /* alloc_candev() succeeded => netdev_priv() is valid at this point */ if (priv->ctrlmode_supported & static_mode) { netdev_warn(dev, "Controller features can not be supported and static at the same time\n"); return -EINVAL; } priv->ctrlmode = static_mode; /* override MTU which was set by default in can_setup()? */ can_set_default_mtu(dev); can_set_cap_info(dev); return 0; } EXPORT_SYMBOL_GPL(can_set_static_ctrlmode); /* generic implementation of netdev_ops::ndo_hwtstamp_get for CAN devices * supporting hardware timestamps */ int can_hwtstamp_get(struct net_device *netdev, struct kernel_hwtstamp_config *cfg) { cfg->tx_type = HWTSTAMP_TX_ON; cfg->rx_filter = HWTSTAMP_FILTER_ALL; return 0; } EXPORT_SYMBOL(can_hwtstamp_get); /* generic implementation of netdev_ops::ndo_hwtstamp_set for CAN devices * supporting hardware timestamps */ int can_hwtstamp_set(struct net_device *netdev, struct kernel_hwtstamp_config *cfg, struct netlink_ext_ack *extack) { if (cfg->tx_type == HWTSTAMP_TX_ON && cfg->rx_filter == HWTSTAMP_FILTER_ALL) return 0; NL_SET_ERR_MSG_MOD(extack, "Only TX on and RX all packets filter supported"); return -ERANGE; } EXPORT_SYMBOL(can_hwtstamp_set); /* generic implementation of ethtool_ops::get_ts_info for CAN devices * supporting hardware timestamps */ int can_ethtool_op_get_ts_info_hwts(struct net_device *dev, struct kernel_ethtool_ts_info *info) { info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; info->tx_types = BIT(HWTSTAMP_TX_ON); info->rx_filters = BIT(HWTSTAMP_FILTER_ALL); return 0; } EXPORT_SYMBOL(can_ethtool_op_get_ts_info_hwts); /* 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);