drivers/net/ethernet/microchip/sparx5/sparx5_packet.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/microchip/sparx5/sparx5_packet.c
Extension
.c
Size
10117 bytes
Lines
381
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

switch (cmp) {
		case XTR_NOT_READY:
			break;
		case XTR_ABORT:
			/* No accompanying data */
			abort_flag = true;
			eof_flag = true;
			break;
		case XTR_EOF_0:
		case XTR_EOF_1:
		case XTR_EOF_2:
		case XTR_EOF_3:
			/* This assumes STATUS_WORD_POS == 1, Status
			 * just after last data
			 */
			if (!byte_swap)
				val = ntohl((__force __be32)val);
			byte_cnt -= (4 - XTR_VALID_BYTES(val));
			eof_flag = true;
			break;
		case XTR_PRUNED:
			/* But get the last 4 bytes as well */
			eof_flag = true;
			pruned_flag = true;
			fallthrough;
		case XTR_ESCAPE:
			*rxbuf = spx5_rd(sparx5, QS_XTR_RD(grp));
			byte_cnt += 4;
			rxbuf++;
			break;
		default:
			*rxbuf = val;
			byte_cnt += 4;
			rxbuf++;
		}
	}

	if (abort_flag || pruned_flag || !eof_flag) {
		netdev_err(netdev, "Discarded frame: abort:%d pruned:%d eof:%d\n",
			   abort_flag, pruned_flag, eof_flag);
		kfree_skb(skb);
		netdev->stats.rx_dropped++;
		return;
	}

	/* Everything we see on an interface that is in the HW bridge
	 * has already been forwarded
	 */
	if (test_bit(port->portno, sparx5->bridge_mask))
		skb->offload_fwd_mark = 1;

	/* Finish up skb */
	skb_put(skb, byte_cnt - ETH_FCS_LEN);
	eth_skb_pad(skb);
	sparx5_ptp_rxtstamp(sparx5, skb, fi.timestamp);
	skb->protocol = eth_type_trans(skb, netdev);
	netdev->stats.rx_bytes += skb->len;
	netdev->stats.rx_packets++;
	netif_rx(skb);
}

static int sparx5_inject(struct sparx5 *sparx5,
			 u32 *ifh,
			 struct sk_buff *skb,
			 struct net_device *ndev)
{
	int grp = INJ_QUEUE;
	u32 val, w, count;
	u8 *buf;

	val = spx5_rd(sparx5, QS_INJ_STATUS);
	if (!(QS_INJ_STATUS_FIFO_RDY_GET(val) & BIT(grp))) {
		pr_err_ratelimited("Injection: Queue not ready: 0x%lx\n",
				   QS_INJ_STATUS_FIFO_RDY_GET(val));
		return -EBUSY;
	}

	/* Indicate SOF */
	spx5_wr(QS_INJ_CTRL_SOF_SET(1) |
		QS_INJ_CTRL_GAP_SIZE_SET(1),
		sparx5, QS_INJ_CTRL(grp));

	/* Write the IFH to the chip. */
	for (w = 0; w < IFH_LEN; w++)
		spx5_wr(ifh[w], sparx5, QS_INJ_WR(grp));

	/* Write words, round up */
	count = DIV_ROUND_UP(skb->len, 4);
	buf = skb->data;
	for (w = 0; w < count; w++, buf += 4) {

Annotation

Implementation Notes