drivers/net/ethernet/cadence/macb_ptp.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/cadence/macb_ptp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/cadence/macb_ptp.c
Extension
.c
Size
12080 bytes
Lines
471
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 (!desc_ptp) {
			dev_warn_ratelimited(&bp->pdev->dev,
					     "Timestamp not supported in BD\n");
			return;
		}
		gem_hw_timestamp(bp, desc_ptp->ts_1, desc_ptp->ts_2, &ts);
		memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
		shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
	}
}

void gem_ptp_txstamp(struct macb *bp, struct sk_buff *skb,
		     struct macb_dma_desc *desc)
{
	struct skb_shared_hwtstamps shhwtstamps;
	struct macb_dma_desc_ptp *desc_ptp;
	struct timespec64 ts;

	if (!GEM_BFEXT(DMA_TXVALID, desc->ctrl)) {
		dev_warn_ratelimited(&bp->pdev->dev,
				     "Timestamp not set in TX BD as expected\n");
		return;
	}

	desc_ptp = macb_ptp_desc(bp, desc);
	/* Unlikely but check */
	if (!desc_ptp) {
		dev_warn_ratelimited(&bp->pdev->dev,
				     "Timestamp not supported in BD\n");
		return;
	}

	/* ensure ts_1/ts_2 is loaded after ctrl (TX_USED check) */
	dma_rmb();
	gem_hw_timestamp(bp, desc_ptp->ts_1, desc_ptp->ts_2, &ts);

	memset(&shhwtstamps, 0, sizeof(shhwtstamps));
	shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
	skb_tstamp_tx(skb, &shhwtstamps);
}

void gem_ptp_init(struct net_device *dev)
{
	struct macb *bp = netdev_priv(dev);

	bp->ptp_clock_info = gem_ptp_caps_template;

	/* nominal frequency and maximum adjustment in ppb */
	bp->tsu_rate = bp->ptp_info->get_tsu_rate(bp);
	bp->ptp_clock_info.max_adj = bp->ptp_info->get_ptp_max_adj();
	gem_ptp_init_timer(bp);
	bp->ptp_clock = ptp_clock_register(&bp->ptp_clock_info, &dev->dev);
	if (IS_ERR(bp->ptp_clock)) {
		pr_err("ptp clock register failed: %ld\n",
			PTR_ERR(bp->ptp_clock));
		bp->ptp_clock = NULL;
		return;
	} else if (bp->ptp_clock == NULL) {
		pr_err("ptp clock register failed\n");
		return;
	}

	spin_lock_init(&bp->tsu_clk_lock);

	gem_ptp_init_tsu(bp);

	dev_info(&bp->pdev->dev, "%s ptp clock registered.\n",
		 GEM_PTP_TIMER_NAME);
}

void gem_ptp_remove(struct net_device *ndev)
{
	struct macb *bp = netdev_priv(ndev);

	if (bp->ptp_clock) {
		ptp_clock_unregister(bp->ptp_clock);
		bp->ptp_clock = NULL;
	}

	gem_ptp_clear_timer(bp);

	dev_info(&bp->pdev->dev, "%s ptp clock unregistered.\n",
		 GEM_PTP_TIMER_NAME);
}

static int gem_ptp_set_ts_mode(struct macb *bp,
			       enum macb_bd_control tx_bd_control,
			       enum macb_bd_control rx_bd_control)
{
	gem_writel(bp, TXBDCTRL, GEM_BF(TXTSMODE, tx_bd_control));

Annotation

Implementation Notes