lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <39946f68-ac16-9412-fd5e-47e10b84ffbf@kvaser.com>
Date:   Sat, 28 May 2022 09:37:28 +0200
From:   Jimmy Assarsson <extja@...ser.com>
To:     Anssi Hannula <anssi.hannula@...wise.fi>
Cc:     linux-can@...r.kernel.org, Marc Kleine-Budde <mkl@...gutronix.de>,
        linux-kernel@...r.kernel.org
Subject: Re: [PATCH 09/12] can: kvaser_usb_leaf: Fix silently failing bus
 params setup

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@...wise.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@...ser.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@...wise.fi>
Signed-off-by: Jimmy Assarsson <extja@...ser.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@...ser.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@...wise.fi>
Signed-off-by: Anssi Hannula <anssi.hannula@...wise.fi>
Signed-off-by: Jimmy Assarsson <extja@...ser.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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