On Tue, Apr 20, 2021 at 07:33:39AM +0000, Y.b. Lu wrote: > > > + /* For two-step timestamp, retrieve ptp_cmd in DSA_SKB_CB_PRIV > > > + * and timestamp ID in clone->cb[0]. > > > + * For one-step timestamp, retrieve ptp_cmd in DSA_SKB_CB_PRIV. > > > + */ > > > + u8 *ptp_cmd = DSA_SKB_CB_PRIV(skb); > > > > This is fine in the sense that it works, but please consider creating something > > similar to sja1105: > > > > struct ocelot_skb_cb { > > u8 ptp_cmd; /* For both one-step and two-step timestamping */ > > u8 ts_id; /* Only for two-step timestamping */ }; > > > > #define OCELOT_SKB_CB(skb) \ > > ((struct ocelot_skb_cb *)DSA_SKB_CB_PRIV(skb)) > > > > And then access as OCELOT_SKB_CB(skb)->ptp_cmd, > > OCELOT_SKB_CB(clone)->ts_id. > > > > and put a comment to explain that this is done in order to have common code > > between Felix DSA and Ocelot switchdev. Basically Ocelot will not use the first > > 8 bytes of skb->cb, but there's enough space for this to not make any > > difference. The original skb will hold only ptp_cmd, the clone will only hold > > ts_id, but it helps to have the same structure in place. > > > > If you create this ocelot_skb_cb structure, I expect the comment above to be > > fairly redundant, you can consider removing it. > > > > You're right to define the structure. > Considering patch #1, move skb cloning to drivers, and populate DSA_SKB_CB(skb)->clone if needs to do so (per suggestion). > Can we totally drop dsa_skb_cb in dsa core? The only usage of it is holding a skb clone pointer, for only felix and sja1105. > Actually we can move such pointer in <device>_skb_cb, instead of reserving the space of skb for any drivers. > > Do you think so? The trouble with skb->cb is that it isn't zero-initialized. But somebody needs to initialize the clone pointer to NULL, otherwise you don't know if this is a valid pointer or not. Because dsa_skb_tx_timestamp() is called before p->xmit(), the driver has no way to initialize the clone pointer by itself. So this was done directly from dsa_slave_xmit(), and not from any driver-specific hook. So this is why there is a DSA_SKB_CB(skb)->clone and not SJA1105_SKB_CB(skb)->clone. The alternative would be to memset(skb->cb, 0, 48) which is a bit sub-optimal because it initializes more than it needs. Alternatively, it might be possible to introduce a new property in struct dsa_device_ops which holds sizeof(struct sja1105_skb_cb), and the generic code will only zero-initialize this number of bytes. I don't know, if you can get it to work in a way that does not incur a noticeable performance penalty, I'm okay with whatever you come up with.