Commit 7e8c182c authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'linux-can-fixes-for-5.19-20220704' of...

Merge tag 'linux-can-fixes-for-5.19-20220704' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
can 2022-07-04

The 1st patch is by Oliver Hartkopp, targets the BCM CAN protocol and
converts a costly synchronize_rcu() to call_rcu() to fix a performance
regression.

Srinivas Neeli's patch for the xilinx_can driver drops the brp limit
down to 1, as only the pre-production silicon have an issue with a brp
of 1.

The next patch is by Duy Nguyen and fixes the data transmission on
R-Car V3U SoCs in the rcar_canfd driver.

Rhett Aultman's patch fixes a DMA memory leak in the gs_usb driver.

Liang He's patch removes an extra of_node_get() in the grcan driver.

The next 2 patches are by me, target the m_can driver and fix the
timestamp handling used for peripheral devices like the tcan4x5x.

Jimmy Assarsson contributes 3 patches for the kvaser_usb driver and
fixes CAN clock and bit timing related issues.

The remaining 5 patches target the mcp251xfd driver. Thomas Kopp
contributes 2 patches to improve the workaround for broken CRC when
reading the TBC register. 3 patches by me add a missing
hrtimer_cancel() during the ndo_stop() callback, and fix the reading
of the Device ID register.

* tag 'linux-can-fixes-for-5.19-20220704' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can:
  can: mcp251xfd: mcp251xfd_register_get_dev_id(): fix endianness conversion
  can: mcp251xfd: mcp251xfd_register_get_dev_id(): use correct length to read dev_id
  can: mcp251xfd: mcp251xfd_stop(): add missing hrtimer_cancel()
  can: mcp251xfd: mcp251xfd_regmap_crc_read(): update workaround broken CRC on TBC register
  can: mcp251xfd: mcp251xfd_regmap_crc_read(): improve workaround handling for mcp2517fd
  can: kvaser_usb: kvaser_usb_leaf: fix bittiming limits
  can: kvaser_usb: kvaser_usb_leaf: fix CAN clock frequency regression
  can: kvaser_usb: replace run-time checks with struct kvaser_usb_driver_info
  can: m_can: m_can_{read_fifo,echo_tx_event}(): shift timestamp to full 32 bits
  can: m_can: m_can_chip_config(): actually enable internal timestamping
  can: grcan: grcan_probe(): remove extra of_node_get()
  can: gs_usb: gs_usb_open/close(): fix memory leak
  can: rcar_canfd: Fix data transmission failed on R-Car V3U
  Revert "can: xilinx_can: Limit CANFD brp to 2"
  can: bcm: use call_rcu() instead of costly synchronize_rcu()
====================

