net/bnxt: add context list for timers
authorKishore Padmanabha <kishore.padmanabha@broadcom.com>
Sun, 30 May 2021 08:59:26 +0000 (14:29 +0530)
committerAjit Khaparde <ajit.khaparde@broadcom.com>
Thu, 8 Jul 2021 00:02:14 +0000 (02:02 +0200)
Add context in ULP for timers.
The alarm callback needs to have a valid context pointer when it is
invoked. The context could become invalid if the port goes down and
the callback is invoked before it is cancelled.

Signed-off-by: Kishore Padmanabha <kishore.padmanabha@broadcom.com>
Signed-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
Reviewed-by: Randy Schacher <stuart.schacher@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
drivers/net/bnxt/tf_ulp/bnxt_ulp.c
drivers/net/bnxt/tf_ulp/bnxt_ulp.h
drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
drivers/net/bnxt/tf_ulp/ulp_ha_mgr.c

index 972bf8b..5f15400 100644 (file)
@@ -8,6 +8,7 @@
 #include <rte_flow.h>
 #include <rte_flow_driver.h>
 #include <rte_tailq.h>
+#include <rte_spinlock.h>
 
 #include "bnxt.h"
 #include "bnxt_ulp.h"
@@ -32,6 +33,17 @@ STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
 /* Mutex to synchronize bnxt_ulp_session_list operations. */
 static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+/* Spin lock to protect context global list */
+rte_spinlock_t bnxt_ulp_ctxt_lock;
+TAILQ_HEAD(cntx_list_entry_list, ulp_context_list_entry);
+static struct cntx_list_entry_list ulp_cntx_list =
+       TAILQ_HEAD_INITIALIZER(ulp_cntx_list);
+
+/* Static function declarations */
+static int32_t bnxt_ulp_cntxt_list_init(void);
+static int32_t bnxt_ulp_cntxt_list_add(struct bnxt_ulp_context *ulp_ctx);
+static void bnxt_ulp_cntxt_list_del(struct bnxt_ulp_context *ulp_ctx);
+
 /*
  * Allow the deletion of context only for the bnxt device that
  * created the session.
@@ -743,6 +755,16 @@ ulp_ctx_init(struct bnxt *bp,
        int32_t                 rc = 0;
        enum bnxt_ulp_device_id devid;
 
+       /* Initialize the context entries list */
+       bnxt_ulp_cntxt_list_init();
+
+       /* Add the context to the context entries list */
+       rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx);
+       if (rc) {
+               BNXT_TF_DBG(ERR, "Failed to add the context list entry\n");
+               return -ENOMEM;
+       }
+
        /* Allocate memory to hold ulp context data. */
        ulp_data = rte_zmalloc("bnxt_ulp_data",
                               sizeof(struct bnxt_ulp_data), 0);
@@ -878,6 +900,13 @@ ulp_ctx_attach(struct bnxt *bp,
        /* update the session details in bnxt tfp */
        bp->tfp.session = session->g_tfp->session;
 
+       /* Add the context to the context entries list */
+       rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx);
+       if (rc) {
+               BNXT_TF_DBG(ERR, "Failed to add the context list entry\n");
+               return -EINVAL;
+       }
+
        /*
         * The supported flag will be set during the init. Use it now to
         * know if we should go through the attach.
@@ -1448,6 +1477,9 @@ bnxt_ulp_port_deinit(struct bnxt *bp)
        BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port deinit\n",
                    bp->eth_dev->data->port_id);
 
+       /* Free the ulp context in the context entry list */
+       bnxt_ulp_cntxt_list_del(bp->ulp_ctx);
+
        /* Get the session details  */
        pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
        pci_addr = &pci_dev->addr;
@@ -1887,3 +1919,66 @@ bnxt_ulp_cntxt_ha_enabled(struct bnxt_ulp_context *ulp_ctx)
                return false;
        return !!ULP_HIGH_AVAIL_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags);
 }
+
+static int32_t
+bnxt_ulp_cntxt_list_init(void)
+{
+       /* Create the cntxt spin lock */
+       rte_spinlock_init(&bnxt_ulp_ctxt_lock);
+
+       return 0;
+}
+
+static int32_t
+bnxt_ulp_cntxt_list_add(struct bnxt_ulp_context *ulp_ctx)
+{
+       struct ulp_context_list_entry   *entry;
+
+       entry = rte_zmalloc(NULL, sizeof(struct ulp_context_list_entry), 0);
+       if (entry == NULL) {
+               BNXT_TF_DBG(ERR, "unable to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       rte_spinlock_lock(&bnxt_ulp_ctxt_lock);
+       entry->ulp_ctx = ulp_ctx;
+       TAILQ_INSERT_TAIL(&ulp_cntx_list, entry, next);
+       rte_spinlock_unlock(&bnxt_ulp_ctxt_lock);
+       return 0;
+}
+
+static void
+bnxt_ulp_cntxt_list_del(struct bnxt_ulp_context *ulp_ctx)
+{
+       struct ulp_context_list_entry   *entry, *temp;
+
+       rte_spinlock_lock(&bnxt_ulp_ctxt_lock);
+       TAILQ_FOREACH_SAFE(entry, &ulp_cntx_list, next, temp) {
+               if (entry->ulp_ctx == ulp_ctx) {
+                       TAILQ_REMOVE(&ulp_cntx_list, entry, next);
+                       rte_free(entry);
+                       break;
+               }
+       }
+       rte_spinlock_unlock(&bnxt_ulp_ctxt_lock);
+}
+
+struct bnxt_ulp_context *
+bnxt_ulp_cntxt_entry_acquire(void)
+{
+       struct ulp_context_list_entry   *entry;
+
+       /* take a lock and get the first ulp context available */
+       if (rte_spinlock_trylock(&bnxt_ulp_ctxt_lock)) {
+               TAILQ_FOREACH(entry, &ulp_cntx_list, next)
+                       if (entry->ulp_ctx)
+                               return entry->ulp_ctx;
+       }
+       return NULL;
+}
+
+void
+bnxt_ulp_cntxt_entry_release(void)
+{
+       rte_spinlock_unlock(&bnxt_ulp_ctxt_lock);
+}
index b1f090a..ea38dc0 100644 (file)
@@ -112,6 +112,11 @@ struct ulp_tlv_param {
        uint8_t value[16];
 };
 
+struct ulp_context_list_entry {
+       TAILQ_ENTRY(ulp_context_list_entry)     next;
+       struct bnxt_ulp_context                 *ulp_ctx;
+};
+
 /*
  * Allow the deletion of context only for the bnxt device that
  * created the session
@@ -285,4 +290,11 @@ bnxt_ulp_cntxt_ptr2_ha_info_get(struct bnxt_ulp_context *ulp_ctx);
 
 bool
 bnxt_ulp_cntxt_ha_enabled(struct bnxt_ulp_context *ulp_ctx);
+
+struct bnxt_ulp_context *
+bnxt_ulp_cntxt_entry_acquire(void);
+
+void
+bnxt_ulp_cntxt_entry_release(void);
+
 #endif /* _BNXT_ULP_H_ */
index 7c83cb2..9a77132 100644 (file)
@@ -197,8 +197,7 @@ ulp_fc_mgr_thread_start(struct bnxt_ulp_context *ctxt)
 
        if (ulp_fc_info && !(ulp_fc_info->flags & ULP_FLAG_FC_THREAD)) {
                rte_eal_alarm_set(US_PER_S * ULP_FC_TIMER,
-                                 ulp_fc_mgr_alarm_cb,
-                                 (void *)ctxt);
+                                 ulp_fc_mgr_alarm_cb, NULL);
                ulp_fc_info->flags |= ULP_FLAG_FC_THREAD;
        }
 
@@ -220,7 +219,7 @@ void ulp_fc_mgr_thread_cancel(struct bnxt_ulp_context *ctxt)
                return;
 
        ulp_fc_info->flags &= ~ULP_FLAG_FC_THREAD;
-       rte_eal_alarm_cancel(ulp_fc_mgr_alarm_cb, (void *)ctxt);
+       rte_eal_alarm_cancel(ulp_fc_mgr_alarm_cb, NULL);
 }
 
 /*
@@ -363,35 +362,48 @@ static int ulp_get_single_flow_stat(struct bnxt_ulp_context *ctxt,
  */
 
 void
-ulp_fc_mgr_alarm_cb(void *arg)
+ulp_fc_mgr_alarm_cb(void *arg __rte_unused)
 {
        int rc = 0;
        unsigned int j;
        enum tf_dir i;
-       struct bnxt_ulp_context *ctxt = arg;
+       struct bnxt_ulp_context *ctxt;
        struct bnxt_ulp_fc_info *ulp_fc_info;
        struct bnxt_ulp_device_params *dparms;
        struct tf *tfp;
        uint32_t dev_id, hw_cntr_id = 0, num_entries = 0;
 
+       ctxt = bnxt_ulp_cntxt_entry_acquire();
+       if (ctxt == NULL) {
+               BNXT_TF_DBG(INFO, "could not get the ulp context lock\n");
+               rte_eal_alarm_set(US_PER_S * ULP_FC_TIMER,
+                                 ulp_fc_mgr_alarm_cb, NULL);
+               return;
+       }
+
        ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt);
-       if (!ulp_fc_info)
+       if (!ulp_fc_info) {
+               bnxt_ulp_cntxt_entry_release();
                return;
+       }
 
        if (bnxt_ulp_cntxt_dev_id_get(ctxt, &dev_id)) {
                BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
+               bnxt_ulp_cntxt_entry_release();
                return;
        }
 
        dparms = bnxt_ulp_device_params_get(dev_id);
        if (!dparms) {
                BNXT_TF_DBG(DEBUG, "Failed to device parms\n");
+               bnxt_ulp_cntxt_entry_release();
                return;
        }
 
        tfp = bnxt_ulp_cntxt_tfp_get(ctxt, BNXT_ULP_SHARED_SESSION_NO);
        if (!tfp) {
                BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n");
+               bnxt_ulp_cntxt_entry_release();
                return;
        }
 
@@ -405,6 +417,7 @@ ulp_fc_mgr_alarm_cb(void *arg)
        if (!ulp_fc_info->num_entries) {
                pthread_mutex_unlock(&ulp_fc_info->fc_lock);
                ulp_fc_mgr_thread_cancel(ctxt);
+               bnxt_ulp_cntxt_entry_release();
                return;
        }
        /*
@@ -443,12 +456,13 @@ ulp_fc_mgr_alarm_cb(void *arg)
 
        if (rc) {
                ulp_fc_mgr_thread_cancel(ctxt);
+               bnxt_ulp_cntxt_entry_release();
                return;
        }
 out:
+       bnxt_ulp_cntxt_entry_release();
        rte_eal_alarm_set(US_PER_S * ULP_FC_TIMER,
-                         ulp_fc_mgr_alarm_cb,
-                         (void *)ctxt);
+                         ulp_fc_mgr_alarm_cb, NULL);
 }
 
 /*
index dc71054..1cfe5cd 100644 (file)
@@ -26,7 +26,7 @@
 #define ULP_HA_IF_TBL_IDX 10
 
 static void ulp_ha_mgr_timer_cancel(struct bnxt_ulp_context *ulp_ctx);
-static int32_t ulp_ha_mgr_timer_start(struct bnxt_ulp_context *ulp_ctx);
+static int32_t ulp_ha_mgr_timer_start(void);
 static void ulp_ha_mgr_timer_cb(void *arg);
 static int32_t ulp_ha_mgr_app_type_set(struct bnxt_ulp_context *ulp_ctx,
                                enum ulp_ha_mgr_app_type app_type);
@@ -126,7 +126,7 @@ ulp_ha_mgr_app_type_set(struct bnxt_ulp_context *ulp_ctx,
  * - Release the flow db lock for flows to continue
  */
 static void
-ulp_ha_mgr_timer_cb(void *arg)
+ulp_ha_mgr_timer_cb(void *arg __rte_unused)
 {
        struct tf_move_tcam_shared_entries_parms mparms = { 0 };
        struct bnxt_ulp_context *ulp_ctx;
@@ -134,7 +134,13 @@ ulp_ha_mgr_timer_cb(void *arg)
        struct tf *tfp;
        int32_t rc;
 
-       ulp_ctx = (struct bnxt_ulp_context *)arg;
+       ulp_ctx = bnxt_ulp_cntxt_entry_acquire();
+       if (ulp_ctx == NULL) {
+               BNXT_TF_DBG(INFO, "could not get the ulp context lock\n");
+               ulp_ha_mgr_timer_start();
+               return;
+       }
+
        rc = ulp_ha_mgr_state_get(ulp_ctx, &curr_state);
        if (rc) {
                /*
@@ -180,31 +186,18 @@ ulp_ha_mgr_timer_cb(void *arg)
        BNXT_TF_DBG(INFO, "On HA CB: SEC[SEC_TIMER_COPY] => PRIM[PRIM_RUN]\n");
 unlock:
        bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
+       bnxt_ulp_cntxt_entry_release();
        return;
 cb_restart:
-       ulp_ha_mgr_timer_start(ulp_ctx);
+       bnxt_ulp_cntxt_entry_release();
+       ulp_ha_mgr_timer_start();
 }
 
 static int32_t
-ulp_ha_mgr_timer_start(struct bnxt_ulp_context *ulp_ctx)
+ulp_ha_mgr_timer_start(void)
 {
-       struct bnxt_ulp_ha_mgr_info *ha_info;
-
-       if (ulp_ctx == NULL) {
-               BNXT_TF_DBG(ERR, "Invalid parmsi for ha timer start.\n");
-               return -EINVAL;
-       }
-
-       ha_info = bnxt_ulp_cntxt_ptr2_ha_info_get(ulp_ctx);
-
-       if (ha_info == NULL) {
-               BNXT_TF_DBG(ERR, "Unable to get HA Info in timer start.\n");
-               return -EINVAL;
-       }
-       ha_info->flags |= ULP_HA_TIMER_THREAD;
        rte_eal_alarm_set(US_PER_S * ULP_HA_TIMER_SEC,
-                         ulp_ha_mgr_timer_cb,
-                         (void *)ulp_ctx);
+                         ulp_ha_mgr_timer_cb, NULL);
        return 0;
 }
 
@@ -374,7 +367,7 @@ ulp_ha_mgr_open(struct bnxt_ulp_context *ulp_ctx)
                 * Clear the high region so the secondary can begin overriding
                 * the current entries.
                 */
-               rc = ulp_ha_mgr_timer_start(ulp_ctx);
+               rc = ulp_ha_mgr_timer_start();
                if (rc) {
                        BNXT_TF_DBG(ERR, "Unable to start timer on HA Open.\n");
                        return -EINVAL;