wifi: mac80211: add support for letting drivers register tc offload support
authorFelix Fietkau <nbd@nbd.name>
Tue, 21 Mar 2023 09:12:48 +0000 (10:12 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 22 Mar 2023 12:20:03 +0000 (13:20 +0100)
On newer MediaTek SoCs (e.g. MT7986), WLAN->WLAN or WLAN->Ethernet flows can
be offloaded by the SoC. In order to support that, the .ndo_setup_tc op is
needed.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://lore.kernel.org/r/20230321091248.30947-1-nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/driver-ops.h
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/trace.h

index f12edca660ba0d73c84e84200657d5e9c9740759..fcfe3e9aff3dae9d612d79893af6fd1640a8ad07 100644 (file)
@@ -4227,6 +4227,10 @@ struct ieee80211_prep_tx_info {
  * @set_hw_timestamp: Enable/disable HW timestamping of TM/FTM frames. This is
  *     not restored at HW reset by mac80211 so drivers need to take care of
  *     that.
+ * @net_setup_tc: Called from .ndo_setup_tc in order to prepare hardware
+ *     flow offloading for flows originating from the vif.
+ *     Note that the driver must not assume that the vif driver_data is valid
+ *     at this point, since the callback can be called during netdev teardown.
  */
 struct ieee80211_ops {
        void (*tx)(struct ieee80211_hw *hw,
@@ -4593,6 +4597,11 @@ struct ieee80211_ops {
        int (*set_hw_timestamp)(struct ieee80211_hw *hw,
                                struct ieee80211_vif *vif,
                                struct cfg80211_set_hw_timestamp *hwts);
+       int (*net_setup_tc)(struct ieee80211_hw *hw,
+                           struct ieee80211_vif *vif,
+                           struct net_device *dev,
+                           enum tc_setup_type type,
+                           void *type_data);
 };
 
 /**
index a68d606e6987222e37e7d0ab33ff5885910989fb..0bf208f5bbc5dec278392e8373f9f69043b318aa 100644 (file)
@@ -1502,6 +1502,23 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
        return ret;
 }
 
+static inline int drv_net_setup_tc(struct ieee80211_local *local,
+                                  struct ieee80211_sub_if_data *sdata,
+                                  struct net_device *dev,
+                                  enum tc_setup_type type, void *type_data)
+{
+       int ret = -EOPNOTSUPP;
+
+       sdata = get_bss_sdata(sdata);
+       trace_drv_net_setup_tc(local, sdata, type);
+       if (local->ops->net_setup_tc)
+               ret = local->ops->net_setup_tc(&local->hw, &sdata->vif, dev,
+                                              type, type_data);
+       trace_drv_return_int(local, ret);
+
+       return ret;
+}
+
 int drv_change_vif_links(struct ieee80211_local *local,
                         struct ieee80211_sub_if_data *sdata,
                         u16 old_links, u16 new_links,
index 3d4edc25a69e04cdbc76d38af0c37cfa4a3bede3..b2535614483ef557f1e2110375d98a6122a42818 100644 (file)
@@ -1939,7 +1939,8 @@ void ieee80211_color_collision_detection_work(struct work_struct *work);
 /* interface handling */
 #define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
                                         NETIF_F_HW_CSUM | NETIF_F_SG | \
-                                        NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE)
+                                        NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE | \
+                                        NETIF_F_HW_TC)
 #define MAC80211_SUPPORTED_FEATURES_RX (NETIF_F_RXCSUM)
 #define MAC80211_SUPPORTED_FEATURES    (MAC80211_SUPPORTED_FEATURES_TX | \
                                         MAC80211_SUPPORTED_FEATURES_RX)
index 23ed13f150675d1ffa869796c857f5905fb8dae8..bd2c48870add1bdbb35e277fe4df3d5cb887e35c 100644 (file)
@@ -813,6 +813,15 @@ ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
        dev_fetch_sw_netstats(stats, dev->tstats);
 }
 
+static int ieee80211_netdev_setup_tc(struct net_device *dev,
+                                    enum tc_setup_type type, void *type_data)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
+
+       return drv_net_setup_tc(local, sdata, dev, type, type_data);
+}
+
 static const struct net_device_ops ieee80211_dataif_ops = {
        .ndo_open               = ieee80211_open,
        .ndo_stop               = ieee80211_stop,
@@ -821,6 +830,7 @@ static const struct net_device_ops ieee80211_dataif_ops = {
        .ndo_set_rx_mode        = ieee80211_set_multicast_list,
        .ndo_set_mac_address    = ieee80211_change_mac,
        .ndo_get_stats64        = ieee80211_get_stats64,
+       .ndo_setup_tc           = ieee80211_netdev_setup_tc,
 };
 
 static u16 ieee80211_monitor_select_queue(struct net_device *dev,
@@ -929,6 +939,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
        .ndo_set_mac_address    = ieee80211_change_mac,
        .ndo_get_stats64        = ieee80211_get_stats64,
        .ndo_fill_forward_path  = ieee80211_netdev_fill_forward_path,
+       .ndo_setup_tc           = ieee80211_netdev_setup_tc,
 };
 
 static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype)
index 9f4377566c425bbe2ca3884dcb39ef02964327ac..e0ccf5fe708ad28592b4ab829b12b54a3e9674e9 100644 (file)
@@ -2478,6 +2478,31 @@ DEFINE_EVENT(sta_event, drv_net_fill_forward_path,
        TP_ARGS(local, sdata, sta)
 );
 
+TRACE_EVENT(drv_net_setup_tc,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                u8 type),
+
+       TP_ARGS(local, sdata, type),
+
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               VIF_ENTRY
+               __field(u8, type)
+       ),
+
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               VIF_ASSIGN;
+               __entry->type = type;
+       ),
+
+       TP_printk(
+               LOCAL_PR_FMT VIF_PR_FMT " type:%d\n",
+               LOCAL_PR_ARG, VIF_PR_ARG, __entry->type
+       )
+);
+
 TRACE_EVENT(drv_change_vif_links,
        TP_PROTO(struct ieee80211_local *local,
                 struct ieee80211_sub_if_data *sdata,