summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/enetc/enetc.c
diff options
context:
space:
mode:
authorPo Liu <Po.Liu@nxp.com>2020-05-01 08:53:18 +0800
committerDavid S. Miller <davem@davemloft.net>2020-05-01 16:08:20 -0700
commit888ae5a3952badf11fdcd210f5da9994462ec2fc (patch)
tree0d55e72daf4969d75046040edc1a9050a901238e /drivers/net/ethernet/freescale/enetc/enetc.c
parent79e499829f3ff5b8f70c87baf1b03ebb3401a3e4 (diff)
net: enetc: add tc flower psfp offload driver
This patch is to add tc flower offload for the enetc IEEE 802.1Qci(PSFP) function. There are four main feature parts to implement the flow policing and filtering for ingress flow with IEEE 802.1Qci features. They are stream identify(this is defined in the P802.1cb exactly but needed for 802.1Qci), stream filtering, stream gate and flow metering. Each function block includes many entries by index to assign parameters. So for one frame would be filtered by stream identify first, then flow into stream filter block by the same handle between stream identify and stream filtering. Then flow into stream gate control which assigned by the stream filtering entry. And then policing by the gate and limited by the max sdu in the filter block(optional). At last, policing by the flow metering block, index choosing at the fitering block. So you can see that each entry of block may link to many upper entries since they can be assigned same index means more streams want to share the same feature in the stream filtering or stream gate or flow metering. To implement such features, each stream filtered by source/destination mac address, some stream maybe also plus the vlan id value would be treated as one flow chain. This would be identified by the chain_index which already in the tc filter concept. Driver would maintain this chain and also with gate modules. The stream filter entry create by the gate index and flow meter(optional) entry id and also one priority value. Offloading only transfer the gate action and flow filtering parameters. Driver would create (or search same gate id and flow meter id and priority) one stream filter entry to set to the hardware. So stream filtering do not need transfer by the action offloading. This architecture is same with tc filter and actions relationship. tc filter maintain the list for each flow feature by keys. And actions maintain by the action list. Below showing a example commands by tc: > tc qdisc add dev eth0 ingress > ip link set eth0 address 10:00:80:00:00:00 > tc filter add dev eth0 parent ffff: protocol ip chain 11 \ flower skip_sw dst_mac 10:00:80:00:00:00 \ action gate index 10 \ sched-entry open 200000000 1 8000000 \ sched-entry close 100000000 -1 -1 Command means to set the dst_mac 10:00:80:00:00:00 to index 11 of stream identify module. Then setting the gate index 10 of stream gate module. Keep the gate open for 200ms and limit the traffic volume to 8MB in this sched-entry. Then direct the frames to the ingress queue 1. Signed-off-by: Po Liu <Po.Liu@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/freescale/enetc/enetc.c')
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 04aac7cbb506..298c55786fd9 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1521,6 +1521,8 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
return enetc_setup_tc_cbs(ndev, type_data);
case TC_SETUP_QDISC_ETF:
return enetc_setup_tc_txtime(ndev, type_data);
+ case TC_SETUP_BLOCK:
+ return enetc_setup_tc_psfp(ndev, type_data);
default:
return -EOPNOTSUPP;
}
@@ -1573,17 +1575,23 @@ static int enetc_set_rss(struct net_device *ndev, int en)
static int enetc_set_psfp(struct net_device *ndev, int en)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ int err;
if (en) {
+ err = enetc_psfp_enable(priv);
+ if (err)
+ return err;
+
priv->active_offloads |= ENETC_F_QCI;
- enetc_get_max_cap(priv);
- enetc_psfp_enable(&priv->si->hw);
- } else {
- priv->active_offloads &= ~ENETC_F_QCI;
- memset(&priv->psfp_cap, 0, sizeof(struct psfp_cap));
- enetc_psfp_disable(&priv->si->hw);
+ return 0;
}
+ err = enetc_psfp_disable(priv);
+ if (err)
+ return err;
+
+ priv->active_offloads &= ~ENETC_F_QCI;
+
return 0;
}
@@ -1591,14 +1599,15 @@ int enetc_set_features(struct net_device *ndev,
netdev_features_t features)
{
netdev_features_t changed = ndev->features ^ features;
+ int err = 0;
if (changed & NETIF_F_RXHASH)
enetc_set_rss(ndev, !!(features & NETIF_F_RXHASH));
if (changed & NETIF_F_HW_TC)
- enetc_set_psfp(ndev, !!(features & NETIF_F_HW_TC));
+ err = enetc_set_psfp(ndev, !!(features & NETIF_F_HW_TC));
- return 0;
+ return err;
}
#ifdef CONFIG_FSL_ENETC_PTP_CLOCK