drivers/net/dsa/sja1105/sja1105_ptp.c

Source file repositories/reference/linux-study-clean/drivers/net/dsa/sja1105/sja1105_ptp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/dsa/sja1105/sja1105_ptp.c
Extension
.c
Size
26255 bytes
Lines
971
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 (rc < 0) {
			dev_err(ds->dev, "Failed to read PTP clock: %d\n", rc);
			kfree_skb(skb);
			continue;
		}

		*shwt = (struct skb_shared_hwtstamps) {0};

		ts = SJA1105_SKB_CB(skb)->tstamp;
		ts = sja1105_tstamp_reconstruct(ds, ticks, ts);

		shwt->hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(ts));
		netif_rx(skb);
	}

	if (ptp_data->extts_enabled)
		sja1105_extts_poll(priv);

	mutex_unlock(&ptp_data->lock);

	/* Don't restart */
	return -1;
}

bool sja1105_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{
	struct sja1105_private *priv = ds->priv;
	struct sja1105_ptp_data *ptp_data = &priv->ptp_data;

	if (!(priv->hwts_rx_en & BIT(port)))
		return false;

	/* We need to read the full PTP clock to reconstruct the Rx
	 * timestamp. For that we need a sleepable context.
	 */
	skb_queue_tail(&ptp_data->skb_rxtstamp_queue, skb);
	ptp_schedule_worker(ptp_data->clock, 0);
	return true;
}

bool sja1110_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{
	struct skb_shared_hwtstamps *shwt = skb_hwtstamps(skb);
	u64 ts = SJA1105_SKB_CB(skb)->tstamp;

	*shwt = (struct skb_shared_hwtstamps) {0};

	shwt->hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(ts));

	/* Don't defer */
	return false;
}

/* Called from dsa_skb_defer_rx_timestamp */
bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
			   struct sk_buff *skb, unsigned int type)
{
	struct sja1105_private *priv = ds->priv;

	return priv->info->rxtstamp(ds, port, skb);
}

void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id,
				 enum sja1110_meta_tstamp dir, u64 tstamp)
{
	struct sja1105_private *priv = ds->priv;
	struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
	struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
	struct skb_shared_hwtstamps shwt = {0};

	/* We don't care about RX timestamps on the CPU port */
	if (dir == SJA1110_META_TSTAMP_RX)
		return;

	spin_lock(&ptp_data->skb_txtstamp_queue.lock);

	skb_queue_walk_safe(&ptp_data->skb_txtstamp_queue, skb, skb_tmp) {
		if (SJA1105_SKB_CB(skb)->ts_id != ts_id)
			continue;

		__skb_unlink(skb, &ptp_data->skb_txtstamp_queue);
		skb_match = skb;

		break;
	}

	spin_unlock(&ptp_data->skb_txtstamp_queue.lock);

	if (WARN_ON(!skb_match))
		return;

Annotation

Implementation Notes