From 283640605de483f948c8eecf159192b7b73036d3 Mon Sep 17 00:00:00 2001 From: Suraj Jaiswal Date: Thu, 22 Aug 2019 16:14:02 +0530 Subject: emac: Perf setting This change add support in emac driver for required performance setting on Talos. Change-Id: I8facf4b72c624484cc4a75d34cd2cfcd5f95f42c --- drivers/emac-dwc-eqos/Android.mk | 9 +++++++++ drivers/emac-dwc-eqos/emac_perf_settings.sh | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 drivers/emac-dwc-eqos/emac_perf_settings.sh (limited to 'drivers') diff --git a/drivers/emac-dwc-eqos/Android.mk b/drivers/emac-dwc-eqos/Android.mk index a50d64f..cff761a 100644 --- a/drivers/emac-dwc-eqos/Android.mk +++ b/drivers/emac-dwc-eqos/Android.mk @@ -22,6 +22,15 @@ KBUILD_OPTIONS += DCONFIG_DEBUGFS_OBJ=1 LOCAL_MODULE := emac_dwc_eqos.ko LOCAL_MODULE_TAGS := optional include $(DLKM_DIR)/AndroidKernelModule.mk + +include $(CLEAR_VARS) +LOCAL_MODULE := emac_perf_settings.sh +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/emac +LOCAL_SRC_FILES := emac_perf_settings.sh +include $(BUILD_PREBUILT) + endif endif diff --git a/drivers/emac-dwc-eqos/emac_perf_settings.sh b/drivers/emac-dwc-eqos/emac_perf_settings.sh new file mode 100644 index 0000000..508e69d --- /dev/null +++ b/drivers/emac-dwc-eqos/emac_perf_settings.sh @@ -0,0 +1,22 @@ +#!/vendor/bin/sh +#Copyright (c) 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 +#only version 2 as published by the Free Software Foundation. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +# +echo 12582912 > /proc/sys/net/core/wmem_max; +echo 12582912 > /proc/sys/net/core/rmem_max; +echo 10240 87380 12582912 > /proc/sys/net/ipv4/tcp_rmem; +echo 10240 87380 12582912 > /proc/sys/net/ipv4/tcp_wmem; +echo 12582912 > /proc/sys/net/ipv4/udp_rmem_min; +echo 12582912 > /proc/sys/net/ipv4/udp_wmem_min; +echo 1 > /proc/sys/net/ipv4/tcp_window_scaling; +echo 18 > /sys/class/net/eth0/queues/rx-0/rps_cpus; + -- cgit v1.2.3 From 7f36751352721ee10a919b61c7480b0299645856 Mon Sep 17 00:00:00 2001 From: Sunil Paidimarri Date: Fri, 19 Apr 2019 13:21:10 -0700 Subject: data-kernel: Add io macro settings for emac core version 2.1.1 Change-Id: I7d661f7bb23e812783d61c63061e19f8e743efff Acked-by: Nisha Menon Signed-off-by: Sunil Paidimarri --- drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c | 19 +++++++++++------- drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c | 10 ++++++---- drivers/emac-dwc-eqos/DWC_ETH_QOS_rgmii_io_macro.c | 23 +++++++++++++++------- 3 files changed, 34 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c index 57c9383..faac49e 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c @@ -543,7 +543,8 @@ static void set_phy_rx_tx_delay(struct DWC_ETH_QOS_prv_data *pdata, EMACDBG("Read 0x%x from offset 0x8\n",phydata); phydata = 0; - if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2) { + if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2 + || pdata->emac_hw_version_type == EMAC_HW_v2_1_1) { u16 tx_clk = 0xE; /* Provide TX_CLK delay of -0.06nsec */ DWC_ETH_QOS_mdio_mmd_register_read_direct(pdata, pdata->phyaddr, @@ -562,7 +563,8 @@ static void set_phy_rx_tx_delay(struct DWC_ETH_QOS_prv_data *pdata, DWC_ETH_QOS_mdio_mmd_register_read_direct(pdata, pdata->phyaddr, DWC_ETH_QOS_MICREL_PHY_DEBUG_MMD_DEV_ADDR,0x5,&phydata); phydata &= ~(0xFF); - if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2) + if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2 || + pdata->emac_hw_version_type == EMAC_HW_v2_1_1) phydata |= ((0x2 << 12) | (0x2 << 8) | (0x2 << 4) | 0x2); else /* Default settings for EMAC_HW_v2_1_0 */ @@ -579,7 +581,8 @@ static void set_phy_rx_tx_delay(struct DWC_ETH_QOS_prv_data *pdata, DWC_ETH_QOS_mdio_mmd_register_read_direct(pdata, pdata->phyaddr, DWC_ETH_QOS_MICREL_PHY_DEBUG_MMD_DEV_ADDR,0x4,&phydata); phydata &= ~(0xF << 4); - if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2) + if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2 || + pdata->emac_hw_version_type == EMAC_HW_v2_1_1) phydata |= (0x2 << 4); else /* Default settings for EMAC_HW_v2_1_0 */ @@ -654,9 +657,10 @@ static void configure_phy_rx_tx_delay(struct DWC_ETH_QOS_prv_data *pdata) set_phy_rx_tx_delay(pdata, ENABLE_RX_DELAY, ENABLE_TX_DELAY); } else { /* Settings for RGMII ID mode. - Not applicable for EMAC core version 2.1.0 and 2.1.2 */ + Not applicable for EMAC core version 2.1.0, 2.1.2 and 2.1.1 */ if (pdata->emac_hw_version_type != EMAC_HW_v2_1_0 && - pdata->emac_hw_version_type != EMAC_HW_v2_1_2) + pdata->emac_hw_version_type != EMAC_HW_v2_1_2 && + pdata->emac_hw_version_type != EMAC_HW_v2_1_1) set_phy_rx_tx_delay(pdata, DISABLE_RX_DELAY, DISABLE_TX_DELAY); } break; @@ -675,9 +679,10 @@ static void configure_phy_rx_tx_delay(struct DWC_ETH_QOS_prv_data *pdata) set_phy_rx_tx_delay(pdata, DISABLE_RX_DELAY, ENABLE_TX_DELAY); } else { /* Settings for RGMII ID mode */ - /* Not applicable for EMAC core version 2.1.0 and 2.1.2 */ + /* Not applicable for EMAC core version 2.1.0, 2.1.2 and 2.1.1 */ if (pdata->emac_hw_version_type != EMAC_HW_v2_1_0 && - pdata->emac_hw_version_type != EMAC_HW_v2_1_2) + pdata->emac_hw_version_type != EMAC_HW_v2_1_2 && + pdata->emac_hw_version_type != EMAC_HW_v2_1_1) set_phy_rx_tx_delay(pdata, DISABLE_RX_DELAY, DISABLE_TX_DELAY); } } diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c index 4d57d7a..2a7e11a 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c @@ -1037,8 +1037,9 @@ int DWC_ETH_QOS_enable_ptp_clk(struct device *dev) int ret; const char* ptp_clock_name; - if (dwc_eth_qos_res_data.emac_hw_version_type == EMAC_HW_v2_1_0 || - dwc_eth_qos_res_data.emac_hw_version_type == EMAC_HW_v2_1_2) + if (dwc_eth_qos_res_data.emac_hw_version_type == EMAC_HW_v2_1_0 + || dwc_eth_qos_res_data.emac_hw_version_type == EMAC_HW_v2_1_2 + || dwc_eth_qos_res_data.emac_hw_version_type == EMAC_HW_v2_1_1) ptp_clock_name = "emac_ptp_clk"; else ptp_clock_name = "eth_ptp_clk"; @@ -1186,8 +1187,9 @@ static int DWC_ETH_QOS_get_clks(struct device *dev) dwc_eth_qos_res_data.rgmii_clk = NULL; dwc_eth_qos_res_data.ptp_clk = NULL; - if (dwc_eth_qos_res_data.emac_hw_version_type == EMAC_HW_v2_1_0 || - (dwc_eth_qos_res_data.emac_hw_version_type == EMAC_HW_v2_1_2)) { + if (dwc_eth_qos_res_data.emac_hw_version_type == EMAC_HW_v2_1_0 + || dwc_eth_qos_res_data.emac_hw_version_type == EMAC_HW_v2_1_2 + || dwc_eth_qos_res_data.emac_hw_version_type == EMAC_HW_v2_1_1) { /* EMAC core version 2.1.0 clocks */ axi_clock_name = "emac_axi_clk"; ahb_clock_name = "emac_slv_ahb_clk"; diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_rgmii_io_macro.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_rgmii_io_macro.c index ad6736f..ebd302c 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_rgmii_io_macro.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_rgmii_io_macro.c @@ -364,7 +364,8 @@ int DWC_ETH_QOS_rgmii_io_macro_init(struct DWC_ETH_QOS_prv_data *pdata) uint rgmii_data_divide_clk; ULONG data; - if (pdata->emac_hw_version_type == EMAC_HW_v2_3_0 || (pdata->emac_hw_version_type == EMAC_HW_v2_3_1)) { + if (pdata->emac_hw_version_type == EMAC_HW_v2_3_0 || (pdata->emac_hw_version_type == EMAC_HW_v2_3_1) + || (pdata->emac_hw_version_type == EMAC_HW_v2_1_1)) { if(pdata->io_macro_phy_intf == RGMII_MODE) loopback_mode_en = 0x1; rgmii_data_divide_clk = 0x0; @@ -403,7 +404,8 @@ int DWC_ETH_QOS_rgmii_io_macro_init(struct DWC_ETH_QOS_prv_data *pdata) RGMII_LOOPBACK_EN_UDFWR(loopback_mode_en); if (pdata->emac_hw_version_type == EMAC_HW_v2_1_0 || pdata->emac_hw_version_type == EMAC_HW_v2_1_2 || - (pdata->emac_hw_version_type == EMAC_HW_v2_3_1)) + (pdata->emac_hw_version_type == EMAC_HW_v2_3_1) || + pdata->emac_hw_version_type == EMAC_HW_v2_1_1) RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x1); } else { /* Enable DDR mode*/ @@ -429,6 +431,8 @@ int DWC_ETH_QOS_rgmii_io_macro_init(struct DWC_ETH_QOS_prv_data *pdata) SDCC_HC_PRG_RCLK_DLY_UDFWR(52); else if (pdata->emac_hw_version_type == EMAC_HW_v2_3_1) SDCC_HC_PRG_RCLK_DLY_UDFWR(104); + else if (pdata->emac_hw_version_type == EMAC_HW_v2_1_1) + SDCC_HC_PRG_RCLK_DLY_UDFWR(130); else { /* Program PRG_RCLK_DLY to 57 for a required delay of 1.8 ns */ SDCC_HC_PRG_RCLK_DLY_UDFWR(57); } @@ -459,9 +463,11 @@ int DWC_ETH_QOS_rgmii_io_macro_init(struct DWC_ETH_QOS_prv_data *pdata) RGMII_LOOPBACK_EN_UDFWR(loopback_mode_en); if (pdata->emac_hw_version_type == EMAC_HW_v2_1_0 || pdata->emac_hw_version_type == EMAC_HW_v2_1_2 || - (pdata->emac_hw_version_type == EMAC_HW_v2_3_1)) + (pdata->emac_hw_version_type == EMAC_HW_v2_3_1) || + pdata->emac_hw_version_type == EMAC_HW_v2_1_1) RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x1); - if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2) + if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2 || + pdata->emac_hw_version_type == EMAC_HW_v2_1_1) RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x1); } else{ RGMII_DDR_MODE_UDFWR(0x1); @@ -506,9 +512,11 @@ int DWC_ETH_QOS_rgmii_io_macro_init(struct DWC_ETH_QOS_prv_data *pdata) RGMII_LOOPBACK_EN_UDFWR(loopback_mode_en); if (pdata->emac_hw_version_type == EMAC_HW_v2_1_0 || pdata->emac_hw_version_type == EMAC_HW_v2_1_2 || - (pdata->emac_hw_version_type == EMAC_HW_v2_3_1)) + (pdata->emac_hw_version_type == EMAC_HW_v2_3_1) || + pdata->emac_hw_version_type == EMAC_HW_v2_1_1) RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x1); - if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2) + if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2 || + pdata->emac_hw_version_type == EMAC_HW_v2_1_1) RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x1); } else{ RGMII_DDR_MODE_UDFWR(0x1); @@ -570,7 +578,8 @@ int DWC_ETH_QOS_rgmii_io_macro_init(struct DWC_ETH_QOS_prv_data *pdata) RGMII_CONFIG_2_DATA_DIVIDE_CLK_SEL_UDFWR(0x1); RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x0); RGMII_CONFIG_2_RERVED_CONFIG_16_EN_UDFWR(0x1); - if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2) + if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2 || + pdata->emac_hw_version_type == EMAC_HW_v2_1_1) RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x1); if (pdata->emac_hw_version_type == EMAC_HW_v2_3_1) RGMII_LOOPBACK_EN_UDFWR(0x1); -- cgit v1.2.3 From 7d0c0a3a5cec1dbda36c10cca14b5c33e3acbc11 Mon Sep 17 00:00:00 2001 From: Chinmay Agarwal Date: Wed, 27 Nov 2019 01:16:36 +0530 Subject: data-kernel: rmnet: shs: Fix Errors Reported during Static Analysis. Set the weights to be used in calculating "avg_pps", when the flow is executing on the Perf CPU's in function "rmnet_shs_wq_get_flow_avg_pps". Change-Id: Ia50db34a348c068a9b1bf3171fced858ce0a62de Signed-off-by: Chinmay Agarwal --- drivers/rmnet/shs/rmnet_shs_wq.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/rmnet/shs/rmnet_shs_wq.c b/drivers/rmnet/shs/rmnet_shs_wq.c index 298058c..60653bf 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq.c +++ b/drivers/rmnet/shs/rmnet_shs_wq.c @@ -455,6 +455,9 @@ static u64 rmnet_shs_wq_get_flow_avg_pps(struct rmnet_shs_wq_hstat_s *hnode) /* More weight to current value */ new_weight = rmnet_shs_wq_tuning; old_weight = 100 - rmnet_shs_wq_tuning; + } else { + old_weight = rmnet_shs_wq_tuning; + new_weight = 100 - rmnet_shs_wq_tuning; } /* computing weighted average per flow, if the flow has just started, -- cgit v1.2.3 From 9255a8a1ef6f8c9c9e86234fdca6bfd61bf896da Mon Sep 17 00:00:00 2001 From: Conner Huff Date: Wed, 27 Nov 2019 12:55:42 -0800 Subject: drivers: perf: Register/unregister on perf Before registering perf structures make sure it has not yet been registered before. Conversely, if deregistering perf, make sure that it was registered in the first place. Signed-off-by: Conner Huff Change-Id: I00b89f45780161615b25faebfa70e79dde530c2f --- drivers/rmnet/perf/rmnet_perf_config.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rmnet/perf/rmnet_perf_config.c b/drivers/rmnet/perf/rmnet_perf_config.c index 8a5f50e..be245d3 100644 --- a/drivers/rmnet/perf/rmnet_perf_config.c +++ b/drivers/rmnet/perf/rmnet_perf_config.c @@ -397,7 +397,9 @@ static int rmnet_perf_config_notify_cb(struct notifier_block *nb, switch (event) { case NETDEV_UNREGISTER: - if (rmnet_is_real_dev_registered(dev) && + pr_info("%s(): rmnet_perf netdevice unregister, name = %s\n", + __func__, dev->name); + if (perf && rmnet_is_real_dev_registered(dev) && rmnet_perf_config_hook_registered() && (!strncmp(dev->name, "rmnet_ipa0", 10) || !strncmp(dev->name, "rmnet_mhi0", 10))) { @@ -413,6 +415,7 @@ static int rmnet_perf_config_notify_cb(struct notifier_block *nb, RCU_INIT_POINTER(rmnet_perf_deag_entry, NULL); RCU_INIT_POINTER(rmnet_perf_desc_entry, NULL); RCU_INIT_POINTER(rmnet_perf_chain_end, NULL); + perf = NULL; } break; case NETDEV_REGISTER: @@ -421,7 +424,7 @@ static int rmnet_perf_config_notify_cb(struct notifier_block *nb, /* Check prevents us from allocating resources for every * interface */ - if (!rmnet_perf_config_hook_registered() && + if (!perf && !rmnet_perf_config_hook_registered() && strncmp(dev->name, "rmnet_data", 10) == 0) { struct rmnet_priv *priv = netdev_priv(dev); -- cgit v1.2.3 From be89ad02e5d82ec54a304c1e947ce66055fc59de Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Fri, 29 Nov 2019 16:35:09 -0700 Subject: drivers: shs: Protect all file system operations using shs ep lock This add synchronization between the file system operations and the updates which occur within the shs workqueue. Fixes the following when there are two instances of userspace handlers running and are killed together- <6> Unable to handle kernel paging request at virtual address ffffffbfadadadb4 <2> pc : __free_pages+0x24/0xc0 <2> lr : free_pages+0x38/0x48 <2> Call trace: <2> __free_pages+0x24/0xc0 <2> free_pages+0x38/0x48 <2> rmnet_shs_release_caps+0x9c/0xb0 [rmnet_shs] <2> close_pdeo+0x94/0x120 <2> proc_reg_release+0x64/0x88 <2> __fput+0xdc/0x1d8 <2> ____fput+0x1c/0x28 <2> task_work_run+0x48/0xd0 <2> do_notify_resume+0x950/0x1160 <2> work_pending+0x8/0x14 CRs-fixed: 2576578 Change-Id: I67d1fc4d1f3c93d4497e988c2118c410091f0dd2 Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs_wq.c | 10 ++++++ drivers/rmnet/shs/rmnet_shs_wq.h | 6 +++- drivers/rmnet/shs/rmnet_shs_wq_mem.c | 61 +++++++++++++++++++++++++++++------- 3 files changed, 65 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/rmnet/shs/rmnet_shs_wq.c b/drivers/rmnet/shs/rmnet_shs_wq.c index 60653bf..4c69b57 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq.c +++ b/drivers/rmnet/shs/rmnet_shs_wq.c @@ -2194,3 +2194,13 @@ u64 rmnet_shs_wq_get_max_allowed_pps(u16 cpu) return rmnet_shs_cpu_rx_max_pps_thresh[cpu]; } + +void rmnet_shs_wq_ep_lock_bh(void) +{ + spin_lock_bh(&rmnet_shs_ep_lock); +} + +void rmnet_shs_wq_ep_unlock_bh(void) +{ + spin_unlock_bh(&rmnet_shs_ep_lock); +} diff --git a/drivers/rmnet/shs/rmnet_shs_wq.h b/drivers/rmnet/shs/rmnet_shs_wq.h index ed37dc8..0d86200 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq.h +++ b/drivers/rmnet/shs/rmnet_shs_wq.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-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 @@ -285,4 +285,8 @@ int rmnet_shs_wq_try_to_move_flow(u16 cur_cpu, u16 dest_cpu, u32 hash_to_move, int rmnet_shs_wq_set_flow_segmentation(u32 hash_to_set, u8 seg_enable); +void rmnet_shs_wq_ep_lock_bh(void); + +void rmnet_shs_wq_ep_unlock_bh(void); + #endif /*_RMNET_SHS_WQ_H_*/ diff --git a/drivers/rmnet/shs/rmnet_shs_wq_mem.c b/drivers/rmnet/shs/rmnet_shs_wq_mem.c index e80d424..56b1c34 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq_mem.c +++ b/drivers/rmnet/shs/rmnet_shs_wq_mem.c @@ -49,13 +49,14 @@ static int rmnet_shs_vm_fault(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; } + rmnet_shs_wq_ep_unlock_bh(); return 0; } @@ -80,13 +81,16 @@ static int rmnet_shs_open_caps(struct inode *inode, struct file *filp) struct rmnet_shs_mmap_info *info; rm_err("%s", "SHS_MEM: rmnet_shs_open - entry\n"); + + rmnet_shs_wq_ep_lock_bh(); if (!cap_shared) { - info = kzalloc(sizeof(struct rmnet_shs_mmap_info), GFP_KERNEL); + info = kzalloc(sizeof(struct rmnet_shs_mmap_info), GFP_ATOMIC); if (!info) { + rmnet_shs_wq_ep_unlock_bh(); rm_err("%s", "SHS_MEM: rmnet_shs_open - FAILED\n"); return -ENOMEM; } - info->data = (char *)get_zeroed_page(GFP_KERNEL); + info->data = (char *)get_zeroed_page(GFP_ATOMIC); cap_shared = info; rm_err("SHS_MEM: virt_to_phys = 0x%llx cap_shared = 0x%llx\n", (unsigned long long)virt_to_phys((void *)info), @@ -94,6 +98,7 @@ static int rmnet_shs_open_caps(struct inode *inode, struct file *filp) } filp->private_data = cap_shared; + rmnet_shs_wq_ep_unlock_bh(); rm_err("%s", "SHS_MEM: rmnet_shs_open - OK\n"); @@ -105,19 +110,24 @@ static int rmnet_shs_open_g_flows(struct inode *inode, struct file *filp) struct rmnet_shs_mmap_info *info; rm_err("%s", "SHS_MEM: rmnet_shs_open g_flows - entry\n"); + + rmnet_shs_wq_ep_lock_bh(); if (!gflow_shared) { - info = kzalloc(sizeof(struct rmnet_shs_mmap_info), GFP_KERNEL); + info = kzalloc(sizeof(struct rmnet_shs_mmap_info), GFP_ATOMIC); if (!info) { + rmnet_shs_wq_ep_unlock_bh(); rm_err("%s", "SHS_MEM: rmnet_shs_open - FAILED\n"); return -ENOMEM; } - info->data = (char *)get_zeroed_page(GFP_KERNEL); + info->data = (char *)get_zeroed_page(GFP_ATOMIC); gflow_shared = info; rm_err("SHS_MEM: virt_to_phys = 0x%llx gflow_shared = 0x%llx\n", (unsigned long long)virt_to_phys((void *)info), (unsigned long long)virt_to_phys((void *)gflow_shared)); } filp->private_data = gflow_shared; + rmnet_shs_wq_ep_unlock_bh(); + return 0; } @@ -126,34 +136,42 @@ static int rmnet_shs_open_ss_flows(struct inode *inode, struct file *filp) struct rmnet_shs_mmap_info *info; rm_err("%s", "SHS_MEM: rmnet_shs_open ss_flows - entry\n"); + + rmnet_shs_wq_ep_lock_bh(); if (!ssflow_shared) { - info = kzalloc(sizeof(struct rmnet_shs_mmap_info), GFP_KERNEL); + info = kzalloc(sizeof(struct rmnet_shs_mmap_info), GFP_ATOMIC); if (!info) { + rmnet_shs_wq_ep_unlock_bh(); rm_err("%s", "SHS_MEM: rmnet_shs_open - FAILED\n"); return -ENOMEM; } - info->data = (char *)get_zeroed_page(GFP_KERNEL); + info->data = (char *)get_zeroed_page(GFP_ATOMIC); ssflow_shared = info; rm_err("SHS_MEM: virt_to_phys = 0x%llx ssflow_shared = 0x%llx\n", (unsigned long long)virt_to_phys((void *)info), (unsigned long long)virt_to_phys((void *)ssflow_shared)); } filp->private_data = ssflow_shared; + rmnet_shs_wq_ep_unlock_bh(); + return 0; } static ssize_t rmnet_shs_read(struct file *filp, char __user *buf, size_t len, loff_t *off) { struct rmnet_shs_mmap_info *info; - int ret; + int ret = 0; rm_err("%s", "SHS_MEM: rmnet_shs_read - entry\n"); + + rmnet_shs_wq_ep_lock_bh(); info = filp->private_data; ret = min_t(size_t, len, RMNET_SHS_BUFFER_SIZE); if (copy_to_user(buf, info->data, ret)) ret = -EFAULT; + rmnet_shs_wq_ep_unlock_bh(); - return 0; + return ret; } static ssize_t rmnet_shs_write(struct file *filp, const char __user *buf, size_t len, loff_t *off) @@ -162,12 +180,17 @@ static ssize_t rmnet_shs_write(struct file *filp, const char __user *buf, size_t int ret; rm_err("%s", "SHS_MEM: rmnet_shs_write - entry\n"); + + rmnet_shs_wq_ep_lock_bh(); info = filp->private_data; ret = min_t(size_t, len, RMNET_SHS_BUFFER_SIZE); if (copy_from_user(info->data, buf, ret)) - return -EFAULT; + ret = -EFAULT; else - return len; + ret = len; + rmnet_shs_wq_ep_unlock_bh(); + + return ret; } static int rmnet_shs_release_caps(struct inode *inode, struct file *filp) @@ -175,6 +198,8 @@ static int rmnet_shs_release_caps(struct inode *inode, struct file *filp) struct rmnet_shs_mmap_info *info; rm_err("%s", "SHS_MEM: rmnet_shs_release - entry\n"); + + rmnet_shs_wq_ep_lock_bh(); if (cap_shared) { info = filp->private_data; cap_shared = NULL; @@ -182,6 +207,8 @@ static int rmnet_shs_release_caps(struct inode *inode, struct file *filp) kfree(info); filp->private_data = NULL; } + rmnet_shs_wq_ep_unlock_bh(); + return 0; } @@ -190,6 +217,8 @@ static int rmnet_shs_release_g_flows(struct inode *inode, struct file *filp) struct rmnet_shs_mmap_info *info; rm_err("%s", "SHS_MEM: rmnet_shs_release - entry\n"); + + rmnet_shs_wq_ep_lock_bh(); if (gflow_shared) { info = filp->private_data; gflow_shared = NULL; @@ -197,6 +226,8 @@ static int rmnet_shs_release_g_flows(struct inode *inode, struct file *filp) kfree(info); filp->private_data = NULL; } + rmnet_shs_wq_ep_unlock_bh(); + return 0; } @@ -205,6 +236,8 @@ 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"); + + rmnet_shs_wq_ep_lock_bh(); if (ssflow_shared) { info = filp->private_data; ssflow_shared = NULL; @@ -212,6 +245,8 @@ static int rmnet_shs_release_ss_flows(struct inode *inode, struct file *filp) kfree(info); filp->private_data = NULL; } + rmnet_shs_wq_ep_unlock_bh(); + return 0; } @@ -607,9 +642,11 @@ void rmnet_shs_wq_mem_init(void) proc_create(RMNET_SHS_PROC_G_FLOWS, 0644, shs_proc_dir, &rmnet_shs_g_flows_fops); proc_create(RMNET_SHS_PROC_SS_FLOWS, 0644, shs_proc_dir, &rmnet_shs_ss_flows_fops); + rmnet_shs_wq_ep_lock_bh(); cap_shared = NULL; gflow_shared = NULL; ssflow_shared = NULL; + rmnet_shs_wq_ep_unlock_bh(); } /* Remove shs files and folders from proc fs */ @@ -620,7 +657,9 @@ void rmnet_shs_wq_mem_deinit(void) remove_proc_entry(RMNET_SHS_PROC_SS_FLOWS, shs_proc_dir); remove_proc_entry(RMNET_SHS_PROC_DIR, NULL); + rmnet_shs_wq_ep_lock_bh(); cap_shared = NULL; gflow_shared = NULL; ssflow_shared = NULL; + rmnet_shs_wq_ep_unlock_bh(); } -- cgit v1.2.3 From f3133356388b2f79088d10dca8e79a24f76a0a6e Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Fri, 29 Nov 2019 17:00:11 -0700 Subject: drivers: shs: Fix potential null dereference on page alloc failure Check before using page allocated for capabilities, gold flows and slow start flows. CRs-fixed: 2576578 Change-Id: I8f062004466447703c84912506af5963035c163c Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs_wq_mem.c | 54 ++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/rmnet/shs/rmnet_shs_wq_mem.c b/drivers/rmnet/shs/rmnet_shs_wq_mem.c index 56b1c34..1675517 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq_mem.c +++ b/drivers/rmnet/shs/rmnet_shs_wq_mem.c @@ -85,12 +85,15 @@ static int rmnet_shs_open_caps(struct inode *inode, struct file *filp) rmnet_shs_wq_ep_lock_bh(); if (!cap_shared) { info = kzalloc(sizeof(struct rmnet_shs_mmap_info), GFP_ATOMIC); - if (!info) { - rmnet_shs_wq_ep_unlock_bh(); - rm_err("%s", "SHS_MEM: rmnet_shs_open - FAILED\n"); - return -ENOMEM; - } + if (!info) + goto fail; + info->data = (char *)get_zeroed_page(GFP_ATOMIC); + if (!info->data) { + kfree(info); + goto fail; + } + cap_shared = info; rm_err("SHS_MEM: virt_to_phys = 0x%llx cap_shared = 0x%llx\n", (unsigned long long)virt_to_phys((void *)info), @@ -103,6 +106,11 @@ static int rmnet_shs_open_caps(struct inode *inode, struct file *filp) rm_err("%s", "SHS_MEM: rmnet_shs_open - OK\n"); return 0; + +fail: + rmnet_shs_wq_ep_unlock_bh(); + rm_err("%s", "SHS_MEM: rmnet_shs_open - FAILED\n"); + return -ENOMEM; } static int rmnet_shs_open_g_flows(struct inode *inode, struct file *filp) @@ -114,12 +122,15 @@ static int rmnet_shs_open_g_flows(struct inode *inode, struct file *filp) rmnet_shs_wq_ep_lock_bh(); if (!gflow_shared) { info = kzalloc(sizeof(struct rmnet_shs_mmap_info), GFP_ATOMIC); - if (!info) { - rmnet_shs_wq_ep_unlock_bh(); - rm_err("%s", "SHS_MEM: rmnet_shs_open - FAILED\n"); - return -ENOMEM; - } + if (!info) + goto fail; + info->data = (char *)get_zeroed_page(GFP_ATOMIC); + if (!info->data) { + kfree(info); + goto fail; + } + gflow_shared = info; rm_err("SHS_MEM: virt_to_phys = 0x%llx gflow_shared = 0x%llx\n", (unsigned long long)virt_to_phys((void *)info), @@ -129,6 +140,11 @@ static int rmnet_shs_open_g_flows(struct inode *inode, struct file *filp) rmnet_shs_wq_ep_unlock_bh(); return 0; + +fail: + rmnet_shs_wq_ep_unlock_bh(); + rm_err("%s", "SHS_MEM: rmnet_shs_open - FAILED\n"); + return -ENOMEM; } static int rmnet_shs_open_ss_flows(struct inode *inode, struct file *filp) @@ -140,12 +156,15 @@ static int rmnet_shs_open_ss_flows(struct inode *inode, struct file *filp) rmnet_shs_wq_ep_lock_bh(); if (!ssflow_shared) { info = kzalloc(sizeof(struct rmnet_shs_mmap_info), GFP_ATOMIC); - if (!info) { - rmnet_shs_wq_ep_unlock_bh(); - rm_err("%s", "SHS_MEM: rmnet_shs_open - FAILED\n"); - return -ENOMEM; - } + if (!info) + goto fail; + info->data = (char *)get_zeroed_page(GFP_ATOMIC); + if (!info->data) { + kfree(info); + goto fail; + } + ssflow_shared = info; rm_err("SHS_MEM: virt_to_phys = 0x%llx ssflow_shared = 0x%llx\n", (unsigned long long)virt_to_phys((void *)info), @@ -155,6 +174,11 @@ static int rmnet_shs_open_ss_flows(struct inode *inode, struct file *filp) rmnet_shs_wq_ep_unlock_bh(); return 0; + +fail: + rmnet_shs_wq_ep_unlock_bh(); + rm_err("%s", "SHS_MEM: rmnet_shs_open - FAILED\n"); + return -ENOMEM; } static ssize_t rmnet_shs_read(struct file *filp, char __user *buf, size_t len, loff_t *off) -- cgit v1.2.3 From 2c45b4f701c5d36b04c110337a99a2d533204ca4 Mon Sep 17 00:00:00 2001 From: Suraj Jaiswal Date: Mon, 18 Nov 2019 16:58:00 +0530 Subject: data-kernel: EMAC: emac cleanp THis change add support for proper cleanup for Ethernet on shutdown/reboot. Change-Id: I3545905ad8ad0e139cf49f489868c738fd699445 --- drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c index 4d57d7a..431357a 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_platform.c @@ -2262,6 +2262,13 @@ int DWC_ETH_QOS_remove(struct platform_device *pdev) static void DWC_ETH_QOS_shutdown(struct platform_device *pdev) { pr_info("qcom-emac-dwc-eqos: DWC_ETH_QOS_shutdown\n"); +#ifdef DWC_ETH_QOS_BUILTIN + if (gDWC_ETH_QOS_prv_data->dev->flags & IFF_UP) { + gDWC_ETH_QOS_prv_data->dev->netdev_ops->ndo_stop(gDWC_ETH_QOS_prv_data->dev); + gDWC_ETH_QOS_prv_data->dev->flags &= ~IFF_UP; + } + DWC_ETH_QOS_remove(pdev); +#endif } #ifdef CONFIG_PM -- cgit v1.2.3 From c7a5aef3cb6d95bd0b307dce66df341be8a91a3d Mon Sep 17 00:00:00 2001 From: Sunil Paidimarri Date: Wed, 4 Dec 2019 11:18:01 -0800 Subject: data-kernel: EMAC: Check NAPI before calling netif_rx_skb Changes to check if NAPI is enabled and then call netif_rx_skb, else follow the legacy way of calling netif_rx_ni. Acked-by: Abhishek Chauhan Signed-off-by: Sunil Paidimarri --- drivers/emac-dwc-eqos/DWC_ETH_QOS_ipa.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_ipa.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_ipa.c index c09a6f5..f871ce3 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_ipa.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_ipa.c @@ -684,15 +684,19 @@ static void ntn_ipa_notify_cb(void *priv, enum ipa_dp_evt_type evt, /* Submit packet to network stack */ /* If its a ping packet submit it via rx_ni else use rx */ - if (ip_hdr->protocol == IPPROTO_ICMP) { - stat = netif_rx_ni(skb); - } else if ((pdata->dev->stats.rx_packets % - IPA_ETH_RX_SOFTIRQ_THRESH) == 0){ - stat = netif_rx_ni(skb); + /* If NAPI is enabled call receive_skb */ + if(ipa_get_lan_rx_napi()){ + stat = netif_receive_skb(skb); } else { - stat = netif_rx(skb); + if (ip_hdr->protocol == IPPROTO_ICMP) { + stat = netif_rx_ni(skb); + } else if ((pdata->dev->stats.rx_packets % + IPA_ETH_RX_SOFTIRQ_THRESH) == 0){ + stat = netif_rx_ni(skb); + } else { + stat = netif_rx(skb); + } } - if(stat == NET_RX_DROP) { pdata->dev->stats.rx_dropped++; } else { -- cgit v1.2.3 From bdc07671ca3f0f6e5d37f667ce028fe128636679 Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Fri, 10 Jan 2020 18:20:45 -0800 Subject: drivers: shs: Clear out pending core switch timers on cleanup In case there is a burst of data beyond a threshold, the core switch timer will try to schedule a worker once the timer expires. While the pending work is cleaned up on timer expiry, the pending timers itself are not cleared up. As part of this change, the core switch module parameter is reset on start of cleanup to ensure no more timers are configured during the cleanup. Fixes the following- 399.705316: <6> Modules linked in: rmnet_perf(O) [last unloaded: rmnet_shs] 399.734305: <2> pstate: 20400085 (nzCv daIf +PAN -UAO) 399.739251: <2> pc : rb_insert_color+0x10/0x168 399.743555: <2> lr : timerqueue_add+0x88/0xc0 400.413555: <2> Call trace: 400.416084: <2> rb_insert_color+0x10/0x168 400.420042: <2> enqueue_hrtimer+0x198/0x1c0 400.424081: <2> __hrtimer_run_queues+0x4e8/0x5b0 400.428568: <2> hrtimer_interrupt+0x108/0x350 400.432793: <2> arch_timer_handler_virt+0x40/0x50 400.437373: <2> handle_percpu_devid_irq+0x1dc/0x428 400.442122: <2> __handle_domain_irq+0xa0/0xf8 400.446345: <2> gic_handle_irq+0x154/0x1d4 400.450298: <2> el1_irq+0xb4/0x130 CRs-fixed: 2594249 Change-Id: I6e4a1982ce4665340cb1a75d0ec17d1db3f286fc Signed-off-by: Subash Abhinov Kasiviswanathan --- drivers/rmnet/shs/rmnet_shs.h | 4 ++-- drivers/rmnet/shs/rmnet_shs_config.c | 6 ++++-- drivers/rmnet/shs/rmnet_shs_main.c | 19 +++++++++++++++---- 3 files changed, 21 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/rmnet/shs/rmnet_shs.h b/drivers/rmnet/shs/rmnet_shs.h index f6ce09e..b7bf773 100644 --- a/drivers/rmnet/shs/rmnet_shs.h +++ b/drivers/rmnet/shs/rmnet_shs.h @@ -299,7 +299,7 @@ extern int (*rmnet_shs_skb_entry)(struct sk_buff *skb, int rmnet_shs_is_lpwr_cpu(u16 cpu); void rmnet_shs_cancel_table(void); void rmnet_shs_rx_wq_init(void); -void rmnet_shs_rx_wq_exit(void); +unsigned int rmnet_shs_rx_wq_exit(void); int rmnet_shs_get_mask_len(u8 mask); int rmnet_shs_chk_and_flush_node(struct rmnet_shs_skbn_s *node, @@ -314,7 +314,7 @@ void rmnet_shs_assign(struct sk_buff *skb, struct rmnet_port *port); void rmnet_shs_flush_table(u8 is_force_flush, u8 ctxt); void rmnet_shs_cpu_node_remove(struct rmnet_shs_skbn_s *node); void rmnet_shs_init(struct net_device *dev, struct net_device *vnd); -void rmnet_shs_exit(void); +void rmnet_shs_exit(unsigned int cpu_switch); void rmnet_shs_ps_on_hdlr(void *port); void rmnet_shs_ps_off_hdlr(void *port); void rmnet_shs_update_cpu_proc_q_all_cpus(void); diff --git a/drivers/rmnet/shs/rmnet_shs_config.c b/drivers/rmnet/shs/rmnet_shs_config.c index e6b4002..6a628dc 100644 --- a/drivers/rmnet/shs/rmnet_shs_config.c +++ b/drivers/rmnet/shs/rmnet_shs_config.c @@ -99,14 +99,16 @@ static int rmnet_shs_dev_notify_cb(struct notifier_block *nb, * phy_dev is going down. */ if (!rmnet_vnd_total && rmnet_shs_cfg.rmnet_shs_init_complete) { + unsigned int cpu_switch; + pr_info("rmnet_shs deinit %s going down ", dev->name); RCU_INIT_POINTER(rmnet_shs_skb_entry, NULL); qmi_rmnet_ps_ind_deregister(rmnet_shs_cfg.port, &rmnet_shs_cfg.rmnet_idl_ind_cb); rmnet_shs_cancel_table(); - rmnet_shs_rx_wq_exit(); + cpu_switch = rmnet_shs_rx_wq_exit(); rmnet_shs_wq_exit(); - rmnet_shs_exit(); + rmnet_shs_exit(cpu_switch); trace_rmnet_shs_high(RMNET_SHS_MODULE, RMNET_SHS_MODULE_INIT_WQ, 0xDEF, 0xDEF, 0xDEF, diff --git a/drivers/rmnet/shs/rmnet_shs_main.c b/drivers/rmnet/shs/rmnet_shs_main.c index ae66460..2accd29 100755 --- a/drivers/rmnet/shs/rmnet_shs_main.c +++ b/drivers/rmnet/shs/rmnet_shs_main.c @@ -1359,14 +1359,25 @@ void rmnet_shs_rx_wq_init(void) INIT_WORK(&shs_rx_work.work, rmnet_flush_buffered); } -void rmnet_shs_rx_wq_exit(void) +unsigned int rmnet_shs_rx_wq_exit(void) { + unsigned int cpu_switch = rmnet_shs_inst_rate_switch; int i; - for (i = 0; i < MAX_CPUS; i++) + /* Disable any further core_flush timer starts untill cleanup + * is complete. + */ + rmnet_shs_inst_rate_switch = 0; + + for (i = 0; i < MAX_CPUS; i++) { + hrtimer_cancel(&GET_CTIMER(i)); + cancel_work_sync(&rmnet_shs_cfg.core_flush[i].work); + } cancel_work_sync(&shs_rx_work.work); + + return cpu_switch; } void rmnet_shs_ps_on_hdlr(void *port) @@ -1724,7 +1735,7 @@ void rmnet_shs_assign(struct sk_buff *skb, struct rmnet_port *port) /* Cancels the flushing timer if it has been armed * Deregisters DL marker indications */ -void rmnet_shs_exit(void) +void rmnet_shs_exit(unsigned int cpu_switch) { rmnet_shs_freq_exit(); rmnet_shs_cfg.dl_mrk_ind_cb.dl_hdr_handler = NULL; @@ -1738,5 +1749,5 @@ void rmnet_shs_exit(void) memset(&rmnet_shs_cfg, 0, sizeof(rmnet_shs_cfg)); rmnet_shs_cfg.port = NULL; rmnet_shs_cfg.rmnet_shs_init_complete = 0; - + rmnet_shs_inst_rate_switch = cpu_switch; } -- cgit v1.2.3