On Mon, 17 Feb 2025 14:01:09 +0100 Lorenzo Bianconi wrote: > +static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev) > +{ > +#if IS_ENABLED(CONFIG_NET_DSA) > + struct ethhdr *ehdr; > + struct dsa_port *dp; > + u8 xmit_tpid; > + u16 tag; > + > + if (!netdev_uses_dsa(dev)) > + return 0; > + > + dp = dev->dsa_ptr; > + if (IS_ERR(dp)) > + return 0; > + > + if (dp->tag_ops->proto != DSA_TAG_PROTO_MTK) > + return 0; > + > + if (skb_ensure_writable(skb, ETH_HLEN)) > + return 0; skb_cow_head() is a lot cheaper (for TCP) > + ehdr = (struct ethhdr *)skb->data; > + tag = be16_to_cpu(ehdr->h_proto); > + xmit_tpid = tag >> 8; > @@ -2390,8 +2498,10 @@ static int airoha_probe(struct platform_device *pdev) > for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { > struct airoha_gdm_port *port = eth->ports[i]; > > - if (port && port->dev->reg_state == NETREG_REGISTERED) > + if (port && port->dev->reg_state == NETREG_REGISTERED) { > + airoha_metadata_dst_free(port); > unregister_netdev(port->dev); Looks a tiny bit reversed, isn't it? First unregister the netdev, then free its metadata. > + } > } > free_netdev(eth->napi_dev); > platform_set_drvdata(pdev, NULL); > @@ -2416,6 +2526,7 @@ static void airoha_remove(struct platform_device *pdev) > continue; > > airoha_dev_stop(port->dev); > + airoha_metadata_dst_free(port); > unregister_netdev(port->dev); same here > } > free_netdev(eth->napi_dev);