Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2046e5a authored by Jimmy Assarsson's avatar Jimmy Assarsson Committed by Greg Kroah-Hartman
Browse files

can: kvaser_usb: Compare requested bittiming parameters with actual parameters...


can: kvaser_usb: Compare requested bittiming parameters with actual parameters in do_set_{,data}_bittiming

[ Upstream commit 39d3df6b0ea80f9b515c632ca07b39b1c156edee ]

The device will respond with a CMD_ERROR_EVENT command, with error_code
KVASER_USB_{LEAF,HYDRA}_ERROR_EVENT_PARAM, if the CMD_SET_BUSPARAMS_REQ
contains invalid bittiming parameters.
However, this command does not contain any channel reference.

To check if the CMD_SET_BUSPARAMS_REQ was successful, redback and compare
the requested bittiming parameters with the device reported parameters.

Fixes: 080f40a6 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices")
Fixes: aec5fb22 ("can: kvaser_usb: Add support for Kvaser USB hydra family")
Tested-by: default avatarAnssi Hannula <anssi.hannula@bitwise.fi>
Co-developed-by: default avatarAnssi Hannula <anssi.hannula@bitwise.fi>
Signed-off-by: default avatarAnssi Hannula <anssi.hannula@bitwise.fi>
Signed-off-by: default avatarJimmy Assarsson <extja@kvaser.com>
Link: https://lore.kernel.org/all/20221010185237.319219-12-extja@kvaser.com


Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 7482f953
Loading
Loading
Loading
Loading
+12 −3
Original line number Original line Diff line number Diff line
@@ -119,9 +119,12 @@ struct kvaser_usb_net_priv {
	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[];
@@ -131,7 +134,9 @@ 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
@@ -153,8 +158,12 @@ 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);
+90 −6
Original line number Original line Diff line number Diff line
@@ -416,10 +416,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;
@@ -510,6 +506,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;
@@ -695,6 +778,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;
@@ -707,7 +791,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))
@@ -719,7 +803,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;
+129 −21
Original line number Original line Diff line number Diff line
@@ -43,6 +43,8 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_flexc;


/* 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
@@ -193,13 +195,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 {
	struct kvaser_usb_busparams busparams_arb;
	struct kvaser_usb_busparams busparams_nominal;
	u8 reserved0[4];
	u8 reserved0[4];
	struct kvaser_usb_busparams busparams_data;
	struct kvaser_usb_busparams busparams_data;
	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
@@ -270,6 +285,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;


@@ -352,6 +369,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,
@@ -805,6 +826,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,
@@ -1291,6 +1345,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;
@@ -1491,15 +1549,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 = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
@@ -1507,11 +1608,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.busparams_arb.bitrate = cpu_to_le32(bt->bitrate);
	memcpy(&cmd->set_busparams_req.busparams_nominal, busparams,
	cmd->set_busparams_req.busparams_arb.sjw = (u8)sjw;
	       sizeof(cmd->set_busparams_req.busparams_nominal));
	cmd->set_busparams_req.busparams_arb.tseg1 = (u8)tseg1;
	cmd->set_busparams_req.busparams_arb.tseg2 = (u8)tseg2;
	cmd->set_busparams_req.busparams_arb.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]);
@@ -1525,15 +1623,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 = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
@@ -1541,11 +1636,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.busparams_data.bitrate = cpu_to_le32(dbt->bitrate);
	memcpy(&cmd->set_busparams_req.busparams_data, busparams,
	cmd->set_busparams_req.busparams_data.sjw = (u8)sjw;
	       sizeof(cmd->set_busparams_req.busparams_data));
	cmd->set_busparams_req.busparams_data.tseg1 = (u8)tseg1;
	cmd->set_busparams_req.busparams_data.tseg2 = (u8)tseg2;
	cmd->set_busparams_req.busparams_data.nsamples = 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)
@@ -1652,6 +1744,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;
@@ -1994,10 +2099,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,
+53 −11
Original line number Original line Diff line number Diff line
@@ -56,6 +56,8 @@
#define CMD_RX_EXT_MESSAGE		14
#define CMD_RX_EXT_MESSAGE		14
#define CMD_TX_EXT_MESSAGE		15
#define CMD_TX_EXT_MESSAGE		15
#define CMD_SET_BUS_PARAMS		16
#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_GET_CHIP_STATE		19
#define CMD_CHIP_STATE_EVENT		20
#define CMD_CHIP_STATE_EVENT		20
#define CMD_SET_CTRL_MODE		21
#define CMD_SET_CTRL_MODE		21
@@ -375,6 +377,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = {
	[CMD_CHIP_STATE_EVENT]		= kvaser_fsize(u.leaf.chip_state_event),
	[CMD_CHIP_STATE_EVENT]		= kvaser_fsize(u.leaf.chip_state_event),
	[CMD_CAN_ERROR_EVENT]		= kvaser_fsize(u.leaf.can_error_event),
	[CMD_CAN_ERROR_EVENT]		= kvaser_fsize(u.leaf.can_error_event),
	[CMD_GET_CAPABILITIES_RESP]	= kvaser_fsize(u.leaf.cap_res),
	[CMD_GET_CAPABILITIES_RESP]	= kvaser_fsize(u.leaf.cap_res),
	[CMD_GET_BUS_PARAMS_REPLY]	= kvaser_fsize(u.busparams),
	[CMD_ERROR_EVENT]		= kvaser_fsize(u.leaf.error_event),
	[CMD_ERROR_EVENT]		= kvaser_fsize(u.leaf.error_event),
	/* ignored events: */
	/* ignored events: */
	[CMD_FLUSH_QUEUE_REPLY]		= CMD_SIZE_ANY,
	[CMD_FLUSH_QUEUE_REPLY]		= CMD_SIZE_ANY,
