mirror of
https://github.com/openwrt/openwrt.git
synced 2025-02-06 19:19:31 +00:00
mediatek: add kernel code for supporting offloading wlan->eth and wlan->wlan flows
Will be enabled by an upcoming mt76 update Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
fbcfb7f7af
commit
d0a06965e8
@ -0,0 +1,149 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Mon, 20 Mar 2023 14:28:08 +0100
|
||||
Subject: [PATCH] wifi: mac80211: add support for letting drivers register tc
|
||||
offload support
|
||||
|
||||
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>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -4196,6 +4196,10 @@ struct ieee80211_prep_tx_info {
|
||||
* Note that a sta can also be inserted or removed with valid links,
|
||||
* i.e. passed to @sta_add/@sta_state with sta->valid_links not zero.
|
||||
* In fact, cannot change from having valid_links and not having them.
|
||||
+ * @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,
|
||||
@@ -4551,6 +4555,11 @@ struct ieee80211_ops {
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
u16 old_links, u16 new_links);
|
||||
+ int (*net_setup_tc)(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_vif *vif,
|
||||
+ struct net_device *dev,
|
||||
+ enum tc_setup_type type,
|
||||
+ void *type_data);
|
||||
};
|
||||
|
||||
/**
|
||||
--- a/net/mac80211/driver-ops.h
|
||||
+++ b/net/mac80211/driver-ops.h
|
||||
@@ -1470,6 +1470,23 @@ static inline int drv_net_fill_forward_p
|
||||
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,
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -1935,7 +1935,8 @@ void ieee80211_color_change_finalize_wor
|
||||
/* 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)
|
||||
--- a/net/mac80211/iface.c
|
||||
+++ b/net/mac80211/iface.c
|
||||
@@ -813,6 +813,21 @@ ieee80211_get_stats64(struct net_device
|
||||
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;
|
||||
+ struct ieee80211_local *local;
|
||||
+
|
||||
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
+ local = sdata->local;
|
||||
+
|
||||
+ if (!local->ops->net_setup_tc)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ 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 +836,7 @@ static const struct net_device_ops ieee8
|
||||
.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 +945,7 @@ static const struct net_device_ops ieee8
|
||||
.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)
|
||||
--- a/net/mac80211/trace.h
|
||||
+++ b/net/mac80211/trace.h
|
||||
@@ -2478,6 +2478,31 @@ DEFINE_EVENT(sta_event, drv_net_fill_for
|
||||
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,
|
@ -18,7 +18,7 @@
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -1645,6 +1645,7 @@ enum ieee80211_smps_mode {
|
||||
@@ -1671,6 +1671,7 @@ enum ieee80211_smps_mode {
|
||||
*
|
||||
* @power_level: requested transmit power (in dBm), backward compatibility
|
||||
* value only that is set to the minimum of all interfaces
|
||||
@ -26,7 +26,7 @@
|
||||
*
|
||||
* @chandef: the channel definition to tune to
|
||||
* @radar_enabled: whether radar detection is enabled
|
||||
@@ -1665,6 +1666,7 @@ enum ieee80211_smps_mode {
|
||||
@@ -1691,6 +1692,7 @@ enum ieee80211_smps_mode {
|
||||
struct ieee80211_conf {
|
||||
u32 flags;
|
||||
int power_level, dynamic_ps_timeout;
|
||||
@ -57,7 +57,7 @@
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -2998,6 +2998,19 @@ static int ieee80211_get_tx_power(struct
|
||||
@@ -3028,6 +3028,19 @@ static int ieee80211_get_tx_power(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@
|
||||
static void ieee80211_rfkill_poll(struct wiphy *wiphy)
|
||||
{
|
||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
@@ -4881,6 +4894,7 @@ const struct cfg80211_ops mac80211_confi
|
||||
@@ -4911,6 +4924,7 @@ const struct cfg80211_ops mac80211_confi
|
||||
.set_wiphy_params = ieee80211_set_wiphy_params,
|
||||
.set_tx_power = ieee80211_set_tx_power,
|
||||
.get_tx_power = ieee80211_get_tx_power,
|
||||
|
@ -1,10 +1,11 @@
|
||||
--- a/include/linux/soc/mediatek/mtk_wed.h
|
||||
+++ b/include/linux/soc/mediatek/mtk_wed.h
|
||||
@@ -5,21 +5,76 @@
|
||||
@@ -5,21 +5,77 @@
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/pci.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <linux/netdevice.h>
|
||||
|
||||
#define MTK_WED_TX_QUEUES 2
|
||||
+#define MTK_WED_RX_QUEUES 2
|
||||
@ -77,7 +78,7 @@
|
||||
struct mtk_wed_device {
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
const struct mtk_wed_ops *ops;
|
||||
@@ -28,30 +83,76 @@ struct mtk_wed_device {
|
||||
@@ -28,30 +84,76 @@ struct mtk_wed_device {
|
||||
bool init_done, running;
|
||||
int wdma_idx;
|
||||
int irq;
|
||||
@ -156,7 +157,7 @@
|
||||
} wlan;
|
||||
#endif
|
||||
};
|
||||
@@ -59,10 +160,16 @@ struct mtk_wed_device {
|
||||
@@ -59,10 +161,16 @@ struct mtk_wed_device {
|
||||
struct mtk_wed_ops {
|
||||
int (*attach)(struct mtk_wed_device *dev);
|
||||
int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring,
|
||||
@ -174,7 +175,16 @@
|
||||
|
||||
void (*stop)(struct mtk_wed_device *dev);
|
||||
void (*start)(struct mtk_wed_device *dev, u32 irq_mask);
|
||||
@@ -97,12 +204,22 @@ mtk_wed_device_attach(struct mtk_wed_dev
|
||||
@@ -73,6 +181,8 @@ struct mtk_wed_ops {
|
||||
|
||||
u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
|
||||
void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
|
||||
+ int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev,
|
||||
+ enum tc_setup_type type, void *type_data);
|
||||
};
|
||||
|
||||
extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
|
||||
@@ -97,12 +207,22 @@ mtk_wed_device_attach(struct mtk_wed_dev
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -199,7 +209,7 @@
|
||||
#define mtk_wed_device_txfree_ring_setup(_dev, _regs) \
|
||||
(_dev)->ops->txfree_ring_setup(_dev, _regs)
|
||||
#define mtk_wed_device_reg_read(_dev, _reg) \
|
||||
@@ -113,6 +230,14 @@ mtk_wed_device_attach(struct mtk_wed_dev
|
||||
@@ -113,6 +233,16 @@ mtk_wed_device_attach(struct mtk_wed_dev
|
||||
(_dev)->ops->irq_get(_dev, _mask)
|
||||
#define mtk_wed_device_irq_set_mask(_dev, _mask) \
|
||||
(_dev)->ops->irq_set_mask(_dev, _mask)
|
||||
@ -211,10 +221,12 @@
|
||||
+ (_dev)->ops->msg_update(_dev, _id, _msg, _len)
|
||||
+#define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
|
||||
+#define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
|
||||
+#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) \
|
||||
+ (_dev)->ops->setup_tc(_dev, _netdev, _type, _type_data)
|
||||
#else
|
||||
static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
|
||||
{
|
||||
@@ -120,12 +245,17 @@ static inline bool mtk_wed_device_active
|
||||
@@ -120,12 +250,18 @@ static inline bool mtk_wed_device_active
|
||||
}
|
||||
#define mtk_wed_device_detach(_dev) do {} while (0)
|
||||
#define mtk_wed_device_start(_dev, _mask) do {} while (0)
|
||||
@ -230,6 +242,7 @@
|
||||
+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
|
||||
+#define mtk_wed_device_stop(_dev) do {} while (0)
|
||||
+#define mtk_wed_device_dma_reset(_dev) do {} while (0)
|
||||
+#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) -EOPNOTSUPP
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,266 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Mon, 20 Mar 2023 11:44:30 +0100
|
||||
Subject: [PATCH] net: ethernet: mtk_eth_soc: add code for offloading flows
|
||||
from wlan devices
|
||||
|
||||
WED version 2 (on MT7986 and later) can offload flows originating from wireless
|
||||
devices. In order to make that work, ndo_setup_tc needs to be implemented on
|
||||
the netdevs. This adds the required code to offload flows coming in from WED,
|
||||
while keeping track of the incoming wed index used for selecting the correct
|
||||
PPE device.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||
@@ -1319,6 +1319,9 @@ int mtk_gmac_rgmii_path_setup(struct mtk
|
||||
int mtk_eth_offload_init(struct mtk_eth *eth);
|
||||
int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
|
||||
void *type_data);
|
||||
+int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls,
|
||||
+ int ppe_index);
|
||||
+void mtk_flow_offload_cleanup(struct mtk_eth *eth, struct list_head *list);
|
||||
void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
|
||||
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
|
||||
@@ -235,7 +235,8 @@ out:
|
||||
}
|
||||
|
||||
static int
|
||||
-mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
|
||||
+mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f,
|
||||
+ int ppe_index)
|
||||
{
|
||||
struct flow_rule *rule = flow_cls_offload_flow_rule(f);
|
||||
struct flow_action_entry *act;
|
||||
@@ -452,6 +453,7 @@ mtk_flow_offload_replace(struct mtk_eth
|
||||
entry->cookie = f->cookie;
|
||||
memcpy(&entry->data, &foe, sizeof(entry->data));
|
||||
entry->wed_index = wed_index;
|
||||
+ entry->ppe_index = ppe_index;
|
||||
|
||||
err = mtk_foe_entry_commit(eth->ppe[entry->ppe_index], entry);
|
||||
if (err < 0)
|
||||
@@ -520,25 +522,15 @@ mtk_flow_offload_stats(struct mtk_eth *e
|
||||
|
||||
static DEFINE_MUTEX(mtk_flow_offload_mutex);
|
||||
|
||||
-static int
|
||||
-mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
|
||||
+int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls,
|
||||
+ int ppe_index)
|
||||
{
|
||||
- struct flow_cls_offload *cls = type_data;
|
||||
- struct net_device *dev = cb_priv;
|
||||
- struct mtk_mac *mac = netdev_priv(dev);
|
||||
- struct mtk_eth *eth = mac->hw;
|
||||
int err;
|
||||
|
||||
- if (!tc_can_offload(dev))
|
||||
- return -EOPNOTSUPP;
|
||||
-
|
||||
- if (type != TC_SETUP_CLSFLOWER)
|
||||
- return -EOPNOTSUPP;
|
||||
-
|
||||
mutex_lock(&mtk_flow_offload_mutex);
|
||||
switch (cls->command) {
|
||||
case FLOW_CLS_REPLACE:
|
||||
- err = mtk_flow_offload_replace(eth, cls);
|
||||
+ err = mtk_flow_offload_replace(eth, cls, ppe_index);
|
||||
break;
|
||||
case FLOW_CLS_DESTROY:
|
||||
err = mtk_flow_offload_destroy(eth, cls);
|
||||
@@ -556,6 +548,23 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_
|
||||
}
|
||||
|
||||
static int
|
||||
+mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
|
||||
+{
|
||||
+ struct flow_cls_offload *cls = type_data;
|
||||
+ struct net_device *dev = cb_priv;
|
||||
+ struct mtk_mac *mac = netdev_priv(dev);
|
||||
+ struct mtk_eth *eth = mac->hw;
|
||||
+
|
||||
+ if (!tc_can_offload(dev))
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (type != TC_SETUP_CLSFLOWER)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ return mtk_flow_offload_cmd(eth, cls, 0);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/soc/mediatek/mtk_wed.h>
|
||||
+#include <net/flow_offload.h>
|
||||
+#include <net/pkt_cls.h>
|
||||
#include "mtk_eth_soc.h"
|
||||
#include "mtk_wed_regs.h"
|
||||
#include "mtk_wed.h"
|
||||
@@ -41,6 +43,11 @@
|
||||
static struct mtk_wed_hw *hw_list[2];
|
||||
static DEFINE_MUTEX(hw_lock);
|
||||
|
||||
+struct mtk_wed_flow_block_priv {
|
||||
+ struct mtk_wed_hw *hw;
|
||||
+ struct net_device *dev;
|
||||
+};
|
||||
+
|
||||
static void
|
||||
wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val)
|
||||
{
|
||||
@@ -1752,6 +1759,99 @@ out:
|
||||
mutex_unlock(&hw_lock);
|
||||
}
|
||||
|
||||
+static int
|
||||
+mtk_wed_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
|
||||
+{
|
||||
+ struct mtk_wed_flow_block_priv *priv = cb_priv;
|
||||
+ struct flow_cls_offload *cls = type_data;
|
||||
+ struct mtk_wed_hw *hw = priv->hw;
|
||||
+
|
||||
+ if (!tc_can_offload(priv->dev))
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (type != TC_SETUP_CLSFLOWER)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ return mtk_flow_offload_cmd(hw->eth, cls, hw->index);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mtk_wed_setup_tc_block(struct mtk_wed_hw *hw, struct net_device *dev,
|
||||
+ struct flow_block_offload *f)
|
||||
+{
|
||||
+ struct mtk_wed_flow_block_priv *priv;
|
||||
+ static LIST_HEAD(block_cb_list);
|
||||
+ struct flow_block_cb *block_cb;
|
||||
+ struct mtk_eth *eth = hw->eth;
|
||||
+ flow_setup_cb_t *cb;
|
||||
+
|
||||
+ if (!eth->soc->offload_version)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ cb = mtk_wed_setup_tc_block_cb;
|
||||
+ f->driver_block_list = &block_cb_list;
|
||||
+
|
||||
+ switch (f->command) {
|
||||
+ case FLOW_BLOCK_BIND:
|
||||
+ block_cb = flow_block_cb_lookup(f->block, cb, dev);
|
||||
+ if (block_cb) {
|
||||
+ flow_block_cb_incref(block_cb);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ priv->hw = hw;
|
||||
+ priv->dev = dev;
|
||||
+ block_cb = flow_block_cb_alloc(cb, dev, priv, NULL);
|
||||
+ if (IS_ERR(block_cb)) {
|
||||
+ kfree(priv);
|
||||
+ return PTR_ERR(block_cb);
|
||||
+ }
|
||||
+
|
||||
+ flow_block_cb_incref(block_cb);
|
||||
+ flow_block_cb_add(block_cb, f);
|
||||
+ list_add_tail(&block_cb->driver_list, &block_cb_list);
|
||||
+ return 0;
|
||||
+ case FLOW_BLOCK_UNBIND:
|
||||
+ block_cb = flow_block_cb_lookup(f->block, cb, dev);
|
||||
+ if (!block_cb)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ if (!flow_block_cb_decref(block_cb)) {
|
||||
+ flow_block_cb_remove(block_cb, f);
|
||||
+ list_del(&block_cb->driver_list);
|
||||
+ kfree(block_cb->cb_priv);
|
||||
+ }
|
||||
+ return 0;
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mtk_wed_setup_tc(struct mtk_wed_device *wed, struct net_device *dev,
|
||||
+ enum tc_setup_type type, void *type_data)
|
||||
+{
|
||||
+ struct mtk_wed_hw *hw = wed->hw;
|
||||
+
|
||||
+ if (hw->version < 2)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case TC_SETUP_BLOCK:
|
||||
+ case TC_SETUP_FT:
|
||||
+ return mtk_wed_setup_tc_block(hw, dev, type_data);
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
|
||||
void __iomem *wdma, phys_addr_t wdma_phy,
|
||||
int index)
|
||||
@@ -1771,6 +1871,7 @@ void mtk_wed_add_hw(struct device_node *
|
||||
.irq_set_mask = mtk_wed_irq_set_mask,
|
||||
.detach = mtk_wed_detach,
|
||||
.ppe_check = mtk_wed_ppe_check,
|
||||
+ .setup_tc = mtk_wed_setup_tc,
|
||||
};
|
||||
struct device_node *eth_np = eth->dev->of_node;
|
||||
struct platform_device *pdev;
|
||||
--- a/include/linux/soc/mediatek/mtk_wed.h
|
||||
+++ b/include/linux/soc/mediatek/mtk_wed.h
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/skbuff.h>
|
||||
+#include <linux/netdevice.h>
|
||||
|
||||
#define MTK_WED_TX_QUEUES 2
|
||||
#define MTK_WED_RX_QUEUES 2
|
||||
@@ -180,6 +181,8 @@ struct mtk_wed_ops {
|
||||
|
||||
u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
|
||||
void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
|
||||
+ int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev,
|
||||
+ enum tc_setup_type type, void *type_data);
|
||||
};
|
||||
|
||||
extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
|
||||
@@ -238,6 +241,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic
|
||||
(_dev)->ops->msg_update(_dev, _id, _msg, _len)
|
||||
#define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
|
||||
#define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
|
||||
+#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) \
|
||||
+ (_dev)->ops->setup_tc(_dev, _netdev, _type, _type_data)
|
||||
#else
|
||||
static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
|
||||
{
|
||||
@@ -256,6 +261,7 @@ static inline bool mtk_wed_device_active
|
||||
#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
|
||||
#define mtk_wed_device_stop(_dev) do {} while (0)
|
||||
#define mtk_wed_device_dma_reset(_dev) do {} while (0)
|
||||
+#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) -EOPNOTSUPP
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,37 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Mon, 20 Mar 2023 15:37:55 +0100
|
||||
Subject: [PATCH] net: ethernet: mediatek: mtk_ppe: prefer newly added l2
|
||||
flows over existing ones
|
||||
|
||||
When a device is roaming between interfaces and a new flow entry is created,
|
||||
we should assume that its output device is more up to date than whatever
|
||||
entry existed already.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
|
||||
@@ -639,10 +639,20 @@ void mtk_foe_entry_clear(struct mtk_ppe
|
||||
static int
|
||||
mtk_foe_entry_commit_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
|
||||
{
|
||||
+ struct mtk_flow_entry *prev;
|
||||
+
|
||||
entry->type = MTK_FLOW_TYPE_L2;
|
||||
|
||||
- return rhashtable_insert_fast(&ppe->l2_flows, &entry->l2_node,
|
||||
- mtk_flow_l2_ht_params);
|
||||
+ prev = rhashtable_lookup_get_insert_fast(&ppe->l2_flows, &entry->l2_node,
|
||||
+ mtk_flow_l2_ht_params);
|
||||
+ if (likely(!prev))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (IS_ERR(prev))
|
||||
+ return PTR_ERR(prev);
|
||||
+
|
||||
+ return rhashtable_replace_fast(&ppe->l2_flows, &prev->l2_node,
|
||||
+ &entry->l2_node, mtk_flow_l2_ht_params);
|
||||
}
|
||||
|
||||
int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
|
@ -22,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
|
||||
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
|
||||
@@ -806,6 +806,24 @@ mtk_wed_rro_alloc(struct mtk_wed_device
|
||||
@@ -813,6 +813,24 @@ mtk_wed_rro_alloc(struct mtk_wed_device
|
||||
struct device_node *np;
|
||||
int index;
|
||||
|
||||
@ -47,7 +47,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
index = of_property_match_string(dev->hw->node, "memory-region-names",
|
||||
"wo-dlm");
|
||||
if (index < 0)
|
||||
@@ -822,6 +840,7 @@ mtk_wed_rro_alloc(struct mtk_wed_device
|
||||
@@ -829,6 +847,7 @@ mtk_wed_rro_alloc(struct mtk_wed_device
|
||||
return -ENODEV;
|
||||
|
||||
dev->rro.miod_phys = rmem->base;
|
||||
|
Loading…
x
Reference in New Issue
Block a user