Messages in this thread Patches in this message |  | | Date | Sat, 28 May 2022 09:37:28 +0200 | Subject | Re: [PATCH 09/12] can: kvaser_usb_leaf: Fix silently failing bus params setup | From | Jimmy Assarsson <> |
| |
On 5/16/22 15:47, Anssi Hannula wrote: > The device may reject bus params with cmd 45, which is an unhandled > error event that does not contain any channel reference. > > In such cases set_bittiming() callback returns 0 so upper levels will > think setting bitrate succeeded and proceed with starting the interface > with wrong parameters, causing bus errors (the kernel log will have > "Unhandled command (45)", though). > > Fix that by verifying the bus params took hold by reading them back. > > Also, add a handler for cmd 45 that simply prints out the error. > > This condition can be triggered on 0bfd:0124 Kvaser Mini PCI Express > 2xHS FW 4.18.778 by trying to set bitrate 1300000 and on 0bfd:0124 > Kvaser Mini PCI Express 2xHS FW 4.18.778 by trying to set bitrate > 1000000.
The device will send cmd CMD_ERROR_EVENT (45) when invalid data is received from the driver and should never occur. CMD_ERROR_EVENT indicates a misbehaving driver.
For the Kvaser Mini PCI Express 2xHS case, the problem is settings resulting in prescaler equal to 1 are not accepted. This is a bug in the firmware and will be fixed in our next release.
And for Kvaser Memorator Professional HS/HS, the can_bittiming_const limits are not correct. I'll have to look into this a bit more. I'm pretty sure we endup with three different can_bittiming_const in kvaser_usb_leaf, depedning on firmware/microcontroller.
I created new patches for the CMD_ERROR_EVENT, based on your patch. See at end of this mail.
I prefere if we can avoid the paramter readback and kvaser_usb_setup_rx_urbs() in kvaser_usb_leaf_set_bittiming(). With correct can_bittiming_const limits this should not be an issue. On the otherhand, since there are existing devices with a bug that will reject parameters that are within the correct limits, and the result silently failing calls, I cannot see any alternative...
If it ok with you I'll create a new patch based on your readback fix, and also implement this in kvaser_usb_hydra?
> Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") > Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi> > > --- > > Not sure about the best/correct naming for cmd 45. kvaser_usb_hydra > calls it CMD_ERROR_EVENT but kvaser_usb_leaf already has > CMD_CAN_ERROR_EVENT (kvaser_cmd.u.leaf.error_event) so I made it > ctrl_error_event to clearly differentiate it. > > > drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 2 + > .../net/can/usb/kvaser_usb/kvaser_usb_core.c | 2 +- > .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 108 ++++++++++++++++++ > 3 files changed, 111 insertions(+), 1 deletion(-) > > diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h > index 70aa7a9ed35b..b618ce299dbc 100644 > --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h > +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h > @@ -182,6 +182,8 @@ struct kvaser_usb_dev_cfg { > extern const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops; > extern const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops; > > +int kvaser_usb_setup_rx_urbs(struct kvaser_usb *dev); > + > void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv); > > int kvaser_usb_recv_cmd(const struct kvaser_usb *dev, void *cmd, int len, > diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c > index 6a1ebdd9ba85..ff0119c74b49 100644 > --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c > +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c > @@ -326,7 +326,7 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb) > } > } > > -static int kvaser_usb_setup_rx_urbs(struct kvaser_usb *dev) > +int kvaser_usb_setup_rx_urbs(struct kvaser_usb *dev) > { > int i, err = 0; > > diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c > index abb681808a28..7ed2ced8ba08 100644 > --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c > +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c > @@ -57,6 +57,8 @@ > #define CMD_RX_EXT_MESSAGE 14 > #define CMD_TX_EXT_MESSAGE 15 > #define CMD_SET_BUS_PARAMS 16 > +#define CMD_GET_BUS_PARAMS 17 > +#define CMD_GET_BUS_PARAMS_REPLY 18 > #define CMD_GET_CHIP_STATE 19 > #define CMD_CHIP_STATE_EVENT 20 > #define CMD_SET_CTRL_MODE 21 > @@ -72,6 +74,7 @@ > #define CMD_GET_CARD_INFO_REPLY 35 > #define CMD_GET_SOFTWARE_INFO 38 > #define CMD_GET_SOFTWARE_INFO_REPLY 39 > +#define CMD_CTRL_ERROR_EVENT 45 > #define CMD_FLUSH_QUEUE 48 > #define CMD_TX_ACKNOWLEDGE 50 > #define CMD_CAN_ERROR_EVENT 51 > @@ -290,6 +293,15 @@ struct leaf_cmd_log_message { > u8 data[8]; > } __packed; > > +struct kvaser_cmd_ctrl_error_event { > + u8 unknown[2]; > + __le16 timestamp[3]; > + u8 reserved; > + u8 error_code; > + __le16 info1; > + __le16 info2; > +} __packed; > + > struct kvaser_cmd { > u8 len; > u8 id; > @@ -319,6 +331,7 @@ struct kvaser_cmd { > struct kvaser_cmd_tx_can tx_can; > struct kvaser_cmd_ctrl_mode ctrl_mode; > struct kvaser_cmd_flush_queue flush_queue; > + struct kvaser_cmd_ctrl_error_event ctrl_error_event; > } u; > } __packed; > > @@ -336,6 +349,8 @@ static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = { > [CMD_LEAF_LOG_MESSAGE] = kvaser_fsize(u.leaf.log_message), > [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.leaf.chip_state_event), > [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event), > + [CMD_GET_BUS_PARAMS_REPLY] = kvaser_fsize(u.busparams), > + [CMD_CTRL_ERROR_EVENT] = kvaser_fsize(u.ctrl_error_event), > /* ignored events: */ > [CMD_FLUSH_QUEUE_REPLY] = CMD_SIZE_ANY, > }; > @@ -350,6 +365,8 @@ static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = { > [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.usbcan.rx_can), > [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.usbcan.chip_state_event), > [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.error_event), > + [CMD_GET_BUS_PARAMS_REPLY] = kvaser_fsize(u.busparams), > + [CMD_CTRL_ERROR_EVENT] = kvaser_fsize(u.ctrl_error_event), > /* ignored events: */ > [CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY, > }; > @@ -380,6 +397,9 @@ struct kvaser_usb_err_summary { > struct kvaser_usb_net_leaf_priv { > struct kvaser_usb_net_priv *net; > > + struct completion get_bus_params_comp; > + struct kvaser_cmd_busparams params_response; > + > struct delayed_work chip_state_req_work; > }; > > @@ -1206,6 +1226,44 @@ static void kvaser_usb_leaf_stop_chip_reply(const struct kvaser_usb *dev, > complete(&priv->stop_comp); > } > > +static void kvaser_usb_leaf_get_bus_params_reply(const struct kvaser_usb *dev, > + const struct kvaser_cmd *cmd) > +{ > + struct kvaser_usb_net_leaf_priv *leaf; > + u8 channel = cmd->u.busparams.channel; > + > + if (channel >= dev->nchannels) { > + dev_err(&dev->intf->dev, > + "Invalid channel number (%d)\n", channel); > + return; > + } > + > + leaf = dev->nets[channel]->sub_priv; > + memcpy(&leaf->params_response, &cmd->u.busparams, sizeof(leaf->params_response)); > + > + complete(&leaf->get_bus_params_comp); > +} > + > +static void kvaser_usb_leaf_ctrl_error_event(const struct kvaser_usb *dev, > + const struct kvaser_cmd *cmd) > +{ > + const char *desc = ""; > + > + if (cmd->u.ctrl_error_event.error_code == 0x00 && > + cmd->u.ctrl_error_event.info1 == CMD_SET_BUS_PARAMS) > + desc = "bus params not accepted"; > + > + dev_err_ratelimited(&dev->intf->dev, > + "received error (cmd 45)%s%s: %02x %02x, code 0x%02x, info1 %u info2 %u\n", > + desc ? ", " : "", > + desc, > + cmd->u.ctrl_error_event.unknown[0], > + cmd->u.ctrl_error_event.unknown[1], > + cmd->u.ctrl_error_event.error_code, > + le16_to_cpu(cmd->u.ctrl_error_event.info1), > + le16_to_cpu(cmd->u.ctrl_error_event.info2)); > +} > + > static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, > const struct kvaser_cmd *cmd) > { > @@ -1244,6 +1302,14 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, > kvaser_usb_leaf_tx_acknowledge(dev, cmd); > break; > > + case CMD_GET_BUS_PARAMS_REPLY: > + kvaser_usb_leaf_get_bus_params_reply(dev, cmd); > + break; > + > + case CMD_CTRL_ERROR_EVENT: > + kvaser_usb_leaf_ctrl_error_event(dev, cmd); > + break; > + > /* Ignored commands */ > case CMD_USBCAN_CLOCK_OVERFLOW_EVENT: > if (dev->card_data.leaf.family != KVASER_USBCAN) > @@ -1402,6 +1468,7 @@ static int kvaser_usb_leaf_init_channel(struct kvaser_usb_net_priv *priv) > return -ENOMEM; > > leaf->net = priv; > + init_completion(&leaf->get_bus_params_comp); > INIT_DELAYED_WORK(&leaf->chip_state_req_work, > kvaser_usb_leaf_chip_state_req_work); > > @@ -1418,9 +1485,34 @@ static void kvaser_usb_leaf_remove_channel(struct kvaser_usb_net_priv *priv) > cancel_delayed_work_sync(&leaf->chip_state_req_work); > } > > +static int kvaser_usb_leaf_get_bus_params(struct kvaser_usb_net_priv *priv) > +{ > + struct kvaser_usb_net_leaf_priv *leaf = priv->sub_priv; > + int err; > + > + /* we need RX urbs enabled to get the reply */ > + err = kvaser_usb_setup_rx_urbs(priv->dev); > + if (err) > + return err; > + > + reinit_completion(&leaf->get_bus_params_comp); > + > + err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_GET_BUS_PARAMS, > + priv->channel); > + if (err) > + return err; > + > + if (!wait_for_completion_timeout(&leaf->get_bus_params_comp, > + msecs_to_jiffies(KVASER_USB_TIMEOUT))) > + return -ETIMEDOUT; > + > + return 0; > +} > + > static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) > { > struct kvaser_usb_net_priv *priv = netdev_priv(netdev); > + struct kvaser_usb_net_leaf_priv *leaf = priv->sub_priv; > struct can_bittiming *bt = &priv->can.bittiming; > struct kvaser_usb *dev = priv->dev; > struct kvaser_cmd *cmd; > @@ -1446,6 +1538,22 @@ static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) > > rc = kvaser_usb_send_cmd(dev, cmd, cmd->len); > > + if (rc < 0) > + goto out; > + > + /* check that the parameters were accepted */ > + > + rc = kvaser_usb_leaf_get_bus_params(priv); > + if (rc < 0) > + goto out; > + > + if (memcmp(&leaf->params_response, &cmd->u.busparams, > + sizeof(leaf->params_response)) != 0) { > + rc = -EINVAL; > + goto out; > + } > + > +out: > kfree(cmd); > return rc; > }
From db14e82d4cf8c29f2f1b225c2d89418980787df8 Mon Sep 17 00:00:00 2001 From: Jimmy Assarsson <extja@kvaser.com> Date: Wed, 25 May 2022 20:42:03 +0200 Subject: [PATCH 05/13] can: kvaser_usb: kvaser_usb_leaf: Rename {leaf,usbcan}_cmd_error_event to {leaf,usbcan}_cmd_can_error_event
Prepare for handling CMD_ERROR_EVENT. Rename struct {leaf,usbcan}_cmd_error_event to {leaf,usbcan}_cmd_can_error_event.
Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") Reported-by: Anssi Hannula <anssi.hannula@bitwise.fi> Signed-off-by: Jimmy Assarsson <extja@kvaser.com> --- .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c index aee2dae67459..420343e512b4 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -244,7 +244,7 @@ struct kvaser_cmd_tx_acknowledge_header { u8 tid; } __packed;
-struct leaf_cmd_error_event { +struct leaf_cmd_can_error_event { u8 tid; u8 flags; __le16 time[3]; @@ -256,7 +256,7 @@ struct leaf_cmd_error_event { u8 error_factor; } __packed;
-struct usbcan_cmd_error_event { +struct usbcan_cmd_can_error_event { u8 tid; u8 padding; u8 tx_errors_count_ch0; @@ -329,7 +329,7 @@ struct kvaser_cmd { struct leaf_cmd_softinfo softinfo; struct leaf_cmd_rx_can rx_can; struct leaf_cmd_chip_state_event chip_state_event; - struct leaf_cmd_error_event error_event; + struct leaf_cmd_can_error_event can_error_event; struct leaf_cmd_log_message log_message; struct kvaser_cmd_cap_req cap_req; struct kvaser_cmd_cap_res cap_res; @@ -339,7 +339,7 @@ struct kvaser_cmd { struct usbcan_cmd_softinfo softinfo; struct usbcan_cmd_rx_can rx_can; struct usbcan_cmd_chip_state_event chip_state_event; - struct usbcan_cmd_error_event error_event; + struct usbcan_cmd_can_error_event can_error_event; } __packed usbcan;
struct kvaser_cmd_tx_can tx_can; @@ -361,7 +361,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = { [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.leaf.rx_can), [CMD_LEAF_LOG_MESSAGE] = kvaser_fsize(u.leaf.log_message), [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.leaf.chip_state_event), - [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event), + [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.can_error_event), [CMD_GET_CAPABILITIES_RESP] = kvaser_fsize(u.leaf.cap_res), /* ignored events: */ [CMD_FLUSH_QUEUE_REPLY] = CMD_SIZE_ANY, @@ -376,7 +376,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = { [CMD_RX_STD_MESSAGE] = kvaser_fsize(u.usbcan.rx_can), [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.usbcan.rx_can), [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.usbcan.chip_state_event), - [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.error_event), + [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.can_error_event), /* ignored events: */ [CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY, }; @@ -1114,11 +1114,11 @@ static void kvaser_usb_leaf_usbcan_rx_error(const struct kvaser_usb *dev,
case CMD_CAN_ERROR_EVENT: es.channel = 0; - es.status = cmd->u.usbcan.error_event.status_ch0; - es.txerr = cmd->u.usbcan.error_event.tx_errors_count_ch0; - es.rxerr = cmd->u.usbcan.error_event.rx_errors_count_ch0; + es.status = cmd->u.usbcan.can_error_event.status_ch0; + es.txerr = cmd->u.usbcan.can_error_event.tx_errors_count_ch0; + es.rxerr = cmd->u.usbcan.can_error_event.rx_errors_count_ch0; es.usbcan.other_ch_status = - cmd->u.usbcan.error_event.status_ch1; + cmd->u.usbcan.can_error_event.status_ch1; kvaser_usb_leaf_usbcan_conditionally_rx_error(dev, &es);
/* The USBCAN firmware supports up to 2 channels. @@ -1126,13 +1126,13 @@ static void kvaser_usb_leaf_usbcan_rx_error(const struct kvaser_usb *dev, */ if (dev->nchannels == MAX_USBCAN_NET_DEVICES) { es.channel = 1; - es.status = cmd->u.usbcan.error_event.status_ch1; + es.status = cmd->u.usbcan.can_error_event.status_ch1; es.txerr = - cmd->u.usbcan.error_event.tx_errors_count_ch1; + cmd->u.usbcan.can_error_event.tx_errors_count_ch1; es.rxerr = - cmd->u.usbcan.error_event.rx_errors_count_ch1; + cmd->u.usbcan.can_error_event.rx_errors_count_ch1; es.usbcan.other_ch_status = - cmd->u.usbcan.error_event.status_ch0; + cmd->u.usbcan.can_error_event.status_ch0; kvaser_usb_leaf_usbcan_conditionally_rx_error(dev, &es); } break; @@ -1149,11 +1149,11 @@ static void kvaser_usb_leaf_leaf_rx_error(const struct kvaser_usb *dev,
switch (cmd->id) { case CMD_CAN_ERROR_EVENT: - es.channel = cmd->u.leaf.error_event.channel; - es.status = cmd->u.leaf.error_event.status; - es.txerr = cmd->u.leaf.error_event.tx_errors_count; - es.rxerr = cmd->u.leaf.error_event.rx_errors_count; - es.leaf.error_factor = cmd->u.leaf.error_event.error_factor; + es.channel = cmd->u.leaf.can_error_event.channel; + es.status = cmd->u.leaf.can_error_event.status; + es.txerr = cmd->u.leaf.can_error_event.tx_errors_count; + es.rxerr = cmd->u.leaf.can_error_event.rx_errors_count; + es.leaf.error_factor = cmd->u.leaf.can_error_event.error_factor; break; case CMD_LEAF_LOG_MESSAGE: es.channel = cmd->u.leaf.log_message.channel; -- 2.36.1
From 33720111c80f23021c1b37deab78e6a10672f81c Mon Sep 17 00:00:00 2001 From: Jimmy Assarsson <extja@kvaser.com> Date: Wed, 25 May 2022 21:08:32 +0200 Subject: [PATCH 06/13] can: kvaser_usb: kvaser_usb_leaf: Handle CMD_ERROR_EVENT
The device will send an error event command, to indicate certain errors. This indicates a misbehaving driver, and should never occur.
Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") Co-developed-by: Anssi Hannula <anssi.hannula@bitwise.fi> Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi> Signed-off-by: Jimmy Assarsson <extja@kvaser.com> --- .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c index 420343e512b4..5fd4a6133787 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -70,6 +70,7 @@ #define CMD_GET_CARD_INFO_REPLY 35 #define CMD_GET_SOFTWARE_INFO 38 #define CMD_GET_SOFTWARE_INFO_REPLY 39 +#define CMD_ERROR_EVENT 45 #define CMD_FLUSH_QUEUE 48 #define CMD_TX_ACKNOWLEDGE 50 #define CMD_CAN_ERROR_EVENT 51 @@ -268,6 +269,28 @@ struct usbcan_cmd_can_error_event { __le16 time; } __packed;
+/* CMD_ERROR_EVENT error codes */ +#define KVASER_USB_LEAF_ERROR_EVENT_TX_QUEUE_FULL 0x8 +#define KVASER_USB_LEAF_ERROR_EVENT_PARAM 0x9 + +struct leaf_cmd_error_event { + u8 tid; + u8 error_code; + __le16 timestamp[3]; + __le16 padding; + __le16 info1; + __le16 info2; +} __packed; + +struct usbcan_cmd_error_event { + u8 tid; + u8 error_code; + __le16 info1; + __le16 info2; + __le16 timestamp; + __le16 padding; +} __packed; + struct kvaser_cmd_ctrl_mode { u8 tid; u8 channel; @@ -331,6 +354,7 @@ struct kvaser_cmd { struct leaf_cmd_chip_state_event chip_state_event; struct leaf_cmd_can_error_event can_error_event; struct leaf_cmd_log_message log_message; + struct leaf_cmd_error_event error_event; struct kvaser_cmd_cap_req cap_req; struct kvaser_cmd_cap_res cap_res; } __packed leaf; @@ -340,6 +364,7 @@ struct kvaser_cmd { struct usbcan_cmd_rx_can rx_can; struct usbcan_cmd_chip_state_event chip_state_event; struct usbcan_cmd_can_error_event can_error_event; + struct usbcan_cmd_error_event error_event; } __packed usbcan;
struct kvaser_cmd_tx_can tx_can; @@ -363,6 +388,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = { [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.leaf.chip_state_event), [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.can_error_event), [CMD_GET_CAPABILITIES_RESP] = kvaser_fsize(u.leaf.cap_res), + [CMD_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event), /* ignored events: */ [CMD_FLUSH_QUEUE_REPLY] = CMD_SIZE_ANY, }; @@ -377,6 +403,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = { [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.usbcan.rx_can), [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.usbcan.chip_state_event), [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.can_error_event), + [CMD_ERROR_EVENT] = kvaser_fsize(u.usbcan.error_event), /* ignored events: */ [CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY, }; @@ -1286,6 +1313,74 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, netif_rx(skb); }
+static void kvaser_usb_leaf_error_event_parameter(const struct kvaser_usb *dev, + const struct kvaser_cmd *cmd) +{ + u16 info1 = 0; + + switch (dev->card_data.leaf.family) { + case KVASER_LEAF: + info1 = le16_to_cpu(cmd->u.leaf.error_event.info1); + break; + case KVASER_USBCAN: + info1 = le16_to_cpu(cmd->u.usbcan.error_event.info1); + break; + } + + /* info1 will contain the offending cmd_no */ + switch (info1) { + case CMD_SET_CTRL_MODE: + dev_warn(&dev->intf->dev, + "CMD_SET_CTRL_MODE error in parameter\n"); + break; + + case CMD_SET_BUS_PARAMS: + dev_warn(&dev->intf->dev, + "CMD_SET_BUS_PARAMS error in parameter\n"); + break; + + default: + dev_warn(&dev->intf->dev, + "Unhandled parameter error event cmd_no (%u)\n", + info1); + break; + } +} + +static void kvaser_usb_leaf_error_event(const struct kvaser_usb *dev, + const struct kvaser_cmd *cmd) +{ + u8 error_code = 0; + + switch (dev->card_data.leaf.family) { + case KVASER_LEAF: + error_code = cmd->u.leaf.error_event.error_code; + break; + case KVASER_USBCAN: + error_code = cmd->u.usbcan.error_event.error_code; + break; + } + + switch (error_code) { + case KVASER_USB_LEAF_ERROR_EVENT_TX_QUEUE_FULL: + /* Received additional CAN message, when firmware TX queue is + * already full. Something is wrong with the driver. + * This should never happen! + */ + dev_err(&dev->intf->dev, + "Received error event TX_QUEUE_FULL\n"); + break; + case KVASER_USB_LEAF_ERROR_EVENT_PARAM: + kvaser_usb_leaf_error_event_parameter(dev, cmd); + break; + + default: + dev_warn(&dev->intf->dev, + "Unhandled error event (%d)\n", error_code); + break; + } +} + static void kvaser_usb_leaf_start_chip_reply(const struct kvaser_usb *dev, const struct kvaser_cmd *cmd) { @@ -1364,6 +1459,10 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, kvaser_usb_leaf_tx_acknowledge(dev, cmd); break;
+ case CMD_ERROR_EVENT: + kvaser_usb_leaf_error_event(dev, cmd); + break; + /* Ignored commands */ case CMD_USBCAN_CLOCK_OVERFLOW_EVENT: if (dev->card_data.leaf.family != KVASER_USBCAN) -- 2.36.1
|  |