mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 21:59:12 -04:00
cnss2: Allow WLAN driver register after cold boot calibration
When cold boot calibration is enabled, it is the first step in WLAN initialization. Cold boot calibration is started post file system mount from init.target.rc and wlan driver is loaded after that. This update is to reject wlan driver register if it is loaded before cold boot calibration is complete. This ensures WLAN init sequence triggered from init.target.rc is followed and wlan driver load from early boot is rejected. Change-Id: Id2d7b6f9ceed0d6d648012ad6d0c24bba4d09854 Signed-off-by: Manikandan Mohan <manikand@codeaurora.org>
This commit is contained in:
parent
bf4eaa44f7
commit
f6efedba75
5 changed files with 81 additions and 32 deletions
|
|
@ -71,8 +71,8 @@ static int cnss_stats_show_state(struct seq_file *s,
|
|||
case CNSS_FW_READY:
|
||||
seq_puts(s, "FW_READY");
|
||||
continue;
|
||||
case CNSS_COLD_BOOT_CAL:
|
||||
seq_puts(s, "COLD_BOOT_CAL");
|
||||
case CNSS_IN_COLD_BOOT_CAL:
|
||||
seq_puts(s, "IN_COLD_BOOT_CAL");
|
||||
continue;
|
||||
case CNSS_DRIVER_LOADING:
|
||||
seq_puts(s, "DRIVER_LOADING");
|
||||
|
|
@ -113,6 +113,9 @@ static int cnss_stats_show_state(struct seq_file *s,
|
|||
case CNSS_IN_REBOOT:
|
||||
seq_puts(s, "IN_REBOOT");
|
||||
continue;
|
||||
case CNSS_COLD_BOOT_CAL_DONE:
|
||||
seq_puts(s, "COLD_BOOT_CAL_DONE");
|
||||
continue;
|
||||
}
|
||||
|
||||
seq_printf(s, "UNKNOWN-%d", i);
|
||||
|
|
|
|||
|
|
@ -390,6 +390,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
|
|||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
cnss_pr_dbg("Processing FW Init Done..\n");
|
||||
del_timer(&plat_priv->fw_boot_timer);
|
||||
set_bit(CNSS_FW_READY, &plat_priv->driver_state);
|
||||
clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
|
||||
|
|
@ -402,7 +403,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
|
|||
if (test_bit(ENABLE_WALTEST, &plat_priv->ctrl_params.quirks)) {
|
||||
ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
|
||||
CNSS_WALTEST);
|
||||
} else if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) {
|
||||
} else if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state)) {
|
||||
cnss_request_antenna_sharing(plat_priv);
|
||||
ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
|
||||
CNSS_CALIBRATION);
|
||||
|
|
@ -1273,19 +1274,30 @@ static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv)
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
if (test_bit(CNSS_FW_READY, &plat_priv->driver_state) ||
|
||||
test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
|
||||
test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
|
||||
cnss_pr_dbg("Device is already active, ignore calibration\n");
|
||||
if (test_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state)) {
|
||||
cnss_pr_dbg("Calibration complete. Ignore calibration req\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
set_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
|
||||
if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
|
||||
test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state) ||
|
||||
test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
|
||||
cnss_pr_err("WLAN in mission mode before cold boot calibration\n");
|
||||
CNSS_ASSERT(0);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
set_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
|
||||
reinit_completion(&plat_priv->cal_complete);
|
||||
ret = cnss_bus_dev_powerup(plat_priv);
|
||||
if (ret) {
|
||||
complete(&plat_priv->cal_complete);
|
||||
clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
|
||||
clear_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
|
||||
/* Set CBC done in driver state to mark attempt and note error
|
||||
* since calibration cannot be retried at boot.
|
||||
*/
|
||||
plat_priv->cal_done = CNSS_CAL_FAILURE;
|
||||
set_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state);
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
@ -1297,7 +1309,7 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv,
|
|||
{
|
||||
struct cnss_cal_info *cal_info = data;
|
||||
|
||||
if (!test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state))
|
||||
if (!test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state))
|
||||
goto out;
|
||||
|
||||
switch (cal_info->cal_status) {
|
||||
|
|
@ -1306,7 +1318,9 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv,
|
|||
plat_priv->cal_done = true;
|
||||
break;
|
||||
case CNSS_CAL_TIMEOUT:
|
||||
cnss_pr_dbg("Calibration timed out, force shutdown\n");
|
||||
case CNSS_CAL_FAILURE:
|
||||
cnss_pr_dbg("Calibration failed. Status: %d, force shutdown\n",
|
||||
cal_info->cal_status);
|
||||
break;
|
||||
default:
|
||||
cnss_pr_err("Unknown calibration status: %u\n",
|
||||
|
|
@ -1320,7 +1334,8 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv,
|
|||
cnss_bus_dev_shutdown(plat_priv);
|
||||
msleep(COLD_BOOT_CAL_SHUTDOWN_DELAY_MS);
|
||||
complete(&plat_priv->cal_complete);
|
||||
clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
|
||||
clear_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
|
||||
set_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state);
|
||||
|
||||
out:
|
||||
kfree(data);
|
||||
|
|
@ -2022,7 +2037,7 @@ static ssize_t fs_ready_store(struct device *dev,
|
|||
return count;
|
||||
}
|
||||
|
||||
if (fs_ready == FILE_SYSTEM_READY) {
|
||||
if (fs_ready == FILE_SYSTEM_READY && plat_priv->cbc_enabled) {
|
||||
cnss_driver_event_post(plat_priv,
|
||||
CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START,
|
||||
0, NULL);
|
||||
|
|
@ -2179,6 +2194,9 @@ static void cnss_init_control_params(struct cnss_plat_data *plat_priv)
|
|||
"cnss-daemon-support"))
|
||||
plat_priv->ctrl_params.quirks |= BIT(ENABLE_DAEMON_SUPPORT);
|
||||
|
||||
plat_priv->cbc_enabled =
|
||||
of_property_read_bool(plat_priv->plat_dev->dev.of_node,
|
||||
"qcom,wlan-cbc-enabled");
|
||||
plat_priv->ctrl_params.mhi_timeout = CNSS_MHI_TIMEOUT_DEFAULT;
|
||||
plat_priv->ctrl_params.mhi_m2_timeout = CNSS_MHI_M2_TIMEOUT_DEFAULT;
|
||||
plat_priv->ctrl_params.qmi_timeout = CNSS_QMI_TIMEOUT_DEFAULT;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#define CNSS_RDDM_TIMEOUT_MS 20000
|
||||
#define RECOVERY_TIMEOUT 60000
|
||||
#define WLAN_WD_TIMEOUT_MS 60000
|
||||
#define WLAN_COLD_BOOT_CAL_TIMEOUT 60000
|
||||
#define WLAN_DRIVER_LOAD_TIMEOUT 90000
|
||||
#define TIME_CLOCK_FREQ_HZ 19200000
|
||||
#define CNSS_RAMDUMP_MAGIC 0x574C414E
|
||||
#define CNSS_RAMDUMP_VERSION 0
|
||||
|
|
@ -218,23 +220,24 @@ enum cnss_driver_event_type {
|
|||
};
|
||||
|
||||
enum cnss_driver_state {
|
||||
CNSS_QMI_WLFW_CONNECTED,
|
||||
CNSS_QMI_WLFW_CONNECTED = 0,
|
||||
CNSS_FW_MEM_READY,
|
||||
CNSS_FW_READY,
|
||||
CNSS_COLD_BOOT_CAL,
|
||||
CNSS_IN_COLD_BOOT_CAL,
|
||||
CNSS_DRIVER_LOADING,
|
||||
CNSS_DRIVER_UNLOADING,
|
||||
CNSS_DRIVER_UNLOADING = 5,
|
||||
CNSS_DRIVER_IDLE_RESTART,
|
||||
CNSS_DRIVER_IDLE_SHUTDOWN,
|
||||
CNSS_DRIVER_PROBED,
|
||||
CNSS_DRIVER_RECOVERY,
|
||||
CNSS_FW_BOOT_RECOVERY,
|
||||
CNSS_FW_BOOT_RECOVERY = 10,
|
||||
CNSS_DEV_ERR_NOTIFY,
|
||||
CNSS_DRIVER_DEBUG,
|
||||
CNSS_COEX_CONNECTED,
|
||||
CNSS_IMS_CONNECTED,
|
||||
CNSS_IN_SUSPEND_RESUME,
|
||||
CNSS_IN_SUSPEND_RESUME = 15,
|
||||
CNSS_IN_REBOOT,
|
||||
CNSS_COLD_BOOT_CAL_DONE,
|
||||
};
|
||||
|
||||
struct cnss_recovery_data {
|
||||
|
|
@ -285,6 +288,7 @@ enum cnss_bdf_type {
|
|||
enum cnss_cal_status {
|
||||
CNSS_CAL_DONE,
|
||||
CNSS_CAL_TIMEOUT,
|
||||
CNSS_CAL_FAILURE,
|
||||
};
|
||||
|
||||
struct cnss_cal_info {
|
||||
|
|
@ -393,6 +397,7 @@ struct cnss_plat_data {
|
|||
u64 dynamic_feature;
|
||||
void *get_info_cb_ctx;
|
||||
int (*get_info_cb)(void *ctx, void *event, int event_len);
|
||||
bool cbc_enabled;
|
||||
u8 use_nv_mac;
|
||||
u8 set_wlaon_pwr_ctrl;
|
||||
struct kobject *shutdown_kobj;
|
||||
|
|
|
|||
|
|
@ -1493,7 +1493,7 @@ int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv)
|
|||
|
||||
plat_priv = pci_priv->plat_priv;
|
||||
|
||||
if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state) ||
|
||||
if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state) ||
|
||||
test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state) ||
|
||||
test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
|
||||
cnss_pr_dbg("Skip driver remove\n");
|
||||
|
|
@ -1839,10 +1839,12 @@ retry:
|
|||
if (ret)
|
||||
goto stop_mhi;
|
||||
} else if (timeout) {
|
||||
if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state))
|
||||
timeout = timeout << 1;
|
||||
if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state))
|
||||
timeout += WLAN_COLD_BOOT_CAL_TIMEOUT;
|
||||
else
|
||||
timeout += WLAN_DRIVER_LOAD_TIMEOUT;
|
||||
mod_timer(&plat_priv->fw_boot_timer,
|
||||
jiffies + msecs_to_jiffies(timeout << 1));
|
||||
jiffies + msecs_to_jiffies(timeout));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -2129,14 +2131,26 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops)
|
|||
return -EEXIST;
|
||||
}
|
||||
|
||||
if (!test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state))
|
||||
if (!plat_priv->cbc_enabled ||
|
||||
test_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state))
|
||||
goto register_driver;
|
||||
|
||||
cnss_pr_dbg("Start to wait for calibration to complete\n");
|
||||
/* If enabled Cold Boot Calibration is the 1st step in init sequence.
|
||||
* CBC is done on file system_ready trigger. Qcacld should be loaded
|
||||
* from init.target.rc after that. Reject qcacld load from
|
||||
* vendor_modprobe.sh at early boot to satisfy this requirement.
|
||||
*/
|
||||
if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state)) {
|
||||
cnss_pr_dbg("Start to wait for calibration to complete\n");
|
||||
} else {
|
||||
cnss_pr_err("Reject WLAN Driver insmod before CBC\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
timeout = cnss_get_boot_timeout(&pci_priv->pci_dev->dev);
|
||||
ret = wait_for_completion_timeout(&plat_priv->cal_complete,
|
||||
msecs_to_jiffies(timeout) << 2);
|
||||
WLAN_COLD_BOOT_CAL_TIMEOUT +
|
||||
msecs_to_jiffies(timeout));
|
||||
if (!ret) {
|
||||
cnss_pr_err("Timeout waiting for calibration to complete\n");
|
||||
if (!test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state))
|
||||
|
|
@ -2152,12 +2166,11 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops)
|
|||
0, cal_info);
|
||||
}
|
||||
|
||||
register_driver:
|
||||
if (test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state)) {
|
||||
cnss_pr_dbg("Reboot or shutdown is in progress, ignore register driver\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
register_driver:
|
||||
reinit_completion(&plat_priv->power_up_complete);
|
||||
ret = cnss_driver_event_post(plat_priv,
|
||||
CNSS_DRIVER_EVENT_REGISTER_DRIVER,
|
||||
|
|
@ -3218,7 +3231,7 @@ void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv)
|
|||
if (!plat_priv)
|
||||
return;
|
||||
|
||||
if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) {
|
||||
if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state)) {
|
||||
cnss_pr_dbg("Ignore FW ready timeout for calibration mode\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,12 +78,11 @@ static int cnss_wlfw_ind_register_send_sync(struct cnss_plat_data *plat_priv)
|
|||
|
||||
req->client_id_valid = 1;
|
||||
req->client_id = WLFW_CLIENT_ID;
|
||||
req->fw_ready_enable_valid = 1;
|
||||
req->fw_ready_enable = 1;
|
||||
req->request_mem_enable_valid = 1;
|
||||
req->request_mem_enable = 1;
|
||||
req->fw_mem_ready_enable_valid = 1;
|
||||
req->fw_mem_ready_enable = 1;
|
||||
/* fw_ready indication is replaced by fw_init_done in HST/HSP */
|
||||
req->fw_init_done_enable_valid = 1;
|
||||
req->fw_init_done_enable = 1;
|
||||
req->pin_connect_result_enable_valid = 1;
|
||||
|
|
@ -1776,6 +1775,12 @@ static void cnss_wlfw_fw_mem_ready_ind_cb(struct qmi_handle *qmi_wlfw,
|
|||
0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_wlfw_fw_ready_ind_cb: FW ready indication handler (Helium arch)
|
||||
*
|
||||
* This event is not required for HST/ HSP as FW calibration done is
|
||||
* provided in QMI_WLFW_CAL_DONE_IND_V01
|
||||
*/
|
||||
static void cnss_wlfw_fw_ready_ind_cb(struct qmi_handle *qmi_wlfw,
|
||||
struct sockaddr_qrtr *sq,
|
||||
struct qmi_txn *txn, const void *data)
|
||||
|
|
@ -1784,13 +1789,18 @@ static void cnss_wlfw_fw_ready_ind_cb(struct qmi_handle *qmi_wlfw,
|
|||
container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
|
||||
struct cnss_cal_info *cal_info;
|
||||
|
||||
cnss_pr_dbg("Received QMI WLFW FW ready indication\n");
|
||||
|
||||
if (!txn) {
|
||||
cnss_pr_err("Spurious indication\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (plat_priv->device_id == QCA6390_DEVICE_ID ||
|
||||
plat_priv->device_id == QCA6490_DEVICE_ID) {
|
||||
cnss_pr_dbg("Ignore FW Ready Indication for HST/HSP");
|
||||
return;
|
||||
}
|
||||
|
||||
cnss_pr_dbg("Received QMI WLFW FW ready indication.\n");
|
||||
cal_info = kzalloc(sizeof(*cal_info), GFP_KERNEL);
|
||||
if (!cal_info)
|
||||
return;
|
||||
|
|
|
|||
Loading…
Reference in a new issue