Merge "cnss2: Allow WLAN driver register after cold boot calibration"

This commit is contained in:
qctecmdr 2020-06-04 10:39:49 -07:00 • committed by Gerrit - the friendly Code Review server
commit b6ea26a756
5 changed files with 81 additions and 32 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -1497,7 +1497,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");
@ -1843,10 +1843,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;
@ -2133,14 +2135,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))
@ -2156,12 +2170,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,
@ -3222,7 +3235,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;
}

View file

@ -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;