Commit 8183602b authored by Marc Kleine-Budde's avatar Marc Kleine-Budde
Browse files

Merge patch series "can: kvaser_usb: Various fixes"

Jimmy Assarsson <extja@kvaser.com> says:

Changes in v5: https://lore.kernel.org/all/20221010150829.199676-1-extja@kvaser.com
 - Split series [1], kept only critical bug fixes that should go into
   stable, since v4 got rejected [2].
   Non-critical fixes are posted in a separate series.

Changes in v4: https://lore.kernel.org/all/20220903182344.139-1-extja@kvaser.com
 - Add Tested-by: Anssi Hannula to
   [PATCH v4 04/15] can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device
 - Update commit message in
   [PATCH v4 04/15] can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device

Changes in v3: https://lore.kernel.org/all/20220901122729.271-1-extja@kvaser.com
 - Rebase on top of commit
   1d5eeda2 ("can: kvaser_usb: advertise timestamping capabilities and add ioctl support")
 - Add Tested-by: Anssi Hannula
 - Add stable@vger.kernel.org to CC.
 - Add my S-o-b to all patches
 - Fix regression introduced in
   [PATCH v2 04/15] can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device
   found by Anssi Hannula
   https://lore.kernel.org/all/b25bc059-d776-146d-0b3c-41aecf4bd9f8@bitwise.fi

v2: https://lore.kernel.org/all/20220708115709.232815-1-extja@kvaser.com

v1: https://lore.kernel.org/all/20220516134748.3724796-1-anssi.hannula@bitwise.fi

[1] https://lore.kernel.org/linux-can/20220903182344.139-1-extja@kvaser.com
[2] https://lore.kernel.org/linux-can/20220920192708.jcvyph3ec7lscuqj@pengutronix.de

Link: https://lore.kernel.org/all/20221010150829.199676-1-extja@kvaser.com


[mkl: add/update links]
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parents b15e2e49 0be1a655
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -178,6 +178,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;

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,
			int *actual_len);

+2 −1
Original line number Diff line number Diff line
@@ -477,7 +477,7 @@ static void kvaser_usb_reset_tx_urb_contexts(struct kvaser_usb_net_priv *priv)
/* This method might sleep. Do not call it in the atomic context
 * of URB completions.
 */
static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
{
	usb_kill_anchored_urbs(&priv->tx_submitted);
	kvaser_usb_reset_tx_urb_contexts(priv);
@@ -729,6 +729,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
	init_usb_anchor(&priv->tx_submitted);
	init_completion(&priv->start_comp);
	init_completion(&priv->stop_comp);
	init_completion(&priv->flush_comp);
	priv->can.ctrlmode_supported = 0;

	priv->dev = dev;
+1 −1
Original line number Diff line number Diff line
@@ -1916,7 +1916,7 @@ static int kvaser_usb_hydra_flush_queue(struct kvaser_usb_net_priv *priv)
{
	int err;

	init_completion(&priv->flush_comp);
	reinit_completion(&priv->flush_comp);

	err = kvaser_usb_hydra_send_simple_cmd(priv->dev, CMD_FLUSH_QUEUE,
					       priv->channel);
+79 −0
Original line number Diff line number Diff line
@@ -310,6 +310,38 @@ struct kvaser_cmd {
	} u;
} __packed;

#define CMD_SIZE_ANY 0xff
#define kvaser_fsize(field) sizeof_field(struct kvaser_cmd, field)

static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = {
	[CMD_START_CHIP_REPLY]		= kvaser_fsize(u.simple),
	[CMD_STOP_CHIP_REPLY]		= kvaser_fsize(u.simple),
	[CMD_GET_CARD_INFO_REPLY]	= kvaser_fsize(u.cardinfo),
	[CMD_TX_ACKNOWLEDGE]		= kvaser_fsize(u.tx_acknowledge_header),
	[CMD_GET_SOFTWARE_INFO_REPLY]	= kvaser_fsize(u.leaf.softinfo),
	[CMD_RX_STD_MESSAGE]		= kvaser_fsize(u.leaf.rx_can),
	[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),
	/* ignored events: */
	[CMD_FLUSH_QUEUE_REPLY]		= CMD_SIZE_ANY,
};

static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = {
	[CMD_START_CHIP_REPLY]		= kvaser_fsize(u.simple),
	[CMD_STOP_CHIP_REPLY]		= kvaser_fsize(u.simple),
	[CMD_GET_CARD_INFO_REPLY]	= kvaser_fsize(u.cardinfo),
	[CMD_TX_ACKNOWLEDGE]		= kvaser_fsize(u.tx_acknowledge_header),
	[CMD_GET_SOFTWARE_INFO_REPLY]	= kvaser_fsize(u.usbcan.softinfo),
	[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),
	/* ignored events: */
	[CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY,
};

/* Summary of a kvaser error event, for a unified Leaf/Usbcan error
 * handling. Some discrepancies between the two families exist:
 *
@@ -397,6 +429,43 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_32mhz = {
	.bittiming_const = &kvaser_usb_flexc_bittiming_const,
};

static int kvaser_usb_leaf_verify_size(const struct kvaser_usb *dev,
				       const struct kvaser_cmd *cmd)
{
	/* buffer size >= cmd->len ensured by caller */
	u8 min_size = 0;

	switch (dev->driver_info->family) {
	case KVASER_LEAF:
		if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_leaf))
			min_size = kvaser_usb_leaf_cmd_sizes_leaf[cmd->id];
		break;
	case KVASER_USBCAN:
		if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_usbcan))
			min_size = kvaser_usb_leaf_cmd_sizes_usbcan[cmd->id];
		break;
	}

	if (min_size == CMD_SIZE_ANY)
		return 0;

	if (min_size) {
		min_size += CMD_HEADER_LEN;
		if (cmd->len >= min_size)
			return 0;

		dev_err_ratelimited(&dev->intf->dev,
				    "Received command %u too short (size %u, needed %u)",
				    cmd->id, cmd->len, min_size);
		return -EIO;
	}

	dev_warn_ratelimited(&dev->intf->dev,
			     "Unhandled command (%d, size %d)\n",
			     cmd->id, cmd->len);
	return -EINVAL;
}

static void *
kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv,
			     const struct sk_buff *skb, int *cmd_len,
@@ -502,6 +571,9 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id,
end:
	kfree(buf);

	if (err == 0)
		err = kvaser_usb_leaf_verify_size(dev, cmd);

	return err;
}

@@ -1133,6 +1205,9 @@ static void kvaser_usb_leaf_stop_chip_reply(const struct kvaser_usb *dev,
static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
					   const struct kvaser_cmd *cmd)
{
	if (kvaser_usb_leaf_verify_size(dev, cmd) < 0)
		return;

	switch (cmd->id) {
	case CMD_START_CHIP_REPLY:
		kvaser_usb_leaf_start_chip_reply(dev, cmd);
@@ -1351,9 +1426,13 @@ static int kvaser_usb_leaf_set_mode(struct net_device *netdev,

	switch (mode) {
	case CAN_MODE_START:
		kvaser_usb_unlink_tx_urbs(priv);

		err = kvaser_usb_leaf_simple_cmd_async(priv, CMD_START_CHIP);
		if (err)
			return err;

		priv->can.state = CAN_STATE_ERROR_ACTIVE;
		break;
	default:
		return -EOPNOTSUPP;