Re: [RFC Patch net-next v2 7/8] net: dsa: microchip: add the transmission tstamp logic

From: Vladimir Oltean
Date: Mon Nov 21 2022 - 17:51:32 EST


Hi Arun,

On Mon, Nov 21, 2022 at 09:11:49PM +0530, Arun Ramadoss wrote:
> This patch adds the routines for transmission of ptp packets. When the
> ptp packets(sync, pdelay_req, pdelay_rsp) to be transmitted, the skb is
> copied to global skb through port_txtstamp ioctl.
> After the packet is transmitted, ISR is triggered. The time at which
> packet transmitted is recorded to separate register available for each
> message. This value is reconstructed to absolute time and posted to the
> user application through skb complete.

"skb complete" is not a thing. "socket error queue" is.

>
> Signed-off-by: Christian Eggers <ceggers@xxxxxxx>
> Signed-off-by: Rakesh Sankaranarayanan <rakesh.sankaranarayanan@xxxxxxxxxxxxx>
> Signed-off-by: Arun Ramadoss <arun.ramadoss@xxxxxxxxxxxxx>
> ---
> +static void ksz_ptp_txtstamp_skb(struct ksz_device *dev,
> + struct ksz_port *prt, struct sk_buff *skb)
> +{
> + struct skb_shared_hwtstamps hwtstamps = {};
> + int ret;
> +
> + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
> +
> + /* timeout must include tstamp latency, IRQ latency and time for
> + * reading the time stamp.
> + */
> + ret = wait_for_completion_timeout(&prt->tstamp_msg_comp,
> + msecs_to_jiffies(100));
> + if (!ret)
> + return;
> +
> + hwtstamps.hwtstamp = prt->tstamp_msg;
> + skb_complete_tx_timestamp(skb, &hwtstamps);
> +}
> +
> +#define work_to_xmit_work(w) \
> + container_of((w), struct ksz_deferred_xmit_work, work)
> +void ksz_port_deferred_xmit(struct kthread_work *work)
> +{
> + struct ksz_deferred_xmit_work *xmit_work = work_to_xmit_work(work);
> + struct sk_buff *clone, *skb = xmit_work->skb;
> + struct dsa_switch *ds = xmit_work->dp->ds;
> + struct ksz_device *dev = ds->priv;
> + struct ksz_port *prt;
> +
> + prt = &dev->ports[xmit_work->dp->index];
> +
> + clone = KSZ_SKB_CB(skb)->clone;
> +
> + reinit_completion(&prt->tstamp_msg_comp);
> +
> + /* Transfer skb to the host port. */
> + dsa_enqueue_skb(skb, skb->dev);
> +
> + ksz_ptp_txtstamp_skb(dev, prt, clone);
> +
> + kfree(xmit_work);
> +}
> +
> static const struct ptp_clock_info ksz_ptp_caps = {
> .owner = THIS_MODULE,
> .name = "Microchip Clock",
> @@ -514,7 +568,29 @@ void ksz_ptp_clock_unregister(struct dsa_switch *ds)
>
> static irqreturn_t ksz_ptp_msg_thread_fn(int irq, void *dev_id)
> {
> - return IRQ_NONE;
> + struct ksz_ptp_irq *ptpmsg_irq = dev_id;
> + struct ksz_device *dev;
> + struct ksz_port *port;
> + u32 tstamp_raw;
> + ktime_t tstamp;
> + int ret;
> +
> + port = ptpmsg_irq->port;
> + dev = port->ksz_dev;
> +
> + if (ptpmsg_irq->ts_en) {
> + ret = ksz_read32(dev, ptpmsg_irq->ts_reg, &tstamp_raw);
> + if (ret)
> + return IRQ_NONE;
> +
> + tstamp = ksz_decode_tstamp(tstamp_raw);
> +
> + port->tstamp_msg = ksz_tstamp_reconstruct(dev->ds, tstamp);
> +
> + complete(&port->tstamp_msg_comp);
> + }
> +
> + return IRQ_HANDLED;
> }

I dug out some notes I had taken while reviewing a previous patch set
from Christian. There was a race condition which caused rare TX timestamping
timeouts, and the issue seems very much still present here. See below my
notes, luckily they resulted in a patch which solved the problem at the time.