Re: [PATCH v2 04/15] can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Sorry about the delay due to vacation.

On 8.7.2022 14.56, Jimmy Assarsson wrote:
> Use the CMD_GET_CAPABILITIES_REQ command to query the device for certain
> capabilities. We are only interested in LISTENONLY mode and wither the
> device reports CAN error counters.
>
> And remove hard coded capabilities for all Leaf devices.
>
> Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices")
> Reported-by: Anssi Hannula <anssi.hannula@xxxxxxxxxx>
> Signed-off-by: Jimmy Assarsson <extja@xxxxxxxxxx>
> ---
> Changes in v2:
>   - New in v2. Replaces [PATCH 04/12] can: kvaser_usb: Mark Mini PCIe 2xHS as supporting
>  error counters
>   - Fixed Anssi's comments; https://lore.kernel.org/linux-can/9742e7ab-3650-74d8-5a44-136555788c08@xxxxxxxxxx/

Unfortunately this breaks error counters on "0bfd:0017 Kvaser Memorator
Professional HS/HS FW 2.0.50", which worked before this commit with the
hardcoded capabilities.

I'm hitting the "No extended capability support. Upgrade device
firmware." case.
Personally I have no need for error counters on this specific HW, but it
is still a regression.

On "0bfd:0124 Kvaser Mini PCI Express 2xHS FW 4.18.778" this fixes the
error counters as expected.


