On Mon, Jul 01, 2019 at 12:03:27PM +0200, Antoine Tenart wrote: > +static irqreturn_t ocelot_ptp_rdy_irq_handler(int irq, void *arg) > +{ > + struct ocelot *ocelot = arg; > + > + do { > + struct skb_shared_hwtstamps shhwtstamps; > + struct list_head *pos, *tmp; > + struct ocelot_skb *entry; > + struct ocelot_port *port; > + struct timespec64 ts; > + struct sk_buff *skb = NULL; > + u32 val, id, txport; > + > + val = ocelot_read(ocelot, SYS_PTP_STATUS); > + > + /* Check if a timestamp can be retrieved */ > + if (!(val & SYS_PTP_STATUS_PTP_MESS_VLD)) > + break;
Instead of an infinite do/while loop, I suggest a for loop bounded by number of iterations or by execution time. That would avoid getting stuck here forever. After all, this code is an ISR. Thanks, Richard > + WARN_ON(val & SYS_PTP_STATUS_PTP_OVFL); > + > + /* Retrieve the ts ID and Tx port */ > + id = SYS_PTP_STATUS_PTP_MESS_ID_X(val); > + txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val); > + > + /* Retrieve its associated skb */ > + port = ocelot->ports[txport]; > + > + list_for_each_safe(pos, tmp, &port->skbs) { > + entry = list_entry(pos, struct ocelot_skb, head); > + if (entry->id != id) > + continue; > + > + skb = entry->skb; > + > + list_del(pos); > + kfree(entry); > + } > + > + /* Next ts */ > + ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT); > + > + if (unlikely(!skb)) > + continue; > + > + /* Get the h/w timestamp */ > + ocelot_get_hwtimestamp(ocelot, &ts); > + > + /* Set the timestamp into the skb */ > + memset(&shhwtstamps, 0, sizeof(shhwtstamps)); > + shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec); > + skb_tstamp_tx(skb, &shhwtstamps); > + > + dev_kfree_skb_any(skb); > + } while (true); > + > + return IRQ_HANDLED; > +}