diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index f76ed64fb9e6..729072622fcb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3619,6 +3619,17 @@ static void stmmac_safety_feat_configuration(struct stmmac_priv *priv) } } +/* STM32MP25xx (dwmac v5.3) states "Do not enable time-based scheduling for + * channels on which the TSO feature is enabled." If we have a skb for a + * channel which has TBS enabled, fall back to software GSO. + */ +static bool stmmac_tso_channel_permitted(struct stmmac_priv *priv, + unsigned int chan) +{ + /* TSO and TBS cannot co-exist */ + return !(priv->dma_conf.tx_queue[chan].tbs & STMMAC_TBS_AVAIL); +} + /** * stmmac_hw_setup - setup mac in a usable state. * @dev : pointer to the device structure. @@ -3707,10 +3718,7 @@ static int stmmac_hw_setup(struct net_device *dev) /* Enable TSO */ if (priv->dma_cap.tsoen && priv->plat->flags & STMMAC_FLAG_TSO_EN) { for (chan = 0; chan < tx_cnt; chan++) { - struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan]; - - /* TSO and TBS cannot co-exist */ - if (tx_q->tbs & STMMAC_TBS_AVAIL) + if (!stmmac_tso_channel_permitted(priv, chan)) continue; stmmac_enable_tso(priv, priv->ioaddr, 1, chan); @@ -4919,6 +4927,21 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } +static netdev_features_t stmmac_features_check(struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features) +{ + u16 queue; + + if (skb_is_gso(skb)) { + queue = skb_get_queue_mapping(skb); + if (!stmmac_tso_channel_permitted(netdev_priv(dev), queue)) + features &= ~NETIF_F_GSO_MASK; + } + + return vlan_features_check(skb, features); +} + static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb) { struct vlan_ethhdr *veth = skb_vlan_eth_hdr(skb); @@ -7208,6 +7231,7 @@ static void stmmac_get_stats64(struct net_device *dev, struct rtnl_link_stats64 static const struct net_device_ops stmmac_netdev_ops = { .ndo_open = stmmac_open, .ndo_start_xmit = stmmac_xmit, + .ndo_features_check = stmmac_features_check, .ndo_stop = stmmac_release, .ndo_change_mtu = stmmac_change_mtu, .ndo_fix_features = stmmac_fix_features,