Link: https://lore.kernel.org/r/20220704122613.1551119-1-mkl@pengutronix.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 1b18f09d 1c0e78a2
...@@ -1646,7 +1646,6 @@ static int grcan_probe(struct platform_device *ofdev) ...@@ -1646,7 +1646,6 @@ static int grcan_probe(struct platform_device *ofdev)
*/ */
sysid_parent = of_find_node_by_path("/ambapp0"); sysid_parent = of_find_node_by_path("/ambapp0");
if (sysid_parent) { if (sysid_parent) {
of_node_get(sysid_parent);
err = of_property_read_u32(sysid_parent, "systemid", &sysid); err = of_property_read_u32(sysid_parent, "systemid", &sysid);
if (!err && ((sysid & GRLIB_VERSION_MASK) >= if (!err && ((sysid & GRLIB_VERSION_MASK) >=
GRCAN_TXBUG_SAFE_GRLIB_VERSION)) GRCAN_TXBUG_SAFE_GRLIB_VERSION))
......
...@@ -529,7 +529,7 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs) ...@@ -529,7 +529,7 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs)
/* acknowledge rx fifo 0 */ /* acknowledge rx fifo 0 */
m_can_write(cdev, M_CAN_RXF0A, fgi); m_can_write(cdev, M_CAN_RXF0A, fgi);
timestamp = FIELD_GET(RX_BUF_RXTS_MASK, fifo_header.dlc); timestamp = FIELD_GET(RX_BUF_RXTS_MASK, fifo_header.dlc) << 16;
m_can_receive_skb(cdev, skb, timestamp); m_can_receive_skb(cdev, skb, timestamp);
...@@ -1030,7 +1030,7 @@ static int m_can_echo_tx_event(struct net_device *dev) ...@@ -1030,7 +1030,7 @@ static int m_can_echo_tx_event(struct net_device *dev)
} }
msg_mark = FIELD_GET(TX_EVENT_MM_MASK, txe); msg_mark = FIELD_GET(TX_EVENT_MM_MASK, txe);
timestamp = FIELD_GET(TX_EVENT_TXTS_MASK, txe); timestamp = FIELD_GET(TX_EVENT_TXTS_MASK, txe) << 16;
/* ack txe element */ /* ack txe element */
m_can_write(cdev, M_CAN_TXEFA, FIELD_PREP(TXEFA_EFAI_MASK, m_can_write(cdev, M_CAN_TXEFA, FIELD_PREP(TXEFA_EFAI_MASK,
...@@ -1351,7 +1351,9 @@ static void m_can_chip_config(struct net_device *dev) ...@@ -1351,7 +1351,9 @@ static void m_can_chip_config(struct net_device *dev)
/* enable internal timestamp generation, with a prescalar of 16. The /* enable internal timestamp generation, with a prescalar of 16. The
* prescalar is applied to the nominal bit timing * prescalar is applied to the nominal bit timing
*/ */
m_can_write(cdev, M_CAN_TSCC, FIELD_PREP(TSCC_TCP_MASK, 0xf)); m_can_write(cdev, M_CAN_TSCC,
FIELD_PREP(TSCC_TCP_MASK, 0xf) |
FIELD_PREP(TSCC_TSS_MASK, TSCC_TSS_INTERNAL));
m_can_config_endisable(cdev, false); m_can_config_endisable(cdev, false);
......
...@@ -1332,6 +1332,9 @@ static void rcar_canfd_set_bittiming(struct net_device *dev) ...@@ -1332,6 +1332,9 @@ static void rcar_canfd_set_bittiming(struct net_device *dev)
cfg = (RCANFD_DCFG_DTSEG1(gpriv, tseg1) | RCANFD_DCFG_DBRP(brp) | cfg = (RCANFD_DCFG_DTSEG1(gpriv, tseg1) | RCANFD_DCFG_DBRP(brp) |
RCANFD_DCFG_DSJW(sjw) | RCANFD_DCFG_DTSEG2(gpriv, tseg2)); RCANFD_DCFG_DSJW(sjw) | RCANFD_DCFG_DTSEG2(gpriv, tseg2));
if (is_v3u(gpriv))
rcar_canfd_write(priv->base, RCANFD_V3U_DCFG(ch), cfg);
else
rcar_canfd_write(priv->base, RCANFD_F_DCFG(ch), cfg); rcar_canfd_write(priv->base, RCANFD_F_DCFG(ch), cfg);
netdev_dbg(priv->ndev, "drate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n", netdev_dbg(priv->ndev, "drate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n",
brp, sjw, tseg1, tseg2); brp, sjw, tseg1, tseg2);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
// Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org> // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
// //
#include <asm/unaligned.h>
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -1650,6 +1651,7 @@ static int mcp251xfd_stop(struct net_device *ndev) ...@@ -1650,6 +1651,7 @@ static int mcp251xfd_stop(struct net_device *ndev)
netif_stop_queue(ndev); netif_stop_queue(ndev);
set_bit(MCP251XFD_FLAGS_DOWN, priv->flags); set_bit(MCP251XFD_FLAGS_DOWN, priv->flags);
hrtimer_cancel(&priv->rx_irq_timer); hrtimer_cancel(&priv->rx_irq_timer);
hrtimer_cancel(&priv->tx_irq_timer);
mcp251xfd_chip_interrupts_disable(priv); mcp251xfd_chip_interrupts_disable(priv);
free_irq(ndev->irq, priv); free_irq(ndev->irq, priv);
can_rx_offload_disable(&priv->offload); can_rx_offload_disable(&priv->offload);
...@@ -1777,7 +1779,7 @@ mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, u32 *dev_id, ...@@ -1777,7 +1779,7 @@ mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, u32 *dev_id,
xfer[0].len = sizeof(buf_tx->cmd); xfer[0].len = sizeof(buf_tx->cmd);
xfer[0].speed_hz = priv->spi_max_speed_hz_slow; xfer[0].speed_hz = priv->spi_max_speed_hz_slow;
xfer[1].rx_buf = buf_rx->data; xfer[1].rx_buf = buf_rx->data;
xfer[1].len = sizeof(dev_id); xfer[1].len = sizeof(*dev_id);
xfer[1].speed_hz = priv->spi_max_speed_hz_fast; xfer[1].speed_hz = priv->spi_max_speed_hz_fast;
mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, MCP251XFD_REG_DEVID); mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, MCP251XFD_REG_DEVID);
...@@ -1786,7 +1788,7 @@ mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, u32 *dev_id, ...@@ -1786,7 +1788,7 @@ mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, u32 *dev_id,
if (err) if (err)
goto out_kfree_buf_tx; goto out_kfree_buf_tx;
*dev_id = be32_to_cpup((__be32 *)buf_rx->data); *dev_id = get_unaligned_le32(buf_rx->data);
*effective_speed_hz_slow = xfer[0].effective_speed_hz; *effective_speed_hz_slow = xfer[0].effective_speed_hz;
*effective_speed_hz_fast = xfer[1].effective_speed_hz; *effective_speed_hz_fast = xfer[1].effective_speed_hz;
......
...@@ -334,19 +334,21 @@ mcp251xfd_regmap_crc_read(void *context, ...@@ -334,19 +334,21 @@ mcp251xfd_regmap_crc_read(void *context,
* register. It increments once per SYS clock tick, * register. It increments once per SYS clock tick,
* which is 20 or 40 MHz. * which is 20 or 40 MHz.
* *
* Observation shows that if the lowest byte (which is * Observation on the mcp2518fd shows that if the
* transferred first on the SPI bus) of that register * lowest byte (which is transferred first on the SPI
* is 0x00 or 0x80 the calculated CRC doesn't always * bus) of that register is 0x00 or 0x80 the
* match the transferred one. * calculated CRC doesn't always match the transferred
* one. On the mcp2517fd this problem is not limited
* to the first byte being 0x00 or 0x80.
* *
* If the highest bit in the lowest byte is flipped * If the highest bit in the lowest byte is flipped
* the transferred CRC matches the calculated one. We * the transferred CRC matches the calculated one. We
* assume for now the CRC calculation in the chip * assume for now the CRC operates on the correct
* works on wrong data and the transferred data is * data.
* correct.
*/ */
if (reg == MCP251XFD_REG_TBC && if (reg == MCP251XFD_REG_TBC &&
(buf_rx->data[0] == 0x0 || buf_rx->data[0] == 0x80)) { ((buf_rx->data[0] & 0xf8) == 0x0 ||
(buf_rx->data[0] & 0xf8) == 0x80)) {
/* Flip highest bit in lowest byte of le32 */ /* Flip highest bit in lowest byte of le32 */
buf_rx->data[0] ^= 0x80; buf_rx->data[0] ^= 0x80;
...@@ -356,10 +358,8 @@ mcp251xfd_regmap_crc_read(void *context, ...@@ -356,10 +358,8 @@ mcp251xfd_regmap_crc_read(void *context,
val_len); val_len);
if (!err) { if (!err) {
/* If CRC is now correct, assume /* If CRC is now correct, assume
* transferred data was OK, flip bit * flipped data is OK.
* back to original value.
*/ */
buf_rx->data[0] ^= 0x80;
goto out; goto out;
} }
} }
......
...@@ -268,6 +268,8 @@ struct gs_can { ...@@ -268,6 +268,8 @@ struct gs_can {
struct usb_anchor tx_submitted; struct usb_anchor tx_submitted;
atomic_t active_tx_urbs; atomic_t active_tx_urbs;
void *rxbuf[GS_MAX_RX_URBS];
dma_addr_t rxbuf_dma[GS_MAX_RX_URBS];
}; };
/* usb interface struct */ /* usb interface struct */
...@@ -742,6 +744,7 @@ static int gs_can_open(struct net_device *netdev) ...@@ -742,6 +744,7 @@ static int gs_can_open(struct net_device *netdev)
for (i = 0; i < GS_MAX_RX_URBS; i++) { for (i = 0; i < GS_MAX_RX_URBS; i++) {
struct urb *urb; struct urb *urb;
u8 *buf; u8 *buf;
dma_addr_t buf_dma;
/* alloc rx urb */ /* alloc rx urb */
urb = usb_alloc_urb(0, GFP_KERNEL); urb = usb_alloc_urb(0, GFP_KERNEL);
...@@ -752,7 +755,7 @@ static int gs_can_open(struct net_device *netdev) ...@@ -752,7 +755,7 @@ static int gs_can_open(struct net_device *netdev)
buf = usb_alloc_coherent(dev->udev, buf = usb_alloc_coherent(dev->udev,
dev->parent->hf_size_rx, dev->parent->hf_size_rx,
GFP_KERNEL, GFP_KERNEL,
&urb->transfer_dma); &buf_dma);
if (!buf) { if (!buf) {
netdev_err(netdev, netdev_err(netdev,
"No memory left for USB buffer\n"); "No memory left for USB buffer\n");
...@@ -760,6 +763,8 @@ static int gs_can_open(struct net_device *netdev) ...@@ -760,6 +763,8 @@ static int gs_can_open(struct net_device *netdev)
return -ENOMEM; return -ENOMEM;
} }
urb->transfer_dma = buf_dma;
/* fill, anchor, and submit rx urb */ /* fill, anchor, and submit rx urb */
usb_fill_bulk_urb(urb, usb_fill_bulk_urb(urb,
dev->udev, dev->udev,
...@@ -781,10 +786,17 @@ static int gs_can_open(struct net_device *netdev) ...@@ -781,10 +786,17 @@ static int gs_can_open(struct net_device *netdev)
"usb_submit failed (err=%d)\n", rc); "usb_submit failed (err=%d)\n", rc);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
usb_free_coherent(dev->udev,
sizeof(struct gs_host_frame),
buf,
buf_dma);
usb_free_urb(urb); usb_free_urb(urb);
break; break;
} }
dev->rxbuf[i] = buf;
dev->rxbuf_dma[i] = buf_dma;
/* Drop reference, /* Drop reference,
* USB core will take care of freeing it * USB core will take care of freeing it
*/ */
...@@ -842,13 +854,20 @@ static int gs_can_close(struct net_device *netdev) ...@@ -842,13 +854,20 @@ static int gs_can_close(struct net_device *netdev)
int rc; int rc;
struct gs_can *dev = netdev_priv(netdev); struct gs_can *dev = netdev_priv(netdev);
struct gs_usb *parent = dev->parent; struct gs_usb *parent = dev->parent;
unsigned int i;
netif_stop_queue(netdev); netif_stop_queue(netdev);
/* Stop polling */ /* Stop polling */
parent->active_channels--; parent->active_channels--;
if (!parent->active_channels) if (!parent->active_channels) {
usb_kill_anchored_urbs(&parent->rx_submitted); 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 */ /* Stop sending URBs */
usb_kill_anchored_urbs(&dev->tx_submitted); usb_kill_anchored_urbs(&dev->tx_submitted);
......
...@@ -35,9 +35,10 @@ ...@@ -35,9 +35,10 @@
#define KVASER_USB_RX_BUFFER_SIZE 3072 #define KVASER_USB_RX_BUFFER_SIZE 3072
#define KVASER_USB_MAX_NET_DEVICES 5 #define KVASER_USB_MAX_NET_DEVICES 5
/* USB devices features */ /* Kvaser USB device quirks */
#define KVASER_USB_HAS_SILENT_MODE BIT(0) #define KVASER_USB_QUIRK_HAS_SILENT_MODE BIT(0)
#define KVASER_USB_HAS_TXRX_ERRORS BIT(1) #define KVASER_USB_QUIRK_HAS_TXRX_ERRORS BIT(1)
#define KVASER_USB_QUIRK_IGNORE_CLK_FREQ BIT(2)
/* Device capabilities */ /* Device capabilities */
#define KVASER_USB_CAP_BERR_CAP 0x01 #define KVASER_USB_CAP_BERR_CAP 0x01
...@@ -65,12 +66,7 @@ struct kvaser_usb_dev_card_data_hydra { ...@@ -65,12 +66,7 @@ struct kvaser_usb_dev_card_data_hydra {
struct kvaser_usb_dev_card_data { struct kvaser_usb_dev_card_data {
u32 ctrlmode_supported; u32 ctrlmode_supported;
u32 capabilities; 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 */ /* Context for an outstanding, not yet ACKed, transmission */
...@@ -83,7 +79,7 @@ struct kvaser_usb { ...@@ -83,7 +79,7 @@ struct kvaser_usb {
struct usb_device *udev; struct usb_device *udev;
struct usb_interface *intf; struct usb_interface *intf;
struct kvaser_usb_net_priv *nets[KVASER_USB_MAX_NET_DEVICES]; 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; const struct kvaser_usb_dev_cfg *cfg;
struct usb_endpoint_descriptor *bulk_in, *bulk_out; struct usb_endpoint_descriptor *bulk_in, *bulk_out;
...@@ -165,6 +161,12 @@ struct kvaser_usb_dev_ops { ...@@ -165,6 +161,12 @@ struct kvaser_usb_dev_ops {
u16 transid); 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 { struct kvaser_usb_dev_cfg {
const struct can_clock clock; const struct can_clock clock;
const unsigned int timestamp_freq; const unsigned int timestamp_freq;
...@@ -184,4 +186,7 @@ int kvaser_usb_send_cmd_async(struct kvaser_usb_net_priv *priv, void *cmd, ...@@ -184,4 +186,7 @@ int kvaser_usb_send_cmd_async(struct kvaser_usb_net_priv *priv, void *cmd,
int len); int len);
int kvaser_usb_can_rx_over_error(struct net_device *netdev); 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 */ #endif /* KVASER_USB_H */
...@@ -61,8 +61,6 @@ ...@@ -61,8 +61,6 @@
#define USB_USBCAN_R_V2_PRODUCT_ID 294 #define USB_USBCAN_R_V2_PRODUCT_ID 294
#define USB_LEAF_LIGHT_R_V2_PRODUCT_ID 295 #define USB_LEAF_LIGHT_R_V2_PRODUCT_ID 295
#define USB_LEAF_LIGHT_HS_V2_OEM2_PRODUCT_ID 296 #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 */ /* Kvaser USBCan-II devices product ids */
#define USB_USBCAN_REVB_PRODUCT_ID 2 #define USB_USBCAN_REVB_PRODUCT_ID 2
...@@ -89,116 +87,153 @@ ...@@ -89,116 +87,153 @@
#define USB_USBCAN_PRO_4HS_PRODUCT_ID 276 #define USB_USBCAN_PRO_4HS_PRODUCT_ID 276
#define USB_HYBRID_CANLIN_PRODUCT_ID 277 #define USB_HYBRID_CANLIN_PRODUCT_ID 277
#define USB_HYBRID_PRO_CANLIN_PRODUCT_ID 278 #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) static const struct kvaser_usb_driver_info kvaser_usb_driver_info_hydra = {
{ .quirks = 0,
return (id->idProduct >= USB_LEAF_DEVEL_PRODUCT_ID && .ops = &kvaser_usb_hydra_dev_ops,
id->idProduct <= USB_CAN_R_PRODUCT_ID) || };
(id->idProduct >= USB_LEAF_LITE_V2_PRODUCT_ID &&
id->idProduct <= USB_LEAF_PRODUCT_ID_END);
}
static inline bool kvaser_is_usbcan(const struct usb_device_id *id) static const struct kvaser_usb_driver_info kvaser_usb_driver_info_usbcan = {
{ .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
return id->idProduct >= USB_USBCAN_REVB_PRODUCT_ID && KVASER_USB_QUIRK_HAS_SILENT_MODE,
id->idProduct <= USB_MEMORATOR_PRODUCT_ID; .family = KVASER_USBCAN,
} .ops = &kvaser_usb_leaf_dev_ops,
};
static inline bool kvaser_is_hydra(const struct usb_device_id *id) static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf = {
{ .quirks = KVASER_USB_QUIRK_IGNORE_CLK_FREQ,
return id->idProduct >= USB_BLACKBIRD_V2_PRODUCT_ID && .family = KVASER_LEAF,
id->idProduct <= USB_HYDRA_PRODUCT_ID_END; .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[] = { static const struct usb_device_id kvaser_usb_table[] = {
/* Leaf USB product IDs */ /* Leaf M32C USB product IDs */
{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID),
{ 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_LITE_PRODUCT_ID),
.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_PRODUCT_ID), { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_PRODUCT_ID),
.driver_info = KVASER_USB_HAS_TXRX_ERRORS | .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
KVASER_USB_HAS_SILENT_MODE },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID), { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID),
.driver_info = KVASER_USB_HAS_TXRX_ERRORS | .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
KVASER_USB_HAS_SILENT_MODE },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID), { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID),
.driver_info = KVASER_USB_HAS_TXRX_ERRORS | .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
KVASER_USB_HAS_SILENT_MODE },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID), { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID),
.driver_info = KVASER_USB_HAS_TXRX_ERRORS | .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
KVASER_USB_HAS_SILENT_MODE },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID), { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID),
.driver_info = KVASER_USB_HAS_TXRX_ERRORS | .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
KVASER_USB_HAS_SILENT_MODE },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID), { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID),
.driver_info = KVASER_USB_HAS_TXRX_ERRORS | .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
KVASER_USB_HAS_SILENT_MODE },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID), { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID),
.driver_info = KVASER_USB_HAS_TXRX_ERRORS | .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
KVASER_USB_HAS_SILENT_MODE },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID), { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID),
.driver_info = KVASER_USB_HAS_TXRX_ERRORS | .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
KVASER_USB_HAS_SILENT_MODE },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID), { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID),
.driver_info = KVASER_USB_HAS_TXRX_ERRORS | .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
KVASER_USB_HAS_SILENT_MODE },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_PRODUCT_ID), { USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_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_GI_PRODUCT_ID) }, { 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), { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_OBDII_PRODUCT_ID),
.driver_info = KVASER_USB_HAS_TXRX_ERRORS | .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
KVASER_USB_HAS_SILENT_MODE },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSLS_PRODUCT_ID), { 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), { 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), { 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), { 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), { 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), { USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_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_V2_PRODUCT_ID) },
{ USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID) }, /* Leaf i.MX28 USB product IDs */
{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM_PRODUCT_ID) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID),
{ 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) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID),
{ 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) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM_PRODUCT_ID),
{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM2_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 */ /* USBCANII USB product IDs */
{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN2_PRODUCT_ID), { 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), { 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), { 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), { 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 */ /* Minihydra USB product IDs */
{ USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_V2_PRODUCT_ID) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_V2_PRODUCT_ID),
{ 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) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_5HS_PRODUCT_ID),
{ 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) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_5HS_PRODUCT_ID),
{ 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) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_4HS_PRODUCT_ID),
{ 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) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_HS_V2_PRODUCT_ID),
{ 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) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_2HS_V2_PRODUCT_ID),
{ 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) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_2HS_PRODUCT_ID),
{ 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) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_2HS_V2_PRODUCT_ID),
{ 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) }, { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_2CANLIN_PRODUCT_ID),
{ USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_CANLIN_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); MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
...@@ -285,6 +320,7 @@ int kvaser_usb_can_rx_over_error(struct net_device *netdev) ...@@ -285,6 +320,7 @@ int kvaser_usb_can_rx_over_error(struct net_device *netdev)
static void kvaser_usb_read_bulk_callback(struct urb *urb) static void kvaser_usb_read_bulk_callback(struct urb *urb)
{ {
struct kvaser_usb *dev = urb->context; struct kvaser_usb *dev = urb->context;
const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
int err; int err;
unsigned int i; unsigned int i;
...@@ -301,7 +337,7 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb) ...@@ -301,7 +337,7 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb)
goto resubmit_urb; goto resubmit_urb;
} }
dev->ops->dev_read_bulk_callback(dev, urb->transfer_buffer, ops->dev_read_bulk_callback(dev, urb->transfer_buffer,
urb->actual_length); urb->actual_length);
resubmit_urb: resubmit_urb:
...@@ -396,6 +432,7 @@ static int kvaser_usb_open(struct net_device *netdev) ...@@ -396,6 +432,7 @@ static int kvaser_usb_open(struct net_device *netdev)
{ {
struct kvaser_usb_net_priv *priv = netdev_priv(netdev); struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
struct kvaser_usb *dev = priv->dev; struct kvaser_usb *dev = priv->dev;
const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
int err; int err;
err = open_candev(netdev); err = open_candev(netdev);
...@@ -406,11 +443,11 @@ static int kvaser_usb_open(struct net_device *netdev) ...@@ -406,11 +443,11 @@ static int kvaser_usb_open(struct net_device *netdev)
if (err) if (err)
goto error; goto error;
err = dev->ops->dev_set_opt_mode(priv); err = ops->dev_set_opt_mode(priv);
if (err) if (err)
goto error; goto error;
err = dev->ops->dev_start_chip(priv); err = ops->dev_start_chip(priv);
if (err) { if (err) {
netdev_warn(netdev, "Cannot start device, error %d\n", err); netdev_warn(netdev, "Cannot start device, error %d\n", err);
goto error; goto error;
...@@ -467,22 +504,23 @@ static int kvaser_usb_close(struct net_device *netdev) ...@@ -467,22 +504,23 @@ static int kvaser_usb_close(struct net_device *netdev)
{ {
struct kvaser_usb_net_priv *priv = netdev_priv(netdev); struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
struct kvaser_usb *dev = priv->dev; struct kvaser_usb *dev = priv->dev;
const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
int err; int err;
netif_stop_queue(netdev); netif_stop_queue(netdev);
err = dev->ops->dev_flush_queue(priv); err = ops->dev_flush_queue(priv);
if (err) if (err)
netdev_warn(netdev, "Cannot flush queue, error %d\n", err); netdev_warn(netdev, "Cannot flush queue, error %d\n", err);
if (dev->ops->dev_reset_chip) { if (ops->dev_reset_chip) {
err = dev->ops->dev_reset_chip(dev, priv->channel); err = ops->dev_reset_chip(dev, priv->channel);
if (err) if (err)
netdev_warn(netdev, "Cannot reset card, error %d\n", netdev_warn(netdev, "Cannot reset card, error %d\n",
err); err);
} }
err = dev->ops->dev_stop_chip(priv); err = ops->dev_stop_chip(priv);
if (err) if (err)
netdev_warn(netdev, "Cannot stop device, error %d\n", err); netdev_warn(netdev, "Cannot stop device, error %d\n", err);
...@@ -521,6 +559,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, ...@@ -521,6 +559,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_net_priv *priv = netdev_priv(netdev);
struct kvaser_usb *dev = priv->dev; 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 net_device_stats *stats = &netdev->stats;
struct kvaser_usb_tx_urb_context *context = NULL; struct kvaser_usb_tx_urb_context *context = NULL;
struct urb *urb; struct urb *urb;
...@@ -563,8 +602,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, ...@@ -563,8 +602,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
goto freeurb; goto freeurb;
} }
buf = dev->ops->dev_frame_to_cmd(priv, skb, &cmd_len, buf = ops->dev_frame_to_cmd(priv, skb, &cmd_len, context->echo_index);
context->echo_index);
if (!buf) { if (!buf) {
stats->tx_dropped++; stats->tx_dropped++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
...@@ -648,15 +686,16 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev) ...@@ -648,15 +686,16 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev)
} }
} }
static int kvaser_usb_init_one(struct kvaser_usb *dev, static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
const struct usb_device_id *id, int channel)
{ {
struct net_device *netdev; struct net_device *netdev;
struct kvaser_usb_net_priv *priv; 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; int err;
if (dev->ops->dev_reset_chip) { if (ops->dev_reset_chip) {
err = dev->ops->dev_reset_chip(dev, channel); err = ops->dev_reset_chip(dev, channel);
if (err) if (err)
return err; return err;
} }
...@@ -685,20 +724,19 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, ...@@ -685,20 +724,19 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev,
priv->can.state = CAN_STATE_STOPPED; priv->can.state = CAN_STATE_STOPPED;
priv->can.clock.freq = dev->cfg->clock.freq; priv->can.clock.freq = dev->cfg->clock.freq;
priv->can.bittiming_const = dev->cfg->bittiming_const; priv->can.bittiming_const = dev->cfg->bittiming_const;
priv->can.do_set_bittiming = dev->ops->dev_set_bittiming; priv->can.do_set_bittiming = ops->dev_set_bittiming;
priv->can.do_set_mode = dev->ops->dev_set_mode; priv->can.do_set_mode = ops->dev_set_mode;
if ((id->driver_info & KVASER_USB_HAS_TXRX_ERRORS) || if ((driver_info->quirks & KVASER_USB_QUIRK_HAS_TXRX_ERRORS) ||
(priv->dev->card_data.capabilities & KVASER_USB_CAP_BERR_CAP)) (priv->dev->card_data.capabilities & KVASER_USB_CAP_BERR_CAP))
priv->can.do_get_berr_counter = dev->ops->dev_get_berr_counter; priv->can.do_get_berr_counter = ops->dev_get_berr_counter;
if (id->driver_info & KVASER_USB_HAS_SILENT_MODE) if (driver_info->quirks & KVASER_USB_QUIRK_HAS_SILENT_MODE)
priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY; priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
priv->can.ctrlmode_supported |= dev->card_data.ctrlmode_supported; priv->can.ctrlmode_supported |= dev->card_data.ctrlmode_supported;
if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) { if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
priv->can.data_bittiming_const = dev->cfg->data_bittiming_const; priv->can.data_bittiming_const = dev->cfg->data_bittiming_const;
priv->can.do_set_data_bittiming = priv->can.do_set_data_bittiming = ops->dev_set_data_bittiming;
dev->ops->dev_set_data_bittiming;
} }
netdev->flags |= IFF_ECHO; netdev->flags |= IFF_ECHO;
...@@ -729,29 +767,22 @@ static int kvaser_usb_probe(struct usb_interface *intf, ...@@ -729,29 +767,22 @@ static int kvaser_usb_probe(struct usb_interface *intf,
struct kvaser_usb *dev; struct kvaser_usb *dev;
int err; int err;
int i; 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); dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL);
if (!dev) if (!dev)
return -ENOMEM; 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->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) { if (err) {
dev_err(&intf->dev, "Cannot get usb endpoint(s)"); dev_err(&intf->dev, "Cannot get usb endpoint(s)");
return err; return err;
...@@ -765,22 +796,22 @@ static int kvaser_usb_probe(struct usb_interface *intf, ...@@ -765,22 +796,22 @@ static int kvaser_usb_probe(struct usb_interface *intf,
dev->card_data.ctrlmode_supported = 0; dev->card_data.ctrlmode_supported = 0;
dev->card_data.capabilities = 0; dev->card_data.capabilities = 0;
err = dev->ops->dev_init_card(dev); err = ops->dev_init_card(dev);
if (err) { if (err) {
dev_err(&intf->dev, dev_err(&intf->dev,
"Failed to initialize card, error %d\n", err); "Failed to initialize card, error %d\n", err);
return err; return err;
} }
err = dev->ops->dev_get_software_info(dev); err = ops->dev_get_software_info(dev);
if (err) { if (err) {
dev_err(&intf->dev, dev_err(&intf->dev,
"Cannot get software info, error %d\n", err); "Cannot get software info, error %d\n", err);
return err; return err;
} }
if (dev->ops->dev_get_software_details) { if (ops->dev_get_software_details) {
err = dev->ops->dev_get_software_details(dev); err = ops->dev_get_software_details(dev);
if (err) { if (err) {
dev_err(&intf->dev, dev_err(&intf->dev,
"Cannot get software details, error %d\n", err); "Cannot get software details, error %d\n", err);
...@@ -798,14 +829,14 @@ static int kvaser_usb_probe(struct usb_interface *intf, ...@@ -798,14 +829,14 @@ static int kvaser_usb_probe(struct usb_interface *intf,
dev_dbg(&intf->dev, "Max outstanding tx = %d URBs\n", dev->max_tx_urbs); 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) { if (err) {
dev_err(&intf->dev, "Cannot get card info, error %d\n", err); dev_err(&intf->dev, "Cannot get card info, error %d\n", err);
return err; return err;
} }
if (dev->ops->dev_get_capabilities) { if (ops->dev_get_capabilities) {
err = dev->ops->dev_get_capabilities(dev); err = ops->dev_get_capabilities(dev);
if (err) { if (err) {
dev_err(&intf->dev, dev_err(&intf->dev,
"Cannot get capabilities, error %d\n", err); "Cannot get capabilities, error %d\n", err);
...@@ -815,7 +846,7 @@ static int kvaser_usb_probe(struct usb_interface *intf, ...@@ -815,7 +846,7 @@ static int kvaser_usb_probe(struct usb_interface *intf,
} }
for (i = 0; i < dev->nchannels; i++) { for (i = 0; i < dev->nchannels; i++) {
err = kvaser_usb_init_one(dev, id, i); err = kvaser_usb_init_one(dev, i);
if (err) { if (err) {
kvaser_usb_remove_interfaces(dev); kvaser_usb_remove_interfaces(dev);
return err; return err;
......
...@@ -375,7 +375,7 @@ static const struct can_bittiming_const kvaser_usb_hydra_kcan_bittiming_c = { ...@@ -375,7 +375,7 @@ static const struct can_bittiming_const kvaser_usb_hydra_kcan_bittiming_c = {
.brp_inc = 1, .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", .name = "kvaser_usb_flex",
.tseg1_min = 4, .tseg1_min = 4,
.tseg1_max = 16, .tseg1_max = 16,
...@@ -2052,7 +2052,7 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_flexc = { ...@@ -2052,7 +2052,7 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_flexc = {
.freq = 24 * MEGA /* Hz */, .freq = 24 * MEGA /* Hz */,
}, },
.timestamp_freq = 1, .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 = { static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_rt = {
......
...@@ -101,16 +101,6 @@ ...@@ -101,16 +101,6 @@
#define USBCAN_ERROR_STATE_RX_ERROR BIT(1) #define USBCAN_ERROR_STATE_RX_ERROR BIT(1)
#define USBCAN_ERROR_STATE_BUSERROR BIT(2) #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 */ /* ctrl modes */
#define KVASER_CTRL_MODE_NORMAL 1 #define KVASER_CTRL_MODE_NORMAL 1
#define KVASER_CTRL_MODE_SILENT 2 #define KVASER_CTRL_MODE_SILENT 2
...@@ -343,48 +333,68 @@ struct kvaser_usb_err_summary { ...@@ -343,48 +333,68 @@ struct kvaser_usb_err_summary {
}; };
}; };
static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = { static const struct can_bittiming_const kvaser_usb_leaf_m16c_bittiming_const = {
.name = "kvaser_usb", .name = "kvaser_usb_ucii",
.tseg1_min = KVASER_USB_TSEG1_MIN, .tseg1_min = 4,
.tseg1_max = KVASER_USB_TSEG1_MAX, .tseg1_max = 16,
.tseg2_min = KVASER_USB_TSEG2_MIN, .tseg2_min = 2,
.tseg2_max = KVASER_USB_TSEG2_MAX, .tseg2_max = 8,
.sjw_max = KVASER_USB_SJW_MAX, .sjw_max = 4,
.brp_min = KVASER_USB_BRP_MIN, .brp_min = 1,
.brp_max = KVASER_USB_BRP_MAX, .brp_max = 16,
.brp_inc = KVASER_USB_BRP_INC, .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 = { .clock = {
.freq = 8 * MEGA /* Hz */, .freq = 8 * MEGA /* Hz */,
}, },
.timestamp_freq = 1, .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 = { .clock = {
.freq = 16 * MEGA /* Hz */, .freq = 16 * MEGA /* Hz */,
}, },
.timestamp_freq = 1, .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 = { .clock = {
.freq = 24 * MEGA /* Hz */, .freq = 24 * MEGA /* Hz */,
}, },
.timestamp_freq = 1, .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 = { .clock = {
.freq = 32 * MEGA /* Hz */, .freq = 32 * MEGA /* Hz */,
}, },
.timestamp_freq = 1, .timestamp_freq = 1,
.bittiming_const = &kvaser_usb_leaf_bittiming_const, .bittiming_const = &kvaser_usb_flexc_bittiming_const,
}; };
static void * static void *
...@@ -404,7 +414,7 @@ kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, ...@@ -404,7 +414,7 @@ kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv,
sizeof(struct kvaser_cmd_tx_can); sizeof(struct kvaser_cmd_tx_can);
cmd->u.tx_can.channel = priv->channel; cmd->u.tx_can.channel = priv->channel;
switch (dev->card_data.leaf.family) { switch (dev->driver_info->family) {
case KVASER_LEAF: case KVASER_LEAF:
cmd_tx_can_flags = &cmd->u.tx_can.leaf.flags; cmd_tx_can_flags = &cmd->u.tx_can.leaf.flags;
break; break;
...@@ -524,17 +534,24 @@ static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev, ...@@ -524,17 +534,24 @@ static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev,
dev->fw_version = le32_to_cpu(softinfo->fw_version); dev->fw_version = le32_to_cpu(softinfo->fw_version);
dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx); dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx);
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) { switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) {
case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK: case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK:
dev->cfg = &kvaser_usb_leaf_dev_cfg_16mhz; dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_16mhz;
break; break;
case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK: case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK:
dev->cfg = &kvaser_usb_leaf_dev_cfg_24mhz; dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_24mhz;
break; break;
case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK: case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK:
dev->cfg = &kvaser_usb_leaf_dev_cfg_32mhz; dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_32mhz;
break; break;
} }
}
} }
static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev)
...@@ -550,7 +567,7 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) ...@@ -550,7 +567,7 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev)
if (err) if (err)
return err; return err;
switch (dev->card_data.leaf.family) { switch (dev->driver_info->family) {
case KVASER_LEAF: case KVASER_LEAF:
kvaser_usb_leaf_get_software_info_leaf(dev, &cmd.u.leaf.softinfo); kvaser_usb_leaf_get_software_info_leaf(dev, &cmd.u.leaf.softinfo);
break; break;
...@@ -558,7 +575,7 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) ...@@ -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->fw_version = le32_to_cpu(cmd.u.usbcan.softinfo.fw_version);
dev->max_tx_urbs = dev->max_tx_urbs =
le16_to_cpu(cmd.u.usbcan.softinfo.max_outstanding_tx); 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; break;
} }
...@@ -597,7 +614,7 @@ static int kvaser_usb_leaf_get_card_info(struct kvaser_usb *dev) ...@@ -597,7 +614,7 @@ static int kvaser_usb_leaf_get_card_info(struct kvaser_usb *dev)
dev->nchannels = cmd.u.cardinfo.nchannels; dev->nchannels = cmd.u.cardinfo.nchannels;
if (dev->nchannels > KVASER_USB_MAX_NET_DEVICES || 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)) dev->nchannels > MAX_USBCAN_NET_DEVICES))
return -EINVAL; return -EINVAL;
...@@ -730,7 +747,7 @@ kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, ...@@ -730,7 +747,7 @@ kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv,
new_state < CAN_STATE_BUS_OFF) new_state < CAN_STATE_BUS_OFF)
priv->can.can_stats.restarts++; priv->can.can_stats.restarts++;
switch (dev->card_data.leaf.family) { switch (dev->driver_info->family) {
case KVASER_LEAF: case KVASER_LEAF:
if (es->leaf.error_factor) { if (es->leaf.error_factor) {
priv->can.can_stats.bus_error++; priv->can.can_stats.bus_error++;
...@@ -809,7 +826,7 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, ...@@ -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: case KVASER_LEAF:
if (es->leaf.error_factor) { if (es->leaf.error_factor) {
cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT; cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
...@@ -999,7 +1016,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, ...@@ -999,7 +1016,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
stats = &priv->netdev->stats; stats = &priv->netdev->stats;
if ((cmd->u.rx_can_header.flag & MSG_FLAG_ERROR_FRAME) && 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)) { cmd->id == CMD_LEAF_LOG_MESSAGE)) {
kvaser_usb_leaf_leaf_rx_error(dev, cmd); kvaser_usb_leaf_leaf_rx_error(dev, cmd);
return; return;
...@@ -1015,7 +1032,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, ...@@ -1015,7 +1032,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
return; return;
} }
switch (dev->card_data.leaf.family) { switch (dev->driver_info->family) {
case KVASER_LEAF: case KVASER_LEAF:
rx_data = cmd->u.leaf.rx_can.data; rx_data = cmd->u.leaf.rx_can.data;
break; break;
...@@ -1030,7 +1047,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, ...@@ -1030,7 +1047,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
return; return;
} }
if (dev->card_data.leaf.family == KVASER_LEAF && cmd->id == if (dev->driver_info->family == KVASER_LEAF && cmd->id ==
CMD_LEAF_LOG_MESSAGE) { CMD_LEAF_LOG_MESSAGE) {
cf->can_id = le32_to_cpu(cmd->u.leaf.log_message.id); cf->can_id = le32_to_cpu(cmd->u.leaf.log_message.id);
if (cf->can_id & KVASER_EXTENDED_FRAME) if (cf->can_id & KVASER_EXTENDED_FRAME)
...@@ -1128,14 +1145,14 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, ...@@ -1128,14 +1145,14 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
break; break;
case CMD_LEAF_LOG_MESSAGE: case CMD_LEAF_LOG_MESSAGE:
if (dev->card_data.leaf.family != KVASER_LEAF) if (dev->driver_info->family != KVASER_LEAF)
goto warn; goto warn;
kvaser_usb_leaf_rx_can_msg(dev, cmd); kvaser_usb_leaf_rx_can_msg(dev, cmd);
break; break;
case CMD_CHIP_STATE_EVENT: case CMD_CHIP_STATE_EVENT:
case CMD_CAN_ERROR_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); kvaser_usb_leaf_leaf_rx_error(dev, cmd);
else else
kvaser_usb_leaf_usbcan_rx_error(dev, cmd); kvaser_usb_leaf_usbcan_rx_error(dev, cmd);
...@@ -1147,12 +1164,12 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, ...@@ -1147,12 +1164,12 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
/* Ignored commands */ /* Ignored commands */
case CMD_USBCAN_CLOCK_OVERFLOW_EVENT: case CMD_USBCAN_CLOCK_OVERFLOW_EVENT:
if (dev->card_data.leaf.family != KVASER_USBCAN) if (dev->driver_info->family != KVASER_USBCAN)
goto warn; goto warn;
break; break;
case CMD_FLUSH_QUEUE_REPLY: case CMD_FLUSH_QUEUE_REPLY:
if (dev->card_data.leaf.family != KVASER_LEAF) if (dev->driver_info->family != KVASER_LEAF)
goto warn; goto warn;
break; break;
......
...@@ -258,7 +258,7 @@ static const struct can_bittiming_const xcan_bittiming_const_canfd2 = { ...@@ -258,7 +258,7 @@ static const struct can_bittiming_const xcan_bittiming_const_canfd2 = {
.tseg2_min = 1, .tseg2_min = 1,
.tseg2_max = 128, .tseg2_max = 128,
.sjw_max = 128, .sjw_max = 128,
.brp_min = 2, .brp_min = 1,
.brp_max = 256, .brp_max = 256,
.brp_inc = 1, .brp_inc = 1,
}; };
...@@ -271,7 +271,7 @@ static const struct can_bittiming_const xcan_data_bittiming_const_canfd2 = { ...@@ -271,7 +271,7 @@ static const struct can_bittiming_const xcan_data_bittiming_const_canfd2 = {
.tseg2_min = 1, .tseg2_min = 1,
.tseg2_max = 16, .tseg2_max = 16,
.sjw_max = 16, .sjw_max = 16,
.brp_min = 2, .brp_min = 1,
.brp_max = 256, .brp_max = 256,
.brp_inc = 1, .brp_inc = 1,
}; };
......
...@@ -100,6 +100,7 @@ static inline u64 get_u64(const struct canfd_frame *cp, int offset) ...@@ -100,6 +100,7 @@ static inline u64 get_u64(const struct canfd_frame *cp, int offset)
struct bcm_op { struct bcm_op {
struct list_head list; struct list_head list;
struct rcu_head rcu;
int ifindex; int ifindex;
canid_t can_id; canid_t can_id;
u32 flags; u32 flags;
...@@ -718,10 +719,9 @@ static struct bcm_op *bcm_find_op(struct list_head *ops, ...@@ -718,10 +719,9 @@ static struct bcm_op *bcm_find_op(struct list_head *ops,
return NULL; return NULL;
} }
static void bcm_remove_op(struct bcm_op *op) static void bcm_free_op_rcu(struct rcu_head *rcu_head)
{ {
hrtimer_cancel(&op->timer); struct bcm_op *op = container_of(rcu_head, struct bcm_op, rcu);
hrtimer_cancel(&op->thrtimer);
if ((op->frames) && (op->frames != &op->sframe)) if ((op->frames) && (op->frames != &op->sframe))
kfree(op->frames); kfree(op->frames);
...@@ -732,6 +732,14 @@ static void bcm_remove_op(struct bcm_op *op) ...@@ -732,6 +732,14 @@ static void bcm_remove_op(struct bcm_op *op)
kfree(op); kfree(op);
} }
static void bcm_remove_op(struct bcm_op *op)
{
hrtimer_cancel(&op->timer);
hrtimer_cancel(&op->thrtimer);
call_rcu(&op->rcu, bcm_free_op_rcu);
}
static void bcm_rx_unreg(struct net_device *dev, struct bcm_op *op) static void bcm_rx_unreg(struct net_device *dev, struct bcm_op *op)
{ {
if (op->rx_reg_dev == dev) { if (op->rx_reg_dev == dev) {
...@@ -757,6 +765,9 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh, ...@@ -757,6 +765,9 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
if ((op->can_id == mh->can_id) && (op->ifindex == ifindex) && if ((op->can_id == mh->can_id) && (op->ifindex == ifindex) &&
(op->flags & CAN_FD_FRAME) == (mh->flags & CAN_FD_FRAME)) { (op->flags & CAN_FD_FRAME) == (mh->flags & CAN_FD_FRAME)) {
/* disable automatic timer on frame reception */
op->flags |= RX_NO_AUTOTIMER;
/* /*
* Don't care if we're bound or not (due to netdev * Don't care if we're bound or not (due to netdev
* problems) can_rx_unregister() is always a save * problems) can_rx_unregister() is always a save
...@@ -785,7 +796,6 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh, ...@@ -785,7 +796,6 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
bcm_rx_handler, op); bcm_rx_handler, op);
list_del(&op->list); list_del(&op->list);
synchronize_rcu();
bcm_remove_op(op); bcm_remove_op(op);
return 1; /* done */ return 1; /* done */
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment