Add the concept of queue-specific filters to the filter handling.  This
will be used in the near future for macvlan offload filters.  In
general, filters for standard use will use a queue of 0, which we'll
take to mean the filter applies to the whole VSI.  Only the filters for
macvlan offload will use a non-zero queue.

Signed-off-by: Shannon Nelson <shannon.nel...@oracle.com>
---
 drivers/net/ethernet/intel/i40e/i40e.h             |   17 +++--
 drivers/net/ethernet/intel/i40e/i40e_debugfs.c     |    4 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c        |   72 ++++++++++++-------
 drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c |   10 ++--
 4 files changed, 63 insertions(+), 40 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e.h 
b/drivers/net/ethernet/intel/i40e/i40e.h
index 18c453a..a187f53 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -539,14 +539,17 @@ struct i40e_pf {
 /**
  * i40e_mac_to_hkey - Convert a 6-byte MAC Address to a u64 hash key
  * @macaddr: the MAC Address as the base key
+ * @queue: if non-zero, the queue to receive packets with this mac address
  *
  * Simply copies the address and returns it as a u64 for hashing
  **/
-static inline u64 i40e_addr_to_hkey(const u8 *macaddr)
+static inline u64 i40e_addr_to_hkey(const u8 *macaddr, u16 queue)
 {
        u64 key = 0;
+       u16 *k = (u16 *)&key;
 
        ether_addr_copy((u8 *)&key, macaddr);
+       k[3] = queue;
        return key;
 }
 
@@ -563,6 +566,7 @@ struct i40e_mac_filter {
        u8 macaddr[ETH_ALEN];
 #define I40E_VLAN_ANY -1
        s16 vlan;
+       u16 queue;
        enum i40e_filter_state state;
 };
 
@@ -892,10 +896,11 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
 u32 i40e_get_global_fd_count(struct i40e_pf *pf);
 bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
 void i40e_set_ethtool_ops(struct net_device *netdev);
-struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
-                                       const u8 *macaddr, s16 vlan);
+struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, const u8 
*macaddr,
+                                       s16 vlan, u16 queue);
 void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f);
-void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan);
+void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr,
+                    s16 vlan, u16 queue);
 int i40e_sync_vsi_filters(struct i40e_vsi *vsi);
 struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
                                u16 uplink, u32 param1);
@@ -971,8 +976,8 @@ static inline void i40e_irq_dynamic_enable(struct i40e_vsi 
*vsi, int vector)
 void i40e_rm_vlan_all_mac(struct i40e_vsi *vsi, s16 vid);
 void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, u16 vid);
 struct i40e_mac_filter *i40e_add_mac_filter(struct i40e_vsi *vsi,
-                                           const u8 *macaddr);
-int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr);
+                                           const u8 *macaddr, u16 queue);
+int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr, u16 queue);
 bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
 struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr);
 void i40e_vlan_stripping_enable(struct i40e_vsi *vsi);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c 
b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index 6f2725f..cf173e1 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -171,8 +171,8 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int 
seid)
                         pf->hw.mac.port_addr);
        hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
                dev_info(&pf->pdev->dev,
-                        "    mac_filter_hash: %pM vid=%d, state %s\n",
-                        f->macaddr, f->vlan,
+                        "    mac_filter_hash: %pM vid=%d q=%d, state %s\n",
+                        f->macaddr, f->vlan, f->queue,
                         i40e_filter_state_string[f->state]);
        }
        dev_info(&pf->pdev->dev, "    active_filters %u, promisc_threshold %u, 
overflow promisc %s\n",
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c 
b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 84c5087..e4b8a4b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -1114,11 +1114,13 @@ void i40e_update_stats(struct i40e_vsi *vsi)
  * @vsi: the VSI to be searched
  * @macaddr: the MAC address
  * @vlan: the vlan
+ * @queue: the queue
  *
  * Returns ptr to the filter object or NULL
  **/
 static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi,
-                                               const u8 *macaddr, s16 vlan)
+                                               const u8 *macaddr, s16 vlan,
+                                               u16 queue)
 {
        struct i40e_mac_filter *f;
        u64 key;
@@ -1126,10 +1128,10 @@ void i40e_update_stats(struct i40e_vsi *vsi)
        if (!vsi || !macaddr)
                return NULL;
 
-       key = i40e_addr_to_hkey(macaddr);
+       key = i40e_addr_to_hkey(macaddr, queue);
        hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) {
                if ((ether_addr_equal(macaddr, f->macaddr)) &&
-                   (vlan == f->vlan))
+                   (vlan == f->vlan) && (queue == f->queue))
                        return f;
        }
        return NULL;
@@ -1151,7 +1153,7 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi 
*vsi, const u8 *macaddr)
        if (!vsi || !macaddr)
                return NULL;
 
-       key = i40e_addr_to_hkey(macaddr);
+       key = i40e_addr_to_hkey(macaddr, 0);
        hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) {
                if ((ether_addr_equal(macaddr, f->macaddr)))
                        return f;
@@ -1277,7 +1279,8 @@ static int i40e_correct_mac_vlan_filters(struct i40e_vsi 
*vsi,
                                new_vlan = I40E_VLAN_ANY;
 
                        /* Create the new filter */
-                       add_head = i40e_add_filter(vsi, f->macaddr, new_vlan);
+                       add_head = i40e_add_filter(vsi, f->macaddr,
+                                                  new_vlan, f->queue);
                        if (!add_head)
                                return -ENOMEM;
 
@@ -1342,14 +1345,15 @@ static void i40e_rm_default_mac_filter(struct i40e_vsi 
*vsi, u8 *macaddr)
  * @vsi: the VSI to be searched
  * @macaddr: the MAC address
  * @vlan: the vlan
+ * @queue: if non-zero, the specific queue to receive for this mac address
  *
  * Returns ptr to the filter object or NULL when no memory available.
  *
  * NOTE: This function is expected to be called with mac_filter_hash_lock
  * being held.
  **/
-struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
-                                       const u8 *macaddr, s16 vlan)
+struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, const u8 
*macaddr,
+                                       s16 vlan, u16 queue)
 {
        struct i40e_mac_filter *f;
        u64 key;
@@ -1357,7 +1361,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi 
*vsi,
        if (!vsi || !macaddr)
                return NULL;
 
-       f = i40e_find_filter(vsi, macaddr, vlan);
+       f = i40e_find_filter(vsi, macaddr, vlan, queue);
        if (!f) {
                f = kzalloc(sizeof(*f), GFP_ATOMIC);
                if (!f)
@@ -1371,6 +1375,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi 
*vsi,
 
                ether_addr_copy(f->macaddr, macaddr);
                f->vlan = vlan;
+               f->queue = queue;
                /* If we're in overflow promisc mode, set the state directly
                 * to failed, so we don't bother to try sending the filter
                 * to the hardware.
@@ -1381,7 +1386,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi 
*vsi,
                        f->state = I40E_FILTER_NEW;
                INIT_HLIST_NODE(&f->hlist);
 
-               key = i40e_addr_to_hkey(macaddr);
+               key = i40e_addr_to_hkey(macaddr, queue);
                hash_add(vsi->mac_filter_hash, &f->hlist, key);
 
                vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
@@ -1443,6 +1448,7 @@ void __i40e_del_filter(struct i40e_vsi *vsi, struct 
i40e_mac_filter *f)
  * @vsi: the VSI to be searched
  * @macaddr: the MAC address
  * @vlan: the VLAN
+ * @queue: if non-zero, the specific queue to receive for this mac address
  *
  * NOTE: This function is expected to be called with mac_filter_hash_lock
  * being held.
@@ -1450,14 +1456,15 @@ void __i40e_del_filter(struct i40e_vsi *vsi, struct 
i40e_mac_filter *f)
  * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
  * instead of list_for_each_entry().
  **/
-void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
+void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr,
+                    s16 vlan, u16 queue)
 {
        struct i40e_mac_filter *f;
 
        if (!vsi || !macaddr)
                return;
 
-       f = i40e_find_filter(vsi, macaddr, vlan);
+       f = i40e_find_filter(vsi, macaddr, vlan, queue);
        __i40e_del_filter(vsi, f);
 }
 
@@ -1465,6 +1472,7 @@ void i40e_del_filter(struct i40e_vsi *vsi, const u8 
*macaddr, s16 vlan)
  * i40e_add_mac_filter - Add a MAC filter for all active VLANs
  * @vsi: the VSI to be searched
  * @macaddr: the mac address to be filtered
+ * @queue: if non-zero, the target ToQueue
  *
  * If we're not in VLAN mode, just add the filter to I40E_VLAN_ANY. Otherwise,
  * go through all the macvlan filters and add a macvlan filter for each
@@ -1474,7 +1482,7 @@ void i40e_del_filter(struct i40e_vsi *vsi, const u8 
*macaddr, s16 vlan)
  * Returns last filter added on success, else NULL
  **/
 struct i40e_mac_filter *i40e_add_mac_filter(struct i40e_vsi *vsi,
-                                           const u8 *macaddr)
+                                           const u8 *macaddr, u16 queue)
 {
        struct i40e_mac_filter *f, *add = NULL;
        struct hlist_node *h;
@@ -1482,15 +1490,15 @@ struct i40e_mac_filter *i40e_add_mac_filter(struct 
i40e_vsi *vsi,
 
        if (vsi->info.pvid)
                return i40e_add_filter(vsi, macaddr,
-                                      le16_to_cpu(vsi->info.pvid));
+                                      le16_to_cpu(vsi->info.pvid), queue);
 
        if (!i40e_is_vsi_in_vlan(vsi))
-               return i40e_add_filter(vsi, macaddr, I40E_VLAN_ANY);
+               return i40e_add_filter(vsi, macaddr, I40E_VLAN_ANY, queue);
 
        hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
                if (f->state == I40E_FILTER_REMOVE)
                        continue;
-               add = i40e_add_filter(vsi, macaddr, f->vlan);
+               add = i40e_add_filter(vsi, macaddr, f->vlan, queue);
                if (!add)
                        return NULL;
        }
@@ -1502,13 +1510,14 @@ struct i40e_mac_filter *i40e_add_mac_filter(struct 
i40e_vsi *vsi,
  * i40e_del_mac_filter - Remove a MAC filter from all VLANs
  * @vsi: the VSI to be searched
  * @macaddr: the mac address to be removed
+ * @queue: if non-zero, the target ToQueue
  *
  * Removes a given MAC address from a VSI regardless of what VLAN it has been
  * associated with.
  *
  * Returns 0 for success, or error
  **/
-int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr)
+int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr, u16 queue)
 {
        struct i40e_mac_filter *f;
        struct hlist_node *h;
@@ -1518,7 +1527,8 @@ int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 
*macaddr)
        WARN(!spin_is_locked(&vsi->mac_filter_hash_lock),
             "Missing mac_filter_hash_lock\n");
        hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
-               if (ether_addr_equal(macaddr, f->macaddr)) {
+               if (ether_addr_equal(macaddr, f->macaddr) &&
+                   queue == f->queue) {
                        __i40e_del_filter(vsi, f);
                        found = true;
                }
@@ -1565,8 +1575,8 @@ static int i40e_set_mac(struct net_device *netdev, void 
*p)
                netdev_info(netdev, "set new mac address %pM\n", addr->sa_data);
 
        spin_lock_bh(&vsi->mac_filter_hash_lock);
-       i40e_del_mac_filter(vsi, netdev->dev_addr);
-       i40e_add_mac_filter(vsi, addr->sa_data);
+       i40e_del_mac_filter(vsi, netdev->dev_addr, 0);
+       i40e_add_mac_filter(vsi, addr->sa_data, 0);
        spin_unlock_bh(&vsi->mac_filter_hash_lock);
        ether_addr_copy(netdev->dev_addr, addr->sa_data);
        if (vsi->type == I40E_VSI_MAIN) {
@@ -1731,7 +1741,7 @@ static int i40e_addr_sync(struct net_device *netdev, 
const u8 *addr)
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
 
-       if (i40e_add_mac_filter(vsi, addr))
+       if (i40e_add_mac_filter(vsi, addr, 0))
                return 0;
        else
                return -ENOMEM;
@@ -1750,7 +1760,7 @@ static int i40e_addr_unsync(struct net_device *netdev, 
const u8 *addr)
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
 
-       i40e_del_mac_filter(vsi, addr);
+       i40e_del_mac_filter(vsi, addr, 0);
 
        return 0;
 }
@@ -1793,7 +1803,7 @@ static void i40e_undo_del_filter_entries(struct i40e_vsi 
*vsi,
        struct hlist_node *h;
 
        hlist_for_each_entry_safe(f, h, from, hlist) {
-               u64 key = i40e_addr_to_hkey(f->macaddr);
+               u64 key = i40e_addr_to_hkey(f->macaddr, f->queue);
 
                /* Move the element back into MAC filter list*/
                hlist_del(&f->hlist);
@@ -2194,7 +2204,15 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                                add_list[num_add].vlan_tag =
                                        cpu_to_le16((u16)(new->f->vlan));
                        }
-                       add_list[num_add].queue_number = 0;
+
+                       if (new->f->queue) {
+                               add_list[num_add].queue_number =
+                                       cpu_to_le16(new->f->queue);
+                               cmd_flags |= I40E_AQC_MACVLAN_ADD_TO_QUEUE;
+                       } else {
+                               add_list[num_add].queue_number = 0;
+                       }
+
                        /* set invalid match method for later detection */
                        add_list[num_add].match_method = I40E_AQC_MM_ERR_NO_RES;
                        cmd_flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;
@@ -2580,7 +2598,7 @@ int i40e_add_vlan_all_mac(struct i40e_vsi *vsi, s16 vid)
        hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
                if (f->state == I40E_FILTER_REMOVE)
                        continue;
-               add_f = i40e_add_filter(vsi, f->macaddr, vid);
+               add_f = i40e_add_filter(vsi, f->macaddr, vid, 0);
                if (!add_f) {
                        dev_info(&vsi->back->pdev->dev,
                                 "Could not add vlan filter %d for %pM\n",
@@ -9772,7 +9790,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
                 */
                i40e_rm_default_mac_filter(vsi, mac_addr);
                spin_lock_bh(&vsi->mac_filter_hash_lock);
-               i40e_add_mac_filter(vsi, mac_addr);
+               i40e_add_mac_filter(vsi, mac_addr, 0);
                spin_unlock_bh(&vsi->mac_filter_hash_lock);
        } else {
                /* Relate the VSI_VMDQ name to the VSI_MAIN name. Note that we
@@ -9786,7 +9804,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
                random_ether_addr(mac_addr);
 
                spin_lock_bh(&vsi->mac_filter_hash_lock);
-               i40e_add_mac_filter(vsi, mac_addr);
+               i40e_add_mac_filter(vsi, mac_addr, 0);
                spin_unlock_bh(&vsi->mac_filter_hash_lock);
        }
 
@@ -9805,7 +9823,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
         */
        eth_broadcast_addr(broadcast);
        spin_lock_bh(&vsi->mac_filter_hash_lock);
-       i40e_add_mac_filter(vsi, broadcast);
+       i40e_add_mac_filter(vsi, broadcast, 0);
        spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
        ether_addr_copy(netdev->dev_addr, mac_addr);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c 
b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 0456813..d2ed218 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -709,14 +709,14 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum 
i40e_vsi_type type)
                spin_lock_bh(&vsi->mac_filter_hash_lock);
                if (is_valid_ether_addr(vf->default_lan_addr.addr)) {
                        f = i40e_add_mac_filter(vsi,
-                                               vf->default_lan_addr.addr);
+                                               vf->default_lan_addr.addr, 0);
                        if (!f)
                                dev_info(&pf->pdev->dev,
                                         "Could not add MAC filter %pM for VF 
%d\n",
                                        vf->default_lan_addr.addr, vf->vf_id);
                }
                eth_broadcast_addr(broadcast);
-               f = i40e_add_mac_filter(vsi, broadcast);
+               f = i40e_add_mac_filter(vsi, broadcast, 0);
                if (!f)
                        dev_info(&pf->pdev->dev,
                                 "Could not allocate VF broadcast filter\n");
@@ -2217,7 +2217,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, 
u8 *msg, u16 msglen)
 
                f = i40e_find_mac(vsi, al->list[i].addr);
                if (!f)
-                       f = i40e_add_mac_filter(vsi, al->list[i].addr);
+                       f = i40e_add_mac_filter(vsi, al->list[i].addr, 0);
 
                if (!f) {
                        dev_err(&pf->pdev->dev,
@@ -2282,7 +2282,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, 
u8 *msg, u16 msglen)
        spin_lock_bh(&vsi->mac_filter_hash_lock);
        /* delete addresses from the list */
        for (i = 0; i < al->num_elements; i++)
-               if (i40e_del_mac_filter(vsi, al->list[i].addr)) {
+               if (i40e_del_mac_filter(vsi, al->list[i].addr, 0)) {
                        ret = I40E_ERR_INVALID_MAC_ADDR;
                        spin_unlock_bh(&vsi->mac_filter_hash_lock);
                        goto error_param;
@@ -2916,7 +2916,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int 
vf_id, u8 *mac)
 
        /* delete the temporary mac address */
        if (!is_zero_ether_addr(vf->default_lan_addr.addr))
-               i40e_del_mac_filter(vsi, vf->default_lan_addr.addr);
+               i40e_del_mac_filter(vsi, vf->default_lan_addr.addr, 0);
 
        /* Delete all the filters for this VSI - we're going to kill it
         * anyway.
-- 
1.7.1

Reply via email to