net: rework setup_tc ndo op to consume general tc operand
authorJohn Fastabend <john.fastabend@gmail.com>
Wed, 17 Feb 2016 05:16:43 +0000 (21:16 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 17 Feb 2016 14:47:35 +0000 (09:47 -0500)
This patch updates setup_tc so we can pass additional parameters into
the ndo op in a generic way. To do this we provide structured union
and type flag.

This lets each classifier and qdisc provide its own set of attributes
without having to add new ndo ops or grow the signature of the
callback.

Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
14 files changed:
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/sfc/efx.h
drivers/net/ethernet/sfc/tx.c
drivers/net/ethernet/ti/netcp_core.c
include/linux/netdevice.h
net/sched/sch_mqprio.c

index 9955cae3cabc54e19333d995c6010b7bc3dddf95..cfd3f7efda1cfcb42d5ce339ce3793df0bce4b25 100644 (file)
@@ -1626,15 +1626,18 @@ static void xgbe_poll_controller(struct net_device *netdev)
 }
 #endif /* End CONFIG_NET_POLL_CONTROLLER */
 
-static int xgbe_setup_tc(struct net_device *netdev, u32 handle, u8 tc)
+static int xgbe_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
+                        struct tc_to_netdev *tc_to_netdev)
 {
        struct xgbe_prv_data *pdata = netdev_priv(netdev);
        unsigned int offset, queue;
-       u8 i;
+       u8 i, tc;
 
-       if (handle != TC_H_ROOT)
+       if (handle != TC_H_ROOT || tc_to_netdev->type != TC_SETUP_MQPRIO)
                return -EINVAL;
 
+       tc = tc_to_netdev->tc;
+
        if (tc && (tc != pdata->hw_feat.tc_cnt))
                return -EINVAL;
 
index b262cba34dfae8bf634f43bfacd67f695b85a1cb..45843d15086846f2d68b5d3005629927e5294da3 100644 (file)
@@ -4272,11 +4272,12 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
        return 0;
 }
 
-int __bnx2x_setup_tc(struct net_device *dev, u32 handle, u8 num_tc)
+int __bnx2x_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+                    struct tc_to_netdev *tc)
 {
-       if (handle != TC_H_ROOT)
+       if (handle != TC_H_ROOT || tc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
-       return bnx2x_setup_tc(dev, num_tc);
+       return bnx2x_setup_tc(dev, tc->tc);
 }
 
 /* called with rtnl_lock */
index 60a4109dcdebe8a9d2ae8fa6b73de01d8145ce7d..0e68fadecfdb83e8acdd88681016a4828496c1be 100644 (file)
@@ -486,7 +486,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
 /* setup_tc callback */
 int bnx2x_setup_tc(struct net_device *dev, u8 num_tc);
-int __bnx2x_setup_tc(struct net_device *dev, u32 handle, u8 num_tc);
+int __bnx2x_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+                    struct tc_to_netdev *tc);
 
 int bnx2x_get_vf_config(struct net_device *dev, int vf,
                        struct ifla_vf_info *ivi);
index ff08faf44ee557c7ffaef2dae713a5f4b642b1e4..169920aa39f3551a5c0e6b33a619979a1a954be6 100644 (file)
@@ -5370,13 +5370,17 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
-static int bnxt_setup_tc(struct net_device *dev, u32 handle, u8 tc)
+static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+                        struct tc_to_netdev *ntc)
 {
        struct bnxt *bp = netdev_priv(dev);
+       u8 tc;
 
-       if (handle != TC_H_ROOT)
+       if (handle != TC_H_ROOT || ntc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
 
+       tc = ntc->tc;
+
        if (tc > bp->max_tc) {
                netdev_err(dev, "too many traffic classes requested: %d Max supported is %d\n",
                           tc, bp->max_tc);
index 12701a4923253a39b9cf76779e6779772c6c3c1d..dc1a82148ff01d27dba588221ae777c1c7c8ca4f 100644 (file)
@@ -1204,12 +1204,13 @@ err_queueing_scheme:
        return err;
 }
 
-static int __fm10k_setup_tc(struct net_device *dev, u32 handle, u8 tc)
+static int __fm10k_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+                           struct tc_to_netdev *tc)
 {
-       if (handle != TC_H_ROOT)
+       if (handle != TC_H_ROOT || tc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
 
-       return fm10k_setup_tc(dev, tc);
+       return fm10k_setup_tc(dev, tc->tc);
 }
 
 static int fm10k_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
index ef9ca075d5e504ceeb46c21b2463c3deca213246..933c4b3d92c88cb382a2fac3bbc0a6e230fd055b 100644 (file)
@@ -788,7 +788,8 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
                                      bool is_vf, bool is_netdev);
 #ifdef I40E_FCOE
 int i40e_close(struct net_device *netdev);
-int __i40e_setup_tc(struct net_device *netdev, u32 handle, u8 tc);
+int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
+                   struct tc_to_netdev *tc);
 void i40e_netpoll(struct net_device *netdev);
 int i40e_fcoe_enable(struct net_device *netdev);
 int i40e_fcoe_disable(struct net_device *netdev);
