cnss2: Add mutex protection between unregister driver and idle restart

Since idle restart is a multiple stages power up sequence, there will be
race conditions when idle restart and unregister driver (which is power
down sequence) come at the same time. Add mutex protection for them so
that they can be serialized completely.

Change-Id: Icc28b5f759cd690cb505b16ab70eaa4abaf2e4cc
Signed-off-by: Yue Ma <yuem@codeaurora.org>
This commit is contained in:
Yue Ma 2020-05-11 17:35:27 -07:00
parent 1edb650f82
commit dc1bf9b8a8
3 changed files with 11 additions and 3 deletions

View file

@ -665,6 +665,8 @@ int cnss_idle_restart(struct device *dev)
return -ENODEV;
}
mutex_lock(&plat_priv->driver_ops_lock);
cnss_pr_dbg("Doing idle restart\n");
reinit_completion(&plat_priv->power_up_complete);
@ -703,9 +705,11 @@ int cnss_idle_restart(struct device *dev)
goto out;
}
mutex_unlock(&plat_priv->driver_ops_lock);
return 0;
out:
mutex_unlock(&plat_priv->driver_ops_lock);
return ret;
}
EXPORT_SYMBOL(cnss_idle_restart);
@ -2154,6 +2158,7 @@ static int cnss_misc_init(struct cnss_plat_data *plat_priv)
init_completion(&plat_priv->rddm_complete);
init_completion(&plat_priv->recovery_complete);
mutex_init(&plat_priv->dev_lock);
mutex_init(&plat_priv->driver_ops_lock);
return 0;
}

View file

@ -361,6 +361,7 @@ struct cnss_plat_data {
struct completion power_up_complete;
struct completion cal_complete;
struct mutex dev_lock; /* mutex for register access through debugfs */
struct mutex driver_ops_lock; /* mutex for external driver ops */
u32 device_freq_hz;
u32 diag_reg_read_addr;
u32 diag_reg_read_mem_type;

View file

@ -2126,9 +2126,9 @@ void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver_ops)
return;
}
if (plat_priv->device_id == QCA6174_DEVICE_ID ||
!(test_bit(CNSS_DRIVER_IDLE_RESTART, &plat_priv->driver_state) ||
test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state)))
mutex_lock(&plat_priv->driver_ops_lock);
if (plat_priv->device_id == QCA6174_DEVICE_ID)
goto skip_wait_power_up;
timeout = cnss_get_qmi_timeout(plat_priv);
@ -2157,6 +2157,8 @@ skip_wait_recovery:
cnss_driver_event_post(plat_priv,
CNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
CNSS_EVENT_SYNC_UNKILLABLE, NULL);
mutex_unlock(&plat_priv->driver_ops_lock);
}
EXPORT_SYMBOL(cnss_wlan_unregister_driver);