Merge "[qca-nss-ecm] Fix destroy re-try mechanism."
diff --git a/ecm_db.c b/ecm_db.c
index ebcf79c..d15e33b 100644
--- a/ecm_db.c
+++ b/ecm_db.c
@@ -1040,6 +1040,8 @@
*/
static void ecm_db_connection_defunct_callback(void *arg)
{
+ struct ecm_front_end_connection_instance *feci;
+ ecm_front_end_acceleration_mode_t accel_mode;
struct ecm_db_connection_instance *ci = (struct ecm_db_connection_instance *)arg;
DEBUG_CHECK_MAGIC(ci, ECM_DB_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", ci);
@@ -1049,7 +1051,20 @@
ci->defunct(ci->feci);
}
- ecm_db_connection_deref(ci);
+ feci = ecm_db_connection_front_end_get_and_ref(ci);
+ accel_mode = feci->accel_state_get(feci);
+ feci->deref(feci);
+
+ /*
+ * It is possible that the defunct process fails and re-try is in progress.
+ * In that case we set the accel mode of the connection to
+ * ECM_FRONT_END_ACCELERATION_MODE_ACCEL so that in the next destroy try the connection
+ * status would be correct. So, if the accel_mode is ECM_FRONT_END_ACCELERATION_MODE_ACCEL,
+ * we shouldn't release the last reference count.
+ */
+ if (accel_mode != ECM_FRONT_END_ACCELERATION_MODE_ACCEL) {
+ ecm_db_connection_deref(ci);
+ }
}
/*
@@ -2385,6 +2400,42 @@
EXPORT_SYMBOL(ecm_db_timer_group_entry_set);
/*
+ * ecm_db_connection_defunct_timer_remove_and_set()
+ * Move the connection to a new timer group.
+ *
+ * Before setting the new group, check if the timer group is set. If it is set,
+ * remove it first from the current group.
+ *
+ */
+void ecm_db_connection_defunct_timer_remove_and_set(struct ecm_db_connection_instance *ci, ecm_db_timer_group_t tg)
+{
+ struct ecm_db_timer_group_entry *tge;
+
+ DEBUG_CHECK_MAGIC(ci, ECM_DB_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", ci);
+ DEBUG_TRACE("%p: ecm_db_connection_defunct_timer_remove_and_set\n", ci);
+
+ spin_lock_bh(&ecm_db_lock);
+ tge = &ci->defunct_timer;
+ if (tge->group == tg) {
+ spin_unlock_bh(&ecm_db_lock);
+ DEBUG_TRACE("%p: timer group is aslready equal to %d\n", ci, tg);
+ return;
+ }
+
+ if (tge->group != ECM_DB_TIMER_GROUPS_MAX) {
+ _ecm_db_timer_group_entry_remove(tge);
+ }
+
+ /*
+ * Set new group
+ */
+ _ecm_db_timer_group_entry_set(tge, tg);
+ spin_unlock_bh(&ecm_db_lock);
+ DEBUG_TRACE("%p: New timer group is: %d\n", ci, tge->group);
+}
+EXPORT_SYMBOL(ecm_db_connection_defunct_timer_remove_and_set);
+
+/*
* ecm_db_timer_group_entry_init()
* Initialise a timer entry ready for setting
*/
diff --git a/ecm_db.h b/ecm_db.h
index d42bcef..6786f46 100644
--- a/ecm_db.h
+++ b/ecm_db.h
@@ -38,6 +38,7 @@
void ecm_db_connection_data_totals_update_dropped(struct ecm_db_connection_instance *ci, bool is_from, uint64_t size, uint64_t packets);
void ecm_db_connection_data_totals_update(struct ecm_db_connection_instance *ci, bool is_from, uint64_t size, uint64_t packets);
+void ecm_db_connection_defunct_timer_remove_and_set(struct ecm_db_connection_instance *ci, ecm_db_timer_group_t tg);
int ecm_db_connection_elapsed_defunct_timer(struct ecm_db_connection_instance *ci);
bool ecm_db_connection_defunct_timer_reset(struct ecm_db_connection_instance *ci, ecm_db_timer_group_t tg);
bool ecm_db_connection_defunct_timer_touch(struct ecm_db_connection_instance *ci);
diff --git a/frontends/ecm_front_end_common.c b/frontends/ecm_front_end_common.c
index 6ed9d4b..37e02f0 100644
--- a/frontends/ecm_front_end_common.c
+++ b/frontends/ecm_front_end_common.c
@@ -110,8 +110,8 @@
spin_unlock_bh(&feci->lock);
/*
- * Reset the defunct timer to a smaller timeout value so that the connection will be
+ * Set the defunct timer to a smaller timeout value so that the connection will be
* tried to be defuncted again, when the timeout expires (its value is 5 seconds).
*/
- ecm_db_connection_defunct_timer_reset(feci->ci, ECM_DB_TIMER_GROUPS_CONNECTION_DEFUNCT_RETRY_TIMEOUT);
+ ecm_db_connection_defunct_timer_remove_and_set(feci->ci, ECM_DB_TIMER_GROUPS_CONNECTION_DEFUNCT_RETRY_TIMEOUT);
}