brintos

brintos / linux-shallow public Read only

0
0
Text · 17.5 KiB · 84ffa18 Raw
566 lines · c
1// SPDX-License-Identifier: GPL-2.02 3/* Driver for ETAS GmbH ES58X USB CAN(-FD) Bus Interfaces.4 *5 * File es58x_fd.c: Adds support to ETAS ES582.1 and ES584.1 (naming6 * convention: we use the term "ES58X FD" when referring to those two7 * variants together).8 *9 * Copyright (c) 2019 Robert Bosch Engineering and Business Solutions. All rights reserved.10 * Copyright (c) 2020 ETAS K.K.. All rights reserved.11 * Copyright (c) 2020-2022 Vincent Mailhol <mailhol.vincent@wanadoo.fr>12 */13 14#include <linux/unaligned.h>15#include <linux/kernel.h>16#include <linux/units.h>17 18#include "es58x_core.h"19#include "es58x_fd.h"20 21/**22 * es58x_fd_sizeof_rx_tx_msg() - Calculate the actual length of the23 *	structure of a rx or tx message.24 * @msg: message of variable length, must have a dlc and a len fields.25 *26 * Even if RTR frames have actually no payload, the ES58X devices27 * still expect it. Must be a macro in order to accept several types28 * (struct es58x_fd_tx_can_msg and struct es58x_fd_rx_can_msg) as an29 * input.30 *31 * Return: length of the message.32 */33#define es58x_fd_sizeof_rx_tx_msg(msg)					\34({									\35	typeof(msg) __msg = (msg);					\36	size_t __msg_len;						\37									\38	if (__msg.flags & ES58X_FLAG_FD_DATA)				\39		__msg_len = canfd_sanitize_len(__msg.len);		\40	else								\41		__msg_len = can_cc_dlc2len(__msg.dlc);			\42									\43	offsetof(typeof(__msg), data[__msg_len]);			\44})45 46static enum es58x_fd_cmd_type es58x_fd_cmd_type(struct net_device *netdev)47{48	u32 ctrlmode = es58x_priv(netdev)->can.ctrlmode;49 50	if (ctrlmode & (CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO))51		return ES58X_FD_CMD_TYPE_CANFD;52	else53		return ES58X_FD_CMD_TYPE_CAN;54}55 56static u16 es58x_fd_get_msg_len(const union es58x_urb_cmd *urb_cmd)57{58	return get_unaligned_le16(&urb_cmd->es58x_fd_urb_cmd.msg_len);59}60 61static int es58x_fd_echo_msg(struct net_device *netdev,62			     const struct es58x_fd_urb_cmd *es58x_fd_urb_cmd)63{64	struct es58x_priv *priv = es58x_priv(netdev);65	const struct es58x_fd_echo_msg *echo_msg;66	struct es58x_device *es58x_dev = priv->es58x_dev;67	u64 *tstamps = es58x_dev->timestamps;68	u16 msg_len = get_unaligned_le16(&es58x_fd_urb_cmd->msg_len);69	int i, num_element;70	u32 rcv_packet_idx;71 72	const u32 mask = GENMASK(BITS_PER_TYPE(mask) - 1,73				 BITS_PER_TYPE(echo_msg->packet_idx));74 75	num_element = es58x_msg_num_element(es58x_dev->dev,76					    es58x_fd_urb_cmd->echo_msg,77					    msg_len);78	if (num_element < 0)79		return num_element;80	echo_msg = es58x_fd_urb_cmd->echo_msg;81 82	rcv_packet_idx = (priv->tx_tail & mask) | echo_msg[0].packet_idx;83	for (i = 0; i < num_element; i++) {84		if ((u8)rcv_packet_idx != echo_msg[i].packet_idx) {85			netdev_err(netdev, "Packet idx jumped from %u to %u\n",86				   (u8)rcv_packet_idx - 1,87				   echo_msg[i].packet_idx);88			return -EBADMSG;89		}90 91		tstamps[i] = get_unaligned_le64(&echo_msg[i].timestamp);92		rcv_packet_idx++;93	}94 95	return es58x_can_get_echo_skb(netdev, priv->tx_tail, tstamps, num_element);96}97 98static int es58x_fd_rx_can_msg(struct net_device *netdev,99			       const struct es58x_fd_urb_cmd *es58x_fd_urb_cmd)100{101	struct es58x_device *es58x_dev = es58x_priv(netdev)->es58x_dev;102	const u8 *rx_can_msg_buf = es58x_fd_urb_cmd->rx_can_msg_buf;103	u16 rx_can_msg_buf_len = get_unaligned_le16(&es58x_fd_urb_cmd->msg_len);104	int pkts, ret;105 106	ret = es58x_check_msg_max_len(es58x_dev->dev,107				      es58x_fd_urb_cmd->rx_can_msg_buf,108				      rx_can_msg_buf_len);109	if (ret)110		return ret;111 112	for (pkts = 0; rx_can_msg_buf_len > 0; pkts++) {113		const struct es58x_fd_rx_can_msg *rx_can_msg =114		    (const struct es58x_fd_rx_can_msg *)rx_can_msg_buf;115		bool is_can_fd = !!(rx_can_msg->flags & ES58X_FLAG_FD_DATA);116		/* rx_can_msg_len is the length of the rx_can_msg117		 * buffer. Not to be confused with rx_can_msg->len118		 * which is the length of the CAN payload119		 * rx_can_msg->data.120		 */121		u16 rx_can_msg_len = es58x_fd_sizeof_rx_tx_msg(*rx_can_msg);122 123		if (rx_can_msg_len > rx_can_msg_buf_len) {124			netdev_err(netdev,125				   "%s: Expected a rx_can_msg of size %d but only %d bytes are left in rx_can_msg_buf\n",126				   __func__,127				   rx_can_msg_len, rx_can_msg_buf_len);128			return -EMSGSIZE;129		}130		if (rx_can_msg->len > CANFD_MAX_DLEN) {131			netdev_err(netdev,132				   "%s: Data length is %d but maximum should be %d\n",133				   __func__, rx_can_msg->len, CANFD_MAX_DLEN);134			return -EMSGSIZE;135		}136 137		if (netif_running(netdev)) {138			u64 tstamp = get_unaligned_le64(&rx_can_msg->timestamp);139			canid_t can_id = get_unaligned_le32(&rx_can_msg->can_id);140			u8 dlc;141 142			if (is_can_fd)143				dlc = can_fd_len2dlc(rx_can_msg->len);144			else145				dlc = rx_can_msg->dlc;146 147			ret = es58x_rx_can_msg(netdev, tstamp, rx_can_msg->data,148					       can_id, rx_can_msg->flags, dlc);149			if (ret)150				break;151		}152 153		rx_can_msg_buf_len -= rx_can_msg_len;154		rx_can_msg_buf += rx_can_msg_len;155	}156 157	if (!netif_running(netdev)) {158		if (net_ratelimit())159			netdev_info(netdev,160				    "%s: %s is down, dropping %d rx packets\n",161				    __func__, netdev->name, pkts);162		netdev->stats.rx_dropped += pkts;163	}164 165	return ret;166}167 168static int es58x_fd_rx_event_msg(struct net_device *netdev,169				 const struct es58x_fd_urb_cmd *es58x_fd_urb_cmd)170{171	struct es58x_device *es58x_dev = es58x_priv(netdev)->es58x_dev;172	u16 msg_len = get_unaligned_le16(&es58x_fd_urb_cmd->msg_len);173	const struct es58x_fd_rx_event_msg *rx_event_msg;174	int ret;175 176	rx_event_msg = &es58x_fd_urb_cmd->rx_event_msg;177	ret = es58x_check_msg_len(es58x_dev->dev, *rx_event_msg, msg_len);178	if (ret)179		return ret;180 181	return es58x_rx_err_msg(netdev, rx_event_msg->error_code,182				rx_event_msg->event_code,183				get_unaligned_le64(&rx_event_msg->timestamp));184}185 186static int es58x_fd_rx_cmd_ret_u32(struct net_device *netdev,187				   const struct es58x_fd_urb_cmd *es58x_fd_urb_cmd,188				   enum es58x_ret_type cmd_ret_type)189{190	struct es58x_device *es58x_dev = es58x_priv(netdev)->es58x_dev;191	u16 msg_len = get_unaligned_le16(&es58x_fd_urb_cmd->msg_len);192	int ret;193 194	ret = es58x_check_msg_len(es58x_dev->dev,195				  es58x_fd_urb_cmd->rx_cmd_ret_le32, msg_len);196	if (ret)197		return ret;198 199	return es58x_rx_cmd_ret_u32(netdev, cmd_ret_type,200				    get_unaligned_le32(&es58x_fd_urb_cmd->rx_cmd_ret_le32));201}202 203static int es58x_fd_tx_ack_msg(struct net_device *netdev,204			       const struct es58x_fd_urb_cmd *es58x_fd_urb_cmd)205{206	struct es58x_device *es58x_dev = es58x_priv(netdev)->es58x_dev;207	const struct es58x_fd_tx_ack_msg *tx_ack_msg;208	u16 msg_len = get_unaligned_le16(&es58x_fd_urb_cmd->msg_len);209	int ret;210 211	tx_ack_msg = &es58x_fd_urb_cmd->tx_ack_msg;212	ret = es58x_check_msg_len(es58x_dev->dev, *tx_ack_msg, msg_len);213	if (ret)214		return ret;215 216	return es58x_tx_ack_msg(netdev,217				get_unaligned_le16(&tx_ack_msg->tx_free_entries),218				get_unaligned_le32(&tx_ack_msg->rx_cmd_ret_le32));219}220 221static int es58x_fd_can_cmd_id(struct es58x_device *es58x_dev,222			       const struct es58x_fd_urb_cmd *es58x_fd_urb_cmd)223{224	struct net_device *netdev;225	int ret;226 227	ret = es58x_get_netdev(es58x_dev, es58x_fd_urb_cmd->channel_idx,228			       ES58X_FD_CHANNEL_IDX_OFFSET, &netdev);229	if (ret)230		return ret;231 232	switch ((enum es58x_fd_can_cmd_id)es58x_fd_urb_cmd->cmd_id) {233	case ES58X_FD_CAN_CMD_ID_ENABLE_CHANNEL:234		return es58x_fd_rx_cmd_ret_u32(netdev, es58x_fd_urb_cmd,235					       ES58X_RET_TYPE_ENABLE_CHANNEL);236 237	case ES58X_FD_CAN_CMD_ID_DISABLE_CHANNEL:238		return es58x_fd_rx_cmd_ret_u32(netdev, es58x_fd_urb_cmd,239					       ES58X_RET_TYPE_DISABLE_CHANNEL);240 241	case ES58X_FD_CAN_CMD_ID_TX_MSG:242		return es58x_fd_tx_ack_msg(netdev, es58x_fd_urb_cmd);243 244	case ES58X_FD_CAN_CMD_ID_ECHO_MSG:245		return es58x_fd_echo_msg(netdev, es58x_fd_urb_cmd);246 247	case ES58X_FD_CAN_CMD_ID_RX_MSG:248		return es58x_fd_rx_can_msg(netdev, es58x_fd_urb_cmd);249 250	case ES58X_FD_CAN_CMD_ID_RESET_RX:251		return es58x_fd_rx_cmd_ret_u32(netdev, es58x_fd_urb_cmd,252					       ES58X_RET_TYPE_RESET_RX);253 254	case ES58X_FD_CAN_CMD_ID_RESET_TX:255		return es58x_fd_rx_cmd_ret_u32(netdev, es58x_fd_urb_cmd,256					       ES58X_RET_TYPE_RESET_TX);257 258	case ES58X_FD_CAN_CMD_ID_ERROR_OR_EVENT_MSG:259		return es58x_fd_rx_event_msg(netdev, es58x_fd_urb_cmd);260 261	default:262		return -EBADRQC;263	}264}265 266static int es58x_fd_device_cmd_id(struct es58x_device *es58x_dev,267				  const struct es58x_fd_urb_cmd *es58x_fd_urb_cmd)268{269	u16 msg_len = get_unaligned_le16(&es58x_fd_urb_cmd->msg_len);270	int ret;271 272	switch ((enum es58x_fd_dev_cmd_id)es58x_fd_urb_cmd->cmd_id) {273	case ES58X_FD_DEV_CMD_ID_TIMESTAMP:274		ret = es58x_check_msg_len(es58x_dev->dev,275					  es58x_fd_urb_cmd->timestamp, msg_len);276		if (ret)277			return ret;278		es58x_rx_timestamp(es58x_dev,279				   get_unaligned_le64(&es58x_fd_urb_cmd->timestamp));280		return 0;281 282	default:283		return -EBADRQC;284	}285}286 287static int es58x_fd_handle_urb_cmd(struct es58x_device *es58x_dev,288				   const union es58x_urb_cmd *urb_cmd)289{290	const struct es58x_fd_urb_cmd *es58x_fd_urb_cmd;291	int ret;292 293	es58x_fd_urb_cmd = &urb_cmd->es58x_fd_urb_cmd;294 295	switch ((enum es58x_fd_cmd_type)es58x_fd_urb_cmd->cmd_type) {296	case ES58X_FD_CMD_TYPE_CAN:297	case ES58X_FD_CMD_TYPE_CANFD:298		ret = es58x_fd_can_cmd_id(es58x_dev, es58x_fd_urb_cmd);299		break;300 301	case ES58X_FD_CMD_TYPE_DEVICE:302		ret = es58x_fd_device_cmd_id(es58x_dev, es58x_fd_urb_cmd);303		break;304 305	default:306		ret = -EBADRQC;307		break;308	}309 310	if (ret == -EBADRQC)311		dev_err(es58x_dev->dev,312			"%s: Unknown command type (0x%02X) and command ID (0x%02X) combination\n",313			__func__, es58x_fd_urb_cmd->cmd_type,314			es58x_fd_urb_cmd->cmd_id);315 316	return ret;317}318 319static void es58x_fd_fill_urb_header(union es58x_urb_cmd *urb_cmd, u8 cmd_type,320				     u8 cmd_id, u8 channel_idx, u16 msg_len)321{322	struct es58x_fd_urb_cmd *es58x_fd_urb_cmd = &urb_cmd->es58x_fd_urb_cmd;323 324	es58x_fd_urb_cmd->SOF = cpu_to_le16(es58x_fd_param.tx_start_of_frame);325	es58x_fd_urb_cmd->cmd_type = cmd_type;326	es58x_fd_urb_cmd->cmd_id = cmd_id;327	es58x_fd_urb_cmd->channel_idx = channel_idx;328	es58x_fd_urb_cmd->msg_len = cpu_to_le16(msg_len);329}330 331static int es58x_fd_tx_can_msg(struct es58x_priv *priv,332			       const struct sk_buff *skb)333{334	struct es58x_device *es58x_dev = priv->es58x_dev;335	union es58x_urb_cmd *urb_cmd = priv->tx_urb->transfer_buffer;336	struct es58x_fd_urb_cmd *es58x_fd_urb_cmd = &urb_cmd->es58x_fd_urb_cmd;337	struct can_frame *cf = (struct can_frame *)skb->data;338	struct es58x_fd_tx_can_msg *tx_can_msg;339	bool is_fd = can_is_canfd_skb(skb);340	u16 msg_len;341	int ret;342 343	if (priv->tx_can_msg_cnt == 0) {344		msg_len = 0;345		es58x_fd_fill_urb_header(urb_cmd,346					 is_fd ? ES58X_FD_CMD_TYPE_CANFD347					       : ES58X_FD_CMD_TYPE_CAN,348					 ES58X_FD_CAN_CMD_ID_TX_MSG_NO_ACK,349					 priv->channel_idx, msg_len);350	} else {351		msg_len = es58x_fd_get_msg_len(urb_cmd);352	}353 354	ret = es58x_check_msg_max_len(es58x_dev->dev,355				      es58x_fd_urb_cmd->tx_can_msg_buf,356				      msg_len + sizeof(*tx_can_msg));357	if (ret)358		return ret;359 360	/* Fill message contents. */361	tx_can_msg = (typeof(tx_can_msg))&es58x_fd_urb_cmd->raw_msg[msg_len];362	tx_can_msg->packet_idx = (u8)priv->tx_head;363	put_unaligned_le32(es58x_get_raw_can_id(cf), &tx_can_msg->can_id);364	tx_can_msg->flags = (u8)es58x_get_flags(skb);365	if (is_fd)366		tx_can_msg->len = cf->len;367	else368		tx_can_msg->dlc = can_get_cc_dlc(cf, priv->can.ctrlmode);369	memcpy(tx_can_msg->data, cf->data, cf->len);370 371	/* Calculate new sizes */372	msg_len += es58x_fd_sizeof_rx_tx_msg(*tx_can_msg);373	priv->tx_urb->transfer_buffer_length = es58x_get_urb_cmd_len(es58x_dev,374								     msg_len);375	put_unaligned_le16(msg_len, &es58x_fd_urb_cmd->msg_len);376 377	return 0;378}379 380static void es58x_fd_convert_bittiming(struct es58x_fd_bittiming *es58x_fd_bt,381				       struct can_bittiming *bt)382{383	/* The actual value set in the hardware registers is one less384	 * than the functional value.385	 */386	const int offset = 1;387 388	es58x_fd_bt->bitrate = cpu_to_le32(bt->bitrate);389	es58x_fd_bt->tseg1 =390	    cpu_to_le16(bt->prop_seg + bt->phase_seg1 - offset);391	es58x_fd_bt->tseg2 = cpu_to_le16(bt->phase_seg2 - offset);392	es58x_fd_bt->brp = cpu_to_le16(bt->brp - offset);393	es58x_fd_bt->sjw = cpu_to_le16(bt->sjw - offset);394}395 396static int es58x_fd_enable_channel(struct es58x_priv *priv)397{398	struct es58x_device *es58x_dev = priv->es58x_dev;399	struct net_device *netdev = es58x_dev->netdev[priv->channel_idx];400	struct es58x_fd_tx_conf_msg tx_conf_msg = { 0 };401	u32 ctrlmode;402	size_t conf_len = 0;403 404	es58x_fd_convert_bittiming(&tx_conf_msg.nominal_bittiming,405				   &priv->can.bittiming);406	ctrlmode = priv->can.ctrlmode;407 408	if (ctrlmode & CAN_CTRLMODE_3_SAMPLES)409		tx_conf_msg.samples_per_bit = ES58X_SAMPLES_PER_BIT_THREE;410	else411		tx_conf_msg.samples_per_bit = ES58X_SAMPLES_PER_BIT_ONE;412	tx_conf_msg.sync_edge = ES58X_SYNC_EDGE_SINGLE;413	tx_conf_msg.physical_layer = ES58X_PHYSICAL_LAYER_HIGH_SPEED;414	tx_conf_msg.echo_mode = ES58X_ECHO_ON;415	if (ctrlmode & CAN_CTRLMODE_LISTENONLY)416		tx_conf_msg.ctrlmode |= ES58X_FD_CTRLMODE_PASSIVE;417	else418		tx_conf_msg.ctrlmode |=  ES58X_FD_CTRLMODE_ACTIVE;419 420	if (ctrlmode & CAN_CTRLMODE_FD_NON_ISO) {421		tx_conf_msg.ctrlmode |= ES58X_FD_CTRLMODE_FD_NON_ISO;422		tx_conf_msg.canfd_enabled = 1;423	} else if (ctrlmode & CAN_CTRLMODE_FD) {424		tx_conf_msg.ctrlmode |= ES58X_FD_CTRLMODE_FD;425		tx_conf_msg.canfd_enabled = 1;426	}427 428	if (tx_conf_msg.canfd_enabled) {429		es58x_fd_convert_bittiming(&tx_conf_msg.data_bittiming,430					   &priv->can.data_bittiming);431 432		if (can_tdc_is_enabled(&priv->can)) {433			tx_conf_msg.tdc_enabled = 1;434			tx_conf_msg.tdco = cpu_to_le16(priv->can.tdc.tdco);435			tx_conf_msg.tdcf = cpu_to_le16(priv->can.tdc.tdcf);436		}437 438		conf_len = ES58X_FD_CANFD_CONF_LEN;439	} else {440		conf_len = ES58X_FD_CAN_CONF_LEN;441	}442 443	return es58x_send_msg(es58x_dev, es58x_fd_cmd_type(netdev),444			      ES58X_FD_CAN_CMD_ID_ENABLE_CHANNEL,445			      &tx_conf_msg, conf_len, priv->channel_idx);446}447 448static int es58x_fd_disable_channel(struct es58x_priv *priv)449{450	/* The type (ES58X_FD_CMD_TYPE_CAN or ES58X_FD_CMD_TYPE_CANFD) does451	 * not matter here.452	 */453	return es58x_send_msg(priv->es58x_dev, ES58X_FD_CMD_TYPE_CAN,454			      ES58X_FD_CAN_CMD_ID_DISABLE_CHANNEL,455			      ES58X_EMPTY_MSG, 0, priv->channel_idx);456}457 458static int es58x_fd_get_timestamp(struct es58x_device *es58x_dev)459{460	return es58x_send_msg(es58x_dev, ES58X_FD_CMD_TYPE_DEVICE,461			      ES58X_FD_DEV_CMD_ID_TIMESTAMP, ES58X_EMPTY_MSG,462			      0, ES58X_CHANNEL_IDX_NA);463}464 465/* Nominal bittiming constants for ES582.1 and ES584.1 as specified in466 * the microcontroller datasheet: "SAM E70/S70/V70/V71 Family" section467 * 49.6.8 "MCAN Nominal Bit Timing and Prescaler Register" from468 * Microchip.469 *470 * The values from the specification are the hardware register471 * values. To convert them to the functional values, all ranges were472 * incremented by 1 (e.g. range [0..n-1] changed to [1..n]).473 */474static const struct can_bittiming_const es58x_fd_nom_bittiming_const = {475	.name = "ES582.1/ES584.1",476	.tseg1_min = 2,477	.tseg1_max = 256,478	.tseg2_min = 2,479	.tseg2_max = 128,480	.sjw_max = 128,481	.brp_min = 1,482	.brp_max = 512,483	.brp_inc = 1484};485 486/* Data bittiming constants for ES582.1 and ES584.1 as specified in487 * the microcontroller datasheet: "SAM E70/S70/V70/V71 Family" section488 * 49.6.4 "MCAN Data Bit Timing and Prescaler Register" from489 * Microchip.490 */491static const struct can_bittiming_const es58x_fd_data_bittiming_const = {492	.name = "ES582.1/ES584.1",493	.tseg1_min = 2,494	.tseg1_max = 32,495	.tseg2_min = 1,496	.tseg2_max = 16,497	.sjw_max = 8,498	.brp_min = 1,499	.brp_max = 32,500	.brp_inc = 1501};502 503/* Transmission Delay Compensation constants for ES582.1 and ES584.1504 * as specified in the microcontroller datasheet: "SAM E70/S70/V70/V71505 * Family" section 49.6.15 "MCAN Transmitter Delay Compensation506 * Register" from Microchip.507 */508static const struct can_tdc_const es58x_tdc_const = {509	.tdcv_min = 0,510	.tdcv_max = 0, /* Manual mode not supported. */511	.tdco_min = 0,512	.tdco_max = 127,513	.tdcf_min = 0,514	.tdcf_max = 127515};516 517const struct es58x_parameters es58x_fd_param = {518	.bittiming_const = &es58x_fd_nom_bittiming_const,519	.data_bittiming_const = &es58x_fd_data_bittiming_const,520	.tdc_const = &es58x_tdc_const,521	/* The devices use NXP TJA1044G transievers which guarantee522	 * the timing for data rates up to 5 Mbps. Bitrates up to 8523	 * Mbps work in an optimal environment but are not recommended524	 * for production environment.525	 */526	.bitrate_max = 8 * MEGA /* BPS */,527	.clock = {.freq = 80 * MEGA /* Hz */},528	.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY |529	    CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO |530	    CAN_CTRLMODE_CC_LEN8_DLC | CAN_CTRLMODE_TDC_AUTO,531	.tx_start_of_frame = 0xCEFA,	/* FACE in little endian */532	.rx_start_of_frame = 0xFECA,	/* CAFE in little endian */533	.tx_urb_cmd_max_len = ES58X_FD_TX_URB_CMD_MAX_LEN,534	.rx_urb_cmd_max_len = ES58X_FD_RX_URB_CMD_MAX_LEN,535	/* Size of internal device TX queue is 500.536	 *537	 * However, when reaching value around 278, the device's busy538	 * LED turns on and thus maximum value of 500 is never reached539	 * in practice. Also, when this value is too high, some error540	 * on the echo_msg were witnessed when the device is541	 * recovering from bus off.542	 *543	 * For above reasons, a value that would prevent the device544	 * from becoming busy was chosen. In practice, BQL would545	 * prevent the value from even getting closer to below546	 * maximum, so no impact on performance was measured.547	 */548	.fifo_mask = 255, /* echo_skb_max = 256 */549	.dql_min_limit = CAN_FRAME_LEN_MAX * 15, /* Empirical value. */550	.tx_bulk_max = ES58X_FD_TX_BULK_MAX,551	.urb_cmd_header_len = ES58X_FD_URB_CMD_HEADER_LEN,552	.rx_urb_max = ES58X_RX_URBS_MAX,553	.tx_urb_max = ES58X_TX_URBS_MAX554};555 556const struct es58x_operators es58x_fd_ops = {557	.get_msg_len = es58x_fd_get_msg_len,558	.handle_urb_cmd = es58x_fd_handle_urb_cmd,559	.fill_urb_header = es58x_fd_fill_urb_header,560	.tx_can_msg = es58x_fd_tx_can_msg,561	.enable_channel = es58x_fd_enable_channel,562	.disable_channel = es58x_fd_disable_channel,563	.reset_device = NULL, /* Not implemented in the device firmware. */564	.get_timestamp = es58x_fd_get_timestamp565};566