Commit 9c8dddab authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next

Marc Kleine-Budde says:

====================
this is a pull request of 29 patches for net-next/master.

The first patch is by Daniel S. Trevitz and adds documentation for
switchable termination resistors.

Zhang Changzhong's patch fixes a debug output in the j13939 stack.

Oliver Hartkopp finally removes the pch_can driver, which is
superseded by the generic c_can driver.

Gustavo A. R. Silva replaces a zero-length array with
DECLARE_FLEX_ARRAY() in the ucan driver.

Kees Cook's patch removes a no longer needed silencing of
"-Warray-bounds" warnings for the kvaser_usb driver.

The next 2 patches target the m_can driver. The first is by me cleans
up the LEC error handling, the second is by Vivek Yadav and extends
the LEC error handling to the data phase of CAN-FD frames.

The next 9 patches all target the gs_usb driver. The first 5 patches
are by me and improve the Kconfig prompt and help text, set
netdev->dev_id to distinguish multi CAN channel devices, allow
loopback and listen only at the same time, and clean up the
gs_can_open() function a bit. The remaining 4 patches are by Jeroen
Hofstee and add support for 2 new features: Bus Error Reporting and
Get State.

Jimmy Assarsson and Anssi Hannula contribute 10 patches for the
kvaser_usb driver. They first add Listen Only and Bus Error Reporting
support, handle CMD_ERROR_EVENT errors, improve CAN state handling,
restart events, and configuration of the bit timing parameters.

Another patch by me which fixes the indention in the m_can driver.

A patch by Dongliang Mu cleans up the ucan_disconnect() function in
the ucan driver.

