diff options
Diffstat (limited to 'drivers/net/can/usb/gs_usb.c')
-rw-r--r-- | drivers/net/can/usb/gs_usb.c | 1068 |
1 files changed, 738 insertions, 330 deletions
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index a4b4b742c80c..9c2c25fde3d1 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -9,25 +9,45 @@ * Many thanks to all socketcan devs! */ +#include <linux/bitfield.h> +#include <linux/clocksource.h> +#include <linux/ethtool.h> #include <linux/init.h> -#include <linux/signal.h> #include <linux/module.h> #include <linux/netdevice.h> +#include <linux/signal.h> +#include <linux/timecounter.h> +#include <linux/units.h> #include <linux/usb.h> +#include <linux/workqueue.h> #include <linux/can.h> #include <linux/can/dev.h> #include <linux/can/error.h> /* Device specific constants */ -#define USB_GSUSB_1_VENDOR_ID 0x1d50 -#define USB_GSUSB_1_PRODUCT_ID 0x606f +#define USB_GS_USB_1_VENDOR_ID 0x1d50 +#define USB_GS_USB_1_PRODUCT_ID 0x606f -#define USB_CANDLELIGHT_VENDOR_ID 0x1209 +#define USB_CANDLELIGHT_VENDOR_ID 0x1209 #define USB_CANDLELIGHT_PRODUCT_ID 0x2323 -#define GSUSB_ENDPOINT_IN 1 -#define GSUSB_ENDPOINT_OUT 2 +#define USB_CES_CANEXT_FD_VENDOR_ID 0x1cd2 +#define USB_CES_CANEXT_FD_PRODUCT_ID 0x606f + +#define USB_ABE_CANDEBUGGER_FD_VENDOR_ID 0x16d0 +#define USB_ABE_CANDEBUGGER_FD_PRODUCT_ID 0x10b8 + +#define GS_USB_ENDPOINT_IN 1 +#define GS_USB_ENDPOINT_OUT 2 + +/* Timestamp 32 bit timer runs at 1 MHz (1 µs tick). Worker accounts + * for timer overflow (will be after ~71 minutes) + */ +#define GS_USB_TIMESTAMP_TIMER_HZ (1 * HZ_PER_MHZ) +#define GS_USB_TIMESTAMP_WORK_DELAY_SEC 1800 +static_assert(GS_USB_TIMESTAMP_WORK_DELAY_SEC < + CYCLECOUNTER_MASK(32) / GS_USB_TIMESTAMP_TIMER_HZ / 2); /* Device specific constants */ enum gs_usb_breq { @@ -39,6 +59,13 @@ enum gs_usb_breq { GS_USB_BREQ_DEVICE_CONFIG, GS_USB_BREQ_TIMESTAMP, GS_USB_BREQ_IDENTIFY, + GS_USB_BREQ_GET_USER_ID, + GS_USB_BREQ_QUIRK_CANTACT_PRO_DATA_BITTIMING = GS_USB_BREQ_GET_USER_ID, + GS_USB_BREQ_SET_USER_ID, + GS_USB_BREQ_DATA_BITTIMING, + GS_USB_BREQ_BT_CONST_EXT, + GS_USB_BREQ_SET_TERMINATION, + GS_USB_BREQ_GET_TERMINATION, }; enum gs_can_mode { @@ -62,85 +89,185 @@ enum gs_can_identify_mode { GS_CAN_IDENTIFY_ON }; +enum gs_can_termination_state { + GS_CAN_TERMINATION_STATE_OFF = 0, + GS_CAN_TERMINATION_STATE_ON +}; + +#define GS_USB_TERMINATION_DISABLED CAN_TERMINATION_DISABLED +#define GS_USB_TERMINATION_ENABLED 120 + /* data types passed between host and device */ + +/* The firmware on the original USB2CAN by Geschwister Schneider + * Technologie Entwicklungs- und Vertriebs UG exchanges all data + * between the host and the device in host byte order. This is done + * with the struct gs_host_config::byte_order member, which is sent + * first to indicate the desired byte order. + * + * The widely used open source firmware candleLight doesn't support + * this feature and exchanges the data in little endian byte order. + */ struct gs_host_config { - u32 byte_order; + __le32 byte_order; } __packed; -/* All data exchanged between host and device is exchanged in host byte order, - * thanks to the struct gs_host_config byte_order member, which is sent first - * to indicate the desired byte order. - */ struct gs_device_config { u8 reserved1; u8 reserved2; u8 reserved3; u8 icount; - u32 sw_version; - u32 hw_version; + __le32 sw_version; + __le32 hw_version; } __packed; -#define GS_CAN_MODE_NORMAL 0 -#define GS_CAN_MODE_LISTEN_ONLY BIT(0) -#define GS_CAN_MODE_LOOP_BACK BIT(1) -#define GS_CAN_MODE_TRIPLE_SAMPLE BIT(2) -#define GS_CAN_MODE_ONE_SHOT BIT(3) +#define GS_CAN_MODE_NORMAL 0 +#define GS_CAN_MODE_LISTEN_ONLY BIT(0) +#define GS_CAN_MODE_LOOP_BACK BIT(1) +#define GS_CAN_MODE_TRIPLE_SAMPLE BIT(2) +#define GS_CAN_MODE_ONE_SHOT BIT(3) +#define GS_CAN_MODE_HW_TIMESTAMP BIT(4) +/* GS_CAN_FEATURE_IDENTIFY BIT(5) */ +/* GS_CAN_FEATURE_USER_ID BIT(6) */ +#define GS_CAN_MODE_PAD_PKTS_TO_MAX_PKT_SIZE BIT(7) +#define GS_CAN_MODE_FD BIT(8) +/* GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9) */ +/* GS_CAN_FEATURE_BT_CONST_EXT BIT(10) */ +/* GS_CAN_FEATURE_TERMINATION BIT(11) */ struct gs_device_mode { - u32 mode; - u32 flags; + __le32 mode; + __le32 flags; } __packed; struct gs_device_state { - u32 state; - u32 rxerr; - u32 txerr; + __le32 state; + __le32 rxerr; + __le32 txerr; } __packed; struct gs_device_bittiming { - u32 prop_seg; - u32 phase_seg1; - u32 phase_seg2; - u32 sjw; - u32 brp; + __le32 prop_seg; + __le32 phase_seg1; + __le32 phase_seg2; + __le32 sjw; + __le32 brp; } __packed; struct gs_identify_mode { - u32 mode; + __le32 mode; } __packed; -#define GS_CAN_FEATURE_LISTEN_ONLY BIT(0) -#define GS_CAN_FEATURE_LOOP_BACK BIT(1) -#define GS_CAN_FEATURE_TRIPLE_SAMPLE BIT(2) -#define GS_CAN_FEATURE_ONE_SHOT BIT(3) -#define GS_CAN_FEATURE_HW_TIMESTAMP BIT(4) -#define GS_CAN_FEATURE_IDENTIFY BIT(5) +struct gs_device_termination_state { + __le32 state; +} __packed; + +#define GS_CAN_FEATURE_LISTEN_ONLY BIT(0) +#define GS_CAN_FEATURE_LOOP_BACK BIT(1) +#define GS_CAN_FEATURE_TRIPLE_SAMPLE BIT(2) +#define GS_CAN_FEATURE_ONE_SHOT BIT(3) +#define GS_CAN_FEATURE_HW_TIMESTAMP BIT(4) +#define GS_CAN_FEATURE_IDENTIFY BIT(5) +#define GS_CAN_FEATURE_USER_ID BIT(6) +#define GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE BIT(7) +#define GS_CAN_FEATURE_FD BIT(8) +#define GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9) +#define GS_CAN_FEATURE_BT_CONST_EXT BIT(10) +#define GS_CAN_FEATURE_TERMINATION BIT(11) +#define GS_CAN_FEATURE_MASK GENMASK(11, 0) + +/* internal quirks - keep in GS_CAN_FEATURE space for now */ + +/* CANtact Pro original firmware: + * BREQ DATA_BITTIMING overlaps with GET_USER_ID + */ +#define GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO BIT(31) struct gs_device_bt_const { - u32 feature; - u32 fclk_can; - u32 tseg1_min; - u32 tseg1_max; - u32 tseg2_min; - u32 tseg2_max; - u32 sjw_max; - u32 brp_min; - u32 brp_max; - u32 brp_inc; + __le32 feature; + __le32 fclk_can; + __le32 tseg1_min; + __le32 tseg1_max; + __le32 tseg2_min; + __le32 tseg2_max; + __le32 sjw_max; + __le32 brp_min; + __le32 brp_max; + __le32 brp_inc; } __packed; -#define GS_CAN_FLAG_OVERFLOW 1 +struct gs_device_bt_const_extended { + __le32 feature; + __le32 fclk_can; + __le32 tseg1_min; + __le32 tseg1_max; + __le32 tseg2_min; + __le32 tseg2_max; + __le32 sjw_max; + __le32 brp_min; + __le32 brp_max; + __le32 brp_inc; + + __le32 dtseg1_min; + __le32 dtseg1_max; + __le32 dtseg2_min; + __le32 dtseg2_max; + __le32 dsjw_max; + __le32 dbrp_min; + __le32 dbrp_max; + __le32 dbrp_inc; +} __packed; + +#define GS_CAN_FLAG_OVERFLOW BIT(0) +#define GS_CAN_FLAG_FD BIT(1) +#define GS_CAN_FLAG_BRS BIT(2) +#define GS_CAN_FLAG_ESI BIT(3) + +struct classic_can { + u8 data[8]; +} __packed; + +struct classic_can_ts { + u8 data[8]; + __le32 timestamp_us; +} __packed; + +struct classic_can_quirk { + u8 data[8]; + u8 quirk; +} __packed; + +struct canfd { + u8 data[64]; +} __packed; + +struct canfd_ts { + u8 data[64]; + __le32 timestamp_us; +} __packed; + +struct canfd_quirk { + u8 data[64]; + u8 quirk; +} __packed; struct gs_host_frame { u32 echo_id; - u32 can_id; + __le32 can_id; u8 can_dlc; u8 channel; u8 flags; u8 reserved; - u8 data[8]; + union { + DECLARE_FLEX_ARRAY(struct classic_can, classic_can); + DECLARE_FLEX_ARRAY(struct classic_can_ts, classic_can_ts); + DECLARE_FLEX_ARRAY(struct classic_can_quirk, classic_can_quirk); + DECLARE_FLEX_ARRAY(struct canfd, canfd); + DECLARE_FLEX_ARRAY(struct canfd_ts, canfd_ts); + DECLARE_FLEX_ARRAY(struct canfd_quirk, canfd_quirk); + }; } __packed; /* The GS USB devices make use of the same flags and masks as in * linux/can.h and linux/can/error.h, and no additional mapping is necessary. @@ -151,9 +278,9 @@ struct gs_host_frame { /* Only launch a max of GS_MAX_RX_URBS usb requests at a time. */ #define GS_MAX_RX_URBS 30 /* Maximum number of interfaces the driver supports per device. - * Current hardware only supports 2 interfaces. The future may vary. + * Current hardware only supports 3 interfaces. The future may vary. */ -#define GS_MAX_INTF 2 +#define GS_MAX_INTF 3 struct gs_tx_context { struct gs_can *dev; @@ -169,9 +296,18 @@ struct gs_can { struct usb_device *udev; struct usb_interface *iface; - struct can_bittiming_const bt_const; + struct can_bittiming_const bt_const, data_bt_const; unsigned int channel; /* channel number */ + /* time counter for hardware timestamps */ + struct cyclecounter cc; + struct timecounter tc; + spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */ + struct delayed_work timestamp; + + u32 feature; + unsigned int hf_size_tx; + /* This lock prevents a race condition between xmit and receive. */ spinlock_t tx_ctx_lock; struct gs_tx_context tx_context[GS_MAX_TX_URBS]; @@ -184,8 +320,9 @@ struct gs_can { struct gs_usb { struct gs_can *canch[GS_MAX_INTF]; struct usb_anchor rx_submitted; - atomic_t active_channels; struct usb_device *udev; + unsigned int hf_size_rx; + u8 active_channels; }; /* 'allocate' a tx context. @@ -235,31 +372,109 @@ static struct gs_tx_context *gs_get_tx_context(struct gs_can *dev, return NULL; } -static int gs_cmd_reset(struct gs_can *gsdev) +static int gs_cmd_reset(struct gs_can *dev) { - struct gs_device_mode *dm; - struct usb_interface *intf = gsdev->iface; + struct gs_device_mode dm = { + .mode = GS_CAN_MODE_RESET, + }; + + return usb_control_msg_send(interface_to_usbdev(dev->iface), 0, + GS_USB_BREQ_MODE, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + dev->channel, 0, &dm, sizeof(dm), 1000, + GFP_KERNEL); +} + +static inline int gs_usb_get_timestamp(const struct gs_can *dev, + u32 *timestamp_p) +{ + __le32 timestamp; int rc; - dm = kzalloc(sizeof(*dm), GFP_KERNEL); - if (!dm) - return -ENOMEM; + rc = usb_control_msg_recv(interface_to_usbdev(dev->iface), 0, + GS_USB_BREQ_TIMESTAMP, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + dev->channel, 0, + ×tamp, sizeof(timestamp), + USB_CTRL_GET_TIMEOUT, + GFP_KERNEL); + if (rc) + return rc; - dm->mode = GS_CAN_MODE_RESET; + *timestamp_p = le32_to_cpu(timestamp); - rc = usb_control_msg(interface_to_usbdev(intf), - usb_sndctrlpipe(interface_to_usbdev(intf), 0), - GS_USB_BREQ_MODE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - gsdev->channel, - 0, - dm, - sizeof(*dm), - 1000); + return 0; +} - kfree(dm); +static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev->tc_lock) +{ + struct gs_can *dev = container_of(cc, struct gs_can, cc); + u32 timestamp = 0; + int err; + + lockdep_assert_held(&dev->tc_lock); + + /* drop lock for synchronous USB transfer */ + spin_unlock_bh(&dev->tc_lock); + err = gs_usb_get_timestamp(dev, ×tamp); + spin_lock_bh(&dev->tc_lock); + if (err) + netdev_err(dev->netdev, + "Error %d while reading timestamp. HW timestamps may be inaccurate.", + err); + + return timestamp; +} - return rc; +static void gs_usb_timestamp_work(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct gs_can *dev; + + dev = container_of(delayed_work, struct gs_can, timestamp); + spin_lock_bh(&dev->tc_lock); + timecounter_read(&dev->tc); + spin_unlock_bh(&dev->tc_lock); + + schedule_delayed_work(&dev->timestamp, + GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ); +} + +static void gs_usb_skb_set_timestamp(struct gs_can *dev, + struct sk_buff *skb, u32 timestamp) +{ + struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb); + u64 ns; + + spin_lock_bh(&dev->tc_lock); + ns = timecounter_cyc2time(&dev->tc, timestamp); + spin_unlock_bh(&dev->tc_lock); + + hwtstamps->hwtstamp = ns_to_ktime(ns); +} + +static void gs_usb_timestamp_init(struct gs_can *dev) +{ + struct cyclecounter *cc = &dev->cc; + + cc->read = gs_usb_timestamp_read; + cc->mask = CYCLECOUNTER_MASK(32); + cc->shift = 32 - bits_per(NSEC_PER_SEC / GS_USB_TIMESTAMP_TIMER_HZ); + cc->mult = clocksource_hz2mult(GS_USB_TIMESTAMP_TIMER_HZ, cc->shift); + + spin_lock_init(&dev->tc_lock); + spin_lock_bh(&dev->tc_lock); + timecounter_init(&dev->tc, &dev->cc, ktime_get_real_ns()); + spin_unlock_bh(&dev->tc_lock); + + INIT_DELAYED_WORK(&dev->timestamp, gs_usb_timestamp_work); + schedule_delayed_work(&dev->timestamp, + GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ); +} + +static void gs_usb_timestamp_stop(struct gs_can *dev) +{ + cancel_delayed_work_sync(&dev->timestamp); } static void gs_update_state(struct gs_can *dev, struct can_frame *cf) @@ -287,6 +502,24 @@ static void gs_update_state(struct gs_can *dev, struct can_frame *cf) } } +static void gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb, + const struct gs_host_frame *hf) +{ + u32 timestamp; + + if (!(dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)) + return; + + if (hf->flags & GS_CAN_FLAG_FD) + timestamp = le32_to_cpu(hf->canfd_ts->timestamp_us); + else + timestamp = le32_to_cpu(hf->classic_can_ts->timestamp_us); + + gs_usb_skb_set_timestamp(dev, skb, timestamp); + + return; +} + static void gs_usb_receive_bulk_callback(struct urb *urb) { struct gs_usb *usbcan = urb->context; @@ -297,6 +530,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) struct gs_host_frame *hf = urb->transfer_buffer; struct gs_tx_context *txc; struct can_frame *cf; + struct canfd_frame *cfd; struct sk_buff *skb; BUG_ON(!usbcan); @@ -314,7 +548,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) /* device reports out of range channel id */ if (hf->channel >= GS_MAX_INTF) - goto resubmit_urb; + goto device_detach; dev = usbcan->canch[hf->channel]; @@ -325,18 +559,35 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) return; if (hf->echo_id == -1) { /* normal rx */ - skb = alloc_can_skb(dev->netdev, &cf); - if (!skb) - return; + if (hf->flags & GS_CAN_FLAG_FD) { + skb = alloc_canfd_skb(dev->netdev, &cfd); + if (!skb) + return; + + cfd->can_id = le32_to_cpu(hf->can_id); + cfd->len = can_fd_dlc2len(hf->can_dlc); + if (hf->flags & GS_CAN_FLAG_BRS) + cfd->flags |= CANFD_BRS; + if (hf->flags & GS_CAN_FLAG_ESI) + cfd->flags |= CANFD_ESI; + + memcpy(cfd->data, hf->canfd->data, cfd->len); + } else { + skb = alloc_can_skb(dev->netdev, &cf); + if (!skb) + return; - cf->can_id = hf->can_id; + cf->can_id = le32_to_cpu(hf->can_id); + can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); - cf->can_dlc = get_can_dlc(hf->can_dlc); - memcpy(cf->data, hf->data, 8); + memcpy(cf->data, hf->classic_can->data, 8); + + /* ERROR frames tell us information about the controller */ + if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) + gs_update_state(dev, cf); + } - /* ERROR frames tell us information about the controller */ - if (hf->can_id & CAN_ERR_FLAG) - gs_update_state(dev, cf); + gs_usb_set_timestamp(dev, skb, hf); netdev->stats.rx_packets++; netdev->stats.rx_bytes += hf->can_dlc; @@ -345,25 +596,27 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) } else { /* echo_id == hf->echo_id */ if (hf->echo_id >= GS_MAX_TX_URBS) { netdev_err(netdev, - "Unexpected out of range echo id %d\n", + "Unexpected out of range echo id %u\n", hf->echo_id); goto resubmit_urb; } - netdev->stats.tx_packets++; - netdev->stats.tx_bytes += hf->can_dlc; - txc = gs_get_tx_context(dev, hf->echo_id); /* bad devices send bad echo_ids. */ if (!txc) { netdev_err(netdev, - "Unexpected unused echo id %d\n", + "Unexpected unused echo id %u\n", hf->echo_id); goto resubmit_urb; } - can_get_echo_skb(netdev, hf->echo_id); + skb = dev->can.echo_skb[hf->echo_id]; + gs_usb_set_timestamp(dev, skb, hf); + + netdev->stats.tx_packets++; + netdev->stats.tx_bytes += can_get_echo_skb(netdev, hf->echo_id, + NULL); gs_free_tx_context(txc); @@ -378,7 +631,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) goto resubmit_urb; cf->can_id |= CAN_ERR_CRTL; - cf->can_dlc = CAN_ERR_DLC; + cf->len = CAN_ERR_DLC; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; stats->rx_over_errors++; stats->rx_errors++; @@ -386,19 +639,16 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) } resubmit_urb: - usb_fill_bulk_urb(urb, - usbcan->udev, - usb_rcvbulkpipe(usbcan->udev, GSUSB_ENDPOINT_IN), - hf, - sizeof(struct gs_host_frame), - gs_usb_receive_bulk_callback, - usbcan - ); + usb_fill_bulk_urb(urb, usbcan->udev, + usb_rcvbulkpipe(usbcan->udev, GS_USB_ENDPOINT_IN), + hf, dev->parent->hf_size_rx, + gs_usb_receive_bulk_callback, usbcan); rc = usb_submit_urb(urb, GFP_ATOMIC); /* USB failure take down all interfaces */ if (rc == -ENODEV) { + device_detach: for (rc = 0; rc < GS_MAX_INTF; rc++) { if (usbcan->canch[rc]) netif_device_detach(usbcan->canch[rc]->netdev); @@ -410,38 +660,44 @@ static int gs_usb_set_bittiming(struct net_device *netdev) { struct gs_can *dev = netdev_priv(netdev); struct can_bittiming *bt = &dev->can.bittiming; - struct usb_interface *intf = dev->iface; - int rc; - struct gs_device_bittiming *dbt; - - dbt = kmalloc(sizeof(*dbt), GFP_KERNEL); - if (!dbt) - return -ENOMEM; - - dbt->prop_seg = bt->prop_seg; - dbt->phase_seg1 = bt->phase_seg1; - dbt->phase_seg2 = bt->phase_seg2; - dbt->sjw = bt->sjw; - dbt->brp = bt->brp; + struct gs_device_bittiming dbt = { + .prop_seg = cpu_to_le32(bt->prop_seg), + .phase_seg1 = cpu_to_le32(bt->phase_seg1), + .phase_seg2 = cpu_to_le32(bt->phase_seg2), + .sjw = cpu_to_le32(bt->sjw), + .brp = cpu_to_le32(bt->brp), + }; /* request bit timings */ - rc = usb_control_msg(interface_to_usbdev(intf), - usb_sndctrlpipe(interface_to_usbdev(intf), 0), - GS_USB_BREQ_BITTIMING, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - dev->channel, - 0, - dbt, - sizeof(*dbt), - 1000); - - kfree(dbt); - - if (rc < 0) - dev_err(netdev->dev.parent, "Couldn't set bittimings (err=%d)", - rc); + return usb_control_msg_send(interface_to_usbdev(dev->iface), 0, + GS_USB_BREQ_BITTIMING, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + dev->channel, 0, &dbt, sizeof(dbt), 1000, + GFP_KERNEL); +} - return (rc > 0) ? 0 : rc; +static int gs_usb_set_data_bittiming(struct net_device *netdev) +{ + struct gs_can *dev = netdev_priv(netdev); + struct can_bittiming *bt = &dev->can.data_bittiming; + struct gs_device_bittiming dbt = { + .prop_seg = cpu_to_le32(bt->prop_seg), + .phase_seg1 = cpu_to_le32(bt->phase_seg1), + .phase_seg2 = cpu_to_le32(bt->phase_seg2), + .sjw = cpu_to_le32(bt->sjw), + .brp = cpu_to_le32(bt->brp), + }; + u8 request = GS_USB_BREQ_DATA_BITTIMING; + + if (dev->feature & GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO) + request = GS_USB_BREQ_QUIRK_CANTACT_PRO_DATA_BITTIMING; + + /* request data bit timings */ + return usb_control_msg_send(interface_to_usbdev(dev->iface), 0, + request, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + dev->channel, 0, &dbt, sizeof(dbt), 1000, + GFP_KERNEL); } static void gs_usb_xmit_callback(struct urb *urb) @@ -451,12 +707,7 @@ static void gs_usb_xmit_callback(struct urb *urb) struct net_device *netdev = dev->netdev; if (urb->status) - netdev_info(netdev, "usb xmit fail %d\n", txc->echo_id); - - usb_free_coherent(urb->dev, - urb->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); + netdev_info(netdev, "usb xmit fail %u\n", txc->echo_id); } static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, @@ -467,11 +718,12 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, struct urb *urb; struct gs_host_frame *hf; struct can_frame *cf; + struct canfd_frame *cfd; int rc; unsigned int idx; struct gs_tx_context *txc; - if (can_dropped_invalid_skb(netdev, skb)) + if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; /* find an empty context to keep track of transmission */ @@ -484,8 +736,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, if (!urb) goto nomem_urb; - hf = usb_alloc_coherent(dev->udev, sizeof(*hf), GFP_ATOMIC, - &urb->transfer_dma); + hf = kmalloc(dev->hf_size_tx, GFP_ATOMIC); if (!hf) { netdev_err(netdev, "No memory left for USB buffer\n"); goto nomem_hf; @@ -494,30 +745,45 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, idx = txc->echo_id; if (idx >= GS_MAX_TX_URBS) { - netdev_err(netdev, "Invalid tx context %d\n", idx); + netdev_err(netdev, "Invalid tx context %u\n", idx); goto badidx; } hf->echo_id = idx; hf->channel = dev->channel; + hf->flags = 0; + hf->reserved = 0; - cf = (struct can_frame *)skb->data; + if (can_is_canfd_skb(skb)) { + cfd = (struct canfd_frame *)skb->data; - hf->can_id = cf->can_id; - hf->can_dlc = cf->can_dlc; - memcpy(hf->data, cf->data, cf->can_dlc); + hf->can_id = cpu_to_le32(cfd->can_id); + hf->can_dlc = can_fd_len2dlc(cfd->len); + hf->flags |= GS_CAN_FLAG_FD; + if (cfd->flags & CANFD_BRS) + hf->flags |= GS_CAN_FLAG_BRS; + if (cfd->flags & CANFD_ESI) + hf->flags |= GS_CAN_FLAG_ESI; + + memcpy(hf->canfd->data, cfd->data, cfd->len); + } else { + cf = (struct can_frame *)skb->data; + + hf->can_id = cpu_to_le32(cf->can_id); + hf->can_dlc = can_get_cc_dlc(cf, dev->can.ctrlmode); + + memcpy(hf->classic_can->data, cf->data, cf->len); + } usb_fill_bulk_urb(urb, dev->udev, - usb_sndbulkpipe(dev->udev, GSUSB_ENDPOINT_OUT), - hf, - sizeof(*hf), - gs_usb_xmit_callback, - txc); + usb_sndbulkpipe(dev->udev, GS_USB_ENDPOINT_OUT), + hf, dev->hf_size_tx, + gs_usb_xmit_callback, txc); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags |= URB_FREE_BUFFER; usb_anchor_urb(urb, &dev->tx_submitted); - can_put_echo_skb(skb, netdev, idx); + can_put_echo_skb(skb, netdev, idx, 0); atomic_inc(&dev->active_tx_urbs); @@ -525,14 +791,10 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, if (unlikely(rc)) { /* usb send failed */ atomic_dec(&dev->active_tx_urbs); - can_free_echo_skb(netdev, idx); + can_free_echo_skb(netdev, idx, NULL); gs_free_tx_context(txc); usb_unanchor_urb(urb); - usb_free_coherent(dev->udev, - sizeof(*hf), - hf, - urb->transfer_dma); if (rc == -ENODEV) { netif_device_detach(netdev); @@ -552,10 +814,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; badidx: - usb_free_coherent(dev->udev, - sizeof(*hf), - hf, - urb->transfer_dma); + kfree(hf); nomem_hf: usb_free_urb(urb); @@ -570,15 +829,34 @@ static int gs_can_open(struct net_device *netdev) { struct gs_can *dev = netdev_priv(netdev); struct gs_usb *parent = dev->parent; - int rc, i; - struct gs_device_mode *dm; + struct gs_device_mode dm = { + .mode = cpu_to_le32(GS_CAN_MODE_START), + }; + struct gs_host_frame *hf; u32 ctrlmode; + u32 flags = 0; + int rc, i; rc = open_candev(netdev); if (rc) return rc; - if (atomic_add_return(1, &parent->active_channels) == 1) { + ctrlmode = dev->can.ctrlmode; + if (ctrlmode & CAN_CTRLMODE_FD) { + flags |= GS_CAN_MODE_FD; + + if (dev->feature & GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX) + dev->hf_size_tx = struct_size(hf, canfd_quirk, 1); + else + dev->hf_size_tx = struct_size(hf, canfd, 1); + } else { + if (dev->feature & GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX) + dev->hf_size_tx = struct_size(hf, classic_can_quirk, 1); + else + dev->hf_size_tx = struct_size(hf, classic_can, 1); + } + + if (!parent->active_channels) { for (i = 0; i < GS_MAX_RX_URBS; i++) { struct urb *urb; u8 *buf; @@ -589,10 +867,8 @@ static int gs_can_open(struct net_device *netdev) return -ENOMEM; /* alloc rx buffer */ - buf = usb_alloc_coherent(dev->udev, - sizeof(struct gs_host_frame), - GFP_KERNEL, - &urb->transfer_dma); + buf = kmalloc(dev->parent->hf_size_rx, + GFP_KERNEL); if (!buf) { netdev_err(netdev, "No memory left for USB buffer\n"); @@ -604,12 +880,11 @@ static int gs_can_open(struct net_device *netdev) usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, - GSUSB_ENDPOINT_IN), + GS_USB_ENDPOINT_IN), buf, - sizeof(struct gs_host_frame), - gs_usb_receive_bulk_callback, - parent); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + dev->parent->hf_size_rx, + gs_usb_receive_bulk_callback, parent); + urb->transfer_flags |= URB_FREE_BUFFER; usb_anchor_urb(urb, &parent->rx_submitted); @@ -619,8 +894,7 @@ static int gs_can_open(struct net_device *netdev) netif_device_detach(dev->netdev); netdev_err(netdev, - "usb_submit failed (err=%d)\n", - rc); + "usb_submit failed (err=%d)\n", rc); usb_unanchor_urb(urb); usb_free_urb(urb); @@ -634,51 +908,46 @@ static int gs_can_open(struct net_device *netdev) } } - dm = kmalloc(sizeof(*dm), GFP_KERNEL); - if (!dm) - return -ENOMEM; - /* flags */ - ctrlmode = dev->can.ctrlmode; - dm->flags = 0; - if (ctrlmode & CAN_CTRLMODE_LOOPBACK) - dm->flags |= GS_CAN_MODE_LOOP_BACK; + flags |= GS_CAN_MODE_LOOP_BACK; else if (ctrlmode & CAN_CTRLMODE_LISTENONLY) - dm->flags |= GS_CAN_MODE_LISTEN_ONLY; + flags |= GS_CAN_MODE_LISTEN_ONLY; /* Controller is not allowed to retry TX * this mode is unavailable on atmels uc3c hardware */ if (ctrlmode & CAN_CTRLMODE_ONE_SHOT) - dm->flags |= GS_CAN_MODE_ONE_SHOT; + flags |= GS_CAN_MODE_ONE_SHOT; if (ctrlmode & CAN_CTRLMODE_3_SAMPLES) - dm->flags |= GS_CAN_MODE_TRIPLE_SAMPLE; + flags |= GS_CAN_MODE_TRIPLE_SAMPLE; + + /* if hardware supports timestamps, enable it */ + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + flags |= GS_CAN_MODE_HW_TIMESTAMP; + + /* start polling timestamp */ + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + gs_usb_timestamp_init(dev); /* finally start device */ - dm->mode = GS_CAN_MODE_START; - rc = usb_control_msg(interface_to_usbdev(dev->iface), - usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0), - GS_USB_BREQ_MODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, - dev->channel, - 0, - dm, - sizeof(*dm), - 1000); - - if (rc < 0) { + dev->can.state = CAN_STATE_ERROR_ACTIVE; + dm.flags = cpu_to_le32(flags); + rc = usb_control_msg_send(interface_to_usbdev(dev->iface), 0, + GS_USB_BREQ_MODE, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + dev->channel, 0, &dm, sizeof(dm), 1000, + GFP_KERNEL); + if (rc) { netdev_err(netdev, "Couldn't start device (err=%d)\n", rc); - kfree(dm); + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + gs_usb_timestamp_stop(dev); + dev->can.state = CAN_STATE_STOPPED; return rc; } - kfree(dm); - - dev->can.state = CAN_STATE_ERROR_ACTIVE; - + parent->active_channels++; if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) netif_start_queue(netdev); @@ -693,9 +962,15 @@ static int gs_can_close(struct net_device *netdev) netif_stop_queue(netdev); + /* stop polling timestamp */ + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + gs_usb_timestamp_stop(dev); + /* Stop polling */ - if (atomic_dec_and_test(&parent->active_channels)) + parent->active_channels--; + if (!parent->active_channels) { usb_kill_anchored_urbs(&parent->rx_submitted); + } /* Stop sending URBs */ usb_kill_anchored_urbs(&dev->tx_submitted); @@ -718,58 +993,57 @@ static int gs_can_close(struct net_device *netdev) return 0; } +static int gs_can_eth_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + const struct gs_can *dev = netdev_priv(netdev); + + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + return can_eth_ioctl_hwts(netdev, ifr, cmd); + + return -EOPNOTSUPP; +} + static const struct net_device_ops gs_usb_netdev_ops = { .ndo_open = gs_can_open, .ndo_stop = gs_can_close, .ndo_start_xmit = gs_can_start_xmit, .ndo_change_mtu = can_change_mtu, + .ndo_eth_ioctl = gs_can_eth_ioctl, }; static int gs_usb_set_identify(struct net_device *netdev, bool do_identify) { struct gs_can *dev = netdev_priv(netdev); - struct gs_identify_mode *imode; - int rc; - - imode = kmalloc(sizeof(*imode), GFP_KERNEL); - - if (!imode) - return -ENOMEM; + struct gs_identify_mode imode; if (do_identify) - imode->mode = GS_CAN_IDENTIFY_ON; + imode.mode = cpu_to_le32(GS_CAN_IDENTIFY_ON); else - imode->mode = GS_CAN_IDENTIFY_OFF; - - rc = usb_control_msg(interface_to_usbdev(dev->iface), - usb_sndctrlpipe(interface_to_usbdev(dev->iface), - 0), - GS_USB_BREQ_IDENTIFY, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, - dev->channel, - 0, - imode, - sizeof(*imode), - 100); - - kfree(imode); - - return (rc > 0) ? 0 : rc; + imode.mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF); + + return usb_control_msg_send(interface_to_usbdev(dev->iface), 0, + GS_USB_BREQ_IDENTIFY, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + dev->channel, 0, &imode, sizeof(imode), 100, + GFP_KERNEL); } /* blink LED's for finding the this interface */ -static int gs_usb_set_phys_id(struct net_device *dev, +static int gs_usb_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) { + const struct gs_can *dev = netdev_priv(netdev); int rc = 0; + if (!(dev->feature & GS_CAN_FEATURE_IDENTIFY)) + return -EOPNOTSUPP; + switch (state) { case ETHTOOL_ID_ACTIVE: - rc = gs_usb_set_identify(dev, GS_CAN_IDENTIFY_ON); + rc = gs_usb_set_identify(netdev, GS_CAN_IDENTIFY_ON); break; case ETHTOOL_ID_INACTIVE: - rc = gs_usb_set_identify(dev, GS_CAN_IDENTIFY_OFF); + rc = gs_usb_set_identify(netdev, GS_CAN_IDENTIFY_OFF); break; default: break; @@ -778,8 +1052,67 @@ static int gs_usb_set_phys_id(struct net_device *dev, return rc; } +static int gs_usb_get_ts_info(struct net_device *netdev, + struct ethtool_ts_info *info) +{ + struct gs_can *dev = netdev_priv(netdev); + + /* report if device supports HW timestamps */ + if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + return can_ethtool_op_get_ts_info_hwts(netdev, info); + + return ethtool_op_get_ts_info(netdev, info); +} + static const struct ethtool_ops gs_usb_ethtool_ops = { .set_phys_id = gs_usb_set_phys_id, + .get_ts_info = gs_usb_get_ts_info, +}; + +static int gs_usb_get_termination(struct net_device *netdev, u16 *term) +{ + struct gs_can *dev = netdev_priv(netdev); + struct gs_device_termination_state term_state; + int rc; + + rc = usb_control_msg_recv(interface_to_usbdev(dev->iface), 0, + GS_USB_BREQ_GET_TERMINATION, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + dev->channel, 0, + &term_state, sizeof(term_state), 1000, + GFP_KERNEL); + if (rc) + return rc; + + if (term_state.state == cpu_to_le32(GS_CAN_TERMINATION_STATE_ON)) + *term = GS_USB_TERMINATION_ENABLED; + else + *term = GS_USB_TERMINATION_DISABLED; + + return 0; +} + +static int gs_usb_set_termination(struct net_device *netdev, u16 term) +{ + struct gs_can *dev = netdev_priv(netdev); + struct gs_device_termination_state term_state; + + if (term == GS_USB_TERMINATION_ENABLED) + term_state.state = cpu_to_le32(GS_CAN_TERMINATION_STATE_ON); + else + term_state.state = cpu_to_le32(GS_CAN_TERMINATION_STATE_OFF); + + return usb_control_msg_send(interface_to_usbdev(dev->iface), 0, + GS_USB_BREQ_SET_TERMINATION, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + dev->channel, 0, + &term_state, sizeof(term_state), 1000, + GFP_KERNEL); +} + +static const u16 gs_usb_termination_const[] = { + GS_USB_TERMINATION_DISABLED, + GS_USB_TERMINATION_ENABLED }; static struct gs_can *gs_make_candev(unsigned int channel, @@ -789,28 +1122,21 @@ static struct gs_can *gs_make_candev(unsigned int channel, struct gs_can *dev; struct net_device *netdev; int rc; - struct gs_device_bt_const *bt_const; - - bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL); - if (!bt_const) - return ERR_PTR(-ENOMEM); + struct gs_device_bt_const_extended bt_const_extended; + struct gs_device_bt_const bt_const; + u32 feature; /* fetch bit timing constants */ - rc = usb_control_msg(interface_to_usbdev(intf), - usb_rcvctrlpipe(interface_to_usbdev(intf), 0), - GS_USB_BREQ_BT_CONST, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - channel, - 0, - bt_const, - sizeof(*bt_const), - 1000); - - if (rc < 0) { + rc = usb_control_msg_recv(interface_to_usbdev(intf), 0, + GS_USB_BREQ_BT_CONST, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + channel, 0, &bt_const, sizeof(bt_const), 1000, + GFP_KERNEL); + + if (rc) { dev_err(&intf->dev, - "Couldn't get bit timing const for channel (err=%d)\n", - rc); - kfree(bt_const); + "Couldn't get bit timing const for channel %d (%pe)\n", + channel, ERR_PTR(rc)); return ERR_PTR(rc); } @@ -818,26 +1144,26 @@ static struct gs_can *gs_make_candev(unsigned int channel, netdev = alloc_candev(sizeof(struct gs_can), GS_MAX_TX_URBS); if (!netdev) { dev_err(&intf->dev, "Couldn't allocate candev\n"); - kfree(bt_const); return ERR_PTR(-ENOMEM); } 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 settup */ - strcpy(dev->bt_const.name, "gs_usb"); - dev->bt_const.tseg1_min = bt_const->tseg1_min; - dev->bt_const.tseg1_max = bt_const->tseg1_max; - dev->bt_const.tseg2_min = bt_const->tseg2_min; - dev->bt_const.tseg2_max = bt_const->tseg2_max; - dev->bt_const.sjw_max = bt_const->sjw_max; - dev->bt_const.brp_min = bt_const->brp_min; - dev->bt_const.brp_max = bt_const->brp_max; - dev->bt_const.brp_inc = bt_const->brp_inc; + /* dev setup */ + 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); + dev->bt_const.tseg2_max = le32_to_cpu(bt_const.tseg2_max); + dev->bt_const.sjw_max = le32_to_cpu(bt_const.sjw_max); + dev->bt_const.brp_min = le32_to_cpu(bt_const.brp_min); + dev->bt_const.brp_max = le32_to_cpu(bt_const.brp_max); + dev->bt_const.brp_inc = le32_to_cpu(bt_const.brp_inc); dev->udev = interface_to_usbdev(intf); dev->iface = intf; @@ -852,42 +1178,126 @@ static struct gs_can *gs_make_candev(unsigned int channel, dev->tx_context[rc].echo_id = GS_MAX_TX_URBS; } - /* can settup */ + /* can setup */ dev->can.state = CAN_STATE_STOPPED; - dev->can.clock.freq = bt_const->fclk_can; + dev->can.clock.freq = le32_to_cpu(bt_const.fclk_can); dev->can.bittiming_const = &dev->bt_const; dev->can.do_set_bittiming = gs_usb_set_bittiming; - dev->can.ctrlmode_supported = 0; + dev->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC; - if (bt_const->feature & GS_CAN_FEATURE_LISTEN_ONLY) + feature = le32_to_cpu(bt_const.feature); + dev->feature = FIELD_GET(GS_CAN_FEATURE_MASK, feature); + if (feature & GS_CAN_FEATURE_LISTEN_ONLY) dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY; - if (bt_const->feature & GS_CAN_FEATURE_LOOP_BACK) + if (feature & GS_CAN_FEATURE_LOOP_BACK) dev->can.ctrlmode_supported |= CAN_CTRLMODE_LOOPBACK; - if (bt_const->feature & GS_CAN_FEATURE_TRIPLE_SAMPLE) + if (feature & GS_CAN_FEATURE_TRIPLE_SAMPLE) dev->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; - if (bt_const->feature & GS_CAN_FEATURE_ONE_SHOT) + if (feature & GS_CAN_FEATURE_ONE_SHOT) dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; - SET_NETDEV_DEV(netdev, &intf->dev); + if (feature & GS_CAN_FEATURE_FD) { + dev->can.ctrlmode_supported |= CAN_CTRLMODE_FD; + /* The data bit timing will be overwritten, if + * GS_CAN_FEATURE_BT_CONST_EXT is set. + */ + dev->can.data_bittiming_const = &dev->bt_const; + dev->can.do_set_data_bittiming = gs_usb_set_data_bittiming; + } + + if (feature & GS_CAN_FEATURE_TERMINATION) { + rc = gs_usb_get_termination(netdev, &dev->can.termination); + if (rc) { + dev->feature &= ~GS_CAN_FEATURE_TERMINATION; + + dev_info(&intf->dev, + "Disabling termination support for channel %d (%pe)\n", + channel, ERR_PTR(rc)); + } else { + dev->can.termination_const = gs_usb_termination_const; + dev->can.termination_const_cnt = ARRAY_SIZE(gs_usb_termination_const); + dev->can.do_set_termination = gs_usb_set_termination; + } + } + + /* The CANtact Pro from LinkLayer Labs is based on the + * LPC54616 µC, which is affected by the NXP LPC USB transfer + * erratum. However, the current firmware (version 2) doesn't + * set the GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX bit. Set the + * feature GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX to workaround + * this issue. + * + * For the GS_USB_BREQ_DATA_BITTIMING USB control message the + * CANtact Pro firmware uses a request value, which is already + * used by the candleLight firmware for a different purpose + * (GS_USB_BREQ_GET_USER_ID). Set the feature + * GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO to workaround this + * issue. + */ + if (dev->udev->descriptor.idVendor == cpu_to_le16(USB_GS_USB_1_VENDOR_ID) && + dev->udev->descriptor.idProduct == cpu_to_le16(USB_GS_USB_1_PRODUCT_ID) && + dev->udev->manufacturer && dev->udev->product && + !strcmp(dev->udev->manufacturer, "LinkLayer Labs") && + !strcmp(dev->udev->product, "CANtact Pro") && + (le32_to_cpu(dconf->sw_version) <= 2)) + dev->feature |= GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX | + GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO; + + /* GS_CAN_FEATURE_IDENTIFY is only supported for sw_version > 1 */ + if (!(le32_to_cpu(dconf->sw_version) > 1 && + feature & GS_CAN_FEATURE_IDENTIFY)) + dev->feature &= ~GS_CAN_FEATURE_IDENTIFY; + + /* fetch extended bit timing constants if device has feature + * GS_CAN_FEATURE_FD and GS_CAN_FEATURE_BT_CONST_EXT + */ + if (feature & GS_CAN_FEATURE_FD && + feature & GS_CAN_FEATURE_BT_CONST_EXT) { + rc = usb_control_msg_recv(interface_to_usbdev(intf), 0, + GS_USB_BREQ_BT_CONST_EXT, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + channel, 0, &bt_const_extended, + sizeof(bt_const_extended), + 1000, GFP_KERNEL); + if (rc) { + dev_err(&intf->dev, + "Couldn't get extended bit timing const for channel %d (%pe)\n", + channel, ERR_PTR(rc)); + goto out_free_candev; + } - if (dconf->sw_version > 1) - if (bt_const->feature & GS_CAN_FEATURE_IDENTIFY) - netdev->ethtool_ops = &gs_usb_ethtool_ops; + 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); + dev->data_bt_const.tseg2_max = le32_to_cpu(bt_const_extended.dtseg2_max); + dev->data_bt_const.sjw_max = le32_to_cpu(bt_const_extended.dsjw_max); + dev->data_bt_const.brp_min = le32_to_cpu(bt_const_extended.dbrp_min); + dev->data_bt_const.brp_max = le32_to_cpu(bt_const_extended.dbrp_max); + dev->data_bt_const.brp_inc = le32_to_cpu(bt_const_extended.dbrp_inc); + + dev->can.data_bittiming_const = &dev->data_bt_const; + } - kfree(bt_const); + SET_NETDEV_DEV(netdev, &intf->dev); rc = register_candev(dev->netdev); if (rc) { - free_candev(dev->netdev); - dev_err(&intf->dev, "Couldn't register candev (err=%d)\n", rc); - return ERR_PTR(rc); + dev_err(&intf->dev, + "Couldn't register candev for channel %d (%pe)\n", + channel, ERR_PTR(rc)); + goto out_free_candev; } return dev; + + out_free_candev: + free_candev(dev->netdev); + return ERR_PTR(rc); } static void gs_destroy_candev(struct gs_can *dev) @@ -900,84 +1310,64 @@ static void gs_destroy_candev(struct gs_can *dev) static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { + struct usb_device *udev = interface_to_usbdev(intf); + struct gs_host_frame *hf; struct gs_usb *dev; - int rc = -ENOMEM; + struct gs_host_config hconf = { + .byte_order = cpu_to_le32(0x0000beef), + }; + struct gs_device_config dconf; unsigned int icount, i; - struct gs_host_config *hconf; - struct gs_device_config *dconf; - - hconf = kmalloc(sizeof(*hconf), GFP_KERNEL); - if (!hconf) - return -ENOMEM; - - hconf->byte_order = 0x0000beef; + int rc; /* send host config */ - rc = usb_control_msg(interface_to_usbdev(intf), - usb_sndctrlpipe(interface_to_usbdev(intf), 0), - GS_USB_BREQ_HOST_FORMAT, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 1, - intf->cur_altsetting->desc.bInterfaceNumber, - hconf, - sizeof(*hconf), - 1000); - - kfree(hconf); - - if (rc < 0) { - dev_err(&intf->dev, "Couldn't send data format (err=%d)\n", - rc); + rc = usb_control_msg_send(udev, 0, + GS_USB_BREQ_HOST_FORMAT, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 1, intf->cur_altsetting->desc.bInterfaceNumber, + &hconf, sizeof(hconf), 1000, + GFP_KERNEL); + if (rc) { + dev_err(&intf->dev, "Couldn't send data format (err=%d)\n", rc); return rc; } - dconf = kmalloc(sizeof(*dconf), GFP_KERNEL); - if (!dconf) - return -ENOMEM; - /* read device config */ - rc = usb_control_msg(interface_to_usbdev(intf), - usb_rcvctrlpipe(interface_to_usbdev(intf), 0), - GS_USB_BREQ_DEVICE_CONFIG, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 1, - intf->cur_altsetting->desc.bInterfaceNumber, - dconf, - sizeof(*dconf), - 1000); - if (rc < 0) { + rc = usb_control_msg_recv(udev, 0, + GS_USB_BREQ_DEVICE_CONFIG, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 1, intf->cur_altsetting->desc.bInterfaceNumber, + &dconf, sizeof(dconf), 1000, + GFP_KERNEL); + if (rc) { dev_err(&intf->dev, "Couldn't get device config: (err=%d)\n", rc); - kfree(dconf); return rc; } - icount = dconf->icount + 1; - dev_info(&intf->dev, "Configuring for %d interfaces\n", icount); + icount = dconf.icount + 1; + dev_info(&intf->dev, "Configuring for %u interfaces\n", icount); if (icount > GS_MAX_INTF) { dev_err(&intf->dev, - "Driver cannot handle more that %d CAN interfaces\n", + "Driver cannot handle more that %u CAN interfaces\n", GS_MAX_INTF); - kfree(dconf); return -EINVAL; } dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - kfree(dconf); + if (!dev) return -ENOMEM; - } init_usb_anchor(&dev->rx_submitted); - atomic_set(&dev->active_channels, 0); - usb_set_intfdata(intf, dev); - dev->udev = interface_to_usbdev(intf); + dev->udev = udev; for (i = 0; i < icount; i++) { - dev->canch[i] = gs_make_candev(i, intf, dconf); + unsigned int hf_size_rx = 0; + + dev->canch[i] = gs_make_candev(i, intf, &dconf); if (IS_ERR_OR_NULL(dev->canch[i])) { /* save error code to return later */ rc = PTR_ERR(dev->canch[i]); @@ -988,22 +1378,36 @@ static int gs_usb_probe(struct usb_interface *intf, gs_destroy_candev(dev->canch[i]); usb_kill_anchored_urbs(&dev->rx_submitted); - kfree(dconf); kfree(dev); return rc; } dev->canch[i]->parent = dev; - } - kfree(dconf); + /* set RX packet size based on FD and if hardware + * timestamps are supported. + */ + if (dev->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) { + if (dev->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + hf_size_rx = struct_size(hf, canfd_ts, 1); + else + hf_size_rx = struct_size(hf, canfd, 1); + } else { + if (dev->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP) + hf_size_rx = struct_size(hf, classic_can_ts, 1); + else + hf_size_rx = struct_size(hf, classic_can, 1); + } + dev->hf_size_rx = max(dev->hf_size_rx, hf_size_rx); + } return 0; } static void gs_usb_disconnect(struct usb_interface *intf) { - unsigned i; struct gs_usb *dev = usb_get_intfdata(intf); + unsigned int i; + usb_set_intfdata(intf, NULL); if (!dev) { @@ -1020,20 +1424,24 @@ static void gs_usb_disconnect(struct usb_interface *intf) } static const struct usb_device_id gs_usb_table[] = { - { USB_DEVICE_INTERFACE_NUMBER(USB_GSUSB_1_VENDOR_ID, - USB_GSUSB_1_PRODUCT_ID, 0) }, + { USB_DEVICE_INTERFACE_NUMBER(USB_GS_USB_1_VENDOR_ID, + USB_GS_USB_1_PRODUCT_ID, 0) }, { USB_DEVICE_INTERFACE_NUMBER(USB_CANDLELIGHT_VENDOR_ID, USB_CANDLELIGHT_PRODUCT_ID, 0) }, + { USB_DEVICE_INTERFACE_NUMBER(USB_CES_CANEXT_FD_VENDOR_ID, + USB_CES_CANEXT_FD_PRODUCT_ID, 0) }, + { USB_DEVICE_INTERFACE_NUMBER(USB_ABE_CANDEBUGGER_FD_VENDOR_ID, + USB_ABE_CANDEBUGGER_FD_PRODUCT_ID, 0) }, {} /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, gs_usb_table); static struct usb_driver gs_usb_driver = { - .name = "gs_usb", - .probe = gs_usb_probe, + .name = KBUILD_MODNAME, + .probe = gs_usb_probe, .disconnect = gs_usb_disconnect, - .id_table = gs_usb_table, + .id_table = gs_usb_table, }; module_usb_driver(gs_usb_driver); |