diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c index 31bd41369d73..8eb0627c8aa3 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include @@ -56,6 +56,16 @@ IPA_GSB_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) +#define IPA_GSB_ERR_RL(fmt, args...) \ + do { \ + pr_err_ratelimited_ipa(IPA_GSB_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa3_get_ipc_logbuf(), \ + IPA_GSB_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa3_get_ipc_logbuf_low(), \ + IPA_GSB_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + #define IPA_GSB_MAX_MSG_LEN 512 #ifdef CONFIG_DEBUG_FS @@ -1184,7 +1194,7 @@ static int ipa_bridge_tx_dp_internal(u32 hdl, struct sk_buff *skb, } if (unlikely(!ipa_gsb_ctx->iface[hdl]->is_resumed)) { - IPA_GSB_ERR("iface %d was suspended\n", hdl); + IPA_GSB_ERR_RL("iface %d was suspended\n", hdl); return -EFAULT; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index cd5c4a7e7fa3..8e0055204e1c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -51,7 +51,7 @@ #endif #define DRV_NAME "ipa" - +#define DELAY_BEFORE_FW_LOAD 500 #define IPA_SUBSYSTEM_NAME "ipa_fws" #define IPA_UC_SUBSYSTEM_NAME "ipa_uc" @@ -126,6 +126,7 @@ static int ipa3_alloc_pkt_init(void); static void ipa3_load_ipa_fw(struct work_struct *work); static DECLARE_WORK(ipa3_fw_loading_work, ipa3_load_ipa_fw); +static DECLARE_DELAYED_WORK(ipa3_fw_load_failure_handle, ipa3_load_ipa_fw); static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work); static DECLARE_DELAYED_WORK(ipa_dec_clients_disable_clks_on_wq_work, @@ -3566,16 +3567,18 @@ static void ipa3_q6_avoid_holb(void) * setting HOLB on Q6 pipes, and from APPS perspective * they are not valid, therefore, the above function * will fail. + * Also don't reset the HOLB timer to 0 for Q6 pipes. */ - ipahal_write_reg_n_fields( - IPA_ENDP_INIT_HOL_BLOCK_TIMER_n, - ep_idx, &ep_holb); + + ipahal_write_reg_n_fields( IPA_ENDP_INIT_HOL_BLOCK_EN_n, ep_idx, &ep_holb); - /* IPA4.5 issue requires HOLB_EN to be written twice */ - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) + /* For targets > IPA_4.0 issue requires HOLB_EN to + * be written twice. + */ + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) ipahal_write_reg_n_fields( IPA_ENDP_INIT_HOL_BLOCK_EN_n, ep_idx, &ep_holb); @@ -6812,12 +6815,14 @@ static void ipa3_load_ipa_fw(struct work_struct *work) IPADBG("Entry\n"); IPA_ACTIVE_CLIENTS_INC_SIMPLE(); - - result = ipa3_attach_to_smmu(); - if (result) { - IPAERR("IPA attach to smmu failed %d\n", result); - IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); - return; + if(!ipa3_ctx->ipa_pil_load) + { + result = ipa3_attach_to_smmu(); + if (result) { + IPAERR("IPA attach to smmu failed %d\n", result); + IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); + return; + } } if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_EMULATION && @@ -6836,13 +6841,18 @@ static void ipa3_load_ipa_fw(struct work_struct *work) result = ipa3_manual_load_ipa_fws(); } - IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); if (result) { - IPAERR("IPA FW loading process has failed result=%d\n", - result); + + ipa3_ctx->ipa_pil_load++; + IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); + IPADBG("IPA firmware loading deffered to a work queue\n"); + queue_delayed_work(ipa3_ctx->transport_power_mgmt_wq, + &ipa3_fw_load_failure_handle, + msecs_to_jiffies(DELAY_BEFORE_FW_LOAD)); return; } + IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); mutex_lock(&ipa3_ctx->fw_load_data.lock); ipa3_ctx->fw_load_data.state = IPA_FW_LOAD_STATE_LOADED; mutex_unlock(&ipa3_ctx->fw_load_data.lock); @@ -6902,7 +6912,7 @@ static void ipa_fw_load_sm_handle_event(enum ipa_fw_load_event ev) if (ipa3_ctx->fw_load_data.state == IPA_FW_LOAD_STATE_INIT) { ipa3_ctx->fw_load_data.state = IPA_FW_LOAD_STATE_SMMU_DONE; - goto out; + goto sched_fw_load; } if (ipa3_ctx->fw_load_data.state == IPA_FW_LOAD_STATE_FWFILE_READY) { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 8ca62014e5cf..939a7716d54d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -67,6 +67,7 @@ int ipa3_enable_data_path(u32 clnt_hdl) holb_cfg.en = IPA_HOLB_TMR_EN; } else if (ipa3_ctx->ipa_hw_type == IPA_HW_v4_11 && (ep->client == IPA_CLIENT_WLAN1_CONS || + ep->client == IPA_CLIENT_WLAN2_CONS || ep->client == IPA_CLIENT_USB_CONS)) { holb_cfg.en = IPA_HOLB_TMR_EN; holb_cfg.tmr_val = IPA_HOLB_TMR_VAL_4_5; @@ -1497,8 +1498,10 @@ int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset, u32 tmr_val, IPA_ENDP_INIT_HOL_BLOCK_EN_n, pipe_idx, &ep_holb); - /* IPA4.5 issue requires HOLB_EN to be written twice */ - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) + /* For targets > IPA_4.0 issue requires HOLB_EN to be + * written twice. + */ + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) ipahal_write_reg_n_fields( IPA_ENDP_INIT_HOL_BLOCK_EN_n, pipe_idx, &ep_holb); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 83d2d1476508..5ba5c7c6fb81 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -345,20 +345,22 @@ static void ipa3_send_nop_desc(struct work_struct *work) return; } list_add_tail(&tx_pkt->link, &sys->head_desc_list); - sys->len++; - sys->nop_pending = false; memset(&nop_xfer, 0, sizeof(nop_xfer)); nop_xfer.type = GSI_XFER_ELEM_NOP; nop_xfer.flags = GSI_XFER_FLAG_EOT; nop_xfer.xfer_user_data = tx_pkt; if (gsi_queue_xfer(sys->ep->gsi_chan_hdl, 1, &nop_xfer, true)) { + list_del(&tx_pkt->link); + kmem_cache_free(ipa3_ctx->tx_pkt_wrapper_cache, tx_pkt); spin_unlock_bh(&sys->spinlock); IPAERR("gsi_queue_xfer for ch:%lu failed\n", sys->ep->gsi_chan_hdl); queue_work(sys->wq, &sys->work); return; } + sys->len++; + sys->nop_pending = false; spin_unlock_bh(&sys->spinlock); /* make sure TAG process is sent before clocks are gated */ @@ -3658,17 +3660,21 @@ static struct sk_buff *handle_page_completion(struct gsi_chan_xfer_notify sys->ep->client == IPA_CLIENT_APPS_LAN_CONS) { rx_skb = alloc_skb(0, GFP_ATOMIC); if (unlikely(!rx_skb)) { - IPAERR("skb alloc failure\n"); - list_del(&rx_pkt->link); - if (!rx_page.is_tmp_alloc) { - init_page_count(rx_page.page); - } else { - dma_unmap_page(ipa3_ctx->pdev, rx_page.dma_addr, - rx_pkt->len, DMA_FROM_DEVICE); - __free_pages(rx_pkt->page_data.page, - IPA_WAN_PAGE_ORDER); + IPAERR("skb alloc failure, free all pending pages\n"); + list_for_each_entry_safe(rx_pkt, tmp, head, link) { + rx_page = rx_pkt->page_data; + size = rx_pkt->data_len; + list_del_init(&rx_pkt->link); + if (!rx_page.is_tmp_alloc) { + init_page_count(rx_page.page); + } else { + dma_unmap_page(ipa3_ctx->pdev, rx_page.dma_addr, + rx_pkt->len, DMA_FROM_DEVICE); + __free_pages(rx_pkt->page_data.page, + IPA_WAN_PAGE_ORDER); + } + rx_pkt->sys->free_rx_wrapper(rx_pkt); } - rx_pkt->sys->free_rx_wrapper(rx_pkt); IPA_STATS_INC_CNT(ipa3_ctx->stats.rx_page_drop_cnt); return NULL; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index a6a742fee493..c4e9c7c78e40 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -2155,6 +2155,8 @@ struct ipa3_context { bool modem_load_ipa_fw; bool fnr_stats_not_supported; bool is_device_crashed; + int ipa_pil_load; + }; struct ipa3_plat_drv_res { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c index 5edd4776669e..8ced02501f84 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c @@ -179,7 +179,7 @@ static int ipa3_nat_ipv6ct_mmap( /* * Check if no smmu or non dma coherent */ - if (!cb->valid || !dev_is_dma_coherent(cb->dev)) { + if (cb && cb->dev && (!cb->valid || !dev_is_dma_coherent(cb->dev))) { IPADBG("Either smmu valid=%u and/or DMA coherent=%u false\n", cb->valid, !dev_is_dma_coherent(cb->dev)); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c index a5dee263c49b..68fbabcdeb2d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c @@ -250,6 +250,7 @@ int ipa3_send_adpl_msg(unsigned long skb_data) list_add_tail(&msg->link, &ipa3_odl_ctx->adpl_msg_list); atomic_inc(&ipa3_odl_ctx->stats.numer_in_queue); mutex_unlock(&ipa3_odl_ctx->adpl_msg_lock); + wake_up(&ipa3_odl_ctx->adpl_msg_waitq); IPA_STATS_INC_CNT(ipa3_odl_ctx->stats.odl_rx_pkt); return 0; @@ -527,7 +528,9 @@ static ssize_t ipa_adpl_read(struct file *filp, char __user *buf, size_t count, int ret = 0; char __user *start = buf; struct ipa3_push_msg_odl *msg; + DEFINE_WAIT_FUNC(wait, woken_wake_function); + add_wait_queue(&ipa3_odl_ctx->adpl_msg_waitq, &wait); while (1) { IPADBG_LOW("Writing message to adpl pipe\n"); if (!ipa3_odl_ctx->odl_state.odl_open) @@ -572,9 +575,6 @@ static ssize_t ipa_adpl_read(struct file *filp, char __user *buf, size_t count, IPA_STATS_INC_CNT(ipa3_odl_ctx->stats.odl_tx_diag_pkt); kfree(msg); msg = NULL; - } else { - ret = -EAGAIN; - break; } ret = -EAGAIN; @@ -587,9 +587,9 @@ static ssize_t ipa_adpl_read(struct file *filp, char __user *buf, size_t count, if (start != buf) break; - + wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); } - + remove_wait_queue(&ipa3_odl_ctx->adpl_msg_waitq, &wait); if (start != buf && ret != -EFAULT) ret = buf - start; @@ -665,6 +665,7 @@ int ipa_odl_init(void) odl_cdev = ipa3_odl_ctx->odl_cdev; INIT_LIST_HEAD(&ipa3_odl_ctx->adpl_msg_list); + init_waitqueue_head(&ipa3_odl_ctx->adpl_msg_waitq); mutex_init(&ipa3_odl_ctx->adpl_msg_lock); mutex_init(&ipa3_odl_ctx->pipe_lock); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h index c39d01dbb57f..e700b442b3ec 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h @@ -58,6 +58,7 @@ struct ipa_odl_context { bool odl_ctl_msg_wq_flag; struct ipa3_odlstats stats; u32 odl_pm_hdl; + wait_queue_head_t adpl_msg_waitq; }; struct ipa3_push_msg_odl { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c index b50625b5d688..4200d188284c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c @@ -1439,7 +1439,7 @@ int ipa3_uc_debug_stats_alloc( result = ipa3_uc_send_cmd((u32)(cmd.phys_base), command, IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS, - false, 10 * HZ); + false, 20 * HZ); if (result) { IPAERR("fail to alloc offload stats\n"); goto cleanup; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 0695a368e945..5c3edacfa78a 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -6332,8 +6332,8 @@ int ipa3_cfg_ep_holb(u32 clnt_hdl, const struct ipa_ep_cfg_holb *ep_holb) ipa3_ctx->ep[clnt_hdl].holb.en = IPA_HOLB_TMR_EN; ipahal_write_reg_n_fields(IPA_ENDP_INIT_HOL_BLOCK_EN_n, clnt_hdl, ep_holb); - /* IPA4.5 issue requires HOLB_EN to be written twice */ - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) + /* For targets > IPA_4.0 issue requires HOLB_EN to be written twice */ + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) ipahal_write_reg_n_fields(IPA_ENDP_INIT_HOL_BLOCK_EN_n, clnt_hdl, ep_holb);