mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-19 18:31:33 +00:00
202 lines
6.4 KiB
Diff
202 lines
6.4 KiB
Diff
--- a/drivers/net/wireless/ath/ath11k/ahb.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
|
|
@@ -573,6 +573,29 @@ static void ath11k_ahb_power_down(struct
|
|
rproc_shutdown(ab->tgt_rproc);
|
|
}
|
|
|
|
+int ath11k_ahb_fwreset_from_cold_boot(struct ath11k_base *ab)
|
|
+{
|
|
+ int timeout;
|
|
+
|
|
+ if (enable_cold_boot_cal == 0 || ab->qmi.cal_done)
|
|
+ return 0;
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_AHB, "wait for cold boot done\n");
|
|
+ timeout = wait_event_timeout(ab->qmi.cold_boot_waitq, (ab->qmi.cal_done == 1),
|
|
+ ATH11K_COLD_BOOT_FW_RESET_DELAY);
|
|
+ if (timeout <= 0) {
|
|
+ ath11k_warn(ab, "Coldboot Calibration timed out\n");
|
|
+ return -ETIMEDOUT;
|
|
+ }
|
|
+
|
|
+ /* reset the firmware */
|
|
+ ath11k_ahb_power_down(ab);
|
|
+ ath11k_ahb_power_up(ab);
|
|
+ ath11k_dbg(ab, ATH11K_DBG_AHB, "exit wait for cold boot done\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
|
|
{
|
|
struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
|
|
@@ -911,6 +934,8 @@ static int ath11k_ahb_probe(struct platf
|
|
goto err_ce_free;
|
|
}
|
|
|
|
+ ath11k_ahb_fwreset_from_cold_boot(ab);
|
|
+
|
|
return 0;
|
|
|
|
err_ce_free:
|
|
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -107,8 +107,12 @@ enum ath11k_firmware_mode {
|
|
|
|
/* factory tests etc */
|
|
ATH11K_FIRMWARE_MODE_FTM,
|
|
+
|
|
+ /* Cold boot calibration */
|
|
+ ATH11K_FIRMWARE_MODE_COLD_BOOT = 7,
|
|
};
|
|
|
|
+extern bool enable_cold_boot_cal;
|
|
#define ATH11K_IRQ_NUM_MAX 52
|
|
#define ATH11K_EXT_IRQ_NUM_MAX 16
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/qmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
|
|
@@ -12,6 +12,12 @@
|
|
#define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02
|
|
#define HOST_CSTATE_BIT 0x04
|
|
|
|
+/* set the default max assoc sta to max supported by driver */
|
|
+bool enable_cold_boot_cal = 1;
|
|
+EXPORT_SYMBOL(enable_cold_boot_cal);
|
|
+module_param(enable_cold_boot_cal, bool, 0644);
|
|
+MODULE_PARM_DESC(enable_cold_boot_cal, "cold boot calibration enable:1 disable:0");
|
|
+
|
|
static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
|
|
{
|
|
.data_type = QMI_OPT_FLAG,
|
|
@@ -1752,6 +1758,7 @@ static int ath11k_qmi_alloc_target_mem_c
|
|
static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
|
|
{
|
|
int i, idx;
|
|
+ u32 caldb_location[2] = {0, 0};
|
|
|
|
for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
|
|
switch (ab->qmi.target_mem[i].type) {
|
|
@@ -1767,9 +1774,20 @@ static int ath11k_qmi_assign_target_mem_
|
|
ath11k_warn(ab, "qmi mem size is low to load caldata\n");
|
|
return -EINVAL;
|
|
}
|
|
- /* TODO ath11k does not support cold boot calibration */
|
|
- ab->qmi.target_mem[idx].paddr = 0;
|
|
- ab->qmi.target_mem[idx].vaddr = NULL;
|
|
+
|
|
+ if (of_property_read_u32_array(ab->dev->of_node, "qcom,caldb-addr",
|
|
+ &caldb_location[0],
|
|
+ ARRAY_SIZE(caldb_location))) {
|
|
+ ath11k_warn(ab, "qmi no bdf_addr in device_tree\n");
|
|
+ }
|
|
+
|
|
+ if (enable_cold_boot_cal) {
|
|
+ ab->qmi.target_mem[idx].paddr = caldb_location[ab->qmi.target_mem_mode];
|
|
+ ab->qmi.target_mem[idx].vaddr = caldb_location[ab->qmi.target_mem_mode];
|
|
+ } else {
|
|
+ ab->qmi.target_mem[idx].paddr = 0;
|
|
+ ab->qmi.target_mem[idx].vaddr = 0;
|
|
+ }
|
|
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
|
|
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
|
|
idx++;
|
|
@@ -2331,6 +2349,30 @@ int ath11k_qmi_firmware_start(struct ath
|
|
return 0;
|
|
}
|
|
|
|
+int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab)
|
|
+{
|
|
+ int ret;
|
|
+ int timeout;
|
|
+
|
|
+ ret = ath11k_qmi_wlanfw_mode_send(ab, ATH11K_FIRMWARE_MODE_COLD_BOOT);
|
|
+ if (ret < 0) {
|
|
+ ath11k_warn(ab, "qmi failed to send wlan fw mode:%d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ath11k_info(ab, "Coldboot calibration wait started\n");
|
|
+ timeout = wait_event_timeout(ab->qmi.cold_boot_waitq, (ab->qmi.cal_done == 1),
|
|
+ ATH11K_COLD_BOOT_FW_RESET_DELAY);
|
|
+ if (timeout <= 0) {
|
|
+ ath11k_warn(ab, "Coldboot Calibration timed out\n");
|
|
+ return -ETIMEDOUT;
|
|
+ }
|
|
+
|
|
+ ath11k_info(ab, "Coldboot calibration wait ended\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int
|
|
ath11k_qmi_driver_event_post(struct ath11k_qmi *qmi,
|
|
enum ath11k_qmi_event_type type,
|
|
@@ -2480,11 +2522,17 @@ static void ath11k_qmi_msg_fw_ready_cb(s
|
|
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_READY, NULL);
|
|
}
|
|
|
|
-static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi,
|
|
+static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi_hdl,
|
|
struct sockaddr_qrtr *sq,
|
|
struct qmi_txn *txn,
|
|
const void *decoded)
|
|
{
|
|
+ struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
|
|
+ struct ath11k_base *ab = qmi->ab;
|
|
+
|
|
+ ab->qmi.cal_done = 1;
|
|
+ wake_up(&ab->qmi.cold_boot_waitq);
|
|
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cold boot calibration done\n");
|
|
}
|
|
|
|
static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
|
|
@@ -2596,11 +2644,14 @@ static void ath11k_qmi_driver_event_work
|
|
queue_work(ab->workqueue, &ab->restart_work);
|
|
break;
|
|
}
|
|
-
|
|
- ath11k_core_qmi_firmware_ready(ab);
|
|
- ab->qmi.cal_done = 1;
|
|
- set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
|
|
-
|
|
+ if (enable_cold_boot_cal && ab->qmi.cal_done == 0) {
|
|
+ ath11k_qmi_process_coldboot_calibration(ab);
|
|
+ } else {
|
|
+ clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
|
|
+ clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
|
|
+ ath11k_core_qmi_firmware_ready(ab);
|
|
+ set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
|
|
+ }
|
|
break;
|
|
case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE:
|
|
break;
|
|
--- a/drivers/net/wireless/ath/ath11k/qmi.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/qmi.h
|
|
@@ -33,6 +33,7 @@
|
|
#define QMI_WLANFW_MAX_DATA_SIZE_V01 6144
|
|
#define ATH11K_FIRMWARE_MODE_OFF 4
|
|
#define ATH11K_QMI_TARGET_MEM_MODE_DEFAULT 0
|
|
+#define ATH11K_COLD_BOOT_FW_RESET_DELAY (40 * HZ)
|
|
|
|
struct ath11k_base;
|
|
|
|
@@ -125,6 +126,7 @@ struct ath11k_qmi {
|
|
struct target_info target;
|
|
struct m3_mem_region m3_mem;
|
|
unsigned int service_ins_id;
|
|
+ wait_queue_head_t cold_boot_waitq;
|
|
};
|
|
|
|
#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 189
|
|
--- a/drivers/net/wireless/ath/ath11k/core.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
|
@@ -901,6 +901,7 @@ struct ath11k_base *ath11k_core_alloc(st
|
|
INIT_LIST_HEAD(&ab->peers);
|
|
init_waitqueue_head(&ab->peer_mapping_wq);
|
|
init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);
|
|
+ init_waitqueue_head(&ab->qmi.cold_boot_waitq);
|
|
INIT_WORK(&ab->restart_work, ath11k_core_restart);
|
|
timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
|
|
ab->dev = dev;
|