bnxt_en: Refactor the hash table logic for ntuple filters.
authorMichael Chan <michael.chan@broadcom.com>
Sat, 23 Dec 2023 04:22:06 +0000 (20:22 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 2 Jan 2024 13:52:28 +0000 (13:52 +0000)
Generalize the ethtool logic that walks the ntuple hash table now that
we have the common bnxt_filter_base structure.  This will allow the code
to easily extend to cover user defined ntuple or ether filters.

Reviewed-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

index 097d440339b09135a2ab03b431eb2116bbe5ed77..1e5bf8b7dd554859b0a146e77cee44e60525394e 100644 (file)
@@ -5615,6 +5615,7 @@ static int bnxt_hwrm_cfa_ntuple_filter_free(struct bnxt *bp,
        struct hwrm_cfa_ntuple_filter_free_input *req;
        int rc;
 
+       set_bit(BNXT_FLTR_FW_DELETED, &fltr->base.state);
        rc = hwrm_req_init(bp, req, HWRM_CFA_NTUPLE_FILTER_FREE);
        if (rc)
                return rc;
index 73e2fe705caf4516fc1ff32d6228db1165285a9a..f37d98d7962a0f4698a7fb70edf273d47d77dd21 100644 (file)
@@ -1349,6 +1349,7 @@ struct bnxt_filter_base {
        unsigned long           state;
 #define BNXT_FLTR_VALID                0
 #define BNXT_FLTR_INSERTED     1
+#define BNXT_FLTR_FW_DELETED   2
 
        struct rcu_head         rcu;
 };
index 65edad2cfeabfa8b9fb28ead9133f414cea1332b..8cc762a12a3e5ef83c0bdeac4c0410d328fafeb1 100644 (file)
@@ -1012,28 +1012,60 @@ static int bnxt_set_channels(struct net_device *dev,
 }
 
 #ifdef CONFIG_RFS_ACCEL
-static int bnxt_grxclsrlall(struct bnxt *bp, struct ethtool_rxnfc *cmd,
-                           u32 *rule_locs)
+static u32 bnxt_get_all_fltr_ids_rcu(struct bnxt *bp, struct hlist_head tbl[],
+                                    int tbl_size, u32 *ids, u32 start,
+                                    u32 id_cnt)
 {
-       int i, j = 0;
+       int i, j = start;
 
-       cmd->data = bp->ntp_fltr_count;
-       for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) {
+       if (j >= id_cnt)
+               return j;
+       for (i = 0; i < tbl_size; i++) {
                struct hlist_head *head;
-               struct bnxt_ntuple_filter *fltr;
+               struct bnxt_filter_base *fltr;
 
-               head = &bp->ntp_fltr_hash_tbl[i];
-               rcu_read_lock();
-               hlist_for_each_entry_rcu(fltr, head, base.hash) {
-                       if (j == cmd->rule_cnt)
-                               break;
-                       rule_locs[j++] = fltr->base.sw_id;
+               head = &tbl[i];
+               hlist_for_each_entry_rcu(fltr, head, hash) {
+                       if (!fltr->flags ||
+                           test_bit(BNXT_FLTR_FW_DELETED, &fltr->state))
+                               continue;
+                       ids[j++] = fltr->sw_id;
+                       if (j == id_cnt)
+                               return j;
                }
-               rcu_read_unlock();
-               if (j == cmd->rule_cnt)
-                       break;
        }
-       cmd->rule_cnt = j;
+       return j;
+}
+
+static struct bnxt_filter_base *bnxt_get_one_fltr_rcu(struct bnxt *bp,
+                                                     struct hlist_head tbl[],
+                                                     int tbl_size, u32 id)
+{
+       int i;
+
+       for (i = 0; i < tbl_size; i++) {
+               struct hlist_head *head;
+               struct bnxt_filter_base *fltr;
+
+               head = &tbl[i];
+               hlist_for_each_entry_rcu(fltr, head, hash) {
+                       if (fltr->flags && fltr->sw_id == id)
+                               return fltr;
+               }
+       }
+       return NULL;
+}
+
+static int bnxt_grxclsrlall(struct bnxt *bp, struct ethtool_rxnfc *cmd,
+                           u32 *rule_locs)
+{
+       cmd->data = bp->ntp_fltr_count;
+       rcu_read_lock();
+       cmd->rule_cnt = bnxt_get_all_fltr_ids_rcu(bp, bp->ntp_fltr_hash_tbl,
+                                                 BNXT_NTP_FLTR_HASH_SIZE,
+                                                 rule_locs, 0, cmd->rule_cnt);
+       rcu_read_unlock();
+
        return 0;
 }
 
@@ -1041,27 +1073,24 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
 {
        struct ethtool_rx_flow_spec *fs =
                (struct ethtool_rx_flow_spec *)&cmd->fs;
+       struct bnxt_filter_base *fltr_base;
        struct bnxt_ntuple_filter *fltr;
        struct flow_keys *fkeys;
-       int i, rc = -EINVAL;
+       int rc = -EINVAL;
 
        if (fs->location >= BNXT_NTP_FLTR_MAX_FLTR)
                return rc;
 
-       for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) {
-               struct hlist_head *head;
-
-               head = &bp->ntp_fltr_hash_tbl[i];
-               rcu_read_lock();
-               hlist_for_each_entry_rcu(fltr, head, base.hash) {
-                       if (fltr->base.sw_id == fs->location)
-                               goto fltr_found;
-               }
+       rcu_read_lock();
+       fltr_base = bnxt_get_one_fltr_rcu(bp, bp->ntp_fltr_hash_tbl,
+                                         BNXT_NTP_FLTR_HASH_SIZE,
+                                         fs->location);
+       if (!fltr_base) {
                rcu_read_unlock();
+               return rc;
        }
-       return rc;
+       fltr = container_of(fltr_base, struct bnxt_ntuple_filter, base);
 
-fltr_found:
        fkeys = &fltr->fkeys;
        if (fkeys->basic.n_proto == htons(ETH_P_IP)) {
                if (fkeys->basic.ip_proto == IPPROTO_TCP)