>  .../net/can/usb/kvaser_usb/kvaser_usb_core.c  |  49 +++---
>  .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c  | 144 +++++++++++++++++-
>  2 files changed, 160 insertions(+), 33 deletions(-)
>
> 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 5caf6e802fc9..d1401a2d23e9 100644
> --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
> +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
> @@ -106,21 +106,6 @@ static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf = {
>  	.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,
> @@ -133,41 +118,41 @@ static const struct usb_device_id kvaser_usb_table[] = {
>  	{ 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),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ 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),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSLS_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_CH_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_SPRO_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_MERCURY_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_LEAF_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID),
> -		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
> +		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
>  
>  	/* Leaf i.MX28 USB product IDs */
>  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID),
> 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 4a82550bdda9..838e072d5d62 100644
> --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
> +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
> @@ -74,6 +74,8 @@
>  #define CMD_TX_ACKNOWLEDGE		50
>  #define CMD_CAN_ERROR_EVENT		51
>  #define CMD_FLUSH_QUEUE_REPLY		68
> +#define CMD_GET_CAPABILITIES_REQ	95
> +#define CMD_GET_CAPABILITIES_RESP	96
>  
>  #define CMD_LEAF_LOG_MESSAGE		106
>  
> @@ -83,6 +85,8 @@
>  #define KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK BIT(5)
>  #define KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK BIT(6)
>  
> +#define KVASER_USB_LEAF_SWOPTION_EXT_CAP BIT(12)
> +
>  /* error factors */
>  #define M16C_EF_ACKE			BIT(0)
>  #define M16C_EF_CRCE			BIT(1)
> @@ -278,6 +282,28 @@ struct leaf_cmd_log_message {
>  	u8 data[8];
>  } __packed;
>  
> +/* Sub commands for cap_req and cap_res */
> +#define KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE 0x02
> +#define KVASER_USB_LEAF_CAP_CMD_ERR_REPORT 0x05
> +struct kvaser_cmd_cap_req {
> +	__le16 padding0;
> +	__le16 cap_cmd;
> +	__le16 padding1;
> +	__le16 channel;
> +} __packed;
> +
> +/* Status codes for cap_res */
> +#define KVASER_USB_LEAF_CAP_STAT_OK 0x00
> +#define KVASER_USB_LEAF_CAP_STAT_NOT_IMPL 0x01
> +#define KVASER_USB_LEAF_CAP_STAT_UNAVAIL 0x02
> +struct kvaser_cmd_cap_res {
> +	__le16 padding;
> +	__le16 cap_cmd;
> +	__le16 status;
> +	__le32 mask;
> +	__le32 value;
> +} __packed;
> +
>  struct kvaser_cmd {
>  	u8 len;
>  	u8 id;
> @@ -295,6 +321,8 @@ struct kvaser_cmd {
>  			struct leaf_cmd_chip_state_event chip_state_event;
>  			struct leaf_cmd_error_event error_event;
>  			struct leaf_cmd_log_message log_message;
> +			struct kvaser_cmd_cap_req cap_req;
> +			struct kvaser_cmd_cap_res cap_res;
>  		} __packed leaf;
>  
>  		union {
> @@ -324,6 +352,7 @@ 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_CAPABILITIES_RESP]	= kvaser_fsize(u.leaf.cap_res),
>  	/* ignored events: */
>  	[CMD_FLUSH_QUEUE_REPLY]		= CMD_SIZE_ANY,
>  };
> @@ -606,6 +635,9 @@ static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev,
>  	dev->fw_version = le32_to_cpu(softinfo->fw_version);
>  	dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx);
>  
> +	if (sw_options & KVASER_USB_LEAF_SWOPTION_EXT_CAP)
> +		dev->card_data.capabilities |= KVASER_USB_CAP_EXT_CAP;
> +
>  	if (dev->driver_info->quirks & KVASER_USB_QUIRK_IGNORE_CLK_FREQ) {
>  		/* Firmware expects bittiming parameters calculated for 16MHz
>  		 * clock, regardless of the actual clock
> @@ -693,6 +725,116 @@ static int kvaser_usb_leaf_get_card_info(struct kvaser_usb *dev)
>  	return 0;
>  }
>  
> +static int kvaser_usb_leaf_get_single_capability(struct kvaser_usb *dev,
> +						 u16 cap_cmd_req, u16 *status)
> +{
> +	struct kvaser_usb_dev_card_data *card_data = &dev->card_data;
> +	struct kvaser_cmd *cmd;
> +	u32 value = 0;
> +	u32 mask = 0;
> +	u16 cap_cmd_res;
> +	int err;
> +	int i;
> +
> +	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
> +	if (!cmd)
> +		return -ENOMEM;
> +
> +	cmd->id = CMD_GET_CAPABILITIES_REQ;
> +	cmd->u.leaf.cap_req.cap_cmd = cpu_to_le16(cap_cmd_req);
> +	cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_cap_req);
> +
> +	err = kvaser_usb_send_cmd(dev, cmd, cmd->len);
> +	if (err)
> +		goto end;
> +
> +	err = kvaser_usb_leaf_wait_cmd(dev, CMD_GET_CAPABILITIES_RESP, cmd);
> +	if (err)
> +		goto end;
> +
> +	*status = le16_to_cpu(cmd->u.leaf.cap_res.status);
> +
> +	if (*status != KVASER_USB_LEAF_CAP_STAT_OK)
> +		goto end;
> +
> +	cap_cmd_res = le16_to_cpu(cmd->u.leaf.cap_res.cap_cmd);
> +	switch (cap_cmd_res) {
> +	case KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE:
> +	case KVASER_USB_LEAF_CAP_CMD_ERR_REPORT:
> +		value = le32_to_cpu(cmd->u.leaf.cap_res.value);
> +		mask = le32_to_cpu(cmd->u.leaf.cap_res.mask);
> +		break;
> +	default:
> +		dev_warn(&dev->intf->dev, "Unknown capability command %u\n",
> +			 cap_cmd_res);
> +		break;
> +	}
> +
> +	for (i = 0; i < dev->nchannels; i++) {
> +		if (BIT(i) & (value & mask)) {
> +			switch (cap_cmd_res) {
> +			case KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE:
> +				card_data->ctrlmode_supported |=
> +						CAN_CTRLMODE_LISTENONLY;
> +				break;
> +			case KVASER_USB_LEAF_CAP_CMD_ERR_REPORT:
> +				card_data->capabilities |=
> +						KVASER_USB_CAP_BERR_CAP;
> +				break;
> +			}
> +		}
> +	}
> +
> +end:
> +	kfree(cmd);
> +
> +	return err;
> +}
> +
> +static int kvaser_usb_leaf_get_capabilities_leaf(struct kvaser_usb *dev)
> +{
> +	int err;
> +	u16 status;
> +
> +	if (!(dev->card_data.capabilities & KVASER_USB_CAP_EXT_CAP)) {
> +		dev_info(&dev->intf->dev,
> +			 "No extended capability support. Upgrade device firmware.\n");
> +		return 0;
> +	}
> +
> +	err = kvaser_usb_leaf_get_single_capability(dev,
> +						    KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE,
> +						    &status);
> +	if (err)
> +		return err;
> +	if (status)
> +		dev_info(&dev->intf->dev,
> +			 "KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE failed %u\n",
> +			 status);
> +
> +	err = kvaser_usb_leaf_get_single_capability(dev,
> +						    KVASER_USB_LEAF_CAP_CMD_ERR_REPORT,
> +						    &status);
> +	if (err)
> +		return err;
> +	if (status)
> +		dev_info(&dev->intf->dev,
> +			 "KVASER_USB_LEAF_CAP_CMD_ERR_REPORT failed %u\n",
> +			 status);
> +
> +	return 0;
> +}
> +
> +static int kvaser_usb_leaf_get_capabilities(struct kvaser_usb *dev)
> +{
> +	int err = 0;
> +
> +	if (dev->driver_info->family == KVASER_LEAF)
> +		err = kvaser_usb_leaf_get_capabilities_leaf(dev);
> +
> +	return err;
> +}
> +
>  static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev,
>  					   const struct kvaser_cmd *cmd)
>  {
> @@ -1479,7 +1621,7 @@ const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {
>  	.dev_get_software_info = kvaser_usb_leaf_get_software_info,
>  	.dev_get_software_details = NULL,
>  	.dev_get_card_info = kvaser_usb_leaf_get_card_info,
> -	.dev_get_capabilities = NULL,
> +	.dev_get_capabilities = kvaser_usb_leaf_get_capabilities,
>  	.dev_set_opt_mode = kvaser_usb_leaf_set_opt_mode,
>  	.dev_start_chip = kvaser_usb_leaf_start_chip,
>  	.dev_stop_chip = kvaser_usb_leaf_stop_chip,


-- 
Anssi Hannula / Bitwise Oy
+358 503803997




[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux