diff options
-rw-r--r-- | cnss2/main.c | 9 | ||||
-rw-r--r-- | cnss2/main.h | 1 | ||||
-rw-r--r-- | cnss2/pci.c | 74 | ||||
-rw-r--r-- | cnss2/qmi.c | 7 | ||||
-rw-r--r-- | cnss2/reg.h | 5 | ||||
-rw-r--r-- | mhi/core/internal.h | 1 | ||||
-rw-r--r-- | mhi/core/misc.c | 12 | ||||
-rw-r--r-- | qrtr/af_qrtr.c | 24 | ||||
-rw-r--r-- | qrtr/mhi.c | 2 | ||||
-rw-r--r-- | qrtr/qrtr.h | 14 |
10 files changed, 129 insertions, 20 deletions
diff --git a/cnss2/main.c b/cnss2/main.c index 736f065..acc5b93 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); @@ -3452,7 +3457,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 1559333..dc78895 100644 --- a/cnss2/pci.c +++ b/cnss2/pci.c @@ -1908,8 +1908,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); @@ -1920,16 +1928,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; @@ -1971,15 +2023,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); @@ -2051,6 +2095,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; @@ -2087,6 +2132,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); @@ -4851,7 +4900,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) { @@ -4867,6 +4915,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 4073d15..9354333 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, ¶m); + 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); @@ -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); |