qcacld-3.0: Minimize race condition by moving mutex iface_change_lock

In the case when Load Driver and MODEM ssr triggered at same time,
the handling by wlan_hdd_purge_notifier lead to a page fault crash
as waitlist of mutex was empty.

Moved the initialization of iface_change_lock to reduce the probability
of the crash.

Change-Id: I069fcf3fa8a9443daa9d36518bceb9e575b57eb6
CRs-fixed: 2124520i
This commit is contained in:
Sourav Mohapatra
2017-11-14 18:05:11 +05:30
committed by snandini
vanhempi 72df9ee8da
commit fed6aa926b

Näytä tiedosto

@@ -7798,6 +7798,33 @@ static int ie_whitelist_attrs_init(struct hdd_context *hdd_ctx)
return ret;
}
/**
* hdd_iface_change_callback() - Function invoked when stop modules expires
* @priv: pointer to hdd context
*
* This function is invoked when the timer waiting for the interface change
* expires, it shall cut-down the power to wlan and stop all the modules.
*
* Return: void
*/
static void hdd_iface_change_callback(void *priv)
{
struct hdd_context *hdd_ctx = (struct hdd_context *) priv;
int ret;
int status = wlan_hdd_validate_context(hdd_ctx);
if (status)
return;
ENTER();
hdd_debug("Interface change timer expired close the modules!");
ret = hdd_wlan_stop_modules(hdd_ctx, false);
if (ret)
hdd_err("Failed to stop modules");
EXIT();
}
/**
* hdd_context_create() - Allocate and inialize HDD context.
* @dev: Device Pointer to the underlying device
@@ -7821,6 +7848,11 @@ static struct hdd_context *hdd_context_create(struct device *dev)
goto err_out;
}
qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
hdd_iface_change_callback, (void *)hdd_ctx);
mutex_init(&hdd_ctx->iface_change_lock);
hdd_ctx->parent_dev = dev;
hdd_ctx->last_scan_reject_session_id = 0xFF;
@@ -7898,6 +7930,8 @@ err_free_config:
err_free_hdd_context:
wiphy_free(hdd_ctx->wiphy);
qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
mutex_destroy(&hdd_ctx->iface_change_lock);
err_out:
return ERR_PTR(ret);
@@ -9660,31 +9694,6 @@ done:
}
/**
* hdd_iface_change_callback() - Function invoked when stop modules expires
* @priv: pointer to hdd context
*
* This function is invoked when the timer waiting for the interface change
* expires, it shall cut-down the power to wlan and stop all the modules.
*
* Return: void
*/
static void hdd_iface_change_callback(void *priv)
{
struct hdd_context *hdd_ctx = (struct hdd_context *) priv;
int ret;
int status = wlan_hdd_validate_context(hdd_ctx);
if (status)
return;
ENTER();
hdd_debug("Interface change timer expired close the modules!");
ret = hdd_wlan_stop_modules(hdd_ctx, false);
if (ret)
hdd_err("Failed to stop modules");
EXIT();
}
/**
* hdd_state_info_dump() - prints state information of hdd layer
@@ -9850,12 +9859,8 @@ int hdd_wlan_startup(struct device *dev)
goto err_hdd_free_context;
}
qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
hdd_iface_change_callback, (void *)hdd_ctx);
qdf_nbuf_init_replenish_timer();
mutex_init(&hdd_ctx->iface_change_lock);
#ifdef FEATURE_WLAN_CH_AVOID
mutex_init(&hdd_ctx->avoid_freq_lock);
#endif
@@ -9992,8 +9997,6 @@ err_hdd_free_context:
hdd_start_complete(ret);
qdf_nbuf_deinit_replenish_timer();
qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
mutex_destroy(&hdd_ctx->iface_change_lock);
hdd_context_destroy(hdd_ctx);
return ret;