summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHsiu-Chang Chen <hsiuchangchen@google.com>2022-09-06 13:32:49 +0800
committerHsiu-Chang Chen <hsiuchangchen@google.com>2022-09-06 13:32:49 +0800
commit846e21e9f4ff37895a01274539511fdc0cd51ed2 (patch)
tree0680cfbfdc532a4461c9a6bd847a28d818983758
parent4194a4d73a9ac567654a7515082b351d2bc6447a (diff)
downloadcnss2-846e21e9f4ff37895a01274539511fdc0cd51ed2.tar.gz
wcn6740: Update cnss/mhi/qmi/qrtr drivers
Migrate wlan codes to PostCS release Bug: 245009352 Test: Regression Test Change-Id: Icb90ab318ced3f028a19d6e329d509a23c3774a6
-rw-r--r--cnss2/main.c9
-rw-r--r--cnss2/main.h1
-rw-r--r--cnss2/pci.c74
-rw-r--r--cnss2/qmi.c7
-rw-r--r--cnss2/reg.h5
-rw-r--r--mhi/core/internal.h1
-rw-r--r--mhi/core/misc.c12
-rw-r--r--qrtr/af_qrtr.c24
-rw-r--r--qrtr/mhi.c2
-rw-r--r--qrtr/qrtr.h14
10 files changed, 129 insertions, 20 deletions
diff --git a/cnss2/main.c b/cnss2/main.c
index 5f4a5ab..b3656de 100644
--- a/cnss2/main.c
+++ b/cnss2/main.c
@@ -676,6 +676,11 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
if (!plat_priv)
return -ENODEV;
+ if (test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state)) {
+ cnss_pr_err("Reboot is in progress, ignore FW ready\n");
+ return -EINVAL;
+ }
+
cnss_pr_dbg("Processing FW Init Done..\n");
del_timer(&plat_priv->fw_boot_timer);
set_bit(CNSS_FW_READY, &plat_priv->driver_state);
@@ -3445,7 +3450,9 @@ static int cnss_misc_init(struct cnss_plat_data *plat_priv)
cnss_pr_err("QMI IPC connection call back register failed, err = %d\n",
ret);
- plat_priv->sram_dump = kcalloc(SRAM_DUMP_SIZE, 1, GFP_KERNEL);
+ if (plat_priv->device_id == QCA6490_DEVICE_ID &&
+ cnss_get_host_build_type() == QMI_HOST_BUILD_TYPE_PRIMARY_V01)
+ plat_priv->sram_dump = kcalloc(SRAM_DUMP_SIZE, 1, GFP_KERNEL);
return 0;
}
diff --git a/cnss2/main.h b/cnss2/main.h
index e965f02..0125237 100644
--- a/cnss2/main.h
+++ b/cnss2/main.h
@@ -554,6 +554,7 @@ struct cnss_plat_data {
/* bitmap to detect FEM combination */
u8 hwid_bitmap;
enum cnss_driver_mode driver_mode;
+ u32 num_shadow_regs_v3;
};
#if IS_ENABLED(CONFIG_ARCH_QCOM) && !IS_ENABLED(CONFIG_WCN_GOOGLE)
diff --git a/cnss2/pci.c b/cnss2/pci.c
index 66a19fc..98e6760 100644
--- a/cnss2/pci.c
+++ b/cnss2/pci.c
@@ -1893,8 +1893,16 @@ static int cnss_pci_get_device_timestamp(struct cnss_pci_data *pci_priv,
return -EINVAL;
}
- cnss_pci_reg_read(pci_priv, WLAON_GLOBAL_COUNTER_CTRL3, &low);
- cnss_pci_reg_read(pci_priv, WLAON_GLOBAL_COUNTER_CTRL4, &high);
+ switch (pci_priv->device_id) {
+ case KIWI_DEVICE_ID:
+ cnss_pci_reg_read(pci_priv, PCIE_MHI_TIME_LOW, &low);
+ cnss_pci_reg_read(pci_priv, PCIE_MHI_TIME_HIGH, &high);
+ break;
+ default:
+ cnss_pci_reg_read(pci_priv, WLAON_GLOBAL_COUNTER_CTRL3, &low);
+ cnss_pci_reg_read(pci_priv, WLAON_GLOBAL_COUNTER_CTRL4, &high);
+ break;
+ }
device_ticks = (u64)high << 32 | low;
do_div(device_ticks, plat_priv->device_freq_hz / 100000);
@@ -1905,16 +1913,60 @@ static int cnss_pci_get_device_timestamp(struct cnss_pci_data *pci_priv,
static void cnss_pci_enable_time_sync_counter(struct cnss_pci_data *pci_priv)
{
+ switch (pci_priv->device_id) {
+ case KIWI_DEVICE_ID:
+ return;
+ default:
+ break;
+ }
+
cnss_pci_reg_write(pci_priv, WLAON_GLOBAL_COUNTER_CTRL5,
TIME_SYNC_ENABLE);
}
static void cnss_pci_clear_time_sync_counter(struct cnss_pci_data *pci_priv)
{
+ switch (pci_priv->device_id) {
+ case KIWI_DEVICE_ID:
+ return;
+ default:
+ break;
+ }
+
cnss_pci_reg_write(pci_priv, WLAON_GLOBAL_COUNTER_CTRL5,
TIME_SYNC_CLEAR);
}
+static void cnss_pci_time_sync_reg_update(struct cnss_pci_data *pci_priv,
+ u32 low, u32 high)
+{
+ u32 time_reg_low;
+ u32 time_reg_high;
+
+ switch (pci_priv->device_id) {
+ case KIWI_DEVICE_ID:
+ /* Use the next two shadow registers after host's usage */
+ time_reg_low = PCIE_SHADOW_REG_VALUE_0 +
+ (pci_priv->plat_priv->num_shadow_regs_v3 *
+ SHADOW_REG_LEN_BYTES);
+ time_reg_high = time_reg_low + SHADOW_REG_LEN_BYTES;
+ break;
+ default:
+ time_reg_low = PCIE_SHADOW_REG_VALUE_34;
+ time_reg_high = PCIE_SHADOW_REG_VALUE_35;
+ break;
+ }
+
+ cnss_pci_reg_write(pci_priv, time_reg_low, low);
+ cnss_pci_reg_write(pci_priv, time_reg_high, high);
+
+ cnss_pci_reg_read(pci_priv, time_reg_low, &low);
+ cnss_pci_reg_read(pci_priv, time_reg_high, &high);
+
+ cnss_pr_dbg("Updated time sync regs [0x%x] = 0x%x, [0x%x] = 0x%x\n",
+ time_reg_low, low, time_reg_high, high);
+}
+
static int cnss_pci_update_timestamp(struct cnss_pci_data *pci_priv)
{
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
@@ -1956,15 +2008,7 @@ static int cnss_pci_update_timestamp(struct cnss_pci_data *pci_priv)
low = offset & 0xFFFFFFFF;
high = offset >> 32;
- cnss_pci_reg_write(pci_priv, PCIE_SHADOW_REG_VALUE_34, low);
- cnss_pci_reg_write(pci_priv, PCIE_SHADOW_REG_VALUE_35, high);
-
- cnss_pci_reg_read(pci_priv, PCIE_SHADOW_REG_VALUE_34, &low);
- cnss_pci_reg_read(pci_priv, PCIE_SHADOW_REG_VALUE_35, &high);
-
- cnss_pr_dbg("Updated time sync regs [0x%x] = 0x%x, [0x%x] = 0x%x\n",
- PCIE_SHADOW_REG_VALUE_34, low,
- PCIE_SHADOW_REG_VALUE_35, high);
+ cnss_pci_time_sync_reg_update(pci_priv, low, high);
force_wake_put:
cnss_pci_force_wake_put(pci_priv);
@@ -2036,6 +2080,7 @@ static void cnss_pci_stop_time_sync_update(struct cnss_pci_data *pci_priv)
switch (pci_priv->device_id) {
case QCA6390_DEVICE_ID:
case QCA6490_DEVICE_ID:
+ case KIWI_DEVICE_ID:
break;
default:
return;
@@ -2072,6 +2117,10 @@ int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv)
return -ENODEV;
plat_priv = pci_priv->plat_priv;
+ if (test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state)) {
+ cnss_pr_err("Reboot is in progress, skip driver probe\n");
+ return -EINVAL;
+ }
if (test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
@@ -4836,7 +4885,6 @@ void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic)
cnss_pci_soc_scratch_reg_dump(pci_priv);
cnss_pci_dump_misc_reg(pci_priv);
cnss_pci_dump_shadow_reg(pci_priv);
- cnss_pci_dump_qdss_reg(pci_priv);
ret = mhi_download_rddm_image(pci_priv->mhi_ctrl, in_panic);
if (ret) {
@@ -4852,6 +4900,8 @@ void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic)
rddm_image = pci_priv->mhi_ctrl->rddm_image;
dump_data->nentries = 0;
+ if (plat_priv->qdss_mem_seg_len)
+ cnss_pci_dump_qdss_reg(pci_priv);
cnss_mhi_dump_sfr(pci_priv);
if (!dump_seg) {
diff --git a/cnss2/qmi.c b/cnss2/qmi.c
index 311b976..1572c94 100644
--- a/cnss2/qmi.c
+++ b/cnss2/qmi.c
@@ -1549,8 +1549,6 @@ int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01)
* req->shadow_reg_v2_len);
} else {
- cnss_pr_dbg("Shadow reg v3 len: %d\n",
- config->num_shadow_reg_v3_cfg);
req->shadow_reg_v3_valid = 1;
if (config->num_shadow_reg_v3_cfg >
MAX_NUM_SHADOW_REG_V3)
@@ -1558,6 +1556,11 @@ int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
else
req->shadow_reg_v3_len = config->num_shadow_reg_v3_cfg;
+ plat_priv->num_shadow_regs_v3 = req->shadow_reg_v3_len;
+
+ cnss_pr_dbg("Shadow reg v3 len: %d\n",
+ plat_priv->num_shadow_regs_v3);
+
memcpy(req->shadow_reg_v3, config->shadow_reg_v3_cfg,
sizeof(struct wlfw_shadow_reg_v3_cfg_s_v01)
* req->shadow_reg_v3_len);
diff --git a/cnss2/reg.h b/cnss2/reg.h
index 9a3729e..7280add 100644
--- a/cnss2/reg.h
+++ b/cnss2/reg.h
@@ -52,13 +52,18 @@
#define CE_REG_INTERVAL 0x2000
#define SHADOW_REG_COUNT 36
+#define SHADOW_REG_LEN_BYTES 4
#define PCIE_SHADOW_REG_VALUE_0 0x8FC
+#define PCIE_SHADOW_REG_VALUE_1 0x900
#define PCIE_SHADOW_REG_VALUE_34 0x984
#define PCIE_SHADOW_REG_VALUE_35 0x988
#define SHADOW_REG_INTER_COUNT 43
#define PCIE_SHADOW_REG_INTER_0 0x1E05000
+#define PCIE_MHI_TIME_LOW 0xA28
+#define PCIE_MHI_TIME_HIGH 0xA2C
+
#define QDSS_APB_DEC_CSR_BASE 0x1C01000
#define QDSS_APB_DEC_CSR_ETRIRQCTRL_OFFSET 0x6C
diff --git a/mhi/core/internal.h b/mhi/core/internal.h
index b53c8e3..aa5a269 100644
--- a/mhi/core/internal.h
+++ b/mhi/core/internal.h
@@ -677,6 +677,7 @@ void mhi_ring_cmd_db(struct mhi_controller *mhi_cntrl, struct mhi_cmd *mhi_cmd);
void mhi_ring_chan_db(struct mhi_controller *mhi_cntrl,
struct mhi_chan *mhi_chan);
void *mhi_to_virtual(struct mhi_ring *ring, dma_addr_t addr);
+dma_addr_t mhi_to_physical(struct mhi_ring *ring, void *addr);
/* Initialization methods */
int mhi_init_mmio(struct mhi_controller *mhi_cntrl);
diff --git a/mhi/core/misc.c b/mhi/core/misc.c
index fffef3e..a04be2d 100644
--- a/mhi/core/misc.c
+++ b/mhi/core/misc.c
@@ -1263,6 +1263,18 @@ int mhi_process_misc_bw_ev_ring(struct mhi_controller *mhi_cntrl,
spin_lock_bh(&mhi_event->lock);
dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp);
+ /**
+ * Check the ev ring local pointer is same as ctxt pointer
+ * if both are same do not process ev ring.
+ */
+ if (ev_ring->rp == dev_rp) {
+ MHI_VERB("Ignore received BW event:0x%llx ev_ring RP:0x%llx\n",
+ dev_rp->ptr,
+ (u64)mhi_to_physical(ev_ring, ev_ring->rp));
+ spin_unlock_bh(&mhi_event->lock);
+ return 0;
+ }
+
/* if rp points to base, we need to wrap it around */
if (dev_rp == ev_ring->base)
dev_rp = ev_ring->base + ev_ring->len;
diff --git a/qrtr/af_qrtr.c b/qrtr/af_qrtr.c
index a64af13..0ea15be 100644
--- a/qrtr/af_qrtr.c
+++ b/qrtr/af_qrtr.c
@@ -194,6 +194,8 @@ struct qrtr_node {
struct wakeup_source *ws;
void *ilc;
+
+ struct xarray no_wake_svc; /* services that will not wake up APPS */
};
struct qrtr_tx_flow_waiter {
@@ -874,6 +876,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
unsigned int ver;
size_t hdrlen;
int errcode;
+ int svc_id;
if (len == 0 || len & 3)
return -EINVAL;
@@ -961,6 +964,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
/* All control packets and non-local destined data packets should be
* queued to the worker for forwarding handling.
*/
+ svc_id = qrtr_get_service_id(cb->src_node, cb->src_port);
if (cb->type != QRTR_TYPE_DATA || cb->dst_node != qrtr_local_nid) {
skb_queue_tail(&node->rx_queue, skb);
kthread_queue_work(&node->kworker, &node->read_data);
@@ -977,8 +981,8 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
goto err;
}
- /* Force wakeup for all packets except for sensors */
- if (node->nid != 9)
+ /* Force wakeup based on services */
+ if (!xa_load(&node->no_wake_svc, svc_id))
pm_wakeup_ws_event(node->ws, qrtr_wakeup_ms, true);
qrtr_port_put(ipc);
@@ -1184,13 +1188,16 @@ static void qrtr_hello_work(struct kthread_work *work)
* @ep: endpoint to register
* @nid: desired node id; may be QRTR_EP_NID_AUTO for auto-assignment
* @rt: flag to notify real time low latency endpoint
+ * @no_wake: array of services to not wake up
* Return: 0 on success; negative error code on failure
*
* The specified endpoint must have the xmit function pointer set on call.
*/
int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id,
- bool rt)
+ bool rt, struct qrtr_array *no_wake)
{
+ int rc, i;
+ size_t size;
struct qrtr_node *node;
struct sched_param param = {.sched_priority = 1};
@@ -1220,6 +1227,17 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id,
if (rt)
sched_setscheduler(node->task, SCHED_FIFO, &param);
+ xa_init(&node->no_wake_svc);
+ size = no_wake ? no_wake->size : 0;
+ for (i = 0; i < size; i++) {
+ rc = xa_insert(&node->no_wake_svc, no_wake->arr[i], node,
+ GFP_KERNEL);
+ if (rc) {
+ kfree(node);
+ return rc;
+ }
+ }
+
mutex_init(&node->qrtr_tx_lock);
INIT_RADIX_TREE(&node->qrtr_tx_flow, GFP_KERNEL);
init_waitqueue_head(&node->resume_tx);
diff --git a/qrtr/mhi.c b/qrtr/mhi.c
index b097fac..9a117f5 100644
--- a/qrtr/mhi.c
+++ b/qrtr/mhi.c
@@ -134,7 +134,7 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
qrtr_mhi_of_parse(mhi_dev, &net_id, &rt);
- rc = qrtr_endpoint_register(&qdev->ep, net_id, rt);
+ rc = qrtr_endpoint_register(&qdev->ep, net_id, rt, NULL);
if (rc)
return rc;
diff --git a/qrtr/qrtr.h b/qrtr/qrtr.h
index 0cf6948..2e09dce 100644
--- a/qrtr/qrtr.h
+++ b/qrtr/qrtr.h
@@ -26,8 +26,20 @@ struct qrtr_endpoint {
struct qrtr_node *node;
};
+/**
+ * struct qrtr_array - array with size
+ * @arr: elements in the array
+ * @size: number of elements
+ *
+ * An array with its size provided.
+ */
+struct qrtr_array {
+ u32 *arr;
+ size_t size;
+};
+
int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id,
- bool rt);
+ bool rt, struct qrtr_array *no_wake);
void qrtr_endpoint_unregister(struct qrtr_endpoint *ep);