index abcb6c152186fa6dd59f0982b31828634977eee5..257d16207976f80813bb18ea4c62ac529a448200 100644 (file)
@@ -5307,14 +5307,16 @@ exit:
 }
 
 #ifdef I40E_FCOE
-int __i40e_setup_tc(struct net_device *netdev, u32 handle, u8 tc)
+int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
+                   struct tc_to_netdev *tc)
 #else
-static int __i40e_setup_tc(struct net_device *netdev, u32 handle, u8 tc)
+static int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
+                          struct tc_to_netdev *tc)
 #endif
 {
-       if (handle != TC_H_ROOT)
+       if (handle != TC_H_ROOT || tc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
-       return i40e_setup_tc(netdev, tc);
+       return i40e_setup_tc(netdev, tc->tc);
 }
 
 /**
index 1ba714efd78c48c91a674d2e5d7493637ae01ed0..dca2298f4c36bf4fcf9b0e61c2dc6bb461fa1a46 100644 (file)
@@ -8200,13 +8200,14 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
        return 0;
 }
 
-int __ixgbe_setup_tc(struct net_device *dev, u32 handle, u8 tc)
+int __ixgbe_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+                    struct tc_to_netdev *tc)
 {
        /* Only support egress tc setup for now */
-       if (handle != TC_H_ROOT)
+       if (handle != TC_H_ROOT || tc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
 
-       return ixgbe_setup_tc(dev, tc);
+       return ixgbe_setup_tc(dev, tc->tc);
 }
 
 #ifdef CONFIG_PCI_IOV
index d5c6c16b9457618d94d59773bc85de21e4454f1f..01d6a9695586322bf06b5034686dec023b697c5a 100644 (file)
@@ -69,12 +69,13 @@ int mlx4_en_setup_tc(struct net_device *dev, u8 up)
        return 0;
 }
 
-static int __mlx4_en_setup_tc(struct net_device *dev, u32 handle, u8 up)
+static int __mlx4_en_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+                             struct tc_to_netdev *tc)
 {
-       if (handle != TC_H_ROOT)
+       if (handle != TC_H_ROOT || tc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
 
-       return mlx4_en_setup_tc(dev, up);
+       return mlx4_en_setup_tc(dev, tc->tc);
 }
 
 #ifdef CONFIG_RFS_ACCEL
index 7815fa09b15d09613f364ec0429f7d2047e0240d..5e3f93f04e624a6b5f4e7885a625c47922766342 100644 (file)
@@ -32,7 +32,8 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
                                struct net_device *net_dev);
 netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
-int efx_setup_tc(struct net_device *net_dev, u32 handle, u8 num_tc);
+int efx_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
+                struct tc_to_netdev *tc);
 unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);
 extern unsigned int efx_piobuf_size;
 extern bool efx_separate_tx_channels;
index 8f1d53e2aca73946317acb9f00bf1f904254655e..2cdb5718ed66a580c0748023f1c6ecd755c51855 100644 (file)
@@ -562,17 +562,20 @@ void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue)
                                     efx->n_tx_channels : 0));
 }
 
-int efx_setup_tc(struct net_device *net_dev, u32 handle, u8 num_tc)
+int efx_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
+                struct tc_to_netdev *ntc)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
        struct efx_channel *channel;
        struct efx_tx_queue *tx_queue;
-       unsigned tc;
+       unsigned tc, num_tc;
        int rc;
 