@@ -1467,6 +1470,25 @@ static void kvaser_usb_leaf_stop_chip_reply(const struct kvaser_usb *dev,
	complete(&priv->stop_comp);
	complete(&priv->stop_comp);
}
}


static void kvaser_usb_leaf_get_busparams_reply(const struct kvaser_usb *dev,
						const struct kvaser_cmd *cmd)
{
	struct kvaser_usb_net_priv *priv;
	u8 channel = cmd->u.busparams.channel;

	if (channel >= dev->nchannels) {
		dev_err(&dev->intf->dev,
			"Invalid channel number (%d)\n", channel);
		return;
	}

	priv = dev->nets[channel];
	memcpy(&priv->busparams_nominal, &cmd->u.busparams.busparams,
	       sizeof(priv->busparams_nominal));

	complete(&priv->get_busparams_comp);
}

static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
					   const struct kvaser_cmd *cmd)
					   const struct kvaser_cmd *cmd)
{
{
@@ -1509,6 +1531,10 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
		kvaser_usb_leaf_error_event(dev, cmd);
		kvaser_usb_leaf_error_event(dev, cmd);
		break;
		break;


	case CMD_GET_BUS_PARAMS_REPLY:
		kvaser_usb_leaf_get_busparams_reply(dev, cmd);
		break;

	/* Ignored commands */
	/* Ignored commands */
	case CMD_USBCAN_CLOCK_OVERFLOW_EVENT:
	case CMD_USBCAN_CLOCK_OVERFLOW_EVENT:
		if (dev->driver_info->family != KVASER_USBCAN)
		if (dev->driver_info->family != KVASER_USBCAN)
@@ -1683,10 +1709,10 @@ static void kvaser_usb_leaf_remove_channel(struct kvaser_usb_net_priv *priv)
		cancel_delayed_work_sync(&leaf->chip_state_req_work);
		cancel_delayed_work_sync(&leaf->chip_state_req_work);
}
}


static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev)
static int kvaser_usb_leaf_set_bittiming(const struct net_device *netdev,
					 const struct kvaser_usb_busparams *busparams)
{
{
	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;
	struct kvaser_cmd *cmd;
	struct kvaser_cmd *cmd;
	int rc;
	int rc;
@@ -1699,15 +1725,8 @@ static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev)
	cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_busparams);
	cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_busparams);
	cmd->u.busparams.channel = priv->channel;
	cmd->u.busparams.channel = priv->channel;
	cmd->u.busparams.tid = 0xff;
	cmd->u.busparams.tid = 0xff;
	cmd->u.busparams.busparams.bitrate = cpu_to_le32(bt->bitrate);
	memcpy(&cmd->u.busparams.busparams, busparams,
	cmd->u.busparams.busparams.sjw = bt->sjw;
	       sizeof(cmd->u.busparams.busparams));
	cmd->u.busparams.busparams.tseg1 = bt->prop_seg + bt->phase_seg1;
	cmd->u.busparams.busparams.tseg2 = bt->phase_seg2;

	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
		cmd->u.busparams.busparams.nsamples = 3;
	else
		cmd->u.busparams.busparams.nsamples = 1;


	rc = kvaser_usb_send_cmd(dev, cmd, cmd->len);
	rc = kvaser_usb_send_cmd(dev, cmd, cmd->len);


@@ -1715,6 +1734,27 @@ static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev)
	return rc;
	return rc;
}
}


static int kvaser_usb_leaf_get_busparams(struct kvaser_usb_net_priv *priv)
{
	int err;

	if (priv->dev->driver_info->family == KVASER_USBCAN)
		return -EOPNOTSUPP;

	reinit_completion(&priv->get_busparams_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(&priv->get_busparams_comp,
					 msecs_to_jiffies(KVASER_USB_TIMEOUT)))
		return -ETIMEDOUT;

	return 0;
}

static int kvaser_usb_leaf_set_mode(struct net_device *netdev,
static int kvaser_usb_leaf_set_mode(struct net_device *netdev,
				    enum can_mode mode)
				    enum can_mode mode)
{
{
@@ -1776,7 +1816,9 @@ static int kvaser_usb_leaf_setup_endpoints(struct kvaser_usb *dev)
const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {
const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {
	.dev_set_mode = kvaser_usb_leaf_set_mode,
	.dev_set_mode = kvaser_usb_leaf_set_mode,
	.dev_set_bittiming = kvaser_usb_leaf_set_bittiming,
	.dev_set_bittiming = kvaser_usb_leaf_set_bittiming,
	.dev_get_busparams = kvaser_usb_leaf_get_busparams,
	.dev_set_data_bittiming = NULL,
	.dev_set_data_bittiming = NULL,
	.dev_get_data_busparams = NULL,
	.dev_get_berr_counter = kvaser_usb_leaf_get_berr_counter,
	.dev_get_berr_counter = kvaser_usb_leaf_get_berr_counter,
	.dev_setup_endpoints = kvaser_usb_leaf_setup_endpoints,
	.dev_setup_endpoints = kvaser_usb_leaf_setup_endpoints,
	.dev_init_card = kvaser_usb_leaf_init_card,
	.dev_init_card = kvaser_usb_leaf_init_card,