drivers/net/can/esd/esdacc.c

Source file repositories/reference/linux-study-clean/drivers/net/can/esd/esdacc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/esd/esdacc.c
Extension
.c
Size
21858 bytes
Lines
770
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 (core->tx_fifo_head == tx_fifo_tail) {
			netdev_warn(core->netdev,
				    "TX interrupt, but queue is empty!?\n");
			return;
		}

		/* Direct access echo skb to attach HW time stamp. */
		skb = priv->can.echo_skb[tx_fifo_tail];
		if (skb) {
			skb_hwtstamps(skb)->hwtstamp =
				acc_ts2ktime(priv->ov, msg->ts);
		}

		stats->tx_packets++;
		stats->tx_bytes += can_get_echo_skb(core->netdev, tx_fifo_tail,
						    NULL);

		core->tx_fifo_tail = acc_tx_fifo_next(core, tx_fifo_tail);

		netif_wake_queue(core->netdev);

	} else {
		struct can_frame *cf;

		skb = alloc_can_skb(core->netdev, &cf);
		if (!skb) {
			stats->rx_dropped++;
			return;
		}

		cf->can_id = msg->id & ACC_ID_ID_MASK;
		if (msg->id & ACC_ID_EFF_FLAG)
			cf->can_id |= CAN_EFF_FLAG;

		can_frame_set_cc_len(cf, msg->acc_dlc.len & ACC_DLC_DLC_MASK,
				     priv->can.ctrlmode);

		if (msg->acc_dlc.len & ACC_DLC_RTR_FLAG) {
			cf->can_id |= CAN_RTR_FLAG;
		} else {
			memcpy(cf->data, msg->data, cf->len);
			stats->rx_bytes += cf->len;
		}
		stats->rx_packets++;

		skb_hwtstamps(skb)->hwtstamp = acc_ts2ktime(priv->ov, msg->ts);

		netif_rx(skb);
	}
}

static void handle_core_msg_txabort(struct acc_core *core,
				    const struct acc_bmmsg_txabort *msg)
{
	struct net_device_stats *stats = &core->netdev->stats;
	u8 tx_fifo_tail = core->tx_fifo_tail;
	u32 abort_mask = msg->abort_mask;   /* u32 extend to avoid warnings later */

	/* The abort_mask shows which frames were aborted in esdACC's FIFO. */
	while (tx_fifo_tail != core->tx_fifo_head && (abort_mask)) {
		const u32 tail_mask = (1U << tx_fifo_tail);

		if (!(abort_mask & tail_mask))
			break;
		abort_mask &= ~tail_mask;

		can_free_echo_skb(core->netdev, tx_fifo_tail, NULL);
		stats->tx_dropped++;
		stats->tx_aborted_errors++;

		tx_fifo_tail = acc_tx_fifo_next(core, tx_fifo_tail);
	}
	core->tx_fifo_tail = tx_fifo_tail;
	if (abort_mask)
		netdev_warn(core->netdev, "Unhandled aborted messages\n");

	if (!acc_resetmode_entered(core))
		netif_wake_queue(core->netdev);
}

static void handle_core_msg_overrun(struct acc_core *core,
				    const struct acc_bmmsg_overrun *msg)
{
	struct acc_net_priv *priv = netdev_priv(core->netdev);
	struct net_device_stats *stats = &core->netdev->stats;
	struct can_frame *cf;
	struct sk_buff *skb;

	/* lost_cnt may be 0 if not supported by esdACC version */
	if (msg->lost_cnt) {

Annotation

Implementation Notes