The last patch by Biju Das is for the rcan_canfd driver and cleans up
the reset handling.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d0217284 68399ff5
...@@ -1148,6 +1148,39 @@ tuning on deep embedded systems'. The author is running a MPC603e ...@@ -1148,6 +1148,39 @@ tuning on deep embedded systems'. The author is running a MPC603e
load without any problems ... load without any problems ...
Switchable Termination Resistors
--------------------------------
CAN bus requires a specific impedance across the differential pair,
typically provided by two 120Ohm resistors on the farthest nodes of
the bus. Some CAN controllers support activating / deactivating a
termination resistor(s) to provide the correct impedance.
Query the available resistances::
$ ip -details link show can0
...
termination 120 [ 0, 120 ]
Activate the terminating resistor::
$ ip link set dev can0 type can termination 120
Deactivate the terminating resistor::
$ ip link set dev can0 type can termination 0
To enable termination resistor support to a can-controller, either
implement in the controller's struct can-priv::
termination_const
termination_const_cnt
do_set_termination
or add gpio control with the device tree entries from
Documentation/devicetree/bindings/net/can/can-controller.yaml
The Virtual CAN Driver (vcan) The Virtual CAN Driver (vcan)
----------------------------- -----------------------------
......
...@@ -198,14 +198,6 @@ config CAN_XILINXCAN ...@@ -198,14 +198,6 @@ config CAN_XILINXCAN
Xilinx CAN driver. This driver supports both soft AXI CAN IP and Xilinx CAN driver. This driver supports both soft AXI CAN IP and
Zynq CANPS IP. Zynq CANPS IP.
config PCH_CAN
tristate "Intel EG20T PCH CAN controller"
depends on PCI && (X86_32 || COMPILE_TEST)
help
This driver is for PCH CAN of Topcliff (Intel EG20T PCH) which
is an IOH for x86 embedded processor (Intel Atom E6xx series).
This driver can access CAN bus.
source "drivers/net/can/c_can/Kconfig" source "drivers/net/can/c_can/Kconfig"
source "drivers/net/can/cc770/Kconfig" source "drivers/net/can/cc770/Kconfig"
source "drivers/net/can/ctucanfd/Kconfig" source "drivers/net/can/ctucanfd/Kconfig"
......
...@@ -30,6 +30,5 @@ obj-$(CONFIG_CAN_SJA1000) += sja1000/ ...@@ -30,6 +30,5 @@ obj-$(CONFIG_CAN_SJA1000) += sja1000/
obj-$(CONFIG_CAN_SUN4I) += sun4i_can.o obj-$(CONFIG_CAN_SUN4I) += sun4i_can.o
obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o
obj-$(CONFIG_PCH_CAN) += pch_can.o
subdir-ccflags-$(CONFIG_CAN_DEBUG_DEVICES) += -DDEBUG subdir-ccflags-$(CONFIG_CAN_DEBUG_DEVICES) += -DDEBUG
...@@ -20,5 +20,6 @@ config CAN_C_CAN_PCI ...@@ -20,5 +20,6 @@ config CAN_C_CAN_PCI
depends on PCI depends on PCI
help help
This driver adds support for the C_CAN/D_CAN chips connected This driver adds support for the C_CAN/D_CAN chips connected
to the PCI bus. to the PCI bus. E.g. for the C_CAN controller IP inside the
Intel Atom E6xx series IOH (aka EG20T 'PCH CAN').
endif endif
...@@ -156,6 +156,7 @@ enum m_can_reg { ...@@ -156,6 +156,7 @@ enum m_can_reg {
#define PSR_EW BIT(6) #define PSR_EW BIT(6)
#define PSR_EP BIT(5) #define PSR_EP BIT(5)
#define PSR_LEC_MASK GENMASK(2, 0) #define PSR_LEC_MASK GENMASK(2, 0)
#define PSR_DLEC_MASK GENMASK(10, 8)
/* Interrupt Register (IR) */ /* Interrupt Register (IR) */
#define IR_ALL_INT 0xffffffff #define IR_ALL_INT 0xffffffff
...@@ -209,7 +210,7 @@ enum m_can_reg { ...@@ -209,7 +210,7 @@ enum m_can_reg {
/* Interrupts for version >= 3.1.x */ /* Interrupts for version >= 3.1.x */
#define IR_ERR_LEC_31X (IR_PED | IR_PEA) #define IR_ERR_LEC_31X (IR_PED | IR_PEA)
#define IR_ERR_BUS_31X (IR_ERR_LEC_31X | IR_WDI | IR_BEU | IR_BEC | \ #define IR_ERR_BUS_31X (IR_ERR_LEC_31X | IR_WDI | IR_BEU | IR_BEC | \
IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \ IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \
IR_RF0L) IR_RF0L)
#define IR_ERR_ALL_31X (IR_ERR_STATE | IR_ERR_BUS_31X) #define IR_ERR_ALL_31X (IR_ERR_STATE | IR_ERR_BUS_31X)
...@@ -816,11 +817,9 @@ static void m_can_handle_other_err(struct net_device *dev, u32 irqstatus) ...@@ -816,11 +817,9 @@ static void m_can_handle_other_err(struct net_device *dev, u32 irqstatus)
netdev_err(dev, "Message RAM access failure occurred\n"); netdev_err(dev, "Message RAM access failure occurred\n");
} }
static inline bool is_lec_err(u32 psr) static inline bool is_lec_err(u8 lec)
{ {
psr &= LEC_UNUSED; return lec != LEC_NO_ERROR && lec != LEC_NO_CHANGE;
return psr && (psr != LEC_UNUSED);
} }
static inline bool m_can_is_protocol_err(u32 irqstatus) static inline bool m_can_is_protocol_err(u32 irqstatus)
...@@ -875,9 +874,20 @@ static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus, ...@@ -875,9 +874,20 @@ static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus,
work_done += m_can_handle_lost_msg(dev); work_done += m_can_handle_lost_msg(dev);
/* handle lec errors on the bus */ /* handle lec errors on the bus */
if ((cdev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) && if (cdev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) {
is_lec_err(psr)) u8 lec = FIELD_GET(PSR_LEC_MASK, psr);
work_done += m_can_handle_lec_err(dev, psr & LEC_UNUSED); u8 dlec = FIELD_GET(PSR_DLEC_MASK, psr);
if (is_lec_err(lec)) {
netdev_dbg(dev, "Arbitration phase error detected\n");
work_done += m_can_handle_lec_err(dev, lec);
}
if (is_lec_err(dlec)) {
netdev_dbg(dev, "Data phase error detected\n");
work_done += m_can_handle_lec_err(dev, dlec);
}
}
/* handle protocol errors in arbitration phase */ /* handle protocol errors in arbitration phase */
if ((cdev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) && if ((cdev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) &&
......
...@@ -38,7 +38,7 @@ enum m_can_lec_type { ...@@ -38,7 +38,7 @@ enum m_can_lec_type {
LEC_BIT1_ERROR, LEC_BIT1_ERROR,
LEC_BIT0_ERROR, LEC_BIT0_ERROR,
LEC_CRC_ERROR, LEC_CRC_ERROR,
LEC_UNUSED, LEC_NO_CHANGE,
}; };
enum m_can_mram_cfg { enum m_can_mram_cfg {
......
This diff is collapsed.
...@@ -1889,17 +1889,17 @@ static int rcar_canfd_probe(struct platform_device *pdev) ...@@ -1889,17 +1889,17 @@ static int rcar_canfd_probe(struct platform_device *pdev)
gpriv->chip_id = chip_id; gpriv->chip_id = chip_id;
gpriv->max_channels = max_channels; gpriv->max_channels = max_channels;
if (gpriv->chip_id == RENESAS_RZG2L) { gpriv->rstc1 = devm_reset_control_get_optional_exclusive(&pdev->dev,
gpriv->rstc1 = devm_reset_control_get_exclusive(&pdev->dev, "rstp_n"); "rstp_n");
if (IS_ERR(gpriv->rstc1)) if (IS_ERR(gpriv->rstc1))
return dev_err_probe(&pdev->dev, PTR_ERR(gpriv->rstc1), return dev_err_probe(&pdev->dev, PTR_ERR(gpriv->rstc1),
"failed to get rstp_n\n"); "failed to get rstp_n\n");
gpriv->rstc2 = devm_reset_control_get_exclusive(&pdev->dev, "rstc_n"); gpriv->rstc2 = devm_reset_control_get_optional_exclusive(&pdev->dev,
if (IS_ERR(gpriv->rstc2)) "rstc_n");
return dev_err_probe(&pdev->dev, PTR_ERR(gpriv->rstc2), if (IS_ERR(gpriv->rstc2))
"failed to get rstc_n\n"); return dev_err_probe(&pdev->dev, PTR_ERR(gpriv->rstc2),
} "failed to get rstc_n\n");
/* Peripheral clock */ /* Peripheral clock */
gpriv->clkp = devm_clk_get(&pdev->dev, "fck"); gpriv->clkp = devm_clk_get(&pdev->dev, "fck");
......
...@@ -38,10 +38,13 @@ config CAN_ETAS_ES58X ...@@ -38,10 +38,13 @@ config CAN_ETAS_ES58X
will be called etas_es58x. will be called etas_es58x.
config CAN_GS_USB config CAN_GS_USB
tristate "Geschwister Schneider UG interfaces" tristate "Geschwister Schneider UG and candleLight compatible interfaces"
help help
This driver supports the Geschwister Schneider and bytewerk.org This driver supports the Geschwister Schneider and
candleLight USB CAN interfaces USB/CAN devices bytewerk.org candleLight compatible
(https://github.com/candle-usb/candleLight_fw) USB/CAN
interfaces.
If unsure choose N, If unsure choose N,
choose Y for built in support, choose Y for built in support,
M to compile as module (module will be named: gs_usb). M to compile as module (module will be named: gs_usb).
......
...@@ -66,6 +66,7 @@ enum gs_usb_breq { ...@@ -66,6 +66,7 @@ enum gs_usb_breq {
GS_USB_BREQ_BT_CONST_EXT, GS_USB_BREQ_BT_CONST_EXT,
GS_USB_BREQ_SET_TERMINATION, GS_USB_BREQ_SET_TERMINATION,
GS_USB_BREQ_GET_TERMINATION, GS_USB_BREQ_GET_TERMINATION,
GS_USB_BREQ_GET_STATE,
}; };
enum gs_can_mode { enum gs_can_mode {
...@@ -134,6 +135,8 @@ struct gs_device_config { ...@@ -134,6 +135,8 @@ struct gs_device_config {
/* GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9) */ /* GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9) */
/* GS_CAN_FEATURE_BT_CONST_EXT BIT(10) */ /* GS_CAN_FEATURE_BT_CONST_EXT BIT(10) */
/* GS_CAN_FEATURE_TERMINATION BIT(11) */ /* GS_CAN_FEATURE_TERMINATION BIT(11) */
#define GS_CAN_MODE_BERR_REPORTING BIT(12)
/* GS_CAN_FEATURE_GET_STATE BIT(13) */
struct gs_device_mode { struct gs_device_mode {
__le32 mode; __le32 mode;
...@@ -174,7 +177,9 @@ struct gs_device_termination_state { ...@@ -174,7 +177,9 @@ struct gs_device_termination_state {
#define GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9) #define GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9)
#define GS_CAN_FEATURE_BT_CONST_EXT BIT(10) #define GS_CAN_FEATURE_BT_CONST_EXT BIT(10)
#define GS_CAN_FEATURE_TERMINATION BIT(11) #define GS_CAN_FEATURE_TERMINATION BIT(11)
#define GS_CAN_FEATURE_MASK GENMASK(11, 0) #define GS_CAN_FEATURE_BERR_REPORTING BIT(12)
#define GS_CAN_FEATURE_GET_STATE BIT(13)
#define GS_CAN_FEATURE_MASK GENMASK(13, 0)
/* internal quirks - keep in GS_CAN_FEATURE space for now */ /* internal quirks - keep in GS_CAN_FEATURE space for now */
...@@ -843,8 +848,6 @@ static int gs_can_open(struct net_device *netdev) ...@@ -843,8 +848,6 @@ static int gs_can_open(struct net_device *netdev)
ctrlmode = dev->can.ctrlmode; ctrlmode = dev->can.ctrlmode;
if (ctrlmode & CAN_CTRLMODE_FD) { if (ctrlmode & CAN_CTRLMODE_FD) {
flags |= GS_CAN_MODE_FD;
if (dev->feature & GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX) if (dev->feature & GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX)
dev->hf_size_tx = struct_size(hf, canfd_quirk, 1); dev->hf_size_tx = struct_size(hf, canfd_quirk, 1);
else else
...@@ -911,25 +914,29 @@ static int gs_can_open(struct net_device *netdev) ...@@ -911,25 +914,29 @@ static int gs_can_open(struct net_device *netdev)
/* flags */ /* flags */
if (ctrlmode & CAN_CTRLMODE_LOOPBACK) if (ctrlmode & CAN_CTRLMODE_LOOPBACK)
flags |= GS_CAN_MODE_LOOP_BACK; flags |= GS_CAN_MODE_LOOP_BACK;
else if (ctrlmode & CAN_CTRLMODE_LISTENONLY)
if (ctrlmode & CAN_CTRLMODE_LISTENONLY)
flags |= GS_CAN_MODE_LISTEN_ONLY; flags |= GS_CAN_MODE_LISTEN_ONLY;
/* Controller is not allowed to retry TX if (ctrlmode & CAN_CTRLMODE_3_SAMPLES)
* this mode is unavailable on atmels uc3c hardware flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
*/
if (ctrlmode & CAN_CTRLMODE_ONE_SHOT) if (ctrlmode & CAN_CTRLMODE_ONE_SHOT)
flags |= GS_CAN_MODE_ONE_SHOT; flags |= GS_CAN_MODE_ONE_SHOT;
if (ctrlmode & CAN_CTRLMODE_3_SAMPLES) if (ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
flags |= GS_CAN_MODE_TRIPLE_SAMPLE; flags |= GS_CAN_MODE_BERR_REPORTING;
if (ctrlmode & CAN_CTRLMODE_FD)
flags |= GS_CAN_MODE_FD;
/* if hardware supports timestamps, enable it */ /* if hardware supports timestamps, enable it */
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) {
flags |= GS_CAN_MODE_HW_TIMESTAMP; flags |= GS_CAN_MODE_HW_TIMESTAMP;
/* start polling timestamp */ /* start polling timestamp */
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
gs_usb_timestamp_init(dev); gs_usb_timestamp_init(dev);
}
/* finally start device */ /* finally start device */
dev->can.state = CAN_STATE_ERROR_ACTIVE; dev->can.state = CAN_STATE_ERROR_ACTIVE;
...@@ -954,6 +961,42 @@ static int gs_can_open(struct net_device *netdev) ...@@ -954,6 +961,42 @@ static int gs_can_open(struct net_device *netdev)
return 0; return 0;
} }
static int gs_usb_get_state(const struct net_device *netdev,
struct can_berr_counter *bec,
enum can_state *state)
{
struct gs_can *dev = netdev_priv(netdev);
struct gs_device_state ds;
int rc;
rc = usb_control_msg_recv(interface_to_usbdev(dev->iface), 0,
GS_USB_BREQ_GET_STATE,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
dev->channel, 0,
&ds, sizeof(ds),
USB_CTRL_GET_TIMEOUT,
GFP_KERNEL);
if (rc)
return rc;
if (le32_to_cpu(ds.state) >= CAN_STATE_MAX)
return -EOPNOTSUPP;
*state = le32_to_cpu(ds.state);
bec->txerr = le32_to_cpu(ds.txerr);
bec->rxerr = le32_to_cpu(ds.rxerr);
return 0;
}
static int gs_usb_can_get_berr_counter(const struct net_device *netdev,
struct can_berr_counter *bec)
{
enum can_state state;
return gs_usb_get_state(netdev, bec, &state);
}
static int gs_can_close(struct net_device *netdev) static int gs_can_close(struct net_device *netdev)
{ {
int rc; int rc;
...@@ -1153,6 +1196,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, ...@@ -1153,6 +1196,7 @@ static struct gs_can *gs_make_candev(unsigned int channel,
netdev->ethtool_ops = &gs_usb_ethtool_ops; netdev->ethtool_ops = &gs_usb_ethtool_ops;
netdev->flags |= IFF_ECHO; /* we support full roundtrip echo */ netdev->flags |= IFF_ECHO; /* we support full roundtrip echo */
netdev->dev_id = channel;
/* dev setup */ /* dev setup */
strcpy(dev->bt_const.name, KBUILD_MODNAME); strcpy(dev->bt_const.name, KBUILD_MODNAME);
...@@ -1224,6 +1268,12 @@ static struct gs_can *gs_make_candev(unsigned int channel, ...@@ -1224,6 +1268,12 @@ static struct gs_can *gs_make_candev(unsigned int channel,
} }
} }
if (feature & GS_CAN_FEATURE_BERR_REPORTING)
dev->can.ctrlmode_supported |= CAN_CTRLMODE_BERR_REPORTING;
if (feature & GS_CAN_FEATURE_GET_STATE)
dev->can.do_get_berr_counter = gs_usb_can_get_berr_counter;
/* The CANtact Pro from LinkLayer Labs is based on the /* The CANtact Pro from LinkLayer Labs is based on the
* LPC54616 µC, which is affected by the NXP LPC USB transfer * LPC54616 µC, which is affected by the NXP LPC USB transfer
* erratum. However, the current firmware (version 2) doesn't * erratum. However, the current firmware (version 2) doesn't
......
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o
kvaser_usb-y = kvaser_usb_core.o kvaser_usb_leaf.o kvaser_usb_hydra.o kvaser_usb-y = kvaser_usb_core.o kvaser_usb_leaf.o kvaser_usb_hydra.o
# FIXME: temporarily silence -Warray-bounds on non W=1+ builds
ifndef KBUILD_EXTRA_WARN
CFLAGS_kvaser_usb_hydra.o += -Wno-array-bounds
endif
...@@ -76,6 +76,14 @@ struct kvaser_usb_tx_urb_context { ...@@ -76,6 +76,14 @@ struct kvaser_usb_tx_urb_context {
u32 echo_index; u32 echo_index;
}; };
struct kvaser_usb_busparams {
__le32 bitrate;
u8 tseg1;
u8 tseg2;
u8 sjw;
u8 nsamples;
} __packed;
struct kvaser_usb { struct kvaser_usb {
struct usb_device *udev; struct usb_device *udev;
struct usb_interface *intf; struct usb_interface *intf;
...@@ -104,13 +112,19 @@ struct kvaser_usb_net_priv { ...@@ -104,13 +112,19 @@ struct kvaser_usb_net_priv {
struct can_priv can; struct can_priv can;
struct can_berr_counter bec; struct can_berr_counter bec;
/* subdriver-specific data */
void *sub_priv;
struct kvaser_usb *dev; struct kvaser_usb *dev;
struct net_device *netdev; struct net_device *netdev;
int channel; int channel;
struct completion start_comp, stop_comp, flush_comp; struct completion start_comp, stop_comp, flush_comp,
get_busparams_comp;
struct usb_anchor tx_submitted; struct usb_anchor tx_submitted;
struct kvaser_usb_busparams busparams_nominal, busparams_data;
spinlock_t tx_contexts_lock; /* lock for active_tx_contexts */ spinlock_t tx_contexts_lock; /* lock for active_tx_contexts */
int active_tx_contexts; int active_tx_contexts;
struct kvaser_usb_tx_urb_context tx_contexts[]; struct kvaser_usb_tx_urb_context tx_contexts[];
...@@ -120,11 +134,15 @@ struct kvaser_usb_net_priv { ...@@ -120,11 +134,15 @@ struct kvaser_usb_net_priv {
* struct kvaser_usb_dev_ops - Device specific functions * struct kvaser_usb_dev_ops - Device specific functions
* @dev_set_mode: used for can.do_set_mode * @dev_set_mode: used for can.do_set_mode
* @dev_set_bittiming: used for can.do_set_bittiming * @dev_set_bittiming: used for can.do_set_bittiming
* @dev_get_busparams: readback arbitration busparams
* @dev_set_data_bittiming: used for can.do_set_data_bittiming * @dev_set_data_bittiming: used for can.do_set_data_bittiming
* @dev_get_data_busparams: readback data busparams
* @dev_get_berr_counter: used for can.do_get_berr_counter * @dev_get_berr_counter: used for can.do_get_berr_counter
* *
* @dev_setup_endpoints: setup USB in and out endpoints * @dev_setup_endpoints: setup USB in and out endpoints
* @dev_init_card: initialize card * @dev_init_card: initialize card
* @dev_init_channel: initialize channel
* @dev_remove_channel: uninitialize channel
* @dev_get_software_info: get software info * @dev_get_software_info: get software info
* @dev_get_software_details: get software details * @dev_get_software_details: get software details
* @dev_get_card_info: get card info * @dev_get_card_info: get card info
...@@ -140,12 +158,18 @@ struct kvaser_usb_net_priv { ...@@ -140,12 +158,18 @@ struct kvaser_usb_net_priv {
*/ */
struct kvaser_usb_dev_ops { struct kvaser_usb_dev_ops {
int (*dev_set_mode)(struct net_device *netdev, enum can_mode mode); int (*dev_set_mode)(struct net_device *netdev, enum can_mode mode);
int (*dev_set_bittiming)(struct net_device *netdev); int (*dev_set_bittiming)(const struct net_device *netdev,
int (*dev_set_data_bittiming)(struct net_device *netdev); const struct kvaser_usb_busparams *busparams);
int (*dev_get_busparams)(struct kvaser_usb_net_priv *priv);
int (*dev_set_data_bittiming)(const struct net_device *netdev,
const struct kvaser_usb_busparams *busparams);
int (*dev_get_data_busparams)(struct kvaser_usb_net_priv *priv);
int (*dev_get_berr_counter)(const struct net_device *netdev, int (*dev_get_berr_counter)(const struct net_device *netdev,
struct can_berr_counter *bec); struct can_berr_counter *bec);
int (*dev_setup_endpoints)(struct kvaser_usb *dev); int (*dev_setup_endpoints)(struct kvaser_usb *dev);
int (*dev_init_card)(struct kvaser_usb *dev); int (*dev_init_card)(struct kvaser_usb *dev);
int (*dev_init_channel)(struct kvaser_usb_net_priv *priv);
void (*dev_remove_channel)(struct kvaser_usb_net_priv *priv);
int (*dev_get_software_info)(struct kvaser_usb *dev); int (*dev_get_software_info)(struct kvaser_usb *dev);
int (*dev_get_software_details)(struct kvaser_usb *dev); int (*dev_get_software_details)(struct kvaser_usb *dev);
int (*dev_get_card_info)(struct kvaser_usb *dev); int (*dev_get_card_info)(struct kvaser_usb *dev);
......
...@@ -440,10 +440,6 @@ static int kvaser_usb_open(struct net_device *netdev) ...@@ -440,10 +440,6 @@ static int kvaser_usb_open(struct net_device *netdev)
if (err) if (err)
return err; return err;
err = kvaser_usb_setup_rx_urbs(dev);
if (err)
goto error;
err = ops->dev_set_opt_mode(priv); err = ops->dev_set_opt_mode(priv);
if (err) if (err)
goto error; goto error;
...@@ -534,6 +530,93 @@ static int kvaser_usb_close(struct net_device *netdev) ...@@ -534,6 +530,93 @@ static int kvaser_usb_close(struct net_device *netdev)
return 0; return 0;
} }
static int kvaser_usb_set_bittiming(struct net_device *netdev)
{
struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
struct kvaser_usb *dev = priv->dev;
const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
struct can_bittiming *bt = &priv->can.bittiming;
struct kvaser_usb_busparams busparams;
int tseg1 = bt->prop_seg + bt->phase_seg1;
int tseg2 = bt->phase_seg2;
int sjw = bt->sjw;
int err = -EOPNOTSUPP;
busparams.bitrate = cpu_to_le32(bt->bitrate);
busparams.sjw = (u8)sjw;
busparams.tseg1 = (u8)tseg1;
busparams.tseg2 = (u8)tseg2;
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
busparams.nsamples = 3;
else
busparams.nsamples = 1;
err = ops->dev_set_bittiming(netdev, &busparams);
if (err)
return err;
err = kvaser_usb_setup_rx_urbs(priv->dev);
if (err)
return err;
err = ops->dev_get_busparams(priv);
if (err) {
/* Treat EOPNOTSUPP as success */
if (err == -EOPNOTSUPP)
err = 0;
return err;
}
if (memcmp(&busparams, &priv->busparams_nominal,
sizeof(priv->busparams_nominal)) != 0)
err = -EINVAL;
return err;
}
static int kvaser_usb_set_data_bittiming(struct net_device *netdev)
{
struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
struct kvaser_usb *dev = priv->dev;
const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
struct can_bittiming *dbt = &priv->can.data_bittiming;
struct kvaser_usb_busparams busparams;
int tseg1 = dbt->prop_seg + dbt->phase_seg1;
int tseg2 = dbt->phase_seg2;
int sjw = dbt->sjw;
int err;
if (!ops->dev_set_data_bittiming ||
!ops->dev_get_data_busparams)
return -EOPNOTSUPP;
busparams.bitrate = cpu_to_le32(dbt->bitrate);
busparams.sjw = (u8)sjw;
busparams.tseg1 = (u8)tseg1;
busparams.tseg2 = (u8)tseg2;
busparams.nsamples = 1;
err = ops->dev_set_data_bittiming(netdev, &busparams);
if (err)
return err;
err = kvaser_usb_setup_rx_urbs(priv->dev);
if (err)
return err;
err = ops->dev_get_data_busparams(priv);
if (err)
return err;
if (memcmp(&busparams, &priv->busparams_data,
sizeof(priv->busparams_data)) != 0)
err = -EINVAL;
return err;
}
static void kvaser_usb_write_bulk_callback(struct urb *urb) static void kvaser_usb_write_bulk_callback(struct urb *urb)
{ {
struct kvaser_usb_tx_urb_context *context = urb->context; struct kvaser_usb_tx_urb_context *context = urb->context;
...@@ -684,6 +767,7 @@ static const struct ethtool_ops kvaser_usb_ethtool_ops_hwts = { ...@@ -684,6 +767,7 @@ static const struct ethtool_ops kvaser_usb_ethtool_ops_hwts = {
static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev) static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev)
{ {
const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
int i; int i;
for (i = 0; i < dev->nchannels; i++) { for (i = 0; i < dev->nchannels; i++) {
...@@ -699,6 +783,9 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev) ...@@ -699,6 +783,9 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev)
if (!dev->nets[i]) if (!dev->nets[i])
continue; continue;
if (ops->dev_remove_channel)
ops->dev_remove_channel(dev->nets[i]);
free_candev(dev->nets[i]->netdev); free_candev(dev->nets[i]->netdev);
} }
} }
...@@ -730,6 +817,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) ...@@ -730,6 +817,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
init_completion(&priv->start_comp); init_completion(&priv->start_comp);
init_completion(&priv->stop_comp); init_completion(&priv->stop_comp);
init_completion(&priv->flush_comp); init_completion(&priv->flush_comp);
init_completion(&priv->get_busparams_comp);
priv->can.ctrlmode_supported = 0; priv->can.ctrlmode_supported = 0;
priv->dev = dev; priv->dev = dev;
...@@ -742,7 +830,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) ...@@ -742,7 +830,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
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 = ops->dev_set_bittiming; priv->can.do_set_bittiming = kvaser_usb_set_bittiming;
priv->can.do_set_mode = ops->dev_set_mode; priv->can.do_set_mode = ops->dev_set_mode;
if ((driver_info->quirks & KVASER_USB_QUIRK_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))
...@@ -754,7 +842,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) ...@@ -754,7 +842,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
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 = ops->dev_set_data_bittiming; priv->can.do_set_data_bittiming = kvaser_usb_set_data_bittiming;
} }
netdev->flags |= IFF_ECHO; netdev->flags |= IFF_ECHO;
...@@ -772,17 +860,26 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) ...@@ -772,17 +860,26 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
dev->nets[channel] = priv; dev->nets[channel] = priv;
if (ops->dev_init_channel) {
err = ops->dev_init_channel(priv);
if (err)
goto err;
}
err = register_candev(netdev); err = register_candev(netdev);
if (err) { if (err) {
dev_err(&dev->intf->dev, "Failed to register CAN device\n"); dev_err(&dev->intf->dev, "Failed to register CAN device\n");
free_candev(netdev); goto err;
dev->nets[channel] = NULL;
return err;
} }
netdev_dbg(netdev, "device registered\n"); netdev_dbg(netdev, "device registered\n");
return 0; return 0;
err:
free_candev(netdev);
dev->nets[channel] = NULL;
return err;
} }
static int kvaser_usb_probe(struct usb_interface *intf, static int kvaser_usb_probe(struct usb_interface *intf,
......
...@@ -45,6 +45,8 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_rt; ...@@ -45,6 +45,8 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_rt;
/* Minihydra command IDs */ /* Minihydra command IDs */
#define CMD_SET_BUSPARAMS_REQ 16 #define CMD_SET_BUSPARAMS_REQ 16
#define CMD_GET_BUSPARAMS_REQ 17
#define CMD_GET_BUSPARAMS_RESP 18
#define CMD_GET_CHIP_STATE_REQ 19 #define CMD_GET_CHIP_STATE_REQ 19
#define CMD_CHIP_STATE_EVENT 20 #define CMD_CHIP_STATE_EVENT 20
#define CMD_SET_DRIVERMODE_REQ 21 #define CMD_SET_DRIVERMODE_REQ 21
...@@ -196,21 +198,26 @@ struct kvaser_cmd_chip_state_event { ...@@ -196,21 +198,26 @@ struct kvaser_cmd_chip_state_event {
#define KVASER_USB_HYDRA_BUS_MODE_CANFD_ISO 0x01 #define KVASER_USB_HYDRA_BUS_MODE_CANFD_ISO 0x01
#define KVASER_USB_HYDRA_BUS_MODE_NONISO 0x02 #define KVASER_USB_HYDRA_BUS_MODE_NONISO 0x02
struct kvaser_cmd_set_busparams { struct kvaser_cmd_set_busparams {
__le32 bitrate; struct kvaser_usb_busparams busparams_nominal;
u8 tseg1;
u8 tseg2;
u8 sjw;
u8 nsamples;
u8 reserved0[4]; u8 reserved0[4];
__le32 bitrate_d; struct kvaser_usb_busparams busparams_data;
u8 tseg1_d;
u8 tseg2_d;
u8 sjw_d;
u8 nsamples_d;
u8 canfd_mode; u8 canfd_mode;
u8 reserved1[7]; u8 reserved1[7];
} __packed; } __packed;
/* Busparam type */
#define KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN 0x00
#define KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD 0x01
struct kvaser_cmd_get_busparams_req {
u8 type;
u8 reserved[27];
} __packed;
struct kvaser_cmd_get_busparams_res {
struct kvaser_usb_busparams busparams;
u8 reserved[20];
} __packed;
/* Ctrl modes */ /* Ctrl modes */
#define KVASER_USB_HYDRA_CTRLMODE_NORMAL 0x01 #define KVASER_USB_HYDRA_CTRLMODE_NORMAL 0x01
#define KVASER_USB_HYDRA_CTRLMODE_LISTEN 0x02 #define KVASER_USB_HYDRA_CTRLMODE_LISTEN 0x02
...@@ -281,6 +288,8 @@ struct kvaser_cmd { ...@@ -281,6 +288,8 @@ struct kvaser_cmd {
struct kvaser_cmd_error_event error_event; struct kvaser_cmd_error_event error_event;
struct kvaser_cmd_set_busparams set_busparams_req; struct kvaser_cmd_set_busparams set_busparams_req;
struct kvaser_cmd_get_busparams_req get_busparams_req;
struct kvaser_cmd_get_busparams_res get_busparams_res;
struct kvaser_cmd_chip_state_event chip_state_event; struct kvaser_cmd_chip_state_event chip_state_event;
...@@ -363,6 +372,10 @@ struct kvaser_cmd_ext { ...@@ -363,6 +372,10 @@ struct kvaser_cmd_ext {
} __packed; } __packed;
} __packed; } __packed;
struct kvaser_usb_net_hydra_priv {
int pending_get_busparams_type;
};
static const struct can_bittiming_const kvaser_usb_hydra_kcan_bittiming_c = { static const struct can_bittiming_const kvaser_usb_hydra_kcan_bittiming_c = {
.name = "kvaser_usb_kcan", .name = "kvaser_usb_kcan",
.tseg1_min = 1, .tseg1_min = 1,
...@@ -840,6 +853,39 @@ static void kvaser_usb_hydra_flush_queue_reply(const struct kvaser_usb *dev, ...@@ -840,6 +853,39 @@ static void kvaser_usb_hydra_flush_queue_reply(const struct kvaser_usb *dev,
complete(&priv->flush_comp); complete(&priv->flush_comp);
} }
static void kvaser_usb_hydra_get_busparams_reply(const struct kvaser_usb *dev,
const struct kvaser_cmd *cmd)
{
struct kvaser_usb_net_priv *priv;
struct kvaser_usb_net_hydra_priv *hydra;
priv = kvaser_usb_hydra_net_priv_from_cmd(dev, cmd);
if (!priv)
return;
hydra = priv->sub_priv;
if (!hydra)
return;
switch (hydra->pending_get_busparams_type) {
case KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN:
memcpy(&priv->busparams_nominal, &cmd->get_busparams_res.busparams,
sizeof(priv->busparams_nominal));
break;
case KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD:
memcpy(&priv->busparams_data, &cmd->get_busparams_res.busparams,
sizeof(priv->busparams_nominal));
break;
default:
dev_warn(&dev->intf->dev, "Unknown get_busparams_type %d\n",
hydra->pending_get_busparams_type);
break;
}
hydra->pending_get_busparams_type = -1;
complete(&priv->get_busparams_comp);
}
static void static void
kvaser_usb_hydra_bus_status_to_can_state(const struct kvaser_usb_net_priv *priv, kvaser_usb_hydra_bus_status_to_can_state(const struct kvaser_usb_net_priv *priv,
u8 bus_status, u8 bus_status,
...@@ -1326,6 +1372,10 @@ static void kvaser_usb_hydra_handle_cmd_std(const struct kvaser_usb *dev, ...@@ -1326,6 +1372,10 @@ static void kvaser_usb_hydra_handle_cmd_std(const struct kvaser_usb *dev,
kvaser_usb_hydra_state_event(dev, cmd); kvaser_usb_hydra_state_event(dev, cmd);
break; break;
case CMD_GET_BUSPARAMS_RESP:
kvaser_usb_hydra_get_busparams_reply(dev, cmd);
break;
case CMD_ERROR_EVENT: case CMD_ERROR_EVENT:
kvaser_usb_hydra_error_event(dev, cmd); kvaser_usb_hydra_error_event(dev, cmd);
break; break;
...@@ -1522,15 +1572,58 @@ static int kvaser_usb_hydra_set_mode(struct net_device *netdev, ...@@ -1522,15 +1572,58 @@ static int kvaser_usb_hydra_set_mode(struct net_device *netdev,
return err; return err;
} }
static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev) static int kvaser_usb_hydra_get_busparams(struct kvaser_usb_net_priv *priv,
int busparams_type)
{
struct kvaser_usb *dev = priv->dev;
struct kvaser_usb_net_hydra_priv *hydra = priv->sub_priv;
struct kvaser_cmd *cmd;
int err;
if (!hydra)
return -EINVAL;
cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd->header.cmd_no = CMD_GET_BUSPARAMS_REQ;
kvaser_usb_hydra_set_cmd_dest_he
(cmd, dev->card_data.hydra.channel_to_he[priv->channel]);
kvaser_usb_hydra_set_cmd_transid
(cmd, kvaser_usb_hydra_get_next_transid(dev));
cmd->get_busparams_req.type = busparams_type;
hydra->pending_get_busparams_type = busparams_type;
reinit_completion(&priv->get_busparams_comp);
err = kvaser_usb_send_cmd(dev, cmd, kvaser_usb_hydra_cmd_size(cmd));
if (err)
return err;
if (!wait_for_completion_timeout(&priv->get_busparams_comp,
msecs_to_jiffies(KVASER_USB_TIMEOUT)))
return -ETIMEDOUT;
return err;
}
static int kvaser_usb_hydra_get_nominal_busparams(struct kvaser_usb_net_priv *priv)
{
return kvaser_usb_hydra_get_busparams(priv, KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN);
}
static int kvaser_usb_hydra_get_data_busparams(struct kvaser_usb_net_priv *priv)
{
return kvaser_usb_hydra_get_busparams(priv, KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD);
}
static int kvaser_usb_hydra_set_bittiming(const struct net_device *netdev,
const struct kvaser_usb_busparams *busparams)
{ {
struct kvaser_cmd *cmd; struct kvaser_cmd *cmd;
struct kvaser_usb_net_priv *priv = netdev_priv(netdev); struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
struct can_bittiming *bt = &priv->can.bittiming;
struct kvaser_usb *dev = priv->dev; struct kvaser_usb *dev = priv->dev;
int tseg1 = bt->prop_seg + bt->phase_seg1;
int tseg2 = bt->phase_seg2;
int sjw = bt->sjw;
int err; int err;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
...@@ -1538,11 +1631,8 @@ static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev) ...@@ -1538,11 +1631,8 @@ static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev)
return -ENOMEM; return -ENOMEM;
cmd->header.cmd_no = CMD_SET_BUSPARAMS_REQ; cmd->header.cmd_no = CMD_SET_BUSPARAMS_REQ;
cmd->set_busparams_req.bitrate = cpu_to_le32(bt->bitrate); memcpy(&cmd->set_busparams_req.busparams_nominal, busparams,
cmd->set_busparams_req.sjw = (u8)sjw; sizeof(cmd->set_busparams_req.busparams_nominal));
cmd->set_busparams_req.tseg1 = (u8)tseg1;
cmd->set_busparams_req.tseg2 = (u8)tseg2;
cmd->set_busparams_req.nsamples = 1;
kvaser_usb_hydra_set_cmd_dest_he kvaser_usb_hydra_set_cmd_dest_he
(cmd, dev->card_data.hydra.channel_to_he[priv->channel]); (cmd, dev->card_data.hydra.channel_to_he[priv->channel]);
...@@ -1556,15 +1646,12 @@ static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev) ...@@ -1556,15 +1646,12 @@ static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev)
return err; return err;
} }
static int kvaser_usb_hydra_set_data_bittiming(struct net_device *netdev) static int kvaser_usb_hydra_set_data_bittiming(const struct net_device *netdev,
const struct kvaser_usb_busparams *busparams)
{ {
struct kvaser_cmd *cmd; struct kvaser_cmd *cmd;
struct kvaser_usb_net_priv *priv = netdev_priv(netdev); struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
struct can_bittiming *dbt = &priv->can.data_bittiming;
struct kvaser_usb *dev = priv->dev; struct kvaser_usb *dev = priv->dev;
int tseg1 = dbt->prop_seg + dbt->phase_seg1;
int tseg2 = dbt->phase_seg2;
int sjw = dbt->sjw;
int err; int err;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
...@@ -1572,11 +1659,8 @@ static int kvaser_usb_hydra_set_data_bittiming(struct net_device *netdev) ...@@ -1572,11 +1659,8 @@ static int kvaser_usb_hydra_set_data_bittiming(struct net_device *netdev)
return -ENOMEM; return -ENOMEM;
cmd->header.cmd_no = CMD_SET_BUSPARAMS_FD_REQ; cmd->header.cmd_no = CMD_SET_BUSPARAMS_FD_REQ;
cmd->set_busparams_req.bitrate_d = cpu_to_le32(dbt->bitrate); memcpy(&cmd->set_busparams_req.busparams_data, busparams,
cmd->set_busparams_req.sjw_d = (u8)sjw; sizeof(cmd->set_busparams_req.busparams_data));
cmd->set_busparams_req.tseg1_d = (u8)tseg1;
cmd->set_busparams_req.tseg2_d = (u8)tseg2;
cmd->set_busparams_req.nsamples_d = 1;
if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
if (priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) if (priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)
...@@ -1683,6 +1767,19 @@ static int kvaser_usb_hydra_init_card(struct kvaser_usb *dev) ...@@ -1683,6 +1767,19 @@ static int kvaser_usb_hydra_init_card(struct kvaser_usb *dev)
return 0; return 0;
} }
static int kvaser_usb_hydra_init_channel(struct kvaser_usb_net_priv *priv)
{
struct kvaser_usb_net_hydra_priv *hydra;
hydra = devm_kzalloc(&priv->dev->intf->dev, sizeof(*hydra), GFP_KERNEL);
if (!hydra)
return -ENOMEM;
priv->sub_priv = hydra;
return 0;
}
static int kvaser_usb_hydra_get_software_info(struct kvaser_usb *dev) static int kvaser_usb_hydra_get_software_info(struct kvaser_usb *dev)
{ {
struct kvaser_cmd cmd; struct kvaser_cmd cmd;
...@@ -2027,10 +2124,13 @@ kvaser_usb_hydra_frame_to_cmd(const struct kvaser_usb_net_priv *priv, ...@@ -2027,10 +2124,13 @@ kvaser_usb_hydra_frame_to_cmd(const struct kvaser_usb_net_priv *priv,
const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops = { const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops = {
.dev_set_mode = kvaser_usb_hydra_set_mode, .dev_set_mode = kvaser_usb_hydra_set_mode,
.dev_set_bittiming = kvaser_usb_hydra_set_bittiming, .dev_set_bittiming = kvaser_usb_hydra_set_bittiming,
.dev_get_busparams = kvaser_usb_hydra_get_nominal_busparams,
.dev_set_data_bittiming = kvaser_usb_hydra_set_data_bittiming, .dev_set_data_bittiming = kvaser_usb_hydra_set_data_bittiming,
.dev_get_data_busparams = kvaser_usb_hydra_get_data_busparams,
.dev_get_berr_counter = kvaser_usb_hydra_get_berr_counter, .dev_get_berr_counter = kvaser_usb_hydra_get_berr_counter,
.dev_setup_endpoints = kvaser_usb_hydra_setup_endpoints, .dev_setup_endpoints = kvaser_usb_hydra_setup_endpoints,
.dev_init_card = kvaser_usb_hydra_init_card, .dev_init_card = kvaser_usb_hydra_init_card,
.dev_init_channel = kvaser_usb_hydra_init_channel,
.dev_get_software_info = kvaser_usb_hydra_get_software_info, .dev_get_software_info = kvaser_usb_hydra_get_software_info,
.dev_get_software_details = kvaser_usb_hydra_get_software_details, .dev_get_software_details = kvaser_usb_hydra_get_software_details,
.dev_get_card_info = kvaser_usb_hydra_get_card_info, .dev_get_card_info = kvaser_usb_hydra_get_card_info,
......
...@@ -245,7 +245,8 @@ struct ucan_message_in { ...@@ -245,7 +245,8 @@ struct ucan_message_in {
/* CAN transmission complete /* CAN transmission complete
* (type == UCAN_IN_TX_COMPLETE) * (type == UCAN_IN_TX_COMPLETE)
*/ */
struct ucan_tx_complete_entry_t can_tx_complete_msg[0]; DECLARE_FLEX_ARRAY(struct ucan_tx_complete_entry_t,
can_tx_complete_msg);
} __aligned(0x4) msg; } __aligned(0x4) msg;
} __packed __aligned(0x4); } __packed __aligned(0x4);
...@@ -1581,7 +1582,7 @@ static void ucan_disconnect(struct usb_interface *intf) ...@@ -1581,7 +1582,7 @@ static void ucan_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
if (up) { if (up) {
unregister_netdev(up->netdev); unregister_candev(up->netdev);
free_candev(up->netdev); free_candev(up->netdev);
} }
} }
......
...@@ -985,7 +985,7 @@ static int j1939_session_tx_eoma(struct j1939_session *session) ...@@ -985,7 +985,7 @@ static int j1939_session_tx_eoma(struct j1939_session *session)
/* wait for the EOMA packet to come in */ /* wait for the EOMA packet to come in */
j1939_tp_set_rxtimeout(session, 1250); j1939_tp_set_rxtimeout(session, 1250);
netdev_dbg(session->priv->ndev, "%p: 0x%p\n", __func__, session); netdev_dbg(session->priv->ndev, "%s: 0x%p\n", __func__, session);
return 0; return 0;
} }
......
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