diff options
Diffstat (limited to 'drivers/net/can/usb')
20 files changed, 612 insertions, 384 deletions
diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index f959215c9d53..1218f9642f33 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig @@ -14,11 +14,18 @@ config CAN_EMS_USB This driver is for the one channel CPC-USB/ARM7 CAN/USB interface from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). -config CAN_ESD_USB2 - tristate "ESD USB/2 CAN/USB interface" +config CAN_ESD_USB + tristate "esd electronics gmbh CAN/USB interfaces" help - This driver supports the CAN-USB/2 interface - from esd electronic system design gmbh (http://www.esd.eu). + This driver adds supports for several CAN/USB interfaces + from esd electronics gmbh (https://www.esd.eu). + + The drivers supports the following devices: + - esd CAN-USB/2 + - esd CAN-USB/Micro + + To compile this driver as a module, choose M here: the module + will be called esd_usb. config CAN_ETAS_ES58X tristate "ETAS ES58X CAN/USB interfaces" diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile index 748cf31a0d53..1ea16be5743b 100644 --- a/drivers/net/can/usb/Makefile +++ b/drivers/net/can/usb/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o -obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o +obj-$(CONFIG_CAN_ESD_USB) += esd_usb.o obj-$(CONFIG_CAN_ETAS_ES58X) += etas_es58x/ obj-$(CONFIG_CAN_GS_USB) += gs_usb.o obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb/ diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index bbec3311d893..d1e1a459c045 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -4,6 +4,7 @@ * * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche */ +#include <linux/ethtool.h> #include <linux/signal.h> #include <linux/slab.h> #include <linux/module.h> @@ -879,8 +880,12 @@ static const struct net_device_ops ems_usb_netdev_ops = { .ndo_change_mtu = can_change_mtu, }; +static const struct ethtool_ops ems_usb_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + static const struct can_bittiming_const ems_usb_bittiming_const = { - .name = "ems_usb", + .name = KBUILD_MODNAME, .tseg1_min = 1, .tseg1_max = 16, .tseg2_min = 1, @@ -990,6 +995,7 @@ static int ems_usb_probe(struct usb_interface *intf, dev->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; netdev->netdev_ops = &ems_usb_netdev_ops; + netdev->ethtool_ops = &ems_usb_ethtool_ops; netdev->flags |= IFF_ECHO; /* we support local echo */ @@ -1074,7 +1080,7 @@ static void ems_usb_disconnect(struct usb_interface *intf) /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver ems_usb_driver = { - .name = "ems_usb", + .name = KBUILD_MODNAME, .probe = ems_usb_probe, .disconnect = ems_usb_disconnect, .id_table = ems_usb_table, diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb.c index 286daaaea0b8..1bcfad11b1e4 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb.c @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * CAN driver for esd CAN-USB/2 and CAN-USB/Micro + * CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Micro * - * Copyright (C) 2010-2012 Matthias Fuchs <[email protected]>, esd gmbh + * Copyright (C) 2010-2012 esd electronic system design gmbh, Matthias Fuchs <[email protected]> + * Copyright (C) 2022 esd electronics gmbh, Frank Jungclaus <[email protected]> */ +#include <linux/ethtool.h> #include <linux/signal.h> #include <linux/slab.h> #include <linux/module.h> @@ -14,20 +16,24 @@ #include <linux/can/dev.h> #include <linux/can/error.h> -MODULE_AUTHOR("Matthias Fuchs <[email protected]>"); -MODULE_DESCRIPTION("CAN driver for esd CAN-USB/2 and CAN-USB/Micro interfaces"); +MODULE_AUTHOR("Matthias Fuchs <[email protected]>"); +MODULE_AUTHOR("Frank Jungclaus <[email protected]>"); +MODULE_DESCRIPTION("CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Micro interfaces"); MODULE_LICENSE("GPL v2"); -/* Define these values to match your devices */ +/* USB vendor and product ID */ #define USB_ESDGMBH_VENDOR_ID 0x0ab4 #define USB_CANUSB2_PRODUCT_ID 0x0010 #define USB_CANUSBM_PRODUCT_ID 0x0011 +/* CAN controller clock frequencies */ #define ESD_USB2_CAN_CLOCK 60000000 #define ESD_USBM_CAN_CLOCK 36000000 -#define ESD_USB2_MAX_NETS 2 -/* USB2 commands */ +/* Maximum number of CAN nets */ +#define ESD_USB_MAX_NETS 2 + +/* USB commands */ #define CMD_VERSION 1 /* also used for VERSION_REPLY */ #define CMD_CAN_RX 2 /* device to host only */ #define CMD_CAN_TX 3 /* also used for TX_DONE */ @@ -43,13 +49,15 @@ MODULE_LICENSE("GPL v2"); #define ESD_EVENT 0x40000000 #define ESD_IDMASK 0x1fffffff -/* esd CAN event ids used by this driver */ -#define ESD_EV_CAN_ERROR_EXT 2 +/* esd CAN event ids */ +#define ESD_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */ /* baudrate message flags */ -#define ESD_USB2_UBR 0x80000000 -#define ESD_USB2_LOM 0x40000000 -#define ESD_USB2_NO_BAUDRATE 0x7fffffff +#define ESD_USB_UBR 0x80000000 +#define ESD_USB_LOM 0x40000000 +#define ESD_USB_NO_BAUDRATE 0x7fffffff + +/* bit timing CAN-USB/2 */ #define ESD_USB2_TSEG1_MIN 1 #define ESD_USB2_TSEG1_MAX 16 #define ESD_USB2_TSEG1_SHIFT 16 @@ -68,7 +76,7 @@ MODULE_LICENSE("GPL v2"); #define ESD_ID_ENABLE 0x80 #define ESD_MAX_ID_SEGMENT 64 -/* SJA1000 ECC register (emulated by usb2 firmware) */ +/* SJA1000 ECC register (emulated by usb firmware) */ #define SJA1000_ECC_SEG 0x1F #define SJA1000_ECC_DIR 0x20 #define SJA1000_ECC_ERR 0x06 @@ -158,7 +166,7 @@ struct set_baudrate_msg { }; /* Main message type used between library and application */ -struct __attribute__ ((packed)) esd_usb2_msg { +struct __packed esd_usb_msg { union { struct header_msg hdr; struct version_msg version; @@ -171,23 +179,23 @@ struct __attribute__ ((packed)) esd_usb2_msg { } msg; }; -static struct usb_device_id esd_usb2_table[] = { +static struct usb_device_id esd_usb_table[] = { {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)}, {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSBM_PRODUCT_ID)}, {} }; -MODULE_DEVICE_TABLE(usb, esd_usb2_table); +MODULE_DEVICE_TABLE(usb, esd_usb_table); -struct esd_usb2_net_priv; +struct esd_usb_net_priv; struct esd_tx_urb_context { - struct esd_usb2_net_priv *priv; + struct esd_usb_net_priv *priv; u32 echo_index; }; -struct esd_usb2 { +struct esd_usb { struct usb_device *udev; - struct esd_usb2_net_priv *nets[ESD_USB2_MAX_NETS]; + struct esd_usb_net_priv *nets[ESD_USB_MAX_NETS]; struct usb_anchor rx_submitted; @@ -198,22 +206,22 @@ struct esd_usb2 { dma_addr_t rxbuf_dma[MAX_RX_URBS]; }; -struct esd_usb2_net_priv { +struct esd_usb_net_priv { struct can_priv can; /* must be the first member */ atomic_t active_tx_jobs; struct usb_anchor tx_submitted; struct esd_tx_urb_context tx_contexts[MAX_TX_URBS]; - struct esd_usb2 *usb2; + struct esd_usb *usb; struct net_device *netdev; int index; u8 old_state; struct can_berr_counter bec; }; -static void esd_usb2_rx_event(struct esd_usb2_net_priv *priv, - struct esd_usb2_msg *msg) +static void esd_usb_rx_event(struct esd_usb_net_priv *priv, + struct esd_usb_msg *msg) { struct net_device_stats *stats = &priv->netdev->stats; struct can_frame *cf; @@ -258,7 +266,8 @@ static void esd_usb2_rx_event(struct esd_usb2_net_priv *priv, priv->can.can_stats.bus_error++; stats->rx_errors++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR | + CAN_ERR_CNT; switch (ecc & SJA1000_ECC_MASK) { case SJA1000_ECC_BIT: @@ -296,8 +305,8 @@ static void esd_usb2_rx_event(struct esd_usb2_net_priv *priv, } } -static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv, - struct esd_usb2_msg *msg) +static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv, + struct esd_usb_msg *msg) { struct net_device_stats *stats = &priv->netdev->stats; struct can_frame *cf; @@ -311,7 +320,7 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv, id = le32_to_cpu(msg->msg.rx.id); if (id & ESD_EVENT) { - esd_usb2_rx_event(priv, msg); + esd_usb_rx_event(priv, msg); } else { skb = alloc_can_skb(priv->netdev, &cf); if (skb == NULL) { @@ -338,12 +347,10 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv, netif_rx(skb); } - - return; } -static void esd_usb2_tx_done_msg(struct esd_usb2_net_priv *priv, - struct esd_usb2_msg *msg) +static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv, + struct esd_usb_msg *msg) { struct net_device_stats *stats = &priv->netdev->stats; struct net_device *netdev = priv->netdev; @@ -370,9 +377,9 @@ static void esd_usb2_tx_done_msg(struct esd_usb2_net_priv *priv, netif_wake_queue(netdev); } -static void esd_usb2_read_bulk_callback(struct urb *urb) +static void esd_usb_read_bulk_callback(struct urb *urb) { - struct esd_usb2 *dev = urb->context; + struct esd_usb *dev = urb->context; int retval; int pos = 0; int i; @@ -394,9 +401,9 @@ static void esd_usb2_read_bulk_callback(struct urb *urb) } while (pos < urb->actual_length) { - struct esd_usb2_msg *msg; + struct esd_usb_msg *msg; - msg = (struct esd_usb2_msg *)(urb->transfer_buffer + pos); + msg = (struct esd_usb_msg *)(urb->transfer_buffer + pos); switch (msg->msg.hdr.cmd) { case CMD_CAN_RX: @@ -405,7 +412,7 @@ static void esd_usb2_read_bulk_callback(struct urb *urb) break; } - esd_usb2_rx_can_msg(dev->nets[msg->msg.rx.net], msg); + esd_usb_rx_can_msg(dev->nets[msg->msg.rx.net], msg); break; case CMD_CAN_TX: @@ -414,8 +421,8 @@ static void esd_usb2_read_bulk_callback(struct urb *urb) break; } - esd_usb2_tx_done_msg(dev->nets[msg->msg.txdone.net], - msg); + esd_usb_tx_done_msg(dev->nets[msg->msg.txdone.net], + msg); break; } @@ -430,7 +437,7 @@ static void esd_usb2_read_bulk_callback(struct urb *urb) resubmit_urb: usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), urb->transfer_buffer, RX_BUFFER_SIZE, - esd_usb2_read_bulk_callback, dev); + esd_usb_read_bulk_callback, dev); retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval == -ENODEV) { @@ -442,19 +449,15 @@ resubmit_urb: dev_err(dev->udev->dev.parent, "failed resubmitting read bulk urb: %d\n", retval); } - - return; } -/* - * callback for bulk IN urb - */ -static void esd_usb2_write_bulk_callback(struct urb *urb) +/* callback for bulk IN urb */ +static void esd_usb_write_bulk_callback(struct urb *urb) { struct esd_tx_urb_context *context = urb->context; - struct esd_usb2_net_priv *priv; + struct esd_usb_net_priv *priv; struct net_device *netdev; - size_t size = sizeof(struct esd_usb2_msg); + size_t size = sizeof(struct esd_usb_msg); WARN_ON(!context); @@ -478,7 +481,7 @@ static ssize_t firmware_show(struct device *d, struct device_attribute *attr, char *buf) { struct usb_interface *intf = to_usb_interface(d); - struct esd_usb2 *dev = usb_get_intfdata(intf); + struct esd_usb *dev = usb_get_intfdata(intf); return sprintf(buf, "%d.%d.%d\n", (dev->version >> 12) & 0xf, @@ -491,7 +494,7 @@ static ssize_t hardware_show(struct device *d, struct device_attribute *attr, char *buf) { struct usb_interface *intf = to_usb_interface(d); - struct esd_usb2 *dev = usb_get_intfdata(intf); + struct esd_usb *dev = usb_get_intfdata(intf); return sprintf(buf, "%d.%d.%d\n", (dev->version >> 28) & 0xf, @@ -504,13 +507,13 @@ static ssize_t nets_show(struct device *d, struct device_attribute *attr, char *buf) { struct usb_interface *intf = to_usb_interface(d); - struct esd_usb2 *dev = usb_get_intfdata(intf); + struct esd_usb *dev = usb_get_intfdata(intf); return sprintf(buf, "%d", dev->net_count); } static DEVICE_ATTR_RO(nets); -static int esd_usb2_send_msg(struct esd_usb2 *dev, struct esd_usb2_msg *msg) +static int esd_usb_send_msg(struct esd_usb *dev, struct esd_usb_msg *msg) { int actual_length; @@ -522,8 +525,8 @@ static int esd_usb2_send_msg(struct esd_usb2 *dev, struct esd_usb2_msg *msg) 1000); } -static int esd_usb2_wait_msg(struct esd_usb2 *dev, - struct esd_usb2_msg *msg) +static int esd_usb_wait_msg(struct esd_usb *dev, + struct esd_usb_msg *msg) { int actual_length; @@ -535,7 +538,7 @@ static int esd_usb2_wait_msg(struct esd_usb2 *dev, 1000); } -static int esd_usb2_setup_rx_urbs(struct esd_usb2 *dev) +static int esd_usb_setup_rx_urbs(struct esd_usb *dev) { int i, err = 0; @@ -568,7 +571,7 @@ static int esd_usb2_setup_rx_urbs(struct esd_usb2 *dev) usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), buf, RX_BUFFER_SIZE, - esd_usb2_read_bulk_callback, dev); + esd_usb_read_bulk_callback, dev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &dev->rx_submitted); @@ -606,14 +609,12 @@ freeurb: return 0; } -/* - * Start interface - */ -static int esd_usb2_start(struct esd_usb2_net_priv *priv) +/* Start interface */ +static int esd_usb_start(struct esd_usb_net_priv *priv) { - struct esd_usb2 *dev = priv->usb2; + struct esd_usb *dev = priv->usb; struct net_device *netdev = priv->netdev; - struct esd_usb2_msg *msg; + struct esd_usb_msg *msg; int err, i; msg = kmalloc(sizeof(*msg), GFP_KERNEL); @@ -622,8 +623,7 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv) goto out; } - /* - * Enable all IDs + /* Enable all IDs * The IDADD message takes up to 64 32 bit bitmasks (2048 bits). * Each bit represents one 11 bit CAN identifier. A set bit * enables reception of the corresponding CAN identifier. A cleared @@ -644,11 +644,11 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv) /* enable 29bit extended IDs */ msg->msg.filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001); - err = esd_usb2_send_msg(dev, msg); + err = esd_usb_send_msg(dev, msg); if (err) goto out; - err = esd_usb2_setup_rx_urbs(dev); + err = esd_usb_setup_rx_urbs(dev); if (err) goto out; @@ -664,9 +664,9 @@ out: return err; } -static void unlink_all_urbs(struct esd_usb2 *dev) +static void unlink_all_urbs(struct esd_usb *dev) { - struct esd_usb2_net_priv *priv; + struct esd_usb_net_priv *priv; int i, j; usb_kill_anchored_urbs(&dev->rx_submitted); @@ -687,9 +687,9 @@ static void unlink_all_urbs(struct esd_usb2 *dev) } } -static int esd_usb2_open(struct net_device *netdev) +static int esd_usb_open(struct net_device *netdev) { - struct esd_usb2_net_priv *priv = netdev_priv(netdev); + struct esd_usb_net_priv *priv = netdev_priv(netdev); int err; /* common open */ @@ -698,7 +698,7 @@ static int esd_usb2_open(struct net_device *netdev) return err; /* finally start device */ - err = esd_usb2_start(priv); + err = esd_usb_start(priv); if (err) { netdev_warn(netdev, "couldn't start device: %d\n", err); close_candev(netdev); @@ -710,20 +710,20 @@ static int esd_usb2_open(struct net_device *netdev) return 0; } -static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb, +static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, struct net_device *netdev) { - struct esd_usb2_net_priv *priv = netdev_priv(netdev); - struct esd_usb2 *dev = priv->usb2; + struct esd_usb_net_priv *priv = netdev_priv(netdev); + struct esd_usb *dev = priv->usb; struct esd_tx_urb_context *context = NULL; struct net_device_stats *stats = &netdev->stats; struct can_frame *cf = (struct can_frame *)skb->data; - struct esd_usb2_msg *msg; + struct esd_usb_msg *msg; struct urb *urb; u8 *buf; int i, err; int ret = NETDEV_TX_OK; - size_t size = sizeof(struct esd_usb2_msg); + size_t size = sizeof(struct esd_usb_msg); if (can_dropped_invalid_skb(netdev, skb)) return NETDEV_TX_OK; @@ -745,7 +745,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb, goto nobufmem; } - msg = (struct esd_usb2_msg *)buf; + msg = (struct esd_usb_msg *)buf; msg->msg.hdr.len = 3; /* minimal length */ msg->msg.hdr.cmd = CMD_CAN_TX; @@ -771,9 +771,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb, } } - /* - * This may never happen. - */ + /* This may never happen */ if (!context) { netdev_warn(netdev, "couldn't find free context\n"); ret = NETDEV_TX_BUSY; @@ -788,7 +786,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb, usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf, msg->msg.hdr.len << 2, - esd_usb2_write_bulk_callback, context); + esd_usb_write_bulk_callback, context); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -821,8 +819,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb, netif_trans_update(netdev); - /* - * Release our reference to this URB, the USB core will eventually free + /* Release our reference to this URB, the USB core will eventually free * it entirely. */ usb_free_urb(urb); @@ -839,24 +836,24 @@ nourbmem: return ret; } -static int esd_usb2_close(struct net_device *netdev) +static int esd_usb_close(struct net_device *netdev) { - struct esd_usb2_net_priv *priv = netdev_priv(netdev); - struct esd_usb2_msg *msg; + struct esd_usb_net_priv *priv = netdev_priv(netdev); + struct esd_usb_msg *msg; int i; msg = kmalloc(sizeof(*msg), GFP_KERNEL); if (!msg) return -ENOMEM; - /* Disable all IDs (see esd_usb2_start()) */ + /* Disable all IDs (see esd_usb_start()) */ msg->msg.hdr.cmd = CMD_IDADD; msg->msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT; msg->msg.filter.net = priv->index; msg->msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */ for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++) msg->msg.filter.mask[i] = 0; - if (esd_usb2_send_msg(priv->usb2, msg) < 0) + if (esd_usb_send_msg(priv->usb, msg) < 0) netdev_err(netdev, "sending idadd message failed\n"); /* set CAN controller to reset mode */ @@ -864,8 +861,8 @@ static int esd_usb2_close(struct net_device *netdev) msg->msg.hdr.cmd = CMD_SETBAUD; msg->msg.setbaud.net = priv->index; msg->msg.setbaud.rsvd = 0; - msg->msg.setbaud.baud = cpu_to_le32(ESD_USB2_NO_BAUDRATE); - if (esd_usb2_send_msg(priv->usb2, msg) < 0) + msg->msg.setbaud.baud = cpu_to_le32(ESD_USB_NO_BAUDRATE); + if (esd_usb_send_msg(priv->usb, msg) < 0) netdev_err(netdev, "sending setbaud message failed\n"); priv->can.state = CAN_STATE_STOPPED; @@ -879,13 +876,17 @@ static int esd_usb2_close(struct net_device *netdev) return 0; } -static const struct net_device_ops esd_usb2_netdev_ops = { - .ndo_open = esd_usb2_open, - .ndo_stop = esd_usb2_close, - .ndo_start_xmit = esd_usb2_start_xmit, +static const struct net_device_ops esd_usb_netdev_ops = { + .ndo_open = esd_usb_open, + .ndo_stop = esd_usb_close, + .ndo_start_xmit = esd_usb_start_xmit, .ndo_change_mtu = can_change_mtu, }; +static const struct ethtool_ops esd_usb_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + static const struct can_bittiming_const esd_usb2_bittiming_const = { .name = "esd_usb2", .tseg1_min = ESD_USB2_TSEG1_MIN, @@ -900,20 +901,20 @@ static const struct can_bittiming_const esd_usb2_bittiming_const = { static int esd_usb2_set_bittiming(struct net_device *netdev) { - struct esd_usb2_net_priv *priv = netdev_priv(netdev); + struct esd_usb_net_priv *priv = netdev_priv(netdev); struct can_bittiming *bt = &priv->can.bittiming; - struct esd_usb2_msg *msg; + struct esd_usb_msg *msg; int err; u32 canbtr; int sjw_shift; - canbtr = ESD_USB2_UBR; + canbtr = ESD_USB_UBR; if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) - canbtr |= ESD_USB2_LOM; + canbtr |= ESD_USB_LOM; canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1); - if (le16_to_cpu(priv->usb2->udev->descriptor.idProduct) == + if (le16_to_cpu(priv->usb->udev->descriptor.idProduct) == USB_CANUSBM_PRODUCT_ID) sjw_shift = ESD_USBM_SJW_SHIFT; else @@ -941,16 +942,16 @@ static int esd_usb2_set_bittiming(struct net_device *netdev) netdev_info(netdev, "setting BTR=%#x\n", canbtr); - err = esd_usb2_send_msg(priv->usb2, msg); + err = esd_usb_send_msg(priv->usb, msg); kfree(msg); return err; } -static int esd_usb2_get_berr_counter(const struct net_device *netdev, - struct can_berr_counter *bec) +static int esd_usb_get_berr_counter(const struct net_device *netdev, + struct can_berr_counter *bec) { - struct esd_usb2_net_priv *priv = netdev_priv(netdev); + struct esd_usb_net_priv *priv = netdev_priv(netdev); bec->txerr = priv->bec.txerr; bec->rxerr = priv->bec.rxerr; @@ -958,7 +959,7 @@ static int esd_usb2_get_berr_counter(const struct net_device *netdev, return 0; } -static int esd_usb2_set_mode(struct net_device *netdev, enum can_mode mode) +static int esd_usb_set_mode(struct net_device *netdev, enum can_mode mode) { switch (mode) { case CAN_MODE_START: @@ -972,11 +973,11 @@ static int esd_usb2_set_mode(struct net_device *netdev, enum can_mode mode) return 0; } -static int esd_usb2_probe_one_net(struct usb_interface *intf, int index) +static int esd_usb_probe_one_net(struct usb_interface *intf, int index) { - struct esd_usb2 *dev = usb_get_intfdata(intf); + struct esd_usb *dev = usb_get_intfdata(intf); struct net_device *netdev; - struct esd_usb2_net_priv *priv; + struct esd_usb_net_priv *priv; int err = 0; int i; @@ -995,7 +996,7 @@ static int esd_usb2_probe_one_net(struct usb_interface *intf, int index) for (i = 0; i < MAX_TX_URBS; i++) priv->tx_contexts[i].echo_index = MAX_TX_URBS; - priv->usb2 = dev; + priv->usb = dev; priv->netdev = netdev; priv->index = index; @@ -1013,12 +1014,13 @@ static int esd_usb2_probe_one_net(struct usb_interface *intf, int index) priv->can.bittiming_const = &esd_usb2_bittiming_const; priv->can.do_set_bittiming = esd_usb2_set_bittiming; - priv->can.do_set_mode = esd_usb2_set_mode; - priv->can.do_get_berr_counter = esd_usb2_get_berr_counter; + priv->can.do_set_mode = esd_usb_set_mode; + priv->can.do_get_berr_counter = esd_usb_get_berr_counter; netdev->flags |= IFF_ECHO; /* we support local echo */ - netdev->netdev_ops = &esd_usb2_netdev_ops; + netdev->netdev_ops = &esd_usb_netdev_ops; + netdev->ethtool_ops = &esd_usb_ethtool_ops; SET_NETDEV_DEV(netdev, &intf->dev); netdev->dev_id = index; @@ -1038,17 +1040,16 @@ done: return err; } -/* - * probe function for new USB2 devices +/* probe function for new USB devices * * check version information and number of available * CAN interfaces */ -static int esd_usb2_probe(struct usb_interface *intf, +static int esd_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - struct esd_usb2 *dev; - struct esd_usb2_msg *msg; + struct esd_usb *dev; + struct esd_usb_msg *msg; int i, err; dev = kzalloc(sizeof(*dev), GFP_KERNEL); @@ -1076,13 +1077,13 @@ static int esd_usb2_probe(struct usb_interface *intf, msg->msg.version.flags = 0; msg->msg.version.drv_version = 0; - err = esd_usb2_send_msg(dev, msg); + err = esd_usb_send_msg(dev, msg); if (err < 0) { dev_err(&intf->dev, "sending version message failed\n"); goto free_msg; } - err = esd_usb2_wait_msg(dev, msg); + err = esd_usb_wait_msg(dev, msg); if (err < 0) { dev_err(&intf->dev, "no version message answer\n"); goto free_msg; @@ -1105,7 +1106,7 @@ static int esd_usb2_probe(struct usb_interface *intf, /* do per device probing */ for (i = 0; i < dev->net_count; i++) - esd_usb2_probe_one_net(intf, i); + esd_usb_probe_one_net(intf, i); free_msg: kfree(msg); @@ -1115,12 +1116,10 @@ done: return err; } -/* - * called by the usb core when the device is removed from the system - */ -static void esd_usb2_disconnect(struct usb_interface *intf) +/* called by the usb core when the device is removed from the system */ +static void esd_usb_disconnect(struct usb_interface *intf) { - struct esd_usb2 *dev = usb_get_intfdata(intf); + struct esd_usb *dev = usb_get_intfdata(intf); struct net_device *netdev; int i; @@ -1144,11 +1143,11 @@ static void esd_usb2_disconnect(struct usb_interface *intf) } /* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver esd_usb2_driver = { - .name = "esd_usb2", - .probe = esd_usb2_probe, - .disconnect = esd_usb2_disconnect, - .id_table = esd_usb2_table, +static struct usb_driver esd_usb_driver = { + .name = KBUILD_MODNAME, + .probe = esd_usb_probe, + .disconnect = esd_usb_disconnect, + .id_table = esd_usb_table, }; -module_usb_driver(esd_usb2_driver); +module_usb_driver(esd_usb_driver); diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c index 2d73ebbf3836..51294b717040 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_core.c +++ b/drivers/net/can/usb/etas_es58x/es58x_core.c @@ -10,6 +10,7 @@ * Copyright (c) 2020, 2021 Vincent Mailhol <[email protected]> */ +#include <linux/ethtool.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/usb.h> @@ -18,14 +19,11 @@ #include "es58x_core.h" -#define DRV_VERSION "1.00" MODULE_AUTHOR("Vincent Mailhol <[email protected]>"); MODULE_AUTHOR("Arunachalam Santhanam <[email protected]>"); MODULE_DESCRIPTION("Socket CAN driver for ETAS ES58X USB adapters"); -MODULE_VERSION(DRV_VERSION); MODULE_LICENSE("GPL v2"); -#define ES58X_MODULE_NAME "etas_es58x" #define ES58X_VENDOR_ID 0x108C #define ES581_4_PRODUCT_ID 0x0159 #define ES582_1_PRODUCT_ID 0x0168 @@ -59,11 +57,11 @@ MODULE_DEVICE_TABLE(usb, es58x_id_table); #define es58x_print_hex_dump(buf, len) \ print_hex_dump(KERN_DEBUG, \ - ES58X_MODULE_NAME " " __stringify(buf) ": ", \ + KBUILD_MODNAME " " __stringify(buf) ": ", \ DUMP_PREFIX_NONE, 16, 1, buf, len, false) #define es58x_print_hex_dump_debug(buf, len) \ - print_hex_dump_debug(ES58X_MODULE_NAME " " __stringify(buf) ": ",\ + print_hex_dump_debug(KBUILD_MODNAME " " __stringify(buf) ": ",\ DUMP_PREFIX_NONE, 16, 1, buf, len, false) /* The last two bytes of an ES58X command is a CRC16. The first two @@ -1462,10 +1460,6 @@ static void es58x_read_bulk_callback(struct urb *urb) } resubmit_urb: - usb_fill_bulk_urb(urb, es58x_dev->udev, es58x_dev->rx_pipe, - urb->transfer_buffer, urb->transfer_buffer_length, - es58x_read_bulk_callback, es58x_dev); - ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret == -ENODEV) { for (i = 0; i < es58x_dev->num_can_ch; i++) @@ -1599,7 +1593,8 @@ static struct urb *es58x_get_tx_urb(struct es58x_device *es58x_dev) return NULL; usb_fill_bulk_urb(urb, es58x_dev->udev, es58x_dev->tx_pipe, - buf, tx_buf_len, NULL, NULL); + buf, tx_buf_len, es58x_write_bulk_callback, + NULL); return urb; } @@ -1632,9 +1627,7 @@ static int es58x_submit_urb(struct es58x_device *es58x_dev, struct urb *urb, int ret; es58x_set_crc(urb->transfer_buffer, urb->transfer_buffer_length); - usb_fill_bulk_urb(urb, es58x_dev->udev, es58x_dev->tx_pipe, - urb->transfer_buffer, urb->transfer_buffer_length, - es58x_write_bulk_callback, netdev); + urb->context = netdev; usb_anchor_urb(urb, &es58x_dev->tx_urbs_busy); ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret) { @@ -1707,7 +1700,7 @@ static int es58x_alloc_rx_urbs(struct es58x_device *es58x_dev) { const struct device *dev = es58x_dev->dev; const struct es58x_parameters *param = es58x_dev->param; - size_t rx_buf_len = es58x_dev->rx_max_packet_size; + u16 rx_buf_len = usb_maxpacket(es58x_dev->udev, es58x_dev->rx_pipe); struct urb *urb; u8 *buf; int i; @@ -1739,7 +1732,7 @@ static int es58x_alloc_rx_urbs(struct es58x_device *es58x_dev) dev_err(dev, "%s: Could not setup any rx URBs\n", __func__); return ret; } - dev_dbg(dev, "%s: Allocated %d rx URBs each of size %zu\n", + dev_dbg(dev, "%s: Allocated %d rx URBs each of size %u\n", __func__, i, rx_buf_len); return ret; @@ -1981,7 +1974,12 @@ static netdev_tx_t es58x_start_xmit(struct sk_buff *skb, static const struct net_device_ops es58x_netdev_ops = { .ndo_open = es58x_open, .ndo_stop = es58x_stop, - .ndo_start_xmit = es58x_start_xmit + .ndo_start_xmit = es58x_start_xmit, + .ndo_eth_ioctl = can_eth_ioctl_hwts, +}; + +static const struct ethtool_ops es58x_ethtool_ops = { + .get_ts_info = can_ethtool_op_get_ts_info_hwts, }; /** @@ -2088,6 +2086,7 @@ static int es58x_init_netdev(struct es58x_device *es58x_dev, int channel_idx) es58x_init_priv(es58x_dev, es58x_priv(netdev), channel_idx); netdev->netdev_ops = &es58x_netdev_ops; + netdev->ethtool_ops = &es58x_ethtool_ops; netdev->flags |= IFF_ECHO; /* We support local echo */ netdev->dev_port = channel_idx; @@ -2181,9 +2180,8 @@ static struct es58x_device *es58x_init_es58x_dev(struct usb_interface *intf, struct usb_endpoint_descriptor *ep_in, *ep_out; int ret; - dev_info(dev, - "Starting %s %s (Serial Number %s) driver version %s\n", - udev->manufacturer, udev->product, udev->serial, DRV_VERSION); + dev_info(dev, "Starting %s %s (Serial Number %s)\n", + udev->manufacturer, udev->product, udev->serial); ret = usb_find_common_endpoints(intf->cur_altsetting, &ep_in, &ep_out, NULL, NULL); @@ -2223,7 +2221,6 @@ static struct es58x_device *es58x_init_es58x_dev(struct usb_interface *intf, ep_in->bEndpointAddress); es58x_dev->tx_pipe = usb_sndbulkpipe(es58x_dev->udev, ep_out->bEndpointAddress); - es58x_dev->rx_max_packet_size = le16_to_cpu(ep_in->wMaxPacketSize); return es58x_dev; } @@ -2281,7 +2278,7 @@ static void es58x_disconnect(struct usb_interface *intf) } static struct usb_driver es58x_driver = { - .name = ES58X_MODULE_NAME, + .name = KBUILD_MODNAME, .probe = es58x_probe, .disconnect = es58x_disconnect, .id_table = es58x_id_table diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.h b/drivers/net/can/usb/etas_es58x/es58x_core.h index e5033cb5e695..d769bdf740b7 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_core.h +++ b/drivers/net/can/usb/etas_es58x/es58x_core.h @@ -380,7 +380,6 @@ struct es58x_operators { * @timestamps: a temporary buffer to store the time stamps before * feeding them to es58x_can_get_echo_skb(). Can only be used * in RX branches. - * @rx_max_packet_size: Maximum length of bulk-in URB. * @num_can_ch: Number of CAN channel (i.e. number of elements of @netdev). * @opened_channel_cnt: number of channels opened. Free of race * conditions because its two users (net_device_ops:ndo_open() @@ -401,8 +400,8 @@ struct es58x_device { const struct es58x_parameters *param; const struct es58x_operators *ops; - int rx_pipe; - int tx_pipe; + unsigned int rx_pipe; + unsigned int tx_pipe; struct usb_anchor rx_urbs; struct usb_anchor tx_urbs_busy; @@ -414,7 +413,6 @@ struct es58x_device { u64 timestamps[ES58X_ECHO_BULK_MAX]; - u16 rx_max_packet_size; u8 num_can_ch; u8 opened_channel_cnt; diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index b29ba9138866..baf749c8cda3 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -268,6 +268,8 @@ struct gs_can { struct usb_anchor tx_submitted; atomic_t active_tx_urbs; + void *rxbuf[GS_MAX_RX_URBS]; + dma_addr_t rxbuf_dma[GS_MAX_RX_URBS]; }; /* usb interface struct */ @@ -742,6 +744,7 @@ static int gs_can_open(struct net_device *netdev) for (i = 0; i < GS_MAX_RX_URBS; i++) { struct urb *urb; u8 *buf; + dma_addr_t buf_dma; /* alloc rx urb */ urb = usb_alloc_urb(0, GFP_KERNEL); @@ -752,7 +755,7 @@ static int gs_can_open(struct net_device *netdev) buf = usb_alloc_coherent(dev->udev, dev->parent->hf_size_rx, GFP_KERNEL, - &urb->transfer_dma); + &buf_dma); if (!buf) { netdev_err(netdev, "No memory left for USB buffer\n"); @@ -760,6 +763,8 @@ static int gs_can_open(struct net_device *netdev) return -ENOMEM; } + urb->transfer_dma = buf_dma; + /* fill, anchor, and submit rx urb */ usb_fill_bulk_urb(urb, dev->udev, @@ -781,10 +786,17 @@ static int gs_can_open(struct net_device *netdev) "usb_submit failed (err=%d)\n", rc); usb_unanchor_urb(urb); + usb_free_coherent(dev->udev, + sizeof(struct gs_host_frame), + buf, + buf_dma); usb_free_urb(urb); break; } + dev->rxbuf[i] = buf; + dev->rxbuf_dma[i] = buf_dma; + /* Drop reference, * USB core will take care of freeing it */ @@ -842,13 +854,20 @@ static int gs_can_close(struct net_device *netdev) int rc; struct gs_can *dev = netdev_priv(netdev); struct gs_usb *parent = dev->parent; + unsigned int i; netif_stop_queue(netdev); /* Stop polling */ parent->active_channels--; - if (!parent->active_channels) + if (!parent->active_channels) { usb_kill_anchored_urbs(&parent->rx_submitted); + for (i = 0; i < GS_MAX_RX_URBS; i++) + usb_free_coherent(dev->udev, + sizeof(struct gs_host_frame), + dev->rxbuf[i], + dev->rxbuf_dma[i]); + } /* Stop sending URBs */ usb_kill_anchored_urbs(&dev->tx_submitted); @@ -927,6 +946,7 @@ static int gs_usb_set_phys_id(struct net_device *dev, static const struct ethtool_ops gs_usb_ethtool_ops = { .set_phys_id = gs_usb_set_phys_id, + .get_ts_info = ethtool_op_get_ts_info, }; static struct gs_can *gs_make_candev(unsigned int channel, @@ -970,11 +990,12 @@ static struct gs_can *gs_make_candev(unsigned int channel, dev = netdev_priv(netdev); netdev->netdev_ops = &gs_usb_netdev_ops; + netdev->ethtool_ops = &gs_usb_ethtool_ops; netdev->flags |= IFF_ECHO; /* we support full roundtrip echo */ /* dev setup */ - strcpy(dev->bt_const.name, "gs_usb"); + strcpy(dev->bt_const.name, KBUILD_MODNAME); dev->bt_const.tseg1_min = le32_to_cpu(bt_const->tseg1_min); dev->bt_const.tseg1_max = le32_to_cpu(bt_const->tseg1_max); dev->bt_const.tseg2_min = le32_to_cpu(bt_const->tseg2_min); @@ -1081,7 +1102,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, return ERR_PTR(rc); } - strcpy(dev->data_bt_const.name, "gs_usb"); + strcpy(dev->data_bt_const.name, KBUILD_MODNAME); dev->data_bt_const.tseg1_min = le32_to_cpu(bt_const_extended->dtseg1_min); dev->data_bt_const.tseg1_max = le32_to_cpu(bt_const_extended->dtseg1_max); dev->data_bt_const.tseg2_min = le32_to_cpu(bt_const_extended->dtseg2_min); @@ -1251,7 +1272,7 @@ static const struct usb_device_id gs_usb_table[] = { MODULE_DEVICE_TABLE(usb, gs_usb_table); static struct usb_driver gs_usb_driver = { - .name = "gs_usb", + .name = KBUILD_MODNAME, .probe = gs_usb_probe, .disconnect = gs_usb_disconnect, .id_table = gs_usb_table, diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h index 3a49257f9fa6..841da29cef93 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h @@ -35,9 +35,11 @@ #define KVASER_USB_RX_BUFFER_SIZE 3072 #define KVASER_USB_MAX_NET_DEVICES 5 -/* USB devices features */ -#define KVASER_USB_HAS_SILENT_MODE BIT(0) -#define KVASER_USB_HAS_TXRX_ERRORS BIT(1) +/* Kvaser USB device quirks */ +#define KVASER_USB_QUIRK_HAS_SILENT_MODE BIT(0) +#define KVASER_USB_QUIRK_HAS_TXRX_ERRORS BIT(1) +#define KVASER_USB_QUIRK_IGNORE_CLK_FREQ BIT(2) +#define KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP BIT(3) /* Device capabilities */ #define KVASER_USB_CAP_BERR_CAP 0x01 @@ -65,12 +67,7 @@ struct kvaser_usb_dev_card_data_hydra { struct kvaser_usb_dev_card_data { u32 ctrlmode_supported; u32 capabilities; - union { - struct { - enum kvaser_usb_leaf_family family; - } leaf; - struct kvaser_usb_dev_card_data_hydra hydra; - }; + struct kvaser_usb_dev_card_data_hydra hydra; }; /* Context for an outstanding, not yet ACKed, transmission */ @@ -83,7 +80,7 @@ struct kvaser_usb { struct usb_device *udev; struct usb_interface *intf; struct kvaser_usb_net_priv *nets[KVASER_USB_MAX_NET_DEVICES]; - const struct kvaser_usb_dev_ops *ops; + const struct kvaser_usb_driver_info *driver_info; const struct kvaser_usb_dev_cfg *cfg; struct usb_endpoint_descriptor *bulk_in, *bulk_out; @@ -165,6 +162,12 @@ struct kvaser_usb_dev_ops { u16 transid); }; +struct kvaser_usb_driver_info { + u32 quirks; + enum kvaser_usb_leaf_family family; + const struct kvaser_usb_dev_ops *ops; +}; + struct kvaser_usb_dev_cfg { const struct can_clock clock; const unsigned int timestamp_freq; @@ -184,4 +187,7 @@ int kvaser_usb_send_cmd_async(struct kvaser_usb_net_priv *priv, void *cmd, int len); int kvaser_usb_can_rx_over_error(struct net_device *netdev); + +extern const struct can_bittiming_const kvaser_usb_flexc_bittiming_const; + #endif /* KVASER_USB_H */ diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c index e67658b53d02..824cab80aa02 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c @@ -13,6 +13,7 @@ #include <linux/completion.h> #include <linux/device.h> +#include <linux/ethtool.h> #include <linux/gfp.h> #include <linux/if.h> #include <linux/kernel.h> @@ -61,8 +62,6 @@ #define USB_USBCAN_R_V2_PRODUCT_ID 294 #define USB_LEAF_LIGHT_R_V2_PRODUCT_ID 295 #define USB_LEAF_LIGHT_HS_V2_OEM2_PRODUCT_ID 296 -#define USB_LEAF_PRODUCT_ID_END \ - USB_LEAF_LIGHT_HS_V2_OEM2_PRODUCT_ID /* Kvaser USBCan-II devices product ids */ #define USB_USBCAN_REVB_PRODUCT_ID 2 @@ -89,116 +88,153 @@ #define USB_USBCAN_PRO_4HS_PRODUCT_ID 276 #define USB_HYBRID_CANLIN_PRODUCT_ID 277 #define USB_HYBRID_PRO_CANLIN_PRODUCT_ID 278 -#define USB_HYDRA_PRODUCT_ID_END \ - USB_HYBRID_PRO_CANLIN_PRODUCT_ID -static inline bool kvaser_is_leaf(const struct usb_device_id *id) -{ - return (id->idProduct >= USB_LEAF_DEVEL_PRODUCT_ID && - id->idProduct <= USB_CAN_R_PRODUCT_ID) || - (id->idProduct >= USB_LEAF_LITE_V2_PRODUCT_ID && - id->idProduct <= USB_LEAF_PRODUCT_ID_END); -} +static const struct kvaser_usb_driver_info kvaser_usb_driver_info_hydra = { + .quirks = KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP, + .ops = &kvaser_usb_hydra_dev_ops, +}; -static inline bool kvaser_is_usbcan(const struct usb_device_id *id) -{ - return id->idProduct >= USB_USBCAN_REVB_PRODUCT_ID && - id->idProduct <= USB_MEMORATOR_PRODUCT_ID; -} +static const struct kvaser_usb_driver_info kvaser_usb_driver_info_usbcan = { + .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS | + KVASER_USB_QUIRK_HAS_SILENT_MODE, + .family = KVASER_USBCAN, + .ops = &kvaser_usb_leaf_dev_ops, +}; -static inline bool kvaser_is_hydra(const struct usb_device_id *id) -{ - return id->idProduct >= USB_BLACKBIRD_V2_PRODUCT_ID && - id->idProduct <= USB_HYDRA_PRODUCT_ID_END; -} +static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf = { + .quirks = KVASER_USB_QUIRK_IGNORE_CLK_FREQ, + .family = KVASER_LEAF, + .ops = &kvaser_usb_leaf_dev_ops, +}; + +static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf_err = { + .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS | + KVASER_USB_QUIRK_IGNORE_CLK_FREQ, + .family = KVASER_LEAF, + .ops = &kvaser_usb_leaf_dev_ops, +}; + +static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf_err_listen = { + .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS | + KVASER_USB_QUIRK_HAS_SILENT_MODE | + KVASER_USB_QUIRK_IGNORE_CLK_FREQ, + .family = KVASER_LEAF, + .ops = &kvaser_usb_leaf_dev_ops, +}; + +static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leafimx = { + .quirks = 0, + .ops = &kvaser_usb_leaf_dev_ops, +}; static const struct usb_device_id kvaser_usb_table[] = { - /* Leaf USB product IDs */ - { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID) }, + /* Leaf M32C USB product IDs */ + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS | - KVASER_USB_HAS_SILENT_MODE }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS | - KVASER_USB_HAS_SILENT_MODE }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS | - KVASER_USB_HAS_SILENT_MODE }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS | - KVASER_USB_HAS_SILENT_MODE }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS | - KVASER_USB_HAS_SILENT_MODE }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS | - KVASER_USB_HAS_SILENT_MODE }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS | - KVASER_USB_HAS_SILENT_MODE }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen }, { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS | - KVASER_USB_HAS_SILENT_MODE }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen }, { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS | - KVASER_USB_HAS_SILENT_MODE }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen }, { USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID) }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_OBDII_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS | - KVASER_USB_HAS_SILENT_MODE }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen }, { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSLS_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_CH_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err }, { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_SPRO_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err }, { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_MERCURY_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err }, { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_LEAF_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err }, { USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_2HS_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_2HS_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_R_V2_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_R_V2_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM2_PRODUCT_ID) }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err }, + + /* Leaf i.MX28 USB product IDs */ + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_2HS_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_2HS_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_R_V2_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_R_V2_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM2_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx }, /* USBCANII USB product IDs */ { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN2_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan }, { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_REVB_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan }, { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMORATOR_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan }, { USB_DEVICE(KVASER_VENDOR_ID, USB_VCI2_PRODUCT_ID), - .driver_info = KVASER_USB_HAS_TXRX_ERRORS }, + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan }, /* Minihydra USB product IDs */ - { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_V2_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_5HS_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_5HS_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_4HS_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_HS_V2_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_2HS_V2_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_2HS_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_2HS_V2_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_2CANLIN_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_USBCAN_PRO_2HS_V2_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_MEMO_PRO_2HS_V2_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_2CANLIN_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_U100_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_U100P_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_U100S_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_4HS_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_CANLIN_PRODUCT_ID) }, - { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_CANLIN_PRODUCT_ID) }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_V2_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_5HS_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_5HS_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_4HS_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_HS_V2_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_2HS_V2_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_2HS_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_2HS_V2_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_2CANLIN_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_USBCAN_PRO_2HS_V2_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_MEMO_PRO_2HS_V2_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_2CANLIN_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_U100_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_U100P_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_U100S_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_4HS_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_CANLIN_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_CANLIN_PRODUCT_ID), + .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra }, { } }; MODULE_DEVICE_TABLE(usb, kvaser_usb_table); @@ -285,6 +321,7 @@ int kvaser_usb_can_rx_over_error(struct net_device *netdev) static void kvaser_usb_read_bulk_callback(struct urb *urb) { struct kvaser_usb *dev = urb->context; + const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops; int err; unsigned int i; @@ -301,8 +338,8 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb) goto resubmit_urb; } - dev->ops->dev_read_bulk_callback(dev, urb->transfer_buffer, - urb->actual_length); + ops->dev_read_bulk_callback(dev, urb->transfer_buffer, + urb->actual_length); resubmit_urb: usb_fill_bulk_urb(urb, dev->udev, @@ -396,6 +433,7 @@ static int kvaser_usb_open(struct net_device *netdev) { struct kvaser_usb_net_priv *priv = netdev_priv(netdev); struct kvaser_usb *dev = priv->dev; + const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops; int err; err = open_candev(netdev); @@ -406,11 +444,11 @@ static int kvaser_usb_open(struct net_device *netdev) if (err) goto error; - err = dev->ops->dev_set_opt_mode(priv); + err = ops->dev_set_opt_mode(priv); if (err) goto error; - err = dev->ops->dev_start_chip(priv); + err = ops->dev_start_chip(priv); if (err) { netdev_warn(netdev, "Cannot start device, error %d\n", err); goto error; @@ -467,22 +505,23 @@ static int kvaser_usb_close(struct net_device *netdev) { struct kvaser_usb_net_priv *priv = netdev_priv(netdev); struct kvaser_usb *dev = priv->dev; + const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops; int err; netif_stop_queue(netdev); - err = dev->ops->dev_flush_queue(priv); + err = ops->dev_flush_queue(priv); if (err) netdev_warn(netdev, "Cannot flush queue, error %d\n", err); - if (dev->ops->dev_reset_chip) { - err = dev->ops->dev_reset_chip(dev, priv->channel); + if (ops->dev_reset_chip) { + err = ops->dev_reset_chip(dev, priv->channel); if (err) netdev_warn(netdev, "Cannot reset card, error %d\n", err); } - err = dev->ops->dev_stop_chip(priv); + err = ops->dev_stop_chip(priv); if (err) netdev_warn(netdev, "Cannot stop device, error %d\n", err); @@ -521,6 +560,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, { struct kvaser_usb_net_priv *priv = netdev_priv(netdev); struct kvaser_usb *dev = priv->dev; + const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops; struct net_device_stats *stats = &netdev->stats; struct kvaser_usb_tx_urb_context *context = NULL; struct urb *urb; @@ -563,8 +603,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, goto freeurb; } - buf = dev->ops->dev_frame_to_cmd(priv, skb, &cmd_len, - context->echo_index); + buf = ops->dev_frame_to_cmd(priv, skb, &cmd_len, context->echo_index); if (!buf) { stats->tx_dropped++; dev_kfree_skb(skb); @@ -627,6 +666,22 @@ static const struct net_device_ops kvaser_usb_netdev_ops = { .ndo_change_mtu = can_change_mtu, }; +static const struct net_device_ops kvaser_usb_netdev_ops_hwts = { + .ndo_open = kvaser_usb_open, + .ndo_stop = kvaser_usb_close, + .ndo_eth_ioctl = can_eth_ioctl_hwts, + .ndo_start_xmit = kvaser_usb_start_xmit, + .ndo_change_mtu = can_change_mtu, +}; + +static const struct ethtool_ops kvaser_usb_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + +static const struct ethtool_ops kvaser_usb_ethtool_ops_hwts = { + .get_ts_info = can_ethtool_op_get_ts_info_hwts, +}; + static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev) { int i; @@ -648,15 +703,16 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev) } } -static int kvaser_usb_init_one(struct kvaser_usb *dev, - const struct usb_device_id *id, int channel) +static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) { struct net_device *netdev; struct kvaser_usb_net_priv *priv; + const struct kvaser_usb_driver_info *driver_info = dev->driver_info; + const struct kvaser_usb_dev_ops *ops = driver_info->ops; int err; - if (dev->ops->dev_reset_chip) { - err = dev->ops->dev_reset_chip(dev, channel); + if (ops->dev_reset_chip) { + err = ops->dev_reset_chip(dev, channel); if (err) return err; } @@ -685,26 +741,31 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, priv->can.state = CAN_STATE_STOPPED; priv->can.clock.freq = dev->cfg->clock.freq; priv->can.bittiming_const = dev->cfg->bittiming_const; - priv->can.do_set_bittiming = dev->ops->dev_set_bittiming; - priv->can.do_set_mode = dev->ops->dev_set_mode; - if ((id->driver_info & KVASER_USB_HAS_TXRX_ERRORS) || + priv->can.do_set_bittiming = ops->dev_set_bittiming; + priv->can.do_set_mode = ops->dev_set_mode; + if ((driver_info->quirks & KVASER_USB_QUIRK_HAS_TXRX_ERRORS) || (priv->dev->card_data.capabilities & KVASER_USB_CAP_BERR_CAP)) - priv->can.do_get_berr_counter = dev->ops->dev_get_berr_counter; - if (id->driver_info & KVASER_USB_HAS_SILENT_MODE) + priv->can.do_get_berr_counter = ops->dev_get_berr_counter; + if (driver_info->quirks & KVASER_USB_QUIRK_HAS_SILENT_MODE) priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY; priv->can.ctrlmode_supported |= dev->card_data.ctrlmode_supported; if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) { priv->can.data_bittiming_const = dev->cfg->data_bittiming_const; - priv->can.do_set_data_bittiming = - dev->ops->dev_set_data_bittiming; + priv->can.do_set_data_bittiming = ops->dev_set_data_bittiming; } netdev->flags |= IFF_ECHO; netdev->netdev_ops = &kvaser_usb_netdev_ops; - + if (driver_info->quirks & KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP) { + netdev->netdev_ops = &kvaser_usb_netdev_ops_hwts; + netdev->ethtool_ops = &kvaser_usb_ethtool_ops_hwts; + } else { + netdev->netdev_ops = &kvaser_usb_netdev_ops; + netdev->ethtool_ops = &kvaser_usb_ethtool_ops; + } SET_NETDEV_DEV(netdev, &dev->intf->dev); netdev->dev_id = channel; @@ -729,29 +790,22 @@ static int kvaser_usb_probe(struct usb_interface *intf, struct kvaser_usb *dev; int err; int i; + const struct kvaser_usb_driver_info *driver_info; + const struct kvaser_usb_dev_ops *ops; + + driver_info = (const struct kvaser_usb_driver_info *)id->driver_info; + if (!driver_info) + return -ENODEV; dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; - if (kvaser_is_leaf(id)) { - dev->card_data.leaf.family = KVASER_LEAF; - dev->ops = &kvaser_usb_leaf_dev_ops; - } else if (kvaser_is_usbcan(id)) { - dev->card_data.leaf.family = KVASER_USBCAN; - dev->ops = &kvaser_usb_leaf_dev_ops; - } else if (kvaser_is_hydra(id)) { - dev->ops = &kvaser_usb_hydra_dev_ops; - } else { - dev_err(&intf->dev, - "Product ID (%d) is not a supported Kvaser USB device\n", - id->idProduct); - return -ENODEV; - } - dev->intf = intf; + dev->driver_info = driver_info; + ops = driver_info->ops; - err = dev->ops->dev_setup_endpoints(dev); + err = ops->dev_setup_endpoints(dev); if (err) { dev_err(&intf->dev, "Cannot get usb endpoint(s)"); return err; @@ -765,22 +819,22 @@ static int kvaser_usb_probe(struct usb_interface *intf, dev->card_data.ctrlmode_supported = 0; dev->card_data.capabilities = 0; - err = dev->ops->dev_init_card(dev); + err = ops->dev_init_card(dev); if (err) { dev_err(&intf->dev, "Failed to initialize card, error %d\n", err); return err; } - err = dev->ops->dev_get_software_info(dev); + err = ops->dev_get_software_info(dev); if (err) { dev_err(&intf->dev, "Cannot get software info, error %d\n", err); return err; } - if (dev->ops->dev_get_software_details) { - err = dev->ops->dev_get_software_details(dev); + if (ops->dev_get_software_details) { + err = ops->dev_get_software_details(dev); if (err) { dev_err(&intf->dev, "Cannot get software details, error %d\n", err); @@ -798,14 +852,14 @@ static int kvaser_usb_probe(struct usb_interface *intf, dev_dbg(&intf->dev, "Max outstanding tx = %d URBs\n", dev->max_tx_urbs); - err = dev->ops->dev_get_card_info(dev); + err = ops->dev_get_card_info(dev); if (err) { dev_err(&intf->dev, "Cannot get card info, error %d\n", err); return err; } - if (dev->ops->dev_get_capabilities) { - err = dev->ops->dev_get_capabilities(dev); + if (ops->dev_get_capabilities) { + err = ops->dev_get_capabilities(dev); if (err) { dev_err(&intf->dev, "Cannot get capabilities, error %d\n", err); @@ -815,7 +869,7 @@ static int kvaser_usb_probe(struct usb_interface *intf, } for (i = 0; i < dev->nchannels; i++) { - err = kvaser_usb_init_one(dev, id, i); + err = kvaser_usb_init_one(dev, i); if (err) { kvaser_usb_remove_interfaces(dev); return err; @@ -838,7 +892,7 @@ static void kvaser_usb_disconnect(struct usb_interface *intf) } static struct usb_driver kvaser_usb_driver = { - .name = "kvaser_usb", + .name = KBUILD_MODNAME, .probe = kvaser_usb_probe, .disconnect = kvaser_usb_disconnect, .id_table = kvaser_usb_table, diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c index a26823c5b62a..dd65c101bfb8 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c @@ -375,7 +375,7 @@ static const struct can_bittiming_const kvaser_usb_hydra_kcan_bittiming_c = { .brp_inc = 1, }; -static const struct can_bittiming_const kvaser_usb_hydra_flexc_bittiming_c = { +const struct can_bittiming_const kvaser_usb_flexc_bittiming_const = { .name = "kvaser_usb_flex", .tseg1_min = 4, .tseg1_max = 16, @@ -917,8 +917,11 @@ static void kvaser_usb_hydra_update_state(struct kvaser_usb_net_priv *priv, new_state < CAN_STATE_BUS_OFF) priv->can.can_stats.restarts++; - cf->data[6] = bec->txerr; - cf->data[7] = bec->rxerr; + if (new_state != CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_CNT; + cf->data[6] = bec->txerr; + cf->data[7] = bec->rxerr; + } netif_rx(skb); } @@ -1069,8 +1072,11 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv, shhwtstamps->hwtstamp = hwtstamp; cf->can_id |= CAN_ERR_BUSERROR; - cf->data[6] = bec.txerr; - cf->data[7] = bec.rxerr; + if (new_state != CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_CNT; + cf->data[6] = bec.txerr; + cf->data[7] = bec.rxerr; + } netif_rx(skb); @@ -2052,7 +2058,7 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_flexc = { .freq = 24 * MEGA /* Hz */, }, .timestamp_freq = 1, - .bittiming_const = &kvaser_usb_hydra_flexc_bittiming_c, + .bittiming_const = &kvaser_usb_flexc_bittiming_const, }; static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_rt = { diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c index c805b999c543..07f687f29b34 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -101,16 +101,6 @@ #define USBCAN_ERROR_STATE_RX_ERROR BIT(1) #define USBCAN_ERROR_STATE_BUSERROR BIT(2) -/* bittiming parameters */ -#define KVASER_USB_TSEG1_MIN 1 -#define KVASER_USB_TSEG1_MAX 16 -#define KVASER_USB_TSEG2_MIN 1 -#define KVASER_USB_TSEG2_MAX 8 -#define KVASER_USB_SJW_MAX 4 -#define KVASER_USB_BRP_MIN 1 -#define KVASER_USB_BRP_MAX 64 -#define KVASER_USB_BRP_INC 1 - /* ctrl modes */ #define KVASER_CTRL_MODE_NORMAL 1 #define KVASER_CTRL_MODE_SILENT 2 @@ -343,48 +333,68 @@ struct kvaser_usb_err_summary { }; }; -static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = { - .name = "kvaser_usb", - .tseg1_min = KVASER_USB_TSEG1_MIN, - .tseg1_max = KVASER_USB_TSEG1_MAX, - .tseg2_min = KVASER_USB_TSEG2_MIN, - .tseg2_max = KVASER_USB_TSEG2_MAX, - .sjw_max = KVASER_USB_SJW_MAX, - .brp_min = KVASER_USB_BRP_MIN, - .brp_max = KVASER_USB_BRP_MAX, - .brp_inc = KVASER_USB_BRP_INC, +static const struct can_bittiming_const kvaser_usb_leaf_m16c_bittiming_const = { + .name = "kvaser_usb_ucii", + .tseg1_min = 4, + .tseg1_max = 16, + .tseg2_min = 2, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 16, + .brp_inc = 1, +}; + +static const struct can_bittiming_const kvaser_usb_leaf_m32c_bittiming_const = { + .name = "kvaser_usb_leaf", + .tseg1_min = 3, + .tseg1_max = 16, + .tseg2_min = 2, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 2, + .brp_max = 128, + .brp_inc = 2, }; -static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_8mhz = { +static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_usbcan_dev_cfg = { .clock = { .freq = 8 * MEGA /* Hz */, }, .timestamp_freq = 1, - .bittiming_const = &kvaser_usb_leaf_bittiming_const, + .bittiming_const = &kvaser_usb_leaf_m16c_bittiming_const, +}; + +static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_m32c_dev_cfg = { + .clock = { + .freq = 16 * MEGA /* Hz */, + }, + .timestamp_freq = 1, + .bittiming_const = &kvaser_usb_leaf_m32c_bittiming_const, }; -static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_16mhz = { +static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_16mhz = { .clock = { .freq = 16 * MEGA /* Hz */, }, .timestamp_freq = 1, - .bittiming_const = &kvaser_usb_leaf_bittiming_const, + .bittiming_const = &kvaser_usb_flexc_bittiming_const, }; -static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_24mhz = { +static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_24mhz = { .clock = { .freq = 24 * MEGA /* Hz */, }, .timestamp_freq = 1, - .bittiming_const = &kvaser_usb_leaf_bittiming_const, + .bittiming_const = &kvaser_usb_flexc_bittiming_const, }; -static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_32mhz = { +static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_32mhz = { .clock = { .freq = 32 * MEGA /* Hz */, }, .timestamp_freq = 1, - .bittiming_const = &kvaser_usb_leaf_bittiming_const, + .bittiming_const = &kvaser_usb_flexc_bittiming_const, }; static void * @@ -404,7 +414,7 @@ kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, sizeof(struct kvaser_cmd_tx_can); cmd->u.tx_can.channel = priv->channel; - switch (dev->card_data.leaf.family) { + switch (dev->driver_info->family) { case KVASER_LEAF: cmd_tx_can_flags = &cmd->u.tx_can.leaf.flags; break; @@ -524,16 +534,23 @@ static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev, dev->fw_version = le32_to_cpu(softinfo->fw_version); dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx); - switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) { - case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK: - dev->cfg = &kvaser_usb_leaf_dev_cfg_16mhz; - break; - case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK: - dev->cfg = &kvaser_usb_leaf_dev_cfg_24mhz; - break; - case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK: - dev->cfg = &kvaser_usb_leaf_dev_cfg_32mhz; - break; + if (dev->driver_info->quirks & KVASER_USB_QUIRK_IGNORE_CLK_FREQ) { + /* Firmware expects bittiming parameters calculated for 16MHz + * clock, regardless of the actual clock + */ + dev->cfg = &kvaser_usb_leaf_m32c_dev_cfg; + } else { + switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) { + case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK: + dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_16mhz; + break; + case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK: + dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_24mhz; + break; + case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK: + dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_32mhz; + break; + } } } @@ -550,7 +567,7 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) if (err) return err; - switch (dev->card_data.leaf.family) { + switch (dev->driver_info->family) { case KVASER_LEAF: kvaser_usb_leaf_get_software_info_leaf(dev, &cmd.u.leaf.softinfo); break; @@ -558,7 +575,7 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) dev->fw_version = le32_to_cpu(cmd.u.usbcan.softinfo.fw_version); dev->max_tx_urbs = le16_to_cpu(cmd.u.usbcan.softinfo.max_outstanding_tx); - dev->cfg = &kvaser_usb_leaf_dev_cfg_8mhz; + dev->cfg = &kvaser_usb_leaf_usbcan_dev_cfg; break; } @@ -597,7 +614,7 @@ static int kvaser_usb_leaf_get_card_info(struct kvaser_usb *dev) dev->nchannels = cmd.u.cardinfo.nchannels; if (dev->nchannels > KVASER_USB_MAX_NET_DEVICES || - (dev->card_data.leaf.family == KVASER_USBCAN && + (dev->driver_info->family == KVASER_USBCAN && dev->nchannels > MAX_USBCAN_NET_DEVICES)) return -EINVAL; @@ -730,7 +747,7 @@ kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, new_state < CAN_STATE_BUS_OFF) priv->can.can_stats.restarts++; - switch (dev->card_data.leaf.family) { + switch (dev->driver_info->family) { case KVASER_LEAF: if (es->leaf.error_factor) { priv->can.can_stats.bus_error++; @@ -809,7 +826,7 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, } } - switch (dev->card_data.leaf.family) { + switch (dev->driver_info->family) { case KVASER_LEAF: if (es->leaf.error_factor) { cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT; @@ -836,8 +853,11 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, break; } - cf->data[6] = es->txerr; - cf->data[7] = es->rxerr; + if (new_state != CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_CNT; + cf->data[6] = es->txerr; + cf->data[7] = es->rxerr; + } netif_rx(skb); } @@ -999,7 +1019,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, stats = &priv->netdev->stats; if ((cmd->u.rx_can_header.flag & MSG_FLAG_ERROR_FRAME) && - (dev->card_data.leaf.family == KVASER_LEAF && + (dev->driver_info->family == KVASER_LEAF && cmd->id == CMD_LEAF_LOG_MESSAGE)) { kvaser_usb_leaf_leaf_rx_error(dev, cmd); return; @@ -1015,7 +1035,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, return; } - switch (dev->card_data.leaf.family) { + switch (dev->driver_info->family) { case KVASER_LEAF: rx_data = cmd->u.leaf.rx_can.data; break; @@ -1030,7 +1050,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, return; } - if (dev->card_data.leaf.family == KVASER_LEAF && cmd->id == + if (dev->driver_info->family == KVASER_LEAF && cmd->id == CMD_LEAF_LOG_MESSAGE) { cf->can_id = le32_to_cpu(cmd->u.leaf.log_message.id); if (cf->can_id & KVASER_EXTENDED_FRAME) @@ -1128,14 +1148,14 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, break; case CMD_LEAF_LOG_MESSAGE: - if (dev->card_data.leaf.family != KVASER_LEAF) + if (dev->driver_info->family != KVASER_LEAF) goto warn; kvaser_usb_leaf_rx_can_msg(dev, cmd); break; case CMD_CHIP_STATE_EVENT: case CMD_CAN_ERROR_EVENT: - if (dev->card_data.leaf.family == KVASER_LEAF) + if (dev->driver_info->family == KVASER_LEAF) kvaser_usb_leaf_leaf_rx_error(dev, cmd); else kvaser_usb_leaf_usbcan_rx_error(dev, cmd); @@ -1147,12 +1167,12 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, /* Ignored commands */ case CMD_USBCAN_CLOCK_OVERFLOW_EVENT: - if (dev->card_data.leaf.family != KVASER_USBCAN) + if (dev->driver_info->family != KVASER_USBCAN) goto warn; break; case CMD_FLUSH_QUEUE_REPLY: - if (dev->card_data.leaf.family != KVASER_LEAF) + if (dev->driver_info->family != KVASER_LEAF) goto warn; break; diff --git a/drivers/net/can/usb/mcba_usb.c b/drivers/net/can/usb/mcba_usb.c index 792ab9da317d..69346c63021f 100644 --- a/drivers/net/can/usb/mcba_usb.c +++ b/drivers/net/can/usb/mcba_usb.c @@ -10,6 +10,7 @@ #include <linux/can.h> #include <linux/can/dev.h> #include <linux/can/error.h> +#include <linux/ethtool.h> #include <linux/module.h> #include <linux/netdevice.h> #include <linux/signal.h> @@ -758,6 +759,10 @@ static const struct net_device_ops mcba_netdev_ops = { .ndo_start_xmit = mcba_usb_start_xmit, }; +static const struct ethtool_ops mcba_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + /* Microchip CANBUS has hardcoded bittiming values by default. * This function sends request via USB to change the speed and align bittiming * values for presentation purposes only @@ -836,6 +841,7 @@ static int mcba_usb_probe(struct usb_interface *intf, priv->can.do_set_bittiming = mcba_net_set_bittiming; netdev->netdev_ops = &mcba_netdev_ops; + netdev->ethtool_ops = &mcba_ethtool_ops; netdev->flags |= IFF_ECHO; /* we support local echo */ diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 091c631ebe23..687dd542f7f6 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -506,6 +506,7 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, /* Supply TX/RX error counters in case of * controller error. */ + cf->can_id = CAN_ERR_CNT; cf->data[6] = mc->pdev->bec.txerr; cf->data[7] = mc->pdev->bec.rxerr; } @@ -964,6 +965,7 @@ static int pcan_usb_set_phys_id(struct net_device *netdev, static const struct ethtool_ops pcan_usb_ethtool_ops = { .set_phys_id = pcan_usb_set_phys_id, + .get_ts_info = pcan_get_ts_info, }; /* diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index b850ff8fe4bd..8c9d53f6e24c 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -57,7 +57,7 @@ MODULE_DEVICE_TABLE(usb, peak_usb_table); * dump memory */ #define DUMP_WIDTH 16 -void pcan_dump_mem(char *prompt, void *p, int l) +void pcan_dump_mem(const char *prompt, const void *p, int l) { pr_info("%s dumping %s (%d bytes):\n", PCAN_USB_DRIVER_NAME, prompt ? prompt : "memory", l); @@ -775,13 +775,54 @@ static int peak_usb_set_data_bittiming(struct net_device *netdev) return 0; } +static int peak_eth_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct hwtstamp_config hwts_cfg = { 0 }; + + switch (cmd) { + case SIOCSHWTSTAMP: /* set */ + if (copy_from_user(&hwts_cfg, ifr->ifr_data, sizeof(hwts_cfg))) + return -EFAULT; + if (hwts_cfg.tx_type == HWTSTAMP_TX_OFF && + hwts_cfg.rx_filter == HWTSTAMP_FILTER_ALL) + return 0; + return -ERANGE; + + case SIOCGHWTSTAMP: /* get */ + hwts_cfg.tx_type = HWTSTAMP_TX_OFF; + hwts_cfg.rx_filter = HWTSTAMP_FILTER_ALL; + if (copy_to_user(ifr->ifr_data, &hwts_cfg, sizeof(hwts_cfg))) + return -EFAULT; + return 0; + + default: + return -EOPNOTSUPP; + } +} + static const struct net_device_ops peak_usb_netdev_ops = { .ndo_open = peak_usb_ndo_open, .ndo_stop = peak_usb_ndo_stop, + .ndo_eth_ioctl = peak_eth_ioctl, .ndo_start_xmit = peak_usb_ndo_start_xmit, .ndo_change_mtu = can_change_mtu, }; +int pcan_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) +{ + info->so_timestamping = + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + info->phc_index = -1; + info->tx_types = BIT(HWTSTAMP_TX_OFF); + info->rx_filters = BIT(HWTSTAMP_FILTER_ALL); + + return 0; +} + /* * create one device which is attached to CAN controller #ctrl_idx of the * usb adapter. diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.h b/drivers/net/can/usb/peak_usb/pcan_usb_core.h index f60af573a2e0..f6bdd8b3f290 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.h +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.h @@ -132,7 +132,7 @@ struct peak_usb_device { struct peak_usb_device *next_siblings; }; -void pcan_dump_mem(char *prompt, void *p, int l); +void pcan_dump_mem(const char *prompt, const void *p, int l); /* common timestamp management */ void peak_usb_init_time_ref(struct peak_time_ref *time_ref, @@ -145,5 +145,6 @@ int peak_usb_netif_rx(struct sk_buff *skb, int peak_usb_netif_rx_64(struct sk_buff *skb, u32 ts_low, u32 ts_high); void peak_usb_async_complete(struct urb *urb); void peak_usb_restart_complete(struct peak_usb_device *dev); +int pcan_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info); #endif diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c index 65487ec33566..2ea1500df393 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c @@ -33,6 +33,10 @@ #define PCAN_UFD_RX_BUFFER_SIZE 2048 #define PCAN_UFD_TX_BUFFER_SIZE 512 +/* struct pcan_ufd_fw_info::type */ +#define PCAN_USBFD_TYPE_STD 1 +#define PCAN_USBFD_TYPE_EXT 2 /* includes EP numbers */ + /* read some versions info from the hw device */ struct __packed pcan_ufd_fw_info { __le16 size_of; /* sizeof this */ @@ -44,6 +48,13 @@ struct __packed pcan_ufd_fw_info { __le32 dev_id[2]; /* "device id" per CAN */ __le32 ser_no; /* S/N */ __le32 flags; /* special functions */ + + /* extended data when type == PCAN_USBFD_TYPE_EXT */ + u8 cmd_out_ep; /* ep for cmd */ + u8 cmd_in_ep; /* ep for replies */ + u8 data_out_ep[2]; /* ep for CANx TX */ + u8 data_in_ep; /* ep for CAN RX */ + u8 dummy[3]; }; /* handle device specific info used by the netdevices */ @@ -171,6 +182,9 @@ static inline void *pcan_usb_fd_cmd_buffer(struct peak_usb_device *dev) /* send PCAN-USB Pro FD commands synchronously */ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) { + struct pcan_usb_fd_device *pdev = + container_of(dev, struct pcan_usb_fd_device, dev); + struct pcan_ufd_fw_info *fw_info = &pdev->usb_if->fw_info; void *cmd_head = pcan_usb_fd_cmd_buffer(dev); int err = 0; u8 *packet_ptr; @@ -200,7 +214,7 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) do { err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, - PCAN_USBPRO_EP_CMDOUT), + fw_info->cmd_out_ep), packet_ptr, packet_len, NULL, PCAN_UFD_CMD_TIMEOUT_MS); if (err) { @@ -426,6 +440,9 @@ static int pcan_usb_fd_set_bittiming_fast(struct peak_usb_device *dev, static int pcan_usb_fd_restart_async(struct peak_usb_device *dev, struct urb *urb, u8 *buf) { + struct pcan_usb_fd_device *pdev = + container_of(dev, struct pcan_usb_fd_device, dev); + struct pcan_ufd_fw_info *fw_info = &pdev->usb_if->fw_info; u8 *pc = buf; /* build the entire cmds list in the provided buffer, to go back into @@ -439,7 +456,7 @@ static int pcan_usb_fd_restart_async(struct peak_usb_device *dev, /* complete the URB */ usb_fill_bulk_urb(urb, dev->udev, - usb_sndbulkpipe(dev->udev, PCAN_USBPRO_EP_CMDOUT), + usb_sndbulkpipe(dev->udev, fw_info->cmd_out_ep), buf, pc - buf, pcan_usb_pro_restart_complete, dev); @@ -839,6 +856,15 @@ static int pcan_usb_fd_get_berr_counter(const struct net_device *netdev, return 0; } +/* probe function for all PCAN-USB FD family usb interfaces */ +static int pcan_usb_fd_probe(struct usb_interface *intf) +{ + struct usb_host_interface *iface_desc = &intf->altsetting[0]; + + /* CAN interface is always interface #0 */ + return iface_desc->desc.bInterfaceNumber; +} + /* stop interface (last chance before set bus off) */ static int pcan_usb_fd_stop(struct peak_usb_device *dev) { @@ -860,6 +886,7 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) { struct pcan_usb_fd_device *pdev = container_of(dev, struct pcan_usb_fd_device, dev); + struct pcan_ufd_fw_info *fw_info; int i, err = -ENOMEM; /* do this for 1st channel only */ @@ -878,10 +905,12 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) /* number of ts msgs to ignore before taking one into account */ pdev->usb_if->cm_ignore_count = 5; + fw_info = &pdev->usb_if->fw_info; + err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO, PCAN_USBPRO_INFO_FW, - &pdev->usb_if->fw_info, - sizeof(pdev->usb_if->fw_info)); + fw_info, + sizeof(*fw_info)); if (err) { dev_err(dev->netdev->dev.parent, "unable to read %s firmware info (err %d)\n", @@ -895,14 +924,14 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) */ dev_info(dev->netdev->dev.parent, "PEAK-System %s v%u fw v%u.%u.%u (%u channels)\n", - dev->adapter->name, pdev->usb_if->fw_info.hw_version, - pdev->usb_if->fw_info.fw_version[0], - pdev->usb_if->fw_info.fw_version[1], - pdev->usb_if->fw_info.fw_version[2], + dev->adapter->name, fw_info->hw_version, + fw_info->fw_version[0], + fw_info->fw_version[1], + fw_info->fw_version[2], dev->adapter->ctrl_count); /* check for ability to switch between ISO/non-ISO modes */ - if (pdev->usb_if->fw_info.fw_version[0] >= 2) { + if (fw_info->fw_version[0] >= 2) { /* firmware >= 2.x supports ISO/non-ISO switching */ dev->can.ctrlmode_supported |= CAN_CTRLMODE_FD_NON_ISO; } else { @@ -910,6 +939,14 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) dev->can.ctrlmode |= CAN_CTRLMODE_FD_NON_ISO; } + /* if vendor rsp is of type 2, then it contains EP numbers to + * use for cmds pipes. If not, then default EP should be used. + */ + if (fw_info->type != cpu_to_le16(PCAN_USBFD_TYPE_EXT)) { + fw_info->cmd_out_ep = PCAN_USBPRO_EP_CMDOUT; + fw_info->cmd_in_ep = PCAN_USBPRO_EP_CMDIN; + } + /* tell the hardware the can driver is running */ err = pcan_usb_fd_drv_loaded(dev, 1); if (err) { @@ -930,12 +967,23 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) /* do a copy of the ctrlmode[_supported] too */ dev->can.ctrlmode = ppdev->dev.can.ctrlmode; dev->can.ctrlmode_supported = ppdev->dev.can.ctrlmode_supported; + + fw_info = &pdev->usb_if->fw_info; } pdev->usb_if->dev[dev->ctrl_idx] = dev; dev->device_number = le32_to_cpu(pdev->usb_if->fw_info.dev_id[dev->ctrl_idx]); + /* if vendor rsp is of type 2, then it contains EP numbers to + * use for data pipes. If not, then statically defined EP are used + * (see peak_usb_create_dev()). + */ + if (fw_info->type == cpu_to_le16(PCAN_USBFD_TYPE_EXT)) { + dev->ep_msg_in = fw_info->data_in_ep; + dev->ep_msg_out = fw_info->data_out_ep[dev->ctrl_idx]; + } + /* set clock domain */ for (i = 0; i < ARRAY_SIZE(pcan_usb_fd_clk_freq); i++) if (dev->adapter->clock.freq == pcan_usb_fd_clk_freq[i]) @@ -1032,6 +1080,7 @@ static int pcan_usb_fd_set_phys_id(struct net_device *netdev, static const struct ethtool_ops pcan_usb_fd_ethtool_ops = { .set_phys_id = pcan_usb_fd_set_phys_id, + .get_ts_info = pcan_get_ts_info, }; /* describes the PCAN-USB FD adapter */ @@ -1091,7 +1140,7 @@ const struct peak_usb_adapter pcan_usb_fd = { .tx_buffer_size = PCAN_UFD_TX_BUFFER_SIZE, /* device callbacks */ - .intf_probe = pcan_usb_pro_probe, /* same as PCAN-USB Pro */ + .intf_probe = pcan_usb_fd_probe, .dev_init = pcan_usb_fd_init, .dev_exit = pcan_usb_fd_exit, diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index ebe087f258e3..5d8f6a40bb2c 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -439,7 +439,7 @@ static int pcan_usb_pro_get_device_id(struct peak_usb_device *dev, return err; pdn = (struct pcan_usb_pro_devid *)pc; - *device_id = le32_to_cpu(pdn->serial_num); + *device_id = le32_to_cpu(pdn->dev_num); return err; } @@ -1022,6 +1022,7 @@ static int pcan_usb_pro_set_phys_id(struct net_device *netdev, static const struct ethtool_ops pcan_usb_pro_ethtool_ops = { .set_phys_id = pcan_usb_pro_set_phys_id, + .get_ts_info = pcan_get_ts_info, }; /* diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.h b/drivers/net/can/usb/peak_usb/pcan_usb_pro.h index 5d4cf14eb9d9..a34e0fc021c9 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.h +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.h @@ -112,7 +112,7 @@ struct __packed pcan_usb_pro_devid { u8 data_type; u8 channel; __le16 dummy; - __le32 serial_num; + __le32 dev_num; }; #define PCAN_USBPRO_LED_DEVICE 0x00 diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c index 5ae0d7c017cc..7c35f50fda4e 100644 --- a/drivers/net/can/usb/ucan.c +++ b/drivers/net/can/usb/ucan.c @@ -28,6 +28,7 @@ #include <linux/can.h> #include <linux/can/dev.h> #include <linux/can/error.h> +#include <linux/ethtool.h> #include <linux/module.h> #include <linux/netdevice.h> #include <linux/signal.h> @@ -1233,6 +1234,10 @@ static const struct net_device_ops ucan_netdev_ops = { .ndo_change_mtu = can_change_mtu, }; +static const struct ethtool_ops ucan_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + /* Request to set bittiming * * This function generates an USB set bittiming message and transmits @@ -1512,6 +1517,7 @@ static int ucan_probe(struct usb_interface *intf, spin_lock_init(&up->context_lock); spin_lock_init(&up->echo_skb_lock); netdev->netdev_ops = &ucan_netdev_ops; + netdev->ethtool_ops = &ucan_ethtool_ops; usb_set_intfdata(intf, up); SET_NETDEV_DEV(netdev, &intf->dev); diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c index f3363575bf32..64c00abe91cf 100644 --- a/drivers/net/can/usb/usb_8dev.c +++ b/drivers/net/can/usb/usb_8dev.c @@ -12,6 +12,7 @@ * who were very cooperative and answered my questions. */ +#include <linux/ethtool.h> #include <linux/signal.h> #include <linux/slab.h> #include <linux/module.h> @@ -438,9 +439,11 @@ static void usb_8dev_rx_err_msg(struct usb_8dev_priv *priv, if (rx_errors) stats->rx_errors++; - - cf->data[6] = txerr; - cf->data[7] = rxerr; + if (priv->can.state != CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_CNT; + cf->data[6] = txerr; + cf->data[7] = rxerr; + } priv->bec.txerr = txerr; priv->bec.rxerr = rxerr; @@ -868,8 +871,12 @@ static const struct net_device_ops usb_8dev_netdev_ops = { .ndo_change_mtu = can_change_mtu, }; +static const struct ethtool_ops usb_8dev_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + static const struct can_bittiming_const usb_8dev_bittiming_const = { - .name = "usb_8dev", + .name = KBUILD_MODNAME, .tseg1_min = 1, .tseg1_max = 16, .tseg2_min = 1, @@ -925,6 +932,7 @@ static int usb_8dev_probe(struct usb_interface *intf, CAN_CTRLMODE_CC_LEN8_DLC; netdev->netdev_ops = &usb_8dev_netdev_ops; + netdev->ethtool_ops = &usb_8dev_ethtool_ops; netdev->flags |= IFF_ECHO; /* we support local echo */ @@ -995,7 +1003,7 @@ static void usb_8dev_disconnect(struct usb_interface *intf) } static struct usb_driver usb_8dev_driver = { - .name = "usb_8dev", + .name = KBUILD_MODNAME, .probe = usb_8dev_probe, .disconnect = usb_8dev_disconnect, .id_table = usb_8dev_table, |