Merge "icnss: Add IO reset logic"

This commit is contained in:
Linux Build Service Account 2016-09-10 06:39:05 -07:00 committed by Gerrit - the friendly Code Review server
commit 50ad11fb8b
3 changed files with 193 additions and 103 deletions

View file

@ -523,6 +523,7 @@ CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_IRQ_HELPER=y CONFIG_QCOM_IRQ_HELPER=y
CONFIG_QCOM_MEMORY_DUMP_V2=y CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_ICNSS=y CONFIG_ICNSS=y
CONFIG_ICNSS_DEBUG=y
CONFIG_MSM_GLADIATOR_ERP_V2=y CONFIG_MSM_GLADIATOR_ERP_V2=y
CONFIG_PANIC_ON_GLADIATOR_ERROR_V2=y CONFIG_PANIC_ON_GLADIATOR_ERROR_V2=y
CONFIG_MSM_GLADIATOR_HANG_DETECT=y CONFIG_MSM_GLADIATOR_HANG_DETECT=y

View file

@ -417,6 +417,15 @@ config ICNSS
control messages to FW over QMI channel. It is also responsible for control messages to FW over QMI channel. It is also responsible for
handling WLAN PD restart notifications. handling WLAN PD restart notifications.
config ICNSS_DEBUG
bool "ICNSS debug support"
depends on ICNSS
---help---
Say 'Y' here to enable ICNSS driver debug support. Debug support
primarily consists of logs consisting of information related to
hardware register access and enabling BUG_ON for certain cases to aid
the debugging.
config MSM_SECURE_BUFFER config MSM_SECURE_BUFFER
bool "Helper functions for securing buffers through TZ" bool "Helper functions for securing buffers through TZ"
help help

View file

