drivers/net/can/rockchip/rockchip_canfd-rx.c

Source file repositories/reference/linux-study-clean/drivers/net/can/rockchip/rockchip_canfd-rx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/rockchip/rockchip_canfd-rx.c
Extension
.c
Size
7464 bytes
Lines
300
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 (header->frameinfo & RKCANFD_REG_FD_FRAMEINFO_RTR) {
			cfd->can_id |= CAN_RTR_FLAG;

			return len;
		}
	}

	return len + cfd->len;
}

static int rkcanfd_rxstx_filter(struct rkcanfd_priv *priv,
				const struct canfd_frame *cfd_rx, const u32 ts,
				bool *tx_done)
{
	struct net_device_stats *stats = &priv->ndev->stats;
	struct rkcanfd_stats *rkcanfd_stats = &priv->stats;
	const struct canfd_frame *cfd_nominal;
	const struct sk_buff *skb;
	unsigned int tx_tail;

	tx_tail = rkcanfd_get_tx_tail(priv);
	skb = priv->can.echo_skb[tx_tail];
	if (!skb) {
		netdev_err(priv->ndev,
			   "%s: echo_skb[%u]=NULL tx_head=0x%08x tx_tail=0x%08x\n",
			   __func__, tx_tail,
			   priv->tx_head, priv->tx_tail);

		return -ENOMSG;
	}
	cfd_nominal = (struct canfd_frame *)skb->data;

	/* We RX'ed a frame identical to our pending TX frame. */
	if (rkcanfd_can_frame_header_equal(cfd_rx, cfd_nominal,
					   cfd_rx->flags & CANFD_FDF) &&
	    rkcanfd_can_frame_data_equal(cfd_rx, cfd_nominal,
					 cfd_rx->flags & CANFD_FDF)) {
		unsigned int frame_len;

		rkcanfd_handle_tx_done_one(priv, ts, &frame_len);

		WRITE_ONCE(priv->tx_tail, priv->tx_tail + 1);
		netif_subqueue_completed_wake(priv->ndev, 0, 1, frame_len,
					      rkcanfd_get_effective_tx_free(priv),
					      RKCANFD_TX_START_THRESHOLD);

		*tx_done = true;

		return 0;
	}

	if (!(priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_6))
		return 0;

	/* Erratum 6: Extended frames may be send as standard frames.
	 *
	 * Not affected if:
	 * - TX'ed a standard frame -or-
	 * - RX'ed an extended frame
	 */
	if (!(cfd_nominal->can_id & CAN_EFF_FLAG) ||
	    (cfd_rx->can_id & CAN_EFF_FLAG))
		return 0;

	/* Not affected if:
	 * - standard part and RTR flag of the TX'ed frame
	 *   is not equal the CAN-ID and RTR flag of the RX'ed frame.
	 */
	if ((cfd_nominal->can_id & (CAN_RTR_FLAG | CAN_SFF_MASK)) !=
	    (cfd_rx->can_id & (CAN_RTR_FLAG | CAN_SFF_MASK)))
		return 0;

	/* Not affected if:
	 * - length is not the same
	 */
	if (cfd_nominal->len != cfd_rx->len)
		return 0;

	/* Not affected if:
	 * - the data of non RTR frames is different
	 */
	if (!(cfd_nominal->can_id & CAN_RTR_FLAG) &&
	    memcmp(cfd_nominal->data, cfd_rx->data, cfd_nominal->len))
		return 0;

	/* Affected by Erratum 6 */
	u64_stats_update_begin(&rkcanfd_stats->syncp);
	u64_stats_inc(&rkcanfd_stats->tx_extended_as_standard_errors);
	u64_stats_update_end(&rkcanfd_stats->syncp);

Annotation

Implementation Notes