drivers/net/can/usb/etas_es58x/es58x_fd.c

Source file repositories/reference/linux-study-clean/drivers/net/can/usb/etas_es58x/es58x_fd.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/usb/etas_es58x/es58x_fd.c
Extension
.c
Size
17903 bytes
Lines
566
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if ((u8)rcv_packet_idx != echo_msg[i].packet_idx) {
			netdev_err(netdev, "Packet idx jumped from %u to %u\n",
				   (u8)rcv_packet_idx - 1,
				   echo_msg[i].packet_idx);
			return -EBADMSG;
		}

		tstamps[i] = get_unaligned_le64(&echo_msg[i].timestamp);
		rcv_packet_idx++;
	}

	return es58x_can_get_echo_skb(netdev, priv->tx_tail, tstamps, num_element);
}

static int es58x_fd_rx_can_msg(struct net_device *netdev,
			       const struct es58x_fd_urb_cmd *es58x_fd_urb_cmd)
{
	struct es58x_device *es58x_dev = es58x_priv(netdev)->es58x_dev;
	const u8 *rx_can_msg_buf = es58x_fd_urb_cmd->rx_can_msg_buf;
	u16 rx_can_msg_buf_len = get_unaligned_le16(&es58x_fd_urb_cmd->msg_len);
	int pkts, ret;

	ret = es58x_check_msg_max_len(es58x_dev->dev,
				      es58x_fd_urb_cmd->rx_can_msg_buf,
				      rx_can_msg_buf_len);
	if (ret)
		return ret;

	for (pkts = 0; rx_can_msg_buf_len > 0; pkts++) {
		const struct es58x_fd_rx_can_msg *rx_can_msg =
		    (const struct es58x_fd_rx_can_msg *)rx_can_msg_buf;
		bool is_can_fd = !!(rx_can_msg->flags & ES58X_FLAG_FD_DATA);
		/* rx_can_msg_len is the length of the rx_can_msg
		 * buffer. Not to be confused with rx_can_msg->len
		 * which is the length of the CAN payload
		 * rx_can_msg->data.
		 */
		u16 rx_can_msg_len = es58x_fd_sizeof_rx_tx_msg(*rx_can_msg);

		if (rx_can_msg_len > rx_can_msg_buf_len) {
			netdev_err(netdev,
				   "%s: Expected a rx_can_msg of size %d but only %d bytes are left in rx_can_msg_buf\n",
				   __func__,
				   rx_can_msg_len, rx_can_msg_buf_len);
			return -EMSGSIZE;
		}
		if (rx_can_msg->len > CANFD_MAX_DLEN) {
			netdev_err(netdev,
				   "%s: Data length is %d but maximum should be %d\n",
				   __func__, rx_can_msg->len, CANFD_MAX_DLEN);
			return -EMSGSIZE;
		}

		if (netif_running(netdev)) {
			u64 tstamp = get_unaligned_le64(&rx_can_msg->timestamp);
			canid_t can_id = get_unaligned_le32(&rx_can_msg->can_id);
			u8 dlc;

			if (is_can_fd)
				dlc = can_fd_len2dlc(rx_can_msg->len);
			else
				dlc = rx_can_msg->dlc;

			ret = es58x_rx_can_msg(netdev, tstamp, rx_can_msg->data,
					       can_id, rx_can_msg->flags, dlc);
			if (ret)
				break;
		}

		rx_can_msg_buf_len -= rx_can_msg_len;
		rx_can_msg_buf += rx_can_msg_len;
	}

	if (!netif_running(netdev)) {
		if (net_ratelimit())
			netdev_info(netdev,
				    "%s: %s is down, dropping %d rx packets\n",
				    __func__, netdev->name, pkts);
		netdev->stats.rx_dropped += pkts;
	}

	return ret;
}

static int es58x_fd_rx_event_msg(struct net_device *netdev,
				 const struct es58x_fd_urb_cmd *es58x_fd_urb_cmd)
{
	struct es58x_device *es58x_dev = es58x_priv(netdev)->es58x_dev;
	u16 msg_len = get_unaligned_le16(&es58x_fd_urb_cmd->msg_len);
	const struct es58x_fd_rx_event_msg *rx_event_msg;

Annotation

Implementation Notes