From 90a4c01494c44a7cc6f737ad375f4233124c3d42 Mon Sep 17 00:00:00 2001 From: gaurank kathpalia Date: Tue, 13 Aug 2019 14:43:02 +0530 Subject: [PATCH 001/208] qcacld-3.0: Extend force 1x1 ini Currently the driver checks whether the device supports antenna sharing, and if the AP is added in the OUI framework, then the driver modifies the nss value to 1 to avoid sending SMPS to the peer AP. Now suppose the device does not support Antenna sharing, but supports DBS and is helium HW, then going to DBS HW mode would result in peer sending a SMPS frame to the peer as the helium HW only has two antennas, and one is needed by each MAC now. Fix is to add a third param in force 1x1 ini which would decide the driver should consider the antenna sharing as mandatory or not. Change-Id: I3ae00fcbd642c7780952d66ccbf1208335fcb077 CRs-Fixed: 2496831 --- core/hdd/inc/wlan_hdd_cfg.h | 16 +++++++++------ core/hdd/src/wlan_hdd_cfg.c | 8 ++++---- core/hdd/src/wlan_hdd_main.c | 2 +- core/mac/inc/sir_api.h | 12 +++++++++++ .../src/pe/lim/lim_send_sme_rsp_messages.c | 2 +- core/sme/inc/csr_api.h | 2 +- core/sme/inc/csr_internal.h | 2 +- core/sme/src/csr/csr_api_roam.c | 20 +++++++++++-------- 8 files changed, 42 insertions(+), 22 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index d138554fc5c6..002797a9d718 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -1847,11 +1847,15 @@ enum hdd_dot11_mode { * * gForce1x1Exception - force 1x1 when connecting to certain peer * @Min: 0 - * @Max: 1 - * @Default: 0 + * @Max: 2 + * @Default: 2 * * This INI when enabled will force 1x1 connection with certain peer. - * + * The implementation for this ini would be as follows:- + * Value 0: Even if the AP is present in OUI, 1x1 will not be forced + * Value 1: If antenna sharing supported, then only do 1x1. + * Value 2: If AP present in OUI, force 1x1 connection. + * * Related: None * @@ -1863,8 +1867,8 @@ enum hdd_dot11_mode { */ #define CFG_FORCE_1X1_NAME "gForce1x1Exception" #define CFG_FORCE_1X1_MIN (0) -#define CFG_FORCE_1X1_MAX (1) -#define CFG_FORCE_1X1_DEFAULT (1) +#define CFG_FORCE_1X1_MAX (2) +#define CFG_FORCE_1X1_DEFAULT (2) /* * @@ -16927,7 +16931,7 @@ struct hdd_config { enum hdd_external_acs_policy external_acs_policy; /* threshold of packet drops at which FW initiates disconnect */ uint16_t pkt_err_disconn_th; - bool is_force_1x1; + enum force_1x1_type is_force_1x1_enable; uint8_t enable_rts_sifsbursting; uint8_t max_mpdus_inampdu; uint16_t sap_max_mcs_txdata; diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 7da6005e9ffe..8e0a768d3cc8 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -4857,7 +4857,7 @@ struct reg_table_entry g_registry_table[] = { CFG_DROPPED_PKT_DISCONNECT_TH_MAX), REG_VARIABLE(CFG_FORCE_1X1_NAME, WLAN_PARAM_Integer, - struct hdd_config, is_force_1x1, + struct hdd_config, is_force_1x1_enable, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, CFG_FORCE_1X1_DEFAULT, CFG_FORCE_1X1_MIN, @@ -7773,7 +7773,7 @@ void hdd_cfg_print(struct hdd_context *hdd_ctx) hdd_debug("Name = [%s] value = [%u]", CFG_FORCE_1X1_NAME, - hdd_ctx->config->is_force_1x1); + hdd_ctx->config->is_force_1x1_enable); hdd_debug("Name = [%s] Value = %u", CFG_ENABLE_CONNECTED_SCAN_NAME, hdd_ctx->config->enable_connected_scan); @@ -9776,8 +9776,8 @@ QDF_STATUS hdd_set_sme_config(struct hdd_context *hdd_ctx) smeConfig->csrConfig.num_disallowed_aps = hdd_ctx->config->num_disallowed_aps; - smeConfig->csrConfig.is_force_1x1 = - hdd_ctx->config->is_force_1x1; + smeConfig->csrConfig.is_force_1x1_enable = + hdd_ctx->config->is_force_1x1_enable; smeConfig->csrConfig.num_11b_tx_chains = hdd_ctx->config->num_11b_tx_chains; smeConfig->csrConfig.num_11ag_tx_chains = diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 0900ab2b4afa..9cac200930c7 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -11454,7 +11454,7 @@ int hdd_configure_cds(struct hdd_context *hdd_ctx) hdd_action_oui_send(hdd_ctx); - if (hdd_ctx->config->is_force_1x1) + if (hdd_ctx->config->is_force_1x1_enable) sme_cli_set_command(0, (int)WMI_PDEV_PARAM_SET_IOT_PATTERN, 1, PDEV_CMD); /* set chip power save failure detected callback */ diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 46d2760fc99b..7084e11df426 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2134,6 +2134,18 @@ struct lim_channel_status { uint32_t cmd_flags; }; +/** + * enum force_1x1_type - enum to specify the type of forced 1x1 ini provided. + * @FORCE_1X1_DISABLED: even if the AP is present in OUI, 1x1 will not be forced + * @FORCE_1X1_ENABLED_FOR_AS: If antenna sharing supported, then only do 1x1. + * @FORCE_1X1_ENABLED_FORCED: If AP present in OUI, force 1x1 connection. + */ +enum force_1x1_type { + FORCE_1X1_DISABLED, + FORCE_1X1_ENABLED_FOR_AS, + FORCE_1X1_ENABLED_FORCED, +}; + /** * struct lim_scan_channel_status * @total_channel: total number of be scanned channel diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index fad1f48dd026..4310e4312672 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -380,7 +380,7 @@ static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx, SIR_MAC_VENDOR_AP_1_OUI, SIR_MAC_VENDOR_AP_1_OUI_LEN, bss_ies, bss_ie_len) != NULL); - if (mac_ctx->roam.configParam.is_force_1x1 && + if (mac_ctx->roam.configParam.is_force_1x1_enable && is_vendor_ap_1_present && (session_entry->nss == 2) && (mac_ctx->lteCoexAntShare == 0 || IS_5G_CH(session_entry->currentOperChannel))) { diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index ac7286e0da10..781de103d26d 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1290,7 +1290,7 @@ typedef struct tagCsrConfigParam { bool qcn_ie_support; uint8_t fils_max_chan_guard_time; uint16_t pkt_err_disconn_th; - bool is_force_1x1; + enum force_1x1_type is_force_1x1_enable; uint16_t num_11b_tx_chains; uint16_t num_11ag_tx_chains; uint32_t disallow_duration; diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 0a8773c2a31a..c111a45930ca 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -597,7 +597,7 @@ struct csr_config { bool qcn_ie_support; uint8_t fils_max_chan_guard_time; uint16_t pkt_err_disconn_th; - bool is_force_1x1; + enum force_1x1_type is_force_1x1_enable; uint16_t num_11b_tx_chains; uint16_t num_11ag_tx_chains; uint32_t disallow_duration; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 219fbb87ccbc..532e2572d939 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -2821,8 +2821,8 @@ QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, if (pParam) { pMac->roam.configParam.pkt_err_disconn_th = pParam->pkt_err_disconn_th; - pMac->roam.configParam.is_force_1x1 = - pParam->is_force_1x1; + pMac->roam.configParam.is_force_1x1_enable = + pParam->is_force_1x1_enable; pMac->roam.configParam.WMMSupportMode = pParam->WMMSupportMode; cfg_set_int(pMac, WNI_CFG_WME_ENABLED, (pParam->WMMSupportMode == eCsrRoamWmmNoQos) ? 0 : 1); @@ -3431,7 +3431,7 @@ QDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) return QDF_STATUS_E_INVAL; pParam->pkt_err_disconn_th = cfg_params->pkt_err_disconn_th; - pParam->is_force_1x1 = cfg_params->is_force_1x1; + pParam->is_force_1x1_enable = cfg_params->is_force_1x1_enable; pParam->WMMSupportMode = cfg_params->WMMSupportMode; pParam->Is11eSupportEnabled = cfg_params->Is11eSupportEnabled; pParam->FragmentationThreshold = cfg_params->FragmentationThreshold; @@ -16003,14 +16003,18 @@ QDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, sme_debug("1x1 with 1 Chain AP"); } - if (pMac->roam.configParam.is_force_1x1 && - pMac->lteCoexAntShare && - is_vendor_ap_present) { + if ((pMac->roam.configParam.is_force_1x1_enable == + FORCE_1X1_ENABLED_FORCED || + (pMac->roam.configParam.is_force_1x1_enable == + FORCE_1X1_ENABLED_FOR_AS && + pMac->lteCoexAntShare)) && is_vendor_ap_present) { pSession->supported_nss_1x1 = true; pSession->vdev_nss = 1; pSession->nss = 1; pSession->nss_forced_1x1 = true; - sme_debug("For special ap, NSS: %d", pSession->nss); + sme_debug("For special ap, NSS: %d force 1x1 %d", + pSession->nss, + pMac->roam.configParam.is_force_1x1_enable); } /* @@ -16038,7 +16042,7 @@ QDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, ucfg_action_oui_search(pMac->psoc, &vendor_ap_search_attr, ACTION_OUI_SWITCH_TO_11N_MODE); - if (pMac->roam.configParam.is_force_1x1 && + if (pMac->roam.configParam.is_force_1x1_enable && pMac->lteCoexAntShare && is_vendor_ap_present && (ucDot11Mode == WNI_CFG_DOT11_MODE_ALL || From 1f9dfe12fc41c9797f7d9ab5ea80ae09faa951b6 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Mon, 7 Oct 2019 19:52:10 -0700 Subject: [PATCH 002/208] drivers: rmnet_shs: Remove rmnet ep access Rmnet driver allocates rmnet_endpoint which rmnet_shs was using to keep track of endpoints that needed. However rmnet driver frees the memory before endpoint unregistration so this leaves a potential race condition where the wq can run after freeing. Change is to instead use net_dev refrerences we keep track of from net_dev_cb and no longer use rmnet_endpoints allocated by rmnet driver. Rmnet_shs was only using netdev references in rmnet_endpoint so no impact should be expected. This use-after-free would cause the following crash-signature. <6> Unable to handle kernel paging request at virtual address 00005000 <6> Mem abort info: <6> Exception class = DABT (current EL), IL = 32 bits <6> SET = 0, FnV = 0 <6> EA = 0, S1PTW = 0 <6> FSC = 5 <6> Data abort info: <6> ISV = 0, ISS = 0x00000005 <6> CM = 0, WnR = 0 <6> user pgtable: 4k pages, 39-bit VAs, pgd = 0000000070b0b425 <6> Internal error: Oops: 96000005 [#1] PREEMPT SMP <6> Workqueue: rmnet_shs_wq rmnet_shs_wq_process_wq [rmnet_shs] <6> task: 00000000deaad59d task.stack: 00000000053e0949 <2> pc : rmnet_shs_wq_update_ep_rps_msk+0x3c/0xd8 [rmnet_shs] <2> lr : rmnet_shs_wq_update_ep_rps_msk+0x28/0xd8 [rmnet_shs] <2> Call trace: <2> rmnet_shs_wq_update_ep_rps_msk+0x3c/0xd8 [rmnet_shs] <2> rmnet_shs_wq_update_stats+0x98/0x928 [rmnet_shs] <2> rmnet_shs_wq_process_wq+0x10c/0x248 [rmnet_shs] <2> process_one_work+0x1f0/0x458 <2> worker_thread+0x2ec/0x450 <2> kthread+0x11c/0x130 <2> ret_from_fork+0x10/0x1c CRs-Fixed: 2541604 Change-Id: I7026f2564c463f4ca989af97572e2a8fe5652087 Acked-by: Raul Martinez Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs_config.c | 7 +- drivers/rmnet/shs/rmnet_shs_main.c | 2 +- drivers/rmnet/shs/rmnet_shs_wq.c | 109 +++++++-------------------- drivers/rmnet/shs/rmnet_shs_wq.h | 8 +- 4 files changed, 36 insertions(+), 90 deletions(-) diff --git a/drivers/rmnet/shs/rmnet_shs_config.c b/drivers/rmnet/shs/rmnet_shs_config.c index ffa4f1d63ca0..4112e1a61653 100644 --- a/drivers/rmnet/shs/rmnet_shs_config.c +++ b/drivers/rmnet/shs/rmnet_shs_config.c @@ -164,14 +164,15 @@ static int rmnet_shs_dev_notify_cb(struct notifier_block *nb, if (ret) pr_err("%s(): rmnet ps_ind registration fail\n", __func__); - + rmnet_shs_update_cfg_mask(); + rmnet_shs_wq_refresh_new_flow_list(); rmnet_shs_cfg.is_reg_dl_mrk_ind = 1; trace_rmnet_shs_high(RMNET_SHS_MODULE, RMNET_SHS_MODULE_INIT_WQ, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); - RCU_INIT_POINTER(rmnet_shs_skb_entry, - rmnet_shs_assign); + RCU_INIT_POINTER(rmnet_shs_skb_entry, + rmnet_shs_assign); } break; diff --git a/drivers/rmnet/shs/rmnet_shs_main.c b/drivers/rmnet/shs/rmnet_shs_main.c index b52e6089e3f8..2ea09dcdf29c 100755 --- a/drivers/rmnet/shs/rmnet_shs_main.c +++ b/drivers/rmnet/shs/rmnet_shs_main.c @@ -1354,7 +1354,7 @@ void rmnet_shs_init(struct net_device *dev, struct net_device *vnd) map_len = 0; } else { map_mask = rmnet_shs_mask_from_map(map); - map_len = rmnet_shs_get_mask_len(rmnet_shs_cfg.map_mask); + map_len = rmnet_shs_get_mask_len(map_mask); } rmnet_shs_cfg.port = rmnet_get_port(dev); diff --git a/drivers/rmnet/shs/rmnet_shs_wq.c b/drivers/rmnet/shs/rmnet_shs_wq.c index 0f0813773182..1ec35ec36928 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq.c +++ b/drivers/rmnet/shs/rmnet_shs_wq.c @@ -168,24 +168,16 @@ static struct list_head rmnet_shs_wq_ep_tbl = */ void rmnet_shs_wq_ep_tbl_add(struct rmnet_shs_wq_ep_s *ep) { - unsigned long flags; trace_rmnet_shs_wq_low(RMNET_SHS_WQ_EP_TBL, RMNET_SHS_WQ_EP_TBL_ADD, 0xDEF, 0xDEF, 0xDEF, 0xDEF, ep, NULL); - spin_lock_irqsave(&rmnet_shs_hstat_tbl_lock, flags); list_add(&ep->ep_list_id, &rmnet_shs_wq_ep_tbl); - spin_unlock_irqrestore(&rmnet_shs_hstat_tbl_lock, flags); } void rmnet_shs_wq_ep_tbl_remove(struct rmnet_shs_wq_ep_s *ep) { - unsigned long flags; trace_rmnet_shs_wq_low(RMNET_SHS_WQ_EP_TBL, RMNET_SHS_WQ_EP_TBL_DEL, 0xDEF, 0xDEF, 0xDEF, 0xDEF, ep, NULL); - - spin_lock_irqsave(&rmnet_shs_hstat_tbl_lock, flags); list_del_init(&ep->ep_list_id); - spin_unlock_irqrestore(&rmnet_shs_hstat_tbl_lock, flags); - } /* Helper functions to add and remove entries to the table @@ -415,7 +407,7 @@ void rmnet_shs_wq_update_hstat_rps_msk(struct rmnet_shs_wq_hstat_s *hstat_p) /*Map RPS mask from the endpoint associated with this flow*/ list_for_each_entry(ep, &rmnet_shs_wq_ep_tbl, ep_list_id) { - if (ep && (node_p->dev == ep->ep->egress_dev)) { + if (ep && (node_p->dev == ep->ep)) { hstat_p->rps_config_msk = ep->rps_config_msk; hstat_p->def_core_msk = ep->default_core_msk; hstat_p->pri_core_msk = ep->pri_core_msk; @@ -556,7 +548,7 @@ static void rmnet_shs_wq_refresh_dl_mrkr_stats(void) tbl_p->dl_mrk_last_rx_bytes = tbl_p->dl_mrk_rx_bytes; tbl_p->dl_mrk_last_rx_pkts = tbl_p->dl_mrk_rx_pkts; - port = rmnet_get_port(rmnet_shs_delayed_wq->netdev); + port = rmnet_shs_cfg.port; if (!port) { rmnet_shs_crit_err[RMNET_SHS_WQ_GET_RMNET_PORT_ERR]++; return; @@ -735,7 +727,7 @@ void rmnet_shs_wq_chng_suggested_cpu(u16 old_cpu, u16 new_cpu, hstat_p = node_p->hstats; if ((hstat_p->suggested_cpu == old_cpu) && - (node_p->dev == ep->ep->egress_dev)) { + (node_p->dev == ep->ep)) { trace_rmnet_shs_wq_high(RMNET_SHS_WQ_FLOW_STATS, RMNET_SHS_WQ_FLOW_STATS_SUGGEST_NEW_CPU, @@ -762,24 +754,6 @@ u64 rmnet_shs_wq_get_max_pps_among_cores(u32 core_msk) return max_pps; } -u32 rmnet_shs_wq_get_dev_rps_msk(struct net_device *dev) -{ - u32 dev_rps_msk = 0; - struct rmnet_shs_wq_ep_s *ep = NULL; - - list_for_each_entry(ep, &rmnet_shs_wq_ep_tbl, ep_list_id) { - if (!ep) - continue; - - if (!ep->is_ep_active) - continue; - - if (ep->ep->egress_dev == dev) - dev_rps_msk = ep->rps_config_msk; - } - return dev_rps_msk; -} - /* Returns the least utilized core from a core mask * In order of priority * 1) Returns leftmost core with no flows (Fully Idle) @@ -1102,7 +1076,7 @@ int rmnet_shs_wq_get_lpwr_cpu_new_flow(struct net_device *dev) if (!ep->is_ep_active) continue; - if (ep->ep->egress_dev == dev) { + if (ep->ep == dev) { is_match_found = 1; break; } @@ -1152,7 +1126,7 @@ int rmnet_shs_wq_get_perf_cpu_new_flow(struct net_device *dev) if (!ep->is_ep_active) continue; - if (ep->ep->egress_dev == dev) { + if (ep->ep == dev) { is_match_found = 1; break; } @@ -1254,18 +1228,18 @@ void rmnet_shs_wq_update_ep_rps_msk(struct rmnet_shs_wq_ep_s *ep) struct rps_map *map; u8 len = 0; - if (!ep || !ep->ep || !ep->ep->egress_dev) { + if (!ep || !ep->ep ) { rmnet_shs_crit_err[RMNET_SHS_WQ_EP_ACCESS_ERR]++; return; } rcu_read_lock(); - if (!ep->ep || !ep->ep->egress_dev) { + if (!ep->ep) { pr_info(" rmnet_shs invalid state %p", ep->ep); rmnet_shs_crit_err[RMNET_SHS_WQ_EP_ACCESS_ERR]++; return; } - map = rcu_dereference(ep->ep->egress_dev->_rx->rps_map); + map = rcu_dereference(ep->ep->_rx->rps_map); ep->rps_config_msk = 0; if (map != NULL) { @@ -1281,20 +1255,23 @@ void rmnet_shs_wq_update_ep_rps_msk(struct rmnet_shs_wq_ep_s *ep) void rmnet_shs_wq_reset_ep_active(struct net_device *dev) { struct rmnet_shs_wq_ep_s *ep = NULL; + struct rmnet_shs_wq_ep_s *tmp = NULL; unsigned long flags; spin_lock_irqsave(&rmnet_shs_ep_lock, flags); - list_for_each_entry(ep, &rmnet_shs_wq_ep_tbl, ep_list_id) { + list_for_each_entry_safe(ep, tmp, &rmnet_shs_wq_ep_tbl, ep_list_id) { if (!ep) continue; - if (ep->netdev == dev){ + if (ep->ep == dev){ ep->is_ep_active = 0; - ep->netdev = NULL; + rmnet_shs_wq_ep_tbl_remove(ep); + kfree(ep); + break; } } - spin_unlock_irqrestore(&rmnet_shs_ep_lock, flags); + spin_unlock_irqrestore(&rmnet_shs_ep_lock, flags); } void rmnet_shs_wq_set_ep_active(struct net_device *dev) @@ -1303,16 +1280,21 @@ void rmnet_shs_wq_set_ep_active(struct net_device *dev) unsigned long flags; spin_lock_irqsave(&rmnet_shs_ep_lock, flags); - list_for_each_entry(ep, &rmnet_shs_wq_ep_tbl, ep_list_id) { - if (!ep) - continue; - if (ep->ep->egress_dev == dev){ - ep->is_ep_active = 1; - ep->netdev = dev; + ep = kzalloc(sizeof(*ep), GFP_ATOMIC); - } + if (!ep) { + rmnet_shs_crit_err[RMNET_SHS_WQ_ALLOC_EP_TBL_ERR]++; + spin_unlock_irqrestore(&rmnet_shs_ep_lock, flags); + return; } + ep->ep = dev; + ep->is_ep_active = 1; + + INIT_LIST_HEAD(&ep->ep_list_id); + rmnet_shs_wq_update_ep_rps_msk(ep); + rmnet_shs_wq_ep_tbl_add(ep); + spin_unlock_irqrestore(&rmnet_shs_ep_lock, flags); } @@ -1443,34 +1425,6 @@ void rmnet_shs_wq_exit(void) 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); } -void rmnet_shs_wq_gather_rmnet_ep(struct net_device *dev) -{ - u8 mux_id; - struct rmnet_port *port; - struct rmnet_endpoint *ep; - struct rmnet_shs_wq_ep_s *ep_wq; - - port = rmnet_get_port(dev); - - for (mux_id = 1; mux_id < 255; mux_id++) { - ep = rmnet_get_endpoint(port, mux_id); - if (!ep) - continue; - - trace_rmnet_shs_wq_high(RMNET_SHS_WQ_EP_TBL, - RMNET_SHS_WQ_EP_TBL_INIT, - 0xDEF, 0xDEF, 0xDEF, 0xDEF, ep, NULL); - ep_wq = kzalloc(sizeof(*ep_wq), GFP_ATOMIC); - if (!ep_wq) { - rmnet_shs_crit_err[RMNET_SHS_WQ_ALLOC_EP_TBL_ERR]++; - return; - } - INIT_LIST_HEAD(&ep_wq->ep_list_id); - ep_wq->ep = ep; - rmnet_shs_wq_update_ep_rps_msk(ep_wq); - rmnet_shs_wq_ep_tbl_add(ep_wq); - } -} void rmnet_shs_wq_init_cpu_rx_flow_tbl(void) { u8 cpu_num; @@ -1527,21 +1481,12 @@ void rmnet_shs_wq_init(struct net_device *dev) return; } - rmnet_shs_delayed_wq->netdev = dev; - rmnet_shs_wq_gather_rmnet_ep(dev); - /*All hstat nodes allocated during Wq init will be held for ever*/ rmnet_shs_wq_hstat_alloc_nodes(RMNET_SHS_MIN_HSTAT_NODES_REQD, 1); rmnet_shs_wq_init_cpu_rx_flow_tbl(); INIT_DEFERRABLE_WORK(&rmnet_shs_delayed_wq->wq, rmnet_shs_wq_process_wq); - /* During initialization, we can start workqueue without a delay - * to initialize all meta data and pre allocated memory - * for hash stats, if required - */ - queue_delayed_work(rmnet_shs_wq, &rmnet_shs_delayed_wq->wq, 0); - trace_rmnet_shs_wq_high(RMNET_SHS_WQ_INIT, RMNET_SHS_WQ_INIT_END, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); } diff --git a/drivers/rmnet/shs/rmnet_shs_wq.h b/drivers/rmnet/shs/rmnet_shs_wq.h index b0bbd9c59639..90d1604b0210 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq.h +++ b/drivers/rmnet/shs/rmnet_shs_wq.h @@ -32,8 +32,7 @@ struct rmnet_shs_wq_ep_s { struct list_head ep_list_id; - struct rmnet_endpoint *ep; - struct net_device *netdev; + struct net_device *ep; int new_lo_core[MAX_CPUS]; int new_hi_core[MAX_CPUS]; u16 default_core_msk; @@ -133,7 +132,6 @@ struct rmnet_shs_wq_rx_flow_s { struct rmnet_shs_delay_wq_s { struct delayed_work wq; - struct net_device *netdev; }; @@ -214,6 +212,8 @@ void rmnet_shs_wq_exit(void); void rmnet_shs_wq_restart(void); void rmnet_shs_wq_pause(void); +void rmnet_shs_update_cfg_mask(void); + u64 rmnet_shs_wq_get_max_pps_among_cores(u32 core_msk); void rmnet_shs_wq_create_new_flow(struct rmnet_shs_skbn_s *node_p); int rmnet_shs_wq_get_least_utilized_core(u16 core_msk); @@ -221,9 +221,9 @@ int rmnet_shs_wq_get_lpwr_cpu_new_flow(struct net_device *dev); int rmnet_shs_wq_get_perf_cpu_new_flow(struct net_device *dev); u64 rmnet_shs_wq_get_max_allowed_pps(u16 cpu); void rmnet_shs_wq_inc_cpu_flow(u16 cpu); -u32 rmnet_shs_wq_get_dev_rps_msk(struct net_device *dev); void rmnet_shs_wq_dec_cpu_flow(u16 cpu); void rmnet_shs_hstat_tbl_delete(void); void rmnet_shs_wq_set_ep_active(struct net_device *dev); void rmnet_shs_wq_reset_ep_active(struct net_device *dev); +void rmnet_shs_wq_refresh_new_flow_list(void); #endif /*_RMNET_SHS_WQ_H_*/ From 1f9473155e630b82382d95f1898d21246aeb03ae Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Mon, 21 Oct 2019 16:43:49 +0530 Subject: [PATCH 003/208] qcacld-3.0: Populate and send correct max rate to the userspace When the ini gReportMaxLinkSpeed is set, it indicates that the rates provided to the userspace should give the maximum possible rate for the given connected parameters. But currently in the driver, the max rate that is being sent to the userspace is dependent on the NSS at which the tx/rx is being done. The NSS is calculated by taking the union of the value from assoc req and from the rate table using MCS index/rates from firmware. The rates fluctuate as per the tx/rx by firmware which subsequently affects the NSS in the host. To keep the max rate independent of this changing NSS, decouple the NSS calculation to contain the value from only the assoc req when reporting max rate. Change-Id: I03d10e397fca6853d05b4812a2adeac0110bc517 CRs-Fixed: 2548498 --- core/hdd/src/wlan_hdd_stats.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index b975446e576f..c1b3418ae1a6 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -4520,7 +4520,8 @@ static int wlan_hdd_get_sta_stats(struct wiphy *wiphy, tx_rate_flags, tx_mcs_index, my_tx_rate, - tx_nss); + wlan_vdev_mlme_get_nss( + adapter->vdev)); rx_rate_calc = hdd_report_max_rate(mac_handle, pCfg, &sinfo->rxrate, @@ -4528,7 +4529,8 @@ static int wlan_hdd_get_sta_stats(struct wiphy *wiphy, rx_rate_flags, rx_mcs_index, my_rx_rate, - rx_nss); + wlan_vdev_mlme_get_nss( + adapter->vdev)); if (!tx_rate_calc || !rx_rate_calc) /* Keep GUI happy */ From 0518cd893e65a0df360946cd2fe052cdc31f42c1 Mon Sep 17 00:00:00 2001 From: Sean Tranchetti Date: Wed, 20 Nov 2019 16:51:45 -0700 Subject: [PATCH 004/208] drivers: rmnet_perf: Check for over pulling Much like the core driver, we must check for the return value of rmnet_frag_pull() to ensure the descriptor is still valid before continuing to process it. Call Trace: __memcpy+0x68/0x180 rmnet_perf_core_send_desc+0x48/0x58 [rmnet_perf] rmnet_perf_opt_flush_single_flow_node+0x244/0x458 [rmnet_perf] rmnet_perf_tcp_opt_ingress+0x228/0x270 [rmnet_perf] rmnet_perf_opt_ingress+0x34c/0x3a0 [rmnet_perf] rmnet_perf_core_desc_entry+0x114/0x168 [rmnet_perf] Change-Id: I6665d7410bcdb6880af1ca20822328f81a2cc0ec Signed-off-by: Sean Tranchetti --- drivers/rmnet/perf/rmnet_perf_opt.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/rmnet/perf/rmnet_perf_opt.c b/drivers/rmnet/perf/rmnet_perf_opt.c index b4114836c539..d6b21f75dc2a 100644 --- a/drivers/rmnet/perf/rmnet_perf_opt.c +++ b/drivers/rmnet/perf/rmnet_perf_opt.c @@ -318,10 +318,12 @@ rmnet_perf_opt_add_flow_subfrags(struct rmnet_perf_opt_flow_node *flow_node) new_frag = pkt_list[i].frag_desc; /* Pull headers if they're there */ - if (new_frag->hdr_ptr == rmnet_frag_data_ptr(new_frag)) - rmnet_frag_pull(new_frag, perf->rmnet_port, - flow_node->ip_len + - flow_node->trans_len); + if (new_frag->hdr_ptr == rmnet_frag_data_ptr(new_frag)) { + if (!rmnet_frag_pull(new_frag, perf->rmnet_port, + flow_node->ip_len + + flow_node->trans_len)) + continue; + } /* Move the fragment onto the subfrags list */ list_move_tail(&new_frag->list, &head_frag->sub_frags); From 9f0b8a6587a7145d3674375b31ca48ad33d9a797 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Wed, 20 Nov 2019 08:18:31 -0700 Subject: [PATCH 005/208] drivers: shs: Change allocation context of shs allocations within spin_lock The allocation of the shs memory for cpu and flow level stats is done is done in the atomic context due to the invocation of the spin_lock_irqsave which disables preemption. Fixes the following- 230.251419: <6> sleeping function called from invalid context at mm/slab.h:422 230.277265: <6> in_atomic(): 1, irqs_disabled(): 128, pid: 62, name: kworker/6:0 230.277267: <2> INFO: lockdep is turned off. 230.284504: <2> irq event stamp: 90 230.284514: <2> hardirqs last enabled at (89): [] _raw_spin_unlock_irq+0x34/0x68 230.284517: <2> hardirqs last disabled at (90): [] __schedule+0x138/0x1128 230.284524: <2> softirqs last enabled at (0): [] copy_process+0x60c/0x1c28 230.284525: <2> softirqs last disabled at (0): [<0000000000000000>] (null) 230.284526: <4> Preemption disabled at: 230.284535: <2> [] rmnet_shs_wq_process_wq+0x18c/0x350 [rmnet_shs] 230.288129: <6> ------------[ cut here ]------------ 230.292958: <6> at kernel/sched/core.c:6786! 230.305980: <6> Internal error: Oops - BUG: 0 [#1] PREEMPT SMP 230.358297: <6> Process kworker/6:0 (pid: 62, stack limit = 0xffffff80083c0000) 230.365454: <6> CPU: 6 PID: 62 Comm: kworker/6:0 Tainted: G S O 4.19.81+ #1 230.379937: <6> Workqueue: rmnet_shs_wq rmnet_shs_wq_process_wq [rmnet_shs] 230.386741: <2> pc : ___might_sleep+0x204/0x208 230.401745: <2> lr : ___might_sleep+0x204/0x208 230.598414: <2> Call trace: 230.598419: <2> ___might_sleep+0x204/0x208 230.598420: <2> __might_sleep+0x50/0x88 230.598423: <2> kmem_cache_alloc_trace+0x74/0x420 230.598430: <2> rmnet_shs_wq_cpu_caps_list_add+0x64/0x118 [rmnet_shs] 230.598433: <2> rmnet_shs_wq_update_stats+0x4dc/0xea0 [rmnet_shs] 230.598435: <2> rmnet_shs_wq_process_wq+0x194/0x350 [rmnet_shs] 230.598438: <2> process_one_work+0x328/0x6b0 230.598439: <2> worker_thread+0x330/0x4d0 230.598441: <2> kthread+0x128/0x138 230.598443: <2> ret_from_fork+0x10/0x1c Also fixes structure padding of shared mem structs, which was causing memcpy overrun. CRs-Fixed: 2570479 Change-Id: Ia58b0bee544afb030353ad1d3cd45d8c16a94f75 Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs_wq_genl.c | 6 +++--- drivers/rmnet/shs/rmnet_shs_wq_mem.c | 6 +++--- drivers/rmnet/shs/rmnet_shs_wq_mem.h | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/rmnet/shs/rmnet_shs_wq_genl.c b/drivers/rmnet/shs/rmnet_shs_wq_genl.c index 7d07acea7b99..b28f0c271e39 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq_genl.c +++ b/drivers/rmnet/shs/rmnet_shs_wq_genl.c @@ -68,7 +68,7 @@ int rmnet_shs_genl_send_int_to_userspace(struct genl_info *info, int val) void *msg_head; int rc; - skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); if (skb == NULL) goto out; @@ -109,7 +109,7 @@ int rmnet_shs_genl_send_int_to_userspace_no_info(int val) return -1; } - skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); if (skb == NULL) goto out; @@ -148,7 +148,7 @@ int rmnet_shs_genl_send_msg_to_userspace(void) int val = rmnet_shs_genl_seqnum++; rm_err("SHS_GNL: Trying to send msg %d\n", val); - skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); if (skb == NULL) goto out; diff --git a/drivers/rmnet/shs/rmnet_shs_wq_mem.c b/drivers/rmnet/shs/rmnet_shs_wq_mem.c index bb5dca8c9a48..164b589b5153 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq_mem.c +++ b/drivers/rmnet/shs/rmnet_shs_wq_mem.c @@ -255,7 +255,7 @@ void rmnet_shs_wq_ssflow_list_add(struct rmnet_shs_wq_hstat_s *hnode, return; } - ssflow_node = kzalloc(sizeof(*ssflow_node), GFP_KERNEL); + ssflow_node = kzalloc(sizeof(*ssflow_node), GFP_ATOMIC); if (ssflow_node != NULL) { ssflow_node->avg_pps = hnode->avg_pps; ssflow_node->cpu_num = hnode->current_cpu; @@ -304,7 +304,7 @@ void rmnet_shs_wq_gflow_list_add(struct rmnet_shs_wq_hstat_s *hnode, } if (!rmnet_shs_is_lpwr_cpu(hnode->current_cpu)) { - gflow_node = kzalloc(sizeof(*gflow_node), GFP_KERNEL); + gflow_node = kzalloc(sizeof(*gflow_node), GFP_ATOMIC); if (gflow_node != NULL) { gflow_node->avg_pps = hnode->avg_pps; gflow_node->cpu_num = hnode->current_cpu; @@ -361,7 +361,7 @@ void rmnet_shs_wq_cpu_caps_list_add( pps_uthresh = rmnet_shs_cpu_rx_max_pps_thresh[cpu_node->cpu_num]; pps_lthresh = rmnet_shs_cpu_rx_min_pps_thresh[cpu_node->cpu_num]; - cap_node = kzalloc(sizeof(*cap_node), GFP_KERNEL); + cap_node = kzalloc(sizeof(*cap_node), GFP_ATOMIC); if (cap_node == NULL) { rmnet_shs_crit_err[RMNET_SHS_WQ_NODE_MALLOC_ERR]++; return; diff --git a/drivers/rmnet/shs/rmnet_shs_wq_mem.h b/drivers/rmnet/shs/rmnet_shs_wq_mem.h index f348e2bd2402..2e5e88906dde 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq_mem.h +++ b/drivers/rmnet/shs/rmnet_shs_wq_mem.h @@ -26,14 +26,14 @@ #define RMNET_SHS_MAX_USRFLOWS (128) -struct rmnet_shs_wq_cpu_cap_usr_s { +struct __attribute__((__packed__)) rmnet_shs_wq_cpu_cap_usr_s { u64 pps_capacity; u64 avg_pps_capacity; u64 bps_capacity; u16 cpu_num; }; -struct rmnet_shs_wq_gflows_usr_s { +struct __attribute__((__packed__)) rmnet_shs_wq_gflows_usr_s { u64 rx_pps; u64 avg_pps; u64 rx_bps; @@ -41,7 +41,7 @@ struct rmnet_shs_wq_gflows_usr_s { u16 cpu_num; }; -struct rmnet_shs_wq_ssflows_usr_s { +struct __attribute__((__packed__)) rmnet_shs_wq_ssflows_usr_s { u64 rx_pps; u64 avg_pps; u64 rx_bps; From b389452e8dd05128b9f0e1919423bffb5aff11ce Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Fri, 22 Nov 2019 12:16:30 -0700 Subject: [PATCH 006/208] drivers: shs: fix null check before freeing slow start list Checks the correct pointer for null before freeing the associated page for slow start shared memory. Fixes the following: [ 2982.239281] Unable to handle kernel paging request at virtual address ffffffbfadadadb4 [ 2982.239512] pc : __free_pages+0x24/0xc0 [ 2982.239515] lr : free_pages+0x38/0x48 [ 2982.240605] Call trace: [ 2982.240609] __free_pages+0x24/0xc0 [ 2982.240613] free_pages+0x38/0x48 [ 2982.240632] rmnet_shs_release_ss_flows+0x38/0x58 [rmnet_shs] Change-Id: I1c61b8c9c89905e94c24f6836eaf1d7f56566162 Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs_wq_mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rmnet/shs/rmnet_shs_wq_mem.c b/drivers/rmnet/shs/rmnet_shs_wq_mem.c index 164b589b5153..bec0da597d51 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq_mem.c +++ b/drivers/rmnet/shs/rmnet_shs_wq_mem.c @@ -205,7 +205,7 @@ static int rmnet_shs_release_ss_flows(struct inode *inode, struct file *filp) struct rmnet_shs_mmap_info *info; rm_err("%s", "SHS_MEM: rmnet_shs_release - entry\n"); - if (gflow_shared) { + if (ssflow_shared) { info = filp->private_data; ssflow_shared = NULL; free_page((unsigned long)info->data); From f094f9504d383590a80071cb5f7cb28462784bfd Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Fri, 22 Nov 2019 18:47:43 -0700 Subject: [PATCH 007/208] drivers: shs: fix deadlock caused between generic netlink and rtnl locks Fix for a deadlock seen when trying to register the shs generic netlink family inside of the callback context of rtnl_netlink. Instead of running in the notifier's context, the generic netlink registration is moved to initialization of the kernel module. Fixes the following lock contention scenario: [ 3302.102281] Call trace: [ 3302.102332] __switch_to+0x108/0x118 [ 3302.102357] __schedule+0x8fc/0xcd8 [ 3302.102368] schedule_preempt_disabled+0x7c/0xa8 [ 3302.102384] __mutex_lock+0x444/0x660 [ 3302.102392] __mutex_lock_slowpath+0x10/0x18 [ 3302.102399] mutex_lock+0x30/0x38 mutex_lock(&rtnl_mutex); [ 3302.102422] rtnl_lock+0x14/0x20 rtnl_lock [ 3302.102448] nl80211_pre_doit+0x28/0x1a0 [ 3302.102465] genl_rcv_msg+0x3a4/0x408 [ 3302.102473] netlink_rcv_skb+0xa8/0x120 [ 3302.102481] genl_rcv+0x30/0x48 down_read(&cb_lock); [ 3302.102487] netlink_unicast+0x1ec/0x290 [ 3302.102496] netlink_sendmsg+0x2ec/0x348 [ 3302.102609] Call trace: [ 3302.102615] __switch_to+0x108/0x118 [ 3302.102624] __schedule+0x8fc/0xcd8 [ 3302.102630] schedule+0x70/0x90 [ 3302.102638] rwsem_down_write_failed+0x2bc/0x3c8 [ 3302.102644] down_write+0x4c/0x50 [ 3302.102652] genl_register_family+0xb4/0x650 down_write(&cb_lock); [ 3302.102818] rmnet_shs_wq_genl_init+0x1c/0x38 [rmnet_shs] [ 3302.102847] rmnet_shs_wq_init+0x218/0x328 [rmnet_shs] [ 3302.102873] rmnet_shs_dev_notify_cb+0x378/0x3e0 [rmnet_shs] [ 3302.102892] raw_notifier_call_chain+0x3c/0x68 [ 3302.102909] register_netdevice+0x374/0x560 [ 3302.102934] rmnet_vnd_newlink+0x6c/0xe8 [ 3302.102942] rmnet_newlink+0x9c/0x198 [ 3302.102950] rtnl_newlink+0x648/0x7b0 [ 3302.102960] rtnetlink_rcv_msg+0x270/0x388 mutex_lock(&rtnl_mutex); Change-Id: Ib71de0cb4617477cab40a7f42154584765e30c2b Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs_config.c | 9 +++++++++ drivers/rmnet/shs/rmnet_shs_wq.c | 5 ----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/rmnet/shs/rmnet_shs_config.c b/drivers/rmnet/shs/rmnet_shs_config.c index a268c989a69e..e6b400241a47 100644 --- a/drivers/rmnet/shs/rmnet_shs_config.c +++ b/drivers/rmnet/shs/rmnet_shs_config.c @@ -20,6 +20,7 @@ #include "rmnet_shs_config.h" #include "rmnet_shs.h" #include "rmnet_shs_wq.h" +#include "rmnet_shs_wq_genl.h" MODULE_LICENSE("GPL v2"); @@ -51,6 +52,11 @@ int __init rmnet_shs_module_init(void) pr_info("%s(): Starting rmnet SHS module\n", __func__); trace_rmnet_shs_high(RMNET_SHS_MODULE, RMNET_SHS_MODULE_INIT, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); + + if (rmnet_shs_wq_genl_init()) { + rm_err("%s", "SHS_GNL: Failed to init generic netlink"); + } + return register_netdevice_notifier(&rmnet_shs_dev_notifier); } @@ -60,6 +66,9 @@ void __exit rmnet_shs_module_exit(void) trace_rmnet_shs_high(RMNET_SHS_MODULE, RMNET_SHS_MODULE_EXIT, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); unregister_netdevice_notifier(&rmnet_shs_dev_notifier); + + rmnet_shs_wq_genl_deinit(); + pr_info("%s(): Exiting rmnet SHS module\n", __func__); } diff --git a/drivers/rmnet/shs/rmnet_shs_wq.c b/drivers/rmnet/shs/rmnet_shs_wq.c index 09aeed7ef392..298058c5b52e 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq.c +++ b/drivers/rmnet/shs/rmnet_shs_wq.c @@ -1989,7 +1989,6 @@ void rmnet_shs_wq_exit(void) if (!rmnet_shs_wq || !rmnet_shs_delayed_wq) return; - rmnet_shs_wq_genl_deinit(); rmnet_shs_wq_mem_deinit(); trace_rmnet_shs_wq_high(RMNET_SHS_WQ_EXIT, RMNET_SHS_WQ_EXIT_START, @@ -2078,10 +2077,6 @@ void rmnet_shs_wq_init(struct net_device *dev) INIT_DEFERRABLE_WORK(&rmnet_shs_delayed_wq->wq, rmnet_shs_wq_process_wq); - if (rmnet_shs_wq_genl_init()) { - rm_err("%s", "SHS_GNL: Failed to init generic netlink"); - } - trace_rmnet_shs_wq_high(RMNET_SHS_WQ_INIT, RMNET_SHS_WQ_INIT_END, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); } From 25ed10526aceab5d700ffe811f78ce7c572f1eba Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Sat, 23 Nov 2019 00:13:46 -0700 Subject: [PATCH 008/208] drivers: shs: limit size copied to cached flows array to avoid globar var corruption Add limit to the number of flows copied into the gold flow and slow start flow arrays before memcpy to shared memory. Going out of bounds on the array write corrupted the global variables for the shared memory pointers. Fixes the following: [ 846.803490] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000081 [ 846.909206] Process kworker/4:1 (pid: 80, stack limit = 0xffffff800b670000) [ 846.916377] CPU: 4 PID: 80 Comm: kworker/4:1 Tainted: G S O 4.19.81+ #1 [ 846.930899] Workqueue: rmnet_shs_wq rmnet_shs_wq_process_wq [rmnet_shs] [ 846.942612] pc : rmnet_shs_wq_mem_update_cached_sorted_ss_flows+0x9c/0xf0 [rmnet_shs] [ 846.950657] lr : rmnet_shs_wq_eval_cpus_caps_and_flows+0x74/0x218 [rmnet_shs] Change-Id: Ifeee71e48fc61c4dd750eb061573beb88fcd2b7d Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs_wq_mem.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/rmnet/shs/rmnet_shs_wq_mem.c b/drivers/rmnet/shs/rmnet_shs_wq_mem.c index bec0da597d51..e80d424a9561 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq_mem.c +++ b/drivers/rmnet/shs/rmnet_shs_wq_mem.c @@ -490,6 +490,14 @@ void rmnet_shs_wq_mem_update_cached_sorted_gold_flows(struct list_head *gold_flo if (!gflow_node) continue; + if (gflow_node->rx_pps == 0) { + continue; + } + + if (idx >= RMNET_SHS_MAX_USRFLOWS) { + break; + } + rm_err("SHS_SGOLD: > flow 0x%x with pps %llu on cpu[%d]", gflow_node->hash, gflow_node->rx_pps, gflow_node->cpu_num); @@ -548,6 +556,15 @@ void rmnet_shs_wq_mem_update_cached_sorted_ss_flows(struct list_head *ss_flows) if (!ssflow_node) continue; + + if (ssflow_node->rx_pps == 0) { + continue; + } + + if (idx >= RMNET_SHS_MAX_USRFLOWS) { + break; + } + rm_err("SHS_SLOW: > flow 0x%x with pps %llu on cpu[%d]", ssflow_node->hash, ssflow_node->rx_pps, ssflow_node->cpu_num); From 13f8a53d34291bb572145e1bfac6b1767c74fd3b Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Tue, 15 Oct 2019 17:59:59 +0530 Subject: [PATCH 009/208] qcacld-3.0: Add driver command to request ANI level The ANI level determines how well the device is coping with interference in the wireless environment. Add support in the driver to query the ANI level from the firmware and populate it for userspace entities to use. Change-Id: I54934f670aa11737e11eca4d64e12f9dffb4f430 CRs-Fixed: 2554674 --- Kbuild | 5 + configs/default_defconfig | 3 + core/hdd/inc/wlan_hdd_power.h | 30 +++++- core/hdd/src/wlan_hdd_ioctl.c | 170 ++++++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_power.c | 110 ++++++++++++++++++++++ core/mac/inc/ani_global.h | 11 +++ core/sme/inc/csr_api.h | 3 + core/sme/inc/sme_api.h | 19 ++++ core/sme/src/common/sme_api.c | 24 +++++ core/wma/inc/wma.h | 13 +++ core/wma/inc/wma_internal.h | 14 +++ core/wma/src/wma_features.c | 47 ++++++++++ core/wma/src/wma_main.c | 12 +++ 13 files changed, 460 insertions(+), 1 deletion(-) diff --git a/Kbuild b/Kbuild index 46b8df480375..330829773e2b 100644 --- a/Kbuild +++ b/Kbuild @@ -2046,6 +2046,11 @@ endif cppflags-$(CONFIG_WLAN_FEATURE_11AX) += -DWLAN_FEATURE_11AX cppflags-$(CONFIG_WLAN_FEATURE_11AX) += -DWLAN_FEATURE_11AX_BSS_COLOR +#Enable support to get ANI value +ifeq ($(CONFIG_ANI_LEVEL_REQUEST), y) +cppflags-y += -DFEATURE_ANI_LEVEL_REQUEST +endif + # Dummy flag for WIN/MCL converged data path compilation cppflags-y += -DDP_PRINT_ENABLE=0 cppflags-y += -DATH_SUPPORT_WRAP=0 diff --git a/configs/default_defconfig b/configs/default_defconfig index dfc5c44ec14e..6de33c39f7c0 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -678,3 +678,6 @@ CONFIG_FEATURE_BECN_STATS := y ifeq ($(CONFIG_ARCH_QCS405), y) CONFIG_QCACLD_FEATURE_MPTA_HELPER := y endif + +#Enable support to get ANI level +CONFIG_ANI_LEVEL_REQUEST := y diff --git a/core/hdd/inc/wlan_hdd_power.h b/core/hdd/inc/wlan_hdd_power.h index fc8f4847c300..e8675af1ed2e 100644 --- a/core/hdd/inc/wlan_hdd_power.h +++ b/core/hdd/inc/wlan_hdd_power.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012, 2014-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -126,6 +126,18 @@ struct pkt_filter_cfg { #endif +#ifdef FEATURE_ANI_LEVEL_REQUEST +/** + * ani_priv - structure to store the priv data for get ani request + * @num_freq: number of freq received from the FW + * @ani: data received from the FW + */ +struct ani_priv { + uint32_t num_freq; + struct wmi_host_ani_level_event *ani; +}; +#endif + /** * enum suspend_resume_state - Suspend resume state * @HDD_WLAN_EARLY_SUSPEND: Early suspend state. @@ -506,4 +518,20 @@ hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev, return 0; } #endif /* WLAN_SUSPEND_RESUME_TEST */ + +#ifdef FEATURE_ANI_LEVEL_REQUEST +/** + * wlan_hdd_get_ani_level() - Wrapper to call API to fetch ani level + * @adapter: pointer to HDD adapter + * @ani: pointer to structure storing ani level for channels + * @parsed_freqs: parsed freqs from the get ani command + * @num_freqs: number of parsed channels + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_hdd_get_ani_level(struct hdd_adapter *adapter, + struct wmi_host_ani_level_event *ani, + uint32_t *parsed_freqs, + uint8_t num_freqs); +#endif /* FEATURE_ANI_LEVEL_REQUEST */ #endif /* __WLAN_HDD_POWER_H */ diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 89c5a1064651..50fdb22aa14c 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -7566,6 +7566,175 @@ static int drv_cmd_get_disable_chan_list(struct hdd_adapter *adapter, return 0; } #endif + +#ifdef FEATURE_ANI_LEVEL_REQUEST +static int drv_cmd_get_ani_level(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + char *extra; + int copied_length = 0, j, temp_int, ret = 0; + uint8_t *param, num_freqs, num_recv_channels; + uint32_t parsed_freqs[MAX_NUM_FREQS_FOR_ANI_LEVEL]; + struct wmi_host_ani_level_event ani[MAX_NUM_FREQS_FOR_ANI_LEVEL]; + size_t user_size = priv_data->total_len; + + hdd_debug("Received Command to get ANI level"); + + param = strnchr(command, strlen(command), ' '); + + /* No argument after the command */ + if (!param) + return -EINVAL; + + /* No space after the command */ + else if (SPACE_ASCII_VALUE != *param) + return -EINVAL; + + param++; + + /* Removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param)) + param++; + + /*no argument followed by spaces */ + if ('\0' == *param) + return -EINVAL; + + /* Getting the first argument ie the number of channels */ + if (sscanf(param, "%d ", &temp_int) != 1) { + hdd_err("Cannot get number of freq from input"); + return -EINVAL; + } + + if (temp_int < 0 || temp_int > MAX_NUM_FREQS_FOR_ANI_LEVEL) { + hdd_err("Invalid Number of channel received"); + return -EINVAL; + } + + hdd_debug("Number of freq to fetch ANI level are: %d", temp_int); + + if (!temp_int) + return 0; + + num_freqs = temp_int; + + for (j = 0; j < num_freqs; j++) { + /* + * Param pointing to the beginning of first space + * after number of channels. + */ + param = strpbrk(param, " "); + /*no channel list after the number of channels argument*/ + if (!param) { + hdd_err("Invalid No of freq provided in the list"); + ret = -EINVAL; + goto parse_failed; + } + + param++; + + /* Removing empty space */ + while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param)) + param++; + + if ('\0' == *param) { + hdd_err("No freq is provided in the list"); + ret = -EINVAL; + goto parse_failed; + } + + if (sscanf(param, "%d ", &temp_int) != 1) { + hdd_err("Cannot read freq number"); + ret = -EINVAL; + goto parse_failed; + } + + hdd_debug("channel_freq[%d] = %d", j, temp_int); + parsed_freqs[j] = temp_int; + } + + /* Extra arguments check */ + param = strpbrk(param, " "); + if (param) { + while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param)) + param++; + + if ('\0' != *param) { + hdd_err("Invalid argument received"); + ret = -EINVAL; + goto parse_failed; + } + } + + qdf_mem_zero(ani, sizeof(ani)); + hdd_debug("num_freq: %d", num_freqs); + if (QDF_IS_STATUS_ERROR(wlan_hdd_get_ani_level(adapter, ani, + parsed_freqs, + num_freqs))) { + hdd_err("Unable to retrieve ani level"); + return -EINVAL; + } + + extra = qdf_mem_malloc(user_size); + if (!extra) { + hdd_err("memory allocation failed"); + ret = -ENOMEM; + goto parse_failed; + } + + /* + * Find the number of channels that are populated. If freq is not + * filled then stop count there + */ + for (num_recv_channels = 0; + (num_recv_channels < num_freqs && + ani[num_recv_channels].chan_freq); num_recv_channels++) + ; + + for (j = 0; j < num_recv_channels; j++) { + /* Sanity check for ANI level validity */ + if (ani[j].ani_level > MAX_ANI_LEVEL) + continue; + + copied_length += scnprintf(extra + copied_length, + user_size - copied_length, "%d:%d\n", + ani[j].chan_freq, ani[j].ani_level); + } + + if (copied_length == 0) { + hdd_err("ANI level not fetched"); + ret = -EINVAL; + goto free; + } + + hdd_debug("data: %s", extra); + + if (copy_to_user(priv_data->buf, extra, copied_length + 1)) { + hdd_err("failed to copy data to user buffer"); + ret = -EFAULT; + goto free; + } + +free: + qdf_mem_free(extra); + +parse_failed: + return ret; +} + +#else +static int drv_cmd_get_ani_level(struct hdd_adapter *adapter, + struct hdd_context *hdd_ctx, + uint8_t *command, + uint8_t command_len, + struct hdd_priv_data *priv_data) +{ + return 0; +} +#endif /* * The following table contains all supported WLAN HDD * IOCTL driver commands and the handler for each of them. @@ -7679,6 +7848,7 @@ static const struct hdd_drv_cmd hdd_drv_cmds[] = { {"GETANTENNAMODE", drv_cmd_get_antenna_mode, false}, {"SET_DISABLE_CHANNEL_LIST", drv_cmd_set_disable_chan_list, true}, {"GET_DISABLE_CHANNEL_LIST", drv_cmd_get_disable_chan_list, false}, + {"GET_ANI_LEVEL", drv_cmd_get_ani_level, false}, {"STOP", drv_cmd_dummy, false}, /* Deprecated commands */ {"RXFILTER-START", drv_cmd_dummy, false}, diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 035fc259398f..d2091aa9132b 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -77,6 +77,7 @@ #include "wlan_ipa_ucfg_api.h" #include #include "wlan_p2p_ucfg_api.h" +#include "wlan_osif_request_manager.h" /* Preprocessor definitions and constants */ #ifdef QCA_WIFI_NAPIER_EMULATION @@ -2148,6 +2149,7 @@ int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, #ifdef QCA_SUPPORT_CP_STATS static void wlan_hdd_get_tx_power(struct hdd_adapter *adapter, int *dbm) + { wlan_cfg80211_mc_cp_stats_get_tx_power(adapter->vdev, dbm); } @@ -2158,6 +2160,114 @@ static void wlan_hdd_get_tx_power(struct hdd_adapter *adapter, int *dbm) *dbm = adapter->hdd_stats.class_a_stat.max_pwr; } #endif + +#ifdef FEATURE_ANI_LEVEL_REQUEST +static void hdd_get_ani_level_cb(struct wmi_host_ani_level_event *ani, + uint8_t num, void *context) +{ + struct osif_request *request; + struct ani_priv *priv; + uint8_t min_recv_freqs = QDF_MIN(num, MAX_NUM_FREQS_FOR_ANI_LEVEL); + + request = osif_request_get(context); + if (!request) { + hdd_err("Obsolete request"); + return; + } + + /* propagate response back to requesting thread */ + priv = osif_request_priv(request); + priv->ani = qdf_mem_malloc(min_recv_freqs * + sizeof(struct wmi_host_ani_level_event)); + if (!priv->ani) + goto complete; + + priv->num_freq = min_recv_freqs; + qdf_mem_copy(priv->ani, ani, + min_recv_freqs * sizeof(struct wmi_host_ani_level_event)); + +complete: + osif_request_complete(request); + osif_request_put(request); +} + +/** + * wlan_hdd_get_ani_level_dealloc() - Dealloc mem allocated in priv data + * @priv: the priv data + * + * Return: None + */ +static void wlan_hdd_get_ani_level_dealloc(void *priv) +{ + struct ani_priv *ani = priv; + + if (ani->ani) + qdf_mem_free(ani->ani); +} + +QDF_STATUS wlan_hdd_get_ani_level(struct hdd_adapter *adapter, + struct wmi_host_ani_level_event *ani, + uint32_t *parsed_freqs, + uint8_t num_freqs) +{ + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + int ret; + QDF_STATUS status; + void *cookie; + struct osif_request *request; + struct ani_priv *priv; + static const struct osif_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = 1000, + .dealloc = wlan_hdd_get_ani_level_dealloc, + }; + + if (!hdd_ctx) { + hdd_err("Invalid HDD context"); + return QDF_STATUS_E_INVAL; + } + + request = osif_request_alloc(¶ms); + if (!request) { + hdd_err("Request allocation failure"); + return QDF_STATUS_E_NOMEM; + } + cookie = osif_request_cookie(request); + + status = sme_get_ani_level(hdd_ctx->mac_handle, parsed_freqs, + num_freqs, hdd_get_ani_level_cb, cookie); + + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Unable to retrieve ani level"); + goto complete; + } else { + /* request was sent -- wait for the response */ + ret = osif_request_wait_for_response(request); + if (ret) { + hdd_err("SME timed out while retrieving ANI level"); + status = QDF_STATUS_E_TIMEOUT; + goto complete; + } + } + + priv = osif_request_priv(request); + + qdf_mem_copy(ani, priv->ani, sizeof(struct wmi_host_ani_level_event) * + priv->num_freq); + +complete: + /* + * either we never sent a request, we sent a request and + * received a response or we sent a request and timed out. + * regardless we are done with the request. + */ + osif_request_put(request); + + hdd_exit(); + return status; +} +#endif + /** * __wlan_hdd_cfg80211_get_txpower() - get TX power * @wiphy: Pointer to wiphy diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index 4cc764004467..d65d7aae0d1c 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -815,6 +815,14 @@ struct mgmt_beacon_probe_filter { uint8_t sap_channel[SIR_MAX_SUPPORTED_BSS]; }; +#ifdef FEATURE_ANI_LEVEL_REQUEST +struct ani_level_params { + void (*ani_level_cb)(struct wmi_host_ani_level_event *ani, uint8_t num, + void *context); + void *context; +}; +#endif + /* ------------------------------------------------------------------- */ /* / MAC Sirius parameter structure */ typedef struct sAniSirGlobal { @@ -890,6 +898,9 @@ typedef struct sAniSirGlobal { /* Beacon stats enabled/disabled from ini */ bool enable_beacon_reception_stats; uint32_t ft_akm_service_bitmap; +#ifdef FEATURE_ANI_LEVEL_REQUEST + struct ani_level_params ani_params; +#endif } tAniSirGlobal; #ifdef FEATURE_WLAN_TDLS diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index cf002792141c..b180b76197f0 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1819,4 +1819,7 @@ csr_get_channel_status(tpAniSirGlobal mac, uint32_t channel_id); * Return: none */ void csr_clear_channel_status(tpAniSirGlobal mac); + +typedef void (*csr_ani_callback)(int8_t *ani, void *context); + #endif diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index d9969c5c7c6d..b1e63d165ae7 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -3003,4 +3003,23 @@ QDF_STATUS sme_roam_control_restore_default_config(mac_handle_t mac_handle, */ QDF_STATUS sme_set_disconnect_ies(mac_handle_t mac_handle, uint8_t vdev_id, uint8_t *ie_data, uint16_t ie_len); + +#ifdef FEATURE_ANI_LEVEL_REQUEST +/* + * sme_get_ani_level() - + * A wrapper function that client calls to register a callback to get ani level + * + * @mac_handle - pointer to mac handle + * @freqs - frequencies for which ANI level has to be fetched + * @num_freqs - number of frequencies + * @callback - SME sends back the ani level using the callback + * @context - user context to be passed back along with the callback + * + * Return: QDF_STATUS + */ +QDF_STATUS sme_get_ani_level(mac_handle_t mac_handle, uint32_t *freqs, + uint8_t num_freqs, void (*callback)( + struct wmi_host_ani_level_event *ani, uint8_t num, + void *context), void *context); +#endif /* FEATURE_ANI_LEVEL_REQUEST */ #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index d12b8a6619c2..487cf25f07be 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -16910,3 +16910,27 @@ QDF_STATUS sme_set_disconnect_ies(mac_handle_t mac_handle, uint8_t vdev_id, wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); return QDF_STATUS_SUCCESS; } + +#ifdef FEATURE_ANI_LEVEL_REQUEST +QDF_STATUS sme_get_ani_level(mac_handle_t mac_handle, uint32_t *freqs, + uint8_t num_freqs, void (*callback)( + struct wmi_host_ani_level_event *ani, uint8_t num, + void *context), void *context) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + tpAniSirGlobal mac = PMAC_STRUCT(mac_handle); + void *wma_handle; + + wma_handle = cds_get_context(QDF_MODULE_ID_WMA); + if (!wma_handle) { + sme_err("wma handle is NULL"); + return QDF_STATUS_E_FAILURE; + } + + mac->ani_params.ani_level_cb = callback; + mac->ani_params.context = context; + + status = wma_send_ani_level_request(wma_handle, freqs, num_freqs); + return status; +} +#endif /* FEATURE_ANI_LEVEL_REQUEST */ diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index d4adef0904b5..3c138b9c3512 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -2565,4 +2565,17 @@ void wma_check_and_set_wake_timer(uint32_t time); */ void wma_force_objmgr_vdev_peer_cleanup(tp_wma_handle wma, uint8_t vdev_id); +#ifdef FEATURE_ANI_LEVEL_REQUEST +/** + * wma_send_ani_level_request() - Send get ani level cmd to WMI + * @wma_handle: wma handle. + * @freqs: pointer to channels for which ANI level has to be retrieved + * @num_freqs: number of channels in the above parameter + * + * Return: QDF_STATUS + */ +QDF_STATUS wma_send_ani_level_request(tp_wma_handle wma_handle, + uint32_t *freqs, uint8_t num_freqs); +#endif /* FEATURE_ANI_LEVEL_REQUEST */ #endif + diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 78d934614109..8b5d57a3872f 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1474,4 +1474,18 @@ int wma_cold_boot_cal_event_handler(void *wma_ctx, uint8_t *event_buff, */ QDF_STATUS wma_set_roam_triggers(tp_wma_handle wma_handle, struct roam_triggers *triggers); + +/** + * wma_get_ani_level_evt_handler - event handler to fetch ani level + * @handle: the wma handle + * @event_buf: buffer with event + * @len: buffer length + * + * This function receives ani level from firmware and passes the event + * to upper layer + * + * Return: 0 on success + */ +int wma_get_ani_level_evt_handler(void *handle, uint8_t *event_buf, + uint32_t len); #endif diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index c6e7d7eab33f..5393d10273d9 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -6099,3 +6099,50 @@ int wma_vdev_bss_color_collision_info_handler(void *handle, return 0; } + +#ifdef FEATURE_ANI_LEVEL_REQUEST +int wma_get_ani_level_evt_handler(void *handle, uint8_t *event_buf, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + struct wmi_host_ani_level_event *ani = NULL; + uint32_t num_freqs = 0; + QDF_STATUS status; + tpAniSirGlobal pmac; + int ret = 0; + + pmac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE); + if (!pmac || !wma) { + WMA_LOGE(FL("Invalid pmac or wma")); + return -EINVAL; + } + + status = wmi_unified_extract_ani_level(wma->wmi_handle, event_buf, + &ani, &num_freqs); + + if (QDF_IS_STATUS_ERROR(status)) { + WMA_LOGE("%s: Failed to extract ani level", __func__); + return -EINVAL; + } + + if (!pmac->ani_params.ani_level_cb) { + WMA_LOGE(FL("Invalid ani_level_cb")); + ret = -EINVAL; + goto free; + } + + pmac->ani_params.ani_level_cb(ani, num_freqs, + pmac->ani_params.context); + +free: + qdf_mem_free(ani); + return ret; +} +#else +int wma_get_ani_level_evt_handler(void *handle, uint8_t *event_buf, + uint32_t len) +{ + return 0; +} +#endif + diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 26c87ac379b0..53b630c1f8e1 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3685,6 +3685,10 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, wma_pdev_div_info_evt_handler, WMA_RX_WORK_CTX); + wmi_unified_register_event_handler(wma_handle->wmi_handle, + wmi_get_ani_level_event_id, + wma_get_ani_level_evt_handler, + WMA_RX_WORK_CTX); wma_register_debug_callback(); wifi_pos_register_get_phy_mode_cb(wma_handle->psoc, @@ -9336,3 +9340,11 @@ QDF_STATUS wma_config_bmiss_bcnt_params(uint32_t vdev_id, uint32_t first_cnt, return status; } +#ifdef FEATURE_ANI_LEVEL_REQUEST +QDF_STATUS wma_send_ani_level_request(tp_wma_handle wma_handle, + uint32_t *freqs, uint8_t num_freqs) +{ + return wmi_unified_ani_level_cmd_send(wma_handle->wmi_handle, freqs, + num_freqs); +} +#endif From e575645180edc5a9ad9ec4fce0633193f3d0b689 Mon Sep 17 00:00:00 2001 From: Sean Tranchetti Date: Mon, 9 Dec 2019 17:07:27 -0700 Subject: [PATCH 010/208] drivers: rmnet_perf: Take lock during DL marker handling Since handling DL markers can result in flushing the various flow nodes, the rmnet_perf lock must be taken to ensure synchronization with the rest of the driver. During hotplug scenarios, a regular flush could be going on while a DL marker handling callback is invoked. In certain cases, the callback can proceed farther than it should, and send a second pointer to a previously flushed descriptor down the call chain. This phantom descriptor can cause various problems, but the most "common" case seen is a NULL dereference such as the following: rmnet_frag_deliver+0x110/0x730 rmnet_perf_core_send_desc+0x44/0x50 [rmnet_perf] rmnet_perf_opt_flush_single_flow_node+0x220/0x430 [rmnet_perf] rmnet_perf_opt_flush_all_flow_nodes+0x40/0x70 [rmnet_perf] rmnet_perf_core_handle_map_control_start+0x38/0x130 [rmnet_perf] rmnet_map_dl_hdr_notify_v2+0x3c/0x58 rmnet_frag_flow_command+0x104/0x120 rmnet_frag_ingress_handler+0x2c8/0x3c8 rmnet_rx_handler+0x188/0x238 Change-Id: I79cb626732358c827d6c9df4239c0c55821bd3a5 Signed-off-by: Sean Tranchetti --- drivers/rmnet/perf/rmnet_perf_core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/rmnet/perf/rmnet_perf_core.c b/drivers/rmnet/perf/rmnet_perf_core.c index 4166c5de8044..ee2a97857a08 100644 --- a/drivers/rmnet/perf/rmnet_perf_core.c +++ b/drivers/rmnet/perf/rmnet_perf_core.c @@ -498,6 +498,7 @@ rmnet_perf_core_handle_map_control_start(struct rmnet_map_dl_ind_hdr *dlhdr) struct rmnet_perf *perf = rmnet_perf_config_get_perf(); struct rmnet_perf_core_burst_marker_state *bm_state; + rmnet_perf_core_grab_lock(); bm_state = perf->core_meta->bm_state; /* if we get two starts in a row, without an end, then we flush * and carry on @@ -516,6 +517,7 @@ rmnet_perf_core_handle_map_control_start(struct rmnet_map_dl_ind_hdr *dlhdr) trace_rmnet_perf_low(RMNET_PERF_MODULE, RMNET_PERF_START_DL_MRK, bm_state->expect_packets, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); + rmnet_perf_core_release_lock(); } void rmnet_perf_core_handle_map_control_end_v2(struct rmnet_map_dl_ind_trl *dltrl, @@ -529,6 +531,7 @@ void rmnet_perf_core_handle_map_control_end(struct rmnet_map_dl_ind_trl *dltrl) struct rmnet_perf *perf = rmnet_perf_config_get_perf(); struct rmnet_perf_core_burst_marker_state *bm_state; + rmnet_perf_core_grab_lock(); bm_state = perf->core_meta->bm_state; rmnet_perf_opt_flush_all_flow_nodes(); rmnet_perf_core_flush_reason_cnt[RMNET_PERF_CORE_DL_MARKER_FLUSHES]++; @@ -537,6 +540,7 @@ void rmnet_perf_core_handle_map_control_end(struct rmnet_map_dl_ind_trl *dltrl) bm_state->expect_packets = 0; trace_rmnet_perf_low(RMNET_PERF_MODULE, RMNET_PERF_END_DL_MRK, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); + rmnet_perf_core_release_lock(); } int rmnet_perf_core_validate_pkt_csum(struct sk_buff *skb, From f03a1e799b2e003b575d0506fb8a886e2237b25d Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Wed, 4 Dec 2019 08:59:50 +0530 Subject: [PATCH 011/208] qcacld-3.0: Report correct max NSS in case of DBS Currently in the driver, the NSS reported to the userspace in case of max rate reporting doesn't take into account if the hardware mode is DBS or not. This causes the NSS to remain 2 even if the connection has changed to 1x1. Add a check if the current mode is DBS or not and update the NSS accordingly. Change-Id: I66ea830c7c6483c7ce957e1276b4ac5a535b17df CRs-Fixed: 2579182 --- core/hdd/src/wlan_hdd_stats.c | 66 ++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index cb77382880a2..41eddaf6bc14 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -4359,6 +4359,36 @@ static void hdd_fill_fcs_and_mpdu_count(struct hdd_adapter *adapter, } #endif +/** + * hdd_check_and_update_nss() - Check and update NSS as per DBS capability + * @hdd_ctx: HDD Context pointer + * @tx_nss: pointer to variable storing the tx_nss + * @rx_nss: pointer to variable storing the rx_nss + * + * The parameters include the NSS obtained from the FW or static NSS. This NSS + * could be invalid in the case the current HW mode is DBS where the connection + * are 1x1. Rectify these NSS values as per the current HW mode. + * + * Return: none + */ +static void hdd_check_and_update_nss(struct hdd_context *hdd_ctx, + uint8_t *tx_nss, uint8_t *rx_nss) +{ + if ((*tx_nss > 1) && + policy_mgr_is_current_hwmode_dbs(hdd_ctx->psoc) && + !policy_mgr_is_hw_dbs_2x2_capable(hdd_ctx->psoc)) { + hdd_debug("Hw mode is DBS, Reduce tx nss(%d) to 1", *tx_nss); + (*tx_nss)--; + } + + if ((*rx_nss > 1) && + policy_mgr_is_current_hwmode_dbs(hdd_ctx->psoc) && + !policy_mgr_is_hw_dbs_2x2_capable(hdd_ctx->psoc)) { + hdd_debug("Hw mode is DBS, Reduce tx nss(%d) to 1", *rx_nss); + (*rx_nss)--; + } +} + /** * wlan_hdd_get_sta_stats() - get aggregate STA stats * @wiphy: wireless phy @@ -4459,21 +4489,7 @@ static int wlan_hdd_get_sta_stats(struct wiphy *wiphy, tx_nss = adapter->hdd_stats.class_a_stat.tx_nss; rx_nss = adapter->hdd_stats.class_a_stat.rx_nss; - if ((tx_nss > 1) && - policy_mgr_is_current_hwmode_dbs(hdd_ctx->psoc) && - !policy_mgr_is_hw_dbs_2x2_capable(hdd_ctx->psoc)) { - hdd_debug("Hw mode is DBS, Reduce nss(%d) to 1", - tx_nss); - tx_nss--; - } - - if ((rx_nss > 1) && - policy_mgr_is_current_hwmode_dbs(hdd_ctx->psoc) && - !policy_mgr_is_hw_dbs_2x2_capable(hdd_ctx->psoc)) { - hdd_debug("Hw mode is DBS, Reduce nss(%d) to 1", - rx_nss); - rx_nss--; - } + hdd_check_and_update_nss(hdd_ctx, &tx_nss, &rx_nss); if (eHDD_LINK_SPEED_REPORT_ACTUAL == pCfg->reportMaxLinkSpeed) { /* Get current rate flags if report actual */ @@ -4512,8 +4528,18 @@ static int wlan_hdd_get_sta_stats(struct wiphy *wiphy, hdd_set_rate_bw(&sinfo->txrate, HDD_RATE_BW_20); if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed) { - bool tx_rate_calc; - bool rx_rate_calc; + bool tx_rate_calc, rx_rate_calc; + uint8_t tx_nss_max, rx_nss_max; + + /* + * Take static NSS for reporting max rates. NSS from the FW + * is not reliable as it changes as per the environment + * quality. + */ + tx_nss_max = wlan_vdev_mlme_get_nss(adapter->vdev); + rx_nss_max = wlan_vdev_mlme_get_nss(adapter->vdev); + + hdd_check_and_update_nss(hdd_ctx, &tx_nss_max, &rx_nss_max); tx_rate_calc = hdd_report_max_rate(mac_handle, pCfg, &sinfo->txrate, @@ -4521,8 +4547,7 @@ static int wlan_hdd_get_sta_stats(struct wiphy *wiphy, tx_rate_flags, tx_mcs_index, my_tx_rate, - wlan_vdev_mlme_get_nss( - adapter->vdev)); + tx_nss_max); rx_rate_calc = hdd_report_max_rate(mac_handle, pCfg, &sinfo->rxrate, @@ -4530,8 +4555,7 @@ static int wlan_hdd_get_sta_stats(struct wiphy *wiphy, rx_rate_flags, rx_mcs_index, my_rx_rate, - wlan_vdev_mlme_get_nss( - adapter->vdev)); + rx_nss_max); if (!tx_rate_calc || !rx_rate_calc) /* Keep GUI happy */ From 1862dbebf2098b1295a64369b25c1482ef5379ee Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Mon, 18 Nov 2019 15:21:59 +0530 Subject: [PATCH 012/208] qcacld-3.0: Populate correct RSSI value for Monitor packets In Monitor Mode, RSSI is always -96 for packets in TCPDUMP. Populate the correct RSSI value in Monitor Mode. Change-Id: Iba9fe7091043d27828f4742058ed3d389cde7e26 CRs-Fixed: 2568129 --- core/dp/htt/htt_monitor_rx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/dp/htt/htt_monitor_rx.c b/core/dp/htt/htt_monitor_rx.c index 25607641d775..5e23a4656a34 100644 --- a/core/dp/htt/htt_monitor_rx.c +++ b/core/dp/htt/htt_monitor_rx.c @@ -492,6 +492,7 @@ static void htt_rx_mon_get_rx_status(htt_pdev_handle pdev, rx_status->chan_flags = channel_flags; rx_status->ant_signal_db = rx_desc->ppdu_start.rssi_comb; + rx_status->rssi_comb = rx_desc->ppdu_start.rssi_comb; } /** From ef25435527044791813b33c8c8b9f8fa98139a09 Mon Sep 17 00:00:00 2001 From: Abhishek Ambure Date: Wed, 27 Nov 2019 19:54:26 +0530 Subject: [PATCH 013/208] qcacld-3.0: Set RSN capability flag for SAP peers Peer assoc command send to firmware updates peer params in firmware ex. peer_new_assoc, peer_associd, need_gtk_2_way etc. If RSN capability flags are present in peer assoc request of SAP and P2P-Go peers, host updates need_gtk_2_way, need_ptk_4_way peer assoc params to firmware. If need_gtk_2_way, need_ptk_4_way params are not updated for RSN capable peers of SAP/P2P-Go, firmware is not able to hanlde data packets(HTT) before the key installation(WMI) is successful. Change-Id: I0a24aab3ac4ff4ca061782f6a4d0ba62dd227b04 CRs-Fixed: 2575133 --- core/mac/src/pe/lim/lim_assoc_utils.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index 76855311b788..1f2460c2c92b 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -2545,6 +2545,20 @@ lim_add_sta(tpAniSirGlobal mac_ctx, add_sta_params->stbc_capable = 0; } + if (session_entry->pePersona == QDF_SAP_MODE || + session_entry->pePersona == QDF_P2P_GO_MODE) { + if (session_entry->parsedAssocReq) { + uint16_t aid = sta_ds->assocId; + /* Get a copy of the already parsed Assoc Request */ + assoc_req = + (tpSirAssocReq) session_entry->parsedAssocReq[aid]; + + add_sta_params->wpa_rsn = assoc_req->rsnPresent; + add_sta_params->wpa_rsn |= + (assoc_req->wpaPresent << 1); + } + } + lim_update_he_stbc_capable(add_sta_params); msg_q.type = WMA_ADD_STA_REQ; From e9ebf9a3ef0659b6b2fcbb44b1c5770a4f16829e Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Tue, 3 Dec 2019 14:14:07 +0530 Subject: [PATCH 014/208] qcacld-3.0: Protect pktlog under mutex to avoid possible race conditions Protect pktlog funcitonality under given mutex to avoid possible race condition between pktlog_release/pktlog_open and pktlogmod_exit. Also call pktlogmod_exit before calling wdi_event_detach to avoid accessing freed memory in pktlog release. Change-Id: I452af523338788447f5c2764e883165237083f7d CRs-Fixed: 2087777 --- core/dp/txrx/ol_txrx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index c5233556ea23..86a6ea0a063f 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -2306,6 +2306,8 @@ static void ol_txrx_pdev_pre_detach(struct cdp_pdev *ppdev, int force) OL_RX_REORDER_TRACE_DETACH(pdev); OL_RX_PN_TRACE_DETACH(pdev); + htt_pktlogmod_exit(pdev); + /* * WDI event detach */ @@ -2347,8 +2349,6 @@ static void ol_txrx_pdev_detach(struct cdp_pdev *ppdev, int force) return; } - htt_pktlogmod_exit(pdev); - qdf_spin_lock_bh(&pdev->req_list_spinlock); if (pdev->req_list_depth > 0) ol_txrx_err( From e71cedcb6fd7478c2457cfac73afbd579c8754ad Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Tue, 10 Dec 2019 18:57:13 -0700 Subject: [PATCH 015/208] drivers: shs: protect mmap file operations using shs ep lock This adds synchronization for the mmap file operation so that an mmap will only occur after a succesful open and will not occur after a release. This is done by using a fault handler for each shared memory file and checking the respective global variable inside of the ep lock. Change-Id: I955dfc8e745b1e275328721e9934ef8c020d8fa3 Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs_wq_mem.c | 122 +++++++++++++++++++++++---- 1 file changed, 106 insertions(+), 16 deletions(-) diff --git a/drivers/rmnet/shs/rmnet_shs_wq_mem.c b/drivers/rmnet/shs/rmnet_shs_wq_mem.c index 1675517561c4..33abf80e0cf5 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq_mem.c +++ b/drivers/rmnet/shs/rmnet_shs_wq_mem.c @@ -44,32 +44,122 @@ static void rmnet_shs_vm_close(struct vm_area_struct *vma) return; } -static int rmnet_shs_vm_fault(struct vm_fault *vmf) +static int rmnet_shs_vm_fault_caps(struct vm_fault *vmf) { struct page *page = NULL; struct rmnet_shs_mmap_info *info; rmnet_shs_wq_ep_lock_bh(); - info = (struct rmnet_shs_mmap_info *) vmf->vma->vm_private_data; - if (info->data) { - page = virt_to_page(info->data); - get_page(page); - vmf->page = page; + if (cap_shared) { + info = (struct rmnet_shs_mmap_info *) vmf->vma->vm_private_data; + if (info->data) { + page = virt_to_page(info->data); + get_page(page); + vmf->page = page; + } else { + rmnet_shs_wq_ep_unlock_bh(); + return VM_FAULT_SIGSEGV; + } + } else { + rmnet_shs_wq_ep_unlock_bh(); + return VM_FAULT_SIGSEGV; } rmnet_shs_wq_ep_unlock_bh(); return 0; } -static const struct vm_operations_struct rmnet_shs_vm_ops = { + +static int rmnet_shs_vm_fault_g_flows(struct vm_fault *vmf) +{ + struct page *page = NULL; + struct rmnet_shs_mmap_info *info; + + rmnet_shs_wq_ep_lock_bh(); + if (gflow_shared) { + info = (struct rmnet_shs_mmap_info *) vmf->vma->vm_private_data; + if (info->data) { + page = virt_to_page(info->data); + get_page(page); + vmf->page = page; + } else { + rmnet_shs_wq_ep_unlock_bh(); + return VM_FAULT_SIGSEGV; + } + } else { + rmnet_shs_wq_ep_unlock_bh(); + return VM_FAULT_SIGSEGV; + + } + rmnet_shs_wq_ep_unlock_bh(); + + return 0; +} + +static int rmnet_shs_vm_fault_ss_flows(struct vm_fault *vmf) +{ + struct page *page = NULL; + struct rmnet_shs_mmap_info *info; + + rmnet_shs_wq_ep_lock_bh(); + if (ssflow_shared) { + info = (struct rmnet_shs_mmap_info *) vmf->vma->vm_private_data; + if (info->data) { + page = virt_to_page(info->data); + get_page(page); + vmf->page = page; + } else { + rmnet_shs_wq_ep_unlock_bh(); + return VM_FAULT_SIGSEGV; + } + } else { + rmnet_shs_wq_ep_unlock_bh(); + return VM_FAULT_SIGSEGV; + } + rmnet_shs_wq_ep_unlock_bh(); + + return 0; +} + +static const struct vm_operations_struct rmnet_shs_vm_ops_caps = { .close = rmnet_shs_vm_close, .open = rmnet_shs_vm_open, - .fault = rmnet_shs_vm_fault, + .fault = rmnet_shs_vm_fault_caps, }; -static int rmnet_shs_mmap(struct file *filp, struct vm_area_struct *vma) +static const struct vm_operations_struct rmnet_shs_vm_ops_g_flows = { + .close = rmnet_shs_vm_close, + .open = rmnet_shs_vm_open, + .fault = rmnet_shs_vm_fault_g_flows, +}; + +static const struct vm_operations_struct rmnet_shs_vm_ops_ss_flows = { + .close = rmnet_shs_vm_close, + .open = rmnet_shs_vm_open, + .fault = rmnet_shs_vm_fault_ss_flows, +}; + +static int rmnet_shs_mmap_caps(struct file *filp, struct vm_area_struct *vma) { - vma->vm_ops = &rmnet_shs_vm_ops; + vma->vm_ops = &rmnet_shs_vm_ops_caps; + vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_private_data = filp->private_data; + + return 0; +} + +static int rmnet_shs_mmap_g_flows(struct file *filp, struct vm_area_struct *vma) +{ + vma->vm_ops = &rmnet_shs_vm_ops_g_flows; + vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_private_data = filp->private_data; + + return 0; +} + +static int rmnet_shs_mmap_ss_flows(struct file *filp, struct vm_area_struct *vma) +{ + vma->vm_ops = &rmnet_shs_vm_ops_ss_flows; vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; vma->vm_private_data = filp->private_data; @@ -226,9 +316,9 @@ static int rmnet_shs_release_caps(struct inode *inode, struct file *filp) rmnet_shs_wq_ep_lock_bh(); if (cap_shared) { info = filp->private_data; - cap_shared = NULL; free_page((unsigned long)info->data); kfree(info); + cap_shared = NULL; filp->private_data = NULL; } rmnet_shs_wq_ep_unlock_bh(); @@ -245,9 +335,9 @@ static int rmnet_shs_release_g_flows(struct inode *inode, struct file *filp) rmnet_shs_wq_ep_lock_bh(); if (gflow_shared) { info = filp->private_data; - gflow_shared = NULL; free_page((unsigned long)info->data); kfree(info); + gflow_shared = NULL; filp->private_data = NULL; } rmnet_shs_wq_ep_unlock_bh(); @@ -264,9 +354,9 @@ static int rmnet_shs_release_ss_flows(struct inode *inode, struct file *filp) rmnet_shs_wq_ep_lock_bh(); if (ssflow_shared) { info = filp->private_data; - ssflow_shared = NULL; free_page((unsigned long)info->data); kfree(info); + ssflow_shared = NULL; filp->private_data = NULL; } rmnet_shs_wq_ep_unlock_bh(); @@ -276,7 +366,7 @@ static int rmnet_shs_release_ss_flows(struct inode *inode, struct file *filp) static const struct file_operations rmnet_shs_caps_fops = { .owner = THIS_MODULE, - .mmap = rmnet_shs_mmap, + .mmap = rmnet_shs_mmap_caps, .open = rmnet_shs_open_caps, .release = rmnet_shs_release_caps, .read = rmnet_shs_read, @@ -285,7 +375,7 @@ static const struct file_operations rmnet_shs_caps_fops = { static const struct file_operations rmnet_shs_g_flows_fops = { .owner = THIS_MODULE, - .mmap = rmnet_shs_mmap, + .mmap = rmnet_shs_mmap_g_flows, .open = rmnet_shs_open_g_flows, .release = rmnet_shs_release_g_flows, .read = rmnet_shs_read, @@ -294,7 +384,7 @@ static const struct file_operations rmnet_shs_g_flows_fops = { static const struct file_operations rmnet_shs_ss_flows_fops = { .owner = THIS_MODULE, - .mmap = rmnet_shs_mmap, + .mmap = rmnet_shs_mmap_ss_flows, .open = rmnet_shs_open_ss_flows, .release = rmnet_shs_release_ss_flows, .read = rmnet_shs_read, From d789e52075f191c6779cd57f2a05d3d56ba4fcef Mon Sep 17 00:00:00 2001 From: Min Liu Date: Thu, 12 Dec 2019 15:47:27 +0800 Subject: [PATCH 016/208] qcacld-3.0: Send deauth to AP when SAE auth failed For some IOT issue on specific AP: STA failed to connect to SAE AP due to incorrect password is used. Then AP will still reject the authentication even correct password is used unless STA send deauth to AP upon authentication failure. Change-Id: I394041177425267e1b213ae468ec316e207cc0fc CRs-Fixed: 2576247 --- .../mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index e993b0f7ca2b..44c491015ad4 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -560,6 +560,21 @@ void lim_process_mlm_auth_cnf(tpAniSirGlobal mac_ctx, uint32_t *msg) MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session_entry->peSessionId, session_entry->limMlmState)); + + /* WAR for some IOT issue on specific AP: + * STA failed to connect to SAE AP due to incorrect + * password is used. Then AP will still reject the + * authentication even correct password is used unless + * STA send deauth to AP upon authentication failure. + */ + if (auth_type == eSIR_AUTH_TYPE_SAE) { + pe_debug("Send deauth for SAE auth failure"); + lim_send_deauth_mgmt_frame(mac_ctx, + auth_cnf->protStatusCode, + auth_cnf->peerMacAddr, + session_entry, false); + } + /* * Need to send Join response with * auth failure to Host. From 4c97eb38d981ac758249dff6061f4db15ea74634 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Fri, 10 Jan 2020 18:32:53 -0800 Subject: [PATCH 017/208] drivers: shs: Check bounds of stat array Ensure that the mapped CPU which SHS suggests is within the bounds of the length of the relevant stats array Change-Id: I83254cd7407231027c05665d3038e367d9545195 Signed-off-by: Conner Huff --- drivers/rmnet/shs/rmnet_shs_config.h | 3 ++- drivers/rmnet/shs/rmnet_shs_main.c | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/rmnet/shs/rmnet_shs_config.h b/drivers/rmnet/shs/rmnet_shs_config.h index dc385e48114f..e55f5f8b87b9 100644 --- a/drivers/rmnet/shs/rmnet_shs_config.h +++ b/drivers/rmnet/shs/rmnet_shs_config.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -46,6 +46,7 @@ enum rmnet_shs_crit_err_e { RMNET_SHS_WQ_INVALID_PTR_ERR, RMNET_SHS_WQ_NODE_MALLOC_ERR, RMNET_SHS_WQ_NL_SOCKET_ERR, + RMNET_SHS_CPU_FLOWS_BNDS_ERR, RMNET_SHS_CRIT_ERR_MAX }; diff --git a/drivers/rmnet/shs/rmnet_shs_main.c b/drivers/rmnet/shs/rmnet_shs_main.c index 2accd29bde09..2df4330d68ff 100755 --- a/drivers/rmnet/shs/rmnet_shs_main.c +++ b/drivers/rmnet/shs/rmnet_shs_main.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -42,6 +42,8 @@ #define GET_CTIMER(CPU) rmnet_shs_cfg.core_flush[CPU].core_timer #define SKB_FLUSH 0 +#define INCREMENT 1 +#define DECREMENT 0 /* Local Definitions and Declarations */ DEFINE_SPINLOCK(rmnet_shs_ht_splock); DEFINE_HASHTABLE(RMNET_SHS_HT, RMNET_SHS_HT_SIZE); @@ -114,13 +116,21 @@ unsigned int rmnet_shs_cpu_max_coresum[MAX_CPUS]; module_param_array(rmnet_shs_cpu_max_coresum, uint, 0, 0644); MODULE_PARM_DESC(rmnet_shs_cpu_max_coresum, "Max coresum seen of each core"); +static void rmnet_shs_change_cpu_num_flows(u16 map_cpu, bool inc) +{ + if (map_cpu < MAX_CPUS) + (inc) ? cpu_num_flows[map_cpu]++: cpu_num_flows[map_cpu]--; + else + rmnet_shs_crit_err[RMNET_SHS_CPU_FLOWS_BNDS_ERR]++; +} + void rmnet_shs_cpu_node_remove(struct rmnet_shs_skbn_s *node) { SHS_TRACE_LOW(RMNET_SHS_CPU_NODE, RMNET_SHS_CPU_NODE_FUNC_REMOVE, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); list_del_init(&node->node_id); - cpu_num_flows[node->map_cpu]--; + rmnet_shs_change_cpu_num_flows(node->map_cpu, DECREMENT); } @@ -131,7 +141,7 @@ void rmnet_shs_cpu_node_add(struct rmnet_shs_skbn_s *node, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); list_add(&node->node_id, hd); - cpu_num_flows[node->map_cpu]++; + rmnet_shs_change_cpu_num_flows(node->map_cpu, INCREMENT); } void rmnet_shs_cpu_node_move(struct rmnet_shs_skbn_s *node, @@ -141,8 +151,8 @@ void rmnet_shs_cpu_node_move(struct rmnet_shs_skbn_s *node, 0xDEF, 0xDEF, 0xDEF, 0xDEF, NULL, NULL); list_move(&node->node_id, hd); - cpu_num_flows[node->map_cpu]++; - cpu_num_flows[oldcpu]--; + rmnet_shs_change_cpu_num_flows(node->map_cpu, INCREMENT); + rmnet_shs_change_cpu_num_flows((u16) oldcpu, DECREMENT); } /* Evaluates the incoming transport protocol of the incoming skb. Determines From c9fd2eb00597fe6529b309a7fa288e2fc2e239b6 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Wed, 15 Jun 2016 12:41:31 +0800 Subject: [PATCH 018/208] qcacld-3.0: Don't indicate P2P client deletion event DUT formed P2P connection with second device and as P2P GO, trigger assert in target, supplicant get P2P client deletion event, and then DUT remove P2P GO and change interface type from P2P GO to P2P device but failed since recovery in progress. This change avoid to indicate P2P client deletion event to up layer since host will sent P2P GO stopping event to up layer. Change-Id: I2221332d062f1e5f74846187ce9b478a11b8eb9f CRs-Fixed: 2589866 --- core/hdd/src/wlan_hdd_hostapd.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index ce31aa370295..9de2cf94a735 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -2354,10 +2354,20 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, WIFI_POWER_EVENT_WAKELOCK_SAP); qdf_wake_lock_timeout_acquire(&hdd_ctx->sap_wake_lock, HDD_SAP_CLIENT_DISCONNECT_WAKE_LOCK_DURATION); - cfg80211_del_sta(dev, - (const u8 *)&pSapEvent->sapevt. - sapStationDisassocCompleteEvent.staMac. - bytes[0], GFP_KERNEL); + + /* + * Don't indicate delete station event if P2P GO and + * SSR in progress. Since supplicant will change mode + * fail and down during this time. + */ + if ((adapter->device_mode != QDF_P2P_GO_MODE) || + (!cds_is_driver_recovering())) { + cfg80211_del_sta(dev, + (const u8 *)&pSapEvent->sapevt. + sapStationDisassocCompleteEvent.staMac. + bytes[0], GFP_KERNEL); + hdd_debug("indicate sta deletion event"); + } /* Update the beacon Interval if it is P2P GO */ qdf_status = policy_mgr_change_mcc_go_beacon_interval( From 386c801cc59599a4fde962079f2daff7247e3f43 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Mon, 16 Mar 2020 16:03:25 -0700 Subject: [PATCH 019/208] drivers: rmnet: shs: Unrevert Deadlock fix Deadlock fix was reverted by mistake as part of merging. Deadlock fix was I760a51f7ff998ab610858f38cf76e577d026ff41 Deadlock issue was reintroduced as part of I6b9c9b18c30575d2b59dd76814f4b7b2a2953bc0 This change will removed the potential rmnet_ht_lock and rmnet_ep_lock deadlock like CR: 2595421 did. Change-Id: I1307d82ffa12d0cc1115baa25a19df8ada924e89 Acked-by: Raul Martinez Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs_wq.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/rmnet/shs/rmnet_shs_wq.c b/drivers/rmnet/shs/rmnet_shs_wq.c index e42b86655dd3..6e581fc134ba 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq.c +++ b/drivers/rmnet/shs/rmnet_shs_wq.c @@ -2011,9 +2011,6 @@ void rmnet_shs_wq_update_stats(void) } rmnet_shs_wq_refresh_new_flow_list(); - /*Invoke after both the locks are released*/ - rmnet_shs_wq_cleanup_hash_tbl(PERIODIC_CLEAN); - rmnet_shs_wq_debug_print_flows(); rmnet_shs_wq_filter(); } From 532378a9b6d8d06584848b602608a755cf0f5b63 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Tue, 14 Apr 2020 15:49:04 +0530 Subject: [PATCH 020/208] qcacld-3.0: Add vdev start check before sending arp_ns stats cmd to fw Add vdev start check such that host does not send ARP_NS stats command to FW when vdev is already stopped. Change-Id: Ifae00ff26a27df92cd4d09047c326bcccfdbf602 CRs-Fixed: 2651406 --- core/wma/src/wma_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 48118eb8d8af..3efc1871f595 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -7809,6 +7809,11 @@ static void wma_set_arp_req_stats(WMA_HANDLE handle, return; } + if (!wma_is_vdev_up(req_buf->vdev_id)) { + WMA_LOGD("vdev id:%d is not started", req_buf->vdev_id); + return; + } + arp_stats = (struct set_arp_stats *)req_buf; status = wmi_unified_set_arp_stats_req(wma_handle->wmi_handle, arp_stats); From ad258cad79c32a14cb5669c17727358ee62b1976 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Wed, 6 May 2020 15:26:28 +0530 Subject: [PATCH 021/208] defconfig: sm6150: Enable PM_AUTOSLEEP for QCS610 Enable PM_AUTOSLEEP needed for LPM testing on QCS610 Change-Id: I7d2225d0cf71a3d816bcfa893c4c0a6c537d87ed Signed-off-by: Avaneesh Kumar Dwivedi --- arch/arm64/configs/vendor/sdmsteppe-perf_defconfig | 1 + arch/arm64/configs/vendor/sdmsteppe_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index 84ee429cd5b1..76563a7b9f8c 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -79,6 +79,7 @@ CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y CONFIG_KRYO_PMU_WORKAROUND=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y CONFIG_PM_WAKELOCKS=y CONFIG_PM_WAKELOCKS_LIMIT=0 # CONFIG_PM_WAKELOCKS_GC is not set diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig index 2d881db14658..9653c3102fae 100644 --- a/arch/arm64/configs/vendor/sdmsteppe_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig @@ -84,6 +84,7 @@ CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y CONFIG_KRYO_PMU_WORKAROUND=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y CONFIG_PM_WAKELOCKS=y CONFIG_PM_WAKELOCKS_LIMIT=0 # CONFIG_PM_WAKELOCKS_GC is not set From 28b783167e1355f5c962406557178a70d7aa87a5 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Wed, 13 May 2020 16:36:10 +0530 Subject: [PATCH 022/208] qcacmn: Update disconnect rssi on every disconnect rssi event Currently there is a check to validate if the station is in associated state or not in the hdd lost link cp stats info cb, There is a race condition where if the disconnection happens from ap in that case the callback gets invoked before the connection state in the station context gets updated and thus the rssi on disconnect is not updated. To address above issue remove the check to validate the station state and update the rssi on disconnect irrespective of the state of the connection. Change-Id: I9cc6a08cdf0a1081adfde7a9423a665bc977cffc CRs-Fixed: 2685175 --- target_if/cp_stats/src/target_if_mc_cp_stats.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target_if/cp_stats/src/target_if_mc_cp_stats.c b/target_if/cp_stats/src/target_if_mc_cp_stats.c index f22a62036bb1..164554dc9367 100644 --- a/target_if/cp_stats/src/target_if_mc_cp_stats.c +++ b/target_if/cp_stats/src/target_if_mc_cp_stats.c @@ -222,6 +222,10 @@ static QDF_STATUS target_if_cp_stats_extract_vdev_summary_stats( dat_snr = vdev_stats.vdev_snr.dat_snr; ev->vdev_summary_stats[i].vdev_id = vdev_stats.vdev_id; + cp_stats_debug("vdev %d SNR bcn: %d data: %d", + ev->vdev_summary_stats[i].vdev_id, bcn_snr, + dat_snr); + for (j = 0; j < 4; j++) { ev->vdev_summary_stats[i].stats.tx_frm_cnt[j] = vdev_stats.tx_frm_cnt[j]; From 10d40dbd4e61b0c03fa00e70f6a503d3fc5692db Mon Sep 17 00:00:00 2001 From: spuligil Date: Sat, 2 May 2020 18:00:35 -0700 Subject: [PATCH 023/208] fw-api: CL 10345835 - update fw common interface files HTT STATS: add TQM active/inactive counts in tqm_cmn_stats Change-Id: I45641a44381591f49f147484d049e24f311b18d7 CRs-Fixed: 2262693 --- fw/htt_stats.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fw/htt_stats.h b/fw/htt_stats.h index 9c262820c984..376351c18c6a 100644 --- a/fw/htt_stats.h +++ b/fw/htt_stats.h @@ -2669,6 +2669,9 @@ typedef struct { A_UINT32 desc_threshold; A_UINT32 hwsch_tqm_invalid_status; A_UINT32 missed_tqm_gen_mpdus; + A_UINT32 tqm_active_tids; + A_UINT32 tqm_inactive_tids; + A_UINT32 tqm_active_msduq_flows; } htt_tx_tqm_cmn_stats_tlv; typedef struct { From 2d4951080c06233007446fa5986a004191756114 Mon Sep 17 00:00:00 2001 From: spuligil Date: Sat, 9 May 2020 06:00:38 -0700 Subject: [PATCH 024/208] fw-api: CL 10404614 - update fw common interface files HTT stats: add UL MIMO,OFDMA seq posted counters Change-Id: I30833bbe5baa6f1a1cd4b84342bd382b57a42013 CRs-Fixed: 2262693 --- fw/htt_stats.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fw/htt_stats.h b/fw/htt_stats.h index 376351c18c6a..674176f723df 100644 --- a/fw/htt_stats.h +++ b/fw/htt_stats.h @@ -771,6 +771,10 @@ typedef struct { A_UINT32 num_mu_peer_blacklisted; /* Num of times mu_ofdma seq posted */ A_UINT32 mu_ofdma_seq_posted; + /* Num of times UL MU MIMO seq posted */ + A_UINT32 ul_mumimo_seq_posted; + /* Num of times UL OFDMA seq posted */ + A_UINT32 ul_ofdma_seq_posted; } htt_tx_pdev_stats_cmn_tlv; #define HTT_TX_PDEV_STATS_URRN_TLV_SZ(_num_elems) (sizeof(A_UINT32) * (_num_elems)) From be0640ad1cb7f46ea3909eec9f808db8c31daaca Mon Sep 17 00:00:00 2001 From: Abhishek Ambure Date: Thu, 14 May 2020 17:17:26 +0530 Subject: [PATCH 025/208] qcacld-3.0: Don't force RSSI trigger in controlled roaming mode Host configures rssi trigger, connected ap rssi delta and rssi threshold in firmware. As rssi threshold is hit, firmware start roam scan. Firmware decreases further RSSI threshold by connected ap rssi delta if matching profile ap not found and so on. Example: STA connects to an AP and host sets rssi trigger, connected ap rssi delta=5 and rssi threshold as -25dbm. Firmware starts roam scan as the rssi threshold is hit. In the roam scan if desired profile ap is not found, decreases rssi threshold by 5dbm i.e connected ap rssi delta. Now rssi threshold becomes -30dbm and then firmware triggers roam scan and so on. Thus the rssi threshold changes dynamically when controlled roaming mode is set from userspace, to fix this do not force RSSI triggers when controlled roaming from userspace is enable. Change-Id: I1de3f71ca96de9f464d5d33b0271f99c55cff535 CRs-Fixed: 2681882 --- core/sme/src/csr/csr_api_roam.c | 4 +++- core/wma/src/wma_scan_roam.c | 16 ++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 9e6c374f27fd..7f6f5474af61 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -19875,8 +19875,10 @@ csr_update_roam_scan_offload_request(tpAniSirGlobal mac_ctx, mac_ctx->roam.configParam.roam_trigger_reason_bitmask; req_buf->roaming_scan_policy = mac_ctx->roam.configParam.roaming_scan_policy; + /* Do not force RSSI triggers in case controlled roaming enable */ req_buf->roam_force_rssi_trigger = - mac_ctx->roam.configParam.roam_force_rssi_trigger; + (!neighbor_roam_info->roam_control_enable && + mac_ctx->roam.configParam.roam_force_rssi_trigger); csr_update_roam_req_adaptive_11r(session, req_buf); diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index c86be6d4f277..16c1beb72586 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -1809,14 +1809,10 @@ QDF_STATUS wma_process_roaming_config(tp_wma_handle wma_handle, break; mode = WMI_ROAM_SCAN_MODE_PERIODIC; - /* Don't use rssi triggered roam scans if external app - * is in control of channel list. - */ - if (roam_req->ChannelCacheType != CHANNEL_LIST_STATIC || - roam_req->roam_force_rssi_trigger) + if (roam_req->roam_force_rssi_trigger) mode |= WMI_ROAM_SCAN_MODE_RSSI_CHANGE; - } else { + } else if (roam_req->roam_force_rssi_trigger) { mode = WMI_ROAM_SCAN_MODE_RSSI_CHANGE; } @@ -2117,14 +2113,10 @@ QDF_STATUS wma_process_roaming_config(tp_wma_handle wma_handle, break; mode = WMI_ROAM_SCAN_MODE_PERIODIC; - /* Don't use rssi triggered roam scans if external app - * is in control of channel list. - */ - if (roam_req->ChannelCacheType != CHANNEL_LIST_STATIC || - roam_req->roam_force_rssi_trigger) + if (roam_req->roam_force_rssi_trigger) mode |= WMI_ROAM_SCAN_MODE_RSSI_CHANGE; - } else { + } else if (roam_req->roam_force_rssi_trigger) { mode = WMI_ROAM_SCAN_MODE_RSSI_CHANGE; } From 19e6e827f973cef0735256f214f37dd881b9cf96 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Thu, 14 May 2020 10:13:15 -0700 Subject: [PATCH 026/208] Release 5.2.03.26U Release 5.2.03.26U Change-Id: I06ceb014f23d7a0f6beb6bfa4df3d173e32e7d44 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 19d9eb0439b5..6f26655b4601 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "T" +#define QWLAN_VERSION_EXTRA "U" #define QWLAN_VERSION_BUILD 26 -#define QWLAN_VERSIONSTR "5.2.03.26T" +#define QWLAN_VERSIONSTR "5.2.03.26U" #endif /* QWLAN_VERSION_H */ From 00c593de9b0b4145226ac7467c4988cd3f66b687 Mon Sep 17 00:00:00 2001 From: Yu Ouyang Date: Wed, 8 May 2019 13:53:07 +0800 Subject: [PATCH 027/208] qcacld-3.0: fix reassociation issue While getting reassociation request frame, user space hostapd will trigger diassociate with reason code 13. Association can't be established. The root cause is host driver forwards more 6 bytes to user space. The 6 bytes is current AP address in association request frame. Hostapd can't paras association request frame because the additional 6 bytes. Skip current AP address before forwarding reassociation request frame to user space. Change-Id: I94a7c26289f24a1f0716fe64c4ee58eae1a913c6 CRs-Fixed: 2435392 --- core/sap/src/sap_fsm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 23d1208c68da..5557c67ae56a 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -1559,6 +1559,12 @@ QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx, reassoc_complete->ies = (csr_roaminfo->assocReqPtr + ASSOC_REQ_IE_OFFSET); + /* skip current AP address in reassoc frame */ + if (csr_roaminfo->fReassocReq) { + reassoc_complete->ies_len -= QDF_MAC_ADDR_SIZE; + reassoc_complete->ies += QDF_MAC_ADDR_SIZE; + } + if (csr_roaminfo->addIELen) { if (wlan_get_vendor_ie_ptr_from_oui( SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE, From 65f926931c6bac8ec7df46847bb6a8772551a510 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Fri, 15 May 2020 04:59:49 -0700 Subject: [PATCH 028/208] Release 5.2.03.26V Release 5.2.03.26V Change-Id: I76cb6e789970d90efcff2218ab97df6d5933cc29 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 6f26655b4601..2788d572f7a0 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "U" +#define QWLAN_VERSION_EXTRA "V" #define QWLAN_VERSION_BUILD 26 -#define QWLAN_VERSIONSTR "5.2.03.26U" +#define QWLAN_VERSIONSTR "5.2.03.26V" #endif /* QWLAN_VERSION_H */ From 60832745a0b7b8778c4de4db29984d406c00ce2a Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Mon, 11 May 2020 13:37:45 +0530 Subject: [PATCH 029/208] qcacld-3.0: Use MAX_PEERS instead of IBSS define in conn_info Currently, SIR_MAX_NUM_STA_IN_IBSS(16) is used while updating sta_ctx->conn_info in hdd_save_peer/hdd_delete_peer. IBSS supports maximum 16 peers but NDP might support more based on platform. This restricts the max supported NDP peers to 16. But host driver supports MAX_PEERS(32) no.of peers and use the same here as sta_ctx->conn_info has support for MAX_PEERS(32) mac addresses. Change-Id: Ic52422435f97929e22cf3c0897ce9173793ee12e CRs-Fixed: 2673110 --- core/hdd/src/wlan_hdd_assoc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 64219aa8da8f..75dc120b1067 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -3666,7 +3666,7 @@ bool hdd_save_peer(struct hdd_station_ctx *sta_ctx, uint8_t sta_id, { int idx; - for (idx = 0; idx < SIR_MAX_NUM_STA_IN_IBSS; idx++) { + for (idx = 0; idx < MAX_PEERS; idx++) { if (HDD_WLAN_INVALID_STA_ID == sta_ctx->conn_info.staId[idx]) { hdd_debug("adding peer: %pM, sta_id: %d, at idx: %d", peer_mac_addr, sta_id, idx); @@ -3691,7 +3691,7 @@ void hdd_delete_peer(struct hdd_station_ctx *sta_ctx, uint8_t sta_id) { int i; - for (i = 0; i < SIR_MAX_NUM_STA_IN_IBSS; i++) { + for (i = 0; i < MAX_PEERS; i++) { if (sta_id == sta_ctx->conn_info.staId[i]) { sta_ctx->conn_info.staId[i] = HDD_WLAN_INVALID_STA_ID; return; @@ -3704,7 +3704,7 @@ bool hdd_any_valid_peer_present(struct hdd_adapter *adapter) struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); int idx; - for (idx = 0; idx < SIR_MAX_NUM_STA_IN_IBSS; idx++) + for (idx = 0; idx < MAX_PEERS; idx++) if (HDD_WLAN_INVALID_STA_ID != sta_ctx->conn_info.staId[idx]) return true; From 6b1c7b416b723a1ae60203bef553b787e31fd26c Mon Sep 17 00:00:00 2001 From: nshrivas Date: Sun, 17 May 2020 07:43:08 -0700 Subject: [PATCH 030/208] Release 5.2.03.26W Release 5.2.03.26W Change-Id: I95f030d840d6afee49340564e8c9766fc7d1f08b CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 2788d572f7a0..210c208e59a5 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "V" +#define QWLAN_VERSION_EXTRA "W" #define QWLAN_VERSION_BUILD 26 -#define QWLAN_VERSIONSTR "5.2.03.26V" +#define QWLAN_VERSIONSTR "5.2.03.26W" #endif /* QWLAN_VERSION_H */ From ffa67e2b7b383247f9e8bfa9f245d7d6e8ed978f Mon Sep 17 00:00:00 2001 From: Utkarsh Bhatnagar Date: Fri, 15 May 2020 20:09:39 +0530 Subject: [PATCH 031/208] qcacld-3.0: Consider Only dot11mode profiles if configured If device is configured to Only dot11mode profile. Don't connect to lesser profile the configured. Change-Id: I7bf5157c0d7324c5ee7c4cdaac7806c0991d5dae CRs-Fixed: 2683763 --- core/sme/src/csr/csr_api_roam.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 7f6f5474af61..6fe827a92088 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -6353,6 +6353,8 @@ static bool csr_roam_select_bss(tpAniSirGlobal mac_ctx, enum policy_mgr_con_mode mode; uint8_t chan_id; QDF_STATUS qdf_status; + eCsrPhyMode self_phymode = mac_ctx->roam.configParam.phyMode; + tDot11fBeaconIEs *bcn_ies; vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, vdev_id, @@ -6375,6 +6377,29 @@ static bool csr_roam_select_bss(tpAniSirGlobal mac_ctx, * sessions exempted */ result = &scan_result->Result; + bcn_ies = result->pvIes; + /* + * If phymode is configured to DOT11 Only profile. + * Don't connect to profile which is less than them. + */ + if (bcn_ies && ((self_phymode == eCSR_DOT11_MODE_11n_ONLY && + !bcn_ies->HTCaps.present) || + (self_phymode == eCSR_DOT11_MODE_11ac_ONLY && + !bcn_ies->VHTCaps.present) || + (self_phymode == eCSR_DOT11_MODE_11ax_ONLY && + !bcn_ies->he_cap.present))) { + sme_info("self_phymode %d mismatch HT %d VHT %d HE %d", + self_phymode, bcn_ies->HTCaps.present, + bcn_ies->VHTCaps.present, + bcn_ies->he_cap.present); + *roam_state = eCsrStopRoamingDueToConcurrency; + status = true; + *roam_bss_entry = csr_ll_next(&bss_list->List, + *roam_bss_entry, + LL_ACCESS_LOCK); + continue; + } + /* * Ignore the BSS if any other vdev is already connected * to it. From f6d05a4b737158dbb9af4ecf07a34e5a21e05dc8 Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Wed, 18 Mar 2020 13:05:51 +0530 Subject: [PATCH 032/208] qcacmn: Abort only host scans on roam start notification The roam sequence in LFR-3.0 is roam scan start notification from firmware followed by roam start indication and then roam synch,roam synch frame events. Roam start is sent after candidate selection and host driver will disable queues when roam start is received. But for emergency roam trigger, firmware sends roam start indication directly without notifying roam scan start to disable data path queues immediately after deauth received from the AP. So roam start is received before roam scan is started at firmware and before candidate selection is done. After roam start notification, host sends scan abort for all scan on vdev by setting scan command request type to WMI_SCN_STOP_VAP_ALL. This results in roam scan getting aborted at firmare in emergency deauth roaming case and roaming fails. Introduce new vdev id value based on which the scan module will abort only host triggered scans setting the flag WMI_SCN_STOP_HOST_VAP_ALL in the scan request. Change-Id: I3a162c55d4a008ff986fd957bed395b39c060bb5 CRs-Fixed: 2636410 --- os_if/linux/scan/src/wlan_cfg80211_scan.c | 4 +++- .../serialization/inc/wlan_serialization_api.h | 2 ++ .../serialization/src/wlan_serialization_dequeue.c | 1 + umac/scan/core/src/wlan_scan_manager.c | 3 +++ umac/scan/dispatcher/inc/wlan_scan_public_structs.h | 6 +++++- umac/scan/dispatcher/src/wlan_scan_ucfg_api.c | 7 +++---- wmi/inc/wmi_unified_param.h | 1 + wmi/src/wmi_unified_tlv.c | 4 ++++ 8 files changed, 22 insertions(+), 6 deletions(-) diff --git a/os_if/linux/scan/src/wlan_cfg80211_scan.c b/os_if/linux/scan/src/wlan_cfg80211_scan.c index 453571bf65ca..caabb23b460a 100644 --- a/os_if/linux/scan/src/wlan_cfg80211_scan.c +++ b/os_if/linux/scan/src/wlan_cfg80211_scan.c @@ -1640,8 +1640,10 @@ QDF_STATUS wlan_abort_scan(struct wlan_objmgr_pdev *pdev, req->cancel_req.scan_id = scan_id; req->cancel_req.pdev_id = pdev_id; req->cancel_req.vdev_id = vdev_id; - if (scan_id != INVAL_SCAN_ID) + if (scan_id != INVAL_SCAN_ID && scan_id != CANCEL_HOST_SCAN_ID) req->cancel_req.req_type = WLAN_SCAN_CANCEL_SINGLE; + else if (scan_id == CANCEL_HOST_SCAN_ID) + req->cancel_req.req_type = WLAN_SCAN_CANCEL_HOST_VDEV_ALL; else if (vdev_id == INVAL_VDEV_ID) req->cancel_req.req_type = WLAN_SCAN_CANCEL_PDEV_ALL; else diff --git a/umac/cmn_services/serialization/inc/wlan_serialization_api.h b/umac/cmn_services/serialization/inc/wlan_serialization_api.h index 392ecdaf96e8..99af2a7fbc1b 100644 --- a/umac/cmn_services/serialization/inc/wlan_serialization_api.h +++ b/umac/cmn_services/serialization/inc/wlan_serialization_api.h @@ -169,12 +169,14 @@ enum wlan_serialization_cmd_type { * @WLAN_SER_CANCEL_SINGLE_SCAN: Cancel a single scan with a given ID * @WLAN_SER_CANCEL_PDEV_SCANS: Cancel all the scans on a given pdev * @WLAN_SER_CANCEL_VDEV_SCANS: Cancel all the scans on given vdev + * @WLAN_SER_CANCEL_VDEV_HOST_SCANS: Cancel all host scans on given vdev * @WLAN_SER_CANCEL_NON_SCAN_CMD: Cancel the given non scan command */ enum wlan_serialization_cancel_type { WLAN_SER_CANCEL_SINGLE_SCAN, WLAN_SER_CANCEL_PDEV_SCANS, WLAN_SER_CANCEL_VDEV_SCANS, + WLAN_SER_CANCEL_VDEV_HOST_SCANS, WLAN_SER_CANCEL_NON_SCAN_CMD, WLAN_SER_CANCEL_MAX, }; diff --git a/umac/cmn_services/serialization/src/wlan_serialization_dequeue.c b/umac/cmn_services/serialization/src/wlan_serialization_dequeue.c index 10602f21ef39..f82a1749ff32 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_dequeue.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_dequeue.c @@ -623,6 +623,7 @@ wlan_serialization_find_and_cancel_cmd( NULL, cmd.cmd_type); break; case WLAN_SER_CANCEL_VDEV_SCANS: + case WLAN_SER_CANCEL_VDEV_HOST_SCANS: /* remove all scan cmds which matches the vdev object */ status = wlan_serialization_cmd_cancel_handler(ser_obj, NULL, NULL, diff --git a/umac/scan/core/src/wlan_scan_manager.c b/umac/scan/core/src/wlan_scan_manager.c index 11261c1060f9..984b4f6e0dea 100644 --- a/umac/scan/core/src/wlan_scan_manager.c +++ b/umac/scan/core/src/wlan_scan_manager.c @@ -524,6 +524,9 @@ get_serialization_cancel_type(enum scan_cancel_req_type type) case WLAN_SCAN_CANCEL_PDEV_ALL: serialization_type = WLAN_SER_CANCEL_PDEV_SCANS; break; + case WLAN_SCAN_CANCEL_HOST_VDEV_ALL: + serialization_type = WLAN_SER_CANCEL_VDEV_HOST_SCANS; + break; default: QDF_ASSERT(0); scm_warn("invalid scan_cancel_req_type: %d", type); diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h index 6a369610f348..d17bd97df255 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h +++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h @@ -40,6 +40,7 @@ typedef uint32_t wlan_scan_id; #define SCM_CANCEL_SCAN_WAIT_ITERATION 600 #define INVAL_SCAN_ID 0xFFFFFFFF +#define CANCEL_HOST_SCAN_ID 0xFFFFFFFE #define INVAL_VDEV_ID 0xFFFFFFFF #define INVAL_PDEV_ID 0xFFFFFFFF @@ -959,12 +960,15 @@ struct scan_start_request { * enum scan_cancel_type - type specifiers for cancel scan request * @WLAN_SCAN_CANCEL_SINGLE: cancel particular scan specified by scan_id * @WLAN_SCAN_CANCEL_VAP_ALL: cancel all scans running on a particular vdevid - * WLAN_SCAN_CANCEL_PDEV_ALL: cancel all scans running on parent pdev of vdevid + * @WLAN_SCAN_CANCEL_PDEV_ALL: cancel all scans running on parent pdev of vdevid + * @WLAN_SCAN_CANCEL_HOST_VDEV_ALL: Cancel all host triggered scans alone on + * vdev */ enum scan_cancel_req_type { WLAN_SCAN_CANCEL_SINGLE = 1, WLAN_SCAN_CANCEL_VDEV_ALL, WLAN_SCAN_CANCEL_PDEV_ALL, + WLAN_SCAN_CANCEL_HOST_VDEV_ALL, }; /** diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index 589c20dbf446..12f18d309736 100644 --- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -1284,11 +1284,10 @@ ucfg_scan_cancel_sync(struct scan_cancel_request *req) return QDF_STATUS_E_NULL_VALUE; } - if (req->cancel_req.req_type == - WLAN_SCAN_CANCEL_PDEV_ALL) + if (req->cancel_req.req_type == WLAN_SCAN_CANCEL_PDEV_ALL) cancel_pdev = true; - else if (req->cancel_req.req_type == - WLAN_SCAN_CANCEL_VDEV_ALL) + else if (req->cancel_req.req_type == WLAN_SCAN_CANCEL_VDEV_ALL || + req->cancel_req.req_type == WLAN_SCAN_CANCEL_HOST_VDEV_ALL) cancel_vdev = true; vdev = req->vdev; diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index e0397cdfe68a..23816f12295e 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -6238,6 +6238,7 @@ typedef enum { wmi_service_packet_capture_support, wmi_service_time_sync_ftm, wmi_roam_scan_chan_list_to_host_support, + wmi_service_host_scan_stop_vdev_all, wmi_services_max, } wmi_conv_service_ids; #define WMI_SERVICE_UNAVAILABLE 0xFFFF diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 1a5e39b18f24..8780804d1d1e 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -3058,6 +3058,8 @@ static QDF_STATUS send_scan_stop_cmd_tlv(wmi_unified_t wmi_handle, } else if (param->req_type == WLAN_SCAN_CANCEL_SINGLE) { /* Cancelling specific scan */ cmd->req_type = WMI_SCAN_STOP_ONE; + } else if (param->req_type == WLAN_SCAN_CANCEL_HOST_VDEV_ALL) { + cmd->req_type = WMI_SCN_STOP_HOST_VAP_ALL; } else { WMI_LOGE("%s: Invalid Command : ", __func__); wmi_buf_free(wmi_buf); @@ -25211,6 +25213,8 @@ static void populate_tlv_service(uint32_t *wmi_service) WMI_SERVICE_AUDIO_SYNC_SUPPORT; wmi_service[wmi_roam_scan_chan_list_to_host_support] = WMI_SERVICE_ROAM_SCAN_CHANNEL_LIST_TO_HOST_SUPPORT; + wmi_service[wmi_service_host_scan_stop_vdev_all] = + WMI_SERVICE_HOST_SCAN_STOP_VDEV_ALL_SUPPORT; } #ifndef CONFIG_MCL From abd3508e3f5c01d50dc6c440d52bff11fd7d3b0a Mon Sep 17 00:00:00 2001 From: nshrivas Date: Sun, 17 May 2020 23:44:03 -0700 Subject: [PATCH 033/208] Release 5.2.03.26X Release 5.2.03.26X Change-Id: I60128d889ef24ceea6869f86ac92caea31eed6c2 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 210c208e59a5..ba4dc611677f 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "W" +#define QWLAN_VERSION_EXTRA "X" #define QWLAN_VERSION_BUILD 26 -#define QWLAN_VERSIONSTR "5.2.03.26W" +#define QWLAN_VERSIONSTR "5.2.03.26X" #endif /* QWLAN_VERSION_H */ From 427fd3ecdbc7c5f8d4a32ceac28e6878b7a439cf Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Mon, 18 May 2020 16:08:26 +0530 Subject: [PATCH 034/208] qcacld-3.0: Add a log to print nan separate vdev capa of host and fw Currently, there is no log to identify whether the firmware doesn't support NAN separate vdev or it's disabled through the ini param nan_separate_iface_support. Add a log to print the firmware and host capabilities when either of these is not supported. Change-Id: I76ad6e192b7b7fc07c106f652df947767f7b4578 CRs-Fixed: 2684544 --- core/hdd/src/wlan_hdd_main.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 6bca166c8248..d340f4b7fc4b 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -10666,6 +10666,7 @@ static int hdd_open_interfaces(struct hdd_context *hdd_ctx, bool rtnl_held) struct hdd_adapter *adapter; enum QDF_GLOBAL_MODE curr_mode; int ret; + bool nan_iface_support; curr_mode = hdd_get_conparam(); /* open monitor mode adapter if con_mode is monitor mode */ @@ -10709,8 +10710,13 @@ static int hdd_open_interfaces(struct hdd_context *hdd_ctx, bool rtnl_held) if (ret) goto err_close_adapters; - if (hdd_ctx->nan_seperate_vdev_supported && - wlan_hdd_nan_separate_iface_supported(hdd_ctx)) { + nan_iface_support = wlan_hdd_nan_separate_iface_supported(hdd_ctx); + if (!hdd_ctx->nan_seperate_vdev_supported || !nan_iface_support) + hdd_debug("NAN separate vdev%s supported by host,%s supported by firmware", + nan_iface_support ? "" : " not", + hdd_ctx->nan_seperate_vdev_supported ? "" : " not"); + + if (hdd_ctx->nan_seperate_vdev_supported && nan_iface_support) { adapter = hdd_open_adapter(hdd_ctx, QDF_NAN_DISC_MODE, "wifi-aware%d", wlan_hdd_get_intf_addr(hdd_ctx, QDF_NAN_DISC_MODE), From 2d4dc7cc7aae51646620c7cb8eac4b1ebedc9774 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Mon, 18 May 2020 07:53:09 -0700 Subject: [PATCH 035/208] Release 5.2.03.26Y Release 5.2.03.26Y Change-Id: I3d692124ebbfdfb9c6b125539285e4806d8af7ec CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index ba4dc611677f..46e46bd70b32 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "X" +#define QWLAN_VERSION_EXTRA "Y" #define QWLAN_VERSION_BUILD 26 -#define QWLAN_VERSIONSTR "5.2.03.26X" +#define QWLAN_VERSIONSTR "5.2.03.26Y" #endif /* QWLAN_VERSION_H */ From f2abb2c13fb93c31883ace63ceffe41b9672797e Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Tue, 19 May 2020 18:50:26 +0530 Subject: [PATCH 036/208] qcacld-3.0: Add null check for frequency list in rrm scan done callback When multiple measurement requests are received in a single beacon report request, multiple iterative scans are triggered for each request for the frequency list provided in the request. This results in free of rrm context global frequency list by the second request rrm scan in the iter measurement timer start failure path and was accessed by the scan done callback of the 1st measurement request. Add null check for rrm context frequency list and also if the timer is already running, send measurement done indication for that request. Change-Id: I149ba47872095228595cd52535fb76c422eefba7 CRs-Fixed: 2648618 --- core/mac/inc/ani_global.h | 3 +- core/mac/src/cfg/cfg_api.c | 2 +- core/mac/src/pe/include/rrm_global.h | 11 +- .../mac/src/pe/lim/lim_process_action_frame.c | 3 +- core/mac/src/pe/rrm/rrm_api.c | 80 ++-- core/mac/src/pe/sch/sch_beacon_gen.c | 2 +- core/sme/inc/sme_rrm_internal.h | 5 +- core/sme/src/common/sme_api.c | 17 +- core/sme/src/csr/csr_api_roam.c | 2 +- core/sme/src/rrm/sme_rrm.c | 436 +++++++++++------- core/wma/src/wma_scan_roam.c | 2 +- 11 files changed, 344 insertions(+), 219 deletions(-) diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index c561273c5d48..8082f5ee1a8d 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -751,7 +751,8 @@ struct mgmt_frm_reg_info { }; typedef struct sRrmContext { - tRrmSMEContext rrmSmeContext; + struct rrm_config_param rrmConfig; + tRrmSMEContext rrmSmeContext[MAX_MEASUREMENT_REQUEST]; tRrmPEContext rrmPEContext; } tRrmContext, *tpRrmContext; diff --git a/core/mac/src/cfg/cfg_api.c b/core/mac/src/cfg/cfg_api.c index 05c705c18f71..f497560db101 100644 --- a/core/mac/src/cfg/cfg_api.c +++ b/core/mac/src/cfg/cfg_api.c @@ -789,7 +789,7 @@ QDF_STATUS cfg_get_capability_info(tpAniSirGlobal pMac, uint16_t *pCap, if (val) pCapInfo->apsd = 1; - pCapInfo->rrm = pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled; + pCapInfo->rrm = pMac->rrm.rrmConfig.rrm_enabled; pe_debug("RRM: %d", pCapInfo->rrm); /* DSSS-OFDM */ /* FIXME : no config defined yet. */ diff --git a/core/mac/src/pe/include/rrm_global.h b/core/mac/src/pe/include/rrm_global.h index 8ba4373fd092..057eab251cc6 100644 --- a/core/mac/src/pe/include/rrm_global.h +++ b/core/mac/src/pe/include/rrm_global.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012, 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2012, 2014-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -27,6 +27,9 @@ ========================================================================*/ +#define MAX_MEASUREMENT_REQUEST 2 +#define DEFAULT_RRM_IDX 0 + typedef enum eRrmRetStatus { eRRM_SUCCESS, eRRM_INCAPABLE, @@ -48,6 +51,7 @@ typedef struct sSirChannelInfo { typedef struct sSirBeaconReportReqInd { uint16_t messageType; /* eWNI_SME_BEACON_REPORT_REQ_IND */ uint16_t length; + uint8_t measurement_idx; tSirMacAddr bssId; uint16_t measurementDuration[SIR_ESE_MAX_MEAS_IE_REQS]; /* ms */ uint16_t randomizationInterval; /* ms */ @@ -65,6 +69,7 @@ typedef struct sSirBeaconReportReqInd { typedef struct sSirBeaconReportXmitInd { uint16_t messageType; /* eWNI_SME_BEACON_REPORT_RESP_XMIT_IND */ uint16_t length; + uint8_t measurement_idx; tSirMacAddr bssId; uint16_t uDialogToken; uint8_t fMeasureDone; @@ -130,6 +135,7 @@ typedef struct sSirNeighborReportInd { uint16_t messageType; /* eWNI_SME_NEIGHBOR_REPORT_IND */ uint16_t length; uint8_t sessionId; + uint8_t measurement_idx; uint16_t numNeighborReports; tSirMacAddr bssId; /* For the session. */ tSirNeighborBssDescription sNeighborBssDescription[1]; @@ -147,6 +153,7 @@ typedef struct sRRMBeaconReportRequestedIes { #define BEACON_REPORTING_DETAIL_ALL_FF_IE 2 typedef struct sRRMReq { + uint8_t measurement_idx; /* Index of the measurement report in frame */ uint8_t dialog_token; /* In action frame; */ uint8_t token; /* Within individual request; */ uint8_t type; @@ -210,7 +217,7 @@ typedef struct sRrmPEContext { /* Dialog token for the request initiated from station. */ uint8_t DialogToken; uint16_t prev_rrm_report_seq_num; - tpRRMReq pCurrentReq; + tpRRMReq pCurrentReq[MAX_MEASUREMENT_REQUEST]; } tRrmPEContext, *tpRrmPEContext; /* 2008 11k spec reference: 18.4.8.5 RCPI Measurement */ diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index 23f7bc291e19..c88ffb56227e 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -1310,7 +1310,8 @@ __lim_process_radio_measure_request(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, HIGH_SEQ_NUM_OFFSET) | pHdr->seqControl.seqNumLo); if (curr_seq_num == pMac->rrm.rrmPEContext.prev_rrm_report_seq_num && - pMac->rrm.rrmPEContext.pCurrentReq) { + (pMac->rrm.rrmPEContext.pCurrentReq[DEFAULT_RRM_IDX] || + pMac->rrm.rrmPEContext.pCurrentReq[DEFAULT_RRM_IDX + 1])) { pe_err("rrm report req frame, seq num: %d is already in progress, drop it", curr_seq_num); return; diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c index dc591d0b68e5..aa4935034042 100644 --- a/core/mac/src/pe/rrm/rrm_api.c +++ b/core/mac/src/pe/rrm/rrm_api.c @@ -406,6 +406,7 @@ rrm_process_neighbor_report_response(tpAniSirGlobal pMac, pSmeNeighborRpt->messageType = eWNI_SME_NEIGHBOR_REPORT_IND; pSmeNeighborRpt->length = length; + pSmeNeighborRpt->measurement_idx = DEFAULT_RRM_IDX; pSmeNeighborRpt->sessionId = pSessionEntry->smeSessionId; pSmeNeighborRpt->numNeighborReports = pNeighborRep->num_NeighborReport; qdf_mem_copy(pSmeNeighborRpt->bssId, pSessionEntry->bssId, @@ -647,6 +648,7 @@ rrm_process_beacon_report_req(tpAniSirGlobal pMac, pSmeBcnReportReq->measurementDuration[0] = SYS_TU_TO_MS(measDuration); pSmeBcnReportReq->fMeasurementtype[0] = pBeaconReq->measurement_request.Beacon.meas_mode; + pSmeBcnReportReq->measurement_idx = pCurrentReq->measurement_idx; qdf_mem_copy(pSmeBcnReportReq->macaddrBssid, pBeaconReq->measurement_request.Beacon.BSSID, sizeof(tSirMacAddr)); @@ -844,7 +846,8 @@ rrm_process_beacon_report_xmit(tpAniSirGlobal mac_ctx, tSirMacRadioMeasureReport *report = NULL; tSirMacBeaconReport *beacon_report; tpSirBssDescription bss_desc; - tpRRMReq curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq; + tpRRMReq curr_req = mac_ctx->rrm.rrmPEContext. + pCurrentReq[beacon_xmit_ind->measurement_idx]; tpPESession session_entry; uint8_t session_id, counter; uint8_t i, j, offset = 0; @@ -854,8 +857,6 @@ rrm_process_beacon_report_xmit(tpAniSirGlobal mac_ctx, uint8_t frag_id = 0; uint8_t num_frames, num_reports_in_frame; - pe_debug("Received beacon report xmit indication"); - if (NULL == beacon_xmit_ind) { pe_err("Received beacon_xmit_ind is NULL in PE"); return QDF_STATUS_E_FAILURE; @@ -867,6 +868,9 @@ rrm_process_beacon_report_xmit(tpAniSirGlobal mac_ctx, goto end; } + pe_debug("Received beacon report xmit indication on idx:%d", + beacon_xmit_ind->measurement_idx); + if ((beacon_xmit_ind->numBssDesc) || curr_req->sendEmptyBcnRpt) { beacon_xmit_ind->numBssDesc = (beacon_xmit_ind->numBssDesc == RRM_BCN_RPT_NO_BSS_INFO) ? RRM_BCN_RPT_MIN_RPT : @@ -1036,13 +1040,19 @@ end: return status; } -static void rrm_process_beacon_request_failure(tpAniSirGlobal pMac, - tpPESession pSessionEntry, - tSirMacAddr peer, - tRrmRetStatus status) +static void +rrm_process_beacon_request_failure(tpAniSirGlobal pMac, + tpPESession pSessionEntry, + tSirMacAddr peer, + tRrmRetStatus status, uint8_t index) { tpSirMacRadioMeasureReport pReport = NULL; - tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq; + tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq[index]; + + if (!pCurrentReq) { + pe_err("Current request is NULL"); + return; + } pReport = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); if (NULL == pReport) { @@ -1082,7 +1092,6 @@ static void rrm_process_beacon_request_failure(tpAniSirGlobal pMac, * @mac_ctx: Global pointer to MAC context * @peer: Macaddress of the peer requesting the radio measurement * @session_entry: session entry - * @curr_req: Pointer to RRM request * @radiomes_report: Pointer to radio measurement report * @rrm_req: Array of Measurement request IEs * @num_report: No.of reports @@ -1095,15 +1104,16 @@ static void rrm_process_beacon_request_failure(tpAniSirGlobal pMac, */ static QDF_STATUS rrm_process_beacon_req(tpAniSirGlobal mac_ctx, tSirMacAddr peer, - tpPESession session_entry, tpRRMReq curr_req, + tpPESession session_entry, tpSirMacRadioMeasureReport *radiomes_report, tDot11fRadioMeasurementRequest *rrm_req, uint8_t *num_report, int index) { tRrmRetStatus rrm_status = eRRM_SUCCESS; tpSirMacRadioMeasureReport report; + tpRRMReq curr_req; - if (curr_req) { + if (index >= MAX_MEASUREMENT_REQUEST) { if (*radiomes_report == NULL) { /* * Allocate memory to send reports for @@ -1126,23 +1136,31 @@ QDF_STATUS rrm_process_beacon_req(tpAniSirGlobal mac_ctx, tSirMacAddr peer, (*num_report)++; return QDF_STATUS_SUCCESS; } else { + curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq[index]; + if (curr_req) { + qdf_mem_free(curr_req); + curr_req = NULL; + } + curr_req = qdf_mem_malloc(sizeof(*curr_req)); if (NULL == curr_req) { pe_err("Unable to allocate memory during RRM Req processing"); - qdf_mem_free(*radiomes_report); + qdf_mem_free(*radiomes_report); + mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = NULL; return QDF_STATUS_E_NOMEM; } - pe_debug("Processing Beacon Report request"); + pe_debug("Processing Beacon Report request idx:%d", index); curr_req->dialog_token = rrm_req->DialogToken.token; curr_req->token = rrm_req-> MeasurementRequest[index].measurement_token; curr_req->sendEmptyBcnRpt = true; - mac_ctx->rrm.rrmPEContext.pCurrentReq = curr_req; + curr_req->measurement_idx = index; + mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = curr_req; rrm_status = rrm_process_beacon_report_req(mac_ctx, curr_req, &rrm_req->MeasurementRequest[index], session_entry); if (eRRM_SUCCESS != rrm_status) { rrm_process_beacon_request_failure(mac_ctx, - session_entry, peer, rrm_status); + session_entry, peer, rrm_status, index); rrm_cleanup(mac_ctx); } } @@ -1215,7 +1233,6 @@ rrm_process_radio_measurement_request(tpAniSirGlobal mac_ctx, QDF_STATUS status = QDF_STATUS_SUCCESS; tpSirMacRadioMeasureReport report = NULL; uint8_t num_report = 0; - tpRRMReq curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq; if (!rrm_req->num_MeasurementRequest) { report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); @@ -1255,9 +1272,10 @@ rrm_process_radio_measurement_request(tpAniSirGlobal mac_ctx, case SIR_MAC_RRM_BEACON_TYPE: /* Process beacon request. */ status = rrm_process_beacon_req(mac_ctx, peer, - session_entry, curr_req, &report, rrm_req, - &num_report, i); - if (QDF_STATUS_SUCCESS != status) + session_entry, &report, + rrm_req, &num_report, + i); + if (QDF_IS_STATUS_ERROR(status)) return status; break; case SIR_MAC_RRM_LCI_TYPE: @@ -1370,7 +1388,9 @@ QDF_STATUS rrm_initialize(tpAniSirGlobal pMac) { tpRRMCaps pRRMCaps = &pMac->rrm.rrmPEContext.rrmEnabledCaps; - pMac->rrm.rrmPEContext.pCurrentReq = NULL; + pMac->rrm.rrmPEContext.pCurrentReq[0] = NULL; + pMac->rrm.rrmPEContext.pCurrentReq[1] = NULL; + pMac->rrm.rrmPEContext.txMgmtPower = 0; pMac->rrm.rrmPEContext.DialogToken = 0; @@ -1413,17 +1433,21 @@ QDF_STATUS rrm_initialize(tpAniSirGlobal pMac) QDF_STATUS rrm_cleanup(tpAniSirGlobal pMac) { - if (pMac->rrm.rrmPEContext.pCurrentReq) { - if (pMac->rrm.rrmPEContext.pCurrentReq->request.Beacon.reqIes. - pElementIds) { - qdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq-> - request.Beacon.reqIes.pElementIds); - } + uint8_t i; - qdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq); + for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) { + if (pMac->rrm.rrmPEContext.pCurrentReq[i]) { + if (pMac->rrm.rrmPEContext.pCurrentReq[i]->request. + Beacon.reqIes.pElementIds) + qdf_mem_free(pMac->rrm.rrmPEContext. + pCurrentReq[i]->request.Beacon. + reqIes.pElementIds); + + qdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq[i]); + } } - pMac->rrm.rrmPEContext.pCurrentReq = NULL; + pMac->rrm.rrmPEContext.pCurrentReq[i] = NULL; return QDF_STATUS_SUCCESS; } diff --git a/core/mac/src/pe/sch/sch_beacon_gen.c b/core/mac/src/pe/sch/sch_beacon_gen.c index 8765591aae4b..3d60a2fde2cb 100644 --- a/core/mac/src/pe/sch/sch_beacon_gen.c +++ b/core/mac/src/pe/sch/sch_beacon_gen.c @@ -433,7 +433,7 @@ sch_set_fixed_beacon_fields(tpAniSirGlobal mac_ctx, tpPESession session) } } } - if (mac_ctx->rrm.rrmSmeContext.rrmConfig.rrm_enabled) + if (mac_ctx->rrm.rrmConfig.rrm_enabled) populate_dot11f_rrm_ie(mac_ctx, &bcn_2->RRMEnabledCap, session); diff --git a/core/sme/inc/sme_rrm_internal.h b/core/sme/inc/sme_rrm_internal.h index c590b4d7e4d7..8545ec908866 100644 --- a/core/sme/inc/sme_rrm_internal.h +++ b/core/sme/inc/sme_rrm_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012, 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2012, 2014-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -64,6 +64,7 @@ typedef struct sRrmSMEContext { uint16_t token; struct qdf_mac_addr sessionBssId; uint8_t regClass; + uint8_t measurement_idx; /* list of all channels to be measured. */ tCsrChannelInfo channelList; uint8_t currentIndex; @@ -74,7 +75,7 @@ typedef struct sRrmSMEContext { uint16_t randnIntvl; uint16_t duration[SIR_ESE_MAX_MEAS_IE_REQS]; uint8_t measMode[SIR_ESE_MAX_MEAS_IE_REQS]; - struct rrm_config_param rrmConfig; + uint32_t scan_id; qdf_mc_timer_t IterMeasTimer; tDblLinkList neighborReportCache; tRrmNeighborRequestControlInfo neighborReqControlInfo; diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 434b0d8f7817..a7f88ae6fd8b 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -913,7 +913,7 @@ QDF_STATUS sme_get_soft_ap_domain(tHalHandle hHal, v_REGDOMAIN_t * Return: None */ void sme_update_fine_time_measurement_capab(tHalHandle hal, uint8_t session_id, - uint32_t val) + uint32_t val) { tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); QDF_STATUS status; @@ -922,11 +922,11 @@ void sme_update_fine_time_measurement_capab(tHalHandle hal, uint8_t session_id, if (!val) { mac_ctx->rrm.rrmPEContext.rrmEnabledCaps.fine_time_meas_rpt = 0; - ((tpRRMCaps)mac_ctx->rrm.rrmSmeContext. + ((tpRRMCaps)mac_ctx->rrm. rrmConfig.rm_capability)->fine_time_meas_rpt = 0; } else { mac_ctx->rrm.rrmPEContext.rrmEnabledCaps.fine_time_meas_rpt = 1; - ((tpRRMCaps)mac_ctx->rrm.rrmSmeContext. + ((tpRRMCaps)mac_ctx->rrm. rrmConfig.rm_capability)->fine_time_meas_rpt = 1; } @@ -1746,7 +1746,7 @@ QDF_STATUS sme_set_ese_beacon_request(tHalHandle hHal, const uint8_t sessionId, tCsrEseBeaconReqParams *pBeaconReq = NULL; uint8_t counter = 0; struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, sessionId); - tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext[0]; if (pSmeRrmContext->eseBcnReqInProgress == true) { sme_err("A Beacon Report Req is already in progress"); @@ -1776,6 +1776,7 @@ QDF_STATUS sme_set_ese_beacon_request(tHalHandle hHal, const uint8_t sessionId, pSmeBcnReportReq->channelInfo.channelNum = 255; pSmeBcnReportReq->channelList.numChannels = pEseBcnReq->numBcnReqIe; pSmeBcnReportReq->msgSource = eRRM_MSG_SOURCE_ESE_UPLOAD; + pSmeBcnReportReq->measurement_idx = 0; for (counter = 0; counter < pEseBcnReq->numBcnReqIe; counter++) { pBeaconReq = @@ -3947,8 +3948,8 @@ QDF_STATUS sme_get_config_param(tHalHandle hHal, tSmeConfigParams *pParam) return status; } qdf_mem_copy(&pParam->rrmConfig, - &pMac->rrm.rrmSmeContext.rrmConfig, - sizeof(pMac->rrm.rrmSmeContext.rrmConfig)); + &pMac->rrm.rrmConfig, + sizeof(pMac->rrm.rrmConfig)); pParam->snr_monitor_enabled = pMac->snr_monitor_enabled; sme_release_global_lock(&pMac->sme); } @@ -4164,7 +4165,7 @@ QDF_STATUS sme_oem_update_capability(tHalHandle hal, tpAniSirGlobal pmac = PMAC_STRUCT(hal); uint8_t *bytes; - bytes = pmac->rrm.rrmSmeContext.rrmConfig.rm_capability; + bytes = pmac->rrm.rrmConfig.rm_capability; if (cap->ftm_rr) bytes[4] |= RM_CAP_FTM_RANGE_REPORT; @@ -4192,7 +4193,7 @@ QDF_STATUS sme_oem_get_capability(tHalHandle hal, tpAniSirGlobal pmac = PMAC_STRUCT(hal); uint8_t *bytes; - bytes = pmac->rrm.rrmSmeContext.rrmConfig.rm_capability; + bytes = pmac->rrm.rrmConfig.rm_capability; cap->ftm_rr = bytes[4] & RM_CAP_FTM_RANGE_REPORT; cap->lci_capability = bytes[4] & RM_CAP_CIVIC_LOC_MEASUREMENT; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 6fe827a92088..0854074cb5af 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -17545,7 +17545,7 @@ QDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId, /* Fill rrm config parameters */ qdf_mem_copy(&csr_join_req->rrm_config, - &pMac->rrm.rrmSmeContext.rrmConfig, + &pMac->rrm.rrmConfig, sizeof(struct rrm_config_param)); pAP_capabilityInfo = diff --git a/core/sme/src/rrm/sme_rrm.c b/core/sme/src/rrm/sme_rrm.c index 2501fd443efe..6faa4402a135 100644 --- a/core/sme/src/rrm/sme_rrm.c +++ b/core/sme/src/rrm/sme_rrm.c @@ -110,46 +110,46 @@ static void rrm_indicate_neighbor_report_result(tpAniSirGlobal pMac, void *callbackContext; /* Reset the neighbor response pending status */ - pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending = - false; + pMac->rrm.rrmSmeContext[DEFAULT_RRM_IDX]. + neighborReqControlInfo.isNeighborRspPending = false; /* Stop the timer if it is already running. * The timer should be running only in the SUCCESS case. */ if (QDF_TIMER_STATE_RUNNING == - qdf_mc_timer_get_current_state(&pMac->rrm.rrmSmeContext. + qdf_mc_timer_get_current_state(&pMac->rrm. + rrmSmeContext[DEFAULT_RRM_IDX]. neighborReqControlInfo. neighborRspWaitTimer)) { sme_debug("No entry in neighbor report cache"); - qdf_mc_timer_stop(&pMac->rrm.rrmSmeContext. + qdf_mc_timer_stop(&pMac->rrm.rrmSmeContext[DEFAULT_RRM_IDX]. neighborReqControlInfo.neighborRspWaitTimer); } callback = - pMac->rrm.rrmSmeContext.neighborReqControlInfo. + pMac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo. neighborRspCallbackInfo.neighborRspCallback; callbackContext = - pMac->rrm.rrmSmeContext.neighborReqControlInfo. + pMac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo. neighborRspCallbackInfo.neighborRspCallbackContext; /* Reset the callback and the callback context before calling the * callback. It is very likely that there may be a registration in * callback itself. */ - pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo. - neighborRspCallback = NULL; - pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo. - neighborRspCallbackContext = NULL; + pMac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo. + neighborRspCallbackInfo.neighborRspCallback = NULL; + pMac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo. + neighborRspCallbackInfo.neighborRspCallbackContext = NULL; /* Call the callback with the status received from caller */ if (callback) callback(callbackContext, qdf_status); - - } /** * sme_RrmBeaconReportXmitInd () - Send beacon report * @mac_ctx Pointer to mac context + * @measurement_index: Measurement index * @result_arr scan results * @msrmnt_status flag to indicate that the measurement is done. * @bss_count bss count @@ -161,8 +161,8 @@ static void rrm_indicate_neighbor_report_result(tpAniSirGlobal pMac, static QDF_STATUS sme_rrm_send_beacon_report_xmit_ind(tpAniSirGlobal mac_ctx, - tCsrScanResultInfo **result_arr, uint8_t msrmnt_status, - uint8_t bss_count) + uint8_t measurement_index, tCsrScanResultInfo **result_arr, + uint8_t msrmnt_status, uint8_t bss_count) { tpSirBssDescription bss_desc = NULL; tpSirBeaconReportXmitInd beacon_rep; @@ -171,7 +171,8 @@ sme_rrm_send_beacon_report_xmit_ind(tpAniSirGlobal mac_ctx, uint8_t i = 0, j = 0, counter = 0; tCsrScanResultInfo *cur_result = NULL; QDF_STATUS status = QDF_STATUS_E_FAILURE; - tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext; + tpRrmSMEContext rrm_ctx = + &mac_ctx->rrm.rrmSmeContext[measurement_index]; tpSirBssDescription bss_desc_to_free[SIR_BCN_REPORT_MAX_BSS_DESC] = {0}; if (NULL == result_arr && !msrmnt_status) { @@ -191,6 +192,7 @@ sme_rrm_send_beacon_report_xmit_ind(tpAniSirGlobal mac_ctx, } beacon_rep->messageType = eWNI_SME_BEACON_REPORT_RESP_XMIT_IND; beacon_rep->length = length; + beacon_rep->measurement_idx = measurement_index; beacon_rep->uDialogToken = rrm_ctx->token; beacon_rep->duration = rrm_ctx->duration[0]; beacon_rep->regClass = rrm_ctx->regClass; @@ -252,6 +254,7 @@ sme_rrm_send_beacon_report_xmit_ind(tpAniSirGlobal mac_ctx, /** * sme_ese_send_beacon_req_scan_results () - Send beacon report * @mac_ctx Pointer to mac context + * @measurement_index: Measurement request index * @session_id - session id * @result_arr scan results * @msrmnt_status flag to indicate that the measurement is done. @@ -266,8 +269,9 @@ sme_rrm_send_beacon_report_xmit_ind(tpAniSirGlobal mac_ctx, * Return: status */ static QDF_STATUS sme_ese_send_beacon_req_scan_results( - tpAniSirGlobal mac_ctx, uint32_t session_id, - uint8_t channel, tCsrScanResultInfo **result_arr, + tpAniSirGlobal mac_ctx, uint8_t measurement_index, + uint32_t session_id, uint8_t channel, + tCsrScanResultInfo **result_arr, uint8_t msrmnt_status, uint8_t bss_count) { QDF_STATUS status = QDF_STATUS_E_FAILURE; @@ -277,7 +281,8 @@ static QDF_STATUS sme_ese_send_beacon_req_scan_results( uint32_t out_ie_len = 0; uint8_t bss_counter = 0; tCsrScanResultInfo *cur_result = NULL; - tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext; + tpRrmSMEContext rrm_ctx = + &mac_ctx->rrm.rrmSmeContext[measurement_index]; struct csr_roam_info *roam_info; tSirEseBcnReportRsp bcn_rpt_rsp; tpSirEseBcnReportRsp bcn_report = &bcn_rpt_rsp; @@ -417,6 +422,7 @@ void sme_reset_ese_bcn_req_in_progress(tpRrmSMEContext sme_rrm_ctx) /** * sme_rrm_send_scan_result() - to get scan result and send the beacon report * @mac_ctx: pointer to mac context + * @measurement_index: Measurement request number * @num_chan: number of channels * @chan_list: list of channels to fetch the result from * @measurementdone: Flag to indicate measurement done or no @@ -427,6 +433,7 @@ void sme_reset_ese_bcn_req_in_progress(tpRrmSMEContext sme_rrm_ctx) * Return: QDF_STATUS */ static QDF_STATUS sme_rrm_send_scan_result(tpAniSirGlobal mac_ctx, + uint8_t measurement_index, uint8_t num_chan, uint8_t *chan_list, uint8_t measurementdone) @@ -439,7 +446,8 @@ static QDF_STATUS sme_rrm_send_scan_result(tpAniSirGlobal mac_ctx, struct scan_result_list *result_list; QDF_STATUS status; uint8_t num_scan_results, counter = 0; - tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext; + tpRrmSMEContext rrm_ctx = + &mac_ctx->rrm.rrmSmeContext[measurement_index]; uint32_t session_id; struct csr_roam_info *roam_info = NULL; tSirScanType scan_type; @@ -506,12 +514,14 @@ static QDF_STATUS sme_rrm_send_scan_result(tpAniSirGlobal mac_ctx, #ifdef FEATURE_WLAN_ESE if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) status = sme_ese_send_beacon_req_scan_results(mac_ctx, - session_id, chan_list[0], - NULL, measurementdone, 0); + measurement_index, session_id, + chan_list[0], NULL, + measurementdone, 0); else #endif /* FEATURE_WLAN_ESE */ status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx, - NULL, measurementdone, 0); + measurement_index, NULL, + measurementdone, 0); return status; } scan_results = sme_scan_result_get_first(mac_handle, result_handle); @@ -519,15 +529,14 @@ static QDF_STATUS sme_rrm_send_scan_result(tpAniSirGlobal mac_ctx, #ifdef FEATURE_WLAN_ESE if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) { status = sme_ese_send_beacon_req_scan_results(mac_ctx, - session_id, - chan_list[0], - NULL, - measurementdone, - 0); + measurement_index, session_id, + chan_list[0], NULL, + measurementdone, 0); } else #endif /* FEATURE_WLAN_ESE */ status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx, - NULL, measurementdone, 0); + measurement_index, NULL, + measurementdone, 0); } result_list = (struct scan_result_list *)result_handle; @@ -618,14 +627,14 @@ static QDF_STATUS sme_rrm_send_scan_result(tpAniSirGlobal mac_ctx, #ifdef FEATURE_WLAN_ESE if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) status = sme_ese_send_beacon_req_scan_results(mac_ctx, - session_id, chan_list[0], - scanresults_arr, measurementdone, - counter); + measurement_index, session_id, + chan_list[0], scanresults_arr, + measurementdone, counter); else #endif /* FEATURE_WLAN_ESE */ status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx, - scanresults_arr, measurementdone, - counter); + measurement_index, scanresults_arr, + measurementdone, counter); } rrm_send_scan_results_done: @@ -640,7 +649,8 @@ rrm_send_scan_results_done: /** * sme_rrm_scan_request_callback() -Sends the beacon report xmit to PE - * @halHandle: Pointer to the Hal Handle. + * @mac_ctx: Pointer to mac context + * @pSmeRrmContext: SME rrm context for measurement request * @sessionId: session id * @scanId: Scan ID. * @status: CSR Status. @@ -651,18 +661,18 @@ rrm_send_scan_results_done: * * Return : 0 for success, non zero for failure */ -static QDF_STATUS sme_rrm_scan_request_callback(tHalHandle halHandle, +static QDF_STATUS sme_rrm_scan_request_callback(tpAniSirGlobal pMac, + tpRrmSMEContext pSmeRrmContext, uint8_t sessionId, uint32_t scanId, eCsrScanStatus status) { uint16_t interval; - tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; - tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; uint32_t time_tick; QDF_STATUS qdf_status; uint32_t session_id; bool valid_result = true; + uint8_t ch_idx, num_chan; /* * RRM scan response received after roaming to different AP. @@ -676,16 +686,46 @@ static QDF_STATUS sme_rrm_scan_request_callback(tHalHandle halHandle, valid_result = false; } + if (pSmeRrmContext->channelList.ChannelList) { + sme_err("[802.11 RRM]: Global freq list is null"); + pSmeRrmContext->channelList.numOfChannels = 0; + sme_reset_ese_bcn_req_in_progress(pSmeRrmContext); + return QDF_STATUS_E_FAILURE; + } + /* if any more channels are pending, start a timer of a random value * within randomization interval. */ - if (((pSmeRrmContext->currentIndex + 1) < - pSmeRrmContext->channelList.numOfChannels) && valid_result) { - sme_rrm_send_scan_result(pMac, 1, - &pSmeRrmContext->channelList. - ChannelList[pSmeRrmContext - ->currentIndex], - false); + ch_idx = pSmeRrmContext->currentIndex; + num_chan = pSmeRrmContext->channelList.numOfChannels; + if (((ch_idx + 1) < num_chan) && valid_result) { + if (QDF_TIMER_STATE_RUNNING == + qdf_mc_timer_get_current_state( + &pSmeRrmContext->IterMeasTimer)) { + /* + * Measurement random timer is already running, this + * should not happen because the driver doesn't support + * multiple measurements simultaneously. Also for + * multiple measurements on a single report, the + * channels in op class should be appended to the global + * channel list + */ + sme_err("[802.11 RRM]: meas timer is already running"); + sme_rrm_send_scan_result( + pMac, pSmeRrmContext->measurement_idx, 1, + &pSmeRrmContext->channelList. + ChannelList[ch_idx], true); + qdf_mem_free(pSmeRrmContext->channelList.ChannelList); + pSmeRrmContext->channelList.ChannelList = NULL; + pSmeRrmContext->channelList.numOfChannels = 0; + sme_reset_ese_bcn_req_in_progress(pSmeRrmContext); + return QDF_STATUS_E_FAILURE; + } + + sme_rrm_send_scan_result(pMac, pSmeRrmContext->measurement_idx, + 1, &pSmeRrmContext->channelList. + ChannelList[ch_idx], false); + /* Advance the current index. */ pSmeRrmContext->currentIndex++; /* start the timer to issue next request. */ @@ -702,6 +742,7 @@ static QDF_STATUS sme_rrm_scan_request_callback(tHalHandle halHandle, if (QDF_IS_STATUS_ERROR(qdf_status)) { qdf_mem_free(pSmeRrmContext->channelList.ChannelList); pSmeRrmContext->channelList.ChannelList = NULL; + pSmeRrmContext->channelList.numOfChannels = 0; sme_reset_ese_bcn_req_in_progress(pSmeRrmContext); } @@ -709,13 +750,12 @@ static QDF_STATUS sme_rrm_scan_request_callback(tHalHandle halHandle, /* Done with the measurement. Clean up all context and send a * message to PE with measurement done flag set. */ - sme_rrm_send_scan_result(pMac, 1, - &pSmeRrmContext->channelList. - ChannelList[pSmeRrmContext - ->currentIndex], - true); + sme_rrm_send_scan_result(pMac, pSmeRrmContext->measurement_idx, + 1, &pSmeRrmContext->channelList. + ChannelList[ch_idx], true); qdf_mem_free(pSmeRrmContext->channelList.ChannelList); pSmeRrmContext->channelList.ChannelList = NULL; + pSmeRrmContext->channelList.numOfChannels = 0; sme_reset_ese_bcn_req_in_progress(pSmeRrmContext); } @@ -725,17 +765,18 @@ static QDF_STATUS sme_rrm_scan_request_callback(tHalHandle halHandle, static void sme_rrm_scan_event_callback(struct wlan_objmgr_vdev *vdev, struct scan_event *event, void *arg) { + tpAniSirGlobal mac_ctx; + tpRrmSMEContext smerrmctx; uint32_t scan_id; - uint8_t session_id; + uint8_t session_id, i; eCsrScanStatus scan_status = eCSR_SCAN_FAILURE; - tHalHandle hal_handle; bool success = false; session_id = wlan_vdev_get_id(vdev); scan_id = event->scan_id; - hal_handle = cds_get_context(QDF_MODULE_ID_SME); - if (!hal_handle) { - QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_FATAL, - FL("invalid h_hal")); + + mac_ctx = (tpAniSirGlobal)arg; + if (!mac_ctx) { + sme_err("invalid mac_ctx"); return; } @@ -748,23 +789,36 @@ static void sme_rrm_scan_event_callback(struct wlan_objmgr_vdev *vdev, if (success) scan_status = eCSR_SCAN_SUCCESS; - sme_rrm_scan_request_callback(hal_handle, session_id, - scan_id, scan_status); + for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) { + smerrmctx = &mac_ctx->rrm.rrmSmeContext[i]; + if (smerrmctx->scan_id == scan_id) + break; + + if (i == (MAX_MEASUREMENT_REQUEST - 1)) + return; + } + + sme_debug("Scan completed for scan_id:%d measurement_idx:%d", + scan_id, smerrmctx->measurement_idx); + sme_rrm_scan_request_callback(mac_ctx, smerrmctx, session_id, + scan_id, scan_status); } /** * sme_rrm_issue_scan_req() - To issue rrm scan request * @mac_ctx: pointer to mac context + * @idx: Measurement Index * * This routine is called to issue rrm scan request * * Return: QDF_STATUS */ -static QDF_STATUS sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx) +static QDF_STATUS +sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx, uint8_t idx) { QDF_STATUS status = QDF_STATUS_SUCCESS; - tpRrmSMEContext sme_rrm_ctx = &mac_ctx->rrm.rrmSmeContext; + tpRrmSMEContext sme_rrm_ctx = &mac_ctx->rrm.rrmSmeContext[idx]; uint32_t session_id; tSirScanType scan_type; @@ -779,7 +833,8 @@ static QDF_STATUS sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx) if ((sme_rrm_ctx->currentIndex) >= sme_rrm_ctx->channelList.numOfChannels) { - sme_rrm_send_beacon_report_xmit_ind(mac_ctx, NULL, true, 0); + sme_rrm_send_beacon_report_xmit_ind(mac_ctx, idx, NULL, + true, 0); sme_debug("done with the complete ch lt. finish and fee now"); goto free_ch_lst; } @@ -817,6 +872,10 @@ static QDF_STATUS sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx) } ucfg_scan_init_default_params(vdev, req); req->scan_req.scan_id = ucfg_scan_get_scan_id(mac_ctx->psoc); + sme_rrm_ctx->scan_id = req->scan_req.scan_id; + + sme_debug("RRM_SCN: rrm_idx:%d scan_id:%d", + sme_rrm_ctx->measurement_idx, sme_rrm_ctx->scan_id); req->scan_req.scan_f_passive = (scan_type == eSIR_ACTIVE_SCAN) ? false : true; req->scan_req.vdev_id = wlan_vdev_get_id(vdev); @@ -911,12 +970,12 @@ static QDF_STATUS sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx) rrm_scan_timer = 0; if ((sme_rrm_ctx->currentIndex + 1) < sme_rrm_ctx->channelList.numOfChannels) { - sme_rrm_send_scan_result(mac_ctx, 1, + sme_rrm_send_scan_result(mac_ctx, idx, 1, &sme_rrm_ctx->channelList.ChannelList[ sme_rrm_ctx->currentIndex], false); /* Advance the current index. */ sme_rrm_ctx->currentIndex++; - sme_rrm_issue_scan_req(mac_ctx); + sme_rrm_issue_scan_req(mac_ctx, idx); #ifdef FEATURE_WLAN_ESE sme_rrm_ctx->eseBcnReqInProgress = false; #endif @@ -926,7 +985,7 @@ static QDF_STATUS sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx) * Done with the measurement. Clean up all context and * send a message to PE with measurement done flag set. */ - sme_rrm_send_scan_result(mac_ctx, 1, + sme_rrm_send_scan_result(mac_ctx, idx, 1, &sme_rrm_ctx->channelList.ChannelList[ sme_rrm_ctx->currentIndex], true); goto free_ch_lst; @@ -940,7 +999,7 @@ static QDF_STATUS sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx) * and PE will not handle subsequent Beacon requests */ send_ind: - sme_rrm_send_beacon_report_xmit_ind(mac_ctx, NULL, true, 0); + sme_rrm_send_beacon_report_xmit_ind(mac_ctx, idx, NULL, true, 0); free_ch_lst: qdf_mem_free(sme_rrm_ctx->channelList.ChannelList); sme_rrm_ctx->channelList.ChannelList = NULL; @@ -996,13 +1055,14 @@ QDF_STATUS sme_rrm_process_beacon_report_req_ind(tpAniSirGlobal pMac, void *pMsgBuf) { tpSirBeaconReportReqInd pBeaconReq = (tpSirBeaconReportReqInd) pMsgBuf; - tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tpRrmSMEContext pSmeRrmContext; uint32_t len = 0, i = 0; uint8_t country[WNI_CFG_COUNTRY_CODE_LEN]; uint32_t session_id; struct csr_roam_session *session; QDF_STATUS status; + pSmeRrmContext = &pMac->rrm.rrmSmeContext[pBeaconReq->measurement_idx]; status = csr_roam_get_session_id_from_bssid(pMac, (struct qdf_mac_addr *) pBeaconReq->bssId, &session_id); @@ -1026,7 +1086,8 @@ QDF_STATUS sme_rrm_process_beacon_report_req_ind(tpAniSirGlobal pMac, country[2] = OP_CLASS_GLOBAL; - sme_debug("Request Reg class %d, AP's country code %c%c 0x%x Channel %d", + sme_debug("RRM SCN: Index:%d Request Reg class %d, AP's country code %c%c 0x%x Channel %d", + pBeaconReq->measurement_idx, pBeaconReq->channelInfo.regulatoryClass, country[0], country[1], country[2], pBeaconReq->channelInfo.channelNum); @@ -1131,7 +1192,7 @@ QDF_STATUS sme_rrm_process_beacon_report_req_ind(tpAniSirGlobal pMac, pSmeRrmContext->regClass = pBeaconReq->channelInfo.regulatoryClass; pSmeRrmContext->randnIntvl = QDF_MAX(pBeaconReq->randomizationInterval, - pSmeRrmContext->rrmConfig.max_randn_interval); + pMac->rrm.rrmConfig.max_randn_interval); pSmeRrmContext->currentIndex = 0; pSmeRrmContext->msgSource = pBeaconReq->msgSource; qdf_mem_copy((uint8_t *) &pSmeRrmContext->measMode, @@ -1145,7 +1206,7 @@ QDF_STATUS sme_rrm_process_beacon_report_req_ind(tpAniSirGlobal pMac, pSmeRrmContext->token, pSmeRrmContext->randnIntvl, pSmeRrmContext->msgSource); - return sme_rrm_issue_scan_req(pMac); + return sme_rrm_issue_scan_req(pMac, pBeaconReq->measurement_idx); cleanup: if (pBeaconReq->msgSource == eRRM_MSG_SOURCE_11K) { @@ -1156,7 +1217,9 @@ cleanup: /* copy measurement bssid */ qdf_mem_copy(pSmeRrmContext->bssId, pBeaconReq->macaddrBssid, sizeof(tSirMacAddr)); - sme_rrm_send_beacon_report_xmit_ind(pMac, NULL, true, 0); + sme_rrm_send_beacon_report_xmit_ind(pMac, + pBeaconReq->measurement_idx, + NULL, true, 0); } return status; @@ -1191,7 +1254,7 @@ QDF_STATUS sme_rrm_neighbor_report_request(tpAniSirGlobal pMac, uint8_t /* If already a report is pending, return failure */ if (true == - pMac->rrm.rrmSmeContext.neighborReqControlInfo. + pMac->rrm.rrmSmeContext[0].neighborReqControlInfo. isNeighborRspPending) { sme_err("Neighbor request already pending.. Not allowed"); return QDF_STATUS_E_AGAIN; @@ -1204,7 +1267,7 @@ QDF_STATUS sme_rrm_neighbor_report_request(tpAniSirGlobal pMac, uint8_t } rrm_ll_purge_neighbor_cache(pMac, - &pMac->rrm.rrmSmeContext.neighborReportCache); + &pMac->rrm.rrmSmeContext[0].neighborReportCache); pMsg->messageType = eWNI_SME_NEIGHBOR_REPORT_REQ_IND; pMsg->length = sizeof(tSirNeighborReportReqInd); @@ -1220,16 +1283,17 @@ QDF_STATUS sme_rrm_neighbor_report_request(tpAniSirGlobal pMac, uint8_t /* Neighbor report request message sent successfully to PE. * Now register the callbacks */ - pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo. - neighborRspCallback = callbackInfo->neighborRspCallback; - pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo. - neighborRspCallbackContext = + pMac->rrm.rrmSmeContext[0].neighborReqControlInfo. + neighborRspCallbackInfo.neighborRspCallback = + callbackInfo->neighborRspCallback; + pMac->rrm.rrmSmeContext[0].neighborReqControlInfo. + neighborRspCallbackInfo.neighborRspCallbackContext = callbackInfo->neighborRspCallbackContext; - pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending = + pMac->rrm.rrmSmeContext[0].neighborReqControlInfo.isNeighborRspPending = true; /* Start neighbor response wait timer now */ - qdf_mc_timer_start(&pMac->rrm.rrmSmeContext.neighborReqControlInfo. + qdf_mc_timer_start(&pMac->rrm.rrmSmeContext[0].neighborReqControlInfo. neighborRspWaitTimer, callbackInfo->timeout); return QDF_STATUS_SUCCESS; @@ -1322,7 +1386,9 @@ check_11r_assoc: /** * rrm_store_neighbor_rpt_by_roam_score()-store Neighbor BSS descriptor + * @pMac: Pointer to mac context * @pNeighborReportDesc - Neighbor BSS Descriptor node to be stored in cache + * @index: RRM sme context index * * This API is called to store a given * Neighbor BSS descriptor to the neighbor cache. This function @@ -1332,9 +1398,10 @@ check_11r_assoc: * Return: void. */ static void rrm_store_neighbor_rpt_by_roam_score(tpAniSirGlobal pMac, - tpRrmNeighborReportDesc pNeighborReportDesc) + tpRrmNeighborReportDesc pNeighborReportDesc, + uint8_t index) { - tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext[0]; tListElem *pEntry; tRrmNeighborReportDesc *pTempNeighborReportDesc; @@ -1410,11 +1477,11 @@ static QDF_STATUS sme_rrm_process_neighbor_report(tpAniSirGlobal pMac, QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; /* Purge the cache on reception of unsolicited neighbor report */ - if (!pMac->rrm.rrmSmeContext.neighborReqControlInfo. - isNeighborRspPending) + if (!pMac->rrm.rrmSmeContext[pNeighborRpt->measurement_idx]. + neighborReqControlInfo.isNeighborRspPending) rrm_ll_purge_neighbor_cache(pMac, - &pMac->rrm.rrmSmeContext. - neighborReportCache); + &pMac->rrm.rrmSmeContext[pNeighborRpt->measurement_idx]. + neighborReportCache); for (i = 0; i < pNeighborRpt->numNeighborReports; i++) { pNeighborReportDesc = @@ -1447,7 +1514,8 @@ static QDF_STATUS sme_rrm_process_neighbor_report(tpAniSirGlobal pMac, if (pNeighborReportDesc->roamScore > 0) { rrm_store_neighbor_rpt_by_roam_score(pMac, - pNeighborReportDesc); + pNeighborReportDesc, + pNeighborRpt->measurement_idx); } else { sme_err("Roam score of BSSID " MAC_ADDRESS_STR " is 0, Ignoring..", @@ -1462,7 +1530,9 @@ static QDF_STATUS sme_rrm_process_neighbor_report(tpAniSirGlobal pMac, } end: - if (!csr_ll_count(&pMac->rrm.rrmSmeContext.neighborReportCache)) + if (!csr_ll_count( + &pMac->rrm.rrmSmeContext[pNeighborRpt->measurement_idx]. + neighborReportCache)) qdf_status = QDF_STATUS_E_FAILURE; rrm_indicate_neighbor_report_result(pMac, qdf_status); @@ -1512,7 +1582,7 @@ QDF_STATUS sme_rrm_msg_processor(tpAniSirGlobal pMac, uint16_t msg_type, /** * rrm_iter_meas_timer_handle() - Timer handler to handlet the timeout - * @ pMac - The handle returned by mac_open. + * @data - Timer data. * * Timer handler to handlet the timeout condition when a specific BT * stop event does not come back, in which case to restore back the @@ -1520,14 +1590,23 @@ QDF_STATUS sme_rrm_msg_processor(tpAniSirGlobal pMac, uint16_t msg_type, * * Return: NULL */ -static void rrm_iter_meas_timer_handle(void *userData) +static void rrm_iter_meas_timer_handle(void *data) { - tpAniSirGlobal pMac = (tpAniSirGlobal) userData; + tpAniSirGlobal pMac; + mac_handle_t mac_handle = cds_get_context(QDF_MODULE_ID_SME); + tpRrmSMEContext sme_rrm_ctx = (tpRrmSMEContext)data; + + pMac = MAC_CONTEXT(mac_handle); + if (!pMac) { + sme_err("Mac ctx is NULL"); + return; + } sme_debug("Randomization timer expired...send on next channel"); /* Issue a scan req for next channel. */ - sme_rrm_issue_scan_req(pMac); + sme_rrm_issue_scan_req(pMac, sme_rrm_ctx->measurement_idx); } + /** * rrm_neighbor_rsp_timeout_handler() - Timer handler to handlet the timeout * @pMac - The handle returned by mac_open. @@ -1547,7 +1626,7 @@ static void rrm_neighbor_rsp_timeout_handler(void *userData) /** * rrm_open() - Initialze all RRM module - * @ pMac: The handle returned by mac_open. + * @pMac: The handle returned by mac_open. * * Initialze all RRM module. * @@ -1557,45 +1636,46 @@ QDF_STATUS rrm_open(tpAniSirGlobal pMac) { QDF_STATUS qdf_status; - tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tpRrmSMEContext pSmeRrmContext; QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; + uint8_t i; - pSmeRrmContext->rrmConfig.max_randn_interval = 50; /* ms */ + pMac->rrm.rrmConfig.max_randn_interval = 50; /* ms */ - qdf_status = qdf_mc_timer_init(&pSmeRrmContext->IterMeasTimer, - QDF_TIMER_TYPE_SW, - rrm_iter_meas_timer_handle, - (void *)pMac); + for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) { + pSmeRrmContext = &pMac->rrm.rrmSmeContext[i]; + qdf_status = qdf_mc_timer_init(&pSmeRrmContext->IterMeasTimer, + QDF_TIMER_TYPE_SW, + rrm_iter_meas_timer_handle, + (void *)pSmeRrmContext); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + sme_err("rrm_open: Fail to init timer"); + return QDF_STATUS_E_FAILURE; + } - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, - "rrm_open: Fail to init timer"); + qdf_status = qdf_mc_timer_init( + &pSmeRrmContext->neighborReqControlInfo. + neighborRspWaitTimer, QDF_TIMER_TYPE_SW, + rrm_neighbor_rsp_timeout_handler, + (void *)pMac); - return QDF_STATUS_E_FAILURE; - } + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + sme_err("rrm_open: Fail to init neighbor rsp timer"); + return QDF_STATUS_E_FAILURE; + } - qdf_status = - qdf_mc_timer_init(&pSmeRrmContext->neighborReqControlInfo. - neighborRspWaitTimer, QDF_TIMER_TYPE_SW, - rrm_neighbor_rsp_timeout_handler, - (void *)pMac); + pSmeRrmContext->measurement_idx = i; + pSmeRrmContext->neighborReqControlInfo.isNeighborRspPending = + false; - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, - "rrm_open: Fail to init timer"); - - return QDF_STATUS_E_FAILURE; - } - - pSmeRrmContext->neighborReqControlInfo.isNeighborRspPending = false; - - qdf_ret_status = csr_ll_open(&pSmeRrmContext->neighborReportCache); - if (QDF_STATUS_SUCCESS != qdf_ret_status) { - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, - "rrm_open: Fail to open neighbor cache result"); - return QDF_STATUS_E_FAILURE; + qdf_ret_status = + csr_ll_open(&pSmeRrmContext->neighborReportCache); + if (QDF_STATUS_SUCCESS != qdf_ret_status) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + "rrm_open: Fail to open neighbor cache result"); + return QDF_STATUS_E_FAILURE; + } } return QDF_STATUS_SUCCESS; @@ -1616,56 +1696,52 @@ QDF_STATUS rrm_close(tpAniSirGlobal pMac) { QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; - tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext; + tpRrmSMEContext pSmeRrmContext; + uint8_t i; - if (QDF_TIMER_STATE_RUNNING == - qdf_mc_timer_get_current_state(&pSmeRrmContext->IterMeasTimer)) { - qdf_status = qdf_mc_timer_stop(&pSmeRrmContext->IterMeasTimer); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, - FL("Timer stop fail")); + for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) { + pSmeRrmContext = &pMac->rrm.rrmSmeContext[i]; + if (QDF_TIMER_STATE_RUNNING == + qdf_mc_timer_get_current_state(&pSmeRrmContext->IterMeasTimer)) { + qdf_status = qdf_mc_timer_stop( + &pSmeRrmContext->IterMeasTimer); + if (QDF_IS_STATUS_ERROR(qdf_status)) + sme_err("Timer stop fail"); } - } - if (pSmeRrmContext->channelList.ChannelList) { - qdf_mem_free(pSmeRrmContext->channelList.ChannelList); - pSmeRrmContext->channelList.ChannelList = NULL; - } - - qdf_status = qdf_mc_timer_destroy(&pSmeRrmContext->IterMeasTimer); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, - FL("Fail to destroy timer")); - - } - - if (QDF_TIMER_STATE_RUNNING == - qdf_mc_timer_get_current_state(&pSmeRrmContext-> - neighborReqControlInfo. - neighborRspWaitTimer)) { - qdf_status = qdf_mc_timer_stop(&pSmeRrmContext-> - neighborReqControlInfo. - neighborRspWaitTimer); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, - FL("Timer stop fail")); + if (pSmeRrmContext->channelList.ChannelList) { + qdf_mem_free(pSmeRrmContext->channelList.ChannelList); + pSmeRrmContext->channelList.ChannelList = NULL; + pSmeRrmContext->channelList.numOfChannels = 0; } + + qdf_status = + qdf_mc_timer_destroy(&pSmeRrmContext->IterMeasTimer); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) + sme_err("Fail to destroy timer"); + + if (QDF_TIMER_STATE_RUNNING == + qdf_mc_timer_get_current_state(&pSmeRrmContext-> + neighborReqControlInfo. + neighborRspWaitTimer)) { + qdf_status = qdf_mc_timer_stop(&pSmeRrmContext-> + neighborReqControlInfo. + neighborRspWaitTimer); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) + sme_err("Timer stop fail"); + } + + qdf_status = qdf_mc_timer_destroy(&pSmeRrmContext-> + neighborReqControlInfo. + neighborRspWaitTimer); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) + sme_err("Fail to destroy timer"); + + rrm_ll_purge_neighbor_cache(pMac, + &pSmeRrmContext->neighborReportCache); + csr_ll_close(&pSmeRrmContext->neighborReportCache); } - qdf_status = - qdf_mc_timer_destroy(&pSmeRrmContext->neighborReqControlInfo. - neighborRspWaitTimer); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, - FL("Fail to destroy timer")); - - } - - rrm_ll_purge_neighbor_cache(pMac, &pSmeRrmContext->neighborReportCache); - - csr_ll_close(&pSmeRrmContext->neighborReportCache); - return qdf_status; } @@ -1681,7 +1757,7 @@ QDF_STATUS rrm_close(tpAniSirGlobal pMac) QDF_STATUS rrm_change_default_config_param(tpAniSirGlobal pMac, struct rrm_config_param *rrm_config) { - qdf_mem_copy(&pMac->rrm.rrmSmeContext.rrmConfig, rrm_config, + qdf_mem_copy(&pMac->rrm.rrmConfig, rrm_config, sizeof(struct rrm_config_param)); return QDF_STATUS_SUCCESS; @@ -1689,22 +1765,36 @@ QDF_STATUS rrm_change_default_config_param(tpAniSirGlobal pMac, QDF_STATUS rrm_start(tpAniSirGlobal mac_ctx) { - tpRrmSMEContext smerrmctx = &mac_ctx->rrm.rrmSmeContext; + tpRrmSMEContext smerrmctx; + wlan_scan_requester req_id; + uint8_t i; /* Register with scan component */ - smerrmctx->req_id = ucfg_scan_register_requester(mac_ctx->psoc, - "RRM", - sme_rrm_scan_event_callback, - smerrmctx); + req_id = ucfg_scan_register_requester(mac_ctx->psoc, + "RRM", + sme_rrm_scan_event_callback, + mac_ctx); + + for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) { + smerrmctx = &mac_ctx->rrm.rrmSmeContext[i]; + smerrmctx->req_id = req_id; + } return QDF_STATUS_SUCCESS; } QDF_STATUS rrm_stop(tpAniSirGlobal mac_ctx) { - tpRrmSMEContext smerrmctx = &mac_ctx->rrm.rrmSmeContext; + tpRrmSMEContext smerrmctx; + wlan_scan_requester req_id; + uint8_t i; - ucfg_scan_unregister_requester(mac_ctx->psoc, smerrmctx->req_id); + for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) { + smerrmctx = &mac_ctx->rrm.rrmSmeContext[i]; + req_id = smerrmctx->req_id; + smerrmctx->req_id = 0; + } + ucfg_scan_unregister_requester(mac_ctx->psoc, req_id); return QDF_STATUS_SUCCESS; } diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 16c1beb72586..b6478258f184 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -3977,7 +3977,7 @@ QDF_STATUS wma_roam_scan_fill_self_caps(tp_wma_handle wma_handle, if (val) selfCaps.apsd = 1; - selfCaps.rrm = pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled; + selfCaps.rrm = pMac->rrm.rrmConfig.rrm_enabled; if (wlan_cfg_get_int(pMac, WNI_CFG_BLOCK_ACK_ENABLED, &val) != QDF_STATUS_SUCCESS) { From 80d432c96aa8113e562c1abdc0eadfb041cbbece Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Fri, 10 Apr 2020 17:40:37 +0530 Subject: [PATCH 037/208] audio-kernel: Fix compile with CONFIG_DEBUG_FS removed Add fix for compilation failure after remove CONFIG_DEBUG_FS. Change-Id: I94f851916e1c397848aa5d107774f7480a74270f Signed-off-by: Laxminath Kasam Signed-off-by: Rahul Shahare --- 4.0/dsp/codecs/audio_alac.c | 7 ++- 4.0/dsp/codecs/audio_ape.c | 6 +- 4.0/dsp/codecs/audio_g711alaw.c | 6 +- 4.0/dsp/codecs/audio_g711mlaw.c | 6 +- 4.0/dsp/q6asm.c | 100 ++++++++++++++++---------------- 4.0/ipc/apr.c | 8 ++- 4.0/ipc/apr_vm.c | 8 ++- dsp/codecs/audio_alac.c | 6 +- dsp/codecs/audio_ape.c | 6 +- dsp/codecs/audio_g711alaw.c | 6 +- dsp/codecs/audio_g711mlaw.c | 6 +- dsp/q6asm.c | 100 ++++++++++++++++---------------- ipc/apr.c | 8 ++- 13 files changed, 155 insertions(+), 118 deletions(-) diff --git a/4.0/dsp/codecs/audio_alac.c b/4.0/dsp/codecs/audio_alac.c index a3e473f7082e..cda7995ed0f9 100644 --- a/4.0/dsp/codecs/audio_alac.c +++ b/4.0/dsp/codecs/audio_alac.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #include @@ -10,6 +10,7 @@ static struct miscdevice audio_alac_misc; static struct ws_mgr audio_alac_ws_mgr; +#ifdef CONFIG_DEBUG_FS static const struct file_operations audio_alac_debug_fops = { .read = audio_aio_debug_read, .open = audio_aio_debug_open, @@ -20,7 +21,7 @@ static struct dentry *config_debugfs_create_file(const char *name, void *data) return debugfs_create_file(name, S_IFREG | 0444, NULL, (void *)data, &audio_alac_debug_fops); } - +#endif static int alac_channel_map(u8 *channel_mapping, uint32_t channels); static long audio_ioctl_shared(struct file *file, unsigned int cmd, @@ -323,10 +324,12 @@ static int audio_open(struct inode *inode, struct file *file) } snprintf(name, sizeof(name), "msm_alac_%04x", audio->ac->session); +#ifdef CONFIG_DEBUG_FS audio->dentry = config_debugfs_create_file(name, (void *)audio); if (IS_ERR_OR_NULL(audio->dentry)) pr_debug("debugfs_create_file failed\n"); +#endif pr_debug("%s:alacdec success mode[%d]session[%d]\n", __func__, audio->feedback, audio->ac->session); diff --git a/4.0/dsp/codecs/audio_ape.c b/4.0/dsp/codecs/audio_ape.c index 319828bd5465..939f1e1ae2b9 100644 --- a/4.0/dsp/codecs/audio_ape.c +++ b/4.0/dsp/codecs/audio_ape.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #include @@ -10,6 +10,7 @@ static struct miscdevice audio_ape_misc; static struct ws_mgr audio_ape_ws_mgr; +#ifdef CONFIG_DEBUG_FS static const struct file_operations audio_ape_debug_fops = { .read = audio_aio_debug_read, .open = audio_aio_debug_open, @@ -19,6 +20,7 @@ static struct dentry *config_debugfs_create_file(const char *name, void *data) return debugfs_create_file(name, S_IFREG | 0444, NULL, (void *)data, &audio_ape_debug_fops); } +#endif static long audio_ioctl_shared(struct file *file, unsigned int cmd, void *arg) @@ -305,10 +307,12 @@ static int audio_open(struct inode *inode, struct file *file) } snprintf(name, sizeof(name), "msm_ape_%04x", audio->ac->session); +#ifdef CONFIG_DEBUG_FS audio->dentry = config_debugfs_create_file(name, (void *)audio); if (IS_ERR_OR_NULL(audio->dentry)) pr_debug("debugfs_create_file failed\n"); +#endif pr_debug("%s:apedec success mode[%d]session[%d]\n", __func__, audio->feedback, audio->ac->session); diff --git a/4.0/dsp/codecs/audio_g711alaw.c b/4.0/dsp/codecs/audio_g711alaw.c index 27d7fe0b35dd..7cf6810b1462 100644 --- a/4.0/dsp/codecs/audio_g711alaw.c +++ b/4.0/dsp/codecs/audio_g711alaw.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -10,6 +10,7 @@ static struct miscdevice audio_g711alaw_misc; static struct ws_mgr audio_g711_ws_mgr; +#ifdef CONFIG_DEBUG_FS static const struct file_operations audio_g711_debug_fops = { .read = audio_aio_debug_read, .open = audio_aio_debug_open, @@ -20,6 +21,7 @@ static struct dentry *config_debugfs_create_file(const char *name, void *data) return debugfs_create_file(name, S_IFREG | 0444, NULL, (void *)data, &audio_g711_debug_fops); } +#endif static int g711_channel_map(u8 *channel_mapping, uint32_t channels); @@ -278,10 +280,12 @@ static int audio_open(struct inode *inode, struct file *file) } snprintf(name, sizeof(name), "msm_g711_%04x", audio->ac->session); +#ifdef CONFIG_DEBUG_FS audio->dentry = config_debugfs_create_file(name, (void *)audio); if (IS_ERR_OR_NULL(audio->dentry)) pr_debug("%s: debugfs_create_file failed\n", __func__); +#endif pr_debug("%s: g711dec success mode[%d]session[%d]\n", __func__, audio->feedback, audio->ac->session); diff --git a/4.0/dsp/codecs/audio_g711mlaw.c b/4.0/dsp/codecs/audio_g711mlaw.c index 57c7f1ae7e09..1c16eef81954 100644 --- a/4.0/dsp/codecs/audio_g711mlaw.c +++ b/4.0/dsp/codecs/audio_g711mlaw.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -10,6 +10,7 @@ static struct miscdevice audio_g711mlaw_misc; static struct ws_mgr audio_g711_ws_mgr; +#ifdef CONFIG_DEBUG_FS static const struct file_operations audio_g711_debug_fops = { .read = audio_aio_debug_read, .open = audio_aio_debug_open, @@ -20,6 +21,7 @@ static struct dentry *config_debugfs_create_file(const char *name, void *data) return debugfs_create_file(name, S_IFREG | 0444, NULL, (void *)data, &audio_g711_debug_fops); } +#endif static int g711_channel_map(u8 *channel_mapping, uint32_t channels); @@ -277,10 +279,12 @@ static int audio_open(struct inode *inode, struct file *file) } snprintf(name, sizeof(name), "msm_g711_%04x", audio->ac->session); +#ifdef CONFIG_DEBUG_FS audio->dentry = config_debugfs_create_file(name, (void *)audio); if (IS_ERR_OR_NULL(audio->dentry)) pr_debug("%s: debugfs_create_file failed\n", __func__); +#endif pr_debug("%s: g711dec success mode[%d]session[%d]\n", __func__, audio->feedback, audio->ac->session); diff --git a/4.0/dsp/q6asm.c b/4.0/dsp/q6asm.c index 8314df747e9f..bb1df5b24432 100644 --- a/4.0/dsp/q6asm.c +++ b/4.0/dsp/q6asm.c @@ -144,56 +144,6 @@ struct generic_get_data_ { }; static struct generic_get_data_ *generic_get_data; -#ifdef CONFIG_DEBUG_FS -#define OUT_BUFFER_SIZE 56 -#define IN_BUFFER_SIZE 24 - -static struct timeval out_cold_tv; -static struct timeval out_warm_tv; -static struct timeval out_cont_tv; -static struct timeval in_cont_tv; -static long out_enable_flag; -static long in_enable_flag; -static struct dentry *out_dentry; -static struct dentry *in_dentry; -static int in_cont_index; -/*This var is used to keep track of first write done for cold output latency */ -static int out_cold_index; -static char *out_buffer; -static char *in_buffer; - -static uint32_t adsp_reg_event_opcode[] = { - ASM_STREAM_CMD_REGISTER_PP_EVENTS, - ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS, - ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE }; - -static uint32_t adsp_raise_event_opcode[] = { - ASM_STREAM_PP_EVENT, - ASM_STREAM_CMD_ENCDEC_EVENTS, - ASM_IEC_61937_MEDIA_FMT_EVENT }; - -static int is_adsp_reg_event(uint32_t cmd) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(adsp_reg_event_opcode); i++) { - if (cmd == adsp_reg_event_opcode[i]) - return i; - } - return -EINVAL; -} - -static int is_adsp_raise_event(uint32_t cmd) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(adsp_raise_event_opcode); i++) { - if (cmd == adsp_raise_event_opcode[i]) - return i; - } - return -EINVAL; -} - static inline void q6asm_set_flag_in_token(union asm_token_struct *asm_token, int flag, int flag_offset) { @@ -276,6 +226,56 @@ uint8_t q6asm_get_stream_id_from_token(uint32_t token) } EXPORT_SYMBOL(q6asm_get_stream_id_from_token); +static uint32_t adsp_reg_event_opcode[] = { + ASM_STREAM_CMD_REGISTER_PP_EVENTS, + ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS, + ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE }; + +static int is_adsp_reg_event(uint32_t cmd) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(adsp_reg_event_opcode); i++) { + if (cmd == adsp_reg_event_opcode[i]) + return i; + } + return -EINVAL; +} + +static uint32_t adsp_raise_event_opcode[] = { + ASM_STREAM_PP_EVENT, + ASM_STREAM_CMD_ENCDEC_EVENTS, + ASM_IEC_61937_MEDIA_FMT_EVENT }; + +static int is_adsp_raise_event(uint32_t cmd) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(adsp_raise_event_opcode); i++) { + if (cmd == adsp_raise_event_opcode[i]) + return i; + } + return -EINVAL; +} + +#ifdef CONFIG_DEBUG_FS +#define OUT_BUFFER_SIZE 56 +#define IN_BUFFER_SIZE 24 + +static struct timeval out_cold_tv; +static struct timeval out_warm_tv; +static struct timeval out_cont_tv; +static struct timeval in_cont_tv; +static long out_enable_flag; +static long in_enable_flag; +static struct dentry *out_dentry; +static struct dentry *in_dentry; +static int in_cont_index; +/*This var is used to keep track of first write done for cold output latency */ +static int out_cold_index; +static char *out_buffer; +static char *in_buffer; + static int audio_output_latency_dbgfs_open(struct inode *inode, struct file *file) { diff --git a/4.0/ipc/apr.c b/4.0/ipc/apr.c index 0ea269454035..033f6b24f45f 100644 --- a/4.0/ipc/apr.c +++ b/4.0/ipc/apr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2010-2014, 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2014, 2016-2020, The Linux Foundation. All rights reserved. */ #include @@ -1117,9 +1117,9 @@ static int __init apr_debug_init(void) } #else static int __init apr_debug_init(void) -( +{ return 0; -) +} #endif static void apr_cleanup(void) @@ -1140,7 +1140,9 @@ static void apr_cleanup(void) mutex_destroy(&client[i][j].svc[k].m_lock); } } +#ifdef CONFIG_DEBUG_FS debugfs_remove(debugfs_apr_debug); +#endif } static int apr_probe(struct platform_device *pdev) diff --git a/4.0/ipc/apr_vm.c b/4.0/ipc/apr_vm.c index f94e3a22db64..1b66013b8cf4 100644 --- a/4.0/ipc/apr_vm.c +++ b/4.0/ipc/apr_vm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2010-2014, 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2014, 2016-2020 The Linux Foundation. All rights reserved. */ #include @@ -1308,9 +1308,9 @@ static int __init apr_debug_init(void) } #else static int __init apr_debug_init(void) -( +{ return 0; -) +} #endif static void apr_cleanup(void) @@ -1331,7 +1331,9 @@ static void apr_cleanup(void) mutex_destroy(&client[i][j].svc[k].m_lock); } } +#ifdef CONFIG_DEBUG_FS debugfs_remove(debugfs_apr_debug); +#endif } static int apr_probe(struct platform_device *pdev) diff --git a/dsp/codecs/audio_alac.c b/dsp/codecs/audio_alac.c index 1bc1a3eb530a..30dfaeaf8db8 100644 --- a/dsp/codecs/audio_alac.c +++ b/dsp/codecs/audio_alac.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -19,6 +19,7 @@ static struct miscdevice audio_alac_misc; static struct ws_mgr audio_alac_ws_mgr; +#ifdef CONFIG_DEBUG_FS static const struct file_operations audio_alac_debug_fops = { .read = audio_aio_debug_read, .open = audio_aio_debug_open, @@ -29,6 +30,7 @@ static struct dentry *config_debugfs_create_file(const char *name, void *data) return debugfs_create_file(name, S_IFREG | 0444, NULL, (void *)data, &audio_alac_debug_fops); } +#endif static int alac_channel_map(u8 *channel_mapping, uint32_t channels); @@ -332,10 +334,12 @@ static int audio_open(struct inode *inode, struct file *file) } snprintf(name, sizeof(name), "msm_alac_%04x", audio->ac->session); +#ifdef CONFIG_DEBUG_FS audio->dentry = config_debugfs_create_file(name, (void *)audio); if (IS_ERR_OR_NULL(audio->dentry)) pr_debug("debugfs_create_file failed\n"); +#endif pr_debug("%s:alacdec success mode[%d]session[%d]\n", __func__, audio->feedback, audio->ac->session); diff --git a/dsp/codecs/audio_ape.c b/dsp/codecs/audio_ape.c index 3f81b535dad6..1bdd40dc9d20 100644 --- a/dsp/codecs/audio_ape.c +++ b/dsp/codecs/audio_ape.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -19,6 +19,7 @@ static struct miscdevice audio_ape_misc; static struct ws_mgr audio_ape_ws_mgr; +#ifdef CONFIG_DEBUG_FS static const struct file_operations audio_ape_debug_fops = { .read = audio_aio_debug_read, .open = audio_aio_debug_open, @@ -28,6 +29,7 @@ static struct dentry *config_debugfs_create_file(const char *name, void *data) return debugfs_create_file(name, S_IFREG | 0444, NULL, (void *)data, &audio_ape_debug_fops); } +#endif static long audio_ioctl_shared(struct file *file, unsigned int cmd, void *arg) @@ -314,10 +316,12 @@ static int audio_open(struct inode *inode, struct file *file) } snprintf(name, sizeof(name), "msm_ape_%04x", audio->ac->session); +#ifdef CONFIG_DEBUG_FS audio->dentry = config_debugfs_create_file(name, (void *)audio); if (IS_ERR_OR_NULL(audio->dentry)) pr_debug("debugfs_create_file failed\n"); +#endif pr_debug("%s:apedec success mode[%d]session[%d]\n", __func__, audio->feedback, audio->ac->session); diff --git a/dsp/codecs/audio_g711alaw.c b/dsp/codecs/audio_g711alaw.c index fec46d24e2e8..bc4b1b4a487a 100644 --- a/dsp/codecs/audio_g711alaw.c +++ b/dsp/codecs/audio_g711alaw.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 2019-2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -19,6 +19,7 @@ static struct miscdevice audio_g711alaw_misc; static struct ws_mgr audio_g711_ws_mgr; +#ifdef CONFIG_DEBUG_FS static const struct file_operations audio_g711_debug_fops = { .read = audio_aio_debug_read, .open = audio_aio_debug_open, @@ -29,6 +30,7 @@ static struct dentry *config_debugfs_create_file(const char *name, void *data) return debugfs_create_file(name, S_IFREG | 0444, NULL, (void *)data, &audio_g711_debug_fops); } +#endif static int g711_channel_map(u8 *channel_mapping, uint32_t channels); @@ -287,10 +289,12 @@ static int audio_open(struct inode *inode, struct file *file) } snprintf(name, sizeof(name), "msm_g711_%04x", audio->ac->session); +#ifdef CONFIG_DEBUG_FS audio->dentry = config_debugfs_create_file(name, (void *)audio); if (IS_ERR_OR_NULL(audio->dentry)) pr_debug("%s: debugfs_create_file failed\n", __func__); +#endif pr_debug("%s: g711dec success mode[%d]session[%d]\n", __func__, audio->feedback, audio->ac->session); diff --git a/dsp/codecs/audio_g711mlaw.c b/dsp/codecs/audio_g711mlaw.c index c27768ae269f..b4eb7def1b12 100644 --- a/dsp/codecs/audio_g711mlaw.c +++ b/dsp/codecs/audio_g711mlaw.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 2019-2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -19,6 +19,7 @@ static struct miscdevice audio_g711mlaw_misc; static struct ws_mgr audio_g711_ws_mgr; +#ifdef CONFIG_DEBUG_FS static const struct file_operations audio_g711_debug_fops = { .read = audio_aio_debug_read, .open = audio_aio_debug_open, @@ -29,6 +30,7 @@ static struct dentry *config_debugfs_create_file(const char *name, void *data) return debugfs_create_file(name, S_IFREG | 0444, NULL, (void *)data, &audio_g711_debug_fops); } +#endif static int g711_channel_map(u8 *channel_mapping, uint32_t channels); @@ -286,10 +288,12 @@ static int audio_open(struct inode *inode, struct file *file) } snprintf(name, sizeof(name), "msm_g711_%04x", audio->ac->session); +#ifdef CONFIG_DEBUG_FS audio->dentry = config_debugfs_create_file(name, (void *)audio); if (IS_ERR_OR_NULL(audio->dentry)) pr_debug("%s: debugfs_create_file failed\n", __func__); +#endif pr_debug("%s: g711dec success mode[%d]session[%d]\n", __func__, audio->feedback, audio->ac->session); diff --git a/dsp/q6asm.c b/dsp/q6asm.c index 957a8546c708..f89b01565870 100644 --- a/dsp/q6asm.c +++ b/dsp/q6asm.c @@ -146,56 +146,6 @@ struct generic_get_data_ { }; static struct generic_get_data_ *generic_get_data; -#ifdef CONFIG_DEBUG_FS -#define OUT_BUFFER_SIZE 56 -#define IN_BUFFER_SIZE 24 - -static struct timeval out_cold_tv; -static struct timeval out_warm_tv; -static struct timeval out_cont_tv; -static struct timeval in_cont_tv; -static long out_enable_flag; -static long in_enable_flag; -static struct dentry *out_dentry; -static struct dentry *in_dentry; -static int in_cont_index; -/*This var is used to keep track of first write done for cold output latency */ -static int out_cold_index; -static char *out_buffer; -static char *in_buffer; - -static uint32_t adsp_reg_event_opcode[] = { - ASM_STREAM_CMD_REGISTER_PP_EVENTS, - ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS, - ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE }; - -static uint32_t adsp_raise_event_opcode[] = { - ASM_STREAM_PP_EVENT, - ASM_STREAM_CMD_ENCDEC_EVENTS, - ASM_IEC_61937_MEDIA_FMT_EVENT }; - -static int is_adsp_reg_event(uint32_t cmd) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(adsp_reg_event_opcode); i++) { - if (cmd == adsp_reg_event_opcode[i]) - return i; - } - return -EINVAL; -} - -static int is_adsp_raise_event(uint32_t cmd) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(adsp_raise_event_opcode); i++) { - if (cmd == adsp_raise_event_opcode[i]) - return i; - } - return -EINVAL; -} - static inline void q6asm_set_flag_in_token(union asm_token_struct *asm_token, int flag, int flag_offset) { @@ -278,6 +228,56 @@ uint8_t q6asm_get_stream_id_from_token(uint32_t token) } EXPORT_SYMBOL(q6asm_get_stream_id_from_token); +static uint32_t adsp_reg_event_opcode[] = { + ASM_STREAM_CMD_REGISTER_PP_EVENTS, + ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS, + ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE }; + +static int is_adsp_reg_event(uint32_t cmd) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(adsp_reg_event_opcode); i++) { + if (cmd == adsp_reg_event_opcode[i]) + return i; + } + return -EINVAL; +} + +static uint32_t adsp_raise_event_opcode[] = { + ASM_STREAM_PP_EVENT, + ASM_STREAM_CMD_ENCDEC_EVENTS, + ASM_IEC_61937_MEDIA_FMT_EVENT }; + +static int is_adsp_raise_event(uint32_t cmd) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(adsp_raise_event_opcode); i++) { + if (cmd == adsp_raise_event_opcode[i]) + return i; + } + return -EINVAL; +} + +#ifdef CONFIG_DEBUG_FS +#define OUT_BUFFER_SIZE 56 +#define IN_BUFFER_SIZE 24 + +static struct timeval out_cold_tv; +static struct timeval out_warm_tv; +static struct timeval out_cont_tv; +static struct timeval in_cont_tv; +static long out_enable_flag; +static long in_enable_flag; +static struct dentry *out_dentry; +static struct dentry *in_dentry; +static int in_cont_index; +/*This var is used to keep track of first write done for cold output latency */ +static int out_cold_index; +static char *out_buffer; +static char *in_buffer; + static int audio_output_latency_dbgfs_open(struct inode *inode, struct file *file) { diff --git a/ipc/apr.c b/ipc/apr.c index b66bd6e63cb6..f5b602de4453 100644 --- a/ipc/apr.c +++ b/ipc/apr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2014, 2016-2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2014, 2016-2020 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1124,9 +1124,9 @@ static int __init apr_debug_init(void) } #else static int __init apr_debug_init(void) -( +{ return 0; -) +} #endif static void apr_cleanup(void) @@ -1147,7 +1147,9 @@ static void apr_cleanup(void) mutex_destroy(&client[i][j].svc[k].m_lock); } } +#ifdef CONFIG_DEBUG_FS debugfs_remove(debugfs_apr_debug); +#endif } static int apr_probe(struct platform_device *pdev) From 66018a5273cba5d8ec69599094ca9f212be1d2c1 Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Tue, 19 May 2020 22:06:34 +0530 Subject: [PATCH 038/208] qcacld-3.0: Fix stack corruption in beacon request table mode When beacon report request is received from AP in table mode, sme_rrm_issue_scan_req() is called recursively till scan results in all channels for that country code is reached. In 6GHz, the number of channels are high and recursively calling sme_rrm_issue_scan_req for that much channels causes stack corruption. Remove recursive call to the function sme_rrm_issue_scan_req. Instead, loop all the frequencies in the list and send scan results on those channels. Change-Id: Id75d00cfc98fcf218c6b1f85da3270e210697403 CRs-Fixed: 2654375 --- core/sme/src/rrm/sme_rrm.c | 57 +++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/core/sme/src/rrm/sme_rrm.c b/core/sme/src/rrm/sme_rrm.c index 6faa4402a135..ef4c0b1dfd27 100644 --- a/core/sme/src/rrm/sme_rrm.c +++ b/core/sme/src/rrm/sme_rrm.c @@ -494,7 +494,8 @@ static QDF_STATUS sme_rrm_send_scan_result(tpAniSirGlobal mac_ctx, if (filter.SSIDs.SSIDList) qdf_mem_free(filter.SSIDs.SSIDList); - sme_debug("RRM Measurement Done %d", measurementdone); + sme_debug("RRM Measurement Done %d for index:%d", measurementdone, + measurement_index); if (NULL == result_handle) { /* * no scan results @@ -821,6 +822,8 @@ sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx, uint8_t idx) tpRrmSMEContext sme_rrm_ctx = &mac_ctx->rrm.rrmSmeContext[idx]; uint32_t session_id; tSirScanType scan_type; + uint8_t *chan_list; + uint8_t ch_idx; status = csr_roam_get_session_id_from_bssid(mac_ctx, &sme_rrm_ctx->sessionBssId, &session_id); @@ -846,7 +849,7 @@ sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx, uint8_t idx) scan_type = sme_rrm_ctx->measMode[0]; if ((eSIR_ACTIVE_SCAN == scan_type) || - (eSIR_PASSIVE_SCAN == scan_type)) { + (eSIR_PASSIVE_SCAN == scan_type)) { uint32_t max_chan_time; uint64_t current_time; struct scan_start_request *req; @@ -968,27 +971,35 @@ sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx, uint8_t idx) * pScanResult->timer >= rrm_scan_timer */ rrm_scan_timer = 0; - if ((sme_rrm_ctx->currentIndex + 1) < - sme_rrm_ctx->channelList.numOfChannels) { - sme_rrm_send_scan_result(mac_ctx, idx, 1, - &sme_rrm_ctx->channelList.ChannelList[ - sme_rrm_ctx->currentIndex], false); - /* Advance the current index. */ - sme_rrm_ctx->currentIndex++; - sme_rrm_issue_scan_req(mac_ctx, idx); -#ifdef FEATURE_WLAN_ESE - sme_rrm_ctx->eseBcnReqInProgress = false; -#endif - return status; - } else { - /* - * Done with the measurement. Clean up all context and - * send a message to PE with measurement done flag set. - */ - sme_rrm_send_scan_result(mac_ctx, idx, 1, - &sme_rrm_ctx->channelList.ChannelList[ - sme_rrm_ctx->currentIndex], true); - goto free_ch_lst; + chan_list = sme_rrm_ctx->channelList.ChannelList; + if (!chan_list) { + sme_err("[802.11 RRM]: Global channel list is null"); + sme_reset_ese_bcn_req_in_progress(sme_rrm_ctx); + status = QDF_STATUS_E_FAILURE; + goto send_ind; + } + + ch_idx = sme_rrm_ctx->currentIndex; + for (; ch_idx < sme_rrm_ctx->channelList.numOfChannels; ch_idx++) { + + if ((ch_idx + 1) < + sme_rrm_ctx->channelList.numOfChannels) { + sme_rrm_send_scan_result(mac_ctx, idx, 1, + &sme_rrm_ctx->channelList.ChannelList[ + ch_idx], false); + /* Advance the current index. */ + sme_rrm_ctx->currentIndex++; + } else { + /* + * Done with the measurement. Clean up all context and + * send a message to PE with measurement done flag set. + */ + sme_rrm_send_scan_result(mac_ctx, idx, 1, + &sme_rrm_ctx->channelList.ChannelList[ + ch_idx], true); + sme_reset_ese_bcn_req_in_progress(sme_rrm_ctx); + goto free_ch_lst; + } } } From 792d5283733652be97e54fa491c41ae59a315713 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Tue, 19 May 2020 13:59:01 -0700 Subject: [PATCH 039/208] Release 5.2.03.26Z Release 5.2.03.26Z Change-Id: I0a8e5e866d7b2aed5e7275f41541f210fe375d99 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 46e46bd70b32..9d31176be7e2 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "Y" +#define QWLAN_VERSION_EXTRA "Z" #define QWLAN_VERSION_BUILD 26 -#define QWLAN_VERSIONSTR "5.2.03.26Y" +#define QWLAN_VERSIONSTR "5.2.03.26Z" #endif /* QWLAN_VERSION_H */ From c223a3524ab32030f2f74da7e83ed78cedbb256f Mon Sep 17 00:00:00 2001 From: Rachit Kankane Date: Mon, 11 May 2020 19:39:12 +0530 Subject: [PATCH 040/208] qcacld-3.0: Handle tx_power_level under radio stat Host driver do receives radio tx power level stats as part of radio stats even though we have different event ID for that. Handling the tx_power_level as part of radio stats only if num_tx_power_level is set. Change-Id: I46aff51c70c444c94c9b10f32b7776ba4a1ca4e8 CRs-Fixed: 2686882 --- core/hdd/src/wlan_hdd_stats.c | 43 ++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index a9c60e0a4aab..c65a3c60b3f2 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -941,15 +941,22 @@ static int hdd_llstats_post_radio_stats(struct hdd_adapter *adapter, QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS, radiostat->numChannels)) { hdd_err("QCA_WLAN_VENDOR_ATTR put fail"); + goto failure; } if (radiostat->total_num_tx_power_levels) { - if (nla_put(vendor_event, + ret = + nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL, sizeof(u32) * radiostat->total_num_tx_power_levels, - radiostat->tx_time_per_power_level)) { + radiostat->tx_time_per_power_level); + qdf_mem_free(radiostat->tx_time_per_power_level); + radiostat->tx_time_per_power_level = NULL; + if (ret) { + qdf_mem_free(radiostat->channels); + radiostat->channels = NULL; hdd_err("nla_put fail"); goto failure; } @@ -1045,7 +1052,7 @@ static void hdd_process_ll_stats(tSirLLStatsResults *results, if (results->paramId & WMI_LINK_STATS_RADIO) { tpSirWifiRadioStat rs_results, stat_result; - u64 channel_size = 0; + u64 channel_size = 0, pwr_lvl_size = 0; int i; stats = qdf_mem_malloc(sizeof(*stats)); if (!stats) @@ -1064,12 +1071,39 @@ static void hdd_process_ll_stats(tSirLLStatsResults *results, for (i = 0; i < results->num_radio; i++) { channel_size = rs_results->numChannels * sizeof(tSirWifiChannelStats); + pwr_lvl_size = sizeof(uint32_t) * + rs_results->total_num_tx_power_levels; + + if (rs_results->total_num_tx_power_levels && + rs_results->tx_time_per_power_level) { + stat_result->tx_time_per_power_level = + qdf_mem_malloc(pwr_lvl_size); + if (!stat_result->tx_time_per_power_level) { + while (i-- > 0) { + stat_result--; + qdf_mem_free(stat_result-> + tx_time_per_power_level); + qdf_mem_free(stat_result-> + channels); + } + qdf_mem_free(stat_result); + qdf_mem_free(stats); + goto exit; + } + qdf_mem_copy(stat_result->tx_time_per_power_level, + rs_results->tx_time_per_power_level, + pwr_lvl_size); + } if (channel_size) { stat_result->channels = qdf_mem_malloc(channel_size); if (!stat_result->channels) { + qdf_mem_free(stat_result-> + tx_time_per_power_level); while (i-- > 0) { stat_result--; + qdf_mem_free(stat_result-> + tx_time_per_power_level); qdf_mem_free(stat_result-> channels); } @@ -1452,6 +1486,9 @@ static void wlan_hdd_handle_ll_stats(struct hdd_adapter *adapter, for (i = 0; i < num_radio; i++) { if (radio_stat->numChannels) qdf_mem_free(radio_stat->channels); + if (radio_stat->total_num_tx_power_levels) + qdf_mem_free(radio_stat-> + tx_time_per_power_level); radio_stat++; } return; From bdcf047c33fc05cfe71aa1c09017e05fc1e1e09f Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Wed, 18 Mar 2020 12:23:46 +0530 Subject: [PATCH 041/208] qcacld-3.0: Abort only host scans on roam start The roam sequence in LFR-3.0 is roam scan start notification from firmware followed by roam start indication and then roam synch,roam synch frame events. Roam start is sent after candidate selection and host driver will disable queues when roam start is received. But for emergency roam trigger, firmware sends roam start indication directly without notifying roam scan start to disable data path queues immediately after deauth received from the AP. So roam start is received before roam scan is started at firmware and before candidate selection is done. After roam start notification, host sends scan abort for all scan on vdev by setting scan command request type to WMI_SCN_STOP_VAP_ALL. This results in roam scan getting aborted at firmare in emergency deauth roaming case and roaming fails. Define new vdev id value based on which the scan module will abort only host triggered scans setting the request type to WMI_SCN_STOP_HOST_VAP_ALL in the scan request. Change-Id: Ie8b005285973461f654329e1b2dc1a45205331f5 CRs-Fixed: 2644323 --- core/mac/inc/ani_global.h | 1 + core/sme/src/common/sme_api.c | 2 ++ core/sme/src/csr/csr_api_roam.c | 25 ++++++++++++++++++++++++- core/wma/inc/wma_tgt_cfg.h | 1 + core/wma/src/wma_main.c | 4 ++++ 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index 8082f5ee1a8d..db0a33d5c949 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -849,6 +849,7 @@ typedef struct sAniSirGlobal { uint8_t beacon_offload; bool pmf_offload; bool is_fils_roaming_supported; + bool stop_all_host_scan_support; bool enable5gEBT; uint8_t f_prefer_non_dfs_on_radar; uint32_t fEnableDebugLog; diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index a7f88ae6fd8b..6d99240aa8ec 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -14101,6 +14101,8 @@ void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg) FL("mac_ctx->pmf_offload: %d"), mac_ctx->pmf_offload); mac_ctx->is_fils_roaming_supported = cfg->is_fils_roaming_supported; + mac_ctx->stop_all_host_scan_support = + cfg->stop_all_host_scan_support; mac_ctx->is_11k_offload_supported = cfg->is_11k_offload_supported; mac_ctx->akm_service_bitmap = cfg->akm_service_bitmap; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 0854074cb5af..26ee654d4d72 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -23779,6 +23779,8 @@ static QDF_STATUS csr_process_roam_sync_callback(tpAniSirGlobal mac_ctx, tpCsrNeighborRoamControlInfo neigh_roam_info = &mac_ctx->roam.neighborRoamInfo[session_id]; uint32_t chan_id; + bool abort_host_scan_cap = false; + wlan_scan_id scan_id; if (!session) { sme_err("LFR3: Session not found"); @@ -23811,8 +23813,29 @@ static QDF_STATUS csr_process_roam_sync_callback(tpAniSirGlobal mac_ctx, ROAMING_OFFLOAD_TIMER_START); csr_roam_call_callback(mac_ctx, session_id, NULL, 0, eCSR_ROAM_START, eCSR_ROAM_RESULT_SUCCESS); + /* + * For emergency deauth roaming, firmware sends ROAM start + * instead of ROAM scan start notification as data path queues + * will be stopped only during roam start notification. + * This is because, for deauth/disassoc triggered roam, the + * AP has sent deauth, and packets shouldn't be sent to AP + * after that. Since firmware is sending roam start directly + * host sends scan abort during roam scan, but in other + * triggers, the host receives roam start after candidate + * selection and roam scan is complete. So when host sends + * roam abort for emergency deauth roam trigger, the firmware + * roam scan is also aborted. This results in roaming failure. + * So send scan_id as CANCEL_HOST_SCAN_ID to scan module to + * abort only host triggered scans. + */ + abort_host_scan_cap = mac_ctx->stop_all_host_scan_support; + if (abort_host_scan_cap) + scan_id = CANCEL_HOST_SCAN_ID; + else + scan_id = INVAL_SCAN_ID; + wlan_abort_scan(mac_ctx->pdev, INVAL_PDEV_ID, - session_id, INVAL_SCAN_ID, false); + session_id, scan_id, false); return status; case SIR_ROAMING_ABORT: csr_roam_roaming_offload_timer_action(mac_ctx, diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h index a1f38149e898..3762b8a7a082 100644 --- a/core/wma/inc/wma_tgt_cfg.h +++ b/core/wma/inc/wma_tgt_cfg.h @@ -78,6 +78,7 @@ struct wma_tgt_services { bool bcn_reception_stats; uint32_t akm_service_bitmap; bool is_adaptive_11r_roam_supported; + bool stop_all_host_scan_support; bool is_roam_scan_ch_to_host; }; diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index f3fdb0b0ba1b..7afd1a4eb853 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -5117,6 +5117,10 @@ static inline void wma_update_target_services(struct wmi_unified *wmi_handle, if (wmi_service_enabled(wmi_handle, wmi_service_adaptive_11r_support)) cfg->is_adaptive_11r_roam_supported = true; + if (wmi_service_enabled(wmi_handle, + wmi_service_host_scan_stop_vdev_all)) + cfg->stop_all_host_scan_support = true; + if (wmi_service_enabled(wmi_handle, wmi_service_twt_requestor)) cfg->twt_requestor = true; if (wmi_service_enabled(wmi_handle, wmi_service_twt_responder)) From ad55595b3044fd5b0e2c378e450d3b30d9c2c6de Mon Sep 17 00:00:00 2001 From: nshrivas Date: Wed, 20 May 2020 00:18:29 -0700 Subject: [PATCH 042/208] Release 5.2.03.27 Release 5.2.03.27 Change-Id: Iee9eb574c67f7e7cdc8715254a5ff50d07430266 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 9d31176be7e2..c9b1e639ff22 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "Z" -#define QWLAN_VERSION_BUILD 26 +#define QWLAN_VERSION_EXTRA "" +#define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.26Z" +#define QWLAN_VERSIONSTR "5.2.03.27" #endif /* QWLAN_VERSION_H */ From d8f7a2b8297870026e625e2df3ed43e9774c3c8d Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Wed, 20 May 2020 12:05:01 +0530 Subject: [PATCH 043/208] qcacld-3.0: Send disconnect reason code as 0 for beacon miss Currently, host driver sends disconnect reason code as WLAN_REASON_UNSPECIFIED(1) when the station disconnects due to continuous beacon miss and corresponding vendor specific reason code is also sent to userspace. This change is introduced with the commit I99bf4573b59dc810e0a1529fcd48061d10acae4e to provide vendor specific reason codes for all internal disconnections. Driver used to send reason code as 0 for beacon miss before this change. Few applications might still expect the same reason code(0) and current behavior causes backward compatibility issues. So, retain the same reason code 0 for beacon miss failure. Change-Id: I82f215ba15ff6e215cb14ac08933e1491371dfde CRs-Fixed: 2689257 --- core/hdd/src/wlan_hdd_cfg80211.c | 6 ++++++ core/sme/src/csr/csr_api_roam.c | 14 ++------------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 68e968f08593..914f4a7e435b 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -21815,6 +21815,12 @@ wlan_hdd_get_cfg80211_disconnect_reason(struct hdd_adapter *adapter, if (reason >= eSIR_MAC_REASON_PROP_START) { adapter->last_disconnect_reason = wlan_hdd_sir_mac_to_qca_reason(reason); + /* + * Applications expect reason code as 0 for beacon miss failure + * due to backward compatibility. So send ieee80211_reason as 0. + */ + if (reason == eSIR_MAC_BEACON_MISSED) + ieee80211_reason = 0; } else { ieee80211_reason = (enum ieee80211_reasoncode)reason; adapter->last_disconnect_reason = diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 26ee654d4d72..a4bbb2179a54 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -4674,20 +4674,10 @@ QDF_STATUS csr_roam_call_callback(tpAniSirGlobal pMac, uint32_t sessionId, csr_dump_connection_stats(pMac, pSession, roam_info, u1, u2); if (NULL != pSession->callback) { - if (roam_info) { + if (roam_info) roam_info->sessionId = (uint8_t) sessionId; - /* - * the reasonCode will be passed to supplicant by - * cfg80211_disconnected. Based on the document, - * the reason code passed to supplicant needs to set - * to 0 if unknown. eSIR_BEACON_MISSED reason code is - * not recognizable so that we set to 0 instead. - */ - if (roam_info->reasonCode == eSIR_MAC_BEACON_MISSED) - roam_info->reasonCode = 0; - } status = pSession->callback(pSession->pContext, roam_info, - roamId, u1, u2); + roamId, u1, u2); } /* * EVENT_WLAN_STATUS_V2: eCSR_ROAM_ASSOCIATION_COMPLETION, From 8f65b3d49005f26d20e290b7adcafe8001af5e31 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Wed, 20 May 2020 01:55:52 -0700 Subject: [PATCH 044/208] Release 5.2.03.27 Release 5.2.03.27 Change-Id: I3641634294e3704af207aaa7ac84afb767b14e58 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 9d31176be7e2..c9b1e639ff22 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "Z" -#define QWLAN_VERSION_BUILD 26 +#define QWLAN_VERSION_EXTRA "" +#define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.26Z" +#define QWLAN_VERSIONSTR "5.2.03.27" #endif /* QWLAN_VERSION_H */ From e8a4e2f44e6c4b23b7728e525e7d5e29cf977f83 Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Wed, 20 May 2020 13:45:08 +0530 Subject: [PATCH 045/208] qcacmn: Add support for WPA3 SuiteB roaming This commit enables support for SuiteB roaming wmi service based on the WPA3 SuiteB roam service capability advertisement received from Firmware. In SuiteB the PMK length is greater than the existing PMK length, added the extended PMK parameters to fill in the remaining bytes of PMK in the RSO command. Change-Id: Ia630580bba050513800e3acac875baf937ec8d14 CRs-Fixed: 2685993 --- wmi/inc/wmi_unified_param.h | 1 + wmi/src/wmi_unified_tlv.c | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 23816f12295e..f5a54a46e1d8 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -6239,6 +6239,7 @@ typedef enum { wmi_service_time_sync_ftm, wmi_roam_scan_chan_list_to_host_support, wmi_service_host_scan_stop_vdev_all, + wmi_service_suiteb_roam_support, wmi_services_max, } wmi_conv_service_ids; #define WMI_SERVICE_UNAVAILABLE 0xFFFF diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 8780804d1d1e..8cbe77cdcaaa 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -6775,6 +6775,18 @@ static QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, roam_req->psk_pmk, roam_offload_11i->pmk_len); + if (auth_mode == + WMI_AUTH_RSNA_SUITE_B_8021X_SHA384) { + roam_offload_11i->pmk_ext_len = + (roam_req->pmk_len - + ROAM_OFFLOAD_PMK_BYTES); + qdf_mem_copy(roam_offload_11i->pmk_ext, + &roam_req->psk_pmk[ + ROAM_OFFLOAD_PMK_BYTES], + roam_offload_11i-> + pmk_ext_len); + } + WMITLV_SET_HDR(&roam_offload_11i->tlv_header, WMITLV_TAG_STRUC_wmi_roam_11i_offload_tlv_param, WMITLV_GET_STRUCT_TLVLEN @@ -6789,11 +6801,8 @@ static QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, buf_ptr += WMI_TLV_HDR_SIZE; WMI_LOGD("pmk_len = %d", roam_offload_11i->pmk_len); - if (roam_offload_11i->pmk_len) - QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, - QDF_TRACE_LEVEL_DEBUG, - roam_offload_11i->pmk, - roam_offload_11i->pmk_len); + WMI_LOGD("pmk_ext_len = %d", + roam_offload_11i->pmk_ext_len); } } else { WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, @@ -25215,6 +25224,8 @@ static void populate_tlv_service(uint32_t *wmi_service) WMI_SERVICE_ROAM_SCAN_CHANNEL_LIST_TO_HOST_SUPPORT; wmi_service[wmi_service_host_scan_stop_vdev_all] = WMI_SERVICE_HOST_SCAN_STOP_VDEV_ALL_SUPPORT; + wmi_service[wmi_service_suiteb_roam_support] = + WMI_SERVICE_WPA3_SUITEB_ROAM_SUPPORT; } #ifndef CONFIG_MCL From 7944d1afcaa339a9edc905cf07d508ec22abd9bf Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Tue, 19 May 2020 23:15:38 +0530 Subject: [PATCH 046/208] qcacld-3.0: Update beacon rpt error code Currently, There is no check for new report to find if previous beacon report request is in progress. So whenever a new beacon report request comes, it is processed without consideration of any ongoing beacon request processing. Fix is to add a check of request in progress and append err code BCN_RPT_ERR_PREVIOUS_REQUEST_PROGRESS in measurement report response. To find that curr report request is in progress, add a check mac_ctx->rrm.rrmPEContext.pCurrentReq[index]. For valid mac_ctx->rrm.rrmPEContext.pCurrentReq[index] err vsie will append. Change-Id: I91127c5c9ccaa19f20c29c85524b89b873e02e17 CRs-Fixed: 2668127 --- core/mac/src/pe/rrm/rrm_api.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c index aa4935034042..e243379ab533 100644 --- a/core/mac/src/pe/rrm/rrm_api.c +++ b/core/mac/src/pe/rrm/rrm_api.c @@ -1113,7 +1113,8 @@ QDF_STATUS rrm_process_beacon_req(tpAniSirGlobal mac_ctx, tSirMacAddr peer, tpSirMacRadioMeasureReport report; tpRRMReq curr_req; - if (index >= MAX_MEASUREMENT_REQUEST) { + if (index >= MAX_MEASUREMENT_REQUEST || + mac_ctx->rrm.rrmPEContext.pCurrentReq[index]) { if (*radiomes_report == NULL) { /* * Allocate memory to send reports for From a2b4f7b28654497b1291042e7d65e7b52c0384f3 Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Thu, 19 Mar 2020 17:09:48 +0530 Subject: [PATCH 047/208] qcacld-3.0: Add support for WPA3 SuiteB roaming This commit enables support for SuiteB roaming for SHA384. Based on the WPA3 SuiteB roam service capability advertisement received from Firmware, we enable the support in Host. Change-Id: Iab4e6bfc9c8ba7d604c2720c8cb848fce40dd6b4 CRs-Fixed: 2685975 --- core/mac/inc/sir_api.h | 1 + core/sme/inc/csr_api.h | 3 +++ core/sme/src/csr/csr_api_roam.c | 13 +++++++++++++ core/wma/src/wma_main.c | 2 ++ 4 files changed, 19 insertions(+) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index d222721de8f1..3191ff451746 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -171,6 +171,7 @@ struct mlme_roam_debug_info { #define AKM_FT_FILS 2 #define AKM_SAE 3 #define AKM_OWE 4 +#define AKM_SUITEB 5 /** * enum sir_roam_op_code - Operation to be done by the callback. diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 5822055762a1..c4396ea2e8fa 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1794,6 +1794,9 @@ typedef QDF_STATUS (*csr_session_close_cb)(uint8_t session_id); #define CSR_IS_FW_FT_FILS_SUPPORTED(fw_akm_bitmap) \ (((fw_akm_bitmap) & (1 << AKM_FT_FILS)) ? true : false) +#define CSR_IS_FW_SUITEB_ROAM_SUPPORTED(fw_akm_bitmap) \ + (((fw_akm_bitmap) & (1 << AKM_SUITEB)) ? true : false) + QDF_STATUS csr_set_channels(tpAniSirGlobal pMac, tCsrConfigParam *pParam); /* enum to string conversion for debug output */ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index a4bbb2179a54..2330bf1619fa 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -240,6 +240,8 @@ enum mgmt_auth_type diag_auth_type_from_csr_type(eCsrAuthType authtype) n = AUTH_WPA_PSK; break; case eCSR_AUTH_TYPE_RSN: + case eCSR_AUTH_TYPE_SUITEB_EAP_SHA256: + case eCSR_AUTH_TYPE_SUITEB_EAP_SHA384: #ifdef WLAN_FEATURE_11W case eCSR_AUTH_TYPE_RSN_8021X_SHA256: #endif @@ -7330,6 +7332,8 @@ static QDF_STATUS csr_roam_save_params(tpAniSirGlobal mac_ctx, (eCSR_AUTH_TYPE_FT_RSN_PSK == auth_type) || (eCSR_AUTH_TYPE_FT_SAE == auth_type) || (eCSR_AUTH_TYPE_FT_SUITEB_EAP_SHA384 == auth_type) || + (eCSR_AUTH_TYPE_SUITEB_EAP_SHA256 == auth_type) || + (eCSR_AUTH_TYPE_SUITEB_EAP_SHA384 == auth_type) || #if defined WLAN_FEATURE_11W (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == auth_type) || (eCSR_AUTH_TYPE_RSN_8021X_SHA256 == auth_type) || @@ -7513,6 +7517,8 @@ static QDF_STATUS csr_roam_save_security_rsp_ie(tpAniSirGlobal pMac, (eCSR_AUTH_TYPE_FT_RSN_PSK == authType) || (eCSR_AUTH_TYPE_FT_SAE == authType) || (eCSR_AUTH_TYPE_FT_SUITEB_EAP_SHA384 == authType) + || (eCSR_AUTH_TYPE_SUITEB_EAP_SHA256 == authType) + || (eCSR_AUTH_TYPE_SUITEB_EAP_SHA384 == authType) #ifdef FEATURE_WLAN_WAPI || (eCSR_AUTH_TYPE_WAPI_WAI_PSK == authType) || (eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE == authType) @@ -21756,6 +21762,13 @@ csr_roam_offload_scan(tpAniSirGlobal mac_ctx, uint8_t session_id, return QDF_STATUS_SUCCESS; } + if ((roam_profile_akm == eCSR_AUTH_TYPE_SUITEB_EAP_SHA256 || + roam_profile_akm == eCSR_AUTH_TYPE_SUITEB_EAP_SHA384) && + !CSR_IS_FW_SUITEB_ROAM_SUPPORTED(fw_akm_bitmap)) { + sme_info("Roaming not supported for SUITEB connection"); + return QDF_STATUS_SUCCESS; + } + /* * If fw doesn't advertise FT SAE, FT-FILS or FT-Suite-B capability, * don't support roaming to that profile diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 7afd1a4eb853..4f4cb7ee86a8 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -5132,6 +5132,8 @@ static inline void wma_update_target_services(struct wmi_unified *wmi_handle, if (wmi_service_enabled(wmi_handle, wmi_roam_scan_chan_list_to_host_support)) cfg->is_roam_scan_ch_to_host = true; + if (wmi_service_enabled(wmi_handle, wmi_service_suiteb_roam_support)) + cfg->akm_service_bitmap |= (1 << AKM_SUITEB); } /** From cda25ba9f21006a0fffd028bc184937e0eb8f1fb Mon Sep 17 00:00:00 2001 From: nshrivas Date: Wed, 20 May 2020 06:16:31 -0700 Subject: [PATCH 048/208] Release 5.2.03.27A Release 5.2.03.27A Change-Id: I2ac709faa88a979d8ce4448951eb268c1d8e680a CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index c9b1e639ff22..46b262306f21 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "" +#define QWLAN_VERSION_EXTRA "A" #define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.27" +#define QWLAN_VERSIONSTR "5.2.03.27A" #endif /* QWLAN_VERSION_H */ From 97377ff3af2d6625abade8e762e5f3632de1ef89 Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Thu, 26 Mar 2020 17:28:27 +0530 Subject: [PATCH 049/208] qcacld-3.0: Ageout connected BSS in beacon table mode The driver doesn't ageout connected BSS from rrm scan result after the scan default ageout time. This results in connected AP information sent in beacon report request in table mode always. Fill the ageout threshold value as the default scan age out time in the rrm scan filter. Change-Id: I8f9b0457bd93e2d9b51a772bdbdfb01dcd429c56 CRs-Fixed: 2650915 --- core/sme/inc/csr_api.h | 1 + core/sme/src/csr/csr_api_scan.c | 1 + core/sme/src/rrm/sme_rrm.c | 15 ++++++++++----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index c4396ea2e8fa..fce0b91dd7aa 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -359,6 +359,7 @@ typedef struct tagCsrScanResultFilter { bool realm_check; uint8_t fils_realm[2]; bool force_rsne_override; + qdf_time_t age_threshold; } tCsrScanResultFilter; typedef struct sCsrChnPower_ { diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 127380947f45..41cd6efc0cd0 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -2547,6 +2547,7 @@ static QDF_STATUS csr_prepare_scan_filter(tpAniSirGlobal mac_ctx, filter->ignore_auth_enc_type = true; filter->rrm_measurement_filter = pFilter->fMeasurement; + filter->age_threshold = pFilter->age_threshold; filter->mobility_domain = pFilter->MDID.mobilityDomain; diff --git a/core/sme/src/rrm/sme_rrm.c b/core/sme/src/rrm/sme_rrm.c index ef4c0b1dfd27..a2886b91265e 100644 --- a/core/sme/src/rrm/sme_rrm.c +++ b/core/sme/src/rrm/sme_rrm.c @@ -478,6 +478,16 @@ static QDF_STATUS sme_rrm_send_scan_result(tpAniSirGlobal mac_ctx, filter.ChannelInfo.ChannelList = chan_list; filter.fMeasurement = true; + if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource || + eRRM_MSG_SOURCE_LEGACY_ESE == rrm_ctx->msgSource) + scan_type = rrm_ctx->measMode[rrm_ctx->currentIndex]; + else + scan_type = rrm_ctx->measMode[0]; + + if (scan_type == eSIR_BEACON_TABLE) + filter.age_threshold = + ucfg_scan_get_aging_time(mac_ctx->psoc); + /* * In case this is beacon report request from last AP (before roaming) * following call to csr_roam_get_session_id_from_bssid will fail, @@ -573,11 +583,6 @@ static QDF_STATUS sme_rrm_send_scan_result(tpAniSirGlobal mac_ctx, goto rrm_send_scan_results_done; } - if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource || - eRRM_MSG_SOURCE_LEGACY_ESE == rrm_ctx->msgSource) - scan_type = rrm_ctx->measMode[rrm_ctx->currentIndex]; - else - scan_type = rrm_ctx->measMode[0]; while (scan_results) { /* From ce387ec0170534f475b071eb65179d3330f609b4 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Wed, 20 May 2020 07:59:22 -0700 Subject: [PATCH 050/208] Release 5.2.03.27B Release 5.2.03.27B Change-Id: I783a9103e32191f896a86f11d114a09d859717ee CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 46b262306f21..8fd22622eb4d 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "A" +#define QWLAN_VERSION_EXTRA "B" #define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.27A" +#define QWLAN_VERSIONSTR "5.2.03.27B" #endif /* QWLAN_VERSION_H */ From f0361e4ff4d28cdb5ce7ab8a069c5b1b56044d1f Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Wed, 20 May 2020 00:55:53 +0530 Subject: [PATCH 051/208] qcacmn: Introduce scan api to get scan entry ageout time The driver doesn't ageout connected BSS from rrm scan result after the scan default ageout time. This results in connected AP information sent in beacon report request in table mode always. Introduce scan api to get the scan age out time configured from scan module. This value will be used as the threshold in rrm scan filter. Change-Id: Ib3981538faf179cff53936770f705d41922dca66 CRs-Fixed: 2650914 --- umac/scan/core/src/wlan_scan_filter.c | 4 ++++ umac/scan/dispatcher/inc/wlan_scan_public_structs.h | 2 +- umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h | 8 ++++++++ umac/scan/dispatcher/src/wlan_scan_ucfg_api.c | 11 +++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/umac/scan/core/src/wlan_scan_filter.c b/umac/scan/core/src/wlan_scan_filter.c index db535b3c6efb..0611c31d9d78 100644 --- a/umac/scan/core/src/wlan_scan_filter.c +++ b/umac/scan/core/src/wlan_scan_filter.c @@ -1148,6 +1148,10 @@ bool scm_filter_match(struct wlan_objmgr_psoc *psoc, if (!def_param) return false; + if (filter->age_threshold && + filter->age_threshold < util_scan_entry_age(db_entry)) + return false; + roam_params = &def_param->roam_params; if (filter->p2p_results && !db_entry->is_p2p) diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h index d17bd97df255..d3ba67f40013 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h +++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h @@ -559,7 +559,7 @@ struct fils_filter_info { struct scan_filter { bool bss_scoring_required; bool enable_adaptive_11r; - uint32_t age_threshold; + qdf_time_t age_threshold; uint32_t p2p_results; uint32_t rrm_measurement_filter; uint32_t num_of_bssid; diff --git a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h index ac87f2f61b7a..9bec549eb387 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h @@ -656,4 +656,12 @@ bool ucfg_scan_wake_lock_in_user_scan(struct wlan_objmgr_psoc *psoc); * Return: Max Scan commands allowed count */ uint32_t ucfg_scan_get_max_cmd_allowed(void); + +/** + * wlan_scan_get_aging_time - Get the scan aging time config + * @psoc: psoc context + * + * Return: Scan aging time config + */ +qdf_time_t ucfg_scan_get_aging_time(struct wlan_objmgr_psoc *psoc); #endif diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index 12f18d309736..734e75f4e3a2 100644 --- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -2530,3 +2530,14 @@ uint32_t ucfg_scan_get_max_cmd_allowed(void) { return MAX_SCAN_COMMANDS; } + +qdf_time_t ucfg_scan_get_aging_time(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_scan_obj *scan_obj; + + scan_obj = wlan_psoc_get_scan_obj(psoc); + if (!scan_obj) + return SCAN_CACHE_AGING_TIME; + + return scan_obj->scan_def.scan_cache_aging_time; +} From bd053c3196f79872f38379d6e249f45154eda80f Mon Sep 17 00:00:00 2001 From: Alan Chen Date: Tue, 19 May 2020 11:20:52 -0700 Subject: [PATCH 052/208] qcacld-3.0: Fix LL Timeout over Debugfs Clear the stats bitmap properly such that LL stats is complete. Change-Id: I1238c438e9d57000006ae46474569c4f2cf60e8f CRs-Fixed: 2690186 --- core/hdd/src/wlan_hdd_stats.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index c65a3c60b3f2..e7a9e70a6948 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -1210,6 +1210,8 @@ static void hdd_debugfs_process_ll_stats(struct hdd_adapter *adapter, if (!results->num_peers) priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER); + + priv->request_bitmap &= ~(WMI_LINK_STATS_IFACE); } else if (results->paramId & WMI_LINK_STATS_ALL_PEER) { hdd_debugfs_process_peer_stats(adapter, results->results); if (!results->moreResultToFollow) From d1c5d9bb6a3adf2f85a2f3d4140a3f025dd7d778 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Thu, 21 May 2020 00:00:14 -0700 Subject: [PATCH 053/208] Release 5.2.03.27C Release 5.2.03.27C Change-Id: I0641fb826013c463fd76031c94e75e37784f88d6 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 8fd22622eb4d..cac57bafffe2 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "B" +#define QWLAN_VERSION_EXTRA "C" #define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.27B" +#define QWLAN_VERSIONSTR "5.2.03.27C" #endif /* QWLAN_VERSION_H */ From 289e86bb19322b66a59e7d8854e0748ad5c0ebff Mon Sep 17 00:00:00 2001 From: Bapiraju Alla Date: Tue, 5 May 2020 20:43:19 +0530 Subject: [PATCH 054/208] qcacmn: Increase HTC control msg timeout to 6 seconds Currently, HTC_CONTROL_RX_TIMEOUT is set to 3 seconds. This is causing HTC control message timeout issue. To resolve this, increase HTC_CONTROL_RX_TIMEOUT to 6 seconds. Change-Id: I3ea0f89c48347a6d509dafea86af0f882452d04f CRs-Fixed: 2671719 --- htc/htc_recv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htc/htc_recv.c b/htc/htc_recv.c index bd52a9ed88e9..1f18e2a63446 100644 --- a/htc/htc_recv.c +++ b/htc/htc_recv.c @@ -22,7 +22,7 @@ #include /* qdf_nbuf_t */ /* HTC Control message receive timeout msec */ -#define HTC_CONTROL_RX_TIMEOUT 3000 +#define HTC_CONTROL_RX_TIMEOUT 6000 #if defined(WLAN_DEBUG) || defined(DEBUG) void debug_dump_bytes(uint8_t *buffer, uint16_t length, char *pDescription) From 57648dee69e305257aa42cdd972b892029927ddd Mon Sep 17 00:00:00 2001 From: spuligil Date: Thu, 14 May 2020 06:00:37 -0700 Subject: [PATCH 055/208] fw-api: CL 10450925 - update fw common interface files Add WLAN_ROAM_SCORE_BAND_6G_INDEX def Change-Id: I12cea3f3c006623178b589e076b02a953db93e3b CRs-Fixed: 2262693 --- fw/wmi_unified.h | 3 ++- fw/wmi_version.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index c0bf6382701d..669cf0911416 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -13513,7 +13513,8 @@ typedef struct { #define WLAN_ROAM_SCORE_BAND_2G_INDEX 0 #define WLAN_ROAM_SCORE_BAND_5G_INDEX 1 -/* 2 and 3 are reserved */ +#define WLAN_ROAM_SCORE_BAND_6G_INDEX 2 +/* 3 is reserved */ #define WLAN_ROAM_SCORE_MAX_BAND_INDEX 4 #define WMI_ROAM_GET_BAND_SCORE_PERCENTAGE(value32, band_index) WMI_GET_BITS(value32, (8 * (band_index)), 8) #define WMI_ROAM_SET_BAND_SCORE_PERCENTAGE(value32, score_pcnt, band_index) WMI_SET_BITS(value32, (8 * (band_index)), 8, score_pcnt) diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 737285e33b20..b19ade10e1e0 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 836 +#define __WMI_REVISION_ 837 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 97ba8d7411387f1ef6bffe38b49d620cd96d93db Mon Sep 17 00:00:00 2001 From: spuligil Date: Fri, 15 May 2020 06:00:38 -0700 Subject: [PATCH 056/208] fw-api: CL 10462927 - update fw common interface files Change-Id: I92c08d0d524be484b000c2abffff4432d121217a WMI: add PMF beacon protect stats CRs-Fixed: 2262693 --- fw/wmi_tlv_defs.h | 4 +++- fw/wmi_unified.h | 46 +++++++++++++++++++++++++++++++--------------- fw/wmi_version.h | 2 +- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/fw/wmi_tlv_defs.h b/fw/wmi_tlv_defs.h index 9d3a5a270faa..191487a3c815 100644 --- a/fw/wmi_tlv_defs.h +++ b/fw/wmi_tlv_defs.h @@ -1076,6 +1076,7 @@ typedef enum { WMITLV_TAG_STRUC_wmi_pdev_non_srg_obss_color_enable_bitmap_cmd_fixed_param, WMITLV_TAG_STRUC_wmi_pdev_non_srg_obss_bssid_enable_bitmap_cmd_fixed_param, WMITLV_TAG_STRUC_wmi_roam_capability_report_event_fixed_param, + WMITLV_TAG_STRUC_wmi_pmf_bcn_protect_stats, } WMITLV_TAG_ID; /* @@ -4916,7 +4917,8 @@ WMITLV_CREATE_PARAM_STRUC(WMI_HOST_SWFDA_EVENTID); WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats, wmi_per_chain_rssi_stats, chain_stats, WMITLV_SIZE_FIX) \ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_rssi_stats, rssi_stats, WMITLV_SIZE_VAR) \ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_congestion_stats, congestion_stats, WMITLV_SIZE_VAR) \ - WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_peer_extd2_stats, peer_extd2_stats, WMITLV_SIZE_VAR) + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_peer_extd2_stats, peer_extd2_stats, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_pmf_bcn_protect_stats, pmf_bcn_protect_stats, WMITLV_SIZE_VAR) WMITLV_CREATE_PARAM_STRUC(WMI_UPDATE_STATS_EVENTID); /* Update PN response Event */ diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index 669cf0911416..7e6069d768d7 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -7533,21 +7533,22 @@ typedef struct { } wmi_pdev_set_wmm_params_cmd_fixed_param; typedef enum { - WMI_REQUEST_PEER_STAT = 0x0001, - WMI_REQUEST_AP_STAT = 0x0002, - WMI_REQUEST_PDEV_STAT = 0x0004, - WMI_REQUEST_VDEV_STAT = 0x0008, - WMI_REQUEST_BCNFLT_STAT = 0x0010, - WMI_REQUEST_VDEV_RATE_STAT = 0x0020, - WMI_REQUEST_INST_STAT = 0x0040, - WMI_REQUEST_MIB_STAT = 0x0080, - WMI_REQUEST_RSSI_PER_CHAIN_STAT = 0x0100, - WMI_REQUEST_CONGESTION_STAT = 0x0200, - WMI_REQUEST_PEER_EXTD_STAT = 0x0400, - WMI_REQUEST_BCN_STAT = 0x0800, - WMI_REQUEST_BCN_STAT_RESET = 0x1000, - WMI_REQUEST_PEER_EXTD2_STAT = 0x2000, - WMI_REQUEST_MIB_EXTD_STAT = 0x4000, + WMI_REQUEST_PEER_STAT = 0x0001, + WMI_REQUEST_AP_STAT = 0x0002, + WMI_REQUEST_PDEV_STAT = 0x0004, + WMI_REQUEST_VDEV_STAT = 0x0008, + WMI_REQUEST_BCNFLT_STAT = 0x0010, + WMI_REQUEST_VDEV_RATE_STAT = 0x0020, + WMI_REQUEST_INST_STAT = 0x0040, + WMI_REQUEST_MIB_STAT = 0x0080, + WMI_REQUEST_RSSI_PER_CHAIN_STAT = 0x0100, + WMI_REQUEST_CONGESTION_STAT = 0x0200, + WMI_REQUEST_PEER_EXTD_STAT = 0x0400, + WMI_REQUEST_BCN_STAT = 0x0800, + WMI_REQUEST_BCN_STAT_RESET = 0x1000, + WMI_REQUEST_PEER_EXTD2_STAT = 0x2000, + WMI_REQUEST_MIB_EXTD_STAT = 0x4000, + WMI_REQUEST_PMF_BCN_PROTECT_STAT = 0x8000, } wmi_stats_id; /* @@ -8268,6 +8269,10 @@ typedef struct { * num_mib_extd_stats * size of(struct wmi_mib_extd_stats) * following the information elements listed above. */ +/* If WMI_REQUEST_PMF_BCN_PROTECT_STAT is set in stats_id, then TLV + * wmi_pmf_bcn_protect_stats pmf_bcn_protect_stats[] + * follows the other TLVs + */ } wmi_stats_event_fixed_param; /* WLAN channel CCA stats bitmap */ @@ -9122,6 +9127,17 @@ typedef struct { A_UINT32 reserved[8]; /* Reserve more fields for future extension */ } wmi_mib_extd_stats; +/** + * Beacon protection statistics. + */ +typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pmf_bcn_protect_stats */ + A_UINT32 igtk_mic_fail_cnt; /* MIC failure count of management packets using IGTK */ + A_UINT32 igtk_replay_cnt; /* Replay detection count of management packets using IGTK */ + A_UINT32 bcn_mic_fail_cnt; /* MIC failure count of beacon packets using BIGTK */ + A_UINT32 bcn_replay_cnt; /* Replay detection count of beacon packets using BIGTK */ +} wmi_pmf_bcn_protect_stats; + typedef struct { A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_rssi_stats */ A_UINT32 vdev_id; diff --git a/fw/wmi_version.h b/fw/wmi_version.h index b19ade10e1e0..e291e375f36f 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 837 +#define __WMI_REVISION_ 838 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 8546af56546d1702a337b6a196f47c2af1e69f31 Mon Sep 17 00:00:00 2001 From: spuligil Date: Fri, 15 May 2020 06:00:51 -0700 Subject: [PATCH 057/208] fw-api: CL 10466792 - update fw common interface files HTT stats: add RSSI values in ul_mumimo_trig TLV Change-Id: Iff5bef545941ba45026e64b4a118d3056e8e7044 CRs-Fixed: 2262693 --- fw/htt_stats.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fw/htt_stats.h b/fw/htt_stats.h index 674176f723df..99a1e8cd1d4c 100644 --- a/fw/htt_stats.h +++ b/fw/htt_stats.h @@ -3596,6 +3596,8 @@ typedef struct { #define HTT_RX_PDEV_STATS_NUM_GI_COUNTERS 4 #define HTT_RX_PDEV_STATS_NUM_DCM_COUNTERS 5 #define HTT_RX_PDEV_STATS_NUM_BW_COUNTERS 4 +#define HTT_RX_PDEV_STATS_TOTAL_BW_COUNTERS \ + (HTT_RX_PDEV_STATS_NUM_BW_EXT_COUNTERS + HTT_RX_PDEV_STATS_NUM_BW_COUNTERS) #define HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS 8 #define HTT_RX_PDEV_STATS_ULMUMIMO_NUM_SPATIAL_STREAMS 8 #define HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES HTT_STATS_PREAM_COUNT @@ -3901,6 +3903,15 @@ typedef struct { /* Stats for MCS 12/13 */ A_UINT32 ul_mumimo_rx_mcs_ext[HTT_RX_PDEV_STATS_NUM_EXTRA_MCS_COUNTERS]; A_UINT32 ul_mumimo_rx_gi_ext[HTT_RX_PDEV_STATS_NUM_GI_COUNTERS][HTT_RX_PDEV_STATS_NUM_EXTRA_MCS_COUNTERS]; + + /* RSSI in dBm for Rx TB PPDUs */ + A_INT8 rx_ul_mumimo_chain_rssi_in_dbm[HTT_RX_PDEV_STATS_ULMUMIMO_NUM_SPATIAL_STREAMS][HTT_RX_PDEV_STATS_TOTAL_BW_COUNTERS]; + /* Target RSSI stats for UL MUMIMO triggers. Units dBm */ + A_INT8 rx_ul_mumimo_target_rssi[HTT_TX_PDEV_STATS_NUM_UL_MUMIMO_USER_STATS][HTT_RX_PDEV_STATS_NUM_BW_COUNTERS]; + /* FD RSSI stats for UL TB PPDUs. Units dBm */ + A_INT8 rx_ul_mumimo_fd_rssi[HTT_TX_PDEV_STATS_NUM_UL_MUMIMO_USER_STATS][HTT_RX_PDEV_STATS_ULMUMIMO_NUM_SPATIAL_STREAMS]; + /* Pilot EVM Stats */ + A_INT8 rx_ulmumimo_pilot_evm_dB_mean[HTT_TX_PDEV_STATS_NUM_UL_MUMIMO_USER_STATS][HTT_RX_PDEV_STATS_ULMUMIMO_NUM_SPATIAL_STREAMS]; } htt_rx_pdev_ul_mumimo_trig_stats_tlv; /* STATS_TYPE : HTT_DBG_EXT_STATS_PDEV_UL_MUMIMO_TRIG_STATS From 4223ec46e5e423535d7fbef591feb323c0bf4967 Mon Sep 17 00:00:00 2001 From: spuligil Date: Fri, 15 May 2020 18:00:43 -0700 Subject: [PATCH 058/208] fw-api: CL 10474092 - update fw common interface files Change-Id: I89e776dbf47873a2d5cc37b66821ac163be97702 WMI: add macros to get/set/clear pdev+vdev Spatial Reuse param bitfields CRs-Fixed: 2262693 --- fw/wmi_unified.h | 17 +++++++++++++++++ fw/wmi_version.h | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index 7e6069d768d7..d83f78c47551 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -6818,6 +6818,23 @@ typedef enum { #define WMI_PDEV_LSIG_LEN_DURATION_GET(lsig_len) WMI_GET_BITS(lsig_len, 0, 30) #define WMI_PDEV_LSIG_LEN_DURATION_SET(lsig_len, value) WMI_SET_BITS(lsig_len, 0, 30, value) +#define WMI_PDEV_IS_NON_SRG_ENABLED(pd_threshold_cfg) WMI_GET_BITS(pd_threshold_cfg, 31, 1) +#define WMI_PDEV_NON_SRG_ENABLE(pd_threshold_cfg) WMI_SET_BITS(pd_threshold_cfg, 31, 1, 1) +#define WMI_PDEV_NON_SRG_DISABLE(pd_threshold_cfg) WMI_SET_BITS(pd_threshold_cfg, 31, 1, 0) +#define WMI_PDEV_NON_SRG_PD_THRESHOLD_SET(pd_threshold_cfg, value) WMI_SET_BITS(pd_threshold_cfg, 0, 8, value) +#define WMI_PDEV_NON_SRG_PD_THRESHOLD_GET(pd_threshold_cfg) WMI_GET_BITS(pd_threshold_cfg, 0, 8) + +#define WMI_PDEV_IS_SRG_ENABLED(pd_threshold_cfg) WMI_GET_BITS(pd_threshold_cfg, 30, 1) +#define WMI_PDEV_SRG_ENABLE(pd_threshold_cfg) WMI_SET_BITS(pd_threshold_cfg, 30, 1, 1) +#define WMI_PDEV_SRG_DISABLE(pd_threshold_cfg) WMI_SET_BITS(pd_threshold_cfg, 30, 1, 0) +#define WMI_PDEV_SRG_PD_THRESHOLD_SET(pd_threshold_cfg, value) WMI_SET_BITS(pd_threshold_cfg, 8, 8, value) +#define WMI_PDEV_SRG_PD_THRESHOLD_GET(pd_threshold_cfg) WMI_GET_BITS(pd_threshold_cfg, 8, 8) + +#define WMI_PDEV_OBSS_PD_ENABLE_PER_AC_SET(per_ac_cfg, value) WMI_SET_BITS(per_ac_cfg, 0, 4, value) + #define WMI_PDEV_OBSS_PD_ENABLE_PER_AC_GET(per_ac_cfg, value) WMI_GET_BITS(per_ac_cfg, 0, 4) +#define WMI_PDEV_SRP_ENABLE_PER_AC_SET(per_ac_cfg, value) WMI_SET_BITS(per_ac_cfg, 16, 4, value) + #define WMI_PDEV_SRP_ENABLE_PER_AC_GET(per_ac_cfg, value) WMI_GET_BITS(per_ac_cfg, 16, 4) + typedef struct { A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_set_param_cmd_fixed_param */ /** pdev_id for identifying the MAC diff --git a/fw/wmi_version.h b/fw/wmi_version.h index e291e375f36f..2de031bbbf66 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 838 +#define __WMI_REVISION_ 839 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From c67b6e87bef9aff7698b7aed75de734bad4816e4 Mon Sep 17 00:00:00 2001 From: spuligil Date: Sat, 16 May 2020 06:00:45 -0700 Subject: [PATCH 059/208] fw-api: CL 10477480 - update fw common interface files Change-Id: I3bd72cfa63d57b15e3e23f982a6e765097ff66fd WMI: add NAN capability TLV to SERVICE_READY_EXT2_EVENT msg CRs-Fixed: 2262693 --- fw/wmi_tlv_defs.h | 4 +++- fw/wmi_unified.h | 14 ++++++++++++++ fw/wmi_version.h | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/fw/wmi_tlv_defs.h b/fw/wmi_tlv_defs.h index 191487a3c815..5991426a5459 100644 --- a/fw/wmi_tlv_defs.h +++ b/fw/wmi_tlv_defs.h @@ -1077,6 +1077,7 @@ typedef enum { WMITLV_TAG_STRUC_wmi_pdev_non_srg_obss_bssid_enable_bitmap_cmd_fixed_param, WMITLV_TAG_STRUC_wmi_roam_capability_report_event_fixed_param, WMITLV_TAG_STRUC_wmi_pmf_bcn_protect_stats, + WMITLV_TAG_STRUC_wmi_nan_capabilities, } WMITLV_TAG_ID; /* @@ -4459,7 +4460,8 @@ WMITLV_CREATE_PARAM_STRUC(WMI_SERVICE_READY_EXT_EVENTID); WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WMI_DMA_RING_CAPABILITIES, dma_ring_caps, WMITLV_SIZE_VAR) \ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_spectral_bin_scaling_params, wmi_bin_scaling_params, WMITLV_SIZE_VAR) \ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WMI_MAC_PHY_CAPABILITIES_EXT, mac_phy_caps, WMITLV_SIZE_VAR) \ - WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WMI_HAL_REG_CAPABILITIES_EXT2, hal_reg_caps, WMITLV_SIZE_VAR) + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, WMI_HAL_REG_CAPABILITIES_EXT2, hal_reg_caps, WMITLV_SIZE_VAR) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_nan_capabilities, wmi_nan_capabilities, nan_cap, WMITLV_SIZE_FIX) WMITLV_CREATE_PARAM_STRUC(WMI_SERVICE_READY_EXT2_EVENTID); #define WMITLV_TABLE_WMI_CHAN_RF_CHARACTERIZATION_INFO_EVENTID(id,op,buf,len) \ diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index d83f78c47551..042afcf68061 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -3651,6 +3651,13 @@ typedef struct { * for any EMA VAP on any pdev. */ A_UINT32 ema_max_profile_period; + /** @brief max_ndp_sessions + * This is the max ndp sessions sent by the host which is the minimum + * of the value requested within the host's ini configurations and + * the max ndp sessions supported by the firmware (as reported in the + * SERVICE_READY_EXT2_EVENT message). + */ + A_UINT32 max_ndp_sessions; } wmi_resource_config; #define WMI_MSDU_FLOW_AST_ENABLE_GET(msdu_flow_config0, ast_x) \ @@ -19022,6 +19029,13 @@ typedef struct { */ } wmi_nan_dmesg_event_fixed_param; +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUCT_wmi_nan_capabilities */ + A_UINT32 tlv_header; + /** Maximum number of ndp sessions supported by the Firmware */ + A_UINT32 max_ndp_sessions; +} wmi_nan_capabilities; + /** NAN DATA CMD's */ /** diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 2de031bbbf66..770cb0fc3e62 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 839 +#define __WMI_REVISION_ 840 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 8df81880c4af36758286a88e5d05c693d0377012 Mon Sep 17 00:00:00 2001 From: spuligil Date: Sat, 16 May 2020 18:00:35 -0700 Subject: [PATCH 060/208] fw-api: CL 10479358 - update fw common interface files HTT stats: provide number of page faults Change-Id: I17dee832273ebc3ee818990c5606f5332a739d68 CRs-Fixed: 2262693 --- fw/htt_stats.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/fw/htt_stats.h b/fw/htt_stats.h index 99a1e8cd1d4c..9a10f1f88119 100644 --- a/fw/htt_stats.h +++ b/fw/htt_stats.h @@ -4746,6 +4746,7 @@ typedef struct { #define HTT_LATENCY_PROFILE_MAX_HIST 3 #define HTT_STATS_MAX_PROF_STATS_NAME_LEN 32 +#define HTT_INTERRUPTS_LATENCY_PROFILE_MAX_HIST 3 typedef struct { htt_tlv_hdr_t tlv_hdr; /* print_header: @@ -4771,6 +4772,20 @@ typedef struct { */ A_UINT32 hist_intvl; A_UINT32 hist[HTT_LATENCY_PROFILE_MAX_HIST]; + A_UINT32 page_fault_max; /* max page faults in any 1 sampling window */ + A_UINT32 page_fault_total; /* summed over all sampling windows */ + /* ignored_latency_count: + * ignore some of profile latency to avoid avg skewing + */ + A_UINT32 ignored_latency_count; + /* interrupts_max: max interrupts within any single sampling window */ + A_UINT32 interrupts_max; + /* interrupts_hist: histogram of interrupt rate + * bin0 contains the number of sampling windows that had 0 interrupts, + * bin1 contains the number of sampling windows that had 1-4 interrupts, + * bin2 contains the number of sampling windows that had > 4 interrupts + */ + A_UINT32 interrupts_hist[HTT_INTERRUPTS_LATENCY_PROFILE_MAX_HIST]; } htt_latency_prof_stats_tlv; typedef struct { From 5ba9f43100eb1aa201f76fbbe9fa042d906e59b8 Mon Sep 17 00:00:00 2001 From: spuligil Date: Wed, 20 May 2020 06:00:45 -0700 Subject: [PATCH 061/208] fw-api: CL 10507628 - update fw common interface files WMI correction: move flags field from vdev_stop_cmd to vdev_up_cmd Change-Id: Iab1cb4932b425958c6b041d72924058f3361d141 CRs-Fixed: 2262693 --- fw/wmi_unified.h | 8 ++++---- fw/wmi_version.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index 042afcf68061..ac1196e2bb45 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -6838,9 +6838,9 @@ typedef enum { #define WMI_PDEV_SRG_PD_THRESHOLD_GET(pd_threshold_cfg) WMI_GET_BITS(pd_threshold_cfg, 8, 8) #define WMI_PDEV_OBSS_PD_ENABLE_PER_AC_SET(per_ac_cfg, value) WMI_SET_BITS(per_ac_cfg, 0, 4, value) - #define WMI_PDEV_OBSS_PD_ENABLE_PER_AC_GET(per_ac_cfg, value) WMI_GET_BITS(per_ac_cfg, 0, 4) + #define WMI_PDEV_OBSS_PD_ENABLE_PER_AC_GET(per_ac_cfg) WMI_GET_BITS(per_ac_cfg, 0, 4) #define WMI_PDEV_SRP_ENABLE_PER_AC_SET(per_ac_cfg, value) WMI_SET_BITS(per_ac_cfg, 16, 4, value) - #define WMI_PDEV_SRP_ENABLE_PER_AC_GET(per_ac_cfg, value) WMI_GET_BITS(per_ac_cfg, 16, 4) + #define WMI_PDEV_SRP_ENABLE_PER_AC_GET(per_ac_cfg) WMI_GET_BITS(per_ac_cfg, 16, 4) typedef struct { A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_pdev_set_param_cmd_fixed_param */ @@ -10014,14 +10014,14 @@ typedef struct { A_UINT32 profile_idx; /** the total profile numbers of non-trans aps (mbssid case). 0 means legacy AP */ A_UINT32 profile_num; + /** flags - this is a bitwise-or combination of WMI_VDEV_UP_FLAGS values */ + A_UINT32 flags; } wmi_vdev_up_cmd_fixed_param; typedef struct { A_UINT32 tlv_header; /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_stop_cmd_fixed_param */ /** unique id identifying the VDEV, generated by the caller */ A_UINT32 vdev_id; - /** flags - this is a bitwise-or combination of WMI_VDEV_UP_FLAGS values */ - A_UINT32 flags; } wmi_vdev_stop_cmd_fixed_param; typedef struct { diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 770cb0fc3e62..705f17af8a4d 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 840 +#define __WMI_REVISION_ 841 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From a6e5686a07879d5b060b4cc348d61e75949c67e8 Mon Sep 17 00:00:00 2001 From: spuligil Date: Thu, 21 May 2020 06:00:46 -0700 Subject: [PATCH 062/208] fw-api: CL 10521320 - update fw common interface files Change-Id: I158d6935219cf4738febc431ec1c03e20f450ecc WMI: add VDEV_PARAM_RSN_CAPABILITY def, add bigtk info to GTK_OFFLOAD msg CRs-Fixed: 2262693 --- fw/wmi_unified.h | 15 +++++++++++++-- fw/wmi_version.h | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index ac1196e2bb45..dd407c86251a 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -10947,7 +10947,7 @@ typedef enum { * take effect if the WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD * setting is also set for the pdev that the vdev belongs to. */ - WMI_VDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD, + WMI_VDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD, /* 0x9E */ /* Parameter used to configure OBSS Packet Detection per Access Category * for SRP based and OBSS_PD based spatial reuse feature. @@ -10971,7 +10971,14 @@ typedef enum { * if the WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC setting is also set for * the pdev that the vdev belongs to. */ - WMI_VDEV_PARAM_SET_CMD_OBSS_PD_PER_AC, + WMI_VDEV_PARAM_SET_CMD_OBSS_PD_PER_AC, /* 0x9F */ + + /** + * VDEV parameter to indicate RSN (Robust Security Network) capability. + * This value will be intersection of the local vdev's (STA's) + * RSN capability and the peer's (AP's) RSN capability. + */ + WMI_VDEV_PARAM_RSN_CAPABILITY, /* 0xA0 */ /* Parameter used to enable/disable SRP feature */ WMI_VDEV_PARAM_ENABLE_SRP, @@ -16140,6 +16147,10 @@ typedef struct { A_UINT8 gtk_keyLength; /* GTK key length */ A_UINT8 gtk_keyRSC[GTK_REPLAY_COUNTER_BYTES]; /* GTK key replay sequence counter */ A_UINT8 gtk_key[WMI_MAX_KEY_LEN]; /* GTK key data */ + A_UINT8 bigtk_keyIndex; /* Use if IGTK_OFFLOAD is defined */ + A_UINT8 bigtk_keyLength; /* Use if IGTK_OFFLOAD is defined */ + A_UINT8 bigtk_keyRSC[IGTK_PN_SIZE]; /* key replay sequence counter *//* Use if IGTK_OFFLOAD is defined */ + A_UINT8 bigtk_key[WMI_MAX_KEY_LEN]; /* Use if IGTK_OFFLOAD is defined */ } WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param; typedef struct { diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 705f17af8a4d..4d3653c9a36e 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 841 +#define __WMI_REVISION_ 842 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From b331b8d91d3ec4729b8c2da0bc24245e15165c19 Mon Sep 17 00:00:00 2001 From: spuligil Date: Thu, 21 May 2020 18:00:42 -0700 Subject: [PATCH 063/208] fw-api: CL 10528997 - update fw common interface files Change-Id: I7609cc2c5c3477558c086eed6a55eb5de7ffb1c9 WMI: control path stats request/report CRs-Fixed: 2262693 --- fw/wmi_services.h | 1 + fw/wmi_tlv_defs.h | 19 +++++++ fw/wmi_unified.h | 124 ++++++++++++++++++++++++++++++++++++++++++++++ fw/wmi_version.h | 2 +- 4 files changed, 145 insertions(+), 1 deletion(-) diff --git a/fw/wmi_services.h b/fw/wmi_services.h index c6acdd985333..b2b02cb3c1c5 100644 --- a/fw/wmi_services.h +++ b/fw/wmi_services.h @@ -442,6 +442,7 @@ typedef enum { WMI_SERVICE_5_DOT_9GHZ_SUPPORT = 247, /* Indicates FW supports new 5.9GHZ (scan, connection and so on) */ WMI_SERVICE_MU_PREAMBLE_PUNCTURE_SUPPORT = 248, /* Indicates FW supports MU preamble puncture */ WMI_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, /* Support for SRG, SRP based spatial reuse support */ + WMI_REQUEST_CTRL_PATH_STATS_REQUEST = 250, /* FW supports control path stats */ /******* ADD NEW SERVICES UP TO 256 HERE *******/ diff --git a/fw/wmi_tlv_defs.h b/fw/wmi_tlv_defs.h index 5991426a5459..c9bdc6fbd861 100644 --- a/fw/wmi_tlv_defs.h +++ b/fw/wmi_tlv_defs.h @@ -1078,6 +1078,9 @@ typedef enum { WMITLV_TAG_STRUC_wmi_roam_capability_report_event_fixed_param, WMITLV_TAG_STRUC_wmi_pmf_bcn_protect_stats, WMITLV_TAG_STRUC_wmi_nan_capabilities, + WMITLV_TAG_STRUC_wmi_request_ctrl_path_stats_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ctrl_path_stats_event_fixed_param, + WMITLV_TAG_STRUC_wmi_ctrl_path_pdev_stats_struct, } WMITLV_TAG_ID; /* @@ -1522,6 +1525,7 @@ typedef enum { OP(WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID) \ OP(WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID) \ OP(WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID) \ + OP(WMI_REQUEST_CTRL_PATH_STATS_CMDID) \ /* add new CMD_LIST elements above this line */ @@ -1772,6 +1776,7 @@ typedef enum { OP(WMI_AUDIO_AGGR_REPORT_STATISTICS_EVENTID) \ OP(WMI_PDEV_SSCAN_FW_PARAM_EVENTID) \ OP(WMI_ROAM_CAPABILITY_REPORT_EVENTID) \ + OP(WMI_CTRL_PATH_STATS_EVENTID) \ /* add new EVT_LIST elements above this line */ @@ -3990,6 +3995,14 @@ WMITLV_CREATE_PARAM_STRUC(WMI_REQUEST_WLAN_STATS_CMDID); WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_request_peer_stats_info_cmd_fixed_param, wmi_request_peer_stats_info_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) WMITLV_CREATE_PARAM_STRUC(WMI_REQUEST_PEER_STATS_INFO_CMDID); +/* Request Control Path stats info cmd */ +#define WMITLV_TABLE_WMI_REQUEST_CTRL_PATH_STATS_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_request_ctrl_path_stats_cmd_fixed_param, wmi_request_ctrl_path_stats_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, pdev_ids, WMITLV_SIZE_VAR)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_UINT32, A_UINT32, vdev_ids, WMITLV_SIZE_VAR)\ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_FIXED_STRUC, wmi_mac_addr, mac_addr_list, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_REQUEST_CTRL_PATH_STATS_CMDID); + /* Host sets the current country code */ #define WMITLV_TABLE_WMI_SET_CURRENT_COUNTRY_CMDID(id,op,buf,len) \ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_set_current_country_cmd_fixed_param, wmi_set_current_country_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) @@ -5725,6 +5738,12 @@ WMITLV_CREATE_PARAM_STRUC(WMI_VDEV_ENCRYPT_DECRYPT_DATA_RESP_EVENTID); WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_peer_stats_info, peer_stats_info, WMITLV_SIZE_VAR) WMITLV_CREATE_PARAM_STRUC(WMI_PEER_STATS_INFO_EVENTID); +/* Update Control Path stats event */ +#define WMITLV_TABLE_WMI_CTRL_PATH_STATS_EVENTID(id, op, buf, len) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_ctrl_path_stats_event_fixed_param, wmi_ctrl_path_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_ctrl_path_pdev_stats_struct, ctrl_path_pdev_stats, WMITLV_SIZE_VAR) +WMITLV_CREATE_PARAM_STRUC(WMI_CTRL_PATH_STATS_EVENTID); + #define WMITLV_TABLE_WMI_RADIO_CHAN_STATS_EVENTID(id, op, buf, len) \ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_radio_chan_stats_event_fixed_param, wmi_radio_chan_stats_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_STRUC, wmi_radio_chan_stats, radio_chan_stats, WMITLV_SIZE_VAR) diff --git a/fw/wmi_unified.h b/fw/wmi_unified.h index dd407c86251a..2b9c0821121b 100644 --- a/fw/wmi_unified.h +++ b/fw/wmi_unified.h @@ -914,6 +914,9 @@ typedef enum { /** request for WLM (wlan latency manager) stats */ WMI_REQUEST_WLM_STATS_CMDID, + /** request for control path stats */ + WMI_REQUEST_CTRL_PATH_STATS_CMDID, + /** ARP OFFLOAD REQUEST*/ WMI_SET_ARP_NS_OFFLOAD_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_ARP_NS_OFL), @@ -1732,6 +1735,10 @@ typedef enum { * and report WLM (WLAN latency manager) stats info to host */ WMI_WLM_STATS_EVENTID, + /** This event is used to respond to WMI_REQUEST_CTRL_PATH_STATS_CMDID + * and report stats info to host */ + WMI_CTRL_PATH_STATS_EVENTID, + /* NLO specific events */ /** NLO match event after the first match */ @@ -8857,6 +8864,73 @@ typedef struct { */ } wmi_peer_stats_info_event_fixed_param; +/** + * WMI arrays of length WMI_MGMT_FRAME_SUBTYPE_MAX use the + * IEEE802.11 standard's enumeration of mgmt frame subtypes: + * 0 -> IEEE80211_FC0_SUBTYPE_ASSOC_REQ + * 1 -> IEEE80211_FC0_SUBTYPE_ASSOC_RESP + * 2 -> IEEE80211_FC0_SUBTYPE_REASSOC_REQ + * 3 -> IEEE80211_FC0_SUBTYPE_REASSOC_RESP + * 4 -> IEEE80211_FC0_SUBTYPE_PROBE_REQ + * 5 -> IEEE80211_FC0_SUBTYPE_PROBE_RESP + * 6 -> Reserved + * 7 -> Reserved + * 8 -> IEEE80211_FC0_SUBTYPE_BEACON + * 9 -> IEEE80211_FC0_SUBTYPE_ATIM + * 10 -> IEEE80211_FC0_SUBTYPE_DISASSOC + * 11 -> IEEE80211_FC0_SUBTYPE_AUTH + * 12 -> IEEE80211_FC0_SUBTYPE_DEAUTH + * 13 -> IEEE80211_FCO_SUBTYPE_ACTION + * 14 -> IEEE80211_FC0_SUBTYPE_ACTION_NOACK + * 15 -> IEEE80211_FC0_SUBTYPE_RESERVED + */ +#define WMI_MGMT_FRAME_SUBTYPE_MAX 16 + +typedef struct { + /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_ctrl_path_pdev_stats_struct*/ + A_UINT32 tlv_header; + /** pdev_id for identifying the MAC */ + A_UINT32 pdev_id; + /** counter of how many times this pdev has + * transmitted each management frame sub-type */ + A_UINT32 tx_mgmt_subtype[WMI_MGMT_FRAME_SUBTYPE_MAX]; + /** counter of how many times this pdev has + * received each management frame sub-type */ + A_UINT32 rx_mgmt_subtype[WMI_MGMT_FRAME_SUBTYPE_MAX]; + /** scan fail dfs violation time in ms */ + A_UINT32 scan_fail_dfs_violation_time_ms; + /** NOL check failed latest channel frequency in MHz */ + A_UINT32 nol_check_fail_last_chan_freq; + /** NOL check failed timestamp in ms */ + A_UINT32 nol_check_fail_time_stamp_ms; + /** total peer create count */ + A_UINT32 total_peer_create_cnt; + /** total peer delete count */ + A_UINT32 total_peer_delete_cnt; + /** total peer delete response count */ + A_UINT32 total_peer_delete_resp_cnt; + /** sched algo FIFO full count */ + A_UINT32 vdev_pause_fail_rt_to_sched_algo_fifo_full_cnt; +} wmi_ctrl_path_pdev_stats_struct; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ctrl_path_stats_event_fixed_param */ + A_UINT32 tlv_header; + /** Request ID*/ + A_UINT32 request_id; + /** more flag + * 1 - More events sent after this event. + * 0 - no more events after this event. + */ + A_UINT32 more; + /** This TLV is (optionally) followed by TLV arrays containing + * different types of stats: + * 1. wmi_ctrl_path_pdev_stats_struct ctrl_path_pdev_stats[]; + * This TLV array contains zero or more pdev stats instances. + */ +} wmi_ctrl_path_stats_event_fixed_param; + typedef struct { /** TLV tag and len; tag equals * WMITLV_TAG_STRUC_wmi_radio_chan_stats */ @@ -24675,6 +24749,55 @@ typedef struct { A_UINT32 reset_after_request; } wmi_request_peer_stats_info_cmd_fixed_param; +typedef enum { + /* + * Multiple stats type can be requested together, so each value + * within this enum represents a bit within a stats bitmap. + */ + WMI_REQUEST_CTRL_PATH_PDEV_TX_STAT = 0x00000001, +} wmi_ctrl_path_stats_id; + +typedef enum { + /* + * The following stats actions are mutually exclusive. + * A single stats request message can only specify one action. + */ + WMI_REQUEST_CTRL_PATH_STAT_GET = 1, + WMI_REQUEST_CTRL_PATH_STAT_RESET = 2, + WMI_REQUEST_CTRL_PATH_STAT_START = 3, + WMI_REQUEST_CTRL_PATH_STAT_STOP = 4, +} wmi_ctrl_path_stats_action; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_request_ctrl_path_stats_cmd_fixed_param */ + A_UINT32 tlv_header; + /** Bitmask showing which of stats IDs 0-31 have been requested. + * These stats ids are defined in enum wmi_ctrl_path_stats_id. + */ + A_UINT32 stats_id_mask; + /** request ID to store the cookies in wifistats */ + A_UINT32 request_id; + /** action + * get/reset/start/stop based on stats id + * defined as a part of wmi_ctrl_path_stats_action + **/ + A_UINT32 action; /* refer to wmi_ctrl_path_stats_action */ + + /** The below TLV arrays optionally follow this fixed_param TLV structure: + * 1. A_UINT32 pdev_ids[]; + * If this array is present and non-zero length, stats should only + * be provided from the pdevs identified in the array. + * 2. A_UINT32 vdev_ids[]; + * If this array is present and non-zero length, stats should only + * be provided from the vdevs identified in the array. + * 3. wmi_mac_addr peer_macaddr[]; + * If this array is present and non-zero length, stats should only + * be provided from the peers with the MAC addresses specified + * in the array. + */ +} wmi_request_ctrl_path_stats_cmd_fixed_param; + typedef enum { WMI_REQUEST_ONE_RADIO_CHAN_STATS = 0x01, /* request stats of one specified channel */ WMI_REQUEST_ALL_RADIO_CHAN_STATS = 0x02, /* request stats of all channels */ @@ -26190,6 +26313,7 @@ static INLINE A_UINT8 *wmi_id_to_name(A_UINT32 wmi_command) WMI_RETURN_STRING(WMI_ANT_CONTROLLER_CMDID); WMI_RETURN_STRING(WMI_SIMULATION_TEST_CMDID); WMI_RETURN_STRING(WMI_AUDIO_AGGR_SET_RTSCTS_CONFIG_CMDID); + WMI_RETURN_STRING(WMI_REQUEST_CTRL_PATH_STATS_CMDID); } return "Invalid WMI cmd"; diff --git a/fw/wmi_version.h b/fw/wmi_version.h index 4d3653c9a36e..320431308605 100644 --- a/fw/wmi_version.h +++ b/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 842 +#define __WMI_REVISION_ 843 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work From 3c1486f5174650544d9bca8912ea4e461ccca642 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Thu, 21 May 2020 13:31:08 -0700 Subject: [PATCH 064/208] rmnet_shs: Remove local_bh_disable in oom handler Low memory handler in shs is in atomic context so prevent the disabling of bottom halves. Change-Id: I0eae18f8876edddd964346fee5b6b39af952d6fa Acked-by: Raul Martinez Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs_main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/rmnet/shs/rmnet_shs_main.c b/drivers/rmnet/shs/rmnet_shs_main.c index dec38c4e3d75..796858eab686 100755 --- a/drivers/rmnet/shs/rmnet_shs_main.c +++ b/drivers/rmnet/shs/rmnet_shs_main.c @@ -1511,7 +1511,7 @@ int rmnet_shs_drop_backlog(struct sk_buff_head *list, int cpu) return 0; } - +/* This will run in process context, avoid disabling bh */ static int rmnet_shs_oom_notify(struct notifier_block *self, unsigned long emtpy, void *free) { @@ -1520,7 +1520,6 @@ static int rmnet_shs_oom_notify(struct notifier_block *self, struct sk_buff_head *process_q; struct sk_buff_head *input_q; - local_bh_disable(); for_each_possible_cpu(cpu) { process_q = &GET_PQUEUE(cpu); @@ -1541,7 +1540,6 @@ static int rmnet_shs_oom_notify(struct notifier_block *self, (*nfree)++; } } - local_bh_enable(); return 0; } From 3eeb4840bf22a044425811402064c73d692484f4 Mon Sep 17 00:00:00 2001 From: Suraj Jaiswal Date: Wed, 27 May 2020 18:56:37 +0530 Subject: [PATCH 065/208] data-kernel: EMAC: copy from user fail handle Handle the fail case of copy from user & return proper error. Change-Id: Id74a422fb820d49e0bf270d561dfb2bbc92c30ff --- drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c | 20 ++++++++++++++------ drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.h | 4 ++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c index d2026101c6c0..d12097ea11ee 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c @@ -5728,11 +5728,11 @@ static int DWC_ETH_QOS_handle_prv_ioctl(struct DWC_ETH_QOS_prv_data *pdata, break; case DWC_ETH_QOS_DCB_ALGORITHM: - DWC_ETH_QOS_program_dcb_algorithm(pdata, req); + ret = DWC_ETH_QOS_program_dcb_algorithm(pdata, req); break; case DWC_ETH_QOS_AVB_ALGORITHM: - DWC_ETH_QOS_program_avb_algorithm(pdata, req); + ret = DWC_ETH_QOS_program_avb_algorithm(pdata, req); break; case DWC_ETH_QOS_RX_SPLIT_HDR_CMD: @@ -6805,19 +6805,22 @@ static void DWC_ETH_QOS_config_tx_pbl(struct DWC_ETH_QOS_prv_data *pdata, * \retval none */ -static void DWC_ETH_QOS_program_dcb_algorithm( +static int DWC_ETH_QOS_program_dcb_algorithm( struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct *req) { struct DWC_ETH_QOS_dcb_algorithm l_dcb_struct, *u_dcb_struct = (struct DWC_ETH_QOS_dcb_algorithm *)req->ptr; struct hw_if_struct *hw_if = &pdata->hw_if; + int ret = 0; DBGPR("-->DWC_ETH_QOS_program_dcb_algorithm\n"); if (copy_from_user(&l_dcb_struct, u_dcb_struct, - sizeof(struct DWC_ETH_QOS_dcb_algorithm))) + sizeof(struct DWC_ETH_QOS_dcb_algorithm))) { dev_alert(&pdata->pdev->dev, "Failed to fetch DCB Struct info from user\n"); + return -EFAULT; + } hw_if->set_tx_queue_operating_mode(l_dcb_struct.qinx, (UINT)l_dcb_struct.op_mode); @@ -6825,6 +6828,7 @@ static void DWC_ETH_QOS_program_dcb_algorithm( hw_if->set_dcb_queue_weight(l_dcb_struct.qinx, l_dcb_struct.weight); DBGPR("<--DWC_ETH_QOS_program_dcb_algorithm\n"); + return ret; } /*! * \details This function configure @@ -6877,18 +6881,21 @@ void DWC_ETH_QOS_program_avb_algorithm_hw_register( * \retval none */ -static void DWC_ETH_QOS_program_avb_algorithm( +static int DWC_ETH_QOS_program_avb_algorithm( struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct *req) { struct DWC_ETH_QOS_avb_algorithm l_avb_struct, *u_avb_struct = (struct DWC_ETH_QOS_avb_algorithm *)req->ptr; + int ret = 0; DBGPR("-->DWC_ETH_QOS_program_avb_algorithm\n"); if (copy_from_user(&l_avb_struct, u_avb_struct, - sizeof(struct DWC_ETH_QOS_avb_algorithm))) + sizeof(struct DWC_ETH_QOS_avb_algorithm))) { dev_alert(&pdata->pdev->dev, "Failed to fetch AVB Struct info from user\n"); + return -EFAULT; + } /*Application uses 1 for CLASS A traffic and 2 for CLASS B traffic @@ -6910,6 +6917,7 @@ static void DWC_ETH_QOS_program_avb_algorithm( /*Backup speed*/ pdata->avb_algorithm_speed_backup = pdata->speed; DBGPR("<--DWC_ETH_QOS_program_avb_algorithm\n"); + return ret; } /*! diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.h b/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.h index c94d45c993e2..6c9463c50c9f 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.h +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.h @@ -74,10 +74,10 @@ static netdev_features_t DWC_ETH_QOS_fix_features( INT DWC_ETH_QOS_configure_remotewakeup(struct net_device *dev, struct ifr_data_struct *req); -static void DWC_ETH_QOS_program_dcb_algorithm( +static int DWC_ETH_QOS_program_dcb_algorithm( struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct *req); -static void DWC_ETH_QOS_program_avb_algorithm( +static int DWC_ETH_QOS_program_avb_algorithm( struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct *req); static void DWC_ETH_QOS_config_tx_pbl(struct DWC_ETH_QOS_prv_data *pdata, From b77628b0cb3809c49adef1d862abb9f569a760d4 Mon Sep 17 00:00:00 2001 From: Lakshit Tyagi Date: Thu, 28 May 2020 12:10:02 +0530 Subject: [PATCH 066/208] data-kernel: EMAC: Fix the overflow for sub second increment Fix the overflow for sub second increment. Change-Id: I225a9330388f437e5dad8cc940fee3de4d42f95a Acked-by: Rahul Kawadgave Signed-off-by: Sunil Paidimarri --- drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c | 31 +++++++++++---------- drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c | 2 +- drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h | 4 +-- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c index a2e32ec55d87..da9209746be6 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c @@ -1134,11 +1134,11 @@ static INT drop_tx_status_enabled(void) * \retval -1 Failure */ -static INT config_sub_second_increment(ULONG ptp_clock) +static INT config_sub_second_increment(u64 ptp_clock) { - ULONG VARMAC_TCR; - double ss_inc = 0; - double sns_inc = 0; + ULONG VARMAC_TCR = 0; + u64 ss_inc = 0; + u64 sns_inc = 0; MAC_TCR_RGRD(VARMAC_TCR); @@ -1147,12 +1147,17 @@ static INT config_sub_second_increment(ULONG ptp_clock) /* where, ptp_clock = 50MHz if FINE correction */ /* and ptp_clock = DWC_ETH_QOS_SYSCLOCK if COARSE correction */ if (GET_VALUE(VARMAC_TCR, MAC_TCR_TSCFUPDT_LPOS, MAC_TCR_TSCFUPDT_HPOS) == 1) { - EMACDBG("Using PTP clock %ld MHz\n", ptp_clock); - ss_inc = (double)1000000000.0 / (double)ptp_clock; + EMACDBG("Using PTP clock %lu MHz\n", ptp_clock); + ss_inc = div_u64((1 * 1000000000ull), ptp_clock); + sns_inc = 1000000000ull - (ss_inc * ptp_clock); //take remainder + sns_inc = div_u64((sns_inc * 256), ptp_clock); //sns_inc needs to be multiplied by 2^8, per spec. + } else { EMACDBG("Using SYSCLOCK for coarse correction\n"); - ss_inc = (double)1000000000.0 / (double)DWC_ETH_QOS_SYSCLOCK; + ss_inc = div_u64((1 * 1000000000ull), DWC_ETH_QOS_SYSCLOCK); + sns_inc = 1000000000ull - (ss_inc * DWC_ETH_QOS_SYSCLOCK); //take remainder + sns_inc = div_u64((sns_inc * 256), DWC_ETH_QOS_SYSCLOCK); //sns_inc needs to be multiplied by 2^8, per spec. } /* 0.465ns accuracy */ @@ -1160,16 +1165,12 @@ static INT config_sub_second_increment(ULONG ptp_clock) VARMAC_TCR, MAC_TCR_TSCTRLSSR_LPOS, MAC_TCR_TSCTRLSSR_HPOS) == 0) { EMACDBG("using 0.465 ns accuracy"); - ss_inc /= 0.465; + ss_inc = div_u64((ss_inc * 1000), 465); } - sns_inc = ss_inc - (int)ss_inc; // take remainder - sns_inc *= 256.0; // sns_inc needs to be multiplied by 2^8, per spec. - sns_inc += 0.5; // round to nearest int value. - - MAC_SSIR_SSINC_UDFWR((int)ss_inc); - MAC_SSIR_SNSINC_UDFWR((int)sns_inc); - EMACDBG("ss_inc = %d, sns_inc = %d\n", (int)ss_inc, (int)sns_inc); + MAC_SSIR_SSINC_UDFWR(ss_inc); + MAC_SSIR_SNSINC_UDFWR(sns_inc); + EMACDBG("ss_inc = %lu, sns_inc = %lu\n", ss_inc, sns_inc); return Y_SUCCESS; } diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c index d2026101c6c0..bbb54721fb5d 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c @@ -5129,7 +5129,7 @@ static int ETH_PTPCLK_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ETH_PPS_ pdata->ptpclk_freq = eth_pps_cfg->ptpclk_freq; ret = hw_if->config_default_addend(pdata, (ULONG)eth_pps_cfg->ptpclk_freq); - ret |= hw_if->config_sub_second_increment( (ULONG)eth_pps_cfg->ptpclk_freq); + ret |= hw_if->config_sub_second_increment(eth_pps_cfg->ptpclk_freq); return ret; } diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h b/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h index 69aa01bf4230..20c1ae62fd6a 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2019, The Linux Foundation. All rights +/* Copyright (c) 2017-2020, The Linux Foundation. All rights * reserved. * * This program is free software; you can redistribute it and/or modify @@ -1013,7 +1013,7 @@ struct hw_if_struct { /* for hw time stamping */ INT(*config_hw_time_stamping)(UINT); - INT(*config_sub_second_increment)(unsigned long ptp_clock); + INT(*config_sub_second_increment)(u64 ptp_clock); INT(*config_default_addend)(struct DWC_ETH_QOS_prv_data *pdata, unsigned long ptp_clock); INT(*init_systime)(UINT, UINT); INT(*config_addend)(UINT); From 1cbc8732c42557c98c852e00dbb5bb60dee82fe0 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Wed, 13 May 2020 19:28:09 +0530 Subject: [PATCH 067/208] qcacld-3.0: Update disconnect rssi on every disconnect rssi event Currently there is a check to validate if the station is in associated state or not in the hdd lost link cp stats info cb, There is a race condition where if the disconnection happens from ap in that case the callback gets invoked before the connection state in the station context gets updated and thus the rssi on disconnect is not updated. To address above issue remove the check to validate the station state and update the rssi on disconnect irrespective of the state of the connection. Change-Id: I9cc6a08cdf0a1081adfde7a9423a665bc977cffc CRs-Fixed: 2678667 --- core/hdd/src/wlan_hdd_stats.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index e7a9e70a6948..65c362efd63e 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -6442,7 +6442,6 @@ static void hdd_lost_link_cp_stats_info_cb(void *stats_ev) struct hdd_adapter *adapter; struct stats_event *ev = stats_ev; uint8_t i; - struct hdd_station_ctx *sta_ctx; if (wlan_hdd_validate_context(hdd_ctx)) return; @@ -6455,16 +6454,11 @@ static void hdd_lost_link_cp_stats_info_cb(void *stats_ev) hdd_debug("invalid adapter"); continue; } - sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); - if ((sta_ctx) && - (eConnectionState_Associated != - sta_ctx->conn_info.connState)) { - adapter->rssi_on_disconnect = + adapter->rssi_on_disconnect = ev->vdev_summary_stats[i].stats.rssi; - hdd_debug("rssi on disconnect %d for " QDF_MAC_ADDR_STR, - adapter->rssi_on_disconnect, - QDF_MAC_ADDR_ARRAY(adapter->mac_addr.bytes)); - } + hdd_debug("rssi %d for " QDF_MAC_ADDR_STR, + adapter->rssi_on_disconnect, + QDF_MAC_ADDR_ARRAY(adapter->mac_addr.bytes)); } } From 8b9ee195ede968ce11c6e3f7259095d5332124a0 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Mon, 1 Jun 2020 00:46:53 -0700 Subject: [PATCH 068/208] Release 5.2.03.27D Release 5.2.03.27D Change-Id: I1c49c2f73379313ad33e9f0f8bad1d0617369a19 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index cac57bafffe2..de2f0343a2ce 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "C" +#define QWLAN_VERSION_EXTRA "D" #define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.27C" +#define QWLAN_VERSIONSTR "5.2.03.27D" #endif /* QWLAN_VERSION_H */ From 5e81d9e7774aa0c8ff2336a6b12857982228a812 Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Mon, 1 Jun 2020 17:08:14 +0530 Subject: [PATCH 069/208] qcacld-3.0: Add CPU mask support to pm_qos calls Call the pm_qos voting for specific instead of applying vote for all cores. Change-Id: I74b3696e15f0adc38149265dacdd5fb10e9055fe CRs-Fixed: 2495713 --- Kbuild | 1 + configs/default_defconfig | 1 + core/hdd/inc/wlan_hdd_main.h | 7 ++ core/hdd/src/wlan_hdd_main.c | 126 +++++++++++++++++++++++++++++++++-- 4 files changed, 131 insertions(+), 4 deletions(-) diff --git a/Kbuild b/Kbuild index 117762943fe3..133d1ca6c0e3 100644 --- a/Kbuild +++ b/Kbuild @@ -2127,6 +2127,7 @@ ifeq ($(CONFIG_QCA6290_11AX), y) cppflags-y += -DQCA_WIFI_QCA6290_11AX endif +cppflags-$(CONFIG_WLAN_CLD_PM_QOS) += -DCLD_PM_QOS cppflags-$(CONFIG_WLAN_FEATURE_11AX) += -DWLAN_FEATURE_11AX cppflags-$(CONFIG_WLAN_FEATURE_11AX) += -DWLAN_FEATURE_11AX_BSS_COLOR diff --git a/configs/default_defconfig b/configs/default_defconfig index ac867842437e..eb588609b424 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -304,6 +304,7 @@ CONFIG_DP_LFR := y CONFIG_HTT_PADDR64 := y CONFIG_RX_OL := y CONFIG_TX_TID_OVERRIDE := y +CONFIG_WLAN_CLD_PM_QOS := y endif # As per target team, build is done as follows: diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index abf6832d48af..6ec64b9dac86 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -47,6 +47,9 @@ #include #include #include +#ifdef CLD_PM_QOS +#include +#endif #include #include #include @@ -2103,6 +2106,10 @@ struct hdd_context { qdf_atomic_t sar_safety_req_resp_event_in_progress; #endif bool roam_ch_from_fw_supported; + +#ifdef CLD_PM_QOS + struct pm_qos_request pm_qos_req; +#endif }; /** diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index d340f4b7fc4b..c724f0e25ec2 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -8610,6 +8610,97 @@ static void hdd_clear_rps_cpu_mask(struct hdd_context *hdd_ctx) hdd_send_rps_disable_ind(adapter); } +#ifdef CLD_PM_QOS +#define PLD_REMOVE_PM_QOS(x) +#define PLD_REQUEST_PM_QOS(x, y) +/** + * hdd_pm_qos_update_cpu_mask() - Prepare CPU mask for PM_qos voting + * @mask: return variable of cpumask for the TPUT + * @high_throughput: only update high cores mask for high TPUT + * + * Return: none + */ +static inline void hdd_pm_qos_update_cpu_mask(cpumask_t *mask, + bool high_throughput) +{ + cpumask_set_cpu(0, mask); + cpumask_set_cpu(1, mask); + cpumask_set_cpu(2, mask); + cpumask_set_cpu(3, mask); + + if (high_throughput) { + /* For high TPUT include GOLD mask also */ + cpumask_set_cpu(4, mask); + cpumask_set_cpu(5, mask); + cpumask_set_cpu(6, mask); + } +} + +/** + * hdd_pm_qos_update_request() - API to request for pm_qos + * @hdd_ctx: handle to hdd context + * @pm_qos_cpu_mask: cpu_mask to apply + * + * Return: none + */ +static inline void hdd_pm_qos_update_request(struct hdd_context *hdd_ctx, + cpumask_t *pm_qos_cpu_mask) +{ + cpumask_copy(&hdd_ctx->pm_qos_req.cpus_affine, pm_qos_cpu_mask); + /* Latency value to be read from INI */ + pm_qos_update_request(&hdd_ctx->pm_qos_req, 1); +} + +#ifdef CONFIG_SMP +/** + * hdd_update_pm_qos_affine_cores() - Update PM_qos request for AFFINE_CORES + * @hdd_ctx: handle to hdd context + * + * Return: none + */ +static inline void hdd_update_pm_qos_affine_cores(struct hdd_context *hdd_ctx) +{ + hdd_ctx->pm_qos_req.type = PM_QOS_REQ_AFFINE_CORES; +} +#else +static inline void hdd_update_pm_qos_affine_cores(struct hdd_context *hdd_ctx) +{ +} +#endif +static inline void hdd_pm_qos_add_request(struct hdd_context *hdd_ctx) +{ + hdd_update_pm_qos_affine_cores(hdd_ctx); + pm_qos_add_request(&hdd_ctx->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); +} + +static inline void hdd_pm_qos_remove_request(struct hdd_context *hdd_ctx) +{ + pm_qos_remove_request(&hdd_ctx->pm_qos_req); +} +#else +#define PLD_REMOVE_PM_QOS(x) pld_remove_pm_qos(x) +#define PLD_REQUEST_PM_QOS(x, y) pld_request_pm_qos(x, y) + +static inline void hdd_pm_qos_add_request(struct hdd_context *hdd_ctx) +{ +} + +static inline void hdd_pm_qos_remove_request(struct hdd_context *hdd_ctx) +{ +} + +static inline void hdd_pm_qos_update_cpu_mask(cpumask_t *mask, + bool high_throughput) +{ +} + +static inline void hdd_pm_qos_update_request(struct hdd_context *hdd_ctx, + cpumask_t *pm_qos_cpu_mask) +{ +} +#endif + /** * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth * @hdd_ctx - handle to hdd context @@ -8640,6 +8731,10 @@ static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx, bool tx_level_change = false; bool rxthread_high_tput_req = false; bool dptrace_high_tput_req; + cpumask_t pm_qos_cpu_mask; + bool enable_pm_qos_high = false; + + cpumask_clear(&pm_qos_cpu_mask); if (total_pkts > hdd_ctx->config->busBandwidthHighThreshold) next_vote_level = PLD_BUS_WIDTH_HIGH; else if (total_pkts > hdd_ctx->config->busBandwidthMediumThreshold) @@ -8661,14 +8756,14 @@ static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx, if ((next_vote_level == PLD_BUS_WIDTH_LOW) || (next_vote_level == PLD_BUS_WIDTH_NONE)) { if (hdd_ctx->hbw_requested) { - pld_remove_pm_qos(hdd_ctx->parent_dev); + PLD_REMOVE_PM_QOS(hdd_ctx->parent_dev); hdd_ctx->hbw_requested = false; } if (hdd_ctx->dynamic_rps) hdd_clear_rps_cpu_mask(hdd_ctx); } else { if (!hdd_ctx->hbw_requested) { - pld_request_pm_qos(hdd_ctx->parent_dev, 1); + PLD_REQUEST_PM_QOS(hdd_ctx->parent_dev, 1); hdd_ctx->hbw_requested = true; } if (hdd_ctx->dynamic_rps) @@ -8725,10 +8820,15 @@ static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx, * 3)For UDP cases */ if (avg_no_rx_offload_pkts > - hdd_ctx->config->busBandwidthHighThreshold) + hdd_ctx->config->busBandwidthHighThreshold) { rxthread_high_tput_req = true; - else + enable_pm_qos_high = true; + } else { rxthread_high_tput_req = false; + enable_pm_qos_high = false; + } + + hdd_pm_qos_update_cpu_mask(&pm_qos_cpu_mask, enable_pm_qos_high); if (cds_sched_handle_throughput_req(rxthread_high_tput_req)) hdd_warn("Rx thread high_tput(%d) affinity request failed", @@ -8770,6 +8870,14 @@ static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx, /* fine-tuning parameters for TX Flows */ temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2; hdd_ctx->prev_tx = tx_packets; + + if (temp_tx > hdd_ctx->config->busBandwidthHighThreshold) + enable_pm_qos_high = true; + else + enable_pm_qos_high = false; + + hdd_pm_qos_update_cpu_mask(&pm_qos_cpu_mask, enable_pm_qos_high); + if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres) next_tx_level = WLAN_SVC_TP_HIGH; else @@ -8800,6 +8908,12 @@ static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx, hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK; } + /* Clear all the mask if no silver/gold vote is required */ + if (next_vote_level < PLD_BUS_WIDTH_MEDIUM) + cpumask_clear(&pm_qos_cpu_mask); + + hdd_pm_qos_update_request(hdd_ctx, &pm_qos_cpu_mask); + hdd_display_periodic_stats(hdd_ctx, (total_pkts > 0) ? true : false); hdd_periodic_sta_stats_display(hdd_ctx); @@ -8965,6 +9079,9 @@ int hdd_bus_bandwidth_init(struct hdd_context *hdd_ctx) hdd_enter(); qdf_spinlock_create(&hdd_ctx->bus_bw_lock); + + hdd_pm_qos_add_request(hdd_ctx); + INIT_WORK(&hdd_ctx->bus_bw_work, hdd_bus_bw_work_handler); hdd_ctx->bus_bw_timer_running = false; qdf_spinlock_create(&hdd_ctx->bus_bw_timer_lock); @@ -8985,6 +9102,7 @@ void hdd_bus_bandwidth_deinit(struct hdd_context *hdd_ctx) qdf_timer_free(&hdd_ctx->bus_bw_timer); qdf_spinlock_destroy(&hdd_ctx->bus_bw_timer_lock); qdf_spinlock_destroy(&hdd_ctx->bus_bw_lock); + hdd_pm_qos_remove_request(hdd_ctx); hdd_exit(); } From c0b4abf79e6b5f98cf4192c00d0607afd0d0aac4 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Mon, 1 Jun 2020 09:46:16 -0700 Subject: [PATCH 070/208] Release 5.2.03.27E Release 5.2.03.27E Change-Id: I9e2511e79e2b7fbf049b4a1417e45a5597bb4d11 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index de2f0343a2ce..321f30ff54e3 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "D" +#define QWLAN_VERSION_EXTRA "E" #define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.27D" +#define QWLAN_VERSIONSTR "5.2.03.27E" #endif /* QWLAN_VERSION_H */ From c528b7976ef4bb9435558d5601519906edc8346d Mon Sep 17 00:00:00 2001 From: Jianmin Zhu Date: Mon, 25 May 2020 20:51:45 +0800 Subject: [PATCH 071/208] qcacld-3.0: Fix intra band roaming issue for dual sta Reproduce steps: 1. Connect 1st STA on 5G, vdev id is 0. 2. Connect 2nd STA on 2G, vdev id is 1. 3. Enable intra band roaming by: wpa_cli -i wlan0 driver SETROAMINTRABAND 1 Since only 1st STA is roamable, so 5G intra band roaming is enabled. 4. Disconnect 1st STA on 5G, vdev id 0 is freed. STA on 2G becomes 1st STA now, roam capability is migrated to it. 5. Connect 2nd STA on 5G again, vdev id 0 is used again. WMI_PDEV_SET_PCL_CMDID is sent to F/W again, roamable STA is got by checking b_roam_scan_offload_started, actually roam scan offload is started for both STA, since 5G STA vdev id is smaller, 5G intra band roam is configed for 2G STA wrongly. 6. When LFR3 happens, STA on 2G will try to roam to 5G, it is out of our expectation. Fix: Since roaming capability is saved as roam_offload_enabled in wma interfaces, not as b_roam_scan_offload_started for dual sta case, accurate vdev with roaming capability and band need be got from wma interfaces when config intra band roaming by set PCL to F/W. Change-Id: I092d9deac4ef1680814891a338daadf09df333ee CRs-Fixed: 2694215 --- core/sme/src/common/sme_api.c | 21 +++++++-------------- core/wma/inc/wma_api.h | 8 ++++++++ core/wma/src/wma_utils.c | 13 +++++++++++++ 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 6d99240aa8ec..0266ff493f3d 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -13573,21 +13573,14 @@ QDF_STATUS sme_set_rssi_monitoring(tHalHandle hal, static enum band_info sme_get_connected_roaming_vdev_band(void) { enum band_info band = BAND_ALL; - tpAniSirGlobal mac = sme_get_mac_context(); - struct csr_roam_session *session; - uint8_t session_id, channel; + tp_wma_handle wma_handle; + uint8_t channel; - if (!mac) { - sme_debug("MAC Context is NULL"); - return band; - } - session_id = csr_get_roam_enabled_sta_sessionid(mac); - if (session_id != CSR_SESSION_ID_INVALID) { - session = CSR_GET_SESSION(mac, session_id); - channel = session->connectedProfile.operationChannel; - band = csr_get_rf_band(channel); - return band; - } + wma_handle = cds_get_context(QDF_MODULE_ID_WMA); + if (!wma_handle) + sme_err("Invalid wma handle"); + channel = wma_get_vdev_chan_roam_enabled(wma_handle); + band = csr_get_rf_band(channel); return band; } diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index 2565e4f23921..8fef24e2a671 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -415,4 +415,12 @@ void wma_wmi_stop(void); */ uint8_t wma_get_mcs_idx(uint16_t max_rate, uint8_t rate_flags, uint8_t *nss, uint8_t *mcs_rate_flag); + +/** + * wma_get_vdev_chan_roam_enabled() -get roam enabled vdev channel. + * @wma_handle: pointer to wma handle. + * + * Return: roam enabled vdev channel + */ +uint8_t wma_get_vdev_chan_roam_enabled(WMA_HANDLE wma_handle); #endif diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 5d617500e39b..a9504c7c0360 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -5141,4 +5141,17 @@ int wma_oem_event_handler(void *wma_ctx, uint8_t *event_buff, uint32_t len) return QDF_STATUS_SUCCESS; } + +uint8_t wma_get_vdev_chan_roam_enabled(WMA_HANDLE wma_handle) +{ + uint8_t id; + tp_wma_handle wma = (tp_wma_handle)wma_handle; + + for (id = 0; id < wma->max_bssid; id++) { + if (wma->interfaces[id].roam_offload_enabled) + return wma->interfaces[id].channel; + } + + return 0; +} #endif From b0d41aab1520c351c84d6939cf8188ad52e8010f Mon Sep 17 00:00:00 2001 From: nshrivas Date: Mon, 1 Jun 2020 19:46:08 -0700 Subject: [PATCH 072/208] Release 5.2.03.27F Release 5.2.03.27F Change-Id: I25455ca747b8caebd031b581b052fced84fcf85e CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 321f30ff54e3..3e161b2008b3 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "E" +#define QWLAN_VERSION_EXTRA "F" #define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.27E" +#define QWLAN_VERSIONSTR "5.2.03.27F" #endif /* QWLAN_VERSION_H */ From 7fa546e185c18298119ac7cdca8a0d4e37b9b6c4 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Mon, 1 Jun 2020 17:41:02 +0530 Subject: [PATCH 073/208] qcacld-3.0: Add support to optimize latency using pm_qos For Voice and Music (V&M) products, extreme latency optimization is needed while playing music and discovery, higher power consumption in this mode could be accepted. With CONFIG_WLAN_LL_MODE enabled, when latency_level is set to ultra low via cfg80211 vendor command, update request pm qos type PM_QOS_CPU_DMA_LATENCY to level DISABLE_KRAIT_IDLE_PS_VAL to speed up CPU efficiency and irq response. Change-Id: Ifb5bc8169f1cd08500c4b4bc0dd65dd0b3667ab6 CRs-Fixed: 2685074 --- Kbuild | 3 +++ configs/qcs40x.snoc.perf_defconfig | 5 +++++ core/hdd/inc/wlan_hdd_main.h | 1 + core/hdd/inc/wlan_hdd_power.h | 2 ++ core/hdd/src/wlan_hdd_cfg80211.c | 24 ++++++++++++++++++++++++ core/hdd/src/wlan_hdd_cfg80211.h | 16 ++++++++++++++++ core/hdd/src/wlan_hdd_driver_ops.c | 2 -- core/hdd/src/wlan_hdd_main.c | 2 +- 8 files changed, 52 insertions(+), 3 deletions(-) diff --git a/Kbuild b/Kbuild index 133d1ca6c0e3..8dca17e2a486 100644 --- a/Kbuild +++ b/Kbuild @@ -2127,6 +2127,9 @@ ifeq ($(CONFIG_QCA6290_11AX), y) cppflags-y += -DQCA_WIFI_QCA6290_11AX endif +# Enable Low latency optimisation mode +cppflags-$(CONFIG_WLAN_FEATURE_LL_MODE) += -DWLAN_FEATURE_LL_MODE + cppflags-$(CONFIG_WLAN_CLD_PM_QOS) += -DCLD_PM_QOS cppflags-$(CONFIG_WLAN_FEATURE_11AX) += -DWLAN_FEATURE_11AX cppflags-$(CONFIG_WLAN_FEATURE_11AX) += -DWLAN_FEATURE_11AX_BSS_COLOR diff --git a/configs/qcs40x.snoc.perf_defconfig b/configs/qcs40x.snoc.perf_defconfig index 1dd63fcb781b..0452f8be72be 100644 --- a/configs/qcs40x.snoc.perf_defconfig +++ b/configs/qcs40x.snoc.perf_defconfig @@ -168,6 +168,11 @@ CONFIG_WLAN_FEATURE_SAE := y CONFIG_GTK_OFFLOAD := y CONFIG_QCACLD_FEATURE_COEX_CONFIG := y CONFIG_QCACLD_FEATURE_MPTA_HELPER := y +CONFIG_WLAN_FEATURE_LL_MODE := y + +ifeq ($(CONFIG_WLAN_FEATURE_LL_MODE), y) + CONFIG_WLAN_CLD_PM_QOS := y +endif ifneq ($(DEVELOPER_DISABLE_BUILD_TIMESTAMP), y) ifneq ($(WLAN_DISABLE_BUILD_TAG), y) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 6ec64b9dac86..589f32364127 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2000,6 +2000,7 @@ struct hdd_context { int radio_index; qdf_work_t sap_pre_cac_work; bool hbw_requested; + bool llm_enabled; uint32_t last_nil_scan_bug_report_timestamp; enum RX_OFFLOAD ol_enable; #ifdef WLAN_FEATURE_NAN_DATAPATH diff --git a/core/hdd/inc/wlan_hdd_power.h b/core/hdd/inc/wlan_hdd_power.h index e8675af1ed2e..28af53248396 100644 --- a/core/hdd/inc/wlan_hdd_power.h +++ b/core/hdd/inc/wlan_hdd_power.h @@ -33,6 +33,8 @@ #define HDD_WAKELOCK_TIMEOUT_CONNECT 1000 #define HDD_WAKELOCK_TIMEOUT_RESUME 1000 +#define DISABLE_KRAIT_IDLE_PS_VAL 1 + /* * HDD_WAKELOCK_CONNECT_COMPLETE = CSR_JOIN_FAILURE_TIMEOUT_DEFAULT (3000) + * WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT_STADEF (1000) + diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 914f4a7e435b..3bf1dd3e777d 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -7759,6 +7759,28 @@ static int hdd_config_disconnect_ies(struct hdd_adapter *adapter, return qdf_status_to_os_return(status); } +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +void wlan_hdd_set_wlm_mode(struct hdd_context *hdd_ctx, uint16_t latency_level) +{ + if (latency_level == + QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW) { + hdd_ctx->llm_enabled = true; + if (!hdd_ctx->hbw_requested) { + pm_qos_update_request(&hdd_ctx->pm_qos_req, + DISABLE_KRAIT_IDLE_PS_VAL); + hdd_ctx->hbw_requested = true; + } + } else { + if (hdd_ctx->hbw_requested) { + pm_qos_update_request(&hdd_ctx->pm_qos_req, + PM_QOS_DEFAULT_VALUE); + hdd_ctx->hbw_requested = false; + } + hdd_ctx->llm_enabled = false; + } +} +#endif + /** * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration * vendor command @@ -8316,6 +8338,8 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, return -EINVAL; } + wlan_hdd_set_wlm_mode(hdd_ctx, latency_level); + /* Mapping the latency value to the level which fw expected * 0 - normal, 1 - moderate, 2 - low, 3 - ultralow */ diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 787629f082c8..d16a0eef0ce5 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -793,4 +793,20 @@ static inline void hdd_configure_sar_resume_index(struct hdd_context *hdd_ctx) #endif +/** + * wlan_hdd_set_wlm_mode() - Function to set pm_qos config in wlm mode + * @hdd_ctx: HDD context + * @latency level: latency value received + * + * Return: None + */ +#if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) +void wlan_hdd_set_wlm_mode(struct hdd_context *hdd_ctx, uint16_t latency_level); +#else +static inline +void wlan_hdd_set_wlm_mode(struct hdd_context *hdd_ctx, uint16_t latency_level) +{ +} +#endif + #endif diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index a400222d52e5..634256ed13c8 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -49,8 +49,6 @@ #define WLAN_MODULE_NAME "wlan" #endif -#define DISABLE_KRAIT_IDLE_PS_VAL 1 - #define SSR_MAX_FAIL_CNT 3 static uint8_t re_init_fail_cnt, probe_fail_cnt; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index c724f0e25ec2..b0514d178eeb 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -8755,7 +8755,7 @@ static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx, pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level); if ((next_vote_level == PLD_BUS_WIDTH_LOW) || (next_vote_level == PLD_BUS_WIDTH_NONE)) { - if (hdd_ctx->hbw_requested) { + if (hdd_ctx->hbw_requested && !hdd_ctx->llm_enabled) { PLD_REMOVE_PM_QOS(hdd_ctx->parent_dev); hdd_ctx->hbw_requested = false; } From a9920f38aebc059492ecd14a098c0d9b1a9a9098 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Mon, 1 Jun 2020 23:48:24 -0700 Subject: [PATCH 074/208] Release 5.2.03.27G Release 5.2.03.27G Change-Id: Ie4d9caa6026e95857d929275aca1f606e0d18c9e CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 3e161b2008b3..498ec6d169ba 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "F" +#define QWLAN_VERSION_EXTRA "G" #define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.27F" +#define QWLAN_VERSIONSTR "5.2.03.27G" #endif /* QWLAN_VERSION_H */ From c11fb8dc2b7c2330af6448f14866f78661f4af63 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Tue, 2 Jun 2020 12:10:52 +0530 Subject: [PATCH 075/208] qcacld-3.0: Add logs for sar safety and sar unsolicited timers Currently there are no logs to check at what time SAR safety timer or sar unsolicited timer starts or stops. Add debug logs to know the exact time when the sar safety timer and sar unsolicited timer start and stop. Change-Id: I2feaff17c6940a18d35bc4271549eda5dc36a13a CRs-Fixed: 2679214 --- core/hdd/src/wlan_hdd_cfg80211.c | 41 +++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 3bf1dd3e777d..bff9c2294415 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -12870,6 +12870,8 @@ static void hdd_sar_safety_timer_cb(void *user_data) void wlan_hdd_sar_unsolicited_timer_start(struct hdd_context *hdd_ctx) { + QDF_STATUS status; + if (!hdd_ctx->config->enable_sar_safety) return; @@ -12879,14 +12881,20 @@ void wlan_hdd_sar_unsolicited_timer_start(struct hdd_context *hdd_ctx) if (QDF_TIMER_STATE_RUNNING != qdf_mc_timer_get_current_state( - &hdd_ctx->sar_safety_unsolicited_timer)) - qdf_mc_timer_start( + &hdd_ctx->sar_safety_unsolicited_timer)) { + status = qdf_mc_timer_start( &hdd_ctx->sar_safety_unsolicited_timer, hdd_ctx->config->sar_safety_unsolicited_timeout); + + if (QDF_IS_STATUS_SUCCESS(status)) + hdd_nofl_debug("sar unsolicited timer started"); + } } void wlan_hdd_sar_timers_reset(struct hdd_context *hdd_ctx) { + QDF_STATUS status; + if (!hdd_ctx->config->enable_sar_safety) return; @@ -12894,16 +12902,26 @@ void wlan_hdd_sar_timers_reset(struct hdd_context *hdd_ctx) return; if (QDF_TIMER_STATE_RUNNING == - qdf_mc_timer_get_current_state(&hdd_ctx->sar_safety_timer)) - qdf_mc_timer_stop(&hdd_ctx->sar_safety_timer); + qdf_mc_timer_get_current_state(&hdd_ctx->sar_safety_timer)) { + status = qdf_mc_timer_stop(&hdd_ctx->sar_safety_timer); + if (QDF_IS_STATUS_SUCCESS(status)) + hdd_nofl_debug("sar safety timer stopped"); + } - qdf_mc_timer_start(&hdd_ctx->sar_safety_timer, - hdd_ctx->config->sar_safety_timeout); + status = qdf_mc_timer_start( + &hdd_ctx->sar_safety_timer, + hdd_ctx->config->sar_safety_timeout); + if (QDF_IS_STATUS_SUCCESS(status)) + hdd_nofl_debug("sar safety timer started"); if (QDF_TIMER_STATE_RUNNING == qdf_mc_timer_get_current_state( - &hdd_ctx->sar_safety_unsolicited_timer)) - qdf_mc_timer_stop(&hdd_ctx->sar_safety_unsolicited_timer); + &hdd_ctx->sar_safety_unsolicited_timer)) { + status = qdf_mc_timer_stop( + &hdd_ctx->sar_safety_unsolicited_timer); + if (QDF_IS_STATUS_SUCCESS(status)) + hdd_nofl_debug("sar unsolicited timer stopped"); + } qdf_event_set(&hdd_ctx->sar_safety_req_resp_event); } @@ -12913,6 +12931,8 @@ void wlan_hdd_sar_timers_init(struct hdd_context *hdd_ctx) if (!hdd_ctx->config->enable_sar_safety) return; + hdd_enter(); + qdf_mc_timer_init(&hdd_ctx->sar_safety_timer, QDF_TIMER_TYPE_SW, hdd_sar_safety_timer_cb, hdd_ctx); @@ -12923,6 +12943,7 @@ void wlan_hdd_sar_timers_init(struct hdd_context *hdd_ctx) qdf_atomic_init(&hdd_ctx->sar_safety_req_resp_event_in_progress); qdf_event_create(&hdd_ctx->sar_safety_req_resp_event); + hdd_exit(); } void wlan_hdd_sar_timers_deinit(struct hdd_context *hdd_ctx) @@ -12930,6 +12951,8 @@ void wlan_hdd_sar_timers_deinit(struct hdd_context *hdd_ctx) if (!hdd_ctx->config->enable_sar_safety) return; + hdd_enter(); + if (QDF_TIMER_STATE_RUNNING == qdf_mc_timer_get_current_state(&hdd_ctx->sar_safety_timer)) qdf_mc_timer_stop(&hdd_ctx->sar_safety_timer); @@ -12944,6 +12967,8 @@ void wlan_hdd_sar_timers_deinit(struct hdd_context *hdd_ctx) qdf_mc_timer_destroy(&hdd_ctx->sar_safety_unsolicited_timer); qdf_event_destroy(&hdd_ctx->sar_safety_req_resp_event); + + hdd_exit(); } #endif From 4b68048d88bcbd4880a9582ec764aebc0e9cbf5a Mon Sep 17 00:00:00 2001 From: nshrivas Date: Tue, 2 Jun 2020 01:47:11 -0700 Subject: [PATCH 076/208] Release 5.2.03.27H Release 5.2.03.27H Change-Id: I250c912f3be1244088ef4b14a34a82d3a883fbb9 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 498ec6d169ba..2b03690a2ed9 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "G" +#define QWLAN_VERSION_EXTRA "H" #define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.27G" +#define QWLAN_VERSIONSTR "5.2.03.27H" #endif /* QWLAN_VERSION_H */ From 4ef7f4f20149c6e3cb0d81e35278d8568b77dc9a Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Sat, 30 May 2020 11:07:06 -0700 Subject: [PATCH 077/208] drivers: rmnet_shs: Reset hstat node correctly Previously hstat node was not being cleared correctly. This change correctly resets segmentation field to prevent the stale field from being used on a recycle. CRs-Fixed: 2699690 Change-Id: Ie9d6b5f64d2e94d8a8c3fb99fdcee1b13ae2ec6d Acked-by: Raul Martinez Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs_config.h | 1 + drivers/rmnet/shs/rmnet_shs_main.c | 2 ++ drivers/rmnet/shs/rmnet_shs_wq.c | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/rmnet/shs/rmnet_shs_config.h b/drivers/rmnet/shs/rmnet_shs_config.h index 10b8f58fa331..8d318c173bed 100644 --- a/drivers/rmnet/shs/rmnet_shs_config.h +++ b/drivers/rmnet/shs/rmnet_shs_config.h @@ -48,6 +48,7 @@ enum rmnet_shs_crit_err_e { RMNET_SHS_WQ_NL_SOCKET_ERR, RMNET_SHS_CPU_FLOWS_BNDS_ERR, RMNET_SHS_OUT_OF_MEM_ERR, + RMNET_SHS_UDP_SEGMENT, RMNET_SHS_CRIT_ERR_MAX }; diff --git a/drivers/rmnet/shs/rmnet_shs_main.c b/drivers/rmnet/shs/rmnet_shs_main.c index 796858eab686..36ba75d01754 100755 --- a/drivers/rmnet/shs/rmnet_shs_main.c +++ b/drivers/rmnet/shs/rmnet_shs_main.c @@ -1012,6 +1012,8 @@ void rmnet_shs_flush_node(struct rmnet_shs_skbn_s *node, u8 ctext) skb_bytes_delivered += skb->len; if (segs_per_skb > 0) { + if (node->skb_tport_proto == IPPROTO_UDP) + rmnet_shs_crit_err[RMNET_SHS_UDP_SEGMENT]++; rmnet_shs_deliver_skb_segmented(skb, ctext, segs_per_skb); } else { diff --git a/drivers/rmnet/shs/rmnet_shs_wq.c b/drivers/rmnet/shs/rmnet_shs_wq.c index f300c22c5c02..5fb0f338c805 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq.c +++ b/drivers/rmnet/shs/rmnet_shs_wq.c @@ -296,6 +296,7 @@ void rmnet_shs_wq_hstat_reset_node(struct rmnet_shs_wq_hstat_s *hnode) hnode->hash = 0; hnode->suggested_cpu = 0; hnode->current_cpu = 0; + hnode->segs_per_skb = 0; hnode->skb_tport_proto = 0; hnode->stat_idx = -1; INIT_LIST_HEAD(&hnode->cpu_node_id); @@ -409,7 +410,8 @@ void rmnet_shs_wq_create_new_flow(struct rmnet_shs_skbn_s *node_p) node_p->hstats->skb_tport_proto = node_p->skb_tport_proto; node_p->hstats->current_cpu = node_p->map_cpu; node_p->hstats->suggested_cpu = node_p->map_cpu; - + /* Set egmentation off by default */ + node_p->hstats->segs_per_skb = 0; /* Start TCP flows with segmentation if userspace connected */ if (rmnet_shs_userspace_connected && node_p->hstats->skb_tport_proto == IPPROTO_TCP) From ddea1152d819bc06cee0f08ac8b80b30cc64ceec Mon Sep 17 00:00:00 2001 From: Vulupala Shashank Reddy Date: Wed, 3 Jun 2020 10:50:16 +0530 Subject: [PATCH 078/208] qcacld-3.0: Update pktcapture support Update pktcapture support for packet capture mode. Change-Id: Id7281d57b7eb547027a999e9662e6ca3c612673d CRs-Fixed: 2700679 --- core/wma/src/wma_main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 4f4cb7ee86a8..e1410b4ad86e 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -92,10 +92,7 @@ #include "init_cmd_api.h" #include "wma_coex.h" #include - -#ifdef WLAN_FEATURE_PKT_CAPTURE #include "wlan_pkt_capture_ucfg_api.h" -#endif #define WMA_LOG_COMPLETION_TIMER 3000 /* 3 seconds */ #define WMI_TLV_HEADROOM 128 @@ -6973,6 +6970,13 @@ int wma_rx_service_ready_ext_event(void *handle, uint8_t *event, wma_get_separate_iface_support(wma_handle)) wlan_res_cfg->nan_separate_iface_support = true; + if (ucfg_pkt_capture_get_mode(wma_handle->psoc) && + wmi_service_enabled(wmi_handle, + wmi_service_packet_capture_support)) + wlan_res_cfg->pktcapture_support = true; + else + wlan_res_cfg->pktcapture_support = false; + return 0; } From 3315013630e2c04db57e81f48ed1150d42b3c7f9 Mon Sep 17 00:00:00 2001 From: nshrivas Date: Wed, 3 Jun 2020 02:32:44 -0700 Subject: [PATCH 079/208] Release 5.2.03.27I Release 5.2.03.27I Change-Id: I51f9d75c7195eca89416272edf1c5a7dd5040a6d CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 2b03690a2ed9..8d9419d4e506 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "H" +#define QWLAN_VERSION_EXTRA "I" #define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.27H" +#define QWLAN_VERSIONSTR "5.2.03.27I" #endif /* QWLAN_VERSION_H */ From 4ea92500711ad706f58fa1097cf7f4a9b35395b9 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Wed, 27 May 2020 12:18:02 +0530 Subject: [PATCH 080/208] qcacld-3.0: Send proper Link Rates to user space Currently, host consider self NSS capability while sending link rates statistics to userspace for "iw wlan0/1 link" command. This results host sends incorrect link rates in case of STA and AP has different NSS capabilities. Fix is to send intersection of Self and AP's NSS capability to userspace. Change-Id: I7a31998ccb6988aa95de9fa25f49dda20f9f8b96 CRs-Fixed: 2686251 --- core/hdd/src/wlan_hdd_stats.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 65c362efd63e..000db6f95d97 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -6151,6 +6151,12 @@ int wlan_hdd_get_station_stats(struct hdd_adapter *adapter) tx_nss = wlan_vdev_mlme_get_nss(adapter->vdev); rx_nss = wlan_vdev_mlme_get_nss(adapter->vdev); } + /* Intersection of self and AP's NSS capability */ + if (tx_nss > wlan_vdev_mlme_get_nss(adapter->vdev)) + tx_nss = wlan_vdev_mlme_get_nss(adapter->vdev); + + if (rx_nss > wlan_vdev_mlme_get_nss(adapter->vdev)) + rx_nss = wlan_vdev_mlme_get_nss(adapter->vdev); /* save class a stats to legacy location */ adapter->hdd_stats.class_a_stat.tx_nss = tx_nss; From 5508118df044224496eca946563a6f258ed8d81b Mon Sep 17 00:00:00 2001 From: nshrivas Date: Thu, 4 Jun 2020 04:46:06 -0700 Subject: [PATCH 081/208] Release 5.2.03.27J Release 5.2.03.27J Change-Id: Ia35f096240d93c799ab34cc70bd30993692de9d3 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 8d9419d4e506..010d424f1c7b 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "I" +#define QWLAN_VERSION_EXTRA "J" #define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.27I" +#define QWLAN_VERSIONSTR "5.2.03.27J" #endif /* QWLAN_VERSION_H */ From 92f5e411a43306e2123695113ec68caade04e9c6 Mon Sep 17 00:00:00 2001 From: Sunil Paidimarri Date: Fri, 30 Nov 2018 17:09:05 -0800 Subject: [PATCH 082/208] data-kernel: EMAC: Fix for stall in bi-dir traffic in sw path Add functionality for Rx per queue aggregated budget check in Rx NAPI polling function. Change-Id: Ia5710aa3a6b991b23a7e72a4e435291b6f18d9f0 CRs-Fixed: 2345270 Acked-by: Nisha Menon Signed-off-by: Sunil Paidimarri --- drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c index a48b4bb47f07..4fc086a59d58 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c @@ -4047,6 +4047,7 @@ int DWC_ETH_QOS_poll_mq(struct napi_struct *napi, int budget) struct DWC_ETH_QOS_prv_data *pdata = rx_queue->pdata; /* divide the budget evenly among all the queues */ int per_q_budget = budget / DWC_ETH_QOS_RX_QUEUE_CNT; + int q_budget_used = 0; int qinx = 0; int received = 0, per_q_received = 0; unsigned long flags; @@ -4077,6 +4078,10 @@ int DWC_ETH_QOS_poll_mq(struct napi_struct *napi, int budget) received += per_q_received; pdata->xstats.rx_pkt_n += per_q_received; pdata->xstats.q_rx_pkt_n[qinx] += per_q_received; + + if (per_q_received > 0) + q_budget_used += per_q_budget; + #ifdef DWC_INET_LRO if (rx_queue->lro_flush_needed) lro_flush_all(&rx_queue->lro_mgr); @@ -4086,7 +4091,7 @@ int DWC_ETH_QOS_poll_mq(struct napi_struct *napi, int budget) /* If we processed all pkts, we are done; * tell the kernel & re-enable interrupt */ - if (received < budget) { + if ((received < q_budget_used) || (received == 0)) { if (pdata->dev->features & NETIF_F_GRO) { /* to turn off polling */ napi_complete(napi); @@ -4106,11 +4111,12 @@ int DWC_ETH_QOS_poll_mq(struct napi_struct *napi, int budget) DWC_ETH_QOS_enable_all_ch_rx_interrpt(pdata); spin_unlock_irqrestore(&pdata->lock, flags); } + return received; } DBGPR("<--DWC_ETH_QOS_poll_mq\n"); - return received; + return budget; } /*! From a383dfe2c8d68d0cc2723ad342d3542934428a58 Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Wed, 27 May 2020 16:02:09 +0530 Subject: [PATCH 083/208] qcacld-3.0: Cleanup rrm measurement data based on the index Currently when rrm measurement is completed for a particular index, the rrm_cleanup() is called which clears the measurement data for all the index. This can cause failure with multiple measurement request where on completion of the first request, second request data structure will also be made null. Also in rrm_cleanup(), after freeing the memory for pCurrReq, the pointer is made to NULL only for the last index resulting in NULL pointer dereference. Pass the measurement index to rrm_cleanup() and clear only that index data. Make the pCurrReq NULL for all the index. Change-Id: Ib712c2da3ddfea374d60b250dd474b08093b24c7 CRs-Fixed: 2695836 --- core/mac/src/pe/include/rrm_api.h | 10 ++++++- core/mac/src/pe/lim/lim_api.c | 3 +- core/mac/src/pe/rrm/rrm_api.c | 48 +++++++++---------------------- 3 files changed, 24 insertions(+), 37 deletions(-) diff --git a/core/mac/src/pe/include/rrm_api.h b/core/mac/src/pe/include/rrm_api.h index 1cb926782cd1..f154666d42fd 100644 --- a/core/mac/src/pe/include/rrm_api.h +++ b/core/mac/src/pe/include/rrm_api.h @@ -41,7 +41,15 @@ uint8_t rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac, int8_t regMax, QDF_STATUS rrm_initialize(tpAniSirGlobal pMac); -QDF_STATUS rrm_cleanup(tpAniSirGlobal pMac); +/** + * rrm_cleanup - cleanup RRM measurement related data for the measurement + * index + * @mac: Pointer to mac context + * @idx: Measurement index + * + * Return: None + */ +void rrm_cleanup(tpAniSirGlobal mac, uint8_t idx); QDF_STATUS rrm_process_link_measurement_request(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 8023a70ac36a..3bb4397b5dd4 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -634,7 +634,8 @@ void lim_cleanup(tpAniSirGlobal pMac) /* Now, finally reset the deferred message queue pointers */ lim_reset_deferred_msg_q(pMac); - rrm_cleanup(pMac); + for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) + rrm_cleanup(pMac, i); lim_ft_cleanup_all_ft_sessions(pMac); diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c index e243379ab533..c24bb529de42 100644 --- a/core/mac/src/pe/rrm/rrm_api.c +++ b/core/mac/src/pe/rrm/rrm_api.c @@ -1031,7 +1031,7 @@ end: if (beacon_xmit_ind->fMeasureDone) { pe_debug("Measurement done."); - rrm_cleanup(mac_ctx); + rrm_cleanup(mac_ctx, beacon_xmit_ind->measurement_idx); } if (NULL != report) @@ -1140,7 +1140,7 @@ QDF_STATUS rrm_process_beacon_req(tpAniSirGlobal mac_ctx, tSirMacAddr peer, curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq[index]; if (curr_req) { qdf_mem_free(curr_req); - curr_req = NULL; + mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = NULL; } curr_req = qdf_mem_malloc(sizeof(*curr_req)); @@ -1162,7 +1162,7 @@ QDF_STATUS rrm_process_beacon_req(tpAniSirGlobal mac_ctx, tSirMacAddr peer, if (eRRM_SUCCESS != rrm_status) { rrm_process_beacon_request_failure(mac_ctx, session_entry, peer, rrm_status, index); - rrm_cleanup(mac_ctx); + rrm_cleanup(mac_ctx, index); } } @@ -1414,42 +1414,20 @@ QDF_STATUS rrm_initialize(tpAniSirGlobal pMac) return QDF_STATUS_SUCCESS; } -/* -------------------------------------------------------------------- */ -/** - * rrm_cleanup - * - * FUNCTION: - * cleanup RRM module - * - * LOGIC: - * - * ASSUMPTIONS: - * - * NOTE: - * - * @param mode - * @param rate - * @return None - */ - -QDF_STATUS rrm_cleanup(tpAniSirGlobal pMac) +void rrm_cleanup(tpAniSirGlobal mac, uint8_t idx) { - uint8_t i; + tpRRMReq cur_rrm_req = NULL; - for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) { - if (pMac->rrm.rrmPEContext.pCurrentReq[i]) { - if (pMac->rrm.rrmPEContext.pCurrentReq[i]->request. - Beacon.reqIes.pElementIds) - qdf_mem_free(pMac->rrm.rrmPEContext. - pCurrentReq[i]->request.Beacon. - reqIes.pElementIds); + cur_rrm_req = mac->rrm.rrmPEContext.pCurrentReq[idx]; + if (!cur_rrm_req) + return; - qdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq[i]); - } - } + qdf_mem_free(cur_rrm_req->request.Beacon.reqIes.pElementIds); + cur_rrm_req->request.Beacon.reqIes.pElementIds = NULL; + cur_rrm_req->request.Beacon.reqIes.num = 0; - pMac->rrm.rrmPEContext.pCurrentReq[i] = NULL; - return QDF_STATUS_SUCCESS; + qdf_mem_free(cur_rrm_req); + mac->rrm.rrmPEContext.pCurrentReq[idx] = NULL; } /** From feb3647d91a076c6c68400a867fd7cf99574a26d Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Fri, 29 May 2020 03:38:04 +0530 Subject: [PATCH 084/208] qcacld-3.0: Fix mem leak while deleting pmksa Due to commit : I95881db229d5193cbdc22c5f30e1375b3892fbd4, while processing set_pmk command driver checks pmk_len to delete pmk. In case if new PMK gets added with 0 length, pmk entry with pmk_len = 0 will never be deleted. It is only added without freeing the existing entry. Fix is to modify del pmk logic to avoid mem leak. Change-Id: I65c8a15e376826670bf6ca49b500bb25aa682a22 CRs-Fixed: 2701754 --- core/sme/src/csr/csr_api_roam.c | 115 ++++++++++++++++-------------- core/sme/src/csr/csr_inside_api.h | 2 +- 2 files changed, 62 insertions(+), 55 deletions(-) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 2330bf1619fa..450e613e2020 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -16009,63 +16009,40 @@ void csr_clear_sae_single_pmk(tpAniSirGlobal pMac, uint8_t vdev_id, #endif void csr_roam_del_pmk_cache_entry(struct csr_roam_session *session, - tPmkidCacheInfo *cached_pmksa) + tPmkidCacheInfo *cached_pmksa, u32 del_idx) { u32 curr_idx; - u8 del_pmk[CSR_RSN_MAX_PMK_LEN] = {0}; - u32 i, del_idx; + u32 i; - /* copy the PMK of matched BSSID */ - qdf_mem_copy(del_pmk, cached_pmksa->pmk, cached_pmksa->pmk_len); - - /* Search for matching PMK in session PMK cache */ - for (del_idx = 0; del_idx != session->NumPmkidCache; del_idx++) { - cached_pmksa = &session->PmkidCacheInfo[del_idx]; - if (cached_pmksa->pmk_len && (!qdf_mem_cmp - (cached_pmksa->pmk, del_pmk, cached_pmksa->pmk_len))) { - /* Clear this - matched entry */ - qdf_mem_zero(cached_pmksa, sizeof(tPmkidCacheInfo)); - - /* Match Found, Readjust the other entries */ - curr_idx = session->curr_cache_idx; - if (del_idx < curr_idx) { - for (i = del_idx; i < (curr_idx - 1); i++) { - qdf_mem_copy(&session-> - PmkidCacheInfo[i], - &session-> - PmkidCacheInfo[i + 1], - sizeof(tPmkidCacheInfo)); - } - - session->curr_cache_idx--; - qdf_mem_zero(&session->PmkidCacheInfo - [session->curr_cache_idx], - sizeof(tPmkidCacheInfo)); - } else if (del_idx > curr_idx) { - for (i = del_idx; i > (curr_idx); i--) { - qdf_mem_copy(&session-> - PmkidCacheInfo[i], - &session-> - PmkidCacheInfo[i - 1], - sizeof(tPmkidCacheInfo)); - } - - qdf_mem_zero(&session->PmkidCacheInfo - [session->curr_cache_idx], - sizeof(tPmkidCacheInfo)); - } - - /* Decrement the count since an entry is been deleted */ - session->NumPmkidCache--; - sme_debug("PMKID at index=%d deleted, current index=%d cache count=%d", - del_idx, session->curr_cache_idx, - session->NumPmkidCache); - /* As we re-adjusted entries by one position search - * again from current index - */ - del_idx--; + /* Clear this - matched entry */ + qdf_mem_zero(cached_pmksa, sizeof(tPmkidCacheInfo)); + /* Match Found, Readjust the other entries */ + curr_idx = session->curr_cache_idx; + if (del_idx < curr_idx) { + for (i = del_idx; i < (curr_idx - 1); i++) { + qdf_mem_copy(&session->PmkidCacheInfo[i], + &session->PmkidCacheInfo[i + 1], + sizeof(tPmkidCacheInfo)); } + + session->curr_cache_idx--; + qdf_mem_zero(&session->PmkidCacheInfo[session->curr_cache_idx], + sizeof(tPmkidCacheInfo)); + } else if (del_idx > curr_idx) { + for (i = del_idx; i > (curr_idx); i--) { + qdf_mem_copy(&session->PmkidCacheInfo[i], + &session->PmkidCacheInfo[i - 1], + sizeof(tPmkidCacheInfo)); + } + + qdf_mem_zero(&session->PmkidCacheInfo[session->curr_cache_idx], + sizeof(tPmkidCacheInfo)); } + + /* Decrement the count since an entry is been deleted */ + session->NumPmkidCache--; + sme_debug("PMKID at index=%d deleted, current index=%d cache count=%d", + del_idx, session->curr_cache_idx, session->NumPmkidCache); } QDF_STATUS csr_roam_del_pmkid_from_cache(tpAniSirGlobal pMac, @@ -16077,6 +16054,9 @@ QDF_STATUS csr_roam_del_pmkid_from_cache(tpAniSirGlobal pMac, bool fMatchFound = false; uint32_t Index; tPmkidCacheInfo *cached_pmksa; + u32 del_idx; + u8 del_pmk[CSR_RSN_MAX_PMK_LEN] = {0}; + if (!pSession) { sme_err("session %d not found", sessionId); @@ -16118,8 +16098,35 @@ QDF_STATUS csr_roam_del_pmkid_from_cache(tpAniSirGlobal pMac, fMatchFound = 1; if (fMatchFound) { - /* Delete the matched PMK cache entry */ - csr_roam_del_pmk_cache_entry(pSession, cached_pmksa); + /* copy the PMK of matched BSSID */ + qdf_mem_copy(del_pmk, cached_pmksa->pmk, + cached_pmksa->pmk_len); + + /* Free the matched entry to address null pmk_len case*/ + csr_roam_del_pmk_cache_entry(pSession, cached_pmksa, + Index); + + /* Search for matching PMK in session PMK cache */ + for (del_idx = 0; del_idx != pSession->NumPmkidCache; + del_idx++) { + cached_pmksa = + &pSession->PmkidCacheInfo[del_idx]; + if (cached_pmksa->pmk_len && (!qdf_mem_cmp + (cached_pmksa->pmk, del_pmk, + cached_pmksa->pmk_len))) { + /* Delete the matched PMK cache entry */ + csr_roam_del_pmk_cache_entry( + pSession, cached_pmksa, + del_idx); + /* Search again from current index as we + * re-adjusted entries by one position + */ + del_idx--; + } + } + /* reset stored pmk */ + qdf_mem_zero(del_pmk, CSR_RSN_MAX_PMK_LEN); + break; } } diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index b1d5890ec515..17ebbbbae19d 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -1001,7 +1001,7 @@ QDF_STATUS csr_roam_del_pmkid_from_cache(tpAniSirGlobal pMac, bool flush_cache); void csr_roam_del_pmk_cache_entry(struct csr_roam_session *session, - tPmkidCacheInfo *cached_pmksa); + tPmkidCacheInfo *cached_pmksa, u32 del_idx); #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) /** From 090986c3be5c27877aa9c64212704bd7a2e26f5c Mon Sep 17 00:00:00 2001 From: nshrivas Date: Thu, 4 Jun 2020 07:48:53 -0700 Subject: [PATCH 085/208] Release 5.2.03.27K Release 5.2.03.27K Change-Id: I0962a71dd3f13f905fd1491770eb9b85111d60f8 CRs-Fixed: 774533 --- core/mac/inc/qwlan_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 010d424f1c7b..f0dff5dc9dde 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "J" +#define QWLAN_VERSION_EXTRA "K" #define QWLAN_VERSION_BUILD 27 -#define QWLAN_VERSIONSTR "5.2.03.27J" +#define QWLAN_VERSIONSTR "5.2.03.27K" #endif /* QWLAN_VERSION_H */ From 7c0e94ba92d4fa9337c8a41881c490c586b95431 Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Wed, 27 May 2020 16:02:09 +0530 Subject: [PATCH 086/208] qcacld-3.0: Cleanup rrm measurement data based on the index Currently when rrm measurement is completed for a particular index, the rrm_cleanup() is called which clears the measurement data for all the index. This can cause failure with multiple measurement request where on completion of the first request, second request data structure will also be made null. Also in rrm_cleanup(), after freeing the memory for pCurrReq, the pointer is made to NULL only for the last index resulting in NULL pointer dereference. Pass the measurement index to rrm_cleanup() and clear only that index data. Make the pCurrReq NULL for all the index. Change-Id: Ib712c2da3ddfea374d60b250dd474b08093b24c7 CRs-Fixed: 2695836 --- core/mac/src/pe/include/rrm_api.h | 10 ++++++- core/mac/src/pe/lim/lim_api.c | 3 +- core/mac/src/pe/rrm/rrm_api.c | 48 +++++++++---------------------- 3 files changed, 24 insertions(+), 37 deletions(-) diff --git a/core/mac/src/pe/include/rrm_api.h b/core/mac/src/pe/include/rrm_api.h index 1cb926782cd1..f154666d42fd 100644 --- a/core/mac/src/pe/include/rrm_api.h +++ b/core/mac/src/pe/include/rrm_api.h @@ -41,7 +41,15 @@ uint8_t rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac, int8_t regMax, QDF_STATUS rrm_initialize(tpAniSirGlobal pMac); -QDF_STATUS rrm_cleanup(tpAniSirGlobal pMac); +/** + * rrm_cleanup - cleanup RRM measurement related data for the measurement + * index + * @mac: Pointer to mac context + * @idx: Measurement index + * + * Return: None + */ +void rrm_cleanup(tpAniSirGlobal mac, uint8_t idx); QDF_STATUS rrm_process_link_measurement_request(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 8023a70ac36a..3bb4397b5dd4 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -634,7 +634,8 @@ void lim_cleanup(tpAniSirGlobal pMac) /* Now, finally reset the deferred message queue pointers */ lim_reset_deferred_msg_q(pMac); - rrm_cleanup(pMac); + for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) + rrm_cleanup(pMac, i); lim_ft_cleanup_all_ft_sessions(pMac); diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c index e243379ab533..c24bb529de42 100644 --- a/core/mac/src/pe/rrm/rrm_api.c +++ b/core/mac/src/pe/rrm/rrm_api.c @@ -1031,7 +1031,7 @@ end: if (beacon_xmit_ind->fMeasureDone) { pe_debug("Measurement done."); - rrm_cleanup(mac_ctx); + rrm_cleanup(mac_ctx, beacon_xmit_ind->measurement_idx); } if (NULL != report) @@ -1140,7 +1140,7 @@ QDF_STATUS rrm_process_beacon_req(tpAniSirGlobal mac_ctx, tSirMacAddr peer, curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq[index]; if (curr_req) { qdf_mem_free(curr_req); - curr_req = NULL; + mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = NULL; } curr_req = qdf_mem_malloc(sizeof(*curr_req)); @@ -1162,7 +1162,7 @@ QDF_STATUS rrm_process_beacon_req(tpAniSirGlobal mac_ctx, tSirMacAddr peer, if (eRRM_SUCCESS != rrm_status) { rrm_process_beacon_request_failure(mac_ctx, session_entry, peer, rrm_status, index); - rrm_cleanup(mac_ctx); + rrm_cleanup(mac_ctx, index); } } @@ -1414,42 +1414,20 @@ QDF_STATUS rrm_initialize(tpAniSirGlobal pMac) return QDF_STATUS_SUCCESS; } -/* -------------------------------------------------------------------- */ -/** - * rrm_cleanup - * - * FUNCTION: - * cleanup RRM module - * - * LOGIC: - * - * ASSUMPTIONS: - * - * NOTE: - * - * @param mode - * @param rate - * @return None - */ - -QDF_STATUS rrm_cleanup(tpAniSirGlobal pMac) +void rrm_cleanup(tpAniSirGlobal mac, uint8_t idx) { - uint8_t i; + tpRRMReq cur_rrm_req = NULL; - for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) { - if (pMac->rrm.rrmPEContext.pCurrentReq[i]) { - if (pMac->rrm.rrmPEContext.pCurrentReq[i]->request. - Beacon.reqIes.pElementIds) - qdf_mem_free(pMac->rrm.rrmPEContext. - pCurrentReq[i]->request.Beacon. - reqIes.pElementIds); + cur_rrm_req = mac->rrm.rrmPEContext.pCurrentReq[idx]; + if (!cur_rrm_req) + return; - qdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq[i]); - } - } + qdf_mem_free(cur_rrm_req->request.Beacon.reqIes.pElementIds); + cur_rrm_req->request.Beacon.reqIes.pElementIds = NULL; + cur_rrm_req->request.Beacon.reqIes.num = 0; - pMac->rrm.rrmPEContext.pCurrentReq[i] = NULL; - return QDF_STATUS_SUCCESS; + qdf_mem_free(cur_rrm_req); + mac->rrm.rrmPEContext.pCurrentReq[idx] = NULL; } /** From b360cc87560cf1e1c5268bb4e4a2f5bb94734cad Mon Sep 17 00:00:00 2001 From: Mohammed Nayeem Ur Rahman Date: Wed, 1 Apr 2020 14:30:33 +0530 Subject: [PATCH 087/208] msm: adsprpc: Fix array index underflow problem Add check to restrict index underflow.This is to avoid that it does not access invalid index. Change-Id: Ib971033c5820ca4dab38ace3b106c7b1b42529e4 Acked-by: Gururaj Chalger Signed-off-by: Mohammed Nayeem Ur Rahman --- drivers/char/adsprpc.c | 67 +++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 4d538a830a1d..c3823ec9bf85 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -706,12 +706,23 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) { struct fastrpc_apps *me = &gfa; struct fastrpc_file *fl; - int vmid; + int vmid, cid = -1, err = 0; struct fastrpc_session_ctx *sess; if (!map) return; fl = map->fl; + if (fl && !(map->flags == ADSP_MMAP_HEAP_ADDR || + map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR)) { + cid = fl->cid; + VERIFY(err, cid >= ADSP_DOMAIN_ID && cid < NUM_CHANNELS); + if (err) { + err = -ECHRNG; + pr_err("adsprpc: ERROR:%s, Invalid channel id: %d, err:%d", + __func__, cid, err); + return; + } + } if (map->flags == ADSP_MMAP_HEAP_ADDR || map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { map->refs--; @@ -783,20 +794,21 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, struct fastrpc_apps *me = &gfa; struct fastrpc_session_ctx *sess; struct fastrpc_apps *apps = fl->apps; - int cid = fl->cid; struct fastrpc_channel_ctx *chan = NULL; struct fastrpc_mmap *map = NULL; dma_addr_t region_phys = 0; void *region_vaddr = NULL; unsigned long flags; - int err = 0, vmid, sgl_index = 0; + int err = 0, vmid, sgl_index = 0, cid = -1; struct scatterlist *sgl = NULL; - VERIFY(err, cid >= 0 && cid < NUM_CHANNELS); - if (err) + cid = fl->cid; + VERIFY(err, cid >= ADSP_DOMAIN_ID && cid < NUM_CHANNELS); + if (err) { + err = -ECHRNG; goto bail; + } chan = &apps->channel[cid]; - if (!fastrpc_mmap_find(fl, fd, va, len, mflags, 1, ppmap)) return 0; map = kzalloc(sizeof(*map), GFP_KERNEL); @@ -1829,8 +1841,16 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx, { struct smq_msg *msg = &ctx->msg; struct fastrpc_file *fl = ctx->fl; - struct fastrpc_channel_ctx *channel_ctx = &fl->apps->channel[fl->cid]; - int err = 0; + struct fastrpc_channel_ctx *channel_ctx = NULL; + int err = 0, cid = -1; + + channel_ctx = &fl->apps->channel[fl->cid]; + cid = fl->cid; + VERIFY(err, cid >= ADSP_DOMAIN_ID && cid < NUM_CHANNELS); + if (err) { + err = -ECHRNG; + goto bail; + } mutex_lock(&channel_ctx->smd_mutex); msg->pid = fl->tgid; @@ -1895,11 +1915,22 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, { struct smq_invoke_ctx *ctx = NULL; struct fastrpc_ioctl_invoke *invoke = &inv->inv; - int cid = fl->cid; - int interrupted = 0; - int err = 0; + int err = 0, cid = -1, interrupted = 0; struct timespec invoket = {0}; - int64_t *perf_counter = getperfcounter(fl, PERF_COUNT); + int64_t *perf_counter = NULL; + + cid = fl->cid; + VERIFY(err, cid >= ADSP_DOMAIN_ID && cid < NUM_CHANNELS); + if (err) { + err = -ECHRNG; + goto bail; + } + VERIFY(err, fl->sctx != NULL); + if (err) { + err = -EBADR; + goto bail; + } + perf_counter = getperfcounter(fl, PERF_COUNT); if (fl->profile) getnstimeofday(&invoket); @@ -1913,14 +1944,6 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, } } - VERIFY(err, fl->cid >= 0 && fl->cid < NUM_CHANNELS && fl->sctx != NULL); - if (err) { - pr_err("adsprpc: ERROR: %s: user application %s domain is not set\n", - __func__, current->comm); - err = -EBADR; - goto bail; - } - if (!kernel) { VERIFY(err, 0 == context_restore_interrupted(fl, inv, &ctx)); @@ -3238,8 +3261,7 @@ static const struct file_operations debugfs_fops = { static int fastrpc_channel_open(struct fastrpc_file *fl) { struct fastrpc_apps *me = &gfa; - int cid, err = 0; - + int cid = -1, err = 0; VERIFY(err, fl && fl->sctx && fl->cid >= 0 && fl->cid < NUM_CHANNELS); if (err) { @@ -3249,7 +3271,6 @@ static int fastrpc_channel_open(struct fastrpc_file *fl) return err; } cid = fl->cid; - mutex_lock(&me->channel[cid].rpmsg_mutex); VERIFY(err, NULL != me->channel[cid].rpdev); if (err) { From 03bafade609a2db7f3547dea8ac8939c3ef38887 Mon Sep 17 00:00:00 2001 From: Om Parkash Date: Tue, 16 Jun 2020 10:28:51 +0530 Subject: [PATCH 088/208] ARM: dts: msm: Include camera sensor DTSi file for QCS410 Include camera sensor DTSi file for QCS410 Target Change-Id: Ie2a2c5981026e12b62ea87353c7ebd591449fda2 Signed-off-by: Om Parkash --- arch/arm64/boot/dts/qcom/qcs410-iot.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi b/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi index 96fb1d37b317..3144838fcefc 100644 --- a/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs410-iot.dtsi @@ -14,6 +14,7 @@ #include #include #include "qcs410.dtsi" +#include "qcs610-camera-sensor-idp.dtsi" / { model = "Qualcomm Technologies, Inc. QCS410 IOT"; From 7547d31593add6914c311e1e082932ceb26b3cae Mon Sep 17 00:00:00 2001 From: Om Parkash Date: Thu, 18 Jun 2020 19:39:15 +0530 Subject: [PATCH 089/208] msm: camera: Remove frame id and timestamp checks for spurious SOF Remove frame id and timestamp checks for spurious SOF for recovering once spurious SOF is received. Change-Id: Iff4510fa5af4ae2e6b4c9f38a44b1f98000bf66d Signed-off-by: Om Parkash --- .../msm/camera/cam_req_mgr/cam_req_mgr_core.c | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c index 35790fd06405..dfbc9b07e4a4 100644 --- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c @@ -2494,7 +2494,6 @@ static int cam_req_mgr_cb_notify_trigger( struct crm_task_payload *task_data; bool send_sof = true; int i = 0; - int64_t sof_time_diff = 0; if (!trigger_data) { CAM_ERR(CAM_CRM, "sof_data is NULL"); @@ -2514,10 +2513,6 @@ static int cam_req_mgr_cb_notify_trigger( if (link->dev_sof_evt[i].dev_hdl == trigger_data->dev_hdl) { if (link->dev_sof_evt[i].sof_done == false) { link->dev_sof_evt[i].sof_done = true; - link->dev_sof_evt[i].frame_id = - trigger_data->frame_id; - link->dev_sof_evt[i].timestamp = - trigger_data->sof_timestamp_val; } else CAM_INFO(CAM_CRM, "Received Spurious SOF"); } else if (link->dev_sof_evt[i].sof_done == false) { @@ -2527,23 +2522,6 @@ static int cam_req_mgr_cb_notify_trigger( if (!send_sof) return 0; - if (link->num_sof_src > 1) { - for (i = 0; i < (link->num_sof_src - 1); i++) { - if (link->dev_sof_evt[i].timestamp >= - link->dev_sof_evt[i+1].timestamp) { - sof_time_diff = link->dev_sof_evt[i].timestamp - - link->dev_sof_evt[i+1].timestamp; - } else { - sof_time_diff = - link->dev_sof_evt[i+1].timestamp - - link->dev_sof_evt[i].timestamp; - } - if ((link->dev_sof_evt[i].frame_id != - link->dev_sof_evt[i+1].frame_id) || - sof_time_diff > TIMESTAMP_DIFF_THRESHOLD) - return 0; - } - } for (i = 0; i < link->num_sof_src; i++) link->dev_sof_evt[i].sof_done = false; From 810dc203caa41222a820fd283a7cba194e67474e Mon Sep 17 00:00:00 2001 From: Om Parkash Date: Thu, 18 Jun 2020 19:56:37 +0530 Subject: [PATCH 090/208] msm: camera: isp: Fix race condition b/w add and apply req There is a chance that CRM shows request as ready while request is not passed in isp pending list. Change-Id: If20ef7671c06a1d3bde7adc5a05a6a489b2622e2 Signed-off-by: Om Parkash --- .../msm/camera/cam_isp/cam_isp_context.c | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c index f855ad1b498e..3e410e53bb23 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c @@ -340,6 +340,23 @@ put: } } +static void __cam_isp_ctx_dequeue_request(struct cam_context *ctx, + struct cam_ctx_request *req) +{ + struct cam_ctx_request *req_current; + struct cam_ctx_request *req_prev; + + spin_lock_bh(&ctx->lock); + list_for_each_entry_safe_reverse(req_current, req_prev, + &ctx->pending_req_list, list) { + if (req->request_id == req_current->request_id) { + list_del_init(&req_current->list); + break; + } + } + spin_unlock_bh(&ctx->lock); +} + static int __cam_isp_ctx_enqueue_request_in_order( struct cam_context *ctx, struct cam_ctx_request *req) { @@ -3409,13 +3426,12 @@ static int __cam_isp_ctx_config_dev_in_top_state( add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; add_req.skip_before_applying = 0; + __cam_isp_ctx_enqueue_request_in_order(ctx, req); rc = ctx->ctx_crm_intf->add_req(&add_req); if (rc) { CAM_ERR(CAM_ISP, "Add req failed: req id=%llu", req->request_id); - } else { - __cam_isp_ctx_enqueue_request_in_order( - ctx, req); + __cam_isp_ctx_dequeue_request(ctx, req); } } else { rc = -EINVAL; From 5861cbd2ae1002100f692efe9d64d13006f9e195 Mon Sep 17 00:00:00 2001 From: Avinash Chandra Date: Tue, 16 Jun 2020 17:43:15 +0530 Subject: [PATCH 091/208] ARM: dts: msm: Add audio support -include audio dts for qcs410 iot target. -Delete fsa i2c handle property as analog usb type C support not required. CRs-Fixed: 2708966 Change-Id: I034e890c5571f15119d1275317be38f6410e53d4 Signed-off-by: Avinash Chandra Signed-off-by: Sohail Hoque --- arch/arm64/boot/dts/qcom/qcs410-iot.dts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs410-iot.dts b/arch/arm64/boot/dts/qcom/qcs410-iot.dts index bac1561fdc2a..2fe709638dbc 100644 --- a/arch/arm64/boot/dts/qcom/qcs410-iot.dts +++ b/arch/arm64/boot/dts/qcom/qcs410-iot.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -14,9 +14,14 @@ #include "qcs410.dtsi" #include "qcs410-iot.dtsi" +#include "sm6150-audio-overlay.dtsi" / { model = "Qualcomm Technologies, Inc. QCS410 IOT"; compatible = "qcom,qcs410-iot", "qcom,qcs410", "qcom,iot"; qcom,board-id = <32 0>; }; + +&sm6150_snd { + /delete-property/ fsa4480-i2c-handle; +}; From 4bd935323d963047e42535f1e8d5e6be0cb571fe Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Mon, 8 Jun 2020 16:52:59 +0530 Subject: [PATCH 092/208] qcacld-3.0: unregister peer hang notifier Currently, we register the peer hang notifier when the peer unmap timer elapses, but do not unregister it. We also pass the peer reference for which the unmap timeout happened as part of the notifier registry. Since we do not unregister the notfier, there are chances that we call the notifier with a stale peer reference during the subsequent hang event which results in a crash; avoid this by unregistering the peer hang notifier as part of device recovery. Change-Id: I36bd8d9c1b4e38e1ba9d8c16b79df7f0cd1c9f82 CRs-Fixed: 2688676 --- core/dp/txrx/ol_txrx.c | 130 +++++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 57 deletions(-) diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 093b882c60ea..c53d00b4aa41 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -130,6 +130,78 @@ extern void ol_txrx_get_pn_info(void *ppeer, uint8_t **last_pn_valid, /* thresh for peer's cached buf queue beyond which the elements are dropped */ #define OL_TXRX_CACHED_BUFQ_THRESH 128 +#ifdef DP_SUPPORT_RECOVERY_NOTIFY +static +int ol_peer_recovery_notifier_cb(struct notifier_block *block, + unsigned long state, void *data) +{ + struct qdf_notifer_data *notif_data = data; + qdf_notif_block *notif_block; + struct ol_txrx_peer_t *peer; + struct peer_hang_data hang_data; + enum peer_debug_id_type dbg_id; + + if (!data || !block) + return -EINVAL; + + notif_block = qdf_container_of(block, qdf_notif_block, notif_block); + + peer = notif_block->priv_data; + if (!peer) + return -EINVAL; + + if (notif_data->offset >= QDF_WLAN_MAX_HOST_OFFSET) + return NOTIFY_STOP_MASK; + + QDF_HANG_EVT_SET_HDR(&hang_data.tlv_header, + HANG_EVT_TAG_DP_PEER_INFO, + QDF_HANG_GET_STRUCT_TLVLEN(struct peer_hang_data)); + + qdf_mem_copy(&hang_data.peer_mac_addr, &peer->mac_addr.raw, + QDF_MAC_ADDR_SIZE); + + for (dbg_id = 0; dbg_id < PEER_DEBUG_ID_MAX; dbg_id++) + if (qdf_atomic_read(&peer->access_list[dbg_id])) + hang_data.peer_timeout_bitmask |= (1 << dbg_id); + + qdf_mem_copy(notif_data->hang_data + notif_data->offset, + &hang_data, sizeof(struct peer_hang_data)); + notif_data->offset += sizeof(struct peer_hang_data); + + return 0; +} + +static qdf_notif_block ol_peer_recovery_notifier = { + .notif_block.notifier_call = ol_peer_recovery_notifier_cb, +}; + +static +QDF_STATUS ol_register_peer_recovery_notifier(struct ol_txrx_peer_t *peer) +{ + ol_peer_recovery_notifier.priv_data = peer; + + return qdf_hang_event_register_notifier(&ol_peer_recovery_notifier); +} + +static +QDF_STATUS ol_unregister_peer_recovery_notifier(void) +{ + return qdf_hang_event_unregister_notifier(&ol_peer_recovery_notifier); +} +#else +static inline +QDF_STATUS ol_register_peer_recovery_notifier(struct ol_txrx_peer_t *peer) +{ + return QDF_STATUS_SUCCESS; +} + +static +QDF_STATUS ol_unregister_peer_recovery_notifier(void) +{ + return QDF_STATUS_SUCCESS; +} +#endif + #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) /** @@ -2393,6 +2465,7 @@ static void ol_txrx_pdev_detach(struct cdp_pdev *ppdev, int force) ol_txrx_pdev_grp_stat_destroy(pdev); ol_txrx_debugfs_exit(pdev); + ol_unregister_peer_recovery_notifier(); qdf_mem_free(pdev); } @@ -3987,63 +4060,6 @@ static QDF_STATUS ol_txrx_clear_peer(struct cdp_pdev *ppdev, uint8_t sta_id) return status; } -#ifdef DP_SUPPORT_RECOVERY_NOTIFY -static -int ol_peer_recovery_notifier_cb(struct notifier_block *block, - unsigned long state, void *data) -{ - struct qdf_notifer_data *notif_data = data; - qdf_notif_block *notif_block; - struct ol_txrx_peer_t *peer; - struct peer_hang_data hang_data; - enum peer_debug_id_type dbg_id; - - if (!data || !block) - return -EINVAL; - - notif_block = qdf_container_of(block, qdf_notif_block, notif_block); - - peer = notif_block->priv_data; - if (!peer) - return -EINVAL; - - QDF_HANG_EVT_SET_HDR(&hang_data.tlv_header, - HANG_EVT_TAG_DP_PEER_INFO, - QDF_HANG_GET_STRUCT_TLVLEN(struct peer_hang_data)); - - qdf_mem_copy(&hang_data.peer_mac_addr, &peer->mac_addr.raw, - QDF_MAC_ADDR_SIZE); - - for (dbg_id = 0; dbg_id < PEER_DEBUG_ID_MAX; dbg_id++) - if (qdf_atomic_read(&peer->access_list[dbg_id])) - hang_data.peer_timeout_bitmask |= (1 << dbg_id); - - qdf_mem_copy(notif_data->hang_data + notif_data->offset, - &hang_data, sizeof(struct peer_hang_data)); - notif_data->offset += sizeof(struct peer_hang_data); - - return 0; -} - -static qdf_notif_block ol_peer_recovery_notifier = { - .notif_block.notifier_call = ol_peer_recovery_notifier_cb, -}; - -static -QDF_STATUS ol_register_peer_recovery_notifier(struct ol_txrx_peer_t *peer) -{ - ol_peer_recovery_notifier.priv_data = peer; - - return qdf_hang_event_register_notifier(&ol_peer_recovery_notifier); -} -#else -static inline -QDF_STATUS ol_register_peer_recovery_notifier(struct ol_txrx_peer_t *peer) -{ - return QDF_STATUS_SUCCESS; -} -#endif - /** * peer_unmap_timer_handler() - peer unmap timer function * @data: peer object pointer From 8a4bbc00fa45fe9cf39ee3b077e2b89ad293e04c Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Wed, 3 Jun 2020 01:43:03 +0530 Subject: [PATCH 093/208] qcacld-3.0: Add dealloc api to free memory allocated for ll_stats Currently there is no dealloc api for ll_stats request to free the memory allocated for the ll_stats request's priv structure because of which memory is not freed from the request manager infrastructure, instead host frees the memory in request api. with this mechanism there is a race condition where if timeout occurs then in the caller api memory is freed for the response list and after processing the response list if the response callback comes then memory is allocated and inserted in the response list which will never be freed as the response list is already processed in the caller api after the timeout. Add a dealloc function for ll_stats request to free the memory with The help of request manager infrastructure. Change-Id: If91d777901d0c4c598a138b1439de7de024249a4 CRs-Fixed: 2703825 --- core/hdd/src/wlan_hdd_stats.c | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 000db6f95d97..d9868aafd3a5 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -1514,6 +1514,48 @@ static void wlan_hdd_handle_ll_stats(struct hdd_adapter *adapter, } } +static void wlan_hdd_dealloc_ll_stats(void *priv) +{ + struct hdd_ll_stats_priv *ll_stats_priv = priv; + struct hdd_ll_stats *stats = NULL; + QDF_STATUS status; + qdf_list_node_t *ll_node; + + if (!ll_stats_priv) + return; + + qdf_spin_lock(&ll_stats_priv->ll_stats_lock); + status = qdf_list_remove_front(&ll_stats_priv->ll_stats_q, &ll_node); + qdf_spin_unlock(&ll_stats_priv->ll_stats_lock); + while (QDF_IS_STATUS_SUCCESS(status)) { + stats = qdf_container_of(ll_node, struct hdd_ll_stats, + ll_stats_node); + + if (stats->result_param_id == WMI_LINK_STATS_RADIO) { + tpSirWifiRadioStat radio_stat = stats->result; + int i; + int num_radio = stats->stats_nradio_npeer.no_of_radios; + + for (i = 0; i < num_radio; i++) { + if (radio_stat->numChannels) + qdf_mem_free(radio_stat->channels); + if (radio_stat->total_num_tx_power_levels) + qdf_mem_free(radio_stat-> + tx_time_per_power_level); + radio_stat++; + } + } + + qdf_mem_free(stats->result); + qdf_mem_free(stats); + qdf_spin_lock(&ll_stats_priv->ll_stats_lock); + status = qdf_list_remove_front(&ll_stats_priv->ll_stats_q, + &ll_node); + qdf_spin_unlock(&ll_stats_priv->ll_stats_lock); + } + qdf_list_destroy(&ll_stats_priv->ll_stats_q); +} + static int wlan_hdd_send_ll_stats_req(struct hdd_adapter *adapter, tSirLLStatsGetReq *req) { @@ -1528,6 +1570,7 @@ static int wlan_hdd_send_ll_stats_req(struct hdd_adapter *adapter, static const struct osif_request_params params = { .priv_size = sizeof(*priv), .timeout_ms = WLAN_WAIT_TIME_LL_STATS, + .dealloc = wlan_hdd_dealloc_ll_stats, }; hdd_enter(); From baa5e3491d80d17590a9117222688f6623a1c43d Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Thu, 18 Jun 2020 20:44:50 +0530 Subject: [PATCH 094/208] qcacld-3.0: Remove validate context check in LL stats get NB ops As a part of LL stats get NB operation, the driver sends the LL stats req to the FW, waits for the response and sends back the stats in a synchronous reply. All this happens as a part of one single NB operation. Within this operation, if an rmmod comes, there can be a possiblity of a memory leak. In function hdd_link_layer_process_radio_stats, there is a check to validate the hdd_context and return if the driver is undergoing load/unload. As a part of the premature return, some memory are not freed properly. To resolve this, remove the validity check from the NB operation. The operation itself comes with DSC synchronization and ensures that the hdd_context remains valid atleast until the operation is complete. Thus there is no need for the redundant check of validity of hdd_context, which resolves the memory leak issue also. Change-Id: Ieea755e83addac99659dbd6e0e5f160b86e6f9fa CRs-Fixed: 2679081 --- core/hdd/src/wlan_hdd_stats.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 000db6f95d97..16cfd46486e5 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -997,13 +997,16 @@ static void hdd_link_layer_process_radio_stats(struct hdd_adapter *adapter, tpSirWifiRadioStat pData, u32 num_radio) { - int status, i, nr, ret; + int i, nr, ret; tSirWifiRadioStat *pWifiRadioStat = pData; - struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); - status = wlan_hdd_validate_context(hdd_ctx); - if (0 != status) - return; + /* + * There is no need for wlan_hdd_validate_context here. This is a NB + * operation that will come with DSC synchronization. This ensures that + * no driver transition will take place as long as this operation is + * not complete. Thus the need to check validity of hdd_context is not + * required. + */ hdd_debug("LL_STATS_RADIO: number of radios: %u", num_radio); From 9d6714e09bc5c5b73567566f9d3313b6a867304c Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 16 Jun 2020 09:56:51 -0700 Subject: [PATCH 095/208] f2fs: avoid checkpatch error ERROR:INITIALISED_STATIC: do not initialise statics to NULL Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 41d12a1413cf..39a6168046f9 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -482,7 +482,7 @@ bool f2fs_is_compress_backend_ready(struct inode *inode) return f2fs_cops[F2FS_I(inode)->i_compress_algorithm]; } -static mempool_t *compress_page_pool = NULL; +static mempool_t *compress_page_pool; static int num_compress_pages = 512; module_param(num_compress_pages, uint, 0444); MODULE_PARM_DESC(num_compress_pages, From 25f287f8eb573caecafa3a37b0d4592aa717467f Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Wed, 10 Jun 2020 01:14:46 +0300 Subject: [PATCH 096/208] f2fs: use kfree() instead of kvfree() to free superblock data Use kfree() instead of kvfree() to free super in read_raw_super_block() because the memory is allocated with kzalloc() in the function. Use kfree() instead of kvfree() to free sbi, raw_super in f2fs_fill_super() and f2fs_put_super() because the memory is allocated with kzalloc(). Signed-off-by: Denis Efremov Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 1a4899141cbd..ac1ece6e0831 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1247,7 +1247,7 @@ static void f2fs_put_super(struct super_block *sb) sb->s_fs_info = NULL; if (sbi->s_chksum_driver) crypto_free_shash(sbi->s_chksum_driver); - kvfree(sbi->raw_super); + kfree(sbi->raw_super); destroy_device_list(sbi); f2fs_destroy_xattr_caches(sbi); @@ -1263,7 +1263,7 @@ static void f2fs_put_super(struct super_block *sb) #ifdef CONFIG_UNICODE utf8_unload(sbi->s_encoding); #endif - kvfree(sbi); + kfree(sbi); } int f2fs_sync_fs(struct super_block *sb, int sync) @@ -3159,7 +3159,7 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi, /* No valid superblock */ if (!*raw_super) - kvfree(super); + kfree(super); else err = 0; @@ -3826,11 +3826,11 @@ free_options: fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); kvfree(options); free_sb_buf: - kvfree(raw_super); + kfree(raw_super); free_sbi: if (sbi->s_chksum_driver) crypto_free_shash(sbi->s_chksum_driver); - kvfree(sbi); + kfree(sbi); /* give only one another chance */ if (retry_cnt > 0 && skip_recovery) { From 0da2692c11a8b0ff98cfd5db76188db416ec302a Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Mon, 15 Jun 2020 16:11:38 +0800 Subject: [PATCH 097/208] f2fs: remove useless truncate in f2fs_collapse_range() Since offset < new_size, no need to do truncate_pagecache() again with new_size. Signed-off-by: Wei Fang Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 953752c0ce2a..002b19bc3db9 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1375,8 +1375,6 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len) truncate_pagecache(inode, offset); new_size = i_size_read(inode) - len; - truncate_pagecache(inode, new_size); - ret = f2fs_truncate_blocks(inode, new_size, true); up_write(&F2FS_I(inode)->i_mmap_sem); if (!ret) From 4946ce1ece152631f7d1eedfa42d645df9ab58c0 Mon Sep 17 00:00:00 2001 From: Wuyun Zhao Date: Thu, 18 Jun 2020 10:58:37 +0800 Subject: [PATCH 098/208] f2fs: fix a race condition between f2fs_write_end_io and f2fs_del_fsync_node_entry Under some condition, the __write_node_page will submit a page which is not f2fs_in_warm_node_list and will not call f2fs_add_fsync_node_entry. f2fs_gc continue to run to invoke f2fs_iget -> do_read_inode to read the same node page and set code node, which make f2fs_in_warm_node_list become true, that will cause f2fs_bug_on in f2fs_del_fsync_node_entry when f2fs_write_end_io called. - f2fs_write_end_io - f2fs_iget - do_read_inode - set_cold_node recover cold node flag - f2fs_in_warm_node_list - is_cold_node if node is cold, assume we have added node to fsync_node_list during writepages() - f2fs_del_fsync_node_entry - f2fs_bug_on() due to node page is not in fsync_node_list [ 34.966133] Call trace: [ 34.969902] f2fs_del_fsync_node_entry+0x100/0x108 [ 34.976071] f2fs_write_end_io+0x1e0/0x288 [ 34.981539] bio_endio+0x248/0x270 [ 34.986289] blk_update_request+0x2b0/0x4d8 [ 34.991841] scsi_end_request+0x40/0x440 [ 34.997126] scsi_io_completion+0xa4/0x748 [ 35.002593] scsi_finish_command+0xdc/0x110 [ 35.008143] scsi_softirq_done+0x118/0x150 [ 35.013610] blk_done_softirq+0x8c/0xe8 [ 35.018811] __do_softirq+0x2e8/0x578 [ 35.023828] irq_exit+0xfc/0x120 [ 35.028398] handle_IPI+0x1d8/0x330 [ 35.033233] gic_handle_irq+0x110/0x1d4 [ 35.038433] el1_irq+0xb4/0x130 [ 35.042917] kmem_cache_alloc+0x3f0/0x418 [ 35.048288] radix_tree_node_alloc+0x50/0xf8 [ 35.053933] __radix_tree_create+0xf8/0x188 [ 35.059484] __radix_tree_insert+0x3c/0x128 [ 35.065035] add_gc_inode+0x90/0x118 [ 35.069967] f2fs_gc+0x1b80/0x2d70 [ 35.074718] f2fs_disable_checkpoint+0x94/0x1d0 [ 35.080621] f2fs_fill_super+0x10c4/0x1b88 [ 35.086088] mount_bdev+0x194/0x1e0 [ 35.090923] f2fs_mount+0x40/0x50 [ 35.095589] mount_fs+0xb4/0x190 [ 35.100159] vfs_kern_mount+0x80/0x1d8 [ 35.105260] do_mount+0x478/0xf18 [ 35.109926] ksys_mount+0x90/0xd0 [ 35.114592] __arm64_sys_mount+0x24/0x38 Signed-off-by: Wuyun Zhao Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index be6ac33461d1..0df5c8ca3e5a 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -402,6 +402,7 @@ static int do_read_inode(struct inode *inode) /* try to recover cold bit for non-dir inode */ if (!S_ISDIR(inode->i_mode) && !is_cold_node(node_page)) { + f2fs_wait_on_page_writeback(node_page, NODE, true, true); set_cold_node(node_page, false); set_page_dirty(node_page); } From 536e43b83e2ccf6e13b015a4deb9a8b6a2e77076 Mon Sep 17 00:00:00 2001 From: Jack Qiu Date: Thu, 18 Jun 2020 12:37:10 +0800 Subject: [PATCH 099/208] f2fs: get the right gc victim section when section has several segments Assume each section has 4 segment: .___________________________. |_Segment0_|_..._|_Segment3_| . . . . .__________. |_section0_| Segment 0~2 has 0 valid block, segment 3 has 512 valid blocks. It will fail if we want to gc section0 in this scenes, because all 4 segments in section0 is not dirty. So we should use dirty section bitmap instead of dirty segment bitmap to get right victim section. Signed-off-by: Jack Qiu Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/gc.c | 39 +++++++++++++++++------------- fs/f2fs/segment.c | 61 +++++++++++++++++++++++++++++++++++++++++++++-- fs/f2fs/segment.h | 8 +++++-- 3 files changed, 88 insertions(+), 20 deletions(-) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 9ea8d6a141a5..236249de9617 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -21,6 +21,9 @@ #include "gc.h" #include +static unsigned int count_bits(const unsigned long *addr, + unsigned int offset, unsigned int len); + static int gc_thread_func(void *data) { struct f2fs_sb_info *sbi = data; @@ -187,14 +190,20 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type, if (p->alloc_mode == SSR) { p->gc_mode = GC_GREEDY; - p->dirty_segmap = dirty_i->dirty_segmap[type]; + p->dirty_bitmap = dirty_i->dirty_segmap[type]; p->max_search = dirty_i->nr_dirty[type]; p->ofs_unit = 1; } else { p->gc_mode = select_gc_type(sbi, gc_type); - p->dirty_segmap = dirty_i->dirty_segmap[DIRTY]; - p->max_search = dirty_i->nr_dirty[DIRTY]; p->ofs_unit = sbi->segs_per_sec; + if (__is_large_section(sbi)) { + p->dirty_bitmap = dirty_i->dirty_secmap; + p->max_search = count_bits(p->dirty_bitmap, + 0, MAIN_SECS(sbi)); + } else { + p->dirty_bitmap = dirty_i->dirty_segmap[DIRTY]; + p->max_search = dirty_i->nr_dirty[DIRTY]; + } } /* @@ -365,10 +374,14 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, } while (1) { - unsigned long cost; - unsigned int segno; + unsigned long cost, *dirty_bitmap; + unsigned int unit_no, segno; - segno = find_next_bit(p.dirty_segmap, last_segment, p.offset); + dirty_bitmap = p.dirty_bitmap; + unit_no = find_next_bit(dirty_bitmap, + last_segment / p.ofs_unit, + p.offset / p.ofs_unit); + segno = unit_no * p.ofs_unit; if (segno >= last_segment) { if (sm->last_victim[p.gc_mode]) { last_segment = @@ -381,14 +394,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, } p.offset = segno + p.ofs_unit; - if (p.ofs_unit > 1) { - p.offset -= segno % p.ofs_unit; - nsearched += count_bits(p.dirty_segmap, - p.offset - p.ofs_unit, - p.ofs_unit); - } else { - nsearched++; - } + nsearched++; #ifdef CONFIG_F2FS_CHECK_FS /* @@ -421,9 +427,10 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, next: if (nsearched >= p.max_search) { if (!sm->last_victim[p.gc_mode] && segno <= last_victim) - sm->last_victim[p.gc_mode] = last_victim + 1; + sm->last_victim[p.gc_mode] = + last_victim + p.ofs_unit; else - sm->last_victim[p.gc_mode] = segno + 1; + sm->last_victim[p.gc_mode] = segno + p.ofs_unit; sm->last_victim[p.gc_mode] %= (MAIN_SECS(sbi) * sbi->segs_per_sec); break; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index e4898789c5c0..142e7d6f549c 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -796,6 +796,18 @@ static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, } if (!test_and_set_bit(segno, dirty_i->dirty_segmap[t])) dirty_i->nr_dirty[t]++; + + if (__is_large_section(sbi)) { + unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); + unsigned short valid_blocks = + get_valid_blocks(sbi, segno, true); + + f2fs_bug_on(sbi, unlikely(!valid_blocks || + valid_blocks == BLKS_PER_SEC(sbi))); + + if (!IS_CURSEC(sbi, secno)) + set_bit(secno, dirty_i->dirty_secmap); + } } } @@ -803,6 +815,7 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, enum dirty_type dirty_type) { struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + unsigned short valid_blocks; if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type])) dirty_i->nr_dirty[dirty_type]--; @@ -814,13 +827,26 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) dirty_i->nr_dirty[t]--; - if (get_valid_blocks(sbi, segno, true) == 0) { + valid_blocks = get_valid_blocks(sbi, segno, true); + if (valid_blocks == 0) { clear_bit(GET_SEC_FROM_SEG(sbi, segno), dirty_i->victim_secmap); #ifdef CONFIG_F2FS_CHECK_FS clear_bit(segno, SIT_I(sbi)->invalid_segmap); #endif } + if (__is_large_section(sbi)) { + unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); + + if (!valid_blocks || + valid_blocks == BLKS_PER_SEC(sbi)) { + clear_bit(secno, dirty_i->dirty_secmap); + return; + } + + if (!IS_CURSEC(sbi, secno)) + set_bit(secno, dirty_i->dirty_secmap); + } } } @@ -4292,8 +4318,9 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi) { struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); struct free_segmap_info *free_i = FREE_I(sbi); - unsigned int segno = 0, offset = 0; + unsigned int segno = 0, offset = 0, secno; unsigned short valid_blocks; + unsigned short blks_per_sec = BLKS_PER_SEC(sbi); while (1) { /* find dirty segment based on free segmap */ @@ -4312,6 +4339,22 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi) __locate_dirty_segment(sbi, segno, DIRTY); mutex_unlock(&dirty_i->seglist_lock); } + + if (!__is_large_section(sbi)) + return; + + mutex_lock(&dirty_i->seglist_lock); + for (segno = 0; segno < MAIN_SECS(sbi); segno += blks_per_sec) { + valid_blocks = get_valid_blocks(sbi, segno, true); + secno = GET_SEC_FROM_SEG(sbi, segno); + + if (!valid_blocks || valid_blocks == blks_per_sec) + continue; + if (IS_CURSEC(sbi, secno)) + continue; + set_bit(secno, dirty_i->dirty_secmap); + } + mutex_unlock(&dirty_i->seglist_lock); } static int init_victim_secmap(struct f2fs_sb_info *sbi) @@ -4348,6 +4391,14 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi) return -ENOMEM; } + if (__is_large_section(sbi)) { + bitmap_size = f2fs_bitmap_size(MAIN_SECS(sbi)); + dirty_i->dirty_secmap = f2fs_kvzalloc(sbi, + bitmap_size, GFP_KERNEL); + if (!dirty_i->dirty_secmap) + return -ENOMEM; + } + init_dirty_segmap(sbi); return init_victim_secmap(sbi); } @@ -4517,6 +4568,12 @@ static void destroy_dirty_segmap(struct f2fs_sb_info *sbi) for (i = 0; i < NR_DIRTY_TYPE; i++) discard_dirty_segmap(sbi, i); + if (__is_large_section(sbi)) { + mutex_lock(&dirty_i->seglist_lock); + kvfree(dirty_i->dirty_secmap); + mutex_unlock(&dirty_i->seglist_lock); + } + destroy_victim_secmap(sbi); SM_I(sbi)->dirty_info = NULL; kvfree(dirty_i); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 1e6ff468fe67..280fcaefa532 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -166,8 +166,11 @@ enum { struct victim_sel_policy { int alloc_mode; /* LFS or SSR */ int gc_mode; /* GC_CB or GC_GREEDY */ - unsigned long *dirty_segmap; /* dirty segment bitmap */ - unsigned int max_search; /* maximum # of segments to search */ + unsigned long *dirty_bitmap; /* dirty segment/section bitmap */ + unsigned int max_search; /* + * maximum # of segments/sections + * to search + */ unsigned int offset; /* last scanned bitmap offset */ unsigned int ofs_unit; /* bitmap search unit */ unsigned int min_cost; /* minimum cost */ @@ -266,6 +269,7 @@ enum dirty_type { struct dirty_seglist_info { const struct victim_selection *v_ops; /* victim selction operation */ unsigned long *dirty_segmap[NR_DIRTY_TYPE]; + unsigned long *dirty_secmap; struct mutex seglist_lock; /* lock for segment bitmaps */ int nr_dirty[NR_DIRTY_TYPE]; /* # of dirty segments */ unsigned long *victim_secmap; /* background GC victims */ From 2b53e9eff9d15eb939d3e03b21ef4f4a21464192 Mon Sep 17 00:00:00 2001 From: Wang Xiaojun Date: Wed, 17 Jun 2020 20:30:12 +0800 Subject: [PATCH 100/208] f2fs: use kfree() to free variables allocated by match_strdup() Use kfree() instead of kvfree() to free variables allocated by match_strdup(). Because the memory is allocated with kmalloc inside match_strdup(). Signed-off-by: Wang Xiaojun Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index ac1ece6e0831..0712c5e6cd8b 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -347,7 +347,7 @@ static int f2fs_set_qf_name(struct super_block *sb, int qtype, set_opt(sbi, QUOTA); return 0; errout: - kvfree(qname); + kfree(qname); return ret; } @@ -359,7 +359,7 @@ static int f2fs_clear_qf_name(struct super_block *sb, int qtype) f2fs_err(sbi, "Cannot change journaled quota options when quota turned on"); return -EINVAL; } - kvfree(F2FS_OPTION(sbi).s_qf_names[qtype]); + kfree(F2FS_OPTION(sbi).s_qf_names[qtype]); F2FS_OPTION(sbi).s_qf_names[qtype] = NULL; return 0; } @@ -493,10 +493,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "sync")) { F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_SYNC; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_disable_roll_forward: set_opt(sbi, DISABLE_ROLL_FORWARD); @@ -653,17 +653,17 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) if (!strcmp(name, "adaptive")) { if (f2fs_sb_has_blkzoned(sbi)) { f2fs_warn(sbi, "adaptive mode is not allowed with zoned block device feature"); - kvfree(name); + kfree(name); return -EINVAL; } F2FS_OPTION(sbi).fs_mode = FS_MODE_ADAPTIVE; } else if (!strcmp(name, "lfs")) { F2FS_OPTION(sbi).fs_mode = FS_MODE_LFS; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_io_size_bits: if (args->from && match_int(args, &arg)) @@ -789,10 +789,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "fs-based")) { F2FS_OPTION(sbi).whint_mode = WHINT_MODE_FS; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_alloc: name = match_strdup(&args[0]); @@ -804,10 +804,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "reuse")) { F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_REUSE; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_fsync: name = match_strdup(&args[0]); @@ -821,10 +821,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_NOBARRIER; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_test_dummy_encryption: ret = f2fs_set_test_dummy_encryption(sb, p, &args[0], @@ -1254,7 +1254,7 @@ static void f2fs_put_super(struct super_block *sb) mempool_destroy(sbi->write_io_dummy); #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); #endif fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); destroy_percpu_info(sbi); @@ -1755,7 +1755,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) GFP_KERNEL); if (!org_mount_opt.s_qf_names[i]) { for (j = 0; j < i; j++) - kvfree(org_mount_opt.s_qf_names[j]); + kfree(org_mount_opt.s_qf_names[j]); return -ENOMEM; } } else { @@ -1880,7 +1880,7 @@ skip: #ifdef CONFIG_QUOTA /* Release old quota file names */ for (i = 0; i < MAXQUOTAS; i++) - kvfree(org_mount_opt.s_qf_names[i]); + kfree(org_mount_opt.s_qf_names[i]); #endif /* Update the POSIXACL Flag */ sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | @@ -1901,7 +1901,7 @@ restore_opts: #ifdef CONFIG_QUOTA F2FS_OPTION(sbi).s_jquota_fmt = org_mount_opt.s_jquota_fmt; for (i = 0; i < MAXQUOTAS; i++) { - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); F2FS_OPTION(sbi).s_qf_names[i] = org_mount_opt.s_qf_names[i]; } #endif @@ -3821,7 +3821,7 @@ free_bio_info: free_options: #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); #endif fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); kvfree(options); From d9b4ee76be63635a47eea7ffdd4632f300aa848b Mon Sep 17 00:00:00 2001 From: Daeho Jeong Date: Thu, 18 Jun 2020 21:51:52 +0900 Subject: [PATCH 101/208] f2fs: add F2FS_IOC_SEC_TRIM_FILE ioctl Added a new ioctl to send discard commands or/and zero out to selected data area of a regular file for security reason. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 15 +++++ fs/f2fs/file.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 974eae36d979..eed1bcdf97f8 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -434,6 +434,8 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal, _IOR(F2FS_IOCTL_MAGIC, 18, __u64) #define F2FS_IOC_RESERVE_COMPRESS_BLOCKS \ _IOR(F2FS_IOCTL_MAGIC, 19, __u64) +#define F2FS_IOC_SEC_TRIM_FILE _IOW(F2FS_IOCTL_MAGIC, 20, \ + struct f2fs_sectrim_range) #define F2FS_IOC_SET_ENCRYPTION_POLICY FS_IOC_SET_ENCRYPTION_POLICY #define F2FS_IOC_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY @@ -450,6 +452,13 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal, #define F2FS_GOING_DOWN_METAFLUSH 0x3 /* going down with meta flush */ #define F2FS_GOING_DOWN_NEED_FSCK 0x4 /* going down to trigger fsck */ +/* + * Flags used by F2FS_IOC_SEC_TRIM_FILE + */ +#define F2FS_TRIM_FILE_DISCARD 0x1 /* send discard command */ +#define F2FS_TRIM_FILE_ZEROOUT 0x2 /* zero out */ +#define F2FS_TRIM_FILE_MASK 0x3 + #if defined(__KERNEL__) && defined(CONFIG_COMPAT) /* * ioctl commands in 32 bit emulation @@ -485,6 +494,12 @@ struct f2fs_flush_device { u32 segments; /* # of segments to flush */ }; +struct f2fs_sectrim_range { + u64 start; + u64 len; + u64 flags; +}; + /* for inline stuff */ #define DEF_INLINE_RESERVED_SIZE 1 static inline int get_extra_isize(struct inode *inode); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 002b19bc3db9..ab27e478c1b0 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "f2fs.h" #include "node.h" @@ -3694,6 +3695,181 @@ out: return ret; } +static int f2fs_secure_erase(struct block_device *bdev, block_t block, + block_t len, u32 flags) +{ + struct request_queue *q = bdev_get_queue(bdev); + sector_t sector = SECTOR_FROM_BLOCK(block); + sector_t nr_sects = SECTOR_FROM_BLOCK(len); + int ret = 0; + + if (!q) + return -ENXIO; + + if (flags & F2FS_TRIM_FILE_DISCARD) + ret = blkdev_issue_discard(bdev, sector, nr_sects, GFP_NOFS, + blk_queue_secure_erase(q) ? + BLKDEV_DISCARD_SECURE : 0); + + if (!ret && (flags & F2FS_TRIM_FILE_ZEROOUT)) + ret = blkdev_issue_zeroout(bdev, sector, nr_sects, GFP_NOFS, 0); + + return ret; +} + +static int f2fs_sec_trim_file(struct file *filp, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct address_space *mapping = inode->i_mapping; + struct block_device *prev_bdev = NULL; + struct f2fs_sectrim_range range; + pgoff_t index, pg_end; + block_t prev_block = 0, len = 0; + u64 end_addr; + bool to_end; + int ret = 0; + + if (!(filp->f_mode & FMODE_WRITE)) + return -EBADF; + + if (copy_from_user(&range, (struct f2fs_sectrim_range __user *)arg, + sizeof(range))) + return -EFAULT; + + if (range.flags == 0 || (range.flags & ~F2FS_TRIM_FILE_MASK) || + !S_ISREG(inode->i_mode)) + return -EINVAL; + + if ((range.flags & F2FS_TRIM_FILE_DISCARD) && + !f2fs_hw_support_discard(sbi)) + return -EOPNOTSUPP; + + file_start_write(filp); + inode_lock(inode); + + if (f2fs_is_atomic_file(inode) || f2fs_compressed_file(inode)) { + ret = -EINVAL; + goto err; + } + + if (inode->i_size == 0) + goto err; + + end_addr = range.start + range.len; + if (end_addr > inode->i_size) { + ret = -EINVAL; + goto err; + } + + to_end = (end_addr == inode->i_size); + if (!IS_ALIGNED(range.start, F2FS_BLKSIZE) || + (!to_end && !IS_ALIGNED(end_addr, F2FS_BLKSIZE))) { + ret = -EINVAL; + goto err; + } + + index = F2FS_BYTES_TO_BLK(range.start); + pg_end = DIV_ROUND_UP(end_addr, F2FS_BLKSIZE); + + ret = f2fs_convert_inline_inode(inode); + if (ret) + goto err; + + down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); + down_write(&F2FS_I(inode)->i_mmap_sem); + + ret = filemap_write_and_wait_range(mapping, range.start, end_addr - 1); + if (ret) + goto out; + + truncate_inode_pages_range(mapping, range.start, + to_end ? -1 : end_addr - 1); + + while (index < pg_end) { + struct dnode_of_data dn; + pgoff_t end_offset, count; + int i; + + set_new_dnode(&dn, inode, NULL, NULL, 0); + ret = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE); + if (ret) { + if (ret == -ENOENT) { + index = f2fs_get_next_page_offset(&dn, index); + continue; + } + goto out; + } + + end_offset = ADDRS_PER_PAGE(dn.node_page, inode); + count = min(end_offset - dn.ofs_in_node, pg_end - index); + for (i = 0; i < count; i++, dn.ofs_in_node++) { + struct block_device *cur_bdev; + block_t blkaddr = f2fs_data_blkaddr(&dn); + + if (!__is_valid_data_blkaddr(blkaddr)) + continue; + + if (!f2fs_is_valid_blkaddr(sbi, blkaddr, + DATA_GENERIC_ENHANCE)) { + ret = -EFSCORRUPTED; + f2fs_put_dnode(&dn); + goto out; + } + + cur_bdev = f2fs_target_device(sbi, blkaddr, NULL); + if (f2fs_is_multi_device(sbi)) { + int di = f2fs_target_device_index(sbi, blkaddr); + + blkaddr -= FDEV(di).start_blk; + } + + if (len) { + if (prev_bdev == cur_bdev && + blkaddr == prev_block + len) { + len++; + } else { + ret = f2fs_secure_erase(prev_bdev, + prev_block, len, range.flags); + if (ret) { + f2fs_put_dnode(&dn); + goto out; + } + + len = 0; + } + } + + if (!len) { + prev_bdev = cur_bdev; + prev_block = blkaddr; + len = 1; + } + } + + f2fs_put_dnode(&dn); + index += count; + + if (fatal_signal_pending(current)) { + ret = -EINTR; + goto out; + } + cond_resched(); + } + + if (len) + ret = f2fs_secure_erase(prev_bdev, prev_block, len, + range.flags); +out: + up_write(&F2FS_I(inode)->i_mmap_sem); + up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); +err: + inode_unlock(inode); + file_end_write(filp); + + return ret; +} + long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp))))) @@ -3776,6 +3952,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return f2fs_release_compress_blocks(filp, arg); case F2FS_IOC_RESERVE_COMPRESS_BLOCKS: return f2fs_reserve_compress_blocks(filp, arg); + case F2FS_IOC_SEC_TRIM_FILE: + return f2fs_sec_trim_file(filp, arg); default: return -ENOTTY; } @@ -3942,6 +4120,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC_GET_COMPRESS_BLOCKS: case F2FS_IOC_RELEASE_COMPRESS_BLOCKS: case F2FS_IOC_RESERVE_COMPRESS_BLOCKS: + case F2FS_IOC_SEC_TRIM_FILE: break; default: return -ENOIOCTLCMD; From 231b862460927fcd9b9f394465601bd6bb9447bb Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Thu, 18 Jun 2020 14:36:22 +0800 Subject: [PATCH 102/208] f2fs: add prefix for exported symbols to avoid polluting global symbol namespace. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 4 ++-- fs/f2fs/data.c | 14 +++++++------- fs/f2fs/f2fs.h | 4 ++-- fs/f2fs/file.c | 4 ++-- fs/f2fs/gc.c | 2 +- fs/f2fs/segment.c | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 39a6168046f9..c7a53a936aec 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -925,7 +925,7 @@ retry: } if (prealloc) { - __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true); + f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true); set_new_dnode(&dn, cc->inode, NULL, NULL, 0); @@ -940,7 +940,7 @@ retry: break; } - __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false); + f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false); } if (likely(!ret)) { diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 6a1cc101d6a7..4b83df8bc7c5 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1426,7 +1426,7 @@ map_blocks: return err; } -void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock) +void f2fs_do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock) { if (flag == F2FS_GET_BLOCK_PRE_AIO) { if (lock) @@ -1491,7 +1491,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, next_dnode: if (map->m_may_create) - __do_map_lock(sbi, flag, true); + f2fs_do_map_lock(sbi, flag, true); /* When reading holes, we need its node page */ set_new_dnode(&dn, inode, NULL, NULL, 0); @@ -1640,7 +1640,7 @@ skip: f2fs_put_dnode(&dn); if (map->m_may_create) { - __do_map_lock(sbi, flag, false); + f2fs_do_map_lock(sbi, flag, false); f2fs_balance_fs(sbi, dn.node_changed); } goto next_dnode; @@ -1666,7 +1666,7 @@ sync_out: f2fs_put_dnode(&dn); unlock_out: if (map->m_may_create) { - __do_map_lock(sbi, flag, false); + f2fs_do_map_lock(sbi, flag, false); f2fs_balance_fs(sbi, dn.node_changed); } out: @@ -3227,7 +3227,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, if (f2fs_has_inline_data(inode) || (pos & PAGE_MASK) >= i_size_read(inode)) { - __do_map_lock(sbi, flag, true); + f2fs_do_map_lock(sbi, flag, true); locked = true; } @@ -3264,7 +3264,7 @@ restart: err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE); if (err || dn.data_blkaddr == NULL_ADDR) { f2fs_put_dnode(&dn); - __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, + f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true); WARN_ON(flag != F2FS_GET_BLOCK_PRE_AIO); locked = true; @@ -3280,7 +3280,7 @@ out: f2fs_put_dnode(&dn); unlock_out: if (locked) - __do_map_lock(sbi, flag, false); + f2fs_do_map_lock(sbi, flag, false); return err; } diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index eed1bcdf97f8..d1d59101b6ae 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3344,7 +3344,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi); int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable); void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi); int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra); -void allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type, +void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type, unsigned int start, unsigned int end); void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi, int type); int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range); @@ -3468,7 +3468,7 @@ struct page *f2fs_get_lock_data_page(struct inode *inode, pgoff_t index, struct page *f2fs_get_new_data_page(struct inode *inode, struct page *ipage, pgoff_t index, bool new_i_size); int f2fs_do_write_data_page(struct f2fs_io_info *fio); -void __do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock); +void f2fs_do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock); int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int create, int flag); int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index ab27e478c1b0..491f5c35614b 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -105,11 +105,11 @@ static int f2fs_vm_page_mkwrite(struct vm_fault *vmf) if (need_alloc) { /* block allocation */ - __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true); + f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true); set_new_dnode(&dn, inode, NULL, NULL, 0); err = f2fs_get_block(&dn, page->index); f2fs_put_dnode(&dn); - __do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false); + f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false); } #ifdef CONFIG_F2FS_FS_COMPRESSION diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 236249de9617..8782d7c8f44a 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1441,7 +1441,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi, /* Move out cursegs from the target range */ for (type = CURSEG_HOT_DATA; type < NR_CURSEG_TYPE; type++) - allocate_segment_for_resize(sbi, type, start, end); + f2fs_allocate_segment_for_resize(sbi, type, start, end); /* do GC to move out valid blocks in the range */ for (segno = start; segno <= end; segno += sbi->segs_per_sec) { diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 142e7d6f549c..e009e6676e63 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2699,7 +2699,7 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi, stat_inc_seg_type(sbi, curseg); } -void allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type, +void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type, unsigned int start, unsigned int end) { struct curseg_info *curseg = CURSEG_I(sbi, type); From 6e0c3af68d67ed8119c3a3070a074e220cad124e Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Thu, 18 Jun 2020 14:36:23 +0800 Subject: [PATCH 103/208] f2fs: shrink node_write lock coverage - to avoid race between checkpoint and quota file writeback, it just needs to hold read lock of node_write in writeback path. - node_write lock has covered all LFS data write paths, it's not necessary, we only need to hold node_write lock at write path of quota file. This refactors commit ca7f76e68074 ("f2fs: fix wrong discard space"). Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 18 +++++++++++++++--- fs/f2fs/data.c | 12 ++++++++++++ fs/f2fs/segment.c | 11 ----------- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index c7a53a936aec..a15c0fea032e 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -1072,8 +1072,16 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc, loff_t psize; int i, err; - if (!IS_NOQUOTA(inode) && !f2fs_trylock_op(sbi)) + if (IS_NOQUOTA(inode)) { + /* + * We need to wait for node_write to avoid block allocation during + * checkpoint. This can only happen to quota writes which can cause + * the below discard race condition. + */ + down_read(&sbi->node_write); + } else if (!f2fs_trylock_op(sbi)) { return -EAGAIN; + } set_new_dnode(&dn, cc->inode, NULL, NULL, 0); @@ -1179,7 +1187,9 @@ unlock_continue: set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN); f2fs_put_dnode(&dn); - if (!IS_NOQUOTA(inode)) + if (IS_NOQUOTA(inode)) + up_read(&sbi->node_write); + else f2fs_unlock_op(sbi); spin_lock(&fi->i_size_lock); @@ -1206,7 +1216,9 @@ out_put_cic: out_put_dnode: f2fs_put_dnode(&dn); out_unlock_op: - if (!IS_NOQUOTA(inode)) + if (IS_NOQUOTA(inode)) + up_read(&sbi->node_write); + else f2fs_unlock_op(sbi); return -EAGAIN; } diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 4b83df8bc7c5..2649b5456f3b 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2729,8 +2729,20 @@ write: /* Dentry/quota blocks are controlled by checkpoint */ if (S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) { + /* + * We need to wait for node_write to avoid block allocation during + * checkpoint. This can only happen to quota writes which can cause + * the below discard race condition. + */ + if (IS_NOQUOTA(inode)) + down_read(&sbi->node_write); + fio.need_lock = LOCK_DONE; err = f2fs_do_write_data_page(&fio); + + if (IS_NOQUOTA(inode)) + up_read(&sbi->node_write); + goto done; } diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index e009e6676e63..52321382b391 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3132,14 +3132,6 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, type = CURSEG_COLD_DATA; } - /* - * We need to wait for node_write to avoid block allocation during - * checkpoint. This can only happen to quota writes which can cause - * the below discard race condition. - */ - if (IS_DATASEG(type)) - down_write(&sbi->node_write); - down_read(&SM_I(sbi)->curseg_lock); mutex_lock(&curseg->curseg_mutex); @@ -3205,9 +3197,6 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, up_read(&SM_I(sbi)->curseg_lock); - if (IS_DATASEG(type)) - up_write(&sbi->node_write); - if (put_pin_sem) up_read(&sbi->pin_sem); } From 59e0254678f11f9ed73ff5b140f6c9c0c1e0ead0 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Thu, 18 Jun 2020 14:36:24 +0800 Subject: [PATCH 104/208] f2fs: clean up parameter of f2fs_allocate_data_block() Use validation of @fio to inidcate whether caller want to serialize IOs in io.io_list or not, then @add_list will be redundant, remove it. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 2 +- fs/f2fs/f2fs.h | 2 +- fs/f2fs/gc.c | 2 +- fs/f2fs/segment.c | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 2649b5456f3b..6cc4d2560d18 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1366,7 +1366,7 @@ alloc: set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); old_blkaddr = dn->data_blkaddr; f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr, - &sum, seg_type, NULL, false); + &sum, seg_type, NULL); if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) invalidate_mapping_pages(META_MAPPING(sbi), old_blkaddr, old_blkaddr); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index d1d59101b6ae..9e62606c94e9 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3369,7 +3369,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn, void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, block_t old_blkaddr, block_t *new_blkaddr, struct f2fs_summary *sum, int type, - struct f2fs_io_info *fio, bool add_list); + struct f2fs_io_info *fio); void f2fs_wait_on_page_writeback(struct page *page, enum page_type type, bool ordered, bool locked); void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr); diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 8782d7c8f44a..1ac921e1109b 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -866,7 +866,7 @@ static int move_data_block(struct inode *inode, block_t bidx, } f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr, - &sum, CURSEG_COLD_DATA, NULL, false); + &sum, CURSEG_COLD_DATA, NULL); fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(fio.sbi), newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 52321382b391..5e8e5e848393 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3114,7 +3114,7 @@ static int __get_segment_type(struct f2fs_io_info *fio) void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, block_t old_blkaddr, block_t *new_blkaddr, struct f2fs_summary *sum, int type, - struct f2fs_io_info *fio, bool add_list) + struct f2fs_io_info *fio) { struct sit_info *sit_i = SIT_I(sbi); struct curseg_info *curseg = CURSEG_I(sbi, type); @@ -3182,7 +3182,7 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, if (F2FS_IO_ALIGNED(sbi)) fio->retry = false; - if (add_list) { + if (fio) { struct f2fs_bio_info *io; INIT_LIST_HEAD(&fio->list); @@ -3231,7 +3231,7 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio) down_read(&fio->sbi->io_order_lock); reallocate: f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr, - &fio->new_blkaddr, sum, type, fio, true); + &fio->new_blkaddr, sum, type, fio); if (GET_SEGNO(fio->sbi, fio->old_blkaddr) != NULL_SEGNO) invalidate_mapping_pages(META_MAPPING(fio->sbi), fio->old_blkaddr, fio->old_blkaddr); From 9fcffbf71ac11dd0f7f03ec6cf10f67080b67fd3 Mon Sep 17 00:00:00 2001 From: Qilong Zhang Date: Sun, 28 Jun 2020 19:23:03 +0800 Subject: [PATCH 105/208] f2fs: add f2fs_gc exception handle in f2fs_ioc_gc_range When f2fs_ioc_gc_range performs multiple segments gc ops, the return value of f2fs_ioc_gc_range is determined by the last segment gc ops. If its ops failed, the f2fs_ioc_gc_range will be considered to be failed despite some of previous segments gc ops succeeded. Therefore, so we fix: Redefine the return value of getting victim ops and add exception handle for f2fs_gc. In particular, 1).if target has no valid block, it will go on. 2).if target sectoion has valid block(s), but it is current section, we will reminder the caller. Signed-off-by: Qilong Zhang Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 5 +++++ fs/f2fs/gc.c | 20 ++++++++++++++------ fs/f2fs/segment.c | 4 ++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 491f5c35614b..b8ec875617a5 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2528,6 +2528,11 @@ do_more: } ret = f2fs_gc(sbi, range.sync, true, GET_SEGNO(sbi, range.start)); + if (ret) { + if (ret == -EBUSY) + ret = -EAGAIN; + goto out; + } range.start += BLKS_PER_SEC(sbi); if (range.start <= end) goto do_more; diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 1ac921e1109b..15cad446fdab 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -330,6 +330,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, unsigned int secno, last_victim; unsigned int last_segment; unsigned int nsearched = 0; + int ret = 0; mutex_lock(&dirty_i->seglist_lock); last_segment = MAIN_SECS(sbi) * sbi->segs_per_sec; @@ -341,12 +342,19 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, p.min_cost = get_max_cost(sbi, &p); if (*result != NULL_SEGNO) { - if (get_valid_blocks(sbi, *result, false) && - !sec_usage_check(sbi, GET_SEC_FROM_SEG(sbi, *result))) + if (!get_valid_blocks(sbi, *result, false)) { + ret = -ENODATA; + goto out; + } + + if (sec_usage_check(sbi, GET_SEC_FROM_SEG(sbi, *result))) + ret = -EBUSY; + else p.min_segno = *result; goto out; } + ret = -ENODATA; if (p.max_search == 0) goto out; @@ -447,6 +455,7 @@ got_result: else set_bit(secno, dirty_i->victim_secmap); } + ret = 0; } out: @@ -456,7 +465,7 @@ out: prefree_segments(sbi), free_segments(sbi)); mutex_unlock(&dirty_i->seglist_lock); - return (p.min_segno == NULL_SEGNO) ? 0 : 1; + return ret; } static const struct victim_selection default_v_ops = { @@ -1340,10 +1349,9 @@ gc_more: ret = -EINVAL; goto stop; } - if (!__get_victim(sbi, &segno, gc_type)) { - ret = -ENODATA; + ret = __get_victim(sbi, &segno, gc_type); + if (ret) goto stop; - } seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type); if (gc_type == FG_GC && seg_freed == sbi->segs_per_sec) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 5e8e5e848393..3ac4052b1c7d 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2630,7 +2630,7 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type) bool reversed = false; /* f2fs_need_SSR() already forces to do this */ - if (v_ops->get_victim(sbi, &segno, BG_GC, type, SSR)) { + if (!v_ops->get_victim(sbi, &segno, BG_GC, type, SSR)) { curseg->next_segno = segno; return 1; } @@ -2657,7 +2657,7 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type) for (; cnt-- > 0; reversed ? i-- : i++) { if (i == type) continue; - if (v_ops->get_victim(sbi, &segno, BG_GC, i, SSR)) { + if (!v_ops->get_victim(sbi, &segno, BG_GC, i, SSR)) { curseg->next_segno = segno; return 1; } From a3b3cee00298f260163efaf30fc234f59d13a89b Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Sun, 28 Jun 2020 10:58:44 +0800 Subject: [PATCH 106/208] f2fs: show more debug info for per-temperature log - Add to account and show per-log dirty_seg, full_seg and valid_blocks in debugfs. - reformat printed info. TYPE segno secno zoneno dirty_seg full_seg valid_blk - COLD data: 1523 1523 1523 1 0 399 - WARM data: 769 769 769 20 255 133098 - HOT data: 767 767 767 9 0 167 - Dir dnode: 22 22 22 3 0 70 - File dnode: 722 722 722 14 10 6505 - Indir nodes: 2 2 2 1 0 3 Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/debug.c | 64 +++++++++++++++++++++++++++++++++++++++---------- fs/f2fs/f2fs.h | 3 +++ 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 05e9ad91167e..2766abe0c300 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -174,6 +174,26 @@ static void update_general_status(struct f2fs_sb_info *sbi) for (i = META_CP; i < META_MAX; i++) si->meta_count[i] = atomic_read(&sbi->meta_count[i]); + for (i = 0; i < NO_CHECK_TYPE; i++) { + si->dirty_seg[i] = 0; + si->full_seg[i] = 0; + si->valid_blks[i] = 0; + } + + for (i = 0; i < MAIN_SEGS(sbi); i++) { + int blks = get_seg_entry(sbi, i)->valid_blocks; + int type = get_seg_entry(sbi, i)->type; + + if (!blks) + continue; + + if (blks == sbi->blocks_per_seg) + si->full_seg[type]++; + else + si->dirty_seg[type]++; + si->valid_blks[type] += blks; + } + for (i = 0; i < 2; i++) { si->segment_count[i] = sbi->segment_count[i]; si->block_count[i] = sbi->block_count[i]; @@ -329,30 +349,50 @@ static int stat_show(struct seq_file *s, void *v) seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", si->main_area_segs, si->main_area_sections, si->main_area_zones); - seq_printf(s, " - COLD data: %d, %d, %d\n", + seq_printf(s, " TYPE %8s %8s %8s %10s %10s %10s\n", + "segno", "secno", "zoneno", "dirty_seg", "full_seg", "valid_blk"); + seq_printf(s, " - COLD data: %8d %8d %8d %10u %10u %10u\n", si->curseg[CURSEG_COLD_DATA], si->cursec[CURSEG_COLD_DATA], - si->curzone[CURSEG_COLD_DATA]); - seq_printf(s, " - WARM data: %d, %d, %d\n", + si->curzone[CURSEG_COLD_DATA], + si->dirty_seg[CURSEG_COLD_DATA], + si->full_seg[CURSEG_COLD_DATA], + si->valid_blks[CURSEG_COLD_DATA]); + seq_printf(s, " - WARM data: %8d %8d %8d %10u %10u %10u\n", si->curseg[CURSEG_WARM_DATA], si->cursec[CURSEG_WARM_DATA], - si->curzone[CURSEG_WARM_DATA]); - seq_printf(s, " - HOT data: %d, %d, %d\n", + si->curzone[CURSEG_WARM_DATA], + si->dirty_seg[CURSEG_WARM_DATA], + si->full_seg[CURSEG_WARM_DATA], + si->valid_blks[CURSEG_WARM_DATA]); + seq_printf(s, " - HOT data: %8d %8d %8d %10u %10u %10u\n", si->curseg[CURSEG_HOT_DATA], si->cursec[CURSEG_HOT_DATA], - si->curzone[CURSEG_HOT_DATA]); - seq_printf(s, " - Dir dnode: %d, %d, %d\n", + si->curzone[CURSEG_HOT_DATA], + si->dirty_seg[CURSEG_HOT_DATA], + si->full_seg[CURSEG_HOT_DATA], + si->valid_blks[CURSEG_HOT_DATA]); + seq_printf(s, " - Dir dnode: %8d %8d %8d %10u %10u %10u\n", si->curseg[CURSEG_HOT_NODE], si->cursec[CURSEG_HOT_NODE], - si->curzone[CURSEG_HOT_NODE]); - seq_printf(s, " - File dnode: %d, %d, %d\n", + si->curzone[CURSEG_HOT_NODE], + si->dirty_seg[CURSEG_HOT_NODE], + si->full_seg[CURSEG_HOT_NODE], + si->valid_blks[CURSEG_HOT_NODE]); + seq_printf(s, " - File dnode: %8d %8d %8d %10u %10u %10u\n", si->curseg[CURSEG_WARM_NODE], si->cursec[CURSEG_WARM_NODE], - si->curzone[CURSEG_WARM_NODE]); - seq_printf(s, " - Indir nodes: %d, %d, %d\n", + si->curzone[CURSEG_WARM_NODE], + si->dirty_seg[CURSEG_WARM_NODE], + si->full_seg[CURSEG_WARM_NODE], + si->valid_blks[CURSEG_WARM_NODE]); + seq_printf(s, " - Indir nodes: %8d %8d %8d %10u %10u %10u\n", si->curseg[CURSEG_COLD_NODE], si->cursec[CURSEG_COLD_NODE], - si->curzone[CURSEG_COLD_NODE]); + si->curzone[CURSEG_COLD_NODE], + si->dirty_seg[CURSEG_COLD_NODE], + si->full_seg[CURSEG_COLD_NODE], + si->valid_blks[CURSEG_COLD_NODE]); seq_printf(s, "\n - Valid: %d\n - Dirty: %d\n", si->main_area_segs - si->dirty_count - si->prefree_count - si->free_segs, diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 9e62606c94e9..b85411a04c77 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3556,6 +3556,9 @@ struct f2fs_stat_info { int curseg[NR_CURSEG_TYPE]; int cursec[NR_CURSEG_TYPE]; int curzone[NR_CURSEG_TYPE]; + unsigned int dirty_seg[NR_CURSEG_TYPE]; + unsigned int full_seg[NR_CURSEG_TYPE]; + unsigned int valid_blks[NR_CURSEG_TYPE]; unsigned int meta_count[META_MAX]; unsigned int segment_count[2]; From 732b32030a5b6c4664a5ed22d08fc081a474341e Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Sun, 28 Jun 2020 10:58:17 +0800 Subject: [PATCH 107/208] f2fs: fix to wait page writeback before update Filesystem including f2fs should support stable page for special device like software raid, however there is one missing path that page could be updated while it is writeback state as below, fix this. - gc_node_segment - f2fs_move_node_page - __write_node_page - set_page_writeback - do_read_inode - f2fs_init_extent_tree - __f2fs_init_extent_tree i_ext->len = 0; Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/extent_cache.c | 18 +++++++++--------- fs/f2fs/f2fs.h | 2 +- fs/f2fs/inode.c | 3 +-- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index e60078460ad1..686c68b98610 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -325,9 +325,10 @@ static void __drop_largest_extent(struct extent_tree *et, } /* return true, if inode page is changed */ -static bool __f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext) +static void __f2fs_init_extent_tree(struct inode *inode, struct page *ipage) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_extent *i_ext = ipage ? &F2FS_INODE(ipage)->i_ext : NULL; struct extent_tree *et; struct extent_node *en; struct extent_info ei; @@ -335,16 +336,18 @@ static bool __f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_e if (!f2fs_may_extent_tree(inode)) { /* drop largest extent */ if (i_ext && i_ext->len) { + f2fs_wait_on_page_writeback(ipage, NODE, true, true); i_ext->len = 0; - return true; + set_page_dirty(ipage); + return; } - return false; + return; } et = __grab_extent_tree(inode); if (!i_ext || !i_ext->len) - return false; + return; get_extent_info(&ei, i_ext); @@ -360,17 +363,14 @@ static bool __f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_e } out: write_unlock(&et->lock); - return false; } -bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext) +void f2fs_init_extent_tree(struct inode *inode, struct page *ipage) { - bool ret = __f2fs_init_extent_tree(inode, i_ext); + __f2fs_init_extent_tree(inode, ipage); if (!F2FS_I(inode)->extent_tree) set_inode_flag(inode, FI_NO_EXTENT); - - return ret; } static bool f2fs_lookup_extent_tree(struct inode *inode, pgoff_t pgofs, diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index b85411a04c77..3d8a055970a8 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3818,7 +3818,7 @@ struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root, bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi, struct rb_root_cached *root); unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink); -bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext); +void f2fs_init_extent_tree(struct inode *inode, struct page *ipage); void f2fs_drop_extent_tree(struct inode *inode); unsigned int f2fs_destroy_extent_node(struct inode *inode); void f2fs_destroy_extent_tree(struct inode *inode); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 0df5c8ca3e5a..1a44b43518c8 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -367,8 +367,7 @@ static int do_read_inode(struct inode *inode) fi->i_pino = le32_to_cpu(ri->i_pino); fi->i_dir_level = ri->i_dir_level; - if (f2fs_init_extent_tree(inode, &ri->i_ext)) - set_page_dirty(node_page); + f2fs_init_extent_tree(inode, node_page); get_inline_info(inode, ri); From 940ef5830998dce00f926107ab524316fe2c59f1 Mon Sep 17 00:00:00 2001 From: Liu Song Date: Thu, 25 Jun 2020 20:40:11 +0800 Subject: [PATCH 108/208] f2fs: fix typo in comment of f2fs_do_add_link stakable/stackable Signed-off-by: Liu Song Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index a02ffa06d9df..d559016668ab 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -779,7 +779,7 @@ int f2fs_do_add_link(struct inode *dir, const struct qstr *name, return err; /* - * An immature stakable filesystem shows a race condition between lookup + * An immature stackable filesystem shows a race condition between lookup * and create. If we have same task when doing lookup and create, it's * definitely fine as expected by VFS normally. Otherwise, let's just * verify on-disk dentry one more time, which guarantees filesystem From 2a4c1fc6d70e8966b17facc420808155d38f2f9d Mon Sep 17 00:00:00 2001 From: Liu Song Date: Sun, 28 Jun 2020 21:48:13 +0800 Subject: [PATCH 109/208] f2fs: remove useless parameter of __insert_free_nid() In current version, @state will only be FREE_NID. This parameter has no real effect so remove it to keep clean. Signed-off-by: Liu Song Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/node.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index d0f5f3de714e..1bf2d0dfe033 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -2108,7 +2108,7 @@ static struct free_nid *__lookup_free_nid_list(struct f2fs_nm_info *nm_i, } static int __insert_free_nid(struct f2fs_sb_info *sbi, - struct free_nid *i, enum nid_state state) + struct free_nid *i) { struct f2fs_nm_info *nm_i = NM_I(sbi); @@ -2116,10 +2116,8 @@ static int __insert_free_nid(struct f2fs_sb_info *sbi, if (err) return err; - f2fs_bug_on(sbi, state != i->state); - nm_i->nid_cnt[state]++; - if (state == FREE_NID) - list_add_tail(&i->list, &nm_i->free_nid_list); + nm_i->nid_cnt[FREE_NID]++; + list_add_tail(&i->list, &nm_i->free_nid_list); return 0; } @@ -2241,7 +2239,7 @@ static bool add_free_nid(struct f2fs_sb_info *sbi, } } ret = true; - err = __insert_free_nid(sbi, i, FREE_NID); + err = __insert_free_nid(sbi, i); err_out: if (update) { update_free_nid_bitmap(sbi, nid, ret, build); From 31198c9f566d636516e3b325c10ca5507521daa2 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Sun, 28 Jun 2020 20:29:38 +0800 Subject: [PATCH 110/208] f2fs: fix wrong return value of f2fs_bmap_compress() If compression is disable, we should return zero rather than -EOPNOTSUPP to indicate f2fs_bmap() is not supported. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 6cc4d2560d18..fa7411eb3a77 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3713,10 +3713,9 @@ static sector_t f2fs_bmap_compress(struct inode *inode, sector_t block) } f2fs_put_dnode(&dn); - return blknr; #else - return -EOPNOTSUPP; + return 0; #endif } From 0eeebc9bf2731ff774b22db46064b4d0c710e00b Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 29 Jun 2020 20:13:12 +0800 Subject: [PATCH 111/208] f2fs: support to trace f2fs_bmap() to show f2fs_bmap()'s result as below: f2fs_bmap: dev = (251,0), ino = 7, lblock:0, pblock:396800 Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 14 +++++++++++--- include/trace/events/f2fs.h | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index fa7411eb3a77..73657750f989 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3723,18 +3723,26 @@ static sector_t f2fs_bmap_compress(struct inode *inode, sector_t block) static sector_t f2fs_bmap(struct address_space *mapping, sector_t block) { struct inode *inode = mapping->host; + struct buffer_head tmp = { + .b_size = i_blocksize(inode), + }; + sector_t blknr = 0; if (f2fs_has_inline_data(inode)) - return 0; + goto out; /* make sure allocating whole blocks */ if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) filemap_write_and_wait(mapping); if (f2fs_compressed_file(inode)) - return f2fs_bmap_compress(inode, block); + blknr = f2fs_bmap_compress(inode, block); - return generic_block_bmap(mapping, block, get_data_block_bmap); + if (!get_data_block_bmap(inode, block, &tmp, 0)) + blknr = tmp.b_blocknr; +out: + trace_f2fs_bmap(inode, block, blknr); + return blknr; } #ifdef CONFIG_MIGRATION diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index e6e695510ad1..570c1827ee32 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -1900,6 +1900,32 @@ TRACE_EVENT(f2fs_iostat, __entry->fs_cdrio, __entry->fs_nrio, __entry->fs_mrio) ); +TRACE_EVENT(f2fs_bmap, + + TP_PROTO(struct inode *inode, sector_t lblock, sector_t pblock), + + TP_ARGS(inode, lblock, pblock), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(sector_t, lblock) + __field(sector_t, pblock) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->lblock = lblock; + __entry->pblock = pblock; + ), + + TP_printk("dev = (%d,%d), ino = %lu, lblock:%lld, pblock:%lld", + show_dev_ino(__entry), + (unsigned long long)__entry->lblock, + (unsigned long long)__entry->pblock) +); + #endif /* _TRACE_F2FS_H */ /* This part must be outside protection */ From fad5080592affb279e60b3501068d4392b097fb7 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 29 Jun 2020 20:13:13 +0800 Subject: [PATCH 112/208] f2fs: support to trace f2fs_fiemap() to show f2fs_fiemap()'s result as below: f2fs_fiemap: dev = (251,0), ino = 7, lblock:0, pblock:1625292800, len:2097152, flags:0, ret:0 Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 6 +++++- fs/f2fs/inline.c | 2 ++ include/trace/events/f2fs.h | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 73657750f989..7bd77c627aac 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1813,6 +1813,7 @@ static int f2fs_xattr_fiemap(struct inode *inode, flags |= FIEMAP_EXTENT_LAST; err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); + trace_f2fs_fiemap(inode, 0, phys, len, flags, err); if (err || err == 1) return err; } @@ -1836,8 +1837,10 @@ static int f2fs_xattr_fiemap(struct inode *inode, flags = FIEMAP_EXTENT_LAST; } - if (phys) + if (phys) { err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); + trace_f2fs_fiemap(inode, 0, phys, len, flags, err); + } return (err < 0 ? err : 0); } @@ -1931,6 +1934,7 @@ next: ret = fiemap_fill_next_extent(fieinfo, logical, phys, size, flags); + trace_f2fs_fiemap(inode, logical, phys, size, flags, ret); if (ret) goto out; size = 0; diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 6e497598c069..652b972dfd7b 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -11,6 +11,7 @@ #include "f2fs.h" #include "node.h" +#include bool f2fs_may_inline_data(struct inode *inode) { @@ -775,6 +776,7 @@ int f2fs_inline_data_fiemap(struct inode *inode, byteaddr += (char *)inline_data_addr(inode, ipage) - (char *)F2FS_INODE(ipage); err = fiemap_fill_next_extent(fieinfo, start, byteaddr, ilen, flags); + trace_f2fs_fiemap(inode, start, byteaddr, ilen, flags, err); out: f2fs_put_page(ipage, 1); return err; diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index 570c1827ee32..482e5785bba6 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -1926,6 +1926,43 @@ TRACE_EVENT(f2fs_bmap, (unsigned long long)__entry->pblock) ); +TRACE_EVENT(f2fs_fiemap, + + TP_PROTO(struct inode *inode, sector_t lblock, sector_t pblock, + unsigned long long len, unsigned int flags, int ret), + + TP_ARGS(inode, lblock, pblock, len, flags, ret), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(sector_t, lblock) + __field(sector_t, pblock) + __field(unsigned long long, len) + __field(unsigned int, flags) + __field(int, ret) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->lblock = lblock; + __entry->pblock = pblock; + __entry->len = len; + __entry->flags = flags; + __entry->ret = ret; + ), + + TP_printk("dev = (%d,%d), ino = %lu, lblock:%lld, pblock:%lld, " + "len:%llu, flags:%u, ret:%d", + show_dev_ino(__entry), + (unsigned long long)__entry->lblock, + (unsigned long long)__entry->pblock, + __entry->len, + __entry->flags, + __entry->ret) +); + #endif /* _TRACE_F2FS_H */ /* This part must be outside protection */ From 00f1c21109d111cdad78ea6f9952439bca2cc6b3 Mon Sep 17 00:00:00 2001 From: Wang Xiaojun Date: Tue, 16 Jun 2020 10:39:24 +0800 Subject: [PATCH 113/208] f2fs: remove the unused compr parameter The parameter compr is unused in the f2fs_cluster_blocks function so we no longer need to pass it as a parameter. Signed-off-by: Wang Xiaojun Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index a15c0fea032e..df92c4917dab 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -797,7 +797,7 @@ static int f2fs_compressed_blocks(struct compress_ctx *cc) } /* return # of valid blocks in compressed cluster */ -static int f2fs_cluster_blocks(struct compress_ctx *cc, bool compr) +static int f2fs_cluster_blocks(struct compress_ctx *cc) { return __f2fs_cluster_blocks(cc, false); } @@ -811,7 +811,7 @@ int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index) .cluster_idx = index >> F2FS_I(inode)->i_log_cluster_size, }; - return f2fs_cluster_blocks(&cc, false); + return f2fs_cluster_blocks(&cc); } static bool cluster_may_compress(struct compress_ctx *cc) @@ -862,7 +862,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc, bool prealloc; retry: - ret = f2fs_cluster_blocks(cc, false); + ret = f2fs_cluster_blocks(cc); if (ret <= 0) return ret; From bebf8350e1817dbbca5954455587c7b4b6d2050f Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Fri, 19 Jun 2020 17:14:19 +0800 Subject: [PATCH 114/208] f2fs: fix to check page dirty status before writeback In f2fs_write_raw_pages(), we need to check page dirty status before writeback, because there could be a racer (e.g. reclaimer) helps writebacking the dirty page. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index df92c4917dab..5133908974c9 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -1298,6 +1298,12 @@ retry_write: congestion_wait(BLK_RW_ASYNC, DEFAULT_IO_TIMEOUT); lock_page(cc->rpages[i]); + + if (!PageDirty(cc->rpages[i])) { + unlock_page(cc->rpages[i]); + continue; + } + clear_page_dirty_for_io(cc->rpages[i]); goto retry_write; } From f544a8a1810c9270e55f9a13841cca0f5da8c778 Mon Sep 17 00:00:00 2001 From: Lihong Kou Date: Sat, 20 Jun 2020 10:12:17 +0800 Subject: [PATCH 115/208] f2fs: make trace enter and end in pairs for unlink In the f2fs_unlink we do not add trace end for some error paths, just add. Signed-off-by: Lihong Kou Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/namei.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 24ce17cb6c95..fe22a2cfe54f 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -570,15 +570,17 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) trace_f2fs_unlink_enter(dir, dentry); - if (unlikely(f2fs_cp_error(sbi))) - return -EIO; + if (unlikely(f2fs_cp_error(sbi))) { + err = -EIO; + goto fail; + } err = dquot_initialize(dir); if (err) - return err; + goto fail; err = dquot_initialize(inode); if (err) - return err; + goto fail; de = f2fs_find_entry(dir, &dentry->d_name, &page); if (!de) { From 20ba6f3bbded4c45955752c9dd8383436f2258e6 Mon Sep 17 00:00:00 2001 From: Yu Changchun Date: Sat, 20 Jun 2020 03:58:29 -0400 Subject: [PATCH 116/208] f2fs: fix an oops in f2fs_is_compressed_page This patch is to fix a crash: #3 [ffffb6580689f898] oops_end at ffffffffa2835bc2 #4 [ffffb6580689f8b8] no_context at ffffffffa28766e7 #5 [ffffb6580689f920] async_page_fault at ffffffffa320135e [exception RIP: f2fs_is_compressed_page+34] RIP: ffffffffa2ba83a2 RSP: ffffb6580689f9d8 RFLAGS: 00010213 RAX: 0000000000000001 RBX: fffffc0f50b34bc0 RCX: 0000000000002122 RDX: 0000000000002123 RSI: 0000000000000c00 RDI: fffffc0f50b34bc0 RBP: ffff97e815a40178 R8: 0000000000000000 R9: ffff97e83ffc9000 R10: 0000000000032300 R11: 0000000000032380 R12: ffffb6580689fa38 R13: fffffc0f50b34bc0 R14: ffff97e825cbd000 R15: 0000000000000c00 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #6 [ffffb6580689f9d8] __is_cp_guaranteed at ffffffffa2b7ea98 #7 [ffffb6580689f9f0] f2fs_submit_page_write at ffffffffa2b81a69 #8 [ffffb6580689fa30] f2fs_do_write_meta_page at ffffffffa2b99777 #9 [ffffb6580689fae0] __f2fs_write_meta_page at ffffffffa2b75f1a #10 [ffffb6580689fb18] f2fs_sync_meta_pages at ffffffffa2b77466 #11 [ffffb6580689fc98] do_checkpoint at ffffffffa2b78e46 #12 [ffffb6580689fd88] f2fs_write_checkpoint at ffffffffa2b79c29 #13 [ffffb6580689fdd0] f2fs_sync_fs at ffffffffa2b69d95 #14 [ffffb6580689fe20] sync_filesystem at ffffffffa2ad2574 #15 [ffffb6580689fe30] generic_shutdown_super at ffffffffa2a9b582 #16 [ffffb6580689fe48] kill_block_super at ffffffffa2a9b6d1 #17 [ffffb6580689fe60] kill_f2fs_super at ffffffffa2b6abe1 #18 [ffffb6580689fea0] deactivate_locked_super at ffffffffa2a9afb6 #19 [ffffb6580689feb8] cleanup_mnt at ffffffffa2abcad4 #20 [ffffb6580689fee0] task_work_run at ffffffffa28bca28 #21 [ffffb6580689ff00] exit_to_usermode_loop at ffffffffa28050b7 #22 [ffffb6580689ff38] do_syscall_64 at ffffffffa280560e #23 [ffffb6580689ff50] entry_SYSCALL_64_after_hwframe at ffffffffa320008c This occurred when umount f2fs if enable F2FS_FS_COMPRESSION with F2FS_IO_TRACE. Fixes it by adding IS_IO_TRACED_PAGE to check validity of pid for page_private. Signed-off-by: Yu Changchun Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 7 +++++++ fs/f2fs/f2fs.h | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 5133908974c9..f1f39a49afd3 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -55,6 +55,13 @@ bool f2fs_is_compressed_page(struct page *page) return false; if (IS_ATOMIC_WRITTEN_PAGE(page) || IS_DUMMY_WRITTEN_PAGE(page)) return false; + /* + * page->private may be set with pid. + * pid_max is enough to check if it is traced. + */ + if (IS_IO_TRACED_PAGE(page)) + return false; + f2fs_bug_on(F2FS_M_SB(page->mapping), *((u32 *)page_private(page)) != F2FS_COMPRESSED_PAGE_MAGIC); return true; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 3d8a055970a8..d55d36d37ef6 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1325,6 +1325,14 @@ enum fsync_mode { #define IS_DUMMY_WRITTEN_PAGE(page) \ (page_private(page) == (unsigned long)DUMMY_WRITTEN_PAGE) +#ifdef CONFIG_F2FS_IO_TRACE +#define IS_IO_TRACED_PAGE(page) \ + (page_private(page) > 0 && \ + page_private(page) < (unsigned long)PID_MAX_LIMIT) +#else +#define IS_IO_TRACED_PAGE(page) (0) +#endif + #ifdef CONFIG_FS_ENCRYPTION #define DUMMY_ENCRYPTION_ENABLED(sbi) \ (unlikely(F2FS_OPTION(sbi).dummy_enc_ctx.ctx != NULL)) From 528d8d79f7aa10696e0b020f9db04b1c12a49d83 Mon Sep 17 00:00:00 2001 From: Yubo Feng Date: Sat, 20 Jun 2020 16:39:43 +0800 Subject: [PATCH 117/208] f2fs: lost matching-pair of trace in f2fs_truncate_inode_blocks if get_node_path() return -E2BIG and trace of f2fs_truncate_inode_blocks_enter/exit enabled then the matching-pair of trace_exit will lost in log. Signed-off-by: Yubo Feng Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/node.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 1bf2d0dfe033..4e6486bf8360 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1039,8 +1039,10 @@ int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from) trace_f2fs_truncate_inode_blocks_enter(inode, from); level = get_node_path(inode, from, offset, noffset); - if (level < 0) + if (level < 0) { + trace_f2fs_truncate_inode_blocks_exit(inode, level); return level; + } page = f2fs_get_node_page(sbi, inode->i_ino); if (IS_ERR(page)) { From 263968a2d77a14507a82e63b70dd385e2bc03cd8 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 27 Nov 2017 23:47:34 +0100 Subject: [PATCH 118/208] scsi: scsi_devinfo: handle non-terminated strings commit ba69ead9e9e9bb3cec5faf03526c36764ac8942a upstream. devinfo->vendor and devinfo->model aren't necessarily zero-terminated. Fixes: b8018b973c7c "scsi_devinfo: fixup string compare" Signed-off-by: Martin Wilck Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen Cc: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_devinfo.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 9654898f3e51..6748e82c6352 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -449,7 +449,8 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor, /* * vendor strings must be an exact match */ - if (vmax != strlen(devinfo->vendor) || + if (vmax != strnlen(devinfo->vendor, + sizeof(devinfo->vendor)) || memcmp(devinfo->vendor, vskip, vmax)) continue; @@ -457,7 +458,7 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor, * @model specifies the full string, and * must be larger or equal to devinfo->model */ - mlen = strlen(devinfo->model); + mlen = strnlen(devinfo->model, sizeof(devinfo->model)); if (mmax < mlen || memcmp(devinfo->model, mskip, mlen)) continue; return devinfo; From bfbaf151efe491e30697e21c8b7ae1b615480873 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 28 May 2020 14:57:47 -0700 Subject: [PATCH 119/208] net: be more gentle about silly gso requests coming from user commit 7c6d2ecbda83150b2036a2b36b21381ad4667762 upstream. Recent change in virtio_net_hdr_to_skb() broke some packetdrill tests. When --mss=XXX option is set, packetdrill always provide gso_type & gso_size for its inbound packets, regardless of packet size. if (packet->tcp && packet->mss) { if (packet->ipv4) gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; else gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; gso.gso_size = packet->mss; } Since many other programs could do the same, relax virtio_net_hdr_to_skb() to no longer return an error, but instead ignore gso settings. This keeps Willem intent to make sure no malicious packet could reach gso stack. Note that TCP stack has a special logic in tcp_set_skb_tso_segs() to clear gso_size for small packets. Fixes: 6dd912f82680 ("net: check untrusted gso_size at kernel entry") Signed-off-by: Eric Dumazet Cc: Willem de Bruijn Acked-by: Willem de Bruijn Signed-off-by: David S. Miller Cc: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- include/linux/virtio_net.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index a16e0bdf7751..d19bfdcf7749 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -107,16 +107,17 @@ retry: if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size); + struct skb_shared_info *shinfo = skb_shinfo(skb); - if (skb->len - p_off <= gso_size) - return -EINVAL; + /* Too small packets are not really GSO ones. */ + if (skb->len - p_off > gso_size) { + shinfo->gso_size = gso_size; + shinfo->gso_type = gso_type; - skb_shinfo(skb)->gso_size = gso_size; - skb_shinfo(skb)->gso_type = gso_type; - - /* Header must be checked, and gso_segs computed. */ - skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; - skb_shinfo(skb)->gso_segs = 0; + /* Header must be checked, and gso_segs computed. */ + shinfo->gso_type |= SKB_GSO_DODGY; + shinfo->gso_segs = 0; + } } return 0; From a32228290d89ddabd4bb2cb2dbcb596a13ae0569 Mon Sep 17 00:00:00 2001 From: yu kuai Date: Mon, 1 Jun 2020 20:38:56 +0800 Subject: [PATCH 120/208] block/bio-integrity: don't free 'buf' if bio_integrity_add_page() failed commit a75ca9303175d36af93c0937dd9b1a6422908b8d upstream. commit e7bf90e5afe3 ("block/bio-integrity: fix a memory leak bug") added a kfree() for 'buf' if bio_integrity_add_page() returns '0'. However, the object will be freed in bio_integrity_free() since 'bio->bi_opf' and 'bio->bi_integrity' were set previousy in bio_integrity_alloc(). Fixes: commit e7bf90e5afe3 ("block/bio-integrity: fix a memory leak bug") Signed-off-by: yu kuai Reviewed-by: Ming Lei Reviewed-by: Bob Liu Acked-by: Martin K. Petersen Signed-off-by: Jens Axboe Cc: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- block/bio-integrity.c | 1 - 1 file changed, 1 deletion(-) diff --git a/block/bio-integrity.c b/block/bio-integrity.c index 7f8010662437..d3df44c3b43a 100644 --- a/block/bio-integrity.c +++ b/block/bio-integrity.c @@ -315,7 +315,6 @@ bool bio_integrity_prep(struct bio *bio) if (ret == 0) { printk(KERN_ERR "could not attach integrity payload\n"); - kfree(buf); status = BLK_STS_RESOURCE; goto err_end_io; } From 1aa52fb6780dc8e0396405612d1c9d505810bd2d Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Tue, 9 Jun 2020 22:11:54 +0200 Subject: [PATCH 121/208] net: sched: export __netdev_watchdog_up() [ Upstream commit 1a3db27ad9a72d033235b9673653962c02e3486e ] Since the quiesce/activate rework, __netdev_watchdog_up() is directly called in the ucc_geth driver. Unfortunately, this function is not available for modules and thus ucc_geth cannot be built as a module anymore. Fix it by exporting __netdev_watchdog_up(). Since the commit introducing the regression was backported to stable branches, this one should ideally be as well. Fixes: 79dde73cf9bc ("net/ethernet/freescale: rework quiesce/activate for ucc_geth") Signed-off-by: Valentin Longchamp Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- net/sched/sch_generic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 21b981abbacb..091a9746627f 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -341,6 +341,7 @@ void __netdev_watchdog_up(struct net_device *dev) dev_hold(dev); } } +EXPORT_SYMBOL_GPL(__netdev_watchdog_up); static void dev_watchdog_up(struct net_device *dev) { From 1180e365f0990dbc83eed1e64041fff614cb3d70 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 6 Jun 2020 23:44:24 -0400 Subject: [PATCH 122/208] fix a braino in "sparc32: fix register window handling in genregs32_[gs]et()" [ Upstream commit 9d964e1b82d8182184153b70174f445ea616f053 ] lost npc in PTRACE_SETREGSET, breaking PTRACE_SETREGS as well Fixes: cf51e129b968 "sparc32: fix register window handling in genregs32_[gs]et()" Signed-off-by: Al Viro Signed-off-by: Sasha Levin --- arch/sparc/kernel/ptrace_32.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/ptrace_32.c b/arch/sparc/kernel/ptrace_32.c index 60f7205ebe40..646dd58169ec 100644 --- a/arch/sparc/kernel/ptrace_32.c +++ b/arch/sparc/kernel/ptrace_32.c @@ -168,12 +168,17 @@ static int genregs32_set(struct task_struct *target, if (ret || !count) return ret; ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - ®s->y, + ®s->npc, 34 * sizeof(u32), 35 * sizeof(u32)); if (ret || !count) return ret; + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + ®s->y, + 35 * sizeof(u32), 36 * sizeof(u32)); + if (ret || !count) + return ret; return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, - 35 * sizeof(u32), 38 * sizeof(u32)); + 36 * sizeof(u32), 38 * sizeof(u32)); } static int fpregs32_get(struct task_struct *target, From ecf8e185a29ab1d71ad5a4f22ddc84bdce6cb5ed Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Sat, 29 Sep 2018 03:49:26 +0200 Subject: [PATCH 123/208] apparmor: don't try to replace stale label in ptraceme check [ Upstream commit ca3fde5214e1d24f78269b337d3f22afd6bf445e ] begin_current_label_crit_section() must run in sleepable context because when label_is_stale() is true, aa_replace_current_label() runs, which uses prepare_creds(), which can sleep. Until now, the ptraceme access check (which runs with tasklist_lock held) violated this rule. Fixes: b2d09ae449ced ("apparmor: move ptrace checks to using labels") Reported-by: Cyrill Gorcunov Reported-by: kernel test robot Signed-off-by: Jann Horn Signed-off-by: John Johansen Signed-off-by: Sasha Levin --- security/apparmor/lsm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 4f08023101f3..1c6b389ad8f9 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -123,11 +123,11 @@ static int apparmor_ptrace_traceme(struct task_struct *parent) struct aa_label *tracer, *tracee; int error; - tracee = begin_current_label_crit_section(); + tracee = __begin_current_label_crit_section(); tracer = aa_get_task_label(parent); error = aa_may_ptrace(tracer, tracee, AA_PTRACE_TRACE); aa_put_label(tracer); - end_current_label_crit_section(tracee); + __end_current_label_crit_section(tracee); return error; } From b5025305521a43684f2b12ead8e8aaaceafd819c Mon Sep 17 00:00:00 2001 From: Thomas Falcon Date: Thu, 18 Jun 2020 10:43:46 -0500 Subject: [PATCH 124/208] ibmveth: Fix max MTU limit [ Upstream commit 5948378b26d89f8aa5eac37629dbd0616ce8d7a7 ] The max MTU limit defined for ibmveth is not accounting for virtual ethernet buffer overhead, which is twenty-two additional bytes set aside for the ethernet header and eight additional bytes of an opaque handle reserved for use by the hypervisor. Update the max MTU to reflect this overhead. Fixes: d894be57ca92 ("ethernet: use net core MTU range checking in more drivers") Fixes: 110447f8269a ("ethernet: fix min/max MTU typos") Signed-off-by: Thomas Falcon Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/ibm/ibmveth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 880d925438c1..b43aebfc7f5b 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -1695,7 +1695,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) } netdev->min_mtu = IBMVETH_MIN_MTU; - netdev->max_mtu = ETH_MAX_MTU; + netdev->max_mtu = ETH_MAX_MTU - IBMVETH_BUFF_OH; memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN); From c24d430285c5e668e9688d3e2c7c990aea8ea61f Mon Sep 17 00:00:00 2001 From: Wang Hai Date: Thu, 11 Jun 2020 15:57:50 +0800 Subject: [PATCH 125/208] mld: fix memory leak in ipv6_mc_destroy_dev() [ Upstream commit ea2fce88d2fd678ed9d45354ff49b73f1d5615dd ] Commit a84d01647989 ("mld: fix memory leak in mld_del_delrec()") fixed the memory leak of MLD, but missing the ipv6_mc_destroy_dev() path, in which mca_sources are leaked after ma_put(). Using ip6_mc_clear_src() to take care of the missing free. BUG: memory leak unreferenced object 0xffff8881113d3180 (size 64): comm "syz-executor071", pid 389, jiffies 4294887985 (age 17.943s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 ff 02 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 ................ backtrace: [<000000002cbc483c>] kmalloc include/linux/slab.h:555 [inline] [<000000002cbc483c>] kzalloc include/linux/slab.h:669 [inline] [<000000002cbc483c>] ip6_mc_add1_src net/ipv6/mcast.c:2237 [inline] [<000000002cbc483c>] ip6_mc_add_src+0x7f5/0xbb0 net/ipv6/mcast.c:2357 [<0000000058b8b1ff>] ip6_mc_source+0xe0c/0x1530 net/ipv6/mcast.c:449 [<000000000bfc4fb5>] do_ipv6_setsockopt.isra.12+0x1b2c/0x3b30 net/ipv6/ipv6_sockglue.c:754 [<00000000e4e7a722>] ipv6_setsockopt+0xda/0x150 net/ipv6/ipv6_sockglue.c:950 [<0000000029260d9a>] rawv6_setsockopt+0x45/0x100 net/ipv6/raw.c:1081 [<000000005c1b46f9>] __sys_setsockopt+0x131/0x210 net/socket.c:2132 [<000000008491f7db>] __do_sys_setsockopt net/socket.c:2148 [inline] [<000000008491f7db>] __se_sys_setsockopt net/socket.c:2145 [inline] [<000000008491f7db>] __x64_sys_setsockopt+0xba/0x150 net/socket.c:2145 [<00000000c7bc11c5>] do_syscall_64+0xa1/0x530 arch/x86/entry/common.c:295 [<000000005fb7a3f3>] entry_SYSCALL_64_after_hwframe+0x49/0xb3 Fixes: 1666d49e1d41 ("mld: do not remove mld souce list info when set link down") Reported-by: Hulk Robot Signed-off-by: Wang Hai Acked-by: Hangbin Liu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/mcast.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 611dc5d55fa0..959057515fc9 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -2599,6 +2599,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev) idev->mc_list = i->next; write_unlock_bh(&idev->lock); + ip6_mc_clear_src(i); ma_put(i); write_lock_bh(&idev->lock); } From bc0feec2bc26f09d263fa20e22dccbe569cacf58 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Thu, 25 Jun 2020 14:26:03 +0200 Subject: [PATCH 126/208] net: bridge: enfore alignment for ethernet address [ Upstream commit db7202dec92e6caa2706c21d6fc359af318bde2e ] The eth_addr member is passed to ether_addr functions that require 2-byte alignment, therefore the member must be properly aligned to avoid unaligned accesses. The problem is in place since the initial merge of multicast to unicast: commit 6db6f0eae6052b70885562e1733896647ec1d807 bridge: multicast to unicast Fixes: 6db6f0eae605 ("bridge: multicast to unicast") Cc: Roopa Prabhu Cc: Nikolay Aleksandrov Cc: David S. Miller Cc: Jakub Kicinski Cc: Felix Fietkau Cc: stable@vger.kernel.org Signed-off-by: Thomas Martitz Acked-by: Nikolay Aleksandrov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bridge/br_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index e870cfc85b14..14ff034e561c 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -190,8 +190,8 @@ struct net_bridge_port_group { struct rcu_head rcu; struct timer_list timer; struct br_ip addr; + unsigned char eth_addr[ETH_ALEN] __aligned(2); unsigned char flags; - unsigned char eth_addr[ETH_ALEN]; }; struct net_bridge_mdb_entry From b8dabb9635a09071b589c83062340ebf179a3dc0 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 16 Jun 2020 09:39:21 +0000 Subject: [PATCH 127/208] net: fix memleak in register_netdevice() [ Upstream commit 814152a89ed52c722ab92e9fbabcac3cb8a39245 ] I got a memleak report when doing some fuzz test: unreferenced object 0xffff888112584000 (size 13599): comm "ip", pid 3048, jiffies 4294911734 (age 343.491s) hex dump (first 32 bytes): 74 61 70 30 00 00 00 00 00 00 00 00 00 00 00 00 tap0............ 00 ee d9 19 81 88 ff ff 00 00 00 00 00 00 00 00 ................ backtrace: [<000000002f60ba65>] __kmalloc_node+0x309/0x3a0 [<0000000075b211ec>] kvmalloc_node+0x7f/0xc0 [<00000000d3a97396>] alloc_netdev_mqs+0x76/0xfc0 [<00000000609c3655>] __tun_chr_ioctl+0x1456/0x3d70 [<000000001127ca24>] ksys_ioctl+0xe5/0x130 [<00000000b7d5e66a>] __x64_sys_ioctl+0x6f/0xb0 [<00000000e1023498>] do_syscall_64+0x56/0xa0 [<000000009ec0eb12>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 unreferenced object 0xffff888111845cc0 (size 8): comm "ip", pid 3048, jiffies 4294911734 (age 343.491s) hex dump (first 8 bytes): 74 61 70 30 00 88 ff ff tap0.... backtrace: [<000000004c159777>] kstrdup+0x35/0x70 [<00000000d8b496ad>] kstrdup_const+0x3d/0x50 [<00000000494e884a>] kvasprintf_const+0xf1/0x180 [<0000000097880a2b>] kobject_set_name_vargs+0x56/0x140 [<000000008fbdfc7b>] dev_set_name+0xab/0xe0 [<000000005b99e3b4>] netdev_register_kobject+0xc0/0x390 [<00000000602704fe>] register_netdevice+0xb61/0x1250 [<000000002b7ca244>] __tun_chr_ioctl+0x1cd1/0x3d70 [<000000001127ca24>] ksys_ioctl+0xe5/0x130 [<00000000b7d5e66a>] __x64_sys_ioctl+0x6f/0xb0 [<00000000e1023498>] do_syscall_64+0x56/0xa0 [<000000009ec0eb12>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 unreferenced object 0xffff88811886d800 (size 512): comm "ip", pid 3048, jiffies 4294911734 (age 343.491s) hex dump (first 32 bytes): 00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00 .....N.......... ff ff ff ff ff ff ff ff c0 66 3d a3 ff ff ff ff .........f=..... backtrace: [<0000000050315800>] device_add+0x61e/0x1950 [<0000000021008dfb>] netdev_register_kobject+0x17e/0x390 [<00000000602704fe>] register_netdevice+0xb61/0x1250 [<000000002b7ca244>] __tun_chr_ioctl+0x1cd1/0x3d70 [<000000001127ca24>] ksys_ioctl+0xe5/0x130 [<00000000b7d5e66a>] __x64_sys_ioctl+0x6f/0xb0 [<00000000e1023498>] do_syscall_64+0x56/0xa0 [<000000009ec0eb12>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 If call_netdevice_notifiers() failed, then rollback_registered() calls netdev_unregister_kobject() which holds the kobject. The reference cannot be put because the netdev won't be add to todo list, so it will leads a memleak, we need put the reference to avoid memleak. Reported-by: Hulk Robot Signed-off-by: Yang Yingliang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index 0aaa1426450f..1ee177485fd0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -7694,6 +7694,13 @@ int register_netdevice(struct net_device *dev) rcu_barrier(); dev->reg_state = NETREG_UNREGISTERED; + /* We should put the kobject that hold in + * netdev_unregister_kobject(), otherwise + * the net device cannot be freed when + * driver calls free_netdev(), because the + * kobject is being hold. + */ + kobject_put(&dev->dev.kobj); } /* * Prevent userspace races by waiting until the network From b7c46bbd3184aa99293720fd09d2c0ad077def56 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Mon, 15 Jun 2020 10:54:56 +0800 Subject: [PATCH 128/208] net: usb: ax88179_178a: fix packet alignment padding [ Upstream commit e869e7a17798d85829fa7d4f9bbe1eebd4b2d3f6 ] Using a AX88179 device (0b95:1790), I see two bytes of appended data on every RX packet. For example, this 48-byte ping, using 0xff as a payload byte: 04:20:22.528472 IP 192.168.1.1 > 192.168.1.2: ICMP echo request, id 2447, seq 1, length 64 0x0000: 000a cd35 ea50 000a cd35 ea4f 0800 4500 0x0010: 0054 c116 4000 4001 f63e c0a8 0101 c0a8 0x0020: 0102 0800 b633 098f 0001 87ea cd5e 0000 0x0030: 0000 dcf2 0600 0000 0000 ffff ffff ffff 0x0040: ffff ffff ffff ffff ffff ffff ffff ffff 0x0050: ffff ffff ffff ffff ffff ffff ffff ffff 0x0060: ffff 961f Those last two bytes - 96 1f - aren't part of the original packet. In the ax88179 RX path, the usbnet rx_fixup function trims a 2-byte 'alignment pseudo header' from the start of the packet, and sets the length from a per-packet field populated by hardware. It looks like that length field *includes* the 2-byte header; the current driver assumes that it's excluded. This change trims the 2-byte alignment header after we've set the packet length, so the resulting packet length is correct. While we're moving the comment around, this also fixes the spelling of 'pseudo'. Signed-off-by: Jeremy Kerr Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/ax88179_178a.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 0f69b77e8502..875639b0e9d5 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1400,10 +1400,10 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) } if (pkt_cnt == 0) { - /* Skip IP alignment psudo header */ - skb_pull(skb, 2); skb->len = pkt_len; - skb_set_tail_pointer(skb, pkt_len); + /* Skip IP alignment pseudo header */ + skb_pull(skb, 2); + skb_set_tail_pointer(skb, skb->len); skb->truesize = pkt_len + sizeof(struct sk_buff); ax88179_rx_checksum(skb, pkt_hdr); return 1; @@ -1412,8 +1412,9 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) ax_skb = skb_clone(skb, GFP_ATOMIC); if (ax_skb) { ax_skb->len = pkt_len; - ax_skb->data = skb->data + 2; - skb_set_tail_pointer(ax_skb, pkt_len); + /* Skip IP alignment pseudo header */ + skb_pull(ax_skb, 2); + skb_set_tail_pointer(ax_skb, ax_skb->len); ax_skb->truesize = pkt_len + sizeof(struct sk_buff); ax88179_rx_checksum(ax_skb, pkt_hdr); usbnet_skb_return(dev, ax_skb); From 69d6961c74b27072f6653419bcd2cb2d7cb0603f Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Fri, 12 Jun 2020 15:27:55 -0500 Subject: [PATCH 129/208] rocker: fix incorrect error handling in dma_rings_init [ Upstream commit 58d0c864e1a759a15c9df78f50ea5a5c32b3989e ] In rocker_dma_rings_init, the goto blocks in case of errors caused by the functions rocker_dma_cmd_ring_waits_alloc() and rocker_dma_ring_create() are incorrect. The patch fixes the order consistent with cleanup in rocker_dma_rings_fini(). Signed-off-by: Aditya Pakki Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/rocker/rocker_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 056cb6093630..8ad05e500829 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -651,10 +651,10 @@ static int rocker_dma_rings_init(struct rocker *rocker) err_dma_event_ring_bufs_alloc: rocker_dma_ring_destroy(rocker, &rocker->event_ring); err_dma_event_ring_create: + rocker_dma_cmd_ring_waits_free(rocker); +err_dma_cmd_ring_waits_alloc: rocker_dma_ring_bufs_free(rocker, &rocker->cmd_ring, PCI_DMA_BIDIRECTIONAL); -err_dma_cmd_ring_waits_alloc: - rocker_dma_cmd_ring_waits_free(rocker); err_dma_cmd_ring_bufs_alloc: rocker_dma_ring_destroy(rocker, &rocker->cmd_ring); return err; From ca03a5c2e70c8c8c433a98441af9804871ad3172 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 19 Jun 2020 23:38:16 +0100 Subject: [PATCH 130/208] rxrpc: Fix notification call on completion of discarded calls [ Upstream commit 0041cd5a50442db6e456b145892a0eaf2dff061f ] When preallocated service calls are being discarded, they're passed to ->discard_new_call() to have the caller clean up any attached higher-layer preallocated pieces before being marked completed. However, the act of marking them completed now invokes the call's notification function - which causes a problem because that function might assume that the previously freed pieces of memory are still there. Fix this by setting a dummy notification function on the socket after calling ->discard_new_call(). This results in the following kasan message when the kafs module is removed. ================================================================== BUG: KASAN: use-after-free in afs_wake_up_async_call+0x6aa/0x770 fs/afs/rxrpc.c:707 Write of size 1 at addr ffff8880946c39e4 by task kworker/u4:1/21 CPU: 0 PID: 21 Comm: kworker/u4:1 Not tainted 5.8.0-rc1-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: netns cleanup_net Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x18f/0x20d lib/dump_stack.c:118 print_address_description.constprop.0.cold+0xd3/0x413 mm/kasan/report.c:383 __kasan_report mm/kasan/report.c:513 [inline] kasan_report.cold+0x1f/0x37 mm/kasan/report.c:530 afs_wake_up_async_call+0x6aa/0x770 fs/afs/rxrpc.c:707 rxrpc_notify_socket+0x1db/0x5d0 net/rxrpc/recvmsg.c:40 __rxrpc_set_call_completion.part.0+0x172/0x410 net/rxrpc/recvmsg.c:76 __rxrpc_call_completed net/rxrpc/recvmsg.c:112 [inline] rxrpc_call_completed+0xca/0xf0 net/rxrpc/recvmsg.c:111 rxrpc_discard_prealloc+0x781/0xab0 net/rxrpc/call_accept.c:233 rxrpc_listen+0x147/0x360 net/rxrpc/af_rxrpc.c:245 afs_close_socket+0x95/0x320 fs/afs/rxrpc.c:110 afs_net_exit+0x1bc/0x310 fs/afs/main.c:155 ops_exit_list.isra.0+0xa8/0x150 net/core/net_namespace.c:186 cleanup_net+0x511/0xa50 net/core/net_namespace.c:603 process_one_work+0x965/0x1690 kernel/workqueue.c:2269 worker_thread+0x96/0xe10 kernel/workqueue.c:2415 kthread+0x3b5/0x4a0 kernel/kthread.c:291 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:293 Allocated by task 6820: save_stack+0x1b/0x40 mm/kasan/common.c:48 set_track mm/kasan/common.c:56 [inline] __kasan_kmalloc mm/kasan/common.c:494 [inline] __kasan_kmalloc.constprop.0+0xbf/0xd0 mm/kasan/common.c:467 kmem_cache_alloc_trace+0x153/0x7d0 mm/slab.c:3551 kmalloc include/linux/slab.h:555 [inline] kzalloc include/linux/slab.h:669 [inline] afs_alloc_call+0x55/0x630 fs/afs/rxrpc.c:141 afs_charge_preallocation+0xe9/0x2d0 fs/afs/rxrpc.c:757 afs_open_socket+0x292/0x360 fs/afs/rxrpc.c:92 afs_net_init+0xa6c/0xe30 fs/afs/main.c:125 ops_init+0xaf/0x420 net/core/net_namespace.c:151 setup_net+0x2de/0x860 net/core/net_namespace.c:341 copy_net_ns+0x293/0x590 net/core/net_namespace.c:482 create_new_namespaces+0x3fb/0xb30 kernel/nsproxy.c:110 unshare_nsproxy_namespaces+0xbd/0x1f0 kernel/nsproxy.c:231 ksys_unshare+0x43d/0x8e0 kernel/fork.c:2983 __do_sys_unshare kernel/fork.c:3051 [inline] __se_sys_unshare kernel/fork.c:3049 [inline] __x64_sys_unshare+0x2d/0x40 kernel/fork.c:3049 do_syscall_64+0x60/0xe0 arch/x86/entry/common.c:359 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Freed by task 21: save_stack+0x1b/0x40 mm/kasan/common.c:48 set_track mm/kasan/common.c:56 [inline] kasan_set_free_info mm/kasan/common.c:316 [inline] __kasan_slab_free+0xf7/0x140 mm/kasan/common.c:455 __cache_free mm/slab.c:3426 [inline] kfree+0x109/0x2b0 mm/slab.c:3757 afs_put_call+0x585/0xa40 fs/afs/rxrpc.c:190 rxrpc_discard_prealloc+0x764/0xab0 net/rxrpc/call_accept.c:230 rxrpc_listen+0x147/0x360 net/rxrpc/af_rxrpc.c:245 afs_close_socket+0x95/0x320 fs/afs/rxrpc.c:110 afs_net_exit+0x1bc/0x310 fs/afs/main.c:155 ops_exit_list.isra.0+0xa8/0x150 net/core/net_namespace.c:186 cleanup_net+0x511/0xa50 net/core/net_namespace.c:603 process_one_work+0x965/0x1690 kernel/workqueue.c:2269 worker_thread+0x96/0xe10 kernel/workqueue.c:2415 kthread+0x3b5/0x4a0 kernel/kthread.c:291 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:293 The buggy address belongs to the object at ffff8880946c3800 which belongs to the cache kmalloc-1k of size 1024 The buggy address is located 484 bytes inside of 1024-byte region [ffff8880946c3800, ffff8880946c3c00) The buggy address belongs to the page: page:ffffea000251b0c0 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 flags: 0xfffe0000000200(slab) raw: 00fffe0000000200 ffffea0002546508 ffffea00024fa248 ffff8880aa000c40 raw: 0000000000000000 ffff8880946c3000 0000000100000002 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8880946c3880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff8880946c3900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >ffff8880946c3980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff8880946c3a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff8880946c3a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ================================================================== Reported-by: syzbot+d3eccef36ddbd02713e9@syzkaller.appspotmail.com Fixes: 5ac0d62226a0 ("rxrpc: Fix missing notification") Signed-off-by: David Howells Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/rxrpc/call_accept.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c index 2dd13f5c47c8..61425179780c 100644 --- a/net/rxrpc/call_accept.c +++ b/net/rxrpc/call_accept.c @@ -26,6 +26,11 @@ #include #include "ar-internal.h" +static void rxrpc_dummy_notify(struct sock *sk, struct rxrpc_call *call, + unsigned long user_call_ID) +{ +} + /* * Preallocate a single service call, connection and peer and, if possible, * give them a user ID and attach the user's side of the ID to them. @@ -227,6 +232,8 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx) if (rx->discard_new_call) { _debug("discard %lx", call->user_call_ID); rx->discard_new_call(call, call->user_call_ID); + if (call->notify_rx) + call->notify_rx = rxrpc_dummy_notify; rxrpc_put_call(call, rxrpc_call_put_kernel); } rxrpc_call_completed(call); From f6be9e85059e0cf0d87c6ea042090b939c9c6039 Mon Sep 17 00:00:00 2001 From: Marcelo Ricardo Leitner Date: Wed, 24 Jun 2020 17:34:18 -0300 Subject: [PATCH 131/208] sctp: Don't advertise IPv4 addresses if ipv6only is set on the socket [ Upstream commit 471e39df96b9a4c4ba88a2da9e25a126624d7a9c ] If a socket is set ipv6only, it will still send IPv4 addresses in the INIT and INIT_ACK packets. This potentially misleads the peer into using them, which then would cause association termination. The fix is to not add IPv4 addresses to ipv6only sockets. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: Corey Minyard Signed-off-by: Marcelo Ricardo Leitner Tested-by: Corey Minyard Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/sctp/constants.h | 8 +++++--- net/sctp/associola.c | 5 ++++- net/sctp/bind_addr.c | 1 + net/sctp/protocol.c | 3 ++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index deaafa9b09cb..d4da07048aa3 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -361,11 +361,13 @@ enum { ipv4_is_anycast_6to4(a)) /* Flags used for the bind address copy functions. */ -#define SCTP_ADDR6_ALLOWED 0x00000001 /* IPv6 address is allowed by +#define SCTP_ADDR4_ALLOWED 0x00000001 /* IPv4 address is allowed by local sock family */ -#define SCTP_ADDR4_PEERSUPP 0x00000002 /* IPv4 address is supported by +#define SCTP_ADDR6_ALLOWED 0x00000002 /* IPv6 address is allowed by + local sock family */ +#define SCTP_ADDR4_PEERSUPP 0x00000004 /* IPv4 address is supported by peer */ -#define SCTP_ADDR6_PEERSUPP 0x00000004 /* IPv6 address is supported by +#define SCTP_ADDR6_PEERSUPP 0x00000008 /* IPv6 address is supported by peer */ /* Reasons to retransmit. */ diff --git a/net/sctp/associola.c b/net/sctp/associola.c index dd1a3bd80be5..0a5764016721 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1598,12 +1598,15 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, enum sctp_scope scope, gfp_t gfp) { + struct sock *sk = asoc->base.sk; int flags; /* Use scoping rules to determine the subset of addresses from * the endpoint. */ - flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0; + flags = (PF_INET6 == sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0; + if (!inet_v6_ipv6only(sk)) + flags |= SCTP_ADDR4_ALLOWED; if (asoc->peer.ipv4_address) flags |= SCTP_ADDR4_PEERSUPP; if (asoc->peer.ipv6_address) diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 7df3704982f5..38d01cfb313e 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -453,6 +453,7 @@ static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest, * well as the remote peer. */ if ((((AF_INET == addr->sa.sa_family) && + (flags & SCTP_ADDR4_ALLOWED) && (flags & SCTP_ADDR4_PEERSUPP))) || (((AF_INET6 == addr->sa.sa_family) && (flags & SCTP_ADDR6_ALLOWED) && diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 785456df7505..8fe9c0646205 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -213,7 +213,8 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp, * sock as well as the remote peer. */ if (addr->a.sa.sa_family == AF_INET && - !(copy_flags & SCTP_ADDR4_PEERSUPP)) + (!(copy_flags & SCTP_ADDR4_ALLOWED) || + !(copy_flags & SCTP_ADDR4_PEERSUPP))) continue; if (addr->a.sa.sa_family == AF_INET6 && (!(copy_flags & SCTP_ADDR6_ALLOWED) || From abbf44f422988e7db012645a6eba2de4ca8bc1c5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 15 Jun 2020 20:37:07 -0700 Subject: [PATCH 132/208] tcp: grow window for OOO packets only for SACK flows [ Upstream commit 662051215c758ae8545451628816204ed6cd372d ] Back in 2013, we made a change that broke fast retransmit for non SACK flows. Indeed, for these flows, a sender needs to receive three duplicate ACK before starting fast retransmit. Sending ACK with different receive window do not count. Even if enabling SACK is strongly recommended these days, there still are some cases where it has to be disabled. Not increasing the window seems better than having to rely on RTO. After the fix, following packetdrill test gives : // Initialize connection 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 +0 bind(3, ..., ...) = 0 +0 listen(3, 1) = 0 +0 < S 0:0(0) win 32792 +0 > S. 0:0(0) ack 1 +0 < . 1:1(0) ack 1 win 514 +0 accept(3, ..., ...) = 4 +0 < . 1:1001(1000) ack 1 win 514 // Quick ack +0 > . 1:1(0) ack 1001 win 264 +0 < . 2001:3001(1000) ack 1 win 514 // DUPACK : Normally we should not change the window +0 > . 1:1(0) ack 1001 win 264 +0 < . 3001:4001(1000) ack 1 win 514 // DUPACK : Normally we should not change the window +0 > . 1:1(0) ack 1001 win 264 +0 < . 4001:5001(1000) ack 1 win 514 // DUPACK : Normally we should not change the window +0 > . 1:1(0) ack 1001 win 264 +0 < . 1001:2001(1000) ack 1 win 514 // Hole is repaired. +0 > . 1:1(0) ack 5001 win 272 Fixes: 4e4f1fc22681 ("tcp: properly increase rcv_ssthresh for ofo packets") Signed-off-by: Eric Dumazet Reported-by: Venkat Venkatsubra Acked-by: Neal Cardwell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_input.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 29f3df4ddd1f..a2c26c2b3a94 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4507,7 +4507,11 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) if (tcp_ooo_try_coalesce(sk, tp->ooo_last_skb, skb, &fragstolen)) { coalesce_done: - tcp_grow_window(sk, skb); + /* For non sack flows, do not grow window to force DUPACK + * and trigger fast retransmit. + */ + if (tcp_is_sack(tp)) + tcp_grow_window(sk, skb); kfree_skb_partial(skb, fragstolen); skb = NULL; goto add_sack; @@ -4591,7 +4595,11 @@ add_sack: tcp_sack_new_ofo_skb(sk, seq, end_seq); end: if (skb) { - tcp_grow_window(sk, skb); + /* For non sack flows, do not grow window to force DUPACK + * and trigger fast retransmit. + */ + if (tcp_is_sack(tp)) + tcp_grow_window(sk, skb); skb_condense(skb); skb_set_owner_r(skb, sk); } From 77dd6d3589f9173ecee302bc0a720ff0b4a47fcf Mon Sep 17 00:00:00 2001 From: David Christensen Date: Wed, 17 Jun 2020 11:51:17 -0700 Subject: [PATCH 133/208] tg3: driver sleeps indefinitely when EEH errors exceed eeh_max_freezes [ Upstream commit 3a2656a211caf35e56afc9425e6e518fa52f7fbc ] The driver function tg3_io_error_detected() calls napi_disable twice, without an intervening napi_enable, when the number of EEH errors exceeds eeh_max_freezes, resulting in an indefinite sleep while holding rtnl_lock. Add check for pcierr_recovery which skips code already executed for the "Frozen" state. Signed-off-by: David Christensen Reviewed-by: Michael Chan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/broadcom/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index bc0221eafe5c..e40d31b40525 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -18179,8 +18179,8 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, rtnl_lock(); - /* We probably don't have netdev yet */ - if (!netdev || !netif_running(netdev)) + /* Could be second call or maybe we don't have netdev yet */ + if (!netdev || tp->pcierr_recovery || !netif_running(netdev)) goto done; /* We needn't recover from permanent error */ From 35e91cf554b9260274b9dff3d2241b29c471db27 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Tue, 16 Jun 2020 16:51:51 +0000 Subject: [PATCH 134/208] ip_tunnel: fix use-after-free in ip_tunnel_lookup() [ Upstream commit ba61539c6ae57f4146284a5cb4f7b7ed8d42bf45 ] In the datapath, the ip_tunnel_lookup() is used and it internally uses fallback tunnel device pointer, which is fb_tunnel_dev. This pointer variable should be set to NULL when a fb interface is deleted. But there is no routine to set fb_tunnel_dev pointer to NULL. So, this pointer will be still used after interface is deleted and it eventually results in the use-after-free problem. Test commands: ip netns add A ip netns add B ip link add eth0 type veth peer name eth1 ip link set eth0 netns A ip link set eth1 netns B ip netns exec A ip link set lo up ip netns exec A ip link set eth0 up ip netns exec A ip link add gre1 type gre local 10.0.0.1 \ remote 10.0.0.2 ip netns exec A ip link set gre1 up ip netns exec A ip a a 10.0.100.1/24 dev gre1 ip netns exec A ip a a 10.0.0.1/24 dev eth0 ip netns exec B ip link set lo up ip netns exec B ip link set eth1 up ip netns exec B ip link add gre1 type gre local 10.0.0.2 \ remote 10.0.0.1 ip netns exec B ip link set gre1 up ip netns exec B ip a a 10.0.100.2/24 dev gre1 ip netns exec B ip a a 10.0.0.2/24 dev eth1 ip netns exec A hping3 10.0.100.2 -2 --flood -d 60000 & ip netns del B Splat looks like: [ 77.793450][ C3] ================================================================== [ 77.794702][ C3] BUG: KASAN: use-after-free in ip_tunnel_lookup+0xcc4/0xf30 [ 77.795573][ C3] Read of size 4 at addr ffff888060bd9c84 by task hping3/2905 [ 77.796398][ C3] [ 77.796664][ C3] CPU: 3 PID: 2905 Comm: hping3 Not tainted 5.8.0-rc1+ #616 [ 77.797474][ C3] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 77.798453][ C3] Call Trace: [ 77.798815][ C3] [ 77.799142][ C3] dump_stack+0x9d/0xdb [ 77.799605][ C3] print_address_description.constprop.7+0x2cc/0x450 [ 77.800365][ C3] ? ip_tunnel_lookup+0xcc4/0xf30 [ 77.800908][ C3] ? ip_tunnel_lookup+0xcc4/0xf30 [ 77.801517][ C3] ? ip_tunnel_lookup+0xcc4/0xf30 [ 77.802145][ C3] kasan_report+0x154/0x190 [ 77.802821][ C3] ? ip_tunnel_lookup+0xcc4/0xf30 [ 77.803503][ C3] ip_tunnel_lookup+0xcc4/0xf30 [ 77.804165][ C3] __ipgre_rcv+0x1ab/0xaa0 [ip_gre] [ 77.804862][ C3] ? rcu_read_lock_sched_held+0xc0/0xc0 [ 77.805621][ C3] gre_rcv+0x304/0x1910 [ip_gre] [ 77.806293][ C3] ? lock_acquire+0x1a9/0x870 [ 77.806925][ C3] ? gre_rcv+0xfe/0x354 [gre] [ 77.807559][ C3] ? erspan_xmit+0x2e60/0x2e60 [ip_gre] [ 77.808305][ C3] ? rcu_read_lock_sched_held+0xc0/0xc0 [ 77.809032][ C3] ? rcu_read_lock_held+0x90/0xa0 [ 77.809713][ C3] gre_rcv+0x1b8/0x354 [gre] [ ... ] Suggested-by: Eric Dumazet Fixes: c54419321455 ("GRE: Refactor GRE tunneling code.") Signed-off-by: Taehee Yoo Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_tunnel.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index f6793017a20d..44cc17c43a6b 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -98,9 +98,10 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, __be32 remote, __be32 local, __be32 key) { - unsigned int hash; struct ip_tunnel *t, *cand = NULL; struct hlist_head *head; + struct net_device *ndev; + unsigned int hash; hash = ip_tunnel_hash(key, remote); head = &itn->tunnels[hash]; @@ -175,8 +176,9 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, if (t && t->dev->flags & IFF_UP) return t; - if (itn->fb_tunnel_dev && itn->fb_tunnel_dev->flags & IFF_UP) - return netdev_priv(itn->fb_tunnel_dev); + ndev = READ_ONCE(itn->fb_tunnel_dev); + if (ndev && ndev->flags & IFF_UP) + return netdev_priv(ndev); return NULL; } @@ -1211,9 +1213,9 @@ void ip_tunnel_uninit(struct net_device *dev) struct ip_tunnel_net *itn; itn = net_generic(net, tunnel->ip_tnl_net_id); - /* fb_tunnel_dev will be unregisted in net-exit call. */ - if (itn->fb_tunnel_dev != dev) - ip_tunnel_del(itn, netdev_priv(dev)); + ip_tunnel_del(itn, netdev_priv(dev)); + if (itn->fb_tunnel_dev == dev) + WRITE_ONCE(itn->fb_tunnel_dev, NULL); dst_cache_reset(&tunnel->dst_cache); } From 60491c5ab451d9adc8fb58fa88d08606f8ba8f92 Mon Sep 17 00:00:00 2001 From: Neal Cardwell Date: Wed, 24 Jun 2020 12:42:02 -0400 Subject: [PATCH 135/208] tcp_cubic: fix spurious HYSTART_DELAY exit upon drop in min RTT [ Upstream commit b344579ca8478598937215f7005d6c7b84d28aee ] Mirja Kuehlewind reported a bug in Linux TCP CUBIC Hystart, where Hystart HYSTART_DELAY mechanism can exit Slow Start spuriously on an ACK when the minimum rtt of a connection goes down. From inspection it is clear from the existing code that this could happen in an example like the following: o The first 8 RTT samples in a round trip are 150ms, resulting in a curr_rtt of 150ms and a delay_min of 150ms. o The 9th RTT sample is 100ms. The curr_rtt does not change after the first 8 samples, so curr_rtt remains 150ms. But delay_min can be lowered at any time, so delay_min falls to 100ms. The code executes the HYSTART_DELAY comparison between curr_rtt of 150ms and delay_min of 100ms, and the curr_rtt is declared far enough above delay_min to force a (spurious) exit of Slow start. The fix here is simple: allow every RTT sample in a round trip to lower the curr_rtt. Fixes: ae27e98a5152 ("[TCP] CUBIC v2.3") Reported-by: Mirja Kuehlewind Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Acked-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/tcp_cubic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 78bfadfcf342..8b5ba0a5cd38 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -403,6 +403,8 @@ static void hystart_update(struct sock *sk, u32 delay) if (hystart_detect & HYSTART_DELAY) { /* obtain the minimum delay of more than sampling packets */ + if (ca->curr_rtt > delay) + ca->curr_rtt = delay; if (ca->sample_cnt < HYSTART_MIN_SAMPLES) { if (ca->curr_rtt == 0 || ca->curr_rtt > delay) ca->curr_rtt = delay; From b7e1a9cff6b0b63a7a56eaf0b92e74b8942ddeb5 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Tue, 16 Jun 2020 16:04:00 +0000 Subject: [PATCH 136/208] ip6_gre: fix use-after-free in ip6gre_tunnel_lookup() [ Upstream commit dafabb6590cb15f300b77c095d50312e2c7c8e0f ] In the datapath, the ip6gre_tunnel_lookup() is used and it internally uses fallback tunnel device pointer, which is fb_tunnel_dev. This pointer variable should be set to NULL when a fb interface is deleted. But there is no routine to set fb_tunnel_dev pointer to NULL. So, this pointer will be still used after interface is deleted and it eventually results in the use-after-free problem. Test commands: ip netns add A ip netns add B ip link add eth0 type veth peer name eth1 ip link set eth0 netns A ip link set eth1 netns B ip netns exec A ip link set lo up ip netns exec A ip link set eth0 up ip netns exec A ip link add ip6gre1 type ip6gre local fc:0::1 \ remote fc:0::2 ip netns exec A ip -6 a a fc:100::1/64 dev ip6gre1 ip netns exec A ip link set ip6gre1 up ip netns exec A ip -6 a a fc:0::1/64 dev eth0 ip netns exec A ip link set ip6gre0 up ip netns exec B ip link set lo up ip netns exec B ip link set eth1 up ip netns exec B ip link add ip6gre1 type ip6gre local fc:0::2 \ remote fc:0::1 ip netns exec B ip -6 a a fc:100::2/64 dev ip6gre1 ip netns exec B ip link set ip6gre1 up ip netns exec B ip -6 a a fc:0::2/64 dev eth1 ip netns exec B ip link set ip6gre0 up ip netns exec A ping fc:100::2 -s 60000 & ip netns del B Splat looks like: [ 73.087285][ C1] BUG: KASAN: use-after-free in ip6gre_tunnel_lookup+0x1064/0x13f0 [ip6_gre] [ 73.088361][ C1] Read of size 4 at addr ffff888040559218 by task ping/1429 [ 73.089317][ C1] [ 73.089638][ C1] CPU: 1 PID: 1429 Comm: ping Not tainted 5.7.0+ #602 [ 73.090531][ C1] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 73.091725][ C1] Call Trace: [ 73.092160][ C1] [ 73.092556][ C1] dump_stack+0x96/0xdb [ 73.093122][ C1] print_address_description.constprop.6+0x2cc/0x450 [ 73.094016][ C1] ? ip6gre_tunnel_lookup+0x1064/0x13f0 [ip6_gre] [ 73.094894][ C1] ? ip6gre_tunnel_lookup+0x1064/0x13f0 [ip6_gre] [ 73.095767][ C1] ? ip6gre_tunnel_lookup+0x1064/0x13f0 [ip6_gre] [ 73.096619][ C1] kasan_report+0x154/0x190 [ 73.097209][ C1] ? ip6gre_tunnel_lookup+0x1064/0x13f0 [ip6_gre] [ 73.097989][ C1] ip6gre_tunnel_lookup+0x1064/0x13f0 [ip6_gre] [ 73.098750][ C1] ? gre_del_protocol+0x60/0x60 [gre] [ 73.099500][ C1] gre_rcv+0x1c5/0x1450 [ip6_gre] [ 73.100199][ C1] ? ip6gre_header+0xf00/0xf00 [ip6_gre] [ 73.100985][ C1] ? rcu_read_lock_sched_held+0xc0/0xc0 [ 73.101830][ C1] ? ip6_input_finish+0x5/0xf0 [ 73.102483][ C1] ip6_protocol_deliver_rcu+0xcbb/0x1510 [ 73.103296][ C1] ip6_input_finish+0x5b/0xf0 [ 73.103920][ C1] ip6_input+0xcd/0x2c0 [ 73.104473][ C1] ? ip6_input_finish+0xf0/0xf0 [ 73.105115][ C1] ? rcu_read_lock_held+0x90/0xa0 [ 73.105783][ C1] ? rcu_read_lock_sched_held+0xc0/0xc0 [ 73.106548][ C1] ipv6_rcv+0x1f1/0x300 [ ... ] Suggested-by: Eric Dumazet Fixes: c12b395a4664 ("gre: Support GRE over IPv6") Signed-off-by: Taehee Yoo Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_gre.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 726ba41133a3..e07cc2cfc1a6 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -124,6 +124,7 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev, int dev_type = (gre_proto == htons(ETH_P_TEB)) ? ARPHRD_ETHER : ARPHRD_IP6GRE; int score, cand_score = 4; + struct net_device *ndev; for_each_ip_tunnel_rcu(t, ign->tunnels_r_l[h0 ^ h1]) { if (!ipv6_addr_equal(local, &t->parms.laddr) || @@ -226,9 +227,9 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev, if (cand) return cand; - dev = ign->fb_tunnel_dev; - if (dev->flags & IFF_UP) - return netdev_priv(dev); + ndev = READ_ONCE(ign->fb_tunnel_dev); + if (ndev && ndev->flags & IFF_UP) + return netdev_priv(ndev); return NULL; } @@ -364,6 +365,8 @@ static void ip6gre_tunnel_uninit(struct net_device *dev) struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id); ip6gre_tunnel_unlink(ign, t); + if (ign->fb_tunnel_dev == dev) + WRITE_ONCE(ign->fb_tunnel_dev, NULL); dst_cache_reset(&t->dst_cache); dev_put(dev); } From 897646bcf4e3d9d21a16bea7d609914a7ba24d95 Mon Sep 17 00:00:00 2001 From: guodeqing Date: Wed, 17 Jun 2020 10:07:16 +0800 Subject: [PATCH 137/208] net: Fix the arp error in some cases [ Upstream commit 5eea3a63ff4aba6a26002e657a6d21934b7e2b96 ] ie., $ ifconfig eth0 6.6.6.6 netmask 255.255.255.0 $ ip rule add from 6.6.6.6 table 6666 $ ip route add 9.9.9.9 via 6.6.6.6 $ ping -I 6.6.6.6 9.9.9.9 PING 9.9.9.9 (9.9.9.9) from 6.6.6.6 : 56(84) bytes of data. 3 packets transmitted, 0 received, 100% packet loss, time 2079ms $ arp Address HWtype HWaddress Flags Mask Iface 6.6.6.6 (incomplete) eth0 The arp request address is error, this is because fib_table_lookup in fib_check_nh lookup the destnation 9.9.9.9 nexthop, the scope of the fib result is RT_SCOPE_LINK,the correct scope is RT_SCOPE_HOST. Here I add a check of whether this is RT_TABLE_MAIN to solve this problem. Fixes: 3bfd847203c6 ("net: Use passed in table for nexthop lookups") Signed-off-by: guodeqing Reviewed-by: David Ahern Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/fib_semantics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index eff703cb13b6..bc233fdfae0f 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -839,7 +839,7 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, if (fl4.flowi4_scope < RT_SCOPE_LINK) fl4.flowi4_scope = RT_SCOPE_LINK; - if (cfg->fc_table) + if (cfg->fc_table && cfg->fc_table != RT_TABLE_MAIN) tbl = fib_get_table(net, cfg->fc_table); if (tbl) From 1eb41db96e1c17d3d1d9b54bb8284fce273949d9 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Mon, 22 Jun 2020 23:26:04 +0300 Subject: [PATCH 138/208] net: Do not clear the sock TX queue in sk_set_socket() [ Upstream commit 41b14fb8724d5a4b382a63cb4a1a61880347ccb8 ] Clearing the sock TX queue in sk_set_socket() might cause unexpected out-of-order transmit when called from sock_orphan(), as outstanding packets can pick a different TX queue and bypass the ones already queued. This is undesired in general. More specifically, it breaks the in-order scheduling property guarantee for device-offloaded TLS sockets. Remove the call to sk_tx_queue_clear() in sk_set_socket(), and add it explicitly only where needed. Fixes: e022f0b4a03f ("net: Introduce sk_tx_queue_mapping") Signed-off-by: Tariq Toukan Reviewed-by: Boris Pismenny Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/sock.h | 1 - net/core/sock.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/net/sock.h b/include/net/sock.h index c6a003bc4737..a2e10d0b1280 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1687,7 +1687,6 @@ static inline int sk_tx_queue_get(const struct sock *sk) static inline void sk_set_socket(struct sock *sk, struct socket *sock) { - sk_tx_queue_clear(sk); sk->sk_socket = sock; } diff --git a/net/core/sock.c b/net/core/sock.c index d2cb2051d045..08ca2ec0ce60 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1538,6 +1538,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, cgroup_sk_alloc(&sk->sk_cgrp_data); sock_update_classid(&sk->sk_cgrp_data); sock_update_netprioidx(&sk->sk_cgrp_data); + sk_tx_queue_clear(sk); } return sk; @@ -1740,6 +1741,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) */ sk_refcnt_debug_inc(newsk); sk_set_socket(newsk, NULL); + sk_tx_queue_clear(newsk); newsk->sk_wq = NULL; if (newsk->sk_prot->sockets_allocated) From 8f8ea18406694238025a16fe15a84322c3301e10 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Tue, 16 Jun 2020 15:52:05 +0000 Subject: [PATCH 139/208] net: core: reduce recursion limit value [ Upstream commit fb7861d14c8d7edac65b2fcb6e8031cb138457b2 ] In the current code, ->ndo_start_xmit() can be executed recursively only 10 times because of stack memory. But, in the case of the vxlan, 10 recursion limit value results in a stack overflow. In the current code, the nested interface is limited by 8 depth. There is no critical reason that the recursion limitation value should be 10. So, it would be good to be the same value with the limitation value of nesting interface depth. Test commands: ip link add vxlan10 type vxlan vni 10 dstport 4789 srcport 4789 4789 ip link set vxlan10 up ip a a 192.168.10.1/24 dev vxlan10 ip n a 192.168.10.2 dev vxlan10 lladdr fc:22:33:44:55:66 nud permanent for i in {9..0} do let A=$i+1 ip link add vxlan$i type vxlan vni $i dstport 4789 srcport 4789 4789 ip link set vxlan$i up ip a a 192.168.$i.1/24 dev vxlan$i ip n a 192.168.$i.2 dev vxlan$i lladdr fc:22:33:44:55:66 nud permanent bridge fdb add fc:22:33:44:55:66 dev vxlan$A dst 192.168.$i.2 self done hping3 192.168.10.2 -2 -d 60000 Splat looks like: [ 103.814237][ T1127] ============================================================================= [ 103.871955][ T1127] BUG kmalloc-2k (Tainted: G B ): Padding overwritten. 0x00000000897a2e4f-0x000 [ 103.873187][ T1127] ----------------------------------------------------------------------------- [ 103.873187][ T1127] [ 103.874252][ T1127] INFO: Slab 0x000000005cccc724 objects=5 used=5 fp=0x0000000000000000 flags=0x10000000001020 [ 103.881323][ T1127] CPU: 3 PID: 1127 Comm: hping3 Tainted: G B 5.7.0+ #575 [ 103.882131][ T1127] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 103.883006][ T1127] Call Trace: [ 103.883324][ T1127] dump_stack+0x96/0xdb [ 103.883716][ T1127] slab_err+0xad/0xd0 [ 103.884106][ T1127] ? _raw_spin_unlock+0x1f/0x30 [ 103.884620][ T1127] ? get_partial_node.isra.78+0x140/0x360 [ 103.885214][ T1127] slab_pad_check.part.53+0xf7/0x160 [ 103.885769][ T1127] ? pskb_expand_head+0x110/0xe10 [ 103.886316][ T1127] check_slab+0x97/0xb0 [ 103.886763][ T1127] alloc_debug_processing+0x84/0x1a0 [ 103.887308][ T1127] ___slab_alloc+0x5a5/0x630 [ 103.887765][ T1127] ? pskb_expand_head+0x110/0xe10 [ 103.888265][ T1127] ? lock_downgrade+0x730/0x730 [ 103.888762][ T1127] ? pskb_expand_head+0x110/0xe10 [ 103.889244][ T1127] ? __slab_alloc+0x3e/0x80 [ 103.889675][ T1127] __slab_alloc+0x3e/0x80 [ 103.890108][ T1127] __kmalloc_node_track_caller+0xc7/0x420 [ ... ] Fixes: 11a766ce915f ("net: Increase xmit RECURSION_LIMIT to 10.") Signed-off-by: Taehee Yoo Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/netdevice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 31fc54757bf2..3512c337a4a6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2449,7 +2449,7 @@ void synchronize_net(void); int init_dummy_netdev(struct net_device *dev); DECLARE_PER_CPU(int, xmit_recursion); -#define XMIT_RECURSION_LIMIT 10 +#define XMIT_RECURSION_LIMIT 8 static inline int dev_recursion_level(void) { From 2cde601014d29ed14b863eefffd35b33fd4f77dc Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Wed, 10 Jun 2020 10:48:44 +0800 Subject: [PATCH 140/208] USB: ohci-sm501: Add missed iounmap() in remove commit 07c112fb09c86c0231f6ff0061a000ffe91c8eb9 upstream. This driver misses calling iounmap() in remove to undo the ioremap() called in probe. Add the missed call to fix it. Fixes: f54aab6ebcec ("usb: ohci-sm501 driver") Cc: stable Signed-off-by: Chuhong Yuan Acked-by: Alan Stern Link: https://lore.kernel.org/r/20200610024844.3628408-1-hslester96@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-sm501.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index d4e0f7cd96fa..b5592fb518e3 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -195,6 +195,7 @@ static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev) struct resource *mem; usb_remove_hcd(hcd); + iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); dma_release_declared_memory(&pdev->dev); From 5d7ab2dd163b361fa665114ecfe48e97c7450732 Mon Sep 17 00:00:00 2001 From: Minas Harutyunyan Date: Tue, 9 Jun 2020 12:28:11 +0400 Subject: [PATCH 141/208] usb: dwc2: Postponed gadget registration to the udc class driver commit 207324a321a866401b098cadf19e4a2dd6584622 upstream. During dwc2 driver probe, after gadget registration to the udc class driver, if exist any builtin function driver it immediately bound to dwc2 and after init host side (dwc2_hcd_init()) stucked in host mode. Patch postpone gadget registration after host side initialization done. Fixes: 117777b2c3bb9 ("usb: dwc2: Move gadget probe function into platform code") Reported-by: kbuild test robot Tested-by: Marek Vasut Cc: stable Signed-off-by: Minas Harutyunyan Link: https://lore.kernel.org/r/f21cb38fecc72a230b86155d94c7e60c9cb66f58.1591690938.git.hminas@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc2/gadget.c | 6 ------ drivers/usb/dwc2/platform.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index aeb6f7c84ea0..03bc479d04e0 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -4723,12 +4723,6 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) epnum, 0); } - ret = usb_add_gadget_udc(dev, &hsotg->gadget); - if (ret) { - dwc2_hsotg_ep_free_request(&hsotg->eps_out[0]->ep, - hsotg->ctrl_req); - return ret; - } dwc2_hsotg_dump(hsotg); return 0; diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index daf0d37acb37..c8ac0391e65f 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -452,6 +452,17 @@ static int dwc2_driver_probe(struct platform_device *dev) if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) dwc2_lowlevel_hw_disable(hsotg); +#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ + IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) + /* Postponed adding a new gadget to the udc class driver list */ + if (hsotg->gadget_enabled) { + retval = usb_add_gadget_udc(hsotg->dev, &hsotg->gadget); + if (retval) { + dwc2_hsotg_remove(hsotg); + goto error; + } + } +#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */ return 0; error: From 9112251097e07a29ba84486b667e2dc959c399b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Meresi=C5=84ski?= Date: Wed, 3 Jun 2020 22:33:46 +0200 Subject: [PATCH 142/208] usb: add USB_QUIRK_DELAY_INIT for Logitech C922 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 5d8021923e8a8cc37a421a64e27c7221f0fee33c upstream. The Logitech C922, just like other Logitech webcams, needs the USB_QUIRK_DELAY_INIT or it will randomly not respond after device connection Signed-off-by: Tomasz MeresiÅ„ski Cc: stable Link: https://lore.kernel.org/r/20200603203347.7792-1-tomasz@meresinski.eu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 27d05f0134de..e6e0f786547b 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -73,11 +73,12 @@ static const struct usb_device_id usb_quirk_list[] = { /* Logitech HD Webcam C270 */ { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, - /* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */ + /* Logitech HD Pro Webcams C920, C920-C, C922, C925e and C930e */ { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x046d, 0x085b), .driver_info = USB_QUIRK_DELAY_INIT }, + { USB_DEVICE(0x046d, 0x085c), .driver_info = USB_QUIRK_DELAY_INIT }, /* Logitech ConferenceCam CC3000e */ { USB_DEVICE(0x046d, 0x0847), .driver_info = USB_QUIRK_DELAY_INIT }, From afc11505746084112ea86cadc14fcea8bd72ea6c Mon Sep 17 00:00:00 2001 From: Longfang Liu Date: Mon, 8 Jun 2020 11:46:59 +0800 Subject: [PATCH 143/208] USB: ehci: reopen solution for Synopsys HC bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1ddcb71a3edf0e1682b6e056158e4c4b00325f66 upstream. A Synopsys USB2.0 core used in Huawei Kunpeng920 SoC has a bug which might cause the host controller not issuing ping. Bug description: After indicating an Interrupt on Async Advance, the software uses the doorbell mechanism to delete the Next Link queue head of the last executed queue head. At this time, the host controller still references the removed queue head(the queue head is NULL). NULL reference causes the host controller to lose the USB device. Solution: After deleting the Next Link queue head, when has_synopsys_hc_bug set to 1,the software can write one of the valid queue head addresses to the ASYNCLISTADDR register to allow the host controller to get the valid queue head. in order to solve that problem, this patch set the flag for Huawei Kunpeng920 There are detailed instructions and solutions in this patch: commit 2f7ac6c19997 ("USB: ehci: add workaround for Synopsys HC bug") Signed-off-by: Longfang Liu Cc: stable Acked-by: Alan Stern Link: https://lore.kernel.org/r/1591588019-44284-1-git-send-email-liulongfang@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 93326974ff4b..265c9af1d2b5 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -229,6 +229,13 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ehci_info(ehci, "applying MosChip frame-index workaround\n"); ehci->frame_index_bug = 1; break; + case PCI_VENDOR_ID_HUAWEI: + /* Synopsys HC bug */ + if (pdev->device == 0xa239) { + ehci_info(ehci, "applying Synopsys HC workaround\n"); + ehci->has_synopsys_hc_bug = 1; + } + break; } /* optional debug port, normally in the first BAR */ From cfb8b3ba68c88786bf67742ac6f1e4b2eb0e45a6 Mon Sep 17 00:00:00 2001 From: Macpaul Lin Date: Wed, 24 Jun 2020 16:59:47 +0300 Subject: [PATCH 144/208] usb: host: xhci-mtk: avoid runtime suspend when removing hcd commit a24d5072e87457a14023ee1dd3fc8b1e76f899ef upstream. When runtime suspend was enabled, runtime suspend might happen when xhci is removing hcd. This might cause kernel panic when hcd has been freed but runtime pm suspend related handle need to reference it. Signed-off-by: Macpaul Lin Reviewed-by: Chunfeng Yun Cc: stable@vger.kernel.org Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20200624135949.22611-4-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mtk.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 35aecbcac6f7..945e108cffb8 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -726,6 +726,9 @@ static int xhci_mtk_remove(struct platform_device *dev) struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct usb_hcd *shared_hcd = xhci->shared_hcd; + pm_runtime_put_noidle(&dev->dev); + pm_runtime_disable(&dev->dev); + usb_remove_hcd(shared_hcd); xhci->shared_hcd = NULL; xhci_mtk_phy_power_off(mtk); @@ -738,8 +741,6 @@ static int xhci_mtk_remove(struct platform_device *dev) xhci_mtk_sch_exit(mtk); xhci_mtk_clks_disable(mtk); xhci_mtk_ldos_disable(mtk); - pm_runtime_put_sync(&dev->dev); - pm_runtime_disable(&dev->dev); return 0; } From 10bffd4ed6320e3e69012915f3c3523af30a22df Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Tue, 2 Jun 2020 19:47:08 +0800 Subject: [PATCH 145/208] usb: host: ehci-exynos: Fix error check in exynos_ehci_probe() commit 44ed240d62736ad29943ec01e41e194b96f7c5e9 upstream. If the function platform_get_irq() failed, the negative value returned will not be detected here. So fix error handling in exynos_ehci_probe(). And when get irq failed, the function platform_get_irq() logs an error message, so remove redundant message here. Fixes: 1bcc5aa87f04 ("USB: Add initial S5P EHCI driver") Cc: stable Signed-off-by: Zhang Shengju Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20200602114708.28620-1-tangbin@cmss.chinamobile.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-exynos.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index 26b641100639..be72a625dc21 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c @@ -199,9 +199,8 @@ skip_phy: hcd->rsrc_len = resource_size(res); irq = platform_get_irq(pdev, 0); - if (!irq) { - dev_err(&pdev->dev, "Failed to get IRQ\n"); - err = -ENODEV; + if (irq < 0) { + err = irq; goto fail_io; } From 6ea5bc874f07e6615f685cdf5d6255758f312479 Mon Sep 17 00:00:00 2001 From: "Yick W. Tse" Date: Sat, 13 Jun 2020 11:40:06 +0000 Subject: [PATCH 146/208] ALSA: usb-audio: add quirk for Denon DCD-1500RE commit c9808bbfed3cfc911ecb60fe8e80c0c27876c657 upstream. fix error "clock source 41 is not valid, cannot use" [] New USB device found, idVendor=154e, idProduct=1002, bcdDevice= 1.00 [] New USB device strings: Mfr=1, Product=2, SerialNumber=0 [] Product: DCD-1500RE [] Manufacturer: D & M Holdings Inc. [] [] clock source 41 is not valid, cannot use [] usbcore: registered new interface driver snd-usb-audio Signed-off-by: Yick W. Tse Cc: Link: https://lore.kernel.org/r/1373857985.210365.1592048406997@mail.yahoo.com Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index f29a8ed4f856..cd36394e27ae 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1164,6 +1164,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) static bool is_itf_usb_dsd_2alts_dac(unsigned int id) { switch (id) { + case USB_ID(0x154e, 0x1002): /* Denon DCD-1500RE */ case USB_ID(0x154e, 0x1003): /* Denon DA-300USB */ case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */ case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */ From e52e7a0239425ab7f4c573af109784246753dd49 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Wed, 24 Jun 2020 16:59:45 +0300 Subject: [PATCH 147/208] xhci: Fix incorrect EP_STATE_MASK commit dceea67058fe22075db3aed62d5cb62092be5053 upstream. EP_STATE_MASK should be 0x7 instead of 0xf xhci spec 6.2.3 shows that the EP state field in the endpoint context data structure consist of bits [2:0]. The old value included a bit from the next field which fortunately is a RsvdZ region. So hopefully this hasn't caused too much harm Cc: stable@vger.kernel.org Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20200624135949.22611-2-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index db1af99d53bd..8b52a7773bc8 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -718,7 +718,7 @@ struct xhci_ep_ctx { * 4 - TRB error * 5-7 - reserved */ -#define EP_STATE_MASK (0xf) +#define EP_STATE_MASK (0x7) #define EP_STATE_DISABLED 0 #define EP_STATE_RUNNING 1 #define EP_STATE_HALTED 2 From 6426108a9b83066a22decc71ba28610b89aab8e2 Mon Sep 17 00:00:00 2001 From: Al Cooper Date: Wed, 24 Jun 2020 16:59:46 +0300 Subject: [PATCH 148/208] xhci: Fix enumeration issue when setting max packet size for FS devices. commit a73d9d9cfc3cfceabd91fb0b0c13e4062b6dbcd7 upstream. Unable to complete the enumeration of a USB TV Tuner device. Per XHCI spec (4.6.5), the EP state field of the input context shall be cleared for a set address command. In the special case of an FS device that has "MaxPacketSize0 = 8", the Linux XHCI driver does not do this before evaluating the context. With an XHCI controller that checks the EP state field for parameter context error this causes a problem in cases such as the device getting reset again after enumeration. When that field is cleared, the problem does not occur. This was found and fixed by Sasi Kumar. Cc: stable@vger.kernel.org Signed-off-by: Al Cooper Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20200624135949.22611-3-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 6c0a0ca316d3..d727cbbad44a 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1346,6 +1346,7 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, xhci->devs[slot_id]->out_ctx, ep_index); ep_ctx = xhci_get_ep_ctx(xhci, command->in_ctx, ep_index); + ep_ctx->ep_info &= cpu_to_le32(~EP_STATE_MASK);/* must clear */ ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK); ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size)); From 484ca169d9f97091a56980cc38649f0d2a518035 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Fri, 5 Jun 2020 12:54:18 +0200 Subject: [PATCH 149/208] cdc-acm: Add DISABLE_ECHO quirk for Microchip/SMSC chip commit 03894573f2913181ee5aae0089f333b2131f2d4b upstream. USB_DEVICE(0x0424, 0x274e) can send data before cdc_acm is ready, causing garbage chars on the TTY causing stray input to the shell and/or login prompt. Signed-off-by: Joakim Tjernlund Cc: stable@vger.kernel.org Acked-by: Oliver Neukum Link: https://lore.kernel.org/r/20200605105418.22263-1-joakim.tjernlund@infinera.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 4067f079b08d..0de467c8593d 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1734,6 +1734,8 @@ static int acm_pre_reset(struct usb_interface *intf) static const struct usb_device_id acm_ids[] = { /* quirky and broken devices */ + { USB_DEVICE(0x0424, 0x274e), /* Microchip Technology, Inc. (formerly SMSC) */ + .driver_info = DISABLE_ECHO, }, /* DISABLE ECHO in termios flag */ { USB_DEVICE(0x076d, 0x0006), /* Denso Cradle CU-321 */ .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */ { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */ From 01317ebd8598f71b9c742d579cd7f4ff8e1af7ff Mon Sep 17 00:00:00 2001 From: Zheng Bin Date: Thu, 18 Jun 2020 12:21:37 +0800 Subject: [PATCH 150/208] loop: replace kill_bdev with invalidate_bdev commit f4bd34b139a3fa2808c4205f12714c65e1548c6c upstream. When a filesystem is mounted on a loop device and on a loop ioctl LOOP_SET_STATUS64, because of kill_bdev, buffer_head mappings are getting destroyed. kill_bdev truncate_inode_pages truncate_inode_pages_range do_invalidatepage block_invalidatepage discard_buffer -->clear BH_Mapped flag sb_bread __bread_gfp bh = __getblk_gfp -->discard_buffer clear BH_Mapped flag __bread_slow submit_bh submit_bh_wbc BUG_ON(!buffer_mapped(bh)) --> hit this BUG_ON Fixes: 5db470e229e2 ("loop: drop caches if offset or block_size are changed") Signed-off-by: Zheng Bin Reviewed-by: Christoph Hellwig Reviewed-by: Bart Van Assche Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/loop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 453e3728e657..c6157ccb9498 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1110,7 +1110,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) if (lo->lo_offset != info->lo_offset || lo->lo_sizelimit != info->lo_sizelimit) { sync_blockdev(lo->lo_device); - kill_bdev(lo->lo_device); + invalidate_bdev(lo->lo_device); } /* I/O need to be drained during transfer transition */ @@ -1380,12 +1380,12 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg) if (lo->lo_queue->limits.logical_block_size != arg) { sync_blockdev(lo->lo_device); - kill_bdev(lo->lo_device); + invalidate_bdev(lo->lo_device); } blk_mq_freeze_queue(lo->lo_queue); - /* kill_bdev should have truncated all the pages */ + /* invalidate_bdev should have truncated all the pages */ if (lo->lo_queue->limits.logical_block_size != arg && lo->lo_device->bd_inode->i_mapping->nrpages) { err = -EAGAIN; From db8971309faeb7408bc8ac3d405aea8fe6e4aeb5 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Thu, 16 Nov 2017 17:35:17 +0100 Subject: [PATCH 151/208] ALSA: usb-audio: uac1: Invalidate ctl on interrupt [ Upstream commit b2500b584cfd228d67e1e43daf27c8af865b499e ] When an interrupt occurs, the value of at least one of the belonging controls should have changed. To make sure they get re-read from device on the next read, invalidate the cache. This was correctly implemented for uac2 already, but missing for uac1. Signed-off-by: Julian Scheel Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/usb/mixer.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index dbbc5609b453..33deb5ec8b7a 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2403,9 +2403,14 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) { struct usb_mixer_elem_list *list; - for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) + for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) { + struct usb_mixer_elem_info *info = + (struct usb_mixer_elem_info *)list; + /* invalidate cache, so the value is read from the device */ + info->cached = 0; snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &list->kctl->id); + } } static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer, From caa09db16ce9dce014af8f7b23a474f8846491ba Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 3 May 2018 12:33:32 +0200 Subject: [PATCH 152/208] ALSA: usb-audio: Clean up mixer element list traverse [ Upstream commit 8c558076c740e8009a96c6fdc3d4245dde62be77 ] Introduce a new macro for iterating over mixer element list for avoiding the open codes in many places. Also the open-coded container_of() and the forced cast to struct usb_mixer_elem_info are replaced with another simple macro, too. No functional changes but just readability improvement. Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/usb/mixer.c | 20 +++++++++----------- sound/usb/mixer.h | 6 ++++++ sound/usb/mixer_quirks.c | 2 +- sound/usb/mixer_scarlett.c | 6 ++---- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 33deb5ec8b7a..1a8d706491e6 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2403,9 +2403,9 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) { struct usb_mixer_elem_list *list; - for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) { + for_each_mixer_elem(list, mixer, unitid) { struct usb_mixer_elem_info *info = - (struct usb_mixer_elem_info *)list; + mixer_elem_list_to_info(list); /* invalidate cache, so the value is read from the device */ info->cached = 0; snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, @@ -2416,7 +2416,7 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer, struct usb_mixer_elem_list *list) { - struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list; + struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list); static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN", "S8", "U8", "S16", "U16"}; snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, " @@ -2442,8 +2442,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry, mixer->ignore_ctl_error); snd_iprintf(buffer, "Card: %s\n", chip->card->longname); for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { - for (list = mixer->id_elems[unitid]; list; - list = list->next_id_elem) { + for_each_mixer_elem(list, mixer, unitid) { snd_iprintf(buffer, " Unit: %i\n", list->id); if (list->kctl) snd_iprintf(buffer, @@ -2473,19 +2472,19 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, return; } - for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) + for_each_mixer_elem(list, mixer, unitid) count++; if (count == 0) return; - for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) { + for_each_mixer_elem(list, mixer, unitid) { struct usb_mixer_elem_info *info; if (!list->kctl) continue; - info = (struct usb_mixer_elem_info *)list; + info = mixer_elem_list_to_info(list); if (count > 1 && info->control != control) continue; @@ -2705,7 +2704,7 @@ int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer) static int restore_mixer_value(struct usb_mixer_elem_list *list) { - struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list; + struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list); int c, err, idx; if (cval->cmask) { @@ -2741,8 +2740,7 @@ int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume) if (reset_resume) { /* restore cached mixer values */ for (id = 0; id < MAX_ID_ELEMS; id++) { - for (list = mixer->id_elems[id]; list; - list = list->next_id_elem) { + for_each_mixer_elem(list, mixer, id) { if (list->resume) { err = list->resume(list); if (err < 0) diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index ba27f7ade670..e02653465e29 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -53,6 +53,12 @@ struct usb_mixer_elem_list { usb_mixer_elem_resume_func_t resume; }; +/* iterate over mixer element list of the given unit id */ +#define for_each_mixer_elem(list, mixer, id) \ + for ((list) = (mixer)->id_elems[id]; (list); (list) = (list)->next_id_elem) +#define mixer_elem_list_to_info(list) \ + container_of(list, struct usb_mixer_elem_info, head) + struct usb_mixer_elem_info { struct usb_mixer_elem_list head; unsigned int control; /* CS or ICN (high byte) */ diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index b9ea4a42aee4..ead0456a747c 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -1171,7 +1171,7 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, int unitid = 12; /* SamleRate ExtensionUnit ID */ list_for_each_entry(mixer, &chip->mixer_list, list) { - cval = (struct usb_mixer_elem_info *)mixer->id_elems[unitid]; + cval = mixer_elem_list_to_info(mixer->id_elems[unitid]); if (cval) { snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, cval->control << 8, diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c index c33e2378089d..4aeb9488a0c9 100644 --- a/sound/usb/mixer_scarlett.c +++ b/sound/usb/mixer_scarlett.c @@ -287,8 +287,7 @@ static int scarlett_ctl_switch_put(struct snd_kcontrol *kctl, static int scarlett_ctl_resume(struct usb_mixer_elem_list *list) { - struct usb_mixer_elem_info *elem = - container_of(list, struct usb_mixer_elem_info, head); + struct usb_mixer_elem_info *elem = mixer_elem_list_to_info(list); int i; for (i = 0; i < elem->channels; i++) @@ -447,8 +446,7 @@ static int scarlett_ctl_enum_put(struct snd_kcontrol *kctl, static int scarlett_ctl_enum_resume(struct usb_mixer_elem_list *list) { - struct usb_mixer_elem_info *elem = - container_of(list, struct usb_mixer_elem_info, head); + struct usb_mixer_elem_info *elem = mixer_elem_list_to_info(list); if (elem->cached) snd_usb_set_cur_mix_value(elem, 0, 0, *elem->cache_val); From 0f7315789b33d14ea79d0914c98391091b7ac8aa Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 24 Jun 2020 14:23:40 +0200 Subject: [PATCH 153/208] ALSA: usb-audio: Fix OOB access of mixer element list [ Upstream commit 220345e98f1cdc768eeb6e3364a0fa7ab9647fe7 ] The USB-audio mixer code holds a linked list of usb_mixer_elem_list, and several operations are performed for each mixer element. A few of them (snd_usb_mixer_notify_id() and snd_usb_mixer_interrupt_v2()) assume each mixer element being a usb_mixer_elem_info object that is a subclass of usb_mixer_elem_list, cast via container_of() and access it members. This may result in an out-of-bound access when a non-standard list element has been added, as spotted by syzkaller recently. This patch adds a new field, is_std_info, in usb_mixer_elem_list to indicate that the element is the usb_mixer_elem_info type or not, and skip the access to such an element if needed. Reported-by: syzbot+fb14314433463ad51625@syzkaller.appspotmail.com Reported-by: syzbot+2405ca3401e943c538b5@syzkaller.appspotmail.com Cc: Link: https://lore.kernel.org/r/20200624122340.9615-1-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/usb/mixer.c | 15 +++++++++++---- sound/usb/mixer.h | 9 +++++++-- sound/usb/mixer_quirks.c | 3 ++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 1a8d706491e6..b29a3546ab6a 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -591,8 +591,9 @@ static int check_matrix_bitmap(unsigned char *bmap, * if failed, give up and free the control instance. */ -int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list, - struct snd_kcontrol *kctl) +int snd_usb_mixer_add_list(struct usb_mixer_elem_list *list, + struct snd_kcontrol *kctl, + bool is_std_info) { struct usb_mixer_interface *mixer = list->mixer; int err; @@ -605,6 +606,7 @@ int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list, return err; } list->kctl = kctl; + list->is_std_info = is_std_info; list->next_id_elem = mixer->id_elems[list->id]; mixer->id_elems[list->id] = list; return 0; @@ -2404,8 +2406,11 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) struct usb_mixer_elem_list *list; for_each_mixer_elem(list, mixer, unitid) { - struct usb_mixer_elem_info *info = - mixer_elem_list_to_info(list); + struct usb_mixer_elem_info *info; + + if (!list->is_std_info) + continue; + info = mixer_elem_list_to_info(list); /* invalidate cache, so the value is read from the device */ info->cached = 0; snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, @@ -2483,6 +2488,8 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, if (!list->kctl) continue; + if (!list->is_std_info) + continue; info = mixer_elem_list_to_info(list); if (count > 1 && info->control != control) diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index e02653465e29..7c824a44589b 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -49,6 +49,7 @@ struct usb_mixer_elem_list { struct usb_mixer_elem_list *next_id_elem; /* list of controls with same id */ struct snd_kcontrol *kctl; unsigned int id; + bool is_std_info; usb_mixer_elem_dump_func_t dump; usb_mixer_elem_resume_func_t resume; }; @@ -86,8 +87,12 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid); int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int value_set); -int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list, - struct snd_kcontrol *kctl); +int snd_usb_mixer_add_list(struct usb_mixer_elem_list *list, + struct snd_kcontrol *kctl, + bool is_std_info); + +#define snd_usb_mixer_add_control(list, kctl) \ + snd_usb_mixer_add_list(list, kctl, true) void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list, struct usb_mixer_interface *mixer, diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index ead0456a747c..5604cce30a58 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -169,7 +169,8 @@ static int add_single_ctl_with_resume(struct usb_mixer_interface *mixer, return -ENOMEM; } kctl->private_free = snd_usb_mixer_elem_free; - return snd_usb_mixer_add_control(list, kctl); + /* don't use snd_usb_mixer_add_control() here, this is a special list element */ + return snd_usb_mixer_add_list(list, kctl, false); } /* From 2b4f83cca72c34a1694a0e55193874728c30041e Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Wed, 24 Jun 2020 16:59:49 +0300 Subject: [PATCH 154/208] xhci: Poll for U0 after disabling USB2 LPM [ Upstream commit b3d71abd135e6919ca0b6cab463738472653ddfb ] USB2 devices with LPM enabled may interrupt the system suspend: [ 932.510475] usb 1-7: usb suspend, wakeup 0 [ 932.510549] hub 1-0:1.0: hub_suspend [ 932.510581] usb usb1: bus suspend, wakeup 0 [ 932.510590] xhci_hcd 0000:00:14.0: port 9 not suspended [ 932.510593] xhci_hcd 0000:00:14.0: port 8 not suspended .. [ 932.520323] xhci_hcd 0000:00:14.0: Port change event, 1-7, id 7, portsc: 0x400e03 .. [ 932.591405] PM: pci_pm_suspend(): hcd_pci_suspend+0x0/0x30 returns -16 [ 932.591414] PM: dpm_run_callback(): pci_pm_suspend+0x0/0x160 returns -16 [ 932.591418] PM: Device 0000:00:14.0 failed to suspend async: error -16 During system suspend, USB core will let HC suspends the device if it doesn't have remote wakeup enabled and doesn't have any children. However, from the log above we can see that the usb 1-7 doesn't get bus suspended due to not in U0. After a while the port finished U2 -> U0 transition, interrupts the suspend process. The observation is that after disabling LPM, port doesn't transit to U0 immediately and can linger in U2. xHCI spec 4.23.5.2 states that the maximum exit latency for USB2 LPM should be BESL + 10us. The BESL for the affected device is advertised as 400us, which is still not enough based on my testing result. So let's use the maximum permitted latency, 10000, to poll for U0 status to solve the issue. Cc: stable@vger.kernel.org Signed-off-by: Kai-Heng Feng Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20200624135949.22611-6-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/usb/host/xhci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d727cbbad44a..cdf1c9155403 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4226,6 +4226,9 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, mutex_lock(hcd->bandwidth_mutex); xhci_change_max_exit_latency(xhci, udev, 0); mutex_unlock(hcd->bandwidth_mutex); + readl_poll_timeout(port_array[port_num], pm_val, + (pm_val & PORT_PLS_MASK) == XDEV_U0, + 100, 10000); return 0; } } From c602de22d93b0134bee32cf334bd3220552dba75 Mon Sep 17 00:00:00 2001 From: Zhang Xiaoxu Date: Tue, 23 Jun 2020 07:31:53 -0400 Subject: [PATCH 155/208] cifs/smb3: Fix data inconsistent when punch hole [ Upstream commit acc91c2d8de4ef46ed751c5f9df99ed9a109b100 ] When punch hole success, we also can read old data from file: # strace -e trace=pread64,fallocate xfs_io -f -c "pread 20 40" \ -c "fpunch 20 40" -c"pread 20 40" file pread64(3, " version 5.8.0-rc1+"..., 40, 20) = 40 fallocate(3, FALLOC_FL_KEEP_SIZE|FALLOC_FL_PUNCH_HOLE, 20, 40) = 0 pread64(3, " version 5.8.0-rc1+"..., 40, 20) = 40 CIFS implements the fallocate(FALLOCATE_FL_PUNCH_HOLE) with send SMB ioctl(FSCTL_SET_ZERO_DATA) to server. It just set the range of the remote file to zero, but local page caches not updated, then the local page caches inconsistent with server. Also can be found by xfstests generic/316. So, we need to remove the page caches before send the SMB ioctl(FSCTL_SET_ZERO_DATA) to server. Fixes: 31742c5a33176 ("enable fallocate punch hole ("fallocate -p") for SMB3") Suggested-by: Pavel Shilovsky Reviewed-by: Pavel Shilovsky Signed-off-by: Zhang Xiaoxu Cc: stable@vger.kernel.org # v3.17 Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/cifs/smb2ops.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 951c444d83e7..61ea429e1210 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1824,6 +1824,12 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, return rc; } + /* + * We implement the punch hole through ioctl, so we need remove the page + * caches first, otherwise the data may be inconsistent with the server. + */ + truncate_pagecache_range(inode, offset, offset + len - 1); + cifs_dbg(FYI, "offset %lld len %lld", offset, len); fsctl_buf.FileOffset = cpu_to_le64(offset); From a174c8680117a17b30a8c54b3f2a62d5eff8cfe5 Mon Sep 17 00:00:00 2001 From: Zhang Xiaoxu Date: Tue, 23 Jun 2020 07:31:54 -0400 Subject: [PATCH 156/208] cifs/smb3: Fix data inconsistent when zero file range [ Upstream commit 6b69040247e14b43419a520f841f2b3052833df9 ] CIFS implements the fallocate(FALLOC_FL_ZERO_RANGE) with send SMB ioctl(FSCTL_SET_ZERO_DATA) to server. It just set the range of the remote file to zero, but local page cache not update, then the data inconsistent with server, which leads the xfstest generic/008 failed. So we need to remove the local page caches before send SMB ioctl(FSCTL_SET_ZERO_DATA) to server. After next read, it will re-cache it. Fixes: 30175628bf7f5 ("[SMB3] Enable fallocate -z support for SMB3 mounts") Reported-by: Hulk Robot Signed-off-by: Zhang Xiaoxu Reviewed-by: Pavel Shilovsky Cc: stable@vger.kernel.org # v3.17 Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/cifs/smb2ops.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 61ea429e1210..b46fdb2b8d34 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1755,6 +1755,12 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, inode = d_inode(cfile->dentry); cifsi = CIFS_I(inode); + /* + * We zero the range through ioctl, so we need remove the page caches + * first, otherwise the data may be inconsistent with the server. + */ + truncate_pagecache_range(inode, offset, offset + len - 1); + /* if file not oplocked can't be sure whether asking to extend size */ if (!CIFS_CACHE_READ(cifsi)) if (keep_size == false) { From cebee7673e1f366259fa96b4e29b1fd23e3f3b41 Mon Sep 17 00:00:00 2001 From: Qiushi Wu Date: Thu, 28 May 2020 13:38:04 -0500 Subject: [PATCH 157/208] efi/esrt: Fix reference count leak in esre_create_sysfs_entry. [ Upstream commit 4ddf4739be6e375116c375f0a68bf3893ffcee21 ] kobject_init_and_add() takes reference even when it fails. If this function returns an error, kobject_put() must be called to properly clean up the memory associated with the object. Previous commit "b8eb718348b8" fixed a similar problem. Fixes: 0bb549052d33 ("efi: Add esrt support") Signed-off-by: Qiushi Wu Link: https://lore.kernel.org/r/20200528183804.4497-1-wu000273@umn.edu Signed-off-by: Ard Biesheuvel Signed-off-by: Sasha Levin --- drivers/firmware/efi/esrt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c index f3c28777b8c6..deb1d8f3bdc8 100644 --- a/drivers/firmware/efi/esrt.c +++ b/drivers/firmware/efi/esrt.c @@ -180,7 +180,7 @@ static int esre_create_sysfs_entry(void *esre, int entry_num) rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL, "entry%d", entry_num); if (rc) { - kfree(entry); + kobject_put(&entry->kobj); return rc; } } From 1688ebca900399d428676e779be5234f055ec0e8 Mon Sep 17 00:00:00 2001 From: Matthew Hagan Date: Sun, 14 Jun 2020 15:19:00 -0700 Subject: [PATCH 158/208] ARM: dts: NSP: Correct FA2 mailbox node [ Upstream commit ac4e106d8934a5894811fc263f4b03fc8ed0fb7a ] The FA2 mailbox is specified at 0x18025000 but should actually be 0x18025c00, length 0x400 according to socregs_nsp.h and board_bu.c. Also the interrupt was off by one and should be GIC SPI 151 instead of 150. Fixes: 17d517172300 ("ARM: dts: NSP: Add mailbox (PDC) to NSP") Signed-off-by: Matthew Hagan Signed-off-by: Florian Fainelli Signed-off-by: Sasha Levin --- arch/arm/boot/dts/bcm-nsp.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi index 1792192001a2..e975f9cabe84 100644 --- a/arch/arm/boot/dts/bcm-nsp.dtsi +++ b/arch/arm/boot/dts/bcm-nsp.dtsi @@ -249,10 +249,10 @@ status = "disabled"; }; - mailbox: mailbox@25000 { + mailbox: mailbox@25c00 { compatible = "brcm,iproc-fa2-mbox"; - reg = <0x25000 0x445>; - interrupts = ; + reg = <0x25c00 0x400>; + interrupts = ; #mbox-cells = <1>; brcm,rx-status-len = <32>; brcm,use-bcm-hdr; From 9cdc893472eedd97334c29f9c65b35a7513d4960 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 17 Jun 2020 23:01:23 +0100 Subject: [PATCH 159/208] rxrpc: Fix handling of rwind from an ACK packet [ Upstream commit a2ad7c21ad8cf1ce4ad65e13df1c2a1c29b38ac5 ] The handling of the receive window size (rwind) from a received ACK packet is not correct. The rxrpc_input_ackinfo() function currently checks the current Tx window size against the rwind from the ACK to see if it has changed, but then limits the rwind size before storing it in the tx_winsize member and, if it increased, wake up the transmitting process. This means that if rwind > RXRPC_RXTX_BUFF_SIZE - 1, this path will always be followed. Fix this by limiting rwind before we compare it to tx_winsize. The effect of this can be seen by enabling the rxrpc_rx_rwind_change tracepoint. Fixes: 702f2ac87a9a ("rxrpc: Wake up the transmitter if Rx window size increases on the peer") Signed-off-by: David Howells Signed-off-by: Sasha Levin --- net/rxrpc/input.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index 18ce6f97462b..98285b117a7c 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c @@ -664,13 +664,12 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb, ntohl(ackinfo->rxMTU), ntohl(ackinfo->maxMTU), rwind, ntohl(ackinfo->jumbo_max)); + if (rwind > RXRPC_RXTX_BUFF_SIZE - 1) + rwind = RXRPC_RXTX_BUFF_SIZE - 1; if (call->tx_winsize != rwind) { - if (rwind > RXRPC_RXTX_BUFF_SIZE - 1) - rwind = RXRPC_RXTX_BUFF_SIZE - 1; if (rwind > call->tx_winsize) wake = true; - trace_rxrpc_rx_rwind_change(call, sp->hdr.serial, - ntohl(ackinfo->rwind), wake); + trace_rxrpc_rx_rwind_change(call, sp->hdr.serial, rwind, wake); call->tx_winsize = rwind; } From b6c4066a2b2a4f550144c8d8fe05f512bddf08b0 Mon Sep 17 00:00:00 2001 From: Mark Zhang Date: Tue, 16 Jun 2020 13:43:04 +0300 Subject: [PATCH 160/208] RDMA/cma: Protect bind_list and listen_list while finding matching cm id [ Upstream commit 730c8912484186d4623d0c76509066d285c3a755 ] The bind_list and listen_list must be accessed under a lock, add the missing locking around the access in cm_ib_id_from_event() In addition add lockdep asserts to make it clearer what the locking semantic is here. general protection fault: 0000 [#1] SMP NOPTI CPU: 226 PID: 126135 Comm: kworker/226:1 Tainted: G OE 4.12.14-150.47-default #1 SLE15 Hardware name: Cray Inc. Windom/Windom, BIOS 0.8.7 01-10-2020 Workqueue: ib_cm cm_work_handler [ib_cm] task: ffff9c5a60a1d2c0 task.stack: ffffc1d91f554000 RIP: 0010:cma_ib_req_handler+0x3f1/0x11b0 [rdma_cm] RSP: 0018:ffffc1d91f557b40 EFLAGS: 00010286 RAX: deacffffffffff30 RBX: 0000000000000001 RCX: ffff9c2af5bb6000 RDX: 00000000000000a9 RSI: ffff9c5aa4ed2f10 RDI: ffffc1d91f557b08 RBP: ffffc1d91f557d90 R08: ffff9c340cc80000 R09: ffff9c2c0f901900 R10: 0000000000000000 R11: 0000000000000001 R12: deacffffffffff30 R13: ffff9c5a48aeec00 R14: ffffc1d91f557c30 R15: ffff9c5c2eea3688 FS: 0000000000000000(0000) GS:ffff9c5c2fa80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00002b5cc03fa320 CR3: 0000003f8500a000 CR4: 00000000003406e0 Call Trace: ? rdma_addr_cancel+0xa0/0xa0 [ib_core] ? cm_process_work+0x28/0x140 [ib_cm] cm_process_work+0x28/0x140 [ib_cm] ? cm_get_bth_pkey.isra.44+0x34/0xa0 [ib_cm] cm_work_handler+0xa06/0x1a6f [ib_cm] ? __switch_to_asm+0x34/0x70 ? __switch_to_asm+0x34/0x70 ? __switch_to_asm+0x40/0x70 ? __switch_to_asm+0x34/0x70 ? __switch_to_asm+0x40/0x70 ? __switch_to_asm+0x34/0x70 ? __switch_to_asm+0x40/0x70 ? __switch_to+0x7c/0x4b0 ? __switch_to_asm+0x40/0x70 ? __switch_to_asm+0x34/0x70 process_one_work+0x1da/0x400 worker_thread+0x2b/0x3f0 ? process_one_work+0x400/0x400 kthread+0x118/0x140 ? kthread_create_on_node+0x40/0x40 ret_from_fork+0x22/0x40 Code: 00 66 83 f8 02 0f 84 ca 05 00 00 49 8b 84 24 d0 01 00 00 48 85 c0 0f 84 68 07 00 00 48 2d d0 01 00 00 49 89 c4 0f 84 59 07 00 00 <41> 0f b7 44 24 20 49 8b 77 50 66 83 f8 0a 75 9e 49 8b 7c 24 28 Fixes: 4c21b5bcef73 ("IB/cma: Add net_dev and private data checks to RDMA CM") Link: https://lore.kernel.org/r/20200616104304.2426081-1-leon@kernel.org Signed-off-by: Mark Zhang Reviewed-by: Maor Gottlieb Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe Signed-off-by: Sasha Levin --- drivers/infiniband/core/cma.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index d901591db9c8..6e8af2b91492 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1482,6 +1482,8 @@ static struct rdma_id_private *cma_find_listener( { struct rdma_id_private *id_priv, *id_priv_dev; + lockdep_assert_held(&lock); + if (!bind_list) return ERR_PTR(-EINVAL); @@ -1530,6 +1532,7 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id, } } + mutex_lock(&lock); /* * Net namespace might be getting deleted while route lookup, * cm_id lookup is in progress. Therefore, perform netdevice @@ -1571,6 +1574,7 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id, id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev); err: rcu_read_unlock(); + mutex_unlock(&lock); if (IS_ERR(id_priv) && *net_dev) { dev_put(*net_dev); *net_dev = NULL; @@ -2287,6 +2291,8 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv, struct net *net = id_priv->id.route.addr.dev_addr.net; int ret; + lockdep_assert_held(&lock); + if (cma_family(id_priv) == AF_IB && !rdma_cap_ib_cm(cma_dev->device, 1)) return; @@ -2993,6 +2999,8 @@ static void cma_bind_port(struct rdma_bind_list *bind_list, u64 sid, mask; __be16 port; + lockdep_assert_held(&lock); + addr = cma_src_addr(id_priv); port = htons(bind_list->port); @@ -3021,6 +3029,8 @@ static int cma_alloc_port(enum rdma_port_space ps, struct rdma_bind_list *bind_list; int ret; + lockdep_assert_held(&lock); + bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL); if (!bind_list) return -ENOMEM; @@ -3047,6 +3057,8 @@ static int cma_port_is_unique(struct rdma_bind_list *bind_list, struct sockaddr *saddr = cma_src_addr(id_priv); __be16 dport = cma_port(daddr); + lockdep_assert_held(&lock); + hlist_for_each_entry(cur_id, &bind_list->owners, node) { struct sockaddr *cur_daddr = cma_dst_addr(cur_id); struct sockaddr *cur_saddr = cma_src_addr(cur_id); @@ -3086,6 +3098,8 @@ static int cma_alloc_any_port(enum rdma_port_space ps, unsigned int rover; struct net *net = id_priv->id.route.addr.dev_addr.net; + lockdep_assert_held(&lock); + inet_get_local_port_range(net, &low, &high); remaining = (high - low) + 1; rover = prandom_u32() % remaining + low; @@ -3133,6 +3147,8 @@ static int cma_check_port(struct rdma_bind_list *bind_list, struct rdma_id_private *cur_id; struct sockaddr *addr, *cur_addr; + lockdep_assert_held(&lock); + addr = cma_src_addr(id_priv); hlist_for_each_entry(cur_id, &bind_list->owners, node) { if (id_priv == cur_id) @@ -3163,6 +3179,8 @@ static int cma_use_port(enum rdma_port_space ps, unsigned short snum; int ret; + lockdep_assert_held(&lock); + snum = ntohs(cma_port(cma_src_addr(id_priv))); if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) return -EACCES; From 5ef8e112ddac71c11f9519067fb920a7595190f3 Mon Sep 17 00:00:00 2001 From: Qiushi Wu Date: Sat, 13 Jun 2020 15:51:58 -0500 Subject: [PATCH 161/208] ASoC: rockchip: Fix a reference count leak. [ Upstream commit f141a422159a199f4c8dedb7e0df55b3b2cf16cd ] Calling pm_runtime_get_sync increments the counter even in case of failure, causing incorrect ref count if pm_runtime_put is not called in error handling paths. Call pm_runtime_put if pm_runtime_get_sync fails. Fixes: fc05a5b22253 ("ASoC: rockchip: add support for pdm controller") Signed-off-by: Qiushi Wu Reviewed-by: Heiko Stuebner Link: https://lore.kernel.org/r/20200613205158.27296-1-wu000273@umn.edu Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/rockchip/rockchip_pdm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index 8a2e3bbce3a1..ad16c8310dd3 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -478,8 +478,10 @@ static int rockchip_pdm_resume(struct device *dev) int ret; ret = pm_runtime_get_sync(dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put(dev); return ret; + } ret = regcache_sync(pdm->regmap); From 1e865dd2d489ce2659484aa133189b05130eb13e Mon Sep 17 00:00:00 2001 From: Fan Guo Date: Fri, 12 Jun 2020 14:38:24 +0800 Subject: [PATCH 162/208] RDMA/mad: Fix possible memory leak in ib_mad_post_receive_mads() [ Upstream commit a17f4bed811c60712d8131883cdba11a105d0161 ] If ib_dma_mapping_error() returns non-zero value, ib_mad_post_receive_mads() will jump out of loops and return -ENOMEM without freeing mad_priv. Fix this memory-leak problem by freeing mad_priv in this case. Fixes: 2c34e68f4261 ("IB/mad: Check and handle potential DMA mapping errors") Link: https://lore.kernel.org/r/20200612063824.180611-1-guofan5@huawei.com Signed-off-by: Fan Guo Signed-off-by: Jason Gunthorpe Signed-off-by: Sasha Levin --- drivers/infiniband/core/mad.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 6072ac7023cb..08d2e9cc28eb 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -2907,6 +2907,7 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, DMA_FROM_DEVICE); if (unlikely(ib_dma_mapping_error(qp_info->port_priv->device, sg_list.addr))) { + kfree(mad_priv); ret = -ENOMEM; break; } From 04fcef5c3c2bd4d8602780d9bb0dcf564a2ea47c Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Tue, 23 Jun 2020 16:51:29 +0300 Subject: [PATCH 163/208] net: qed: fix left elements count calculation [ Upstream commit 97dd1abd026ae4e6a82fa68645928404ad483409 ] qed_chain_get_element_left{,_u32} returned 0 when the difference between producer and consumer page count was equal to the total page count. Fix this by conditional expanding of producer value (vs unconditional). This allowed to eliminate normalizaton against total page count, which was the cause of this bug. Misc: replace open-coded constants with common defines. Fixes: a91eb52abb50 ("qed: Revisit chain implementation") Signed-off-by: Alexander Lobakin Signed-off-by: Igor Russkikh Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- include/linux/qed/qed_chain.h | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/include/linux/qed/qed_chain.h b/include/linux/qed/qed_chain.h index 733fad7dfbed..6d15040c642c 100644 --- a/include/linux/qed/qed_chain.h +++ b/include/linux/qed/qed_chain.h @@ -207,28 +207,34 @@ static inline u32 qed_chain_get_cons_idx_u32(struct qed_chain *p_chain) static inline u16 qed_chain_get_elem_left(struct qed_chain *p_chain) { + u16 elem_per_page = p_chain->elem_per_page; + u32 prod = p_chain->u.chain16.prod_idx; + u32 cons = p_chain->u.chain16.cons_idx; u16 used; - used = (u16) (((u32)0x10000 + - (u32)p_chain->u.chain16.prod_idx) - - (u32)p_chain->u.chain16.cons_idx); + if (prod < cons) + prod += (u32)U16_MAX + 1; + + used = (u16)(prod - cons); if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR) - used -= p_chain->u.chain16.prod_idx / p_chain->elem_per_page - - p_chain->u.chain16.cons_idx / p_chain->elem_per_page; + used -= prod / elem_per_page - cons / elem_per_page; return (u16)(p_chain->capacity - used); } static inline u32 qed_chain_get_elem_left_u32(struct qed_chain *p_chain) { + u16 elem_per_page = p_chain->elem_per_page; + u64 prod = p_chain->u.chain32.prod_idx; + u64 cons = p_chain->u.chain32.cons_idx; u32 used; - used = (u32) (((u64)0x100000000ULL + - (u64)p_chain->u.chain32.prod_idx) - - (u64)p_chain->u.chain32.cons_idx); + if (prod < cons) + prod += (u64)U32_MAX + 1; + + used = (u32)(prod - cons); if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR) - used -= p_chain->u.chain32.prod_idx / p_chain->elem_per_page - - p_chain->u.chain32.cons_idx / p_chain->elem_per_page; + used -= (u32)(prod / elem_per_page - cons / elem_per_page); return p_chain->capacity - used; } From b8fa3e8db10b5464f8757c41b37bc3268489eebe Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Tue, 23 Jun 2020 16:51:32 +0300 Subject: [PATCH 164/208] net: qed: fix NVMe login fails over VFs [ Upstream commit ccd7c7ce167a21dbf2b698ffcf00f11d96d44f9b ] 25ms sleep cycles in waiting for PF response are excessive and may lead to different timeout failures. Start to wait with short udelays, and in most cases polling will end here. If the time was not sufficient, switch to msleeps. usleep_range() may go far beyond 100us depending on platform and tick configuration, hence atomic udelays for consistency. Also add explicit DMA barriers since 'done' always comes from a shared request-response DMA pool, and note that in the comment nearby. Fixes: 1408cc1fa48c ("qed: Introduce VFs") Signed-off-by: Alexander Lobakin Signed-off-by: Igor Russkikh Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/qlogic/qed/qed_vf.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c index a2a9921b467b..693f2a039383 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_vf.c +++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c @@ -81,12 +81,17 @@ static void qed_vf_pf_req_end(struct qed_hwfn *p_hwfn, int req_status) mutex_unlock(&(p_hwfn->vf_iov_info->mutex)); } +#define QED_VF_CHANNEL_USLEEP_ITERATIONS 90 +#define QED_VF_CHANNEL_USLEEP_DELAY 100 +#define QED_VF_CHANNEL_MSLEEP_ITERATIONS 10 +#define QED_VF_CHANNEL_MSLEEP_DELAY 25 + static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size) { union vfpf_tlvs *p_req = p_hwfn->vf_iov_info->vf2pf_request; struct ustorm_trigger_vf_zone trigger; struct ustorm_vf_zone *zone_data; - int rc = 0, time = 100; + int iter, rc = 0; zone_data = (struct ustorm_vf_zone *)PXP_VF_BAR0_START_USDM_ZONE_B; @@ -126,11 +131,19 @@ static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size) REG_WR(p_hwfn, (uintptr_t)&zone_data->trigger, *((u32 *)&trigger)); /* When PF would be done with the response, it would write back to the - * `done' address. Poll until then. + * `done' address from a coherent DMA zone. Poll until then. */ - while ((!*done) && time) { - msleep(25); - time--; + + iter = QED_VF_CHANNEL_USLEEP_ITERATIONS; + while (!*done && iter--) { + udelay(QED_VF_CHANNEL_USLEEP_DELAY); + dma_rmb(); + } + + iter = QED_VF_CHANNEL_MSLEEP_ITERATIONS; + while (!*done && iter--) { + msleep(QED_VF_CHANNEL_MSLEEP_DELAY); + dma_rmb(); } if (!*done) { From 24495b2bcd0bf49d195481073932d23e9b737005 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Tue, 23 Jun 2020 16:51:33 +0300 Subject: [PATCH 165/208] net: qed: fix excessive QM ILT lines consumption [ Upstream commit d434d02f7e7c24c721365fd594ed781acb18e0da ] This is likely a copy'n'paste mistake. The amount of ILT lines to reserve for a single VF was being multiplied by the total VFs count. This led to a huge redundancy in reservation and potential lines drainouts. Fixes: 1408cc1fa48c ("qed: Introduce VFs") Signed-off-by: Alexander Lobakin Signed-off-by: Igor Russkikh Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/qlogic/qed/qed_cxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c index 27ba476f761d..4fc3468f6f38 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c @@ -396,7 +396,7 @@ static void qed_cxt_qm_iids(struct qed_hwfn *p_hwfn, vf_tids += segs[NUM_TASK_PF_SEGMENTS].count; } - iids->vf_cids += vf_cids * p_mngr->vf_count; + iids->vf_cids = vf_cids; iids->tids += vf_tids * p_mngr->vf_count; DP_VERBOSE(p_hwfn, QED_MSG_ILT, From 9be0376a05b0a80ad073773ad47dbe7f5d5e622f Mon Sep 17 00:00:00 2001 From: yu kuai Date: Thu, 4 Jun 2020 20:42:06 +0800 Subject: [PATCH 166/208] ARM: imx5: add missing put_device() call in imx_suspend_alloc_ocram() [ Upstream commit 586745f1598ccf71b0a5a6df2222dee0a865954e ] if of_find_device_by_node() succeed, imx_suspend_alloc_ocram() doesn't have a corresponding put_device(). Thus add a jump target to fix the exception handling for this function implementation. Fixes: 1579c7b9fe01 ("ARM: imx53: Set DDR pins to high impedance when in suspend to RAM.") Signed-off-by: yu kuai Signed-off-by: Shawn Guo Signed-off-by: Sasha Levin --- arch/arm/mach-imx/pm-imx5.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c index 868781fd460c..14c630c899c5 100644 --- a/arch/arm/mach-imx/pm-imx5.c +++ b/arch/arm/mach-imx/pm-imx5.c @@ -301,14 +301,14 @@ static int __init imx_suspend_alloc_ocram( if (!ocram_pool) { pr_warn("%s: ocram pool unavailable!\n", __func__); ret = -ENODEV; - goto put_node; + goto put_device; } ocram_base = gen_pool_alloc(ocram_pool, size); if (!ocram_base) { pr_warn("%s: unable to alloc ocram!\n", __func__); ret = -ENOMEM; - goto put_node; + goto put_device; } phys = gen_pool_virt_to_phys(ocram_pool, ocram_base); @@ -318,6 +318,8 @@ static int __init imx_suspend_alloc_ocram( if (virt_out) *virt_out = virt; +put_device: + put_device(&pdev->dev); put_node: of_node_put(node); From a861f428586bfa4d09006cb4863e1f4d08d6f9ff Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 15 Jun 2020 14:27:19 +0300 Subject: [PATCH 167/208] usb: gadget: udc: Potential Oops in error handling code [ Upstream commit e55f3c37cb8d31c7e301f46396b2ac6a19eb3a7c ] If this is in "transceiver" mode the the ->qwork isn't required and is a NULL pointer. This can lead to a NULL dereference when we call destroy_workqueue(udc->qwork). Fixes: 3517c31a8ece ("usb: gadget: mv_udc: use devm_xxx for probe") Signed-off-by: Dan Carpenter Signed-off-by: Felipe Balbi Signed-off-by: Sasha Levin --- drivers/usb/gadget/udc/mv_udc_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index 4103bf7cf52a..62fad60d0c06 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c @@ -2317,7 +2317,8 @@ static int mv_udc_probe(struct platform_device *pdev) return 0; err_create_workqueue: - destroy_workqueue(udc->qwork); + if (udc->qwork) + destroy_workqueue(udc->qwork); err_destroy_dma: dma_pool_destroy(udc->dtd_pool); err_free_dma: From 64c4a9d931dede1516d825d76f242f7df929442d Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 10 Jun 2020 21:51:11 +0100 Subject: [PATCH 168/208] netfilter: ipset: fix unaligned atomic access [ Upstream commit 715028460082d07a7ec6fcd87b14b46784346a72 ] When using ip_set with counters and comment, traffic causes the kernel to panic on 32-bit ARM: Alignment trap: not handling instruction e1b82f9f at [] Unhandled fault: alignment exception (0x221) at 0xea08133c PC is at ip_set_match_extensions+0xe0/0x224 [ip_set] The problem occurs when we try to update the 64-bit counters - the faulting address above is not 64-bit aligned. The problem occurs due to the way elements are allocated, for example: set->dsize = ip_set_elem_len(set, tb, 0, 0); map = ip_set_alloc(sizeof(*map) + elements * set->dsize); If the element has a requirement for a member to be 64-bit aligned, and set->dsize is not a multiple of 8, but is a multiple of four, then every odd numbered elements will be misaligned - and hitting an atomic64_add() on that element will cause the kernel to panic. ip_set_elem_len() must return a size that is rounded to the maximum alignment of any extension field stored in the element. This change ensures that is the case. Fixes: 95ad1f4a9358 ("netfilter: ipset: Fix extension alignment") Signed-off-by: Russell King Acked-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- net/netfilter/ipset/ip_set_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index c2b21c9c1229..5c59bbad8d19 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -381,6 +381,8 @@ ip_set_elem_len(struct ip_set *set, struct nlattr *tb[], size_t len, for (id = 0; id < IPSET_EXT_ID_MAX; id++) { if (!add_extension(id, cadt_flags, tb)) continue; + if (align < ip_set_extensions[id].align) + align = ip_set_extensions[id].align; len = ALIGN(len, ip_set_extensions[id].align); set->offset[id] = len; set->extensions |= ip_set_extensions[id].type; From 2a0ef851e1e8626fc6b49b4fba0ffcf012c8870c Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Wed, 24 Jun 2020 18:14:55 -0700 Subject: [PATCH 169/208] net: bcmgenet: use hardware padding of runt frames [ Upstream commit 20d1f2d1b024f6be199a3bedf1578a1d21592bc5 ] When commit 474ea9cafc45 ("net: bcmgenet: correctly pad short packets") added the call to skb_padto() it should have been located before the nr_frags parameter was read since that value could be changed when padding packets with lengths between 55 and 59 bytes (inclusive). The use of a stale nr_frags value can cause corruption of the pad data when tx-scatter-gather is enabled. This corruption of the pad can cause invalid checksum computation when hardware offload of tx-checksum is also enabled. Since the original reason for the padding was corrected by commit 7dd399130efb ("net: bcmgenet: fix skb_len in bcmgenet_xmit_single()") we can remove the software padding all together and make use of hardware padding of short frames as long as the hardware also always appends the FCS value to the frame. Fixes: 474ea9cafc45 ("net: bcmgenet: correctly pad short packets") Signed-off-by: Doug Berger Acked-by: Florian Fainelli Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 7d3cbbd88a00..8bfa2523e253 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1567,11 +1567,6 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) goto out; } - if (skb_padto(skb, ETH_ZLEN)) { - ret = NETDEV_TX_OK; - goto out; - } - /* Retain how many bytes will be sent on the wire, without TSB inserted * by transmit checksum offload */ @@ -1621,6 +1616,9 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) len_stat = (size << DMA_BUFLENGTH_SHIFT) | (priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT); + /* Note: if we ever change from DMA_TX_APPEND_CRC below we + * will need to restore software padding of "runt" packets + */ if (!i) { len_stat |= DMA_TX_APPEND_CRC | DMA_SOP; if (skb->ip_summed == CHECKSUM_PARTIAL) From ea8e50ab0b115ecbace5bf8653c8943c1500ccc0 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Mon, 19 Nov 2018 16:32:01 +0100 Subject: [PATCH 170/208] sched/core: Fix PI boosting between RT and DEADLINE tasks [ Upstream commit 740797ce3a124b7dd22b7fb832d87bc8fba1cf6f ] syzbot reported the following warning: WARNING: CPU: 1 PID: 6351 at kernel/sched/deadline.c:628 enqueue_task_dl+0x22da/0x38a0 kernel/sched/deadline.c:1504 At deadline.c:628 we have: 623 static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se) 624 { 625 struct dl_rq *dl_rq = dl_rq_of_se(dl_se); 626 struct rq *rq = rq_of_dl_rq(dl_rq); 627 628 WARN_ON(dl_se->dl_boosted); 629 WARN_ON(dl_time_before(rq_clock(rq), dl_se->deadline)); [...] } Which means that setup_new_dl_entity() has been called on a task currently boosted. This shouldn't happen though, as setup_new_dl_entity() is only called when the 'dynamic' deadline of the new entity is in the past w.r.t. rq_clock and boosted tasks shouldn't verify this condition. Digging through the PI code I noticed that what above might in fact happen if an RT tasks blocks on an rt_mutex hold by a DEADLINE task. In the first branch of boosting conditions we check only if a pi_task 'dynamic' deadline is earlier than mutex holder's and in this case we set mutex holder to be dl_boosted. However, since RT 'dynamic' deadlines are only initialized if such tasks get boosted at some point (or if they become DEADLINE of course), in general RT 'dynamic' deadlines are usually equal to 0 and this verifies the aforementioned condition. Fix it by checking that the potential donor task is actually (even if temporary because in turn boosted) running at DEADLINE priority before using its 'dynamic' deadline value. Fixes: 2d3d891d3344 ("sched/deadline: Add SCHED_DEADLINE inheritance logic") Reported-by: syzbot+119ba87189432ead09b4@syzkaller.appspotmail.com Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Ingo Molnar Reviewed-by: Daniel Bristot de Oliveira Tested-by: Daniel Wagner Link: https://lkml.kernel.org/r/20181119153201.GB2119@localhost.localdomain Signed-off-by: Sasha Levin --- kernel/sched/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 97a27726ea21..c5599174e745 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3731,7 +3731,8 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task) */ if (dl_prio(prio)) { if (!dl_prio(p->normal_prio) || - (pi_task && dl_entity_preempt(&pi_task->dl, &p->dl))) { + (pi_task && dl_prio(pi_task->prio) && + dl_entity_preempt(&pi_task->dl, &p->dl))) { p->dl.dl_boosted = 1; queue_flag |= ENQUEUE_REPLENISH; } else From a5eda762c897730f2ce7d170846a142b529bde57 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Fri, 5 Jun 2020 09:41:49 +0800 Subject: [PATCH 171/208] ata/libata: Fix usage of page address by page_address in ata_scsi_mode_select_xlat function [ Upstream commit f650ef61e040bcb175dd8762164b00a5d627f20e ] BUG: KASAN: use-after-free in ata_scsi_mode_select_xlat+0x10bd/0x10f0 drivers/ata/libata-scsi.c:4045 Read of size 1 at addr ffff88803b8cd003 by task syz-executor.6/12621 CPU: 1 PID: 12621 Comm: syz-executor.6 Not tainted 4.19.95 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xac/0xee lib/dump_stack.c:118 print_address_description+0x60/0x223 mm/kasan/report.c:253 kasan_report_error mm/kasan/report.c:351 [inline] kasan_report mm/kasan/report.c:409 [inline] kasan_report.cold+0xae/0x2d8 mm/kasan/report.c:393 ata_scsi_mode_select_xlat+0x10bd/0x10f0 drivers/ata/libata-scsi.c:4045 ata_scsi_translate+0x2da/0x680 drivers/ata/libata-scsi.c:2035 __ata_scsi_queuecmd drivers/ata/libata-scsi.c:4360 [inline] ata_scsi_queuecmd+0x2e4/0x790 drivers/ata/libata-scsi.c:4409 scsi_dispatch_cmd+0x2ee/0x6c0 drivers/scsi/scsi_lib.c:1867 scsi_queue_rq+0xfd7/0x1990 drivers/scsi/scsi_lib.c:2170 blk_mq_dispatch_rq_list+0x1e1/0x19a0 block/blk-mq.c:1186 blk_mq_do_dispatch_sched+0x147/0x3d0 block/blk-mq-sched.c:108 blk_mq_sched_dispatch_requests+0x427/0x680 block/blk-mq-sched.c:204 __blk_mq_run_hw_queue+0xbc/0x200 block/blk-mq.c:1308 __blk_mq_delay_run_hw_queue+0x3c0/0x460 block/blk-mq.c:1376 blk_mq_run_hw_queue+0x152/0x310 block/blk-mq.c:1413 blk_mq_sched_insert_request+0x337/0x6c0 block/blk-mq-sched.c:397 blk_execute_rq_nowait+0x124/0x320 block/blk-exec.c:64 blk_execute_rq+0xc5/0x112 block/blk-exec.c:101 sg_scsi_ioctl+0x3b0/0x6a0 block/scsi_ioctl.c:507 sg_ioctl+0xd37/0x23f0 drivers/scsi/sg.c:1106 vfs_ioctl fs/ioctl.c:46 [inline] file_ioctl fs/ioctl.c:501 [inline] do_vfs_ioctl+0xae6/0x1030 fs/ioctl.c:688 ksys_ioctl+0x76/0xa0 fs/ioctl.c:705 __do_sys_ioctl fs/ioctl.c:712 [inline] __se_sys_ioctl fs/ioctl.c:710 [inline] __x64_sys_ioctl+0x6f/0xb0 fs/ioctl.c:710 do_syscall_64+0xa0/0x2e0 arch/x86/entry/common.c:293 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x45c479 Code: ad b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 7b b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007fb0e9602c78 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007fb0e96036d4 RCX: 000000000045c479 RDX: 0000000020000040 RSI: 0000000000000001 RDI: 0000000000000003 RBP: 000000000076bfc0 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff R13: 000000000000046d R14: 00000000004c6e1a R15: 000000000076bfcc Allocated by task 12577: set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc mm/kasan/kasan.c:553 [inline] kasan_kmalloc+0xbf/0xe0 mm/kasan/kasan.c:531 __kmalloc+0xf3/0x1e0 mm/slub.c:3749 kmalloc include/linux/slab.h:520 [inline] load_elf_phdrs+0x118/0x1b0 fs/binfmt_elf.c:441 load_elf_binary+0x2de/0x4610 fs/binfmt_elf.c:737 search_binary_handler fs/exec.c:1654 [inline] search_binary_handler+0x15c/0x4e0 fs/exec.c:1632 exec_binprm fs/exec.c:1696 [inline] __do_execve_file.isra.0+0xf52/0x1a90 fs/exec.c:1820 do_execveat_common fs/exec.c:1866 [inline] do_execve fs/exec.c:1883 [inline] __do_sys_execve fs/exec.c:1964 [inline] __se_sys_execve fs/exec.c:1959 [inline] __x64_sys_execve+0x8a/0xb0 fs/exec.c:1959 do_syscall_64+0xa0/0x2e0 arch/x86/entry/common.c:293 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Freed by task 12577: set_track mm/kasan/kasan.c:460 [inline] __kasan_slab_free+0x129/0x170 mm/kasan/kasan.c:521 slab_free_hook mm/slub.c:1370 [inline] slab_free_freelist_hook mm/slub.c:1397 [inline] slab_free mm/slub.c:2952 [inline] kfree+0x8b/0x1a0 mm/slub.c:3904 load_elf_binary+0x1be7/0x4610 fs/binfmt_elf.c:1118 search_binary_handler fs/exec.c:1654 [inline] search_binary_handler+0x15c/0x4e0 fs/exec.c:1632 exec_binprm fs/exec.c:1696 [inline] __do_execve_file.isra.0+0xf52/0x1a90 fs/exec.c:1820 do_execveat_common fs/exec.c:1866 [inline] do_execve fs/exec.c:1883 [inline] __do_sys_execve fs/exec.c:1964 [inline] __se_sys_execve fs/exec.c:1959 [inline] __x64_sys_execve+0x8a/0xb0 fs/exec.c:1959 do_syscall_64+0xa0/0x2e0 arch/x86/entry/common.c:293 entry_SYSCALL_64_after_hwframe+0x44/0xa9 The buggy address belongs to the object at ffff88803b8ccf00 which belongs to the cache kmalloc-512 of size 512 The buggy address is located 259 bytes inside of 512-byte region [ffff88803b8ccf00, ffff88803b8cd100) The buggy address belongs to the page: page:ffffea0000ee3300 count:1 mapcount:0 mapping:ffff88806cc03080 index:0xffff88803b8cc780 compound_mapcount: 0 flags: 0x100000000008100(slab|head) raw: 0100000000008100 ffffea0001104080 0000000200000002 ffff88806cc03080 raw: ffff88803b8cc780 00000000800c000b 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff88803b8ccf00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff88803b8ccf80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >ffff88803b8cd000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff88803b8cd080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff88803b8cd100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc You can refer to "https://www.lkml.org/lkml/2019/1/17/474" reproduce this error. The exception code is "bd_len = p[3];", "p" value is ffff88803b8cd000 which belongs to the cache kmalloc-512 of size 512. The "page_address(sg_page(scsi_sglist(scmd)))" maybe from sg_scsi_ioctl function "buffer" which allocated by kzalloc, so "buffer" may not page aligned. This also looks completely buggy on highmem systems and really needs to use a kmap_atomic. --Christoph Hellwig To address above bugs, Paolo Bonzini advise to simpler to just make a char array of size CACHE_MPAGE_LEN+8+8+4-2(or just 64 to make it easy), use sg_copy_to_buffer to copy from the sglist into the buffer, and workthere. Signed-off-by: Ye Bin Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- drivers/ata/libata-scsi.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 2f81d6534270..bc2c27f0493f 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3996,12 +3996,13 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) { struct scsi_cmnd *scmd = qc->scsicmd; const u8 *cdb = scmd->cmnd; - const u8 *p; u8 pg, spg; unsigned six_byte, pg_len, hdr_len, bd_len; int len; u16 fp = (u16)-1; u8 bp = 0xff; + u8 buffer[64]; + const u8 *p = buffer; VPRINTK("ENTER\n"); @@ -4035,12 +4036,14 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len) goto invalid_param_len; - p = page_address(sg_page(scsi_sglist(scmd))); - /* Move past header and block descriptors. */ if (len < hdr_len) goto invalid_param_len; + if (!sg_copy_to_buffer(scsi_sglist(scmd), scsi_sg_count(scmd), + buffer, sizeof(buffer))) + goto invalid_param_len; + if (six_byte) bd_len = p[3]; else From 9cef5a5722202e49bac8a07f93d0e74b5501ce86 Mon Sep 17 00:00:00 2001 From: Zekun Shen Date: Mon, 15 Jun 2020 11:50:29 -0400 Subject: [PATCH 172/208] net: alx: fix race condition in alx_remove [ Upstream commit e89df5c4322c1bf495f62d74745895b5fd2a4393 ] There is a race condition exist during termination. The path is alx_stop and then alx_remove. An alx_schedule_link_check could be called before alx_stop by interrupt handler and invoke alx_link_check later. Alx_stop frees the napis, and alx_remove cancels any pending works. If any of the work is scheduled before termination and invoked before alx_remove, a null-ptr-deref occurs because both expect alx->napis[i]. This patch fix the race condition by moving cancel_work_sync functions before alx_free_napis inside alx_stop. Because interrupt handler can call alx_schedule_link_check again, alx_free_irq is moved before cancel_work_sync calls too. Signed-off-by: Zekun Shen Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/atheros/alx/main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index 5e5022fa1d04..85029d43da75 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -1250,8 +1250,12 @@ out_disable_adv_intr: static void __alx_stop(struct alx_priv *alx) { - alx_halt(alx); alx_free_irq(alx); + + cancel_work_sync(&alx->link_check_wk); + cancel_work_sync(&alx->reset_wk); + + alx_halt(alx); alx_free_rings(alx); alx_free_napis(alx); } @@ -1863,9 +1867,6 @@ static void alx_remove(struct pci_dev *pdev) struct alx_priv *alx = pci_get_drvdata(pdev); struct alx_hw *hw = &alx->hw; - cancel_work_sync(&alx->link_check_wk); - cancel_work_sync(&alx->reset_wk); - /* restore permanent mac address */ alx_set_macaddr(hw, hw->perm_addr); From 5f311c5e6476e598bf5b1f448fbcbfad65837b17 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Mon, 9 Mar 2020 16:44:50 +0100 Subject: [PATCH 173/208] s390/ptrace: fix setting syscall number [ Upstream commit 873e5a763d604c32988c4a78913a8dab3862d2f9 ] When strace wants to update the syscall number, it sets GPR2 to the desired number and updates the GPR via PTRACE_SETREGSET. It doesn't update regs->int_code which would cause the old syscall executed on syscall restart. As we cannot change the ptrace ABI and don't have a field for the interruption code, check whether the tracee is in a syscall and the last instruction was svc. In that case assume that the tracer wants to update the syscall number and copy the GPR2 value to regs->int_code. Signed-off-by: Sven Schnelle Signed-off-by: Vasily Gorbik Signed-off-by: Sasha Levin --- arch/s390/kernel/ptrace.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 56e0190d6e65..42e4cd20fbbe 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -322,6 +322,25 @@ static inline void __poke_user_per(struct task_struct *child, child->thread.per_user.end = data; } +static void fixup_int_code(struct task_struct *child, addr_t data) +{ + struct pt_regs *regs = task_pt_regs(child); + int ilc = regs->int_code >> 16; + u16 insn; + + if (ilc > 6) + return; + + if (ptrace_access_vm(child, regs->psw.addr - (regs->int_code >> 16), + &insn, sizeof(insn), FOLL_FORCE) != sizeof(insn)) + return; + + /* double check that tracee stopped on svc instruction */ + if ((insn >> 8) != 0xa) + return; + + regs->int_code = 0x20000 | (data & 0xffff); +} /* * Write a word to the user area of a process at location addr. This * operation does have an additional problem compared to peek_user. @@ -333,7 +352,9 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) struct user *dummy = NULL; addr_t offset; + if (addr < (addr_t) &dummy->regs.acrs) { + struct pt_regs *regs = task_pt_regs(child); /* * psw and gprs are stored on the stack */ @@ -351,7 +372,11 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) /* Invalid addressing mode bits */ return -EINVAL; } - *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data; + + if (test_pt_regs_flag(regs, PIF_SYSCALL) && + addr == offsetof(struct user, regs.gprs[2])) + fixup_int_code(child, data); + *(addr_t *)((addr_t) ®s->psw + addr) = data; } else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) { /* @@ -717,6 +742,10 @@ static int __poke_user_compat(struct task_struct *child, regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) | (__u64)(tmp & PSW32_ADDR_AMODE); } else { + + if (test_pt_regs_flag(regs, PIF_SYSCALL) && + addr == offsetof(struct compat_user, regs.gprs[2])) + fixup_int_code(child, data); /* gpr 0-15 */ *(__u32*)((addr_t) ®s->psw + addr*2 + 4) = tmp; } From b066e9ee99e5660fd25fb95afc62c382fd565ebb Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 14 Jun 2020 23:43:40 +0900 Subject: [PATCH 174/208] kbuild: improve cc-option to clean up all temporary files [ Upstream commit f2f02ebd8f3833626642688b2d2c6a7b3c141fa9 ] When cc-option and friends evaluate compiler flags, the temporary file $$TMP is created as an output object, and automatically cleaned up. The actual file path of $$TMP is ..tmp, here is the process ID of $(shell ...) invoked from cc-option. (Please note $$$$ is the escape sequence of $$). Such garbage files are cleaned up in most cases, but some compiler flags create additional output files. For example, -gsplit-dwarf creates a .dwo file. When CONFIG_DEBUG_INFO_SPLIT=y, you will see a bunch of ..dwo files left in the top of build directories. You may not notice them unless you do 'ls -a', but the garbage files will increase every time you run 'make'. This commit changes the temporary object path to .tmp_/tmp, and removes .tmp_ directory when exiting. Separate build artifacts such as *.dwo will be cleaned up all together because their file paths are usually determined based on the base name of the object. Another example is -ftest-coverage, which outputs the coverage data into .gcno Signed-off-by: Masahiro Yamada Signed-off-by: Sasha Levin --- scripts/Kbuild.include | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index a33fa1a91873..28bfb4378dbd 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -82,20 +82,21 @@ cc-cross-prefix = \ fi))) # output directory for tests below -TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/) +TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$ # try-run # Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise) # Exit code chooses option. "$$TMP" serves as a temporary file and is # automatically cleaned up. try-run = $(shell set -e; \ - TMP="$(TMPOUT).$$$$.tmp"; \ - TMPO="$(TMPOUT).$$$$.o"; \ + TMP=$(TMPOUT)/tmp; \ + TMPO=$(TMPOUT)/tmp.o; \ + mkdir -p $(TMPOUT); \ + trap "rm -rf $(TMPOUT)" EXIT; \ if ($(1)) >/dev/null 2>&1; \ then echo "$(2)"; \ else echo "$(3)"; \ - fi; \ - rm -f "$$TMP" "$$TMPO") + fi) # as-option # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) From b851d4c9c087fd9efd15cbaf658520a661417962 Mon Sep 17 00:00:00 2001 From: Luis Chamberlain Date: Fri, 5 Jun 2020 16:58:36 +0200 Subject: [PATCH 175/208] blktrace: break out of blktrace setup on concurrent calls [ Upstream commit 1b0b283648163dae2a214ca28ed5a99f62a77319 ] We use one blktrace per request_queue, that means one per the entire disk. So we cannot run one blktrace on say /dev/vda and then /dev/vda1, or just two calls on /dev/vda. We check for concurrent setup only at the very end of the blktrace setup though. If we try to run two concurrent blktraces on the same block device the second one will fail, and the first one seems to go on. However when one tries to kill the first one one will see things like this: The kernel will show these: ``` debugfs: File 'dropped' in directory 'nvme1n1' already present! debugfs: File 'msg' in directory 'nvme1n1' already present! debugfs: File 'trace0' in directory 'nvme1n1' already present! `` And userspace just sees this error message for the second call: ``` blktrace /dev/nvme1n1 BLKTRACESETUP(2) /dev/nvme1n1 failed: 5/Input/output error ``` The first userspace process #1 will also claim that the files were taken underneath their nose as well. The files are taken away form the first process given that when the second blktrace fails, it will follow up with a BLKTRACESTOP and BLKTRACETEARDOWN. This means that even if go-happy process #1 is waiting for blktrace data, we *have* been asked to take teardown the blktrace. This can easily be reproduced with break-blktrace [0] run_0005.sh test. Just break out early if we know we're already going to fail, this will prevent trying to create the files all over again, which we know still exist. [0] https://github.com/mcgrof/break-blktrace Signed-off-by: Luis Chamberlain Signed-off-by: Jan Kara Reviewed-by: Bart Van Assche Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- kernel/trace/blktrace.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 304a164f5e7e..9a55c5bc5243 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -15,6 +15,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -504,6 +507,16 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, */ strreplace(buts->name, '/', '_'); + /* + * bdev can be NULL, as with scsi-generic, this is a helpful as + * we can be. + */ + if (q->blk_trace) { + pr_warn("Concurrent blktraces are not allowed on %s\n", + buts->name); + return -EBUSY; + } + bt = kzalloc(sizeof(*bt), GFP_KERNEL); if (!bt) return -ENOMEM; From 494cb2d62a19521cfe62b64d991bee120a19ace1 Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Thu, 11 Jun 2020 11:08:45 -0700 Subject: [PATCH 176/208] ALSA: hda: Add NVIDIA codec IDs 9a & 9d through a0 to patch table commit adb36a8203831e40494a92095dacd566b2ad4a69 upstream. These IDs are for upcoming NVIDIA chips with audio functions that are largely similar to the existing ones. Signed-off-by: Aaron Plattner Cc: Link: https://lore.kernel.org/r/20200611180845.39942-1-aplattner@nvidia.com Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_hdmi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 6b4ebaefd8f8..9e8cfc409b4b 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -3861,6 +3861,11 @@ HDA_CODEC_ENTRY(0x10de0095, "GPU 95 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0097, "GPU 97 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0098, "GPU 98 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0099, "GPU 99 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de009a, "GPU 9a HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de009d, "GPU 9d HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de009e, "GPU 9e HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de009f, "GPU 9f HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de00a0, "GPU a0 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI", patch_nvhdmi_2ch), HDA_CODEC_ENTRY(0x10de8067, "MCP67/68 HDMI", patch_nvhdmi_2ch), HDA_CODEC_ENTRY(0x11069f80, "VX900 HDMI/DP", patch_via_hdmi), From f8902c346e786a387d00567d9de29025f2e634de Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Thu, 11 Jun 2020 21:51:50 -0700 Subject: [PATCH 177/208] ACPI: sysfs: Fix pm_profile_attr type commit e6d701dca9893990d999fd145e3e07223c002b06 upstream. When running a kernel with Clang's Control Flow Integrity implemented, there is a violation that happens when accessing /sys/firmware/acpi/pm_profile: $ cat /sys/firmware/acpi/pm_profile 0 $ dmesg ... [ 17.352564] ------------[ cut here ]------------ [ 17.352568] CFI failure (target: acpi_show_profile+0x0/0x8): [ 17.352572] WARNING: CPU: 3 PID: 497 at kernel/cfi.c:29 __cfi_check_fail+0x33/0x40 [ 17.352573] Modules linked in: [ 17.352575] CPU: 3 PID: 497 Comm: cat Tainted: G W 5.7.0-microsoft-standard+ #1 [ 17.352576] RIP: 0010:__cfi_check_fail+0x33/0x40 [ 17.352577] Code: 48 c7 c7 50 b3 85 84 48 c7 c6 50 0a 4e 84 e8 a4 d8 60 00 85 c0 75 02 5b c3 48 c7 c7 dc 5e 49 84 48 89 de 31 c0 e8 7d 06 eb ff <0f> 0b 5b c3 00 00 cc cc 00 00 cc cc 00 85 f6 74 25 41 b9 ea ff ff [ 17.352577] RSP: 0018:ffffaa6dc3c53d30 EFLAGS: 00010246 [ 17.352578] RAX: 331267e0c06cee00 RBX: ffffffff83d85890 RCX: ffffffff8483a6f8 [ 17.352579] RDX: ffff9cceabbb37c0 RSI: 0000000000000082 RDI: ffffffff84bb9e1c [ 17.352579] RBP: ffffffff845b2bc8 R08: 0000000000000001 R09: ffff9cceabbba200 [ 17.352579] R10: 000000000000019d R11: 0000000000000000 R12: ffff9cc947766f00 [ 17.352580] R13: ffffffff83d6bd50 R14: ffff9ccc6fa80000 R15: ffffffff845bd328 [ 17.352582] FS: 00007fdbc8d13580(0000) GS:ffff9cce91ac0000(0000) knlGS:0000000000000000 [ 17.352582] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 17.352583] CR2: 00007fdbc858e000 CR3: 00000005174d0000 CR4: 0000000000340ea0 [ 17.352584] Call Trace: [ 17.352586] ? rev_id_show+0x8/0x8 [ 17.352587] ? __cfi_check+0x45bac/0x4b640 [ 17.352589] ? kobj_attr_show+0x73/0x80 [ 17.352590] ? sysfs_kf_seq_show+0xc1/0x140 [ 17.352592] ? ext4_seq_options_show.cfi_jt+0x8/0x8 [ 17.352593] ? seq_read+0x180/0x600 [ 17.352595] ? sysfs_create_file_ns.cfi_jt+0x10/0x10 [ 17.352596] ? tlbflush_read_file+0x8/0x8 [ 17.352597] ? __vfs_read+0x6b/0x220 [ 17.352598] ? handle_mm_fault+0xa23/0x11b0 [ 17.352599] ? vfs_read+0xa2/0x130 [ 17.352599] ? ksys_read+0x6a/0xd0 [ 17.352601] ? __do_sys_getpgrp+0x8/0x8 [ 17.352602] ? do_syscall_64+0x72/0x120 [ 17.352603] ? entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 17.352604] ---[ end trace 7b1fa81dc897e419 ]--- When /sys/firmware/acpi/pm_profile is read, sysfs_kf_seq_show is called, which in turn calls kobj_attr_show, which gets the ->show callback member by calling container_of on attr (casting it to struct kobj_attribute) then calls it. There is a CFI violation because pm_profile_attr is of type struct device_attribute but kobj_attr_show calls ->show expecting it to be from struct kobj_attribute. CFI checking ensures that function pointer types match when doing indirect calls. Fix pm_profile_attr to be defined in terms of kobj_attribute so there is no violation or mismatch. Fixes: 362b646062b2 ("ACPI: Export FADT pm_profile integer value to userspace") Link: https://github.com/ClangBuiltLinux/linux/issues/1051 Reported-by: yuu ichii Signed-off-by: Nathan Chancellor Cc: 3.10+ # 3.10+ Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index a663014cfa52..3b7e23866b42 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -942,13 +942,13 @@ static void __exit interrupt_stats_exit(void) } static ssize_t -acpi_show_profile(struct device *dev, struct device_attribute *attr, +acpi_show_profile(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile); } -static const struct device_attribute pm_profile_attr = +static const struct kobj_attribute pm_profile_attr = __ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL); static ssize_t hotplug_enabled_show(struct kobject *kobj, From cdf6d1e638e93a4ce812e2c9cb3ca3e5e52d34e1 Mon Sep 17 00:00:00 2001 From: Xiaoyao Li Date: Tue, 16 Jun 2020 15:33:07 +0800 Subject: [PATCH 178/208] KVM: X86: Fix MSR range of APIC registers in X2APIC mode commit bf10bd0be53282183f374af23577b18b5fbf7801 upstream. Only MSR address range 0x800 through 0x8ff is architecturally reserved and dedicated for accessing APIC registers in x2APIC mode. Fixes: 0105d1a52640 ("KVM: x2apic interface to lapic") Signed-off-by: Xiaoyao Li Message-Id: <20200616073307.16440-1-xiaoyao.li@intel.com> Cc: stable@vger.kernel.org Reviewed-by: Sean Christopherson Reviewed-by: Jim Mattson Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/x86.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 3401061a2231..0db7f5cd9c72 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2344,7 +2344,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) return kvm_mtrr_set_msr(vcpu, msr, data); case MSR_IA32_APICBASE: return kvm_set_apic_base(vcpu, msr_info); - case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff: + case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff: return kvm_x2apic_msr_write(vcpu, msr, data); case MSR_IA32_TSCDEADLINE: kvm_set_lapic_tscdeadline_msr(vcpu, data); @@ -2629,7 +2629,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_IA32_APICBASE: msr_info->data = kvm_get_apic_base(vcpu); break; - case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff: + case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff: return kvm_x2apic_msr_read(vcpu, msr_info->index, &msr_info->data); break; case MSR_IA32_TSCDEADLINE: From 4e387bedce68c204f10cd023a2ef21435ec9b22e Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Mon, 22 Jun 2020 14:58:29 -0700 Subject: [PATCH 179/208] KVM: nVMX: Plumb L2 GPA through to PML emulation commit 2dbebf7ae1ed9a420d954305e2c9d5ed39ec57c3 upstream. Explicitly pass the L2 GPA to kvm_arch_write_log_dirty(), which for all intents and purposes is vmx_write_pml_buffer(), instead of having the latter pull the GPA from vmcs.GUEST_PHYSICAL_ADDRESS. If the dirty bit update is the result of KVM emulation (rare for L2), then the GPA in the VMCS may be stale and/or hold a completely unrelated GPA. Fixes: c5f983f6e8455 ("nVMX: Implement emulated Page Modification Logging") Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson Message-Id: <20200622215832.22090-2-sean.j.christopherson@intel.com> Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/mmu.c | 4 ++-- arch/x86/kvm/mmu.h | 2 +- arch/x86/kvm/paging_tmpl.h | 7 ++++--- arch/x86/kvm/vmx.c | 5 ++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 9529fe69e1d9..ecb6009a2c8a 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1060,7 +1060,7 @@ struct kvm_x86_ops { void (*enable_log_dirty_pt_masked)(struct kvm *kvm, struct kvm_memory_slot *slot, gfn_t offset, unsigned long mask); - int (*write_log_dirty)(struct kvm_vcpu *vcpu); + int (*write_log_dirty)(struct kvm_vcpu *vcpu, gpa_t l2_gpa); /* pmu operations of sub-arch */ const struct kvm_pmu_ops *pmu_ops; diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 082d0cea72f4..9df3d5d7214a 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1713,10 +1713,10 @@ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm, * Emulate arch specific page modification logging for the * nested hypervisor */ -int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu) +int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa) { if (kvm_x86_ops->write_log_dirty) - return kvm_x86_ops->write_log_dirty(vcpu); + return kvm_x86_ops->write_log_dirty(vcpu, l2_gpa); return 0; } diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 068feab64acf..816a626b6250 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -194,7 +194,7 @@ void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn); void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn); bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm, struct kvm_memory_slot *slot, u64 gfn); -int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu); +int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa); int kvm_mmu_post_init_vm(struct kvm *kvm); void kvm_mmu_pre_destroy_vm(struct kvm *kvm); diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 8cf7a09bdd73..7260a165488d 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -202,7 +202,7 @@ static inline unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, u64 gpte) static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, struct guest_walker *walker, - int write_fault) + gpa_t addr, int write_fault) { unsigned level, index; pt_element_t pte, orig_pte; @@ -227,7 +227,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu, !(pte & PT_GUEST_DIRTY_MASK)) { trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte)); #if PTTYPE == PTTYPE_EPT - if (kvm_arch_write_log_dirty(vcpu)) + if (kvm_arch_write_log_dirty(vcpu, addr)) return -EINVAL; #endif pte |= PT_GUEST_DIRTY_MASK; @@ -424,7 +424,8 @@ retry_walk: (PT_GUEST_DIRTY_SHIFT - PT_GUEST_ACCESSED_SHIFT); if (unlikely(!accessed_dirty)) { - ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker, write_fault); + ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker, + addr, write_fault); if (unlikely(ret < 0)) goto error; else if (ret) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 42c6ca05a613..11e683ec6c85 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -12462,11 +12462,10 @@ static void vmx_flush_log_dirty(struct kvm *kvm) kvm_flush_pml_buffers(kvm); } -static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu) +static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu, gpa_t gpa) { struct vmcs12 *vmcs12; struct vcpu_vmx *vmx = to_vmx(vcpu); - gpa_t gpa; struct page *page = NULL; u64 *pml_address; @@ -12487,7 +12486,7 @@ static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu) return 1; } - gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS) & ~0xFFFull; + gpa &= ~0xFFFull; page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->pml_address); if (is_error_page(page)) From bdbae19beef8db3687c81dfda63f79359a063c56 Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Mon, 15 Jun 2020 18:48:58 +0100 Subject: [PATCH 180/208] btrfs: fix failure of RWF_NOWAIT write into prealloc extent beyond eof commit 4b1946284dd6641afdb9457101056d9e6ee6204c upstream. If we attempt to write to prealloc extent located after eof using a RWF_NOWAIT write, we always fail with -EAGAIN. We do actually check if we have an allocated extent for the write at the start of btrfs_file_write_iter() through a call to check_can_nocow(), but later when we go into the actual direct IO write path we simply return -EAGAIN if the write starts at or beyond EOF. Trivial to reproduce: $ mkfs.btrfs -f /dev/sdb $ mount /dev/sdb /mnt $ touch /mnt/foo $ chattr +C /mnt/foo $ xfs_io -d -c "pwrite -S 0xab 0 64K" /mnt/foo wrote 65536/65536 bytes at offset 0 64 KiB, 16 ops; 0.0004 sec (135.575 MiB/sec and 34707.1584 ops/sec) $ xfs_io -c "falloc -k 64K 1M" /mnt/foo $ xfs_io -d -c "pwrite -N -V 1 -S 0xfe -b 64K 64K 64K" /mnt/foo pwrite: Resource temporarily unavailable On xfs and ext4 the write succeeds, as expected. Fix this by removing the wrong check at btrfs_direct_IO(). Fixes: edf064e7c6fec3 ("btrfs: nowait aio support") CC: stable@vger.kernel.org # 4.14+ Signed-off-by: Filipe Manana Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/inode.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index ad138f0b0ce1..39ad582d72c4 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -8947,9 +8947,6 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) dio_data.overwrite = 1; inode_unlock(inode); relock = true; - } else if (iocb->ki_flags & IOCB_NOWAIT) { - ret = -EAGAIN; - goto out; } ret = btrfs_delalloc_reserve_space(inode, &data_reserved, offset, count); From 06491c36d48e5df27cf1889a582a0c8eb5053a5b Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Thu, 25 Jun 2020 20:29:52 -0700 Subject: [PATCH 181/208] mm/slab: use memzero_explicit() in kzfree() commit 8982ae527fbef170ef298650c15d55a9ccd33973 upstream. The kzfree() function is normally used to clear some sensitive information, like encryption keys, in the buffer before freeing it back to the pool. Memset() is currently used for buffer clearing. However unlikely, there is still a non-zero probability that the compiler may choose to optimize away the memory clearing especially if LTO is being used in the future. To make sure that this optimization will never happen, memzero_explicit(), which is introduced in v3.18, is now used in kzfree() to future-proof it. Link: http://lkml.kernel.org/r/20200616154311.12314-2-longman@redhat.com Fixes: 3ef0e5ba4673 ("slab: introduce kzfree()") Signed-off-by: Waiman Long Acked-by: Michal Hocko Cc: David Howells Cc: Jarkko Sakkinen Cc: James Morris Cc: "Serge E. Hallyn" Cc: Joe Perches Cc: Matthew Wilcox Cc: David Rientjes Cc: Johannes Weiner Cc: Dan Carpenter Cc: "Jason A . Donenfeld" Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/slab_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/slab_common.c b/mm/slab_common.c index f6764cf162b8..caba3efce3f4 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -1449,7 +1449,7 @@ void kzfree(const void *p) if (unlikely(ZERO_OR_NULL_PTR(mem))) return; ks = ksize(mem); - memset(mem, 0, ks); + memzero_explicit(mem, ks); kfree(mem); } EXPORT_SYMBOL(kzfree); From 0c01d249b9765eff4c5f195eb5f201bb365fe2b5 Mon Sep 17 00:00:00 2001 From: Junxiao Bi Date: Thu, 25 Jun 2020 20:29:33 -0700 Subject: [PATCH 182/208] ocfs2: load global_inode_alloc commit 7569d3c754e452769a5747eeeba488179e38a5da upstream. Set global_inode_alloc as OCFS2_FIRST_ONLINE_SYSTEM_INODE, that will make it load during mount. It can be used to test whether some global/system inodes are valid. One use case is that nfsd will test whether root inode is valid. Link: http://lkml.kernel.org/r/20200616183829.87211-3-junxiao.bi@oracle.com Signed-off-by: Junxiao Bi Reviewed-by: Joseph Qi Cc: Changwei Ge Cc: Gang He Cc: Joel Becker Cc: Jun Piao Cc: Mark Fasheh Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/ocfs2_fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index 5bb4a89f9045..7a3866d7fc36 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h @@ -339,8 +339,8 @@ struct ocfs2_system_inode_info { enum { BAD_BLOCK_SYSTEM_INODE = 0, GLOBAL_INODE_ALLOC_SYSTEM_INODE, +#define OCFS2_FIRST_ONLINE_SYSTEM_INODE GLOBAL_INODE_ALLOC_SYSTEM_INODE SLOT_MAP_SYSTEM_INODE, -#define OCFS2_FIRST_ONLINE_SYSTEM_INODE SLOT_MAP_SYSTEM_INODE HEARTBEAT_SYSTEM_INODE, GLOBAL_BITMAP_SYSTEM_INODE, USER_QUOTA_SYSTEM_INODE, From b40e75385c7a2fafb80b27a714951b5244086895 Mon Sep 17 00:00:00 2001 From: Junxiao Bi Date: Thu, 25 Jun 2020 20:29:40 -0700 Subject: [PATCH 183/208] ocfs2: fix value of OCFS2_INVALID_SLOT commit 9277f8334ffc719fe922d776444d6e4e884dbf30 upstream. In the ocfs2 disk layout, slot number is 16 bits, but in ocfs2 implementation, slot number is 32 bits. Usually this will not cause any issue, because slot number is converted from u16 to u32, but OCFS2_INVALID_SLOT was defined as -1, when an invalid slot number from disk was obtained, its value was (u16)-1, and it was converted to u32. Then the following checking in get_local_system_inode will be always skipped: static struct inode **get_local_system_inode(struct ocfs2_super *osb, int type, u32 slot) { BUG_ON(slot == OCFS2_INVALID_SLOT); ... } Link: http://lkml.kernel.org/r/20200616183829.87211-5-junxiao.bi@oracle.com Signed-off-by: Junxiao Bi Reviewed-by: Joseph Qi Cc: Mark Fasheh Cc: Joel Becker Cc: Changwei Ge Cc: Gang He Cc: Jun Piao Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/ocfs2_fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index 7a3866d7fc36..0773c774e2bf 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h @@ -303,7 +303,7 @@ #define OCFS2_MAX_SLOTS 255 /* Slot map indicator for an empty slot */ -#define OCFS2_INVALID_SLOT -1 +#define OCFS2_INVALID_SLOT ((u16)-1) #define OCFS2_VOL_UUID_LEN 16 #define OCFS2_MAX_VOL_LABEL_LEN 64 From 91d8b24ba51f8dcfd8dae65fa340fb79af4547b2 Mon Sep 17 00:00:00 2001 From: Junxiao Bi Date: Thu, 25 Jun 2020 20:29:37 -0700 Subject: [PATCH 184/208] ocfs2: fix panic on nfs server over ocfs2 commit e5a15e17a78d58f933d17cafedfcf7486a29f5b4 upstream. The following kernel panic was captured when running nfs server over ocfs2, at that time ocfs2_test_inode_bit() was checking whether one inode locating at "blkno" 5 was valid, that is ocfs2 root inode, its "suballoc_slot" was OCFS2_INVALID_SLOT(65535) and it was allocted from //global_inode_alloc, but here it wrongly assumed that it was got from per slot inode alloctor which would cause array overflow and trigger kernel panic. BUG: unable to handle kernel paging request at 0000000000001088 IP: [] _raw_spin_lock+0x18/0xf0 PGD 1e06ba067 PUD 1e9e7d067 PMD 0 Oops: 0002 [#1] SMP CPU: 6 PID: 24873 Comm: nfsd Not tainted 4.1.12-124.36.1.el6uek.x86_64 #2 Hardware name: Huawei CH121 V3/IT11SGCA1, BIOS 3.87 02/02/2018 RIP: _raw_spin_lock+0x18/0xf0 RSP: e02b:ffff88005ae97908 EFLAGS: 00010206 RAX: ffff88005ae98000 RBX: 0000000000001088 RCX: 0000000000000000 RDX: 0000000000020000 RSI: 0000000000000009 RDI: 0000000000001088 RBP: ffff88005ae97928 R08: 0000000000000000 R09: ffff880212878e00 R10: 0000000000007ff0 R11: 0000000000000000 R12: 0000000000001088 R13: ffff8800063c0aa8 R14: ffff8800650c27d0 R15: 000000000000ffff FS: 0000000000000000(0000) GS:ffff880218180000(0000) knlGS:ffff880218180000 CS: e033 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000001088 CR3: 00000002033d0000 CR4: 0000000000042660 Call Trace: igrab+0x1e/0x60 ocfs2_get_system_file_inode+0x63/0x3a0 [ocfs2] ocfs2_test_inode_bit+0x328/0xa00 [ocfs2] ocfs2_get_parent+0xba/0x3e0 [ocfs2] reconnect_path+0xb5/0x300 exportfs_decode_fh+0xf6/0x2b0 fh_verify+0x350/0x660 [nfsd] nfsd4_putfh+0x4d/0x60 [nfsd] nfsd4_proc_compound+0x3d3/0x6f0 [nfsd] nfsd_dispatch+0xe0/0x290 [nfsd] svc_process_common+0x412/0x6a0 [sunrpc] svc_process+0x123/0x210 [sunrpc] nfsd+0xff/0x170 [nfsd] kthread+0xcb/0xf0 ret_from_fork+0x61/0x90 Code: 83 c2 02 0f b7 f2 e8 18 dc 91 ff 66 90 eb bf 0f 1f 40 00 55 48 89 e5 41 56 41 55 41 54 53 0f 1f 44 00 00 48 89 fb ba 00 00 02 00 0f c1 17 89 d0 45 31 e4 45 31 ed c1 e8 10 66 39 d0 41 89 c6 RIP _raw_spin_lock+0x18/0xf0 CR2: 0000000000001088 ---[ end trace 7264463cd1aac8f9 ]--- Kernel panic - not syncing: Fatal exception Link: http://lkml.kernel.org/r/20200616183829.87211-4-junxiao.bi@oracle.com Signed-off-by: Junxiao Bi Reviewed-by: Joseph Qi Cc: Changwei Ge Cc: Gang He Cc: Joel Becker Cc: Jun Piao Cc: Mark Fasheh Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/ocfs2/suballoc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 71f22c8fbffd..4ca2f71565f9 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -2891,9 +2891,12 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res) goto bail; } - inode_alloc_inode = - ocfs2_get_system_file_inode(osb, INODE_ALLOC_SYSTEM_INODE, - suballoc_slot); + if (suballoc_slot == (u16)OCFS2_INVALID_SLOT) + inode_alloc_inode = ocfs2_get_system_file_inode(osb, + GLOBAL_INODE_ALLOC_SYSTEM_INODE, suballoc_slot); + else + inode_alloc_inode = ocfs2_get_system_file_inode(osb, + INODE_ALLOC_SYSTEM_INODE, suballoc_slot); if (!inode_alloc_inode) { /* the error code could be inaccurate, but we are not able to * get the correct one. */ From 1c7b654a37d68757cc1eef45454238dc8df0ee6a Mon Sep 17 00:00:00 2001 From: Jiping Ma Date: Mon, 11 May 2020 10:52:07 +0800 Subject: [PATCH 185/208] arm64: perf: Report the PC value in REGS_ABI_32 mode commit 8dfe804a4031ca6ba3a3efb2048534249b64f3a5 upstream. A 32-bit perf querying the registers of a compat task using REGS_ABI_32 will receive zeroes from w15, when it expects to find the PC. Return the PC value for register dwarf register 15 when returning register values for a compat task to perf. Cc: Acked-by: Mark Rutland Signed-off-by: Jiping Ma Link: https://lore.kernel.org/r/1589165527-188401-1-git-send-email-jiping.ma2@windriver.com [will: Shuffled code and added a comment] Signed-off-by: Will Deacon Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/perf_regs.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c index 1d091d048d04..0819db91ca94 100644 --- a/arch/arm64/kernel/perf_regs.c +++ b/arch/arm64/kernel/perf_regs.c @@ -15,15 +15,34 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) return 0; /* - * Compat (i.e. 32 bit) mode: - * - PC has been set in the pt_regs struct in kernel_entry, - * - Handle SP and LR here. + * Our handling of compat tasks (PERF_SAMPLE_REGS_ABI_32) is weird, but + * we're stuck with it for ABI compatability reasons. + * + * For a 32-bit consumer inspecting a 32-bit task, then it will look at + * the first 16 registers (see arch/arm/include/uapi/asm/perf_regs.h). + * These correspond directly to a prefix of the registers saved in our + * 'struct pt_regs', with the exception of the PC, so we copy that down + * (x15 corresponds to SP_hyp in the architecture). + * + * So far, so good. + * + * The oddity arises when a 64-bit consumer looks at a 32-bit task and + * asks for registers beyond PERF_REG_ARM_MAX. In this case, we return + * SP_usr, LR_usr and PC in the positions where the AArch64 SP, LR and + * PC registers would normally live. The initial idea was to allow a + * 64-bit unwinder to unwind a 32-bit task and, although it's not clear + * how well that works in practice, somebody might be relying on it. + * + * At the time we make a sample, we don't know whether the consumer is + * 32-bit or 64-bit, so we have to cater for both possibilities. */ if (compat_user_mode(regs)) { if ((u32)idx == PERF_REG_ARM64_SP) return regs->compat_sp; if ((u32)idx == PERF_REG_ARM64_LR) return regs->compat_lr; + if (idx == 15) + return regs->pc; } if ((u32)idx == PERF_REG_ARM64_SP) From 9e88cda0cd976f843c65e4ac4cf628474a59c883 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Sat, 20 Jun 2020 12:46:03 +0900 Subject: [PATCH 186/208] tracing: Fix event trigger to accept redundant spaces commit 6784beada631800f2c5afd567e5628c843362cee upstream. Fix the event trigger to accept redundant spaces in the trigger input. For example, these return -EINVAL echo " traceon" > events/ftrace/print/trigger echo "traceon if common_pid == 0" > events/ftrace/print/trigger echo "disable_event:kmem:kmalloc " > events/ftrace/print/trigger But these are hard to find what is wrong. To fix this issue, use skip_spaces() to remove spaces in front of actual tokens, and set NULL if there is no token. Link: http://lkml.kernel.org/r/159262476352.185015.5261566783045364186.stgit@devnote2 Cc: Tom Zanussi Cc: stable@vger.kernel.org Fixes: 85f2b08268c0 ("tracing: Add basic event trigger framework") Reviewed-by: Tom Zanussi Signed-off-by: Masami Hiramatsu Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace_events_trigger.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c index 6fb5eb7b57dc..13f501337308 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -223,11 +223,17 @@ static int event_trigger_regex_open(struct inode *inode, struct file *file) static int trigger_process_regex(struct trace_event_file *file, char *buff) { - char *command, *next = buff; + char *command, *next; struct event_command *p; int ret = -EINVAL; + next = buff = skip_spaces(buff); command = strsep(&next, ": \t"); + if (next) { + next = skip_spaces(next); + if (!*next) + next = NULL; + } command = (command[0] != '!') ? command : command + 1; mutex_lock(&trigger_cmd_mutex); @@ -630,8 +636,14 @@ event_trigger_callback(struct event_command *cmd_ops, int ret; /* separate the trigger from the filter (t:n [if filter]) */ - if (param && isdigit(param[0])) + if (param && isdigit(param[0])) { trigger = strsep(¶m, " \t"); + if (param) { + param = skip_spaces(param); + if (!*param) + param = NULL; + } + } trigger_ops = cmd_ops->get_trigger_ops(cmd, trigger); @@ -1342,6 +1354,11 @@ int event_enable_trigger_func(struct event_command *cmd_ops, trigger = strsep(¶m, " \t"); if (!trigger) return -EINVAL; + if (param) { + param = skip_spaces(param); + if (!*param) + param = NULL; + } system = strsep(&trigger, ":"); if (!trigger) From d51c789bce9efd4de5a22bca0f86ef8319b91caf Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Mon, 22 Jun 2020 23:31:22 +0300 Subject: [PATCH 187/208] drm/radeon: fix fb_div check in ni_init_smc_spll_table() commit 35f760b44b1b9cb16a306bdcc7220fbbf78c4789 upstream. clk_s is checked twice in a row in ni_init_smc_spll_table(). fb_div should be checked instead. Fixes: 69e0b57a91ad ("drm/radeon/kms: add dpm support for cayman (v5)") Cc: stable@vger.kernel.org Signed-off-by: Denis Efremov Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/ni_dpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index 9416e72f86aa..d491b3aa124f 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -2126,7 +2126,7 @@ static int ni_init_smc_spll_table(struct radeon_device *rdev) if (clk_s & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT)) ret = -EINVAL; - if (clk_s & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT)) + if (fb_div & ~(SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT)) ret = -EINVAL; if (clk_v & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT)) From a6b8dfe9bd1af356d23ab9e26819573ef1897068 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 3 Jun 2020 13:19:58 +0300 Subject: [PATCH 188/208] Staging: rtl8723bs: prevent buffer overflow in update_sta_support_rate() commit b65a2d8c8614386f7e8d38ea150749f8a862f431 upstream. The "ie_len" variable is in the 0-255 range and it comes from the network. If it's over NDIS_802_11_LENGTH_RATES_EX (16) then that will lead to memory corruption. Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") Signed-off-by: Dan Carpenter Cc: stable Link: https://lore.kernel.org/r/20200603101958.GA1845750@mwanda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_wlan_util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c index f485f541e36d..d6de62ee681e 100644 --- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c @@ -1904,12 +1904,14 @@ int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, uint var_ie_l pIE = (struct ndis_80211_var_ie *)rtw_get_ie(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len); if (pIE == NULL) return _FAIL; + if (ie_len > sizeof(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates)) + return _FAIL; memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len); supportRateNum = ie_len; pIE = (struct ndis_80211_var_ie *)rtw_get_ie(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len); - if (pIE) + if (pIE && (ie_len <= sizeof(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates) - supportRateNum)) memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len); return _SUCCESS; From bbffca92d1feb9604168dbfb199071c823839200 Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Mon, 1 Jun 2020 11:54:57 +0300 Subject: [PATCH 189/208] sunrpc: fixed rollback in rpc_gssd_dummy_populate() commit b7ade38165ca0001c5a3bd5314a314abbbfbb1b7 upstream. __rpc_depopulate(gssd_dentry) was lost on error path cc: stable@vger.kernel.org Fixes: commit 4b9a445e3eeb ("sunrpc: create a new dummy pipe for gssd to hold open") Signed-off-by: Vasily Averin Reviewed-by: Jeff Layton Signed-off-by: Anna Schumaker Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/rpc_pipe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 34f94052c519..137f92bfafac 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -1347,6 +1347,7 @@ rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data) q.len = strlen(gssd_dummy_clnt_dir[0].name); clnt_dentry = d_hash_and_lookup(gssd_dentry, &q); if (!clnt_dentry) { + __rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1); pipe_dentry = ERR_PTR(-ENOENT); goto out; } From 653db17384a3a1875d13cab23e7a4bd04188e9e0 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Thu, 25 Jun 2020 11:32:34 -0400 Subject: [PATCH 190/208] SUNRPC: Properly set the @subbuf parameter of xdr_buf_subsegment() commit 89a3c9f5b9f0bcaa9aea3e8b2a616fcaea9aad78 upstream. @subbuf is an output parameter of xdr_buf_subsegment(). A survey of call sites shows that @subbuf is always uninitialized before xdr_buf_segment() is invoked by callers. There are some execution paths through xdr_buf_subsegment() that do not set all of the fields in @subbuf, leaving some pointer fields containing garbage addresses. Subsequent processing of that buffer then results in a page fault. Signed-off-by: Chuck Lever Cc: Signed-off-by: Anna Schumaker Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xdr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 4f382805eb9c..87cf0b933f99 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -1036,6 +1036,7 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, base = 0; } else { base -= buf->head[0].iov_len; + subbuf->head[0].iov_base = buf->head[0].iov_base; subbuf->head[0].iov_len = 0; } @@ -1048,6 +1049,8 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, base = 0; } else { base -= buf->page_len; + subbuf->pages = buf->pages; + subbuf->page_base = 0; subbuf->page_len = 0; } @@ -1059,6 +1062,7 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, base = 0; } else { base -= buf->tail[0].iov_len; + subbuf->tail[0].iov_base = buf->tail[0].iov_base; subbuf->tail[0].iov_len = 0; } From 75aceaa6ad5bc2d67f65314eb657ffcc8c1669af Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 22 Jun 2020 15:04:15 -0400 Subject: [PATCH 191/208] pNFS/flexfiles: Fix list corruption if the mirror count changes commit 8b04013737341442ed914b336cde866b902664ae upstream. If the mirror count changes in the new layout we pick up inside ff_layout_pg_init_write(), then we can end up adding the request to the wrong mirror and corrupting the mirror->pg_list. Fixes: d600ad1f2bdb ("NFS41: pop some layoutget errors to application") Cc: stable@vger.kernel.org Signed-off-by: Trond Myklebust Signed-off-by: Anna Schumaker Signed-off-by: Greg Kroah-Hartman --- fs/nfs/flexfilelayout/flexfilelayout.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 8dbde5ded042..74f15498c9bf 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -921,9 +921,8 @@ retry: goto out_mds; /* Use a direct mapping of ds_idx to pgio mirror_idx */ - if (WARN_ON_ONCE(pgio->pg_mirror_count != - FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg))) - goto out_mds; + if (pgio->pg_mirror_count != FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg)) + goto out_eagain; for (i = 0; i < pgio->pg_mirror_count; i++) { ds = nfs4_ff_layout_prepare_ds(pgio->pg_lseg, i, true); @@ -942,11 +941,15 @@ retry: } return; - +out_eagain: + pnfs_generic_pg_cleanup(pgio); + pgio->pg_error = -EAGAIN; + return; out_mds: pnfs_put_lseg(pgio->pg_lseg); pgio->pg_lseg = NULL; nfs_pageio_reset_write_mds(pgio); + pgio->pg_error = -EAGAIN; } static unsigned int From 76c3f19c35965ddbd8bf6fa786b68e75ecdbf394 Mon Sep 17 00:00:00 2001 From: Olga Kornievskaia Date: Wed, 24 Jun 2020 13:54:08 -0400 Subject: [PATCH 192/208] NFSv4 fix CLOSE not waiting for direct IO compeletion commit d03727b248d0dae6199569a8d7b629a681154633 upstream. Figuring out the root case for the REMOVE/CLOSE race and suggesting the solution was done by Neil Brown. Currently what happens is that direct IO calls hold a reference on the open context which is decremented as an asynchronous task in the nfs_direct_complete(). Before reference is decremented, control is returned to the application which is free to close the file. When close is being processed, it decrements its reference on the open_context but since directIO still holds one, it doesn't sent a close on the wire. It returns control to the application which is free to do other operations. For instance, it can delete a file. Direct IO is finally releasing its reference and triggering an asynchronous close. Which races with the REMOVE. On the server, REMOVE can be processed before the CLOSE, failing the REMOVE with EACCES as the file is still opened. Signed-off-by: Olga Kornievskaia Suggested-by: Neil Brown CC: stable@vger.kernel.org Signed-off-by: Anna Schumaker Signed-off-by: Greg Kroah-Hartman --- fs/nfs/direct.c | 13 +++++++++---- fs/nfs/file.c | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index e6ea4511c41c..3cef33b0f7e0 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -396,8 +396,6 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq) { struct inode *inode = dreq->inode; - inode_dio_end(inode); - if (dreq->iocb) { long res = (long) dreq->error; if (dreq->count != 0) { @@ -409,7 +407,10 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq) complete(&dreq->completion); + igrab(inode); nfs_direct_req_release(dreq); + inode_dio_end(inode); + iput(inode); } static void nfs_direct_read_completion(struct nfs_pgio_header *hdr) @@ -539,8 +540,10 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, * generic layer handle the completion. */ if (requested_bytes == 0) { - inode_dio_end(inode); + igrab(inode); nfs_direct_req_release(dreq); + inode_dio_end(inode); + iput(inode); return result < 0 ? result : -EIO; } @@ -957,8 +960,10 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, * generic layer handle the completion. */ if (requested_bytes == 0) { - inode_dio_end(inode); + igrab(inode); nfs_direct_req_release(dreq); + inode_dio_end(inode); + iput(inode); return result < 0 ? result : -EIO; } diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 81cca49a8375..7da2cea1e7a0 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -82,6 +82,7 @@ nfs_file_release(struct inode *inode, struct file *filp) dprintk("NFS: release(%pD2)\n", filp); nfs_inc_stats(inode, NFSIOS_VFSRELEASE); + inode_dio_wait(inode); nfs_file_clear_open_context(filp); return 0; } From 115267e8d9fce8d5efe0949f1d2e5cee30441cf7 Mon Sep 17 00:00:00 2001 From: Zheng Bin Date: Fri, 21 Feb 2020 07:38:20 -0800 Subject: [PATCH 193/208] xfs: add agf freeblocks verify in xfs_agf_verify [ Upstream commit d0c7feaf87678371c2c09b3709400be416b2dc62 ] We recently used fuzz(hydra) to test XFS and automatically generate tmp.img(XFS v5 format, but some metadata is wrong) xfs_repair information(just one AG): agf_freeblks 0, counted 3224 in ag 0 agf_longest 536874136, counted 3224 in ag 0 sb_fdblocks 613, counted 3228 Test as follows: mount tmp.img tmpdir cp file1M tmpdir sync In 4.19-stable, sync will stuck, the reason is: xfs_mountfs xfs_check_summary_counts if ((!xfs_sb_version_haslazysbcount(&mp->m_sb) || XFS_LAST_UNMOUNT_WAS_CLEAN(mp)) && !xfs_fs_has_sickness(mp, XFS_SICK_FS_COUNTERS)) return 0; -->just return, incore sb_fdblocks still be 613 xfs_initialize_perag_data cp file1M tmpdir -->ok(write file to pagecache) sync -->stuck(write pagecache to disk) xfs_map_blocks xfs_iomap_write_allocate while (count_fsb != 0) { nimaps = 0; while (nimaps == 0) { --> endless loop nimaps = 1; xfs_bmapi_write(..., &nimaps) --> nimaps becomes 0 again xfs_bmapi_write xfs_bmap_alloc xfs_bmap_btalloc xfs_alloc_vextent xfs_alloc_fix_freelist xfs_alloc_space_available -->fail(agf_freeblks is 0) In linux-next, sync not stuck, cause commit c2b3164320b5 ("xfs: use the latest extent at writeback delalloc conversion time") remove the above while, dmesg is as follows: [ 55.250114] XFS (loop0): page discard on page ffffea0008bc7380, inode 0x1b0c, offset 0. Users do not know why this page is discard, the better soultion is: 1. Like xfs_repair, make sure sb_fdblocks is equal to counted (xfs_initialize_perag_data did this, who is not called at this mount) 2. Add agf verify, if fail, will tell users to repair This patch use the second soultion. Signed-off-by: Zheng Bin Signed-off-by: Ren Xudong Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong Signed-off-by: Sasha Levin --- fs/xfs/libxfs/xfs_alloc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 516e0c57cf9c..a10d9a3c181e 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2529,6 +2529,13 @@ xfs_agf_verify( be32_to_cpu(agf->agf_flcount) <= xfs_agfl_size(mp))) return false; + if (be32_to_cpu(agf->agf_length) > mp->m_sb.sb_dblocks) + return false; + + if (be32_to_cpu(agf->agf_freeblks) < be32_to_cpu(agf->agf_longest) || + be32_to_cpu(agf->agf_freeblks) > be32_to_cpu(agf->agf_length)) + return false; + if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) < 1 || be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) < 1 || be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) > XFS_BTREE_MAXLEVELS || @@ -2540,6 +2547,10 @@ xfs_agf_verify( be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS)) return false; + if (xfs_sb_version_hasrmapbt(&mp->m_sb) && + be32_to_cpu(agf->agf_rmap_blocks) > be32_to_cpu(agf->agf_length)) + return false; + /* * during growfs operations, the perag is not fully initialised, * so we can't use it for any useful checking. growfs ensures we can't @@ -2553,6 +2564,11 @@ xfs_agf_verify( be32_to_cpu(agf->agf_btreeblks) > be32_to_cpu(agf->agf_length)) return false; + if (xfs_sb_version_hasreflink(&mp->m_sb) && + be32_to_cpu(agf->agf_refcount_blocks) > + be32_to_cpu(agf->agf_length)) + return false; + if (xfs_sb_version_hasreflink(&mp->m_sb) && (be32_to_cpu(agf->agf_refcount_level) < 1 || be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS)) From f1bd26cf65a3f3d9dea9218eac4470af1dfcfb1e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 12 May 2020 10:22:44 +0200 Subject: [PATCH 194/208] Revert "tty: hvc: Fix data abort due to race in hvc_open" commit cf9c94456ebafc6d75a834e58dfdc8ae71a3acbc upstream. This reverts commit e2bd1dcbe1aa34ff5570b3427c530e4332ecf0fe. In discussion on the mailing list, it has been determined that this is not the correct type of fix for this issue. Revert it so that we can do this correctly. Reported-by: Jiri Slaby Reported-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20200428032601.22127-1-rananta@codeaurora.org Cc: Raghavendra Rao Ananta Signed-off-by: Greg Kroah-Hartman --- drivers/tty/hvc/hvc_console.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index 663cbe3669e1..d52221ae1b85 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -88,8 +88,6 @@ static LIST_HEAD(hvc_structs); */ static DEFINE_SPINLOCK(hvc_structs_lock); -/* Mutex to serialize hvc_open */ -static DEFINE_MUTEX(hvc_open_mutex); /* * This value is used to assign a tty->index value to a hvc_struct based * upon order of exposure via hvc_probe(), when we can not match it to @@ -334,24 +332,16 @@ static int hvc_install(struct tty_driver *driver, struct tty_struct *tty) */ static int hvc_open(struct tty_struct *tty, struct file * filp) { - struct hvc_struct *hp; + struct hvc_struct *hp = tty->driver_data; unsigned long flags; int rc = 0; - mutex_lock(&hvc_open_mutex); - - hp = tty->driver_data; - if (!hp) { - rc = -EIO; - goto out; - } - spin_lock_irqsave(&hp->port.lock, flags); /* Check and then increment for fast path open. */ if (hp->port.count++ > 0) { spin_unlock_irqrestore(&hp->port.lock, flags); hvc_kick(); - goto out; + return 0; } /* else count == 0 */ spin_unlock_irqrestore(&hp->port.lock, flags); @@ -379,8 +369,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) /* Force wakeup of the polling thread */ hvc_kick(); -out: - mutex_unlock(&hvc_open_mutex); return rc; } From 4139fb08c05fec734f85a99e8b7d99dc12b1b68c Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Tue, 30 Jun 2020 16:24:19 -0400 Subject: [PATCH 195/208] Linux 4.14.187 Signed-off-by: Sasha Levin --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5152fefccab5..42b7d816d102 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 14 -SUBLEVEL = 186 +SUBLEVEL = 187 EXTRAVERSION = NAME = Petit Gorille From c8dc8a070fc2b93b369082870815d9a63e8bd092 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 22 Jun 2020 17:38:48 +0800 Subject: [PATCH 196/208] f2fs: split f2fs_allocate_new_segments() to two independent functions: - f2fs_allocate_new_segment() for specified type segment allocation - f2fs_allocate_new_segments() for all data type segments allocation Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 3 ++- fs/f2fs/file.c | 2 +- fs/f2fs/recovery.c | 2 +- fs/f2fs/segment.c | 41 ++++++++++++++++++++++++----------------- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index d55d36d37ef6..f90c915fa7db 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3354,7 +3354,8 @@ void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi); int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra); void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type, unsigned int start, unsigned int end); -void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi, int type); +void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type); +void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi); int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range); bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi, struct cp_control *cpc); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index b8ec875617a5..906219b46ee9 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1661,7 +1661,7 @@ next_alloc: map.m_seg_type = CURSEG_COLD_DATA_PINNED; f2fs_lock_op(sbi); - f2fs_allocate_new_segments(sbi, CURSEG_COLD_DATA); + f2fs_allocate_new_segment(sbi, CURSEG_COLD_DATA); f2fs_unlock_op(sbi); err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_DIO); diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 7cb7ec838a6f..0b837856098a 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -742,7 +742,7 @@ next: f2fs_put_page(page, 1); } if (!err) - f2fs_allocate_new_segments(sbi, NO_CHECK_TYPE); + f2fs_allocate_new_segments(sbi); return err; } diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 3ac4052b1c7d..d87ed33b64a3 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2732,28 +2732,35 @@ unlock: up_read(&SM_I(sbi)->curseg_lock); } -void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi, int type) +static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type) { - struct curseg_info *curseg; + struct curseg_info *curseg = CURSEG_I(sbi, type); unsigned int old_segno; + + if (!curseg->next_blkoff && + !get_valid_blocks(sbi, curseg->segno, false) && + !get_ckpt_valid_blocks(sbi, curseg->segno)) + return; + + old_segno = curseg->segno; + SIT_I(sbi)->s_ops->allocate_segment(sbi, type, true); + locate_dirty_segment(sbi, old_segno); +} + +void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type) +{ + down_write(&SIT_I(sbi)->sentry_lock); + __allocate_new_segment(sbi, type); + up_write(&SIT_I(sbi)->sentry_lock); +} + +void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi) +{ int i; down_write(&SIT_I(sbi)->sentry_lock); - - for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { - if (type != NO_CHECK_TYPE && i != type) - continue; - - curseg = CURSEG_I(sbi, i); - if (type == NO_CHECK_TYPE || curseg->next_blkoff || - get_valid_blocks(sbi, curseg->segno, false) || - get_ckpt_valid_blocks(sbi, curseg->segno)) { - old_segno = curseg->segno; - SIT_I(sbi)->s_ops->allocate_segment(sbi, i, true); - locate_dirty_segment(sbi, old_segno); - } - } - + for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) + __allocate_new_segment(sbi, i); up_write(&SIT_I(sbi)->sentry_lock); } From e12ef1e93518597ec682ec292ded296d8981543b Mon Sep 17 00:00:00 2001 From: Jia Yang Date: Wed, 1 Jul 2020 10:27:40 +0800 Subject: [PATCH 197/208] f2fs: add parameter op_flag in f2fs_submit_page_read() The parameter op_flag is not used in f2fs_get_read_data_page(), but it is used in f2fs_grab_read_bio(). Obviously, op_flag is not passed to f2fs_grab_read_bio() successfully. We need to add parameter in f2fs_submit_page_read() to pass it. The case: - gc_data_segment - f2fs_get_read_data_page(.., op_flag = REQ_RAHEAD,..) - f2fs_submit_page_read - f2fs_grab_read_bio(.., op_flag = 0, ..) Signed-off-by: Jia Yang Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 7bd77c627aac..f654b9c91d49 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1025,12 +1025,13 @@ static void f2fs_release_read_bio(struct bio *bio) /* This can handle encryption stuffs */ static int f2fs_submit_page_read(struct inode *inode, struct page *page, - block_t blkaddr, bool for_write) + block_t blkaddr, int op_flags, bool for_write) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct bio *bio; - bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0, page->index, for_write); + bio = f2fs_grab_read_bio(inode, blkaddr, 1, op_flags, + page->index, for_write); if (IS_ERR(bio)) return PTR_ERR(bio); @@ -1217,7 +1218,8 @@ got_it: return page; } - err = f2fs_submit_page_read(inode, page, dn.data_blkaddr, for_write); + err = f2fs_submit_page_read(inode, page, dn.data_blkaddr, + op_flags, for_write); if (err) goto put_err; return page; @@ -3408,7 +3410,7 @@ repeat: err = -EFSCORRUPTED; goto fail; } - err = f2fs_submit_page_read(inode, page, blkaddr, true); + err = f2fs_submit_page_read(inode, page, blkaddr, 0, true); if (err) goto fail; From e265a3c0496aa31226c72a5cbf6036600c12ee1f Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 1 Jul 2020 10:27:09 +0800 Subject: [PATCH 198/208] f2fs: fix return value of move_data_block() If f2fs_grab_cache_page() fails, it needs to return -ENOMEM. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/gc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 15cad446fdab..30dfac35db52 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -849,8 +849,10 @@ static int move_data_block(struct inode *inode, block_t bidx, mpage = f2fs_grab_cache_page(META_MAPPING(fio.sbi), fio.old_blkaddr, false); - if (!mpage) + if (!mpage) { + err = -ENOMEM; goto up_out; + } fio.encrypted_page = mpage; From e345d1d0664f4afec110815d0ef56cb58b453a86 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 22 Jun 2020 23:01:05 -0700 Subject: [PATCH 199/208] f2fs: avoid readahead race condition If two readahead threads having same offset enter in readpages, every read IOs are split and issued to the disk which giving lower bandwidth. This patch tries to avoid redundant readahead calls. Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 18 +++++++++++++++++- fs/f2fs/f2fs.h | 1 + fs/f2fs/super.c | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index f654b9c91d49..e05cf10c57e0 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2299,6 +2299,7 @@ int f2fs_mpage_readpages(struct address_space *mapping, #endif unsigned max_nr_pages = nr_pages; int ret = 0; + bool drop_ra = false; map.m_pblk = 0; map.m_lblk = 0; @@ -2309,13 +2310,25 @@ int f2fs_mpage_readpages(struct address_space *mapping, map.m_seg_type = NO_CHECK_TYPE; map.m_may_create = false; + /* + * Two readahead threads for same address range can cause race condition + * which fragments sequential read IOs. So let's avoid each other. + */ + if (pages && is_readahead) { + page = list_last_entry(pages, struct page, lru); + if (READ_ONCE(F2FS_I(inode)->ra_offset) == page_index(page)) + drop_ra = true; + else + WRITE_ONCE(F2FS_I(inode)->ra_offset, page_index(page)); + } + for (; nr_pages; nr_pages--) { if (pages) { page = list_last_entry(pages, struct page, lru); prefetchw(&page->flags); list_del(&page->lru); - if (add_to_page_cache_lru(page, mapping, + if (drop_ra || add_to_page_cache_lru(page, mapping, page_index(page), readahead_gfp_mask(mapping))) goto next_page; @@ -2380,6 +2393,9 @@ next_page: BUG_ON(pages && !list_empty(pages)); if (bio) __submit_bio(F2FS_I_SB(inode), bio, DATA); + + if (pages && is_readahead && !drop_ra) + WRITE_ONCE(F2FS_I(inode)->ra_offset, -1); return pages ? 0 : ret; } diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index f90c915fa7db..758c4f32a9c1 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -806,6 +806,7 @@ struct f2fs_inode_info { struct list_head inmem_pages; /* inmemory pages managed by f2fs */ struct task_struct *inmem_task; /* store inmemory task */ struct mutex inmem_lock; /* lock for inmemory pages */ + pgoff_t ra_offset; /* ongoing readahead offset */ struct extent_tree *extent_tree; /* cached extent_tree entry */ /* avoid racing between foreground op and gc */ diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 0712c5e6cd8b..18c0123286df 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1011,6 +1011,8 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) /* Will be used by directory only */ fi->i_dir_level = F2FS_SB(sb)->dir_level; + fi->ra_offset = -1; + return &fi->vfs_inode; } From 8913b25b116b421489e5f3ae4d254cfea5f947db Mon Sep 17 00:00:00 2001 From: Daeho Jeong Date: Tue, 30 Jun 2020 09:54:22 +0900 Subject: [PATCH 200/208] f2fs: add GC_URGENT_LOW mode in gc_urgent Added a new gc_urgent mode, GC_URGENT_LOW, in which mode F2FS will lower the bar of checking idle in order to process outstanding discard commands and GC a little bit aggressively. Signed-off-by: Daeho Jeong Signed-off-by: Jaegeuk Kim --- Documentation/ABI/testing/sysfs-fs-f2fs | 4 +++- fs/f2fs/f2fs.h | 10 ++++++++-- fs/f2fs/gc.c | 6 +++--- fs/f2fs/segment.c | 4 ++-- fs/f2fs/sysfs.c | 6 ++++-- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index f007cb671a47..cd58dd469ae7 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -229,7 +229,9 @@ Date: August 2017 Contact: "Jaegeuk Kim" Description: Do background GC agressively when set. When gc_urgent = 1, background thread starts to do GC by given gc_urgent_sleep_time - interval. It is set to 0 by default. + interval. When gc_urgent = 2, F2FS will lower the bar of + checking idle in order to process outstanding discard commands + and GC a little bit aggressively. It is set to 0 by default. What: /sys/fs/f2fs//gc_urgent_sleep_time Date: August 2017 diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 758c4f32a9c1..a2ea6595fa8e 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1280,7 +1280,8 @@ enum { GC_NORMAL, GC_IDLE_CB, GC_IDLE_GREEDY, - GC_URGENT, + GC_URGENT_HIGH, + GC_URGENT_LOW, }; enum { @@ -1536,6 +1537,7 @@ struct f2fs_sb_info { unsigned int cur_victim_sec; /* current victim section num */ unsigned int gc_mode; /* current GC state */ unsigned int next_victim_seg[2]; /* next segment in victim section */ + /* for skip statistic */ unsigned int atomic_files; /* # of opened atomic file */ unsigned long long skipped_atomic_files[2]; /* FG_GC and BG_GC */ @@ -2477,7 +2479,7 @@ static inline void *f2fs_kmem_cache_alloc(struct kmem_cache *cachep, static inline bool is_idle(struct f2fs_sb_info *sbi, int type) { - if (sbi->gc_mode == GC_URGENT) + if (sbi->gc_mode == GC_URGENT_HIGH) return true; if (get_pages(sbi, F2FS_RD_DATA) || get_pages(sbi, F2FS_RD_NODE) || @@ -2495,6 +2497,10 @@ static inline bool is_idle(struct f2fs_sb_info *sbi, int type) atomic_read(&SM_I(sbi)->fcc_info->queued_flush)) return false; + if (sbi->gc_mode == GC_URGENT_LOW && + (type == DISCARD_TIME || type == GC_TIME)) + return true; + return f2fs_time_over(sbi, type); } diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 30dfac35db52..a85cd0f39ab8 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -82,7 +82,7 @@ static int gc_thread_func(void *data) * invalidated soon after by user update or deletion. * So, I'd like to wait some time to collect dirty segments. */ - if (sbi->gc_mode == GC_URGENT) { + if (sbi->gc_mode == GC_URGENT_HIGH) { wait_ms = gc_th->urgent_sleep_time; down_write(&sbi->gc_lock); goto do_gc; @@ -176,7 +176,7 @@ static int select_gc_type(struct f2fs_sb_info *sbi, int gc_type) gc_mode = GC_CB; break; case GC_IDLE_GREEDY: - case GC_URGENT: + case GC_URGENT_HIGH: gc_mode = GC_GREEDY; break; } @@ -211,7 +211,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type, * foreground GC and urgent GC cases. */ if (gc_type != FG_GC && - (sbi->gc_mode != GC_URGENT) && + (sbi->gc_mode != GC_URGENT_HIGH) && p->max_search > sbi->max_victim_search) p->max_search = sbi->max_victim_search; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index d87ed33b64a3..543878c6222c 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -174,7 +174,7 @@ bool f2fs_need_SSR(struct f2fs_sb_info *sbi) if (f2fs_lfs_mode(sbi)) return false; - if (sbi->gc_mode == GC_URGENT) + if (sbi->gc_mode == GC_URGENT_HIGH) return true; if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) return true; @@ -1759,7 +1759,7 @@ static int issue_discard_thread(void *data) continue; } - if (sbi->gc_mode == GC_URGENT) + if (sbi->gc_mode == GC_URGENT_HIGH) __init_discard_policy(sbi, &dpolicy, DPOLICY_FORCE, 1); sb_start_intwrite(sbi->sb); diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 8f53ef414a2b..6b4cbda632ad 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -350,14 +350,16 @@ out: return -EINVAL; if (!strcmp(a->attr.name, "gc_urgent")) { - if (t >= 1) { - sbi->gc_mode = GC_URGENT; + if (t == 1) { + sbi->gc_mode = GC_URGENT_HIGH; if (sbi->gc_thread) { sbi->gc_thread->gc_wake = 1; wake_up_interruptible_all( &sbi->gc_thread->gc_wait_queue_head); wake_up_discard_thread(sbi, true); } + } else if (t == 2) { + sbi->gc_mode = GC_URGENT_LOW; } else { sbi->gc_mode = GC_NORMAL; } From 86e589c5b22aab405be5e77732c895693b355505 Mon Sep 17 00:00:00 2001 From: Daeho Jeong Date: Tue, 30 Jun 2020 09:56:25 +0900 Subject: [PATCH 201/208] f2fs: add symbolic link to kobject in sysfs Added a symbolic link to directory of sysfs. It will create a symbolic link such as "mount_0" and "mount_1" to each f2fs mount in the order of mounting filesystem. It will provide easy access to sysfs node even if not knowing the specific device node name like sda19 and dm-3. Signed-off-by: Daeho Jeong Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 4 ++++ fs/f2fs/sysfs.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index a2ea6595fa8e..5d8766786592 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1415,6 +1415,8 @@ struct decompress_io_ctx { #define MAX_COMPRESS_LOG_SIZE 8 #define MAX_COMPRESS_WINDOW_SIZE ((PAGE_SIZE) << MAX_COMPRESS_LOG_SIZE) +#define MOUNT_NAME_SIZE 20 + struct f2fs_sb_info { struct super_block *sb; /* pointer to VFS super block */ struct proc_dir_entry *s_proc; /* proc entry */ @@ -1595,6 +1597,8 @@ struct f2fs_sb_info { /* For sysfs suppport */ struct kobject s_kobj; struct completion s_kobj_unregister; + int s_mount_id; + char s_mount_name[MOUNT_NAME_SIZE]; /* For shrinker support */ struct list_head s_list; diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 6b4cbda632ad..139eb9b050d0 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -18,6 +18,7 @@ #include static struct proc_dir_entry *f2fs_proc_root; +static struct ida f2fs_mount_ida; /* Sysfs support for f2fs */ enum { @@ -922,6 +923,9 @@ int __init f2fs_init_sysfs(void) } else { f2fs_proc_root = proc_mkdir("fs/f2fs", NULL); } + + ida_init(&f2fs_mount_ida); + return ret; } @@ -931,6 +935,7 @@ void f2fs_exit_sysfs(void) kset_unregister(&f2fs_kset); remove_proc_entry("fs/f2fs", NULL); f2fs_proc_root = NULL; + ida_destroy(&f2fs_mount_ida); } int f2fs_register_sysfs(struct f2fs_sb_info *sbi) @@ -942,12 +947,22 @@ int f2fs_register_sysfs(struct f2fs_sb_info *sbi) init_completion(&sbi->s_kobj_unregister); err = kobject_init_and_add(&sbi->s_kobj, &f2fs_sb_ktype, NULL, "%s", sb->s_id); - if (err) { - kobject_put(&sbi->s_kobj); - wait_for_completion(&sbi->s_kobj_unregister); - return err; + if (err) + goto err1; + + sbi->s_mount_id = ida_simple_get(&f2fs_mount_ida, 0, 0, GFP_KERNEL); + if (sbi->s_mount_id < 0) { + err = sbi->s_mount_id; + goto err1; } + snprintf(sbi->s_mount_name, MOUNT_NAME_SIZE, "mount_%d", + sbi->s_mount_id); + err = sysfs_create_link(&f2fs_kset.kobj, &sbi->s_kobj, + sbi->s_mount_name); + if (err) + goto err2; + if (f2fs_proc_root) sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root); @@ -962,6 +977,12 @@ int f2fs_register_sysfs(struct f2fs_sb_info *sbi) &f2fs_seq_victim_bits_fops, sb); } return 0; +err2: + ida_simple_remove(&f2fs_mount_ida, sbi->s_mount_id); +err1: + kobject_put(&sbi->s_kobj); + wait_for_completion(&sbi->s_kobj_unregister); + return err; } void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi) @@ -973,6 +994,8 @@ void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi) remove_proc_entry("victim_bits", sbi->s_proc); remove_proc_entry(sbi->sb->s_id, f2fs_proc_root); } + sysfs_remove_link(&f2fs_kset.kobj, sbi->s_mount_name); + ida_simple_remove(&f2fs_mount_ida, sbi->s_mount_id); kobject_del(&sbi->s_kobj); kobject_put(&sbi->s_kobj); } From 416b1c0ee25eee076b60103b202361f79e542bb0 Mon Sep 17 00:00:00 2001 From: Alistair Delva Date: Wed, 1 Jul 2020 12:12:04 -0700 Subject: [PATCH 202/208] ANDROID: GKI: scripts: Makefile: update the lz4 command (#2) When the command was switched over from 'lz4c' to 'lz4', it changed the meaning of '-c' in a subtle way. In the older lz4c tool, this '-cX' seems to be a different flag, meaning the compression level. In the newer lz4 tool, it means to compress to stdout. However, since kbuild already specifies stdout as a file name, '-c' is superfluous, and generates a warning: Warning : stdout won't be used ! Do you want multiple input files (-m) ? Fix it by removing the extra stdout flag. Bug: 159285792 Bug: 160031736 Test: build/build.sh Signed-off-by: Alistair Delva Change-Id: I96247317ccb31f224c6a8e6e453cddde5e0c2550 --- scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 85a82e22b14f..bdd20ad3935d 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -364,7 +364,7 @@ cmd_lzo = (cat $(filter-out FORCE,$^) | \ quiet_cmd_lz4 = LZ4 $@ cmd_lz4 = (cat $(filter-out FORCE,$^) | \ - lz4 -c -l -12 --favor-decSpeed stdin stdout && \ + lz4 -l -12 --favor-decSpeed stdin stdout && \ $(call size_append, $(filter-out FORCE,$^))) > $@ || \ (rm -f $@ ; false) From addf3c0aafd53a3ae57e3750153cb0033f55d7a0 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Mon, 23 Jul 2018 18:50:38 -0700 Subject: [PATCH 203/208] iommu: io-pgtable-fast: Separate dma and io-pagetable layers The io-pgtable layer should be responsible for 1) Reading/modifying the pagetable 2) Performing cpu cache maintenance on the pagetable Remove code which does this from the DMA layer, and re-add it in the io-pgtable layer, if duplicate functionality does not already exist. Change-Id: I2250c0f574b933f524ff464f6539ea6db1699729 Signed-off-by: Patrick Daly Signed-off-by: UtsavBalar1231 --- drivers/iommu/arm-smmu.c | 2 +- drivers/iommu/dma-mapping-fast.c | 121 +++++++++++------------------- drivers/iommu/io-pgtable-fast.c | 124 ++++++++++++++++++++++--------- include/linux/dma-mapping-fast.h | 7 +- include/linux/io-pgtable-fast.h | 53 +++++++++++-- include/linux/iommu.h | 2 +- 6 files changed, 183 insertions(+), 126 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 954006f81b87..6b9e3e477b69 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -3521,7 +3521,7 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain, ret = -ENODEV; break; } - info->pmds = smmu_domain->pgtbl_cfg.av8l_fast_cfg.pmds; + info->ops = smmu_domain->pgtbl_ops; ret = 0; break; } diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c index 08deff94e783..11b2dfacd30f 100644 --- a/drivers/iommu/dma-mapping-fast.c +++ b/drivers/iommu/dma-mapping-fast.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -21,6 +21,7 @@ #include #include #include +#include "io-pgtable.h" #include #include @@ -29,14 +30,6 @@ #define FAST_PAGE_SHIFT 12 #define FAST_PAGE_SIZE (1UL << FAST_PAGE_SHIFT) #define FAST_PAGE_MASK (~(PAGE_SIZE - 1)) -#define FAST_PTE_ADDR_MASK ((av8l_fast_iopte)0xfffffffff000) -#define FAST_MAIR_ATTR_IDX_CACHE 1 -#define FAST_PTE_ATTRINDX_SHIFT 2 -#define FAST_PTE_ATTRINDX_MASK 0x7 -#define FAST_PTE_SH_SHIFT 8 -#define FAST_PTE_SH_MASK (((av8l_fast_iopte)0x3) << FAST_PTE_SH_SHIFT) -#define FAST_PTE_SH_OS (((av8l_fast_iopte)2) << FAST_PTE_SH_SHIFT) -#define FAST_PTE_SH_IS (((av8l_fast_iopte)3) << FAST_PTE_SH_SHIFT) static pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot, bool coherent) @@ -61,27 +54,6 @@ static int __get_iommu_pgprot(unsigned long attrs, int prot, return prot; } -static void fast_dmac_clean_range(struct dma_fast_smmu_mapping *mapping, - void *start, void *end) -{ - if (!mapping->is_smmu_pt_coherent) - dmac_clean_range(start, end); -} - -static bool __fast_is_pte_coherent(av8l_fast_iopte *ptep) -{ - int attr_idx = (*ptep & (FAST_PTE_ATTRINDX_MASK << - FAST_PTE_ATTRINDX_SHIFT)) >> - FAST_PTE_ATTRINDX_SHIFT; - - if ((attr_idx == FAST_MAIR_ATTR_IDX_CACHE) && - (((*ptep & FAST_PTE_SH_MASK) == FAST_PTE_SH_IS) || - (*ptep & FAST_PTE_SH_MASK) == FAST_PTE_SH_OS)) - return true; - - return false; -} - static bool is_dma_coherent(struct device *dev, unsigned long attrs) { bool is_coherent; @@ -201,7 +173,7 @@ static dma_addr_t __fast_smmu_alloc_iova(struct dma_fast_smmu_mapping *mapping, iommu_tlbiall(mapping->domain); mapping->have_stale_tlbs = false; - av8l_fast_clear_stale_ptes(mapping->pgtbl_pmds, skip_sync); + av8l_fast_clear_stale_ptes(mapping->pgtbl_ops, skip_sync); } iova = (bit << FAST_PAGE_SHIFT) + mapping->base; @@ -374,12 +346,10 @@ static dma_addr_t fast_smmu_map_page(struct device *dev, struct page *page, struct dma_fast_smmu_mapping *mapping = dev->archdata.mapping->fast; dma_addr_t iova; unsigned long flags; - av8l_fast_iopte *pmd; phys_addr_t phys_plus_off = page_to_phys(page) + offset; phys_addr_t phys_to_map = round_down(phys_plus_off, FAST_PAGE_SIZE); unsigned long offset_from_phys_to_map = phys_plus_off & ~FAST_PAGE_MASK; size_t len = ALIGN(size + offset_from_phys_to_map, FAST_PAGE_SIZE); - int nptes = len >> FAST_PAGE_SHIFT; bool skip_sync = (attrs & DMA_ATTR_SKIP_CPU_SYNC); int prot = __fast_dma_direction_to_prot(dir); bool is_coherent = is_dma_coherent(dev, attrs); @@ -397,13 +367,10 @@ static dma_addr_t fast_smmu_map_page(struct device *dev, struct page *page, if (unlikely(iova == DMA_ERROR_CODE)) goto fail; - pmd = iopte_pmd_offset(mapping->pgtbl_pmds, iova); - - if (unlikely(av8l_fast_map_public(pmd, phys_to_map, len, prot))) + if (unlikely(av8l_fast_map_public(mapping->pgtbl_ops, iova, + phys_to_map, len, prot))) goto fail_free_iova; - fast_dmac_clean_range(mapping, pmd, pmd + nptes); - spin_unlock_irqrestore(&mapping->lock, flags); trace_map(mapping->domain, iova, phys_to_map, len, prot); @@ -422,20 +389,23 @@ static void fast_smmu_unmap_page(struct device *dev, dma_addr_t iova, { struct dma_fast_smmu_mapping *mapping = dev->archdata.mapping->fast; unsigned long flags; - av8l_fast_iopte *pmd = iopte_pmd_offset(mapping->pgtbl_pmds, iova); unsigned long offset = iova & ~FAST_PAGE_MASK; size_t len = ALIGN(size + offset, FAST_PAGE_SIZE); - int nptes = len >> FAST_PAGE_SHIFT; - struct page *page = phys_to_page((*pmd & FAST_PTE_ADDR_MASK)); bool skip_sync = (attrs & DMA_ATTR_SKIP_CPU_SYNC); bool is_coherent = is_dma_coherent(dev, attrs); - if (!skip_sync && !is_coherent) - __fast_dma_page_dev_to_cpu(page, offset, size, dir); + if (!skip_sync && !is_coherent) { + phys_addr_t phys; + + phys = av8l_fast_iova_to_phys_public(mapping->pgtbl_ops, iova); + WARN_ON(!phys); + + __fast_dma_page_dev_to_cpu(phys_to_page(phys), offset, + size, dir); + } spin_lock_irqsave(&mapping->lock, flags); - av8l_fast_unmap_public(pmd, len); - fast_dmac_clean_range(mapping, pmd, pmd + nptes); + av8l_fast_unmap_public(mapping->pgtbl_ops, iova, len); __fast_smmu_free_iova(mapping, iova - offset, len); spin_unlock_irqrestore(&mapping->lock, flags); @@ -446,24 +416,34 @@ static void fast_smmu_sync_single_for_cpu(struct device *dev, dma_addr_t iova, size_t size, enum dma_data_direction dir) { struct dma_fast_smmu_mapping *mapping = dev->archdata.mapping->fast; - av8l_fast_iopte *pmd = iopte_pmd_offset(mapping->pgtbl_pmds, iova); unsigned long offset = iova & ~FAST_PAGE_MASK; - struct page *page = phys_to_page((*pmd & FAST_PTE_ADDR_MASK)); - if (!__fast_is_pte_coherent(pmd)) - __fast_dma_page_dev_to_cpu(page, offset, size, dir); + if (!av8l_fast_iova_coherent_public(mapping->pgtbl_ops, iova)) { + phys_addr_t phys; + + phys = av8l_fast_iova_to_phys_public(mapping->pgtbl_ops, iova); + WARN_ON(!phys); + + __fast_dma_page_dev_to_cpu(phys_to_page(phys), offset, + size, dir); + } } static void fast_smmu_sync_single_for_device(struct device *dev, dma_addr_t iova, size_t size, enum dma_data_direction dir) { struct dma_fast_smmu_mapping *mapping = dev->archdata.mapping->fast; - av8l_fast_iopte *pmd = iopte_pmd_offset(mapping->pgtbl_pmds, iova); unsigned long offset = iova & ~FAST_PAGE_MASK; - struct page *page = phys_to_page((*pmd & FAST_PTE_ADDR_MASK)); - if (!__fast_is_pte_coherent(pmd)) - __fast_dma_page_cpu_to_dev(page, offset, size, dir); + if (!av8l_fast_iova_coherent_public(mapping->pgtbl_ops, iova)) { + phys_addr_t phys; + + phys = av8l_fast_iova_to_phys_public(mapping->pgtbl_ops, iova); + WARN_ON(!phys); + + __fast_dma_page_cpu_to_dev(phys_to_page(phys), offset, + size, dir); + } } static int fast_smmu_map_sg(struct device *dev, struct scatterlist *sg, @@ -538,7 +518,6 @@ static void *fast_smmu_alloc(struct device *dev, size_t size, struct sg_table sgt; dma_addr_t dma_addr, iova_iter; void *addr; - av8l_fast_iopte *ptep; unsigned long flags; struct sg_mapping_iter miter; size_t count = ALIGN(size, SZ_4K) >> PAGE_SHIFT; @@ -596,17 +575,14 @@ static void *fast_smmu_alloc(struct device *dev, size_t size, sg_miter_start(&miter, sgt.sgl, sgt.orig_nents, SG_MITER_FROM_SG | SG_MITER_ATOMIC); while (sg_miter_next(&miter)) { - int nptes = miter.length >> FAST_PAGE_SHIFT; - - ptep = iopte_pmd_offset(mapping->pgtbl_pmds, iova_iter); if (unlikely(av8l_fast_map_public( - ptep, page_to_phys(miter.page), + mapping->pgtbl_ops, iova_iter, + page_to_phys(miter.page), miter.length, prot))) { dev_err(dev, "no map public\n"); /* TODO: unwind previously successful mappings */ goto out_free_iova; } - fast_dmac_clean_range(mapping, ptep, ptep + nptes); iova_iter += miter.length; } sg_miter_stop(&miter); @@ -626,9 +602,7 @@ static void *fast_smmu_alloc(struct device *dev, size_t size, out_unmap: /* need to take the lock again for page tables and iova */ spin_lock_irqsave(&mapping->lock, flags); - ptep = iopte_pmd_offset(mapping->pgtbl_pmds, dma_addr); - av8l_fast_unmap_public(ptep, size); - fast_dmac_clean_range(mapping, ptep, ptep + count); + av8l_fast_unmap_public(mapping->pgtbl_ops, dma_addr, size); out_free_iova: __fast_smmu_free_iova(mapping, dma_addr, size); spin_unlock_irqrestore(&mapping->lock, flags); @@ -647,7 +621,6 @@ static void fast_smmu_free(struct device *dev, size_t size, struct vm_struct *area; struct page **pages; size_t count = ALIGN(size, SZ_4K) >> FAST_PAGE_SHIFT; - av8l_fast_iopte *ptep; unsigned long flags; size = ALIGN(size, SZ_4K); @@ -658,10 +631,8 @@ static void fast_smmu_free(struct device *dev, size_t size, pages = area->pages; dma_common_free_remap(vaddr, size, VM_USERMAP, false); - ptep = iopte_pmd_offset(mapping->pgtbl_pmds, dma_handle); spin_lock_irqsave(&mapping->lock, flags); - av8l_fast_unmap_public(ptep, size); - fast_dmac_clean_range(mapping, ptep, ptep + count); + av8l_fast_unmap_public(mapping->pgtbl_ops, dma_handle, size); __fast_smmu_free_iova(mapping, dma_handle, size); spin_unlock_irqrestore(&mapping->lock, flags); __fast_smmu_free_pages(pages, count); @@ -767,16 +738,20 @@ static int fast_smmu_mapping_error(struct device *dev, static void __fast_smmu_mapped_over_stale(struct dma_fast_smmu_mapping *fast, void *data) { - av8l_fast_iopte *ptep = data; + av8l_fast_iopte *pmds, *ptep = data; dma_addr_t iova; unsigned long bitmap_idx; + struct io_pgtable *tbl; - bitmap_idx = (unsigned long)(ptep - fast->pgtbl_pmds); + tbl = container_of(fast->pgtbl_ops, struct io_pgtable, ops); + pmds = tbl->cfg.av8l_fast_cfg.pmds; + + bitmap_idx = (unsigned long)(ptep - pmds); iova = bitmap_idx << FAST_PAGE_SHIFT; dev_err(fast->dev, "Mapped over stale tlb at %pa\n", &iova); dev_err(fast->dev, "bitmap (failure at idx %lu):\n", bitmap_idx); dev_err(fast->dev, "ptep: %p pmds: %p diff: %lu\n", ptep, - fast->pgtbl_pmds, bitmap_idx); + pmds, bitmap_idx); print_hex_dump(KERN_ERR, "bmap: ", DUMP_PREFIX_ADDRESS, 32, 8, fast->bitmap, fast->bitmap_size, false); } @@ -963,13 +938,7 @@ int fast_smmu_init_mapping(struct device *dev, err = -EINVAL; goto release_mapping; } - mapping->fast->pgtbl_pmds = info.pmds; - - if (iommu_domain_get_attr(domain, DOMAIN_ATTR_PAGE_TABLE_IS_COHERENT, - &mapping->fast->is_smmu_pt_coherent)) { - err = -EINVAL; - goto release_mapping; - } + mapping->fast->pgtbl_ops = (struct io_pgtable_ops *)info.ops; mapping->fast->notifier.notifier_call = fast_smmu_notify; av8l_register_notify(&mapping->fast->notifier); diff --git a/drivers/iommu/io-pgtable-fast.c b/drivers/iommu/io-pgtable-fast.c index bf34c646fe57..850b92fa40cc 100644 --- a/drivers/iommu/io-pgtable-fast.c +++ b/drivers/iommu/io-pgtable-fast.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -58,6 +58,7 @@ struct av8l_fast_io_pgtable { #define AV8L_FAST_PTE_SH_NS (((av8l_fast_iopte)0) << 8) #define AV8L_FAST_PTE_SH_OS (((av8l_fast_iopte)2) << 8) #define AV8L_FAST_PTE_SH_IS (((av8l_fast_iopte)3) << 8) +#define AV8L_FAST_PTE_SH_MASK (((av8l_fast_iopte)3) << 8) #define AV8L_FAST_PTE_NS (((av8l_fast_iopte)1) << 5) #define AV8L_FAST_PTE_VALID (((av8l_fast_iopte)1) << 0) @@ -75,6 +76,7 @@ struct av8l_fast_io_pgtable { #define AV8L_FAST_PTE_AP_PRIV_RO (((av8l_fast_iopte)2) << 6) #define AV8L_FAST_PTE_AP_RO (((av8l_fast_iopte)3) << 6) #define AV8L_FAST_PTE_ATTRINDX_SHIFT 2 +#define AV8L_FAST_PTE_ATTRINDX_MASK 0x7 #define AV8L_FAST_PTE_nG (((av8l_fast_iopte)1) << 11) /* Stage-2 PTE */ @@ -142,6 +144,13 @@ struct av8l_fast_io_pgtable { #define AV8L_FAST_PAGE_SHIFT 12 +#define PTE_MAIR_IDX(pte) \ + ((pte >> AV8L_FAST_PTE_ATTRINDX_SHIFT) && \ + AV8L_FAST_PTE_ATTRINDX_MASK) + +#define PTE_SH_IDX(pte) (pte & AV8L_FAST_PTE_SH_MASK) + +#define iopte_pmd_offset(pmds, iova) (pmds + (iova >> 12)) #ifdef CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB @@ -170,10 +179,11 @@ static void __av8l_check_for_stale_tlb(av8l_fast_iopte *ptep) } } -void av8l_fast_clear_stale_ptes(av8l_fast_iopte *pmds, bool skip_sync) +void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, bool skip_sync) { int i; - av8l_fast_iopte *pmdp = pmds; + struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); + av8l_fast_iopte *pmdp = data->pmds; for (i = 0; i < ((SZ_1G * 4UL) >> AV8L_FAST_PAGE_SHIFT); ++i) { if (!(*pmdp & AV8L_FAST_PTE_VALID)) { @@ -190,11 +200,18 @@ static void __av8l_check_for_stale_tlb(av8l_fast_iopte *ptep) } #endif -/* caller must take care of cache maintenance on *ptep */ -int av8l_fast_map_public(av8l_fast_iopte *ptep, phys_addr_t paddr, size_t size, - int prot) +static void av8l_clean_range(struct io_pgtable_ops *ops, + av8l_fast_iopte *start, av8l_fast_iopte *end) +{ + struct io_pgtable *iop = iof_pgtable_ops_to_pgtable(ops); + + if (!(iop->cfg.quirks & IO_PGTABLE_QUIRK_NO_DMA)) + dmac_clean_range(start, end); +} + +static av8l_fast_iopte +av8l_fast_prot_to_pte(struct av8l_fast_io_pgtable *data, int prot) { - int i, nptes = size >> AV8L_FAST_PAGE_SHIFT; av8l_fast_iopte pte = AV8L_FAST_PTE_XN | AV8L_FAST_PTE_TYPE_PAGE | AV8L_FAST_PTE_AF @@ -216,13 +233,7 @@ int av8l_fast_map_public(av8l_fast_iopte *ptep, phys_addr_t paddr, size_t size, else pte |= AV8L_FAST_PTE_AP_RW; - paddr &= AV8L_FAST_PTE_ADDR_MASK; - for (i = 0; i < nptes; i++, paddr += SZ_4K) { - __av8l_check_for_stale_tlb(ptep + i); - *(ptep + i) = pte | paddr; - } - - return 0; + return pte; } static int av8l_fast_map(struct io_pgtable_ops *ops, unsigned long iova, @@ -230,44 +241,59 @@ static int av8l_fast_map(struct io_pgtable_ops *ops, unsigned long iova, { struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); av8l_fast_iopte *ptep = iopte_pmd_offset(data->pmds, iova); - unsigned long nptes = size >> AV8L_FAST_PAGE_SHIFT; + unsigned long i, nptes = size >> AV8L_FAST_PAGE_SHIFT; + av8l_fast_iopte pte; - av8l_fast_map_public(ptep, paddr, size, prot); - dmac_clean_range(ptep, ptep + nptes); + pte = av8l_fast_prot_to_pte(data, prot); + paddr &= AV8L_FAST_PTE_ADDR_MASK; + for (i = 0; i < nptes; i++, paddr += SZ_4K) { + __av8l_check_for_stale_tlb(ptep + i); + *(ptep + i) = pte | paddr; + } + av8l_clean_range(ops, ptep, ptep + nptes); return 0; } -static void __av8l_fast_unmap(av8l_fast_iopte *ptep, size_t size, - bool need_stale_tlb_tracking) +int av8l_fast_map_public(struct io_pgtable_ops *ops, unsigned long iova, + phys_addr_t paddr, size_t size, int prot) { - unsigned long nptes = size >> AV8L_FAST_PAGE_SHIFT; - int val = need_stale_tlb_tracking + return av8l_fast_map(ops, iova, paddr, size, prot); +} + +static size_t +__av8l_fast_unmap(struct io_pgtable_ops *ops, unsigned long iova, + size_t size, bool allow_stale_tlb) +{ + struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); + unsigned long nptes; + av8l_fast_iopte *ptep; + int val = allow_stale_tlb ? AV8L_FAST_PTE_UNMAPPED_NEED_TLBI : 0; + ptep = iopte_pmd_offset(data->pmds, iova); + nptes = size >> AV8L_FAST_PAGE_SHIFT; + memset(ptep, val, sizeof(*ptep) * nptes); + av8l_clean_range(ops, ptep, ptep + nptes); + if (!allow_stale_tlb) + io_pgtable_tlb_flush_all(&data->iop); + + return size; } -/* caller must take care of cache maintenance on *ptep */ -void av8l_fast_unmap_public(av8l_fast_iopte *ptep, size_t size) +/* caller must take care of tlb cache maintenance */ +void av8l_fast_unmap_public(struct io_pgtable_ops *ops, unsigned long iova, + size_t size) { - __av8l_fast_unmap(ptep, size, true); + __av8l_fast_unmap(ops, iova, size, true); } static size_t av8l_fast_unmap(struct io_pgtable_ops *ops, unsigned long iova, size_t size) { - struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); - struct io_pgtable *iop = &data->iop; - av8l_fast_iopte *ptep = iopte_pmd_offset(data->pmds, iova); - unsigned long nptes = size >> AV8L_FAST_PAGE_SHIFT; - - __av8l_fast_unmap(ptep, size, false); - dmac_clean_range(ptep, ptep + nptes); - io_pgtable_tlb_flush_all(iop); - - return size; + return __av8l_fast_unmap(ops, iova, size, false); } #if defined(CONFIG_ARM64) @@ -312,6 +338,12 @@ static phys_addr_t av8l_fast_iova_to_phys(struct io_pgtable_ops *ops, return phys | (iova & 0xfff); } +phys_addr_t av8l_fast_iova_to_phys_public(struct io_pgtable_ops *ops, + unsigned long iova) +{ + return av8l_fast_iova_to_phys(ops, iova); +} + static int av8l_fast_map_sg(struct io_pgtable_ops *ops, unsigned long iova, struct scatterlist *sg, unsigned int nents, int prot, size_t *size) @@ -319,6 +351,23 @@ static int av8l_fast_map_sg(struct io_pgtable_ops *ops, unsigned long iova, return -ENODEV; } +static bool av8l_fast_iova_coherent(struct io_pgtable_ops *ops, + unsigned long iova) +{ + struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); + av8l_fast_iopte *ptep = iopte_pmd_offset(data->pmds, iova); + + return ((PTE_MAIR_IDX(*ptep) == AV8L_FAST_MAIR_ATTR_IDX_CACHE) && + ((PTE_SH_IDX(*ptep) == AV8L_FAST_PTE_SH_OS) || + (PTE_SH_IDX(*ptep) == AV8L_FAST_PTE_SH_IS))); +} + +bool av8l_fast_iova_coherent_public(struct io_pgtable_ops *ops, + unsigned long iova) +{ + return av8l_fast_iova_coherent(ops, iova); +} + static struct av8l_fast_io_pgtable * av8l_fast_alloc_pgtable_data(struct io_pgtable_cfg *cfg) { @@ -333,6 +382,7 @@ av8l_fast_alloc_pgtable_data(struct io_pgtable_cfg *cfg) .map_sg = av8l_fast_map_sg, .unmap = av8l_fast_unmap, .iova_to_phys = av8l_fast_iova_to_phys, + .is_iova_coherent = av8l_fast_iova_coherent, }; return data; @@ -641,7 +691,7 @@ static int __init av8l_fast_positive_testing(void) } /* sweep up TLB proving PTEs */ - av8l_fast_clear_stale_ptes(pmds, false); + av8l_fast_clear_stale_ptes(ops, false); /* map the entire 4GB VA space with 8K map calls */ for (iova = 0; iova < max; iova += SZ_8K) { @@ -662,7 +712,7 @@ static int __init av8l_fast_positive_testing(void) } /* sweep up TLB proving PTEs */ - av8l_fast_clear_stale_ptes(pmds, false); + av8l_fast_clear_stale_ptes(ops, false); /* map the entire 4GB VA space with 16K map calls */ for (iova = 0; iova < max; iova += SZ_16K) { @@ -683,7 +733,7 @@ static int __init av8l_fast_positive_testing(void) } /* sweep up TLB proving PTEs */ - av8l_fast_clear_stale_ptes(pmds, false); + av8l_fast_clear_stale_ptes(ops, false); /* map the entire 4GB VA space with 64K map calls */ for (iova = 0; iova < max; iova += SZ_64K) { diff --git a/include/linux/dma-mapping-fast.h b/include/linux/dma-mapping-fast.h index e9dabab33a48..b0d821e04424 100644 --- a/include/linux/dma-mapping-fast.h +++ b/include/linux/dma-mapping-fast.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -17,6 +17,7 @@ #include struct dma_iommu_mapping; +struct io_pgtable_ops; struct dma_fast_smmu_mapping { struct device *dev; @@ -35,12 +36,10 @@ struct dma_fast_smmu_mapping { bool have_stale_tlbs; dma_addr_t pgtbl_dma_handle; - av8l_fast_iopte *pgtbl_pmds; + struct io_pgtable_ops *pgtbl_ops; spinlock_t lock; struct notifier_block notifier; - - int is_smmu_pt_coherent; }; #ifdef CONFIG_IOMMU_IO_PGTABLE_FAST diff --git a/include/linux/io-pgtable-fast.h b/include/linux/io-pgtable-fast.h index 78b069369eb7..f5a6f0eb1c69 100644 --- a/include/linux/io-pgtable-fast.h +++ b/include/linux/io-pgtable-fast.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -15,13 +15,52 @@ #include +/* + * This ought to be private to io-pgtable-fast, but dma-mapping-fast + * currently requires it for a debug usecase. + */ typedef u64 av8l_fast_iopte; -#define iopte_pmd_offset(pmds, iova) (pmds + (iova >> 12)) +struct io_pgtable_ops; + +#ifdef CONFIG_IOMMU_IO_PGTABLE_FAST + +int av8l_fast_map_public(struct io_pgtable_ops *ops, unsigned long iova, + phys_addr_t paddr, size_t size, int prot); + +void av8l_fast_unmap_public(struct io_pgtable_ops *ops, unsigned long iova, + size_t size); + +bool av8l_fast_iova_coherent_public(struct io_pgtable_ops *ops, + unsigned long iova); + +phys_addr_t av8l_fast_iova_to_phys_public(struct io_pgtable_ops *ops, + unsigned long iova); +#else +static inline int +av8l_fast_map_public(struct io_pgtable_ops *ops, unsigned long iova, + phys_addr_t paddr, size_t size, int prot) +{ + return -EINVAL; +} +static inline void av8l_fast_unmap_public(struct io_pgtable_ops *ops, + unsigned long iova, size_t size) +{ +} + +static inline bool av8l_fast_iova_coherent_public(struct io_pgtable_ops *ops, + unsigned long iova) +{ + return false; +} +static inline phys_addr_t +av8l_fast_iova_to_phys_public(struct io_pgtable_ops *ops, + unsigned long iova) +{ + return 0; +} +#endif /* CONFIG_IOMMU_IO_PGTABLE_FAST */ -int av8l_fast_map_public(av8l_fast_iopte *ptep, phys_addr_t paddr, size_t size, - int prot); -void av8l_fast_unmap_public(av8l_fast_iopte *ptep, size_t size); /* events for notifiers passed to av8l_register_notify */ #define MAPPED_OVER_STALE_TLB 1 @@ -36,14 +75,14 @@ void av8l_fast_unmap_public(av8l_fast_iopte *ptep, size_t size); */ #define AV8L_FAST_PTE_UNMAPPED_NEED_TLBI 0xa -void av8l_fast_clear_stale_ptes(av8l_fast_iopte *puds, bool skip_sync); +void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, bool skip_sync); void av8l_register_notify(struct notifier_block *nb); #else /* !CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB */ #define AV8L_FAST_PTE_UNMAPPED_NEED_TLBI 0 -static inline void av8l_fast_clear_stale_ptes(av8l_fast_iopte *puds, +static inline void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, bool skip_sync) { } diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 3e4f4fedda98..2c9fffc697fb 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -74,7 +74,7 @@ struct iommu_domain_geometry { }; struct iommu_pgtbl_info { - void *pmds; + void *ops; }; /* Domain feature flags */ From df1d261e09adb9afb3f1af8f2b7e2876a4466d84 Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Wed, 15 Feb 2017 16:43:01 +0530 Subject: [PATCH 204/208] iommu/io-pgtable-fast: optimize statically allocated pages Presently fastmap iommu feature allocates page tables for full 4GB virtual address space. This can be optimized to consider virtual address range [base, size] needed by client and prepare page tables only for applicable region. CRs-Fixed: 2011508 Change-Id: Ie6c23cb8e1702a823567e126f452b1e72d851f71 Signed-off-by: Shiraz Hashim Signed-off-by: Prakash Gupta Signed-off-by: UtsavBalar1231 --- drivers/iommu/arm-smmu.c | 10 +++ drivers/iommu/dma-mapping-fast.c | 9 ++- drivers/iommu/io-pgtable-fast.c | 117 ++++++++++++++++++++----------- drivers/iommu/io-pgtable.h | 2 + include/linux/io-pgtable-fast.h | 7 +- 5 files changed, 102 insertions(+), 43 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 6b9e3e477b69..c90b1bcf311b 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -2223,6 +2223,8 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, }, .tlb = tlb_ops, .iommu_dev = smmu->dev, + .iova_base = domain->geometry.aperture_start, + .iova_end = domain->geometry.aperture_end, }; fmt = ARM_MSM_SECURE; } else { @@ -2233,6 +2235,8 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, .oas = oas, .tlb = tlb_ops, .iommu_dev = smmu->dev, + .iova_base = domain->geometry.aperture_start, + .iova_end = domain->geometry.aperture_end, }; } @@ -2257,6 +2261,12 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, domain->pgsize_bitmap = smmu_domain->pgtbl_cfg.pgsize_bitmap; domain->geometry.aperture_end = (1UL << ias) - 1; domain->geometry.force_aperture = true; + if (smmu_domain->attributes & (1 << DOMAIN_ATTR_FAST)) { + domain->geometry.aperture_start = + smmu_domain->pgtbl_cfg.iova_base; + domain->geometry.aperture_end = + smmu_domain->pgtbl_cfg.iova_end; + } /* Assign an asid */ ret = arm_smmu_init_asid(domain, smmu); diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c index 11b2dfacd30f..68e97f1e88d2 100644 --- a/drivers/iommu/dma-mapping-fast.c +++ b/drivers/iommu/dma-mapping-fast.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -173,7 +173,9 @@ static dma_addr_t __fast_smmu_alloc_iova(struct dma_fast_smmu_mapping *mapping, iommu_tlbiall(mapping->domain); mapping->have_stale_tlbs = false; - av8l_fast_clear_stale_ptes(mapping->pgtbl_ops, skip_sync); + av8l_fast_clear_stale_ptes(mapping->pgtbl_ops, mapping->base, + mapping->base + mapping->size - 1, + skip_sync); } iova = (bit << FAST_PAGE_SHIFT) + mapping->base; @@ -932,6 +934,9 @@ int fast_smmu_init_mapping(struct device *dev, fast_smmu_reserve_pci_windows(dev, mapping->fast); + domain->geometry.aperture_start = mapping->base; + domain->geometry.aperture_end = mapping->base + size - 1; + if (iommu_domain_get_attr(domain, DOMAIN_ATTR_PGTBL_INFO, &info)) { dev_err(dev, "Couldn't get page table info\n"); diff --git a/drivers/iommu/io-pgtable-fast.c b/drivers/iommu/io-pgtable-fast.c index 850b92fa40cc..cdcf77097abf 100644 --- a/drivers/iommu/io-pgtable-fast.c +++ b/drivers/iommu/io-pgtable-fast.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,9 @@ struct av8l_fast_io_pgtable { av8l_fast_iopte *puds[4]; av8l_fast_iopte *pmds; struct page **pages; /* page table memory */ + int nr_pages; + dma_addr_t base; + dma_addr_t end; }; /* Page table bits */ @@ -150,7 +154,7 @@ struct av8l_fast_io_pgtable { #define PTE_SH_IDX(pte) (pte & AV8L_FAST_PTE_SH_MASK) -#define iopte_pmd_offset(pmds, iova) (pmds + (iova >> 12)) +#define iopte_pmd_offset(pmds, base, iova) (pmds + ((iova - base) >> 12)) #ifdef CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB @@ -179,13 +183,15 @@ static void __av8l_check_for_stale_tlb(av8l_fast_iopte *ptep) } } -void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, bool skip_sync) +void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, u64 base, + u64 end, bool skip_sync) { int i; struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); av8l_fast_iopte *pmdp = data->pmds; - for (i = 0; i < ((SZ_1G * 4UL) >> AV8L_FAST_PAGE_SHIFT); ++i) { + for (i = base >> AV8L_FAST_PAGE_SHIFT; + i <= (end >> AV8L_FAST_PAGE_SHIFT); ++i) { if (!(*pmdp & AV8L_FAST_PTE_VALID)) { *pmdp = 0; if (!skip_sync) @@ -240,7 +246,7 @@ static int av8l_fast_map(struct io_pgtable_ops *ops, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); - av8l_fast_iopte *ptep = iopte_pmd_offset(data->pmds, iova); + av8l_fast_iopte *ptep = iopte_pmd_offset(data->pmds, data->base, iova); unsigned long i, nptes = size >> AV8L_FAST_PAGE_SHIFT; av8l_fast_iopte pte; @@ -272,7 +278,7 @@ __av8l_fast_unmap(struct io_pgtable_ops *ops, unsigned long iova, ? AV8L_FAST_PTE_UNMAPPED_NEED_TLBI : 0; - ptep = iopte_pmd_offset(data->pmds, iova); + ptep = iopte_pmd_offset(data->pmds, data->base, iova); nptes = size >> AV8L_FAST_PAGE_SHIFT; memset(ptep, val, sizeof(*ptep) * nptes); @@ -355,7 +361,7 @@ static bool av8l_fast_iova_coherent(struct io_pgtable_ops *ops, unsigned long iova) { struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); - av8l_fast_iopte *ptep = iopte_pmd_offset(data->pmds, iova); + av8l_fast_iopte *ptep = iopte_pmd_offset(data->pmds, data->base, iova); return ((PTE_MAIR_IDX(*ptep) == AV8L_FAST_MAIR_ATTR_IDX_CACHE) && ((PTE_SH_IDX(*ptep) == AV8L_FAST_PTE_SH_OS) || @@ -389,7 +395,7 @@ av8l_fast_alloc_pgtable_data(struct io_pgtable_cfg *cfg) } /* - * We need 1 page for the pgd, 4 pages for puds (1GB VA per pud page) and + * We need max 1 page for the pgd, 4 pages for puds (1GB VA per pud page) and * 2048 pages for pmds (each pud page contains 512 table entries, each * pointing to a pmd). */ @@ -398,12 +404,38 @@ av8l_fast_alloc_pgtable_data(struct io_pgtable_cfg *cfg) #define NUM_PMD_PAGES 2048 #define NUM_PGTBL_PAGES (NUM_PGD_PAGES + NUM_PUD_PAGES + NUM_PMD_PAGES) +/* undefine arch specific definitions which depends on page table format */ +#undef pud_index +#undef pud_mask +#undef pud_next +#undef pmd_index +#undef pmd_mask +#undef pmd_next + +#define pud_index(addr) (((addr) >> 30) & 0x3) +#define pud_mask(addr) ((addr) & ~((1UL << 30) - 1)) +#define pud_next(addr, end) \ +({ unsigned long __boundary = pud_mask(addr + (1UL << 30));\ + (__boundary - 1 < (end) - 1) ? __boundary : (end); \ +}) + +#define pmd_index(addr) (((addr) >> 21) & 0x1ff) +#define pmd_mask(addr) ((addr) & ~((1UL << 21) - 1)) +#define pmd_next(addr, end) \ +({ unsigned long __boundary = pmd_mask(addr + (1UL << 21));\ + (__boundary - 1 < (end) - 1) ? __boundary : (end); \ +}) + static int av8l_fast_prepopulate_pgtables(struct av8l_fast_io_pgtable *data, struct io_pgtable_cfg *cfg, void *cookie) { int i, j, pg = 0; struct page **pages, *page; + dma_addr_t base = cfg->iova_base; + dma_addr_t end = cfg->iova_end; + dma_addr_t pud, pmd; + int pmd_pg_index; pages = kmalloc(sizeof(*pages) * NUM_PGTBL_PAGES, __GFP_NOWARN | __GFP_NORETRY); @@ -421,10 +453,11 @@ av8l_fast_prepopulate_pgtables(struct av8l_fast_io_pgtable *data, data->pgd = page_address(page); /* - * We need 2048 entries at level 2 to map 4GB of VA space. A page - * can hold 512 entries, so we need 4 pages. + * We need max 2048 entries at level 2 to map 4GB of VA space. A page + * can hold 512 entries, so we need max 4 pages. */ - for (i = 0; i < 4; ++i) { + for (i = pud_index(base), pud = base; pud < end; + ++i, pud = pud_next(pud, end)) { av8l_fast_iopte pte, *ptep; page = alloc_page(GFP_KERNEL | __GFP_ZERO); @@ -439,12 +472,15 @@ av8l_fast_prepopulate_pgtables(struct av8l_fast_io_pgtable *data, dmac_clean_range(data->pgd, data->pgd + 4); /* - * We have 4 puds, each of which can point to 512 pmds, so we'll - * have 2048 pmds, each of which can hold 512 ptes, for a grand + * We have max 4 puds, each of which can point to 512 pmds, so we'll + * have max 2048 pmds, each of which can hold 512 ptes, for a grand * total of 2048*512=1048576 PTEs. */ - for (i = 0; i < 4; ++i) { - for (j = 0; j < 512; ++j) { + pmd_pg_index = pg; + for (i = pud_index(base), pud = base; pud < end; + ++i, pud = pud_next(pud, end)) { + for (j = pmd_index(pud), pmd = pud; pmd < pud_next(pud, end); + ++j, pmd = pmd_next(pmd, end)) { av8l_fast_iopte pte, *pudp; void *addr; @@ -463,21 +499,21 @@ av8l_fast_prepopulate_pgtables(struct av8l_fast_io_pgtable *data, dmac_clean_range(data->puds[i], data->puds[i] + 512); } - if (WARN_ON(pg != NUM_PGTBL_PAGES)) - goto err_free_pages; - /* * We map the pmds into a virtually contiguous space so that we * don't have to traverse the first two levels of the page tables * to find the appropriate pud. Instead, it will be a simple * offset from the virtual base of the pmds. */ - data->pmds = vmap(&pages[NUM_PGD_PAGES + NUM_PUD_PAGES], NUM_PMD_PAGES, + data->pmds = vmap(&pages[pmd_pg_index], pg - pmd_pg_index, VM_IOREMAP, PAGE_KERNEL); if (!data->pmds) goto err_free_pages; data->pages = pages; + data->nr_pages = pg; + data->base = base; + data->end = end; return 0; err_free_pages: @@ -583,7 +619,7 @@ static void av8l_fast_free_pgtable(struct io_pgtable *iop) struct av8l_fast_io_pgtable *data = iof_pgtable_to_data(iop); vunmap(data->pmds); - for (i = 0; i < NUM_PGTBL_PAGES; ++i) + for (i = 0; i < data->nr_pages; ++i) __free_page(data->pages[i]); kvfree(data->pages); kfree(data); @@ -655,6 +691,7 @@ static int __init av8l_fast_positive_testing(void) struct av8l_fast_io_pgtable *data; av8l_fast_iopte *pmds; u64 max = SZ_1G * 4ULL - 1; + u64 base = 0; cfg = (struct io_pgtable_cfg) { .quirks = 0, @@ -662,6 +699,8 @@ static int __init av8l_fast_positive_testing(void) .ias = 32, .oas = 32, .pgsize_bitmap = SZ_4K, + .iova_base = base, + .iova_end = max, }; cfg_cookie = &cfg; @@ -674,81 +713,81 @@ static int __init av8l_fast_positive_testing(void) pmds = data->pmds; /* map the entire 4GB VA space with 4K map calls */ - for (iova = 0; iova < max; iova += SZ_4K) { + for (iova = base; iova < max; iova += SZ_4K) { if (WARN_ON(ops->map(ops, iova, iova, SZ_4K, IOMMU_READ))) { failed++; continue; } } - if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, 0, 0, - max))) + if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, base, + base, max - base))) failed++; /* unmap it all */ - for (iova = 0; iova < max; iova += SZ_4K) { + for (iova = base; iova < max; iova += SZ_4K) { if (WARN_ON(ops->unmap(ops, iova, SZ_4K) != SZ_4K)) failed++; } /* sweep up TLB proving PTEs */ - av8l_fast_clear_stale_ptes(ops, false); + av8l_fast_clear_stale_ptes(ops, base, max, false); /* map the entire 4GB VA space with 8K map calls */ - for (iova = 0; iova < max; iova += SZ_8K) { + for (iova = base; iova < max; iova += SZ_8K) { if (WARN_ON(ops->map(ops, iova, iova, SZ_8K, IOMMU_READ))) { failed++; continue; } } - if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, 0, 0, - max))) + if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, base, + base, max - base))) failed++; /* unmap it all with 8K unmap calls */ - for (iova = 0; iova < max; iova += SZ_8K) { + for (iova = base; iova < max; iova += SZ_8K) { if (WARN_ON(ops->unmap(ops, iova, SZ_8K) != SZ_8K)) failed++; } /* sweep up TLB proving PTEs */ - av8l_fast_clear_stale_ptes(ops, false); + av8l_fast_clear_stale_ptes(ops, base, max, false); /* map the entire 4GB VA space with 16K map calls */ - for (iova = 0; iova < max; iova += SZ_16K) { + for (iova = base; iova < max; iova += SZ_16K) { if (WARN_ON(ops->map(ops, iova, iova, SZ_16K, IOMMU_READ))) { failed++; continue; } } - if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, 0, 0, - max))) + if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, base, + base, max - base))) failed++; /* unmap it all */ - for (iova = 0; iova < max; iova += SZ_16K) { + for (iova = base; iova < max; iova += SZ_16K) { if (WARN_ON(ops->unmap(ops, iova, SZ_16K) != SZ_16K)) failed++; } /* sweep up TLB proving PTEs */ - av8l_fast_clear_stale_ptes(ops, false); + av8l_fast_clear_stale_ptes(ops, base, max, false); /* map the entire 4GB VA space with 64K map calls */ - for (iova = 0; iova < max; iova += SZ_64K) { + for (iova = base; iova < max; iova += SZ_64K) { if (WARN_ON(ops->map(ops, iova, iova, SZ_64K, IOMMU_READ))) { failed++; continue; } } - if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, 0, 0, - max))) + if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, base, + base, max - base))) failed++; /* unmap it all at once */ - if (WARN_ON(ops->unmap(ops, 0, max) != max)) + if (WARN_ON(ops->unmap(ops, base, max - base) != (max - base))) failed++; free_io_pgtable_ops(ops); diff --git a/drivers/iommu/io-pgtable.h b/drivers/iommu/io-pgtable.h index 8e03a2c37780..294b9aea0b8b 100644 --- a/drivers/iommu/io-pgtable.h +++ b/drivers/iommu/io-pgtable.h @@ -114,6 +114,8 @@ struct io_pgtable_cfg { unsigned int oas; const struct iommu_gather_ops *tlb; struct device *iommu_dev; + dma_addr_t iova_base; + dma_addr_t iova_end; /* Low-level data specific to the table format */ union { diff --git a/include/linux/io-pgtable-fast.h b/include/linux/io-pgtable-fast.h index f5a6f0eb1c69..b97f27b08b0c 100644 --- a/include/linux/io-pgtable-fast.h +++ b/include/linux/io-pgtable-fast.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -75,7 +75,8 @@ av8l_fast_iova_to_phys_public(struct io_pgtable_ops *ops, */ #define AV8L_FAST_PTE_UNMAPPED_NEED_TLBI 0xa -void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, bool skip_sync); +void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, u64 base, u64 end, + bool skip_sync); void av8l_register_notify(struct notifier_block *nb); #else /* !CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB */ @@ -83,6 +84,8 @@ void av8l_register_notify(struct notifier_block *nb); #define AV8L_FAST_PTE_UNMAPPED_NEED_TLBI 0 static inline void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, + u64 base, + u64 end, bool skip_sync) { } From c01d0806f65ca71e2e8312fb68ed15042b32abb5 Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Mon, 3 Apr 2017 16:43:53 -0700 Subject: [PATCH 205/208] iommu/arm-smmu: add support to configure IOVA range Allow clients to specify the IOVA range for fastmap clients via the DOMAIN_ATTR_GEOMETRY domain attribute. Presently fastmap only allocates page tables for the IOVA range specified during the create mapping call. However clients may want to use IOVA addresses outside this range, such as for their calls to iommu_map. So allow clients to extend the available IOVA space by setting the DOMAIN_ATTR_GEOMETRY domain attribute's iommu_domain_geometry.aperture_start to the new start address of the IOVA space and by setting iommu_domain_geometry.aperture_end to the new end address of the IOVA space. The new IOVA space created by iommu_domain_geometry.aperture_start and iommu_domain_geometry.aperture_end will be a superset of the IOVA range which was created through the create mapping call. The DOMAIN_ATTR_GEOMETRY domain attribute can only be set before attaching. Calls to set the DOMAIN_ATTR_GEOMETRY domain attribute can only be used to extend the IOVA space, it cannot shrink the range. Note that extending the IOVA range will not change the range of IOVA addresses which will be available to the DMA APIs. CRs-Fixed: 2035925 Change-Id: Ib389e019a022d98417884002de08115fb0fc9384 Signed-off-by: Liam Mark [guptap@codeaurora.org: update geometry.aperture with mapping] Signed-off-by: Prakash Gupta Signed-off-by: UtsavBalar1231 --- drivers/iommu/arm-smmu.c | 53 +++++++++++++++++++++++++++----- drivers/iommu/dma-mapping-fast.c | 6 ++-- drivers/iommu/io-pgtable-fast.c | 13 ++++---- include/linux/io-pgtable-fast.h | 5 +-- 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index c90b1bcf311b..f37b39801f69 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -2213,6 +2213,14 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, cfg->cbndx = ret; + if (!(smmu_domain->attributes & (1 << DOMAIN_ATTR_GEOMETRY))) { + /* Geometry is not set use the default geometry */ + domain->geometry.aperture_start = 0; + domain->geometry.aperture_end = (1UL << ias) - 1; + if (domain->geometry.aperture_end >= SZ_1G * 4ULL) + domain->geometry.aperture_end = (SZ_1G * 4ULL) - 1; + } + if (arm_smmu_is_slave_side_secure(smmu_domain)) { smmu_domain->pgtbl_cfg = (struct io_pgtable_cfg) { .quirks = quirks, @@ -2261,12 +2269,6 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, domain->pgsize_bitmap = smmu_domain->pgtbl_cfg.pgsize_bitmap; domain->geometry.aperture_end = (1UL << ias) - 1; domain->geometry.force_aperture = true; - if (smmu_domain->attributes & (1 << DOMAIN_ATTR_FAST)) { - domain->geometry.aperture_start = - smmu_domain->pgtbl_cfg.iova_base; - domain->geometry.aperture_end = - smmu_domain->pgtbl_cfg.iova_end; - } /* Assign an asid */ ret = arm_smmu_init_asid(domain, smmu); @@ -3792,7 +3794,6 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain, ret = 0; break; } - case DOMAIN_ATTR_CB_STALL_DISABLE: if (*((int *)data)) smmu_domain->attributes |= @@ -3805,6 +3806,44 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain, 1 << DOMAIN_ATTR_NO_CFRE; ret = 0; break; + case DOMAIN_ATTR_GEOMETRY: { + struct iommu_domain_geometry *geometry = + (struct iommu_domain_geometry *)data; + + if (smmu_domain->smmu != NULL) { + dev_err(smmu_domain->smmu->dev, + "cannot set geometry attribute while attached\n"); + ret = -EBUSY; + break; + } + + if (geometry->aperture_start >= SZ_1G * 4ULL || + geometry->aperture_end >= SZ_1G * 4ULL) { + pr_err("fastmap does not support IOVAs >= 4GB\n"); + ret = -EINVAL; + break; + } + if (smmu_domain->attributes + & (1 << DOMAIN_ATTR_GEOMETRY)) { + if (geometry->aperture_start + < domain->geometry.aperture_start) + domain->geometry.aperture_start = + geometry->aperture_start; + + if (geometry->aperture_end + > domain->geometry.aperture_end) + domain->geometry.aperture_end = + geometry->aperture_end; + } else { + smmu_domain->attributes |= 1 << DOMAIN_ATTR_GEOMETRY; + domain->geometry.aperture_start = + geometry->aperture_start; + domain->geometry.aperture_end = geometry->aperture_end; + } + ret = 0; + break; + } + default: ret = -ENODEV; } diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c index 68e97f1e88d2..ec4ba8670b9a 100644 --- a/drivers/iommu/dma-mapping-fast.c +++ b/drivers/iommu/dma-mapping-fast.c @@ -173,7 +173,9 @@ static dma_addr_t __fast_smmu_alloc_iova(struct dma_fast_smmu_mapping *mapping, iommu_tlbiall(mapping->domain); mapping->have_stale_tlbs = false; - av8l_fast_clear_stale_ptes(mapping->pgtbl_ops, mapping->base, + av8l_fast_clear_stale_ptes(mapping->pgtbl_ops, + mapping->domain->geometry.aperture_start, + mapping->base, mapping->base + mapping->size - 1, skip_sync); } @@ -799,7 +801,7 @@ static const struct dma_map_ops fast_smmu_dma_ops = { * * Creates a mapping structure which holds information about used/unused IO * address ranges, which is required to perform mapping with IOMMU aware - * functions. The only VA range supported is [0, 4GB). + * functions. The only VA range supported is [0, 4GB]. * * The client device need to be attached to the mapping with * fast_smmu_attach_device function. diff --git a/drivers/iommu/io-pgtable-fast.c b/drivers/iommu/io-pgtable-fast.c index cdcf77097abf..8f26083ba76a 100644 --- a/drivers/iommu/io-pgtable-fast.c +++ b/drivers/iommu/io-pgtable-fast.c @@ -45,6 +45,7 @@ struct av8l_fast_io_pgtable { struct page **pages; /* page table memory */ int nr_pages; dma_addr_t base; + dma_addr_t start; dma_addr_t end; }; @@ -184,13 +185,13 @@ static void __av8l_check_for_stale_tlb(av8l_fast_iopte *ptep) } void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, u64 base, - u64 end, bool skip_sync) + u64 start, u64 end, bool skip_sync) { int i; struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); - av8l_fast_iopte *pmdp = data->pmds; + av8l_fast_iopte *pmdp = iopte_pmd_offset(pmds, base, start); - for (i = base >> AV8L_FAST_PAGE_SHIFT; + for (i = start >> AV8L_FAST_PAGE_SHIFT; i <= (end >> AV8L_FAST_PAGE_SHIFT); ++i) { if (!(*pmdp & AV8L_FAST_PTE_VALID)) { *pmdp = 0; @@ -730,7 +731,7 @@ static int __init av8l_fast_positive_testing(void) } /* sweep up TLB proving PTEs */ - av8l_fast_clear_stale_ptes(ops, base, max, false); + av8l_fast_clear_stale_ptes(ops, base, base, max, false); /* map the entire 4GB VA space with 8K map calls */ for (iova = base; iova < max; iova += SZ_8K) { @@ -751,7 +752,7 @@ static int __init av8l_fast_positive_testing(void) } /* sweep up TLB proving PTEs */ - av8l_fast_clear_stale_ptes(ops, base, max, false); + av8l_fast_clear_stale_ptes(ops, base, base, max, false); /* map the entire 4GB VA space with 16K map calls */ for (iova = base; iova < max; iova += SZ_16K) { @@ -772,7 +773,7 @@ static int __init av8l_fast_positive_testing(void) } /* sweep up TLB proving PTEs */ - av8l_fast_clear_stale_ptes(ops, base, max, false); + av8l_fast_clear_stale_ptes(ops, base, base, max, false); /* map the entire 4GB VA space with 64K map calls */ for (iova = base; iova < max; iova += SZ_64K) { diff --git a/include/linux/io-pgtable-fast.h b/include/linux/io-pgtable-fast.h index b97f27b08b0c..1d5e993c9d22 100644 --- a/include/linux/io-pgtable-fast.h +++ b/include/linux/io-pgtable-fast.h @@ -75,8 +75,8 @@ av8l_fast_iova_to_phys_public(struct io_pgtable_ops *ops, */ #define AV8L_FAST_PTE_UNMAPPED_NEED_TLBI 0xa -void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, u64 base, u64 end, - bool skip_sync); +void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, u64 base, + u64 start, u64 end, bool skip_sync); void av8l_register_notify(struct notifier_block *nb); #else /* !CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB */ @@ -85,6 +85,7 @@ void av8l_register_notify(struct notifier_block *nb); static inline void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, u64 base, + u64 start, u64 end, bool skip_sync) { From 06f6e73376a35e8e0766102b253e3e7c21410b0d Mon Sep 17 00:00:00 2001 From: Sudarshan Rajagopalan Date: Fri, 10 May 2019 21:34:05 -0700 Subject: [PATCH 206/208] dma-mapping-fast: Fix erroneous MAIR idx calculation Fix the erroneous PTE MAIR calculation by using the right operator. Change-Id: I061b4e9f7599d0f43001adfb531b58e3bfd1a3c8 Signed-off-by: Sudarshan Rajagopalan Signed-off-by: UtsavBalar1231 --- drivers/iommu/io-pgtable-fast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/io-pgtable-fast.c b/drivers/iommu/io-pgtable-fast.c index 8f26083ba76a..5a5d597a00a6 100644 --- a/drivers/iommu/io-pgtable-fast.c +++ b/drivers/iommu/io-pgtable-fast.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -150,7 +150,7 @@ struct av8l_fast_io_pgtable { #define AV8L_FAST_PAGE_SHIFT 12 #define PTE_MAIR_IDX(pte) \ - ((pte >> AV8L_FAST_PTE_ATTRINDX_SHIFT) && \ + ((pte >> AV8L_FAST_PTE_ATTRINDX_SHIFT) & \ AV8L_FAST_PTE_ATTRINDX_MASK) #define PTE_SH_IDX(pte) (pte & AV8L_FAST_PTE_SH_MASK) From ad99ea2d27d14858547f1583b0d4c6f64da8fe82 Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Wed, 18 Mar 2020 15:14:53 +0530 Subject: [PATCH 207/208] diag: Prevent resource leakage of task structure The task structure with reference count incremented while dci client is registered should be updated with reference count decremented in failure case of registration. Change-Id: I093229d83dca2699e0343224756895eff0915e38 Signed-off-by: Manoj Prabhu B Signed-off-by: UtsavBalar1231 --- drivers/char/diag/diag_dci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index 25a1706b6508..369aa81ab8c1 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -3170,6 +3170,7 @@ fail_alloc: kfree(new_entry); new_entry = NULL; } + put_task_struct(current); mutex_unlock(&driver->dci_mutex); put_task_struct(task_s); put_task_struct(task_s); From c82ba301266e70140be03dee2749da805ad37bee Mon Sep 17 00:00:00 2001 From: Sreelakshmi Gownipalli Date: Wed, 10 Jul 2019 23:25:28 -0700 Subject: [PATCH 208/208] diag: Clear the local masks only during local usb disconnect Clear the masks on the apps only during usb disconnect on local usb diag channel but not for the remote proc usb disconnect. Change-Id: I1d3f828f9fecf628bc15f3f62ce1e4dc482c57db Signed-off-by: Sreelakshmi Gownipalli Signed-off-by: UtsavBalar1231 --- drivers/char/diag/diag_usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c index 92c4fc187001..43cf043eb7d5 100644 --- a/drivers/char/diag/diag_usb.c +++ b/drivers/char/diag/diag_usb.c @@ -253,7 +253,8 @@ static void usb_disconnect_work_fn(struct work_struct *work) ch->name, atomic_read(&ch->disconnected), atomic_read(&ch->connected)); if (!atomic_read(&ch->connected) && - driver->usb_connected && diag_mask_param()) + driver->usb_connected && diag_mask_param() && + ch->id == DIAG_USB_LOCAL) diag_clear_masks(0); usb_disconnect(ch);