@ -44,11 +44,11 @@
#include "wlan_firmware_service_v01.h" #include "wlan_firmware_service_v01.h"
#define ICNSS_PANIC 1
#define WLFW_TIMEOUT_MS 3000 #define WLFW_TIMEOUT_MS 3000
#define WLFW_SERVICE_INS_ID_V01 0 #define WLFW_SERVICE_INS_ID_V01 0
#define MAX_PROP_SIZE 32 #define MAX_PROP_SIZE 32
#define NUM_LOG_PAGES 4 #define NUM_LOG_PAGES 10
#define NUM_REG_LOG_PAGES 4
/* /*
* Registers: MPM2_PSHOLD * Registers: MPM2_PSHOLD
@ -57,9 +57,12 @@
#define MPM_WCSSAON_CONFIG_OFFSET 0x18 #define MPM_WCSSAON_CONFIG_OFFSET 0x18
#define MPM_WCSSAON_CONFIG_ARES_N BIT(0) #define MPM_WCSSAON_CONFIG_ARES_N BIT(0)
#define MPM_WCSSAON_CONFIG_WLAN_DISABLE BIT(1) #define MPM_WCSSAON_CONFIG_WLAN_DISABLE BIT(1)
#define MPM_WCSSAON_CONFIG_MSM_CLAMP_EN_OVRD BIT(6)
#define MPM_WCSSAON_CONFIG_MSM_CLAMP_EN_OVRD_VAL BIT(7)
#define MPM_WCSSAON_CONFIG_FORCE_ACTIVE BIT(14) #define MPM_WCSSAON_CONFIG_FORCE_ACTIVE BIT(14)
#define MPM_WCSSAON_CONFIG_FORCE_XO_ENABLE BIT(19) #define MPM_WCSSAON_CONFIG_FORCE_XO_ENABLE BIT(19)
#define MPM_WCSSAON_CONFIG_DISCONNECT_CLR BIT(21) #define MPM_WCSSAON_CONFIG_DISCONNECT_CLR BIT(21)
#define MPM_WCSSAON_CONFIG_M2W_CLAMP_EN BIT(22)
/* /*
* Registers: WCSS_SR_SHADOW_REGISTERS * Registers: WCSS_SR_SHADOW_REGISTERS
@ -148,6 +151,10 @@
#define ICNSS_HW_REG_RETRY 10 #define ICNSS_HW_REG_RETRY 10
#define WCSS_HM_A_PMM_HW_VERSION_V10 0x40000000
#define WCSS_HM_A_PMM_HW_VERSION_V20 0x40010000
#define WCSS_HM_A_PMM_HW_VERSION_Q10 0x40010001
#define ICNSS_SERVICE_LOCATION_CLIENT_NAME "ICNSS-WLAN" #define ICNSS_SERVICE_LOCATION_CLIENT_NAME "ICNSS-WLAN"
#define ICNSS_WLAN_SERVICE_NAME "wlan/fw" #define ICNSS_WLAN_SERVICE_NAME "wlan/fw"
@ -156,6 +163,15 @@
ipc_log_string(icnss_ipc_log_context, _x); \ ipc_log_string(icnss_ipc_log_context, _x); \
} while (0) } while (0)
#ifdef CONFIG_ICNSS_DEBUG
#define icnss_ipc_log_long_string(_x...) do { \
if (icnss_ipc_log_long_context) \
ipc_log_string(icnss_ipc_log_long_context, _x); \
} while (0)
#else
#define icnss_ipc_log_long_string(_x...)
#endif
#define icnss_pr_err(_fmt, ...) do { \ #define icnss_pr_err(_fmt, ...) do { \
pr_err(_fmt, ##__VA_ARGS__); \ pr_err(_fmt, ##__VA_ARGS__); \
icnss_ipc_log_string("ERR: " pr_fmt(_fmt), \ icnss_ipc_log_string("ERR: " pr_fmt(_fmt), \
@ -180,7 +196,13 @@
##__VA_ARGS__); \ ##__VA_ARGS__); \
} while (0) } while (0)
#ifdef ICNSS_PANIC #define icnss_reg_dbg(_fmt, ...) do { \
pr_debug(_fmt, ##__VA_ARGS__); \
icnss_ipc_log_long_string("REG: " pr_fmt(_fmt), \
##__VA_ARGS__); \
} while (0)
#ifdef CONFIG_ICNSS_DEBUG
#define ICNSS_ASSERT(_condition) do { \ #define ICNSS_ASSERT(_condition) do { \
if (!(_condition)) { \ if (!(_condition)) { \
icnss_pr_err("ASSERT at line %d\n", \ icnss_pr_err("ASSERT at line %d\n", \
@ -215,6 +237,10 @@ module_param(quirks, ulong, 0600);
void *icnss_ipc_log_context; void *icnss_ipc_log_context;
#ifdef CONFIG_ICNSS_DEBUG
void *icnss_ipc_log_long_context;
#endif
#define ICNSS_EVENT_PENDING 2989 #define ICNSS_EVENT_PENDING 2989
enum icnss_driver_event_type { enum icnss_driver_event_type {
@ -383,7 +409,7 @@ static u32 icnss_hw_read_reg(void *base, u32 offset)
{ {
u32 rdata = readl_relaxed(base + offset); u32 rdata = readl_relaxed(base + offset);
icnss_pr_dbg(" READ: offset: 0x%06x 0x%08x\n", offset, rdata); icnss_reg_dbg(" READ: offset: 0x%06x 0x%08x\n", offset, rdata);
return rdata; return rdata;
} }
@ -395,7 +421,7 @@ static void icnss_hw_write_reg_field(void *base, u32 offset, u32 mask, u32 val)
val = (rdata & ~mask) | (val << shift); val = (rdata & ~mask) | (val << shift);
icnss_pr_dbg("WRITE: offset: 0x%06x 0x%08x -> 0x%08x\n", icnss_reg_dbg("WRITE: offset: 0x%06x 0x%08x -> 0x%08x\n",
offset, rdata, val); offset, rdata, val);
icnss_hw_write_reg(base, offset, val); icnss_hw_write_reg(base, offset, val);
@ -414,12 +440,12 @@ static int icnss_hw_poll_reg_field(void *base, u32 offset, u32 mask, u32 val,
rdata = readl_relaxed(base + offset); rdata = readl_relaxed(base + offset);
icnss_pr_dbg(" POLL: offset: 0x%06x 0x%08x == 0x%08x & 0x%08x\n", icnss_reg_dbg(" POLL: offset: 0x%06x 0x%08x == 0x%08x & 0x%08x\n",
offset, val, rdata, mask); offset, val, rdata, mask);
while ((rdata & mask) != val) { while ((rdata & mask) != val) {
if (retry != 0 && r >= retry) { if (retry != 0 && r >= retry) {
icnss_pr_err(" POLL FAILED: offset: 0x%06x 0x%08x == 0x%08x & 0x%08x\n", icnss_pr_err("POLL FAILED: offset: 0x%06x 0x%08x == 0x%08x & 0x%08x\n",
offset, val, rdata, mask); offset, val, rdata, mask);
return -EIO; return -EIO;
@ -430,7 +456,7 @@ static int icnss_hw_poll_reg_field(void *base, u32 offset, u32 mask, u32 val,
rdata = readl_relaxed(base + offset); rdata = readl_relaxed(base + offset);
if (retry) if (retry)
icnss_pr_dbg(" POLL: offset: 0x%06x 0x%08x == 0x%08x & 0x%08x\n", icnss_reg_dbg(" POLL: offset: 0x%06x 0x%08x == 0x%08x & 0x%08x\n",
offset, val, rdata, mask); offset, val, rdata, mask);
} }
@ -758,6 +784,32 @@ static void icnss_hw_top_level_reset(struct icnss_priv *priv)
ICNSS_HW_REG_RETRY); ICNSS_HW_REG_RETRY);
} }
static void icnss_hw_io_reset(struct icnss_priv *priv, bool on)
{
u32 hw_version = priv->soc_info.soc_id;
if (on && !test_bit(ICNSS_FW_READY, &priv->state))
return;
icnss_pr_dbg("HW io reset: %s, SoC: 0x%x, state: 0x%lx\n",
on ? "ON" : "OFF", priv->soc_info.soc_id, priv->state);
if (hw_version == WCSS_HM_A_PMM_HW_VERSION_V10 ||
hw_version == WCSS_HM_A_PMM_HW_VERSION_V20) {
icnss_hw_write_reg_field(priv->mpm_config_va,
MPM_WCSSAON_CONFIG_OFFSET,
MPM_WCSSAON_CONFIG_MSM_CLAMP_EN_OVRD_VAL, 0);
icnss_hw_write_reg_field(priv->mpm_config_va,
MPM_WCSSAON_CONFIG_OFFSET,
MPM_WCSSAON_CONFIG_MSM_CLAMP_EN_OVRD, on);
} else if (hw_version == WCSS_HM_A_PMM_HW_VERSION_Q10) {
icnss_hw_write_reg_field(priv->mpm_config_va,
MPM_WCSSAON_CONFIG_OFFSET,
MPM_WCSSAON_CONFIG_M2W_CLAMP_EN,
on);
}
}
int icnss_hw_reset_wlan_ss_power_down(struct icnss_priv *priv) int icnss_hw_reset_wlan_ss_power_down(struct icnss_priv *priv)
{ {
u32 rdata; u32 rdata;
@ -1123,7 +1175,7 @@ static int icnss_hw_power_on(struct icnss_priv *priv)
int ret = 0; int ret = 0;
unsigned long flags; unsigned long flags;
icnss_pr_dbg("Power on: state: 0x%lx\n", priv->state); icnss_pr_dbg("HW Power on: state: 0x%lx\n", priv->state);
spin_lock_irqsave(&priv->on_off_lock, flags); spin_lock_irqsave(&priv->on_off_lock, flags);
if (test_bit(ICNSS_POWER_ON, &priv->state)) { if (test_bit(ICNSS_POWER_ON, &priv->state)) {
@ -1143,6 +1195,8 @@ static int icnss_hw_power_on(struct icnss_priv *priv)
icnss_hw_top_level_release_reset(priv); icnss_hw_top_level_release_reset(priv);
icnss_hw_io_reset(penv, 1);
return ret; return ret;
out: out:
clear_bit(ICNSS_POWER_ON, &priv->state); clear_bit(ICNSS_POWER_ON, &priv->state);
@ -1157,7 +1211,7 @@ static int icnss_hw_power_off(struct icnss_priv *priv)
if (test_bit(HW_ALWAYS_ON, &quirks)) if (test_bit(HW_ALWAYS_ON, &quirks))
return 0; return 0;
icnss_pr_dbg("Power off: 0x%lx\n", priv->state); icnss_pr_dbg("HW Power off: 0x%lx\n", priv->state);
spin_lock_irqsave(&priv->on_off_lock, flags); spin_lock_irqsave(&priv->on_off_lock, flags);
if (!test_bit(ICNSS_POWER_ON, &priv->state)) { if (!test_bit(ICNSS_POWER_ON, &priv->state)) {
@ -1167,6 +1221,8 @@ static int icnss_hw_power_off(struct icnss_priv *priv)
clear_bit(ICNSS_POWER_ON, &priv->state); clear_bit(ICNSS_POWER_ON, &priv->state);
spin_unlock_irqrestore(&priv->on_off_lock, flags); spin_unlock_irqrestore(&priv->on_off_lock, flags);
icnss_hw_io_reset(penv, 0);
icnss_hw_reset(priv); icnss_hw_reset(priv);
icnss_clk_deinit(priv); icnss_clk_deinit(priv);
@ -1191,6 +1247,8 @@ int icnss_power_on(struct device *dev)
return -EINVAL; return -EINVAL;
} }
icnss_pr_dbg("Power On: 0x%lx\n", priv->state);
return icnss_hw_power_on(priv); return icnss_hw_power_on(priv);
} }
EXPORT_SYMBOL(icnss_power_on); EXPORT_SYMBOL(icnss_power_on);
@ -1205,6 +1263,8 @@ int icnss_power_off(struct device *dev)
return -EINVAL; return -EINVAL;
} }
icnss_pr_dbg("Power Off: 0x%lx\n", priv->state);
return icnss_hw_power_off(priv); return icnss_hw_power_off(priv);
} }
EXPORT_SYMBOL(icnss_power_off); EXPORT_SYMBOL(icnss_power_off);
@ -1235,11 +1295,11 @@ int icnss_map_msa_permissions(struct icnss_priv *priv, u32 index)
ret = hyp_assign_phys(addr, size, source_vmlist, source_nelems, ret = hyp_assign_phys(addr, size, source_vmlist, source_nelems,
dest_vmids, dest_perms, dest_nelems); dest_vmids, dest_perms, dest_nelems);
if (ret) { if (ret) {
icnss_pr_err("region %u hyp_assign_phys failed IPA=%pa size=%u err=%d\n", icnss_pr_err("Region %u hyp_assign_phys failed IPA=%pa size=%u err=%d\n",
index, &addr, size, ret); index, &addr, size, ret);
goto out; goto out;
} }
icnss_pr_dbg("hypervisor map for region %u: source=%x, dest_nelems=%d, dest[0]=%x, dest[1]=%x, dest[2]=%x\n", icnss_pr_dbg("Hypervisor map for region %u: source=%x, dest_nelems=%d, dest[0]=%x, dest[1]=%x, dest[2]=%x\n",
index, source_vmlist[0], dest_nelems, index, source_vmlist[0], dest_nelems,
dest_vmids[0], dest_vmids[1], dest_vmids[2]); dest_vmids[0], dest_vmids[1], dest_vmids[2]);
out: out:
@ -1271,7 +1331,7 @@ int icnss_unmap_msa_permissions(struct icnss_priv *priv, u32 index)
ret = hyp_assign_phys(addr, size, source_vmlist, source_nelems, ret = hyp_assign_phys(addr, size, source_vmlist, source_nelems,
dest_vmids, dest_perms, dest_nelems); dest_vmids, dest_perms, dest_nelems);
if (ret) { if (ret) {
icnss_pr_err("region %u hyp_assign_phys failed IPA=%pa size=%u err=%d\n", icnss_pr_err("Region %u hyp_assign_phys failed IPA=%pa size=%u err=%d\n",
index, &addr, size, ret); index, &addr, size, ret);
goto out; goto out;
} }
@ -1310,16 +1370,14 @@ static void icnss_remove_msa_permissions(struct icnss_priv *priv)
static int wlfw_msa_mem_info_send_sync_msg(void) static int wlfw_msa_mem_info_send_sync_msg(void)
{ {
int ret = 0; int ret;
int i; int i;
struct wlfw_msa_info_req_msg_v01 req; struct wlfw_msa_info_req_msg_v01 req;
struct wlfw_msa_info_resp_msg_v01 resp; struct wlfw_msa_info_resp_msg_v01 resp;
struct msg_desc req_desc, resp_desc; struct msg_desc req_desc, resp_desc;
if (!penv || !penv->wlfw_clnt) { if (!penv || !penv->wlfw_clnt)
ret = -ENODEV; return -ENODEV;
goto out;
}
icnss_pr_dbg("Sending MSA mem info, state: 0x%lx\n", penv->state); icnss_pr_dbg("Sending MSA mem info, state: 0x%lx\n", penv->state);
@ -1342,15 +1400,14 @@ static int wlfw_msa_mem_info_send_sync_msg(void)
ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req), ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp), WLFW_TIMEOUT_MS); &resp_desc, &resp, sizeof(resp), WLFW_TIMEOUT_MS);
if (ret < 0) { if (ret < 0) {
icnss_pr_err("Send req failed %d\n", ret); icnss_pr_err("Send MSA Mem info req failed %d\n", ret);
goto out; goto out;
} }
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI request failed %d %d\n", icnss_pr_err("QMI MSA Mem info request failed %d %d\n",
resp.resp.result, resp.resp.error); resp.resp.result, resp.resp.error);
ret = resp.resp.result; ret = resp.resp.result;
penv->stats.msa_info_err++;
goto out; goto out;
} }
@ -1361,7 +1418,6 @@ static int wlfw_msa_mem_info_send_sync_msg(void)
icnss_pr_err("Invalid memory region length received: %d\n", icnss_pr_err("Invalid memory region length received: %d\n",
resp.mem_region_info_len); resp.mem_region_info_len);
ret = -EINVAL; ret = -EINVAL;
penv->stats.msa_info_err++;
goto out; goto out;
} }
@ -1379,7 +1435,11 @@ static int wlfw_msa_mem_info_send_sync_msg(void)
penv->icnss_mem_region[i].secure_flag); penv->icnss_mem_region[i].secure_flag);
} }
return 0;
out: out:
penv->stats.msa_info_err++;
ICNSS_ASSERT(false);
return ret; return ret;
} }
@ -1390,10 +1450,8 @@ static int wlfw_msa_ready_send_sync_msg(void)
struct wlfw_msa_ready_resp_msg_v01 resp; struct wlfw_msa_ready_resp_msg_v01 resp;
struct msg_desc req_desc, resp_desc; struct msg_desc req_desc, resp_desc;
if (!penv || !penv->wlfw_clnt) { if (!penv || !penv->wlfw_clnt)
ret = -ENODEV; return -ENODEV;
goto out;
}
icnss_pr_dbg("Sending MSA ready request message, state: 0x%lx\n", icnss_pr_dbg("Sending MSA ready request message, state: 0x%lx\n",
penv->state); penv->state);
@ -1413,20 +1471,23 @@ static int wlfw_msa_ready_send_sync_msg(void)
ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req), ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp), WLFW_TIMEOUT_MS); &resp_desc, &resp, sizeof(resp), WLFW_TIMEOUT_MS);
if (ret < 0) { if (ret < 0) {
penv->stats.msa_ready_err++; icnss_pr_err("Send MSA ready req failed %d\n", ret);
icnss_pr_err("Send req failed %d\n", ret);
goto out; goto out;
} }
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI request failed %d %d\n", icnss_pr_err("QMI MSA ready request failed %d %d\n",
resp.resp.result, resp.resp.error); resp.resp.result, resp.resp.error);
penv->stats.msa_ready_err++;
ret = resp.resp.result; ret = resp.resp.result;
goto out; goto out;
} }
penv->stats.msa_ready_resp++; penv->stats.msa_ready_resp++;
return 0;
out: out:
penv->stats.msa_ready_err++;
ICNSS_ASSERT(false);
return ret; return ret;
} }
@ -1437,10 +1498,8 @@ static int wlfw_ind_register_send_sync_msg(void)
struct wlfw_ind_register_resp_msg_v01 resp; struct wlfw_ind_register_resp_msg_v01 resp;
struct msg_desc req_desc, resp_desc; struct msg_desc req_desc, resp_desc;
if (!penv || !penv->wlfw_clnt) { if (!penv || !penv->wlfw_clnt)
ret = -ENODEV; return -ENODEV;
goto out;
}
icnss_pr_dbg("Sending indication register message, state: 0x%lx\n", icnss_pr_dbg("Sending indication register message, state: 0x%lx\n",
penv->state); penv->state);
@ -1468,21 +1527,24 @@ static int wlfw_ind_register_send_sync_msg(void)
ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req), ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp), &resp_desc, &resp, sizeof(resp),
WLFW_TIMEOUT_MS); WLFW_TIMEOUT_MS);
penv->stats.ind_register_resp++;
if (ret < 0) { if (ret < 0) {
icnss_pr_err("Send req failed %d\n", ret); icnss_pr_err("Send indication register req failed %d\n", ret);
penv->stats.ind_register_err++;
goto out; goto out;
} }
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI request failed %d %d\n", icnss_pr_err("QMI indication register request failed %d %d\n",
resp.resp.result, resp.resp.error); resp.resp.result, resp.resp.error);
ret = resp.resp.result; ret = resp.resp.result;
penv->stats.ind_register_err++;
goto out; goto out;
} }
penv->stats.ind_register_resp++;
return 0;
out: out:
penv->stats.ind_register_err++;
ICNSS_ASSERT(false);
return ret; return ret;
} }
@ -1493,10 +1555,8 @@ static int wlfw_cap_send_sync_msg(void)
struct wlfw_cap_resp_msg_v01 resp; struct wlfw_cap_resp_msg_v01 resp;
struct msg_desc req_desc, resp_desc; struct msg_desc req_desc, resp_desc;
if (!penv || !penv->wlfw_clnt) { if (!penv || !penv->wlfw_clnt)
ret = -ENODEV; return -ENODEV;
goto out;
}
icnss_pr_dbg("Sending capability message, state: 0x%lx\n", penv->state); icnss_pr_dbg("Sending capability message, state: 0x%lx\n", penv->state);
@ -1515,16 +1575,14 @@ static int wlfw_cap_send_sync_msg(void)
&resp_desc, &resp, sizeof(resp), &resp_desc, &resp, sizeof(resp),
WLFW_TIMEOUT_MS); WLFW_TIMEOUT_MS);
if (ret < 0) { if (ret < 0) {
icnss_pr_err("Send req failed %d\n", ret); icnss_pr_err("Send capability req failed %d\n", ret);
penv->stats.cap_err++;
goto out; goto out;
} }
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI request failed %d %d\n", icnss_pr_err("QMI capability request failed %d %d\n",
resp.resp.result, resp.resp.error); resp.resp.result, resp.resp.error);
ret = resp.resp.result; ret = resp.resp.result;
penv->stats.cap_err++;
goto out; goto out;
} }
@ -1546,7 +1604,12 @@ static int wlfw_cap_send_sync_msg(void)
penv->board_info.board_id, penv->soc_info.soc_id, penv->board_info.board_id, penv->soc_info.soc_id,
penv->fw_version_info.fw_version, penv->fw_version_info.fw_version,
penv->fw_version_info.fw_build_timestamp); penv->fw_version_info.fw_build_timestamp);
return 0;
out: out:
penv->stats.cap_err++;
ICNSS_ASSERT(false);
return ret; return ret;
} }
@ -1557,10 +1620,8 @@ static int wlfw_wlan_mode_send_sync_msg(enum wlfw_driver_mode_enum_v01 mode)
struct wlfw_wlan_mode_resp_msg_v01 resp; struct wlfw_wlan_mode_resp_msg_v01 resp;
struct msg_desc req_desc, resp_desc; struct msg_desc req_desc, resp_desc;
if (!penv || !penv->wlfw_clnt) { if (!penv || !penv->wlfw_clnt)
ret = -ENODEV; return -ENODEV;
goto out;
}
/* During recovery do not send mode request for WLAN OFF as /* During recovery do not send mode request for WLAN OFF as
* FW not able to process it. * FW not able to process it.
@ -1592,20 +1653,24 @@ static int wlfw_wlan_mode_send_sync_msg(enum wlfw_driver_mode_enum_v01 mode)
&resp_desc, &resp, sizeof(resp), &resp_desc, &resp, sizeof(resp),
WLFW_TIMEOUT_MS); WLFW_TIMEOUT_MS);
if (ret < 0) { if (ret < 0) {
icnss_pr_err("Send req failed %d\n", ret); icnss_pr_err("Send mode req failed, mode: %d ret: %d\n",
penv->stats.mode_req_err++; mode, ret);
goto out; goto out;
} }
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI request failed %d %d\n", icnss_pr_err("QMI mode request failed mode: %d, %d %d\n",
resp.resp.result, resp.resp.error); mode, resp.resp.result, resp.resp.error);
ret = resp.resp.result; ret = resp.resp.result;
penv->stats.mode_req_err++;
goto out; goto out;
} }
penv->stats.mode_resp++; penv->stats.mode_resp++;
return 0;
out: out:
penv->stats.mode_req_err++;
ICNSS_ASSERT(false);
return ret; return ret;
} }
@ -1616,10 +1681,8 @@ static int wlfw_wlan_cfg_send_sync_msg(struct wlfw_wlan_cfg_req_msg_v01 *data)
struct wlfw_wlan_cfg_resp_msg_v01 resp; struct wlfw_wlan_cfg_resp_msg_v01 resp;
struct msg_desc req_desc, resp_desc; struct msg_desc req_desc, resp_desc;
if (!penv || !penv->wlfw_clnt) { if (!penv || !penv->wlfw_clnt)
return -ENODEV; return -ENODEV;
goto out;
}
icnss_pr_dbg("Sending config request, state: 0x%lx\n", penv->state); icnss_pr_dbg("Sending config request, state: 0x%lx\n", penv->state);
@ -1641,20 +1704,23 @@ static int wlfw_wlan_cfg_send_sync_msg(struct wlfw_wlan_cfg_req_msg_v01 *data)
&resp_desc, &resp, sizeof(resp), &resp_desc, &resp, sizeof(resp),
WLFW_TIMEOUT_MS); WLFW_TIMEOUT_MS);
if (ret < 0) { if (ret < 0) {
icnss_pr_err("Send req failed %d\n", ret); icnss_pr_err("Send config req failed %d\n", ret);
penv->stats.cfg_req_err++;
goto out; goto out;
} }
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI request failed %d %d\n", icnss_pr_err("QMI config request failed %d %d\n",
resp.resp.result, resp.resp.error); resp.resp.result, resp.resp.error);
ret = resp.resp.result; ret = resp.resp.result;
penv->stats.cfg_req_err++;
goto out; goto out;
} }
penv->stats.cfg_resp++; penv->stats.cfg_resp++;
return 0;
out: out:
penv->stats.cfg_req_err++;
ICNSS_ASSERT(false);
return ret; return ret;
} }
@ -1665,10 +1731,8 @@ static int wlfw_ini_send_sync_msg(bool enable_fw_log)
struct wlfw_ini_resp_msg_v01 resp; struct wlfw_ini_resp_msg_v01 resp;
struct msg_desc req_desc, resp_desc; struct msg_desc req_desc, resp_desc;
if (!penv || !penv->wlfw_clnt) { if (!penv || !penv->wlfw_clnt)
ret = -ENODEV; return -ENODEV;
goto out;
}
icnss_pr_dbg("Sending ini sync request, state: 0x%lx, fw_log: %d\n", icnss_pr_dbg("Sending ini sync request, state: 0x%lx, fw_log: %d\n",
penv->state, enable_fw_log); penv->state, enable_fw_log);
@ -1692,20 +1756,24 @@ static int wlfw_ini_send_sync_msg(bool enable_fw_log)
ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req), ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp), WLFW_TIMEOUT_MS); &resp_desc, &resp, sizeof(resp), WLFW_TIMEOUT_MS);
if (ret < 0) { if (ret < 0) {
icnss_pr_err("send req failed %d\n", ret); icnss_pr_err("Send INI req failed fw_log: %d, ret: %d\n",
penv->stats.ini_req_err++; enable_fw_log, ret);
goto out; goto out;
} }
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI request failed %d %d\n", icnss_pr_err("QMI INI request failed fw_log: %d, %d %d\n",
resp.resp.result, resp.resp.error); enable_fw_log, resp.resp.result, resp.resp.error);
ret = resp.resp.result; ret = resp.resp.result;
penv->stats.ini_req_err++;
goto out; goto out;
} }
penv->stats.ini_resp++; penv->stats.ini_resp++;
return 0;
out: out:
penv->stats.ini_req_err++;
ICNSS_ASSERT(false);
return ret; return ret;
} }
@ -1789,12 +1857,11 @@ static int icnss_driver_event_server_arrive(void *data)
goto out; goto out;
} }
ret = qmi_connect_to_service(penv->wlfw_clnt, ret = qmi_connect_to_service(penv->wlfw_clnt, WLFW_SERVICE_ID_V01,
WLFW_SERVICE_ID_V01,
WLFW_SERVICE_VERS_V01, WLFW_SERVICE_VERS_V01,
WLFW_SERVICE_INS_ID_V01); WLFW_SERVICE_INS_ID_V01);
if (ret < 0) { if (ret < 0) {
icnss_pr_err("Server not found : %d\n", ret); icnss_pr_err("QMI WLAN Service not found : %d\n", ret);
goto fail; goto fail;
} }
@ -1815,10 +1882,8 @@ static int icnss_driver_event_server_arrive(void *data)
goto fail; goto fail;
ret = wlfw_ind_register_send_sync_msg(); ret = wlfw_ind_register_send_sync_msg();
if (ret < 0) { if (ret < 0)
icnss_pr_err("Failed to send indication message: %d\n", ret);
goto err_power_on; goto err_power_on;
}
if (!penv->msa_va) { if (!penv->msa_va) {
icnss_pr_err("Invalid MSA address\n"); icnss_pr_err("Invalid MSA address\n");
@ -1827,27 +1892,21 @@ static int icnss_driver_event_server_arrive(void *data)
} }
ret = wlfw_msa_mem_info_send_sync_msg(); ret = wlfw_msa_mem_info_send_sync_msg();
if (ret < 0) { if (ret < 0)
icnss_pr_err("Failed to send MSA info: %d\n", ret);
goto err_power_on; goto err_power_on;
}
ret = icnss_setup_msa_permissions(penv); ret = icnss_setup_msa_permissions(penv);
if (ret < 0) { if (ret < 0)
icnss_pr_err("Failed to setup msa permissions: %d\n",
ret);
goto err_power_on; goto err_power_on;
}
ret = wlfw_msa_ready_send_sync_msg(); ret = wlfw_msa_ready_send_sync_msg();
if (ret < 0) { if (ret < 0)
icnss_pr_err("Failed to send MSA ready : %d\n", ret);
goto err_setup_msa; goto err_setup_msa;
}
ret = wlfw_cap_send_sync_msg(); ret = wlfw_cap_send_sync_msg();
if (ret < 0) { if (ret < 0)
icnss_pr_err("Failed to get capability: %d\n", ret);
goto err_setup_msa; goto err_setup_msa;
}
return ret; return ret;
err_setup_msa: err_setup_msa:
@ -2680,14 +2739,10 @@ int icnss_wlan_enable(struct icnss_wlan_enable_cfg *config,
sizeof(struct wlfw_shadow_reg_cfg_s_v01) * req.shadow_reg_len); sizeof(struct wlfw_shadow_reg_cfg_s_v01) * req.shadow_reg_len);
ret = wlfw_wlan_cfg_send_sync_msg(&req); ret = wlfw_wlan_cfg_send_sync_msg(&req);
if (ret) { if (ret)
icnss_pr_err("Failed to send cfg, ret = %d\n", ret);
goto out; goto out;
}
skip: skip:
ret = wlfw_wlan_mode_send_sync_msg(mode); ret = wlfw_wlan_mode_send_sync_msg(mode);
if (ret)
icnss_pr_err("Failed to send mode, ret = %d\n", ret);
out: out:
if (test_bit(SKIP_QMI, &quirks)) if (test_bit(SKIP_QMI, &quirks))
ret = 0; ret = 0;
@ -3416,6 +3471,8 @@ static int icnss_probe(struct platform_device *pdev)
return -EEXIST; return -EEXIST;
} }
icnss_pr_dbg("Platform driver probe\n");
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
@ -3515,9 +3572,8 @@ static int icnss_probe(struct platform_device *pdev)
} else { } else {
priv->smmu_iova_start = res->start; priv->smmu_iova_start = res->start;
priv->smmu_iova_len = resource_size(res); priv->smmu_iova_len = resource_size(res);
icnss_pr_dbg("smmu_iova_start: %pa, smmu_iova_len: %zu\n", icnss_pr_dbg("SMMU IOVA start: %pa, len: %zu\n",
&priv->smmu_iova_start, &priv->smmu_iova_start, priv->smmu_iova_len);
priv->smmu_iova_len);
res = platform_get_resource_byname(pdev, res = platform_get_resource_byname(pdev,
IORESOURCE_MEM, IORESOURCE_MEM,
@ -3527,7 +3583,7 @@ static int icnss_probe(struct platform_device *pdev)
} else { } else {
priv->smmu_iova_ipa_start = res->start; priv->smmu_iova_ipa_start = res->start;
priv->smmu_iova_ipa_len = resource_size(res); priv->smmu_iova_ipa_len = resource_size(res);
icnss_pr_dbg("smmu_iova_ipa_start: %pa, smmu_iova_ipa_len: %zu\n", icnss_pr_dbg("SMMU IOVA IPA start: %pa, len: %zu\n",
&priv->smmu_iova_ipa_start, &priv->smmu_iova_ipa_start,
priv->smmu_iova_ipa_len); priv->smmu_iova_ipa_len);
} }
@ -3688,6 +3744,26 @@ static struct platform_driver icnss_driver = {
}, },
}; };
#ifdef CONFIG_ICNSS_DEBUG
static void __init icnss_ipc_log_long_context_init(void)
{
icnss_ipc_log_long_context = ipc_log_context_create(NUM_REG_LOG_PAGES,
"icnss_long", 0);
if (!icnss_ipc_log_long_context)
icnss_pr_err("Unable to create register log context\n");
}
static void __exit icnss_ipc_log_long_context_destroy(void)
{
ipc_log_context_destroy(icnss_ipc_log_long_context);
icnss_ipc_log_long_context = NULL;
}
#else
static void __init icnss_ipc_log_long_context_init(void) { }
static void __exit icnss_ipc_log_long_context_destroy(void) { }
#endif
static int __init icnss_initialize(void) static int __init icnss_initialize(void)
{ {
icnss_ipc_log_context = ipc_log_context_create(NUM_LOG_PAGES, icnss_ipc_log_context = ipc_log_context_create(NUM_LOG_PAGES,
@ -3695,6 +3771,8 @@ static int __init icnss_initialize(void)
if (!icnss_ipc_log_context) if (!icnss_ipc_log_context)
icnss_pr_err("Unable to create log context\n"); icnss_pr_err("Unable to create log context\n");
icnss_ipc_log_long_context_init();
return platform_driver_register(&icnss_driver); return platform_driver_register(&icnss_driver);
} }
@ -3703,6 +3781,8 @@ static void __exit icnss_exit(void)
platform_driver_unregister(&icnss_driver); platform_driver_unregister(&icnss_driver);
ipc_log_context_destroy(icnss_ipc_log_context); ipc_log_context_destroy(icnss_ipc_log_context);
icnss_ipc_log_context = NULL; icnss_ipc_log_context = NULL;
icnss_ipc_log_long_context_destroy();
} }