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>
#include <rte_flow.h>
#include <rte_flow_driver.h>
#include <rte_tailq.h>
+#include <rte_spinlock.h>
#include "bnxt.h"
#include "bnxt_ulp.h"
/* 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.
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);
/* 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.
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;
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);
+}
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
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_ */
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;
}
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);
}
/*
*/
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;
}
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;
}
/*
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);
}
/*
#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);
* - 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;
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) {
/*
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;
}
* 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;