-       if (handle != TC_H_ROOT)
+       if (handle != TC_H_ROOT || ntc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
 
+       num_tc = ntc->tc;
+
        if (efx_nic_rev(efx) < EFX_REV_FALCON_B0 || num_tc > EFX_MAX_TX_TC)
                return -EINVAL;
 
index 40cde814608b7147daeae2488d2bbddf93b74495..8586a203401909ec082959ce5350dc90769cf08f 100644 (file)
@@ -1835,25 +1835,26 @@ static u16 netcp_select_queue(struct net_device *dev, struct sk_buff *skb,
        return 0;
 }
 
-static int netcp_setup_tc(struct net_device *dev, u32 handle, u8 num_tc)
+static int netcp_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+                         struct tc_to_netdev tc)
 {
        int i;
 
        /* setup tc must be called under rtnl lock */
        ASSERT_RTNL();
 
-       if (handle != TC_H_ROOT)
+       if (handle != TC_H_ROOT || tc->type != TC_SETUP_MQPRIO)
                return -EINVAL;
 
        /* Sanity-check the number of traffic classes requested */
        if ((dev->real_num_tx_queues <= 1) ||
-           (dev->real_num_tx_queues < num_tc))
+           (dev->real_num_tx_queues < tc->tc))
                return -EINVAL;
 
        /* Configure traffic class to queue mappings */
-       if (num_tc) {
-               netdev_set_num_tc(dev, num_tc);
-               for (i = 0; i < num_tc; i++)
+       if (tc->tc) {
+               netdev_set_num_tc(dev, tc->tc);
+               for (i = 0; i < tc->tc; i++)
                        netdev_set_tc_queue(dev, i, 1, i);
        } else {
                netdev_reset_tc(dev);
index 48928b6f9cb6a153eae00a3c2a55f53402ed6074..e396060f815f34a9ea5885e3f0b2e5e4142ce79f 100644 (file)
@@ -779,6 +779,21 @@ static inline bool netdev_phys_item_id_same(struct netdev_phys_item_id *a,
 typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
                                       struct sk_buff *skb);
 
+/* This structure holds attributes of qdisc and classifiers
+ * that are being passed to the netdevice through the setup_tc op.
+ */
+enum {
+       TC_SETUP_MQPRIO,
+};
+
+struct tc_to_netdev {
+       unsigned int type;
+       union {
+               u8 tc;
+       };
+};
+
+
 /*
  * This structure defines the management hooks for network devices.
  * The following hooks can be defined; unless noted otherwise, they are
@@ -1151,7 +1166,10 @@ struct net_device_ops {
        int                     (*ndo_set_vf_rss_query_en)(
                                                   struct net_device *dev,
                                                   int vf, bool setting);
-       int                     (*ndo_setup_tc)(struct net_device *dev, u32 handle, u8 tc);
+       int                     (*ndo_setup_tc)(struct net_device *dev,
+                                               u32 handle,
+                                               __be16 protocol,
+                                               struct tc_to_netdev *tc);
 #if IS_ENABLED(CONFIG_FCOE)
        int                     (*ndo_fcoe_enable)(struct net_device *dev);
        int                     (*ndo_fcoe_disable)(struct net_device *dev);
index f5a0e8a4dbd7734c52dd22dd2ead65f53bb5693d..f9947d1f4952096049137df70974ea0a26a8fed9 100644 (file)
@@ -28,6 +28,7 @@ static void mqprio_destroy(struct Qdisc *sch)
 {
        struct net_device *dev = qdisc_dev(sch);
        struct mqprio_sched *priv = qdisc_priv(sch);
+       struct tc_to_netdev tc = {.type = TC_SETUP_MQPRIO};
        unsigned int ntx;
 
        if (priv->qdiscs) {
@@ -39,7 +40,7 @@ static void mqprio_destroy(struct Qdisc *sch)
        }
 
        if (priv->hw_owned && dev->netdev_ops->ndo_setup_tc)
-               dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0);
+               dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
        else
                netdev_set_num_tc(dev, 0);
 }
@@ -140,9 +141,11 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
         * supplied and verified mapping
         */
        if (qopt->hw) {
+               struct tc_to_netdev tc = {.type = TC_SETUP_MQPRIO,
+                                         .tc = qopt->num_tc};
+
                priv->hw_owned = 1;
-               err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle,
-                                                   qopt->num_tc);
+               err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
                if (err)
                        goto err;
        } else {