diff --git a/techpack/datarmnet/core/Android.mk b/techpack/datarmnet/core/Android.mk index 9aad807d7d38..f358d0b2ee38 100644 --- a/techpack/datarmnet/core/Android.mk +++ b/techpack/datarmnet/core/Android.mk @@ -2,14 +2,16 @@ ifneq ($(TARGET_PRODUCT),qssi) RMNET_CORE_DLKM_PLATFORMS_LIST := lahaina RMNET_CORE_DLKM_PLATFORMS_LIST += holi RMNET_CORE_DLKM_PLATFORMS_LIST += monaco -RMNET_CORE_DLKM_PLATFORMS_LIST += monaco_go -RMNET_CORE_DLKM_PLATFORMS_LIST += monaco_go_aon ifeq ($(call is-board-platform-in-list, $(RMNET_CORE_DLKM_PLATFORMS_LIST)),true) #Make file to create RMNET_CORE DLKM LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) +ifeq ($(BOARD_COMMON_DIR),) + BOARD_COMMON_DIR := device/qcom/common +endif + LOCAL_CFLAGS := -Wno-macro-redefined -Wno-unused-function -Wall -Werror LOCAL_CLANG :=true @@ -30,7 +32,7 @@ LOCAL_SRC_FILES := \ wda_qmi.c RMNET_BLD_DIR := ../../vendor/qcom/opensource/datarmnet/core -DLKM_DIR := $(TOP)/device/qcom/common/dlkm +DLKM_DIR := $(TOP)/$(BOARD_COMMON_DIR)/dlkm KBUILD_OPTIONS := $(RMNET_BLD_DIR) @@ -51,7 +53,7 @@ LOCAL_SRC_FILES := \ rmnet_ctl_ipa.c RMNET_BLD_DIR := ../../vendor/qcom/opensource/datarmnet/core -DLKM_DIR := $(TOP)/device/qcom/common/dlkm +DLKM_DIR := $(TOP)/$(BOARD_COMMON_DIR)/dlkm KBUILD_OPTIONS := $(RMNET_BLD_DIR) diff --git a/techpack/datarmnet/core/dfc_qmap.c b/techpack/datarmnet/core/dfc_qmap.c index f371a0f6e7bf..6afc12cdb15f 100644 --- a/techpack/datarmnet/core/dfc_qmap.c +++ b/techpack/datarmnet/core/dfc_qmap.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -139,11 +140,13 @@ static void dfc_qmap_send_cmd(struct sk_buff *skb) { trace_dfc_qmap(skb->data, skb->len, false); - if (unlikely(!rmnet_ctl || !rmnet_ctl->send) || - rmnet_ctl->send(rmnet_ctl_handle, skb)) { - pr_err("Failed to send to rmnet ctl\n"); + if (unlikely(!rmnet_ctl || !rmnet_ctl->send)) { kfree_skb(skb); + return; } + + if (rmnet_ctl->send(rmnet_ctl_handle, skb)) + pr_err("Failed to send to rmnet ctl\n"); } static void dfc_qmap_send_inband_ack(struct dfc_qmi_data *dfc, diff --git a/techpack/datarmnet/core/dfc_qmi.c b/techpack/datarmnet/core/dfc_qmi.c index f52d9e3e032f..2b10540564c6 100644 --- a/techpack/datarmnet/core/dfc_qmi.c +++ b/techpack/datarmnet/core/dfc_qmi.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 @@ -1003,7 +1004,9 @@ static int dfc_update_fc_map(struct net_device *dev, struct qos_info *qos, u32 adjusted_grant; itm = qmi_rmnet_get_bearer_map(qos, fc_info->bearer_id); - if (!itm) + + /* cache the bearer assuming it is a new bearer */ + if (unlikely(!itm && !is_query && fc_info->num_bytes)) itm = qmi_rmnet_get_bearer_noref(qos, fc_info->bearer_id); if (itm) { diff --git a/techpack/datarmnet/core/qmi_rmnet.c b/techpack/datarmnet/core/qmi_rmnet.c index 84818c9b8f57..851d63c6f66b 100644 --- a/techpack/datarmnet/core/qmi_rmnet.c +++ b/techpack/datarmnet/core/qmi_rmnet.c @@ -1,5 +1,6 @@ /* -* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 @@ -221,21 +222,6 @@ int qmi_rmnet_flow_control(struct net_device *dev, u32 mq_idx, int enable) return 0; } -static void qmi_rmnet_reset_txq(struct net_device *dev, unsigned int txq) -{ - struct Qdisc *qdisc; - - if (unlikely(txq >= dev->num_tx_queues)) - return; - - qdisc = rtnl_dereference(netdev_get_tx_queue(dev, txq)->qdisc); - if (qdisc) { - spin_lock_bh(qdisc_lock(qdisc)); - qdisc_reset(qdisc); - spin_unlock_bh(qdisc_lock(qdisc)); - } -} - /** * qmi_rmnet_watchdog_fn - watchdog timer func */ @@ -361,15 +347,13 @@ static void __qmi_rmnet_bearer_put(struct net_device *dev, continue; mq->bearer = NULL; - if (reset) { - qmi_rmnet_reset_txq(dev, i); - qmi_rmnet_flow_control(dev, i, 1); + mq->drop_on_remove = reset; + smp_mb(); - if (dfc_mode == DFC_MODE_SA) { - j = i + ACK_MQ_OFFSET; - qmi_rmnet_reset_txq(dev, j); - qmi_rmnet_flow_control(dev, j, 1); - } + qmi_rmnet_flow_control(dev, i, 1); + if (dfc_mode == DFC_MODE_SA) { + j = i + ACK_MQ_OFFSET; + qmi_rmnet_flow_control(dev, j, 1); } } @@ -393,6 +377,8 @@ static void __qmi_rmnet_update_mq(struct net_device *dev, mq = &qos_info->mq[itm->mq_idx]; if (!mq->bearer) { mq->bearer = bearer; + mq->drop_on_remove = false; + smp_mb(); if (dfc_mode == DFC_MODE_SA) { bearer->mq_idx = itm->mq_idx; @@ -401,12 +387,15 @@ static void __qmi_rmnet_update_mq(struct net_device *dev, bearer->mq_idx = itm->mq_idx; } - qmi_rmnet_flow_control(dev, itm->mq_idx, - bearer->grant_size > 0 ? 1 : 0); - + /* Always enable flow for the newly associated bearer */ + if (!bearer->grant_size) { + bearer->grant_size = DEFAULT_GRANT; + bearer->grant_thresh = + qmi_rmnet_grant_per(DEFAULT_GRANT); + } + qmi_rmnet_flow_control(dev, itm->mq_idx, 1); if (dfc_mode == DFC_MODE_SA) - qmi_rmnet_flow_control(dev, bearer->ack_mq_idx, - bearer->grant_size > 0 ? 1 : 0); + qmi_rmnet_flow_control(dev, bearer->ack_mq_idx, 1); } } @@ -873,6 +862,26 @@ bool qmi_rmnet_all_flows_enabled(struct net_device *dev) EXPORT_SYMBOL(qmi_rmnet_all_flows_enabled); #ifdef CONFIG_QTI_QMI_DFC +bool qmi_rmnet_get_flow_state(struct net_device *dev, struct sk_buff *skb, + bool *drop) +{ + struct qos_info *qos = rmnet_get_qos_pt(dev); + int txq = skb->queue_mapping; + + if (txq > ACK_MQ_OFFSET) + txq -= ACK_MQ_OFFSET; + + if (unlikely(!qos || txq >= MAX_MQ_NUM)) + return false; + + /* If the bearer is gone, packets may need to be dropped */ + *drop = (txq != DEFAULT_MQ_NUM && !READ_ONCE(qos->mq[txq].bearer) && + READ_ONCE(qos->mq[txq].drop_on_remove)); + + return true; +} +EXPORT_SYMBOL(qmi_rmnet_get_flow_state); + void qmi_rmnet_burst_fc_check(struct net_device *dev, int ip_type, u32 mark, unsigned int len) { diff --git a/techpack/datarmnet/core/qmi_rmnet.h b/techpack/datarmnet/core/qmi_rmnet.h index 80689e807236..855817d39a6c 100644 --- a/techpack/datarmnet/core/qmi_rmnet.h +++ b/techpack/datarmnet/core/qmi_rmnet.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 @@ -59,6 +60,8 @@ void *qmi_rmnet_qos_init(struct net_device *real_dev, struct net_device *vnd_dev, u8 mux_id); void qmi_rmnet_qos_exit_pre(void *qos); void qmi_rmnet_qos_exit_post(void); +bool qmi_rmnet_get_flow_state(struct net_device *dev, struct sk_buff *skb, + bool *drop); void qmi_rmnet_burst_fc_check(struct net_device *dev, int ip_type, u32 mark, unsigned int len); int qmi_rmnet_get_queue(struct net_device *dev, struct sk_buff *skb); @@ -78,6 +81,13 @@ static inline void qmi_rmnet_qos_exit_post(void) { } +static inline bool qmi_rmnet_get_flow_state(struct net_device *dev, + struct sk_buff *skb, + bool *drop) +{ + return false; +} + static inline void qmi_rmnet_burst_fc_check(struct net_device *dev, int ip_type, u32 mark, unsigned int len) diff --git a/techpack/datarmnet/core/qmi_rmnet_i.h b/techpack/datarmnet/core/qmi_rmnet_i.h index 082351065686..dc50d30a2e73 100644 --- a/techpack/datarmnet/core/qmi_rmnet_i.h +++ b/techpack/datarmnet/core/qmi_rmnet_i.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 @@ -82,6 +83,7 @@ struct svc_info { struct mq_map { struct rmnet_bearer_map *bearer; + bool drop_on_remove; }; struct qos_info { diff --git a/techpack/datarmnet/core/rmnet_config.c b/techpack/datarmnet/core/rmnet_config.c index b341099c15b7..47cc316bd37c 100644 --- a/techpack/datarmnet/core/rmnet_config.c +++ b/techpack/datarmnet/core/rmnet_config.c @@ -1,4 +1,5 @@ /* Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -641,6 +642,7 @@ EXPORT_SYMBOL(rmnet_init_qmi_pt); void rmnet_get_packets(void *port, u64 *rx, u64 *tx) { + struct net_device *dev; struct rmnet_priv *priv; struct rmnet_pcpu_stats *ps; unsigned int cpu, start; @@ -654,8 +656,12 @@ void rmnet_get_packets(void *port, u64 *rx, u64 *tx) *tx = 0; *rx = 0; rcu_read_lock(); - hash_for_each(((struct rmnet_port *)port)->muxed_ep, bkt, ep, hlnode) { - priv = netdev_priv(ep->egress_dev); + hash_for_each_rcu(((struct rmnet_port *)port)->muxed_ep, bkt, ep, + hlnode) { + dev = ep->egress_dev; + if (!dev) + continue; + priv = netdev_priv(dev); for_each_possible_cpu(cpu) { ps = per_cpu_ptr(priv->pcpu_stats, cpu); do { diff --git a/techpack/datarmnet/core/rmnet_ctl_client.c b/techpack/datarmnet/core/rmnet_ctl_client.c index 4958deac1c75..1ec53dea3f18 100644 --- a/techpack/datarmnet/core/rmnet_ctl_client.c +++ b/techpack/datarmnet/core/rmnet_ctl_client.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * RMNET_CTL client handlers * @@ -171,8 +172,10 @@ int rmnet_ctl_send_client(void *handle, struct sk_buff *skb) struct rmnet_ctl_dev *dev; int rc = -EINVAL; - if (client != rcu_dereference(ctl_ep.client)) + if (client != rcu_dereference(ctl_ep.client)) { + kfree_skb(skb); return rc; + } rmnet_ctl_log_info("TX", skb->data, skb->len); @@ -181,11 +184,13 @@ int rmnet_ctl_send_client(void *handle, struct sk_buff *skb) dev = rcu_dereference(ctl_ep.dev); if (dev && dev->xmit) rc = dev->xmit(dev, skb); + else + kfree_skb(skb); rcu_read_unlock(); if (rc) - rmnet_ctl_log_err("TXE", rc, skb->data, skb->len); + rmnet_ctl_log_err("TXE", rc, NULL, 0); return rc; } diff --git a/techpack/datarmnet/core/rmnet_vnd.c b/techpack/datarmnet/core/rmnet_vnd.c index d5187be0497d..84e43271318f 100644 --- a/techpack/datarmnet/core/rmnet_vnd.c +++ b/techpack/datarmnet/core/rmnet_vnd.c @@ -1,4 +1,5 @@ /* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 @@ -68,6 +69,7 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, int ip_type; u32 mark; unsigned int len; + bool need_to_drop = false; priv = netdev_priv(dev); if (priv->real_dev) { @@ -76,6 +78,14 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, mark = skb->mark; len = skb->len; trace_rmnet_xmit_skb(skb); + + qmi_rmnet_get_flow_state(dev, skb, &need_to_drop); + if (unlikely(need_to_drop)) { + this_cpu_inc(priv->pcpu_stats->stats.tx_drops); + kfree_skb(skb); + return NETDEV_TX_OK; + } + rmnet_egress_handler(skb); qmi_rmnet_burst_fc_check(dev, ip_type, mark, len); qmi_rmnet_work_maybe_restart(rmnet_get_rmnet_port(dev)); diff --git a/techpack/datarmnet/datarmnet_dlkm_vendor_board.mk b/techpack/datarmnet/datarmnet_dlkm_vendor_board.mk index 60a81a7d351b..3eb26a9fc94d 100644 --- a/techpack/datarmnet/datarmnet_dlkm_vendor_board.mk +++ b/techpack/datarmnet/datarmnet_dlkm_vendor_board.mk @@ -2,8 +2,6 @@ DATA_DLKM_BOARD_PLATFORMS_LIST := lahaina DATA_DLKM_BOARD_PLATFORMS_LIST += holi DATA_DLKM_BOARD_PLATFORMS_LIST += monaco -DATA_DLKM_BOARD_PLATFORMS_LIST += monaco_go -DATA_DLKM_BOARD_PLATFORMS_LIST += monaco_go_aon ifneq ($(TARGET_BOARD_AUTO),true) ifeq ($(call is-board-platform-in-list,$(DATA_DLKM_BOARD_PLATFORMS_LIST)),true) BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/rmnet_core.ko