qcacld-3.0: Add sysfs entry to dynamically control GRO
Add dp_aggregation sysfs entry under the wifi sysfs directory to dynamically control aggregation in the rx direction. Change-Id: Ic7b13806f5fbd19fe5c56cabdf71d032b730448c CRs-Fixed: 2718131
This commit is contained in:
parent
cec526afda
commit
0c04652083
1
Kbuild
1
Kbuild
@ -369,6 +369,7 @@ ifeq ($(CONFIG_REMOVE_PKT_LOG), n)
|
||||
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_sysfs_pktlog.o
|
||||
endif
|
||||
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_sysfs_policy_mgr.o
|
||||
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_sysfs_dp_aggregation.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_QCACLD_FEATURE_FW_STATE), y)
|
||||
|
@ -104,6 +104,7 @@
|
||||
#include "wma_sar_public_structs.h"
|
||||
#include "wlan_mlme_ucfg_api.h"
|
||||
#include "pld_common.h"
|
||||
#include <dp_txrx.h>
|
||||
|
||||
#ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH
|
||||
#include "qdf_periodic_work.h"
|
||||
@ -1649,6 +1650,8 @@ struct hdd_fw_ver_info {
|
||||
* @dynamic_nss_chains_support: Per vdev dynamic nss chains update capability
|
||||
* @sar_cmd_params: SAR command params to be configured to the FW
|
||||
* @country_change_work: work for updating vdev when country changes
|
||||
* @rx_aggregation: rx aggregation enable or disable state
|
||||
* @gro_force_flush: gro force flushed indication flag
|
||||
*/
|
||||
struct hdd_context {
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
@ -1974,6 +1977,10 @@ struct hdd_context {
|
||||
uint8_t dutycycle_off_percent;
|
||||
#endif
|
||||
qdf_work_t country_change_work;
|
||||
struct {
|
||||
qdf_atomic_t rx_aggregation;
|
||||
uint8_t gro_force_flush[DP_MAX_RX_THREADS];
|
||||
} dp_agg_param;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -75,6 +75,7 @@
|
||||
#include <wlan_hdd_sysfs_ipa.h>
|
||||
#include <wlan_hdd_sysfs_pkt_log.h>
|
||||
#include <wlan_hdd_sysfs_policy_mgr.h>
|
||||
#include <wlan_hdd_sysfs_dp_aggregation.h>
|
||||
|
||||
#define MAX_PSOC_ID_SIZE 10
|
||||
|
||||
@ -782,12 +783,14 @@ void hdd_create_sysfs_files(struct hdd_context *hdd_ctx)
|
||||
hdd_sysfs_pm_cinfo_create(driver_kobject);
|
||||
hdd_sysfs_pm_pcl_create(driver_kobject);
|
||||
hdd_sysfs_pm_dbs_create(driver_kobject);
|
||||
hdd_sysfs_dp_aggregation_create(driver_kobject);
|
||||
}
|
||||
}
|
||||
|
||||
void hdd_destroy_sysfs_files(void)
|
||||
{
|
||||
if (QDF_GLOBAL_MISSION_MODE == hdd_get_conparam()) {
|
||||
hdd_sysfs_dp_aggregation_destroy(driver_kobject);
|
||||
hdd_sysfs_pm_dbs_destroy(driver_kobject);
|
||||
hdd_sysfs_pm_pcl_destroy(driver_kobject);
|
||||
hdd_sysfs_pm_cinfo_destroy(driver_kobject);
|
||||
|
178
core/hdd/src/wlan_hdd_sysfs_dp_aggregation.c
Normal file
178
core/hdd/src/wlan_hdd_sysfs_dp_aggregation.c
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 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 above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: wlan_hdd_sysfs_dp_aggregation.c
|
||||
*
|
||||
* implementation for creating sysfs files:
|
||||
*
|
||||
* dp_aggregation
|
||||
*/
|
||||
|
||||
#include <wlan_hdd_includes.h>
|
||||
#include "osif_psoc_sync.h"
|
||||
#include <wlan_hdd_sysfs.h>
|
||||
#include <wlan_hdd_sysfs_dp_aggregation.h>
|
||||
#if defined(WLAN_SUPPORT_RX_FISA)
|
||||
#include "dp_fisa_rx.h"
|
||||
#endif
|
||||
|
||||
#if defined(WLAN_SUPPORT_RX_FISA)
|
||||
static inline
|
||||
void hdd_rx_skip_fisa(ol_txrx_soc_handle dp_soc, uint32_t value)
|
||||
{
|
||||
dp_rx_skip_fisa(dp_soc, value);
|
||||
}
|
||||
#else
|
||||
static inline
|
||||
void hdd_rx_skip_fisa(ol_txrx_soc_handle dp_soc, uint32_t value)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t
|
||||
__hdd_sysfs_dp_aggregation_show(struct hdd_context *hdd_ctx,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wlan_hdd_validate_context(hdd_ctx);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (!wlan_hdd_validate_modules_state(hdd_ctx))
|
||||
return -EINVAL;
|
||||
|
||||
hdd_debug("dp_aggregation: %d",
|
||||
qdf_atomic_read(&hdd_ctx->dp_agg_param.rx_aggregation));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t hdd_sysfs_dp_aggregation_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct osif_psoc_sync *psoc_sync;
|
||||
struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
|
||||
ssize_t errno_size;
|
||||
|
||||
errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
|
||||
&psoc_sync);
|
||||
if (errno_size)
|
||||
return errno_size;
|
||||
|
||||
errno_size = __hdd_sysfs_dp_aggregation_show(hdd_ctx, attr, buf);
|
||||
|
||||
osif_psoc_sync_op_stop(psoc_sync);
|
||||
|
||||
return errno_size;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
__hdd_sysfs_dp_aggregation_store(struct hdd_context *hdd_ctx,
|
||||
struct kobj_attribute *attr, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
|
||||
char *sptr, *token;
|
||||
uint32_t value;
|
||||
int ret;
|
||||
ol_txrx_soc_handle dp_soc = cds_get_context(QDF_MODULE_ID_SOC);
|
||||
|
||||
ret = wlan_hdd_validate_context(hdd_ctx);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (!wlan_hdd_validate_modules_state(hdd_ctx) || !dp_soc)
|
||||
return -EINVAL;
|
||||
|
||||
ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
|
||||
buf, count);
|
||||
|
||||
if (ret) {
|
||||
hdd_err_rl("invalid input");
|
||||
return ret;
|
||||
}
|
||||
|
||||
sptr = buf_local;
|
||||
token = strsep(&sptr, " ");
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
if (kstrtou32(token, 0, &value))
|
||||
return -EINVAL;
|
||||
|
||||
hdd_debug("dp_aggregation: %d", value);
|
||||
|
||||
hdd_rx_skip_fisa(dp_soc, value);
|
||||
qdf_atomic_set(&hdd_ctx->dp_agg_param.rx_aggregation, !!value);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
hdd_sysfs_dp_aggregation_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char const *buf, size_t count)
|
||||
{
|
||||
struct osif_psoc_sync *psoc_sync;
|
||||
struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
|
||||
ssize_t errno_size;
|
||||
|
||||
errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
|
||||
&psoc_sync);
|
||||
if (errno_size)
|
||||
return errno_size;
|
||||
|
||||
errno_size = __hdd_sysfs_dp_aggregation_store(hdd_ctx, attr,
|
||||
buf, count);
|
||||
|
||||
osif_psoc_sync_op_stop(psoc_sync);
|
||||
|
||||
return errno_size;
|
||||
}
|
||||
|
||||
static struct kobj_attribute dp_aggregation_attribute =
|
||||
__ATTR(dp_aggregation, 0664, hdd_sysfs_dp_aggregation_show,
|
||||
hdd_sysfs_dp_aggregation_store);
|
||||
|
||||
int hdd_sysfs_dp_aggregation_create(struct kobject *driver_kobject)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!driver_kobject) {
|
||||
hdd_err("could not get driver kobject!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
error = sysfs_create_file(driver_kobject,
|
||||
&dp_aggregation_attribute.attr);
|
||||
if (error)
|
||||
hdd_err("could not create dp_aggregation sysfs file");
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
hdd_sysfs_dp_aggregation_destroy(struct kobject *driver_kobject)
|
||||
{
|
||||
if (!driver_kobject) {
|
||||
hdd_err("could not get driver kobject!");
|
||||
return;
|
||||
}
|
||||
|
||||
sysfs_remove_file(driver_kobject, &dp_aggregation_attribute.attr);
|
||||
}
|
65
core/hdd/src/wlan_hdd_sysfs_dp_aggregation.h
Normal file
65
core/hdd/src/wlan_hdd_sysfs_dp_aggregation.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 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 above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: wlan_hdd_sysfs_dp_aggregation.h
|
||||
*
|
||||
* implementation for creating sysfs files:
|
||||
*
|
||||
* dp_aggregation
|
||||
*/
|
||||
|
||||
#ifndef _WLAN_HDD_SYSFS_DP_AGGREGATION_H
|
||||
#define _WLAN_HDD_SYSFS_DP_AGGREGATION_H
|
||||
|
||||
#if defined(WLAN_SYSFS)
|
||||
/**
|
||||
* hdd_sysfs_dp_aggregation_create() - API to create dp aggregation
|
||||
* related sysfs entry
|
||||
* @driver_kobject: sysfs driver kobject
|
||||
*
|
||||
* file path: /sys/kernel/wifi/dp_aggregation
|
||||
*
|
||||
* usage:
|
||||
* echo [0/1] > dp_aggregation
|
||||
*
|
||||
* Return: 0 on success and errno on failure
|
||||
*/
|
||||
int
|
||||
hdd_sysfs_dp_aggregation_create(struct kobject *drv_kobj);
|
||||
|
||||
/**
|
||||
* hdd_sysfs_dp_aggregation_destroy() - API to destroy dp aggregation
|
||||
* related sysfs entry
|
||||
* @driver_kobject: sysfs driver kobject
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void
|
||||
hdd_sysfs_dp_aggregation_destroy(struct kobject *drv_kobj);
|
||||
#else
|
||||
static inline int
|
||||
hdd_sysfs_dp_aggregation_create(struct kobject *drv_kobj)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hdd_sysfs_dp_aggregation_destroy(struct kobject *drv_kobj)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef _WLAN_HDD_SYSFS_DP_AGGREGATION_H */
|
@ -1578,18 +1578,25 @@ static QDF_STATUS hdd_gro_rx_bh_disable(struct hdd_adapter *adapter,
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
struct hdd_context *hdd_ctx = adapter->hdd_ctx;
|
||||
gro_result_t gro_ret;
|
||||
uint32_t rx_aggregation;
|
||||
uint8_t rx_ctx_id = QDF_NBUF_CB_RX_CTX_ID(skb);
|
||||
|
||||
rx_aggregation = qdf_atomic_read(&hdd_ctx->dp_agg_param.rx_aggregation);
|
||||
|
||||
skb_set_hash(skb, QDF_NBUF_CB_RX_FLOW_ID(skb), PKT_HASH_TYPE_L4);
|
||||
|
||||
local_bh_disable();
|
||||
gro_ret = napi_gro_receive(napi_to_use, skb);
|
||||
|
||||
if (hdd_get_current_throughput_level(hdd_ctx) == PLD_BUS_WIDTH_IDLE) {
|
||||
if (hdd_get_current_throughput_level(hdd_ctx) == PLD_BUS_WIDTH_IDLE ||
|
||||
!rx_aggregation) {
|
||||
if (HDD_IS_EXTRA_GRO_FLUSH_NECESSARY(gro_ret)) {
|
||||
adapter->hdd_stats.tx_rx_stats.
|
||||
rx_gro_low_tput_flush++;
|
||||
dp_rx_napi_gro_flush(napi_to_use);
|
||||
}
|
||||
if (!rx_aggregation)
|
||||
hdd_ctx->dp_agg_param.gro_force_flush[rx_ctx_id] = 1;
|
||||
}
|
||||
local_bh_enable();
|
||||
|
||||
@ -1759,6 +1766,7 @@ static void hdd_register_rx_ol_cb(struct hdd_context *hdd_ctx,
|
||||
hdd_ctx->receive_offload_cb = hdd_lro_rx;
|
||||
hdd_debug("LRO is enabled");
|
||||
} else if (hdd_ctx->ol_enable == CFG_GRO_ENABLED) {
|
||||
qdf_atomic_set(&hdd_ctx->dp_agg_param.rx_aggregation, 1);
|
||||
if (lithium_based_target) {
|
||||
/* no flush registration needed, it happens in DP thread */
|
||||
hdd_ctx->receive_offload_cb = hdd_gro_rx_dp_thread;
|
||||
@ -1992,12 +2000,14 @@ QDF_STATUS hdd_rx_deliver_to_stack(struct hdd_adapter *adapter,
|
||||
int status = QDF_STATUS_E_FAILURE;
|
||||
int netif_status;
|
||||
bool skb_receive_offload_ok = false;
|
||||
uint8_t rx_ctx_id = QDF_NBUF_CB_RX_CTX_ID(skb);
|
||||
|
||||
if (QDF_NBUF_CB_RX_TCP_PROTO(skb) &&
|
||||
!QDF_NBUF_CB_RX_PEER_CACHED_FRM(skb))
|
||||
skb_receive_offload_ok = true;
|
||||
|
||||
if (skb_receive_offload_ok && hdd_ctx->receive_offload_cb) {
|
||||
if (skb_receive_offload_ok && hdd_ctx->receive_offload_cb &&
|
||||
!hdd_ctx->dp_agg_param.gro_force_flush[rx_ctx_id]) {
|
||||
status = hdd_ctx->receive_offload_cb(adapter, skb);
|
||||
|
||||
if (QDF_IS_STATUS_SUCCESS(status)) {
|
||||
@ -2011,6 +2021,15 @@ QDF_STATUS hdd_rx_deliver_to_stack(struct hdd_adapter *adapter,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The below case handles the scenario when rx_aggregation is
|
||||
* re-enabled dynamically, in which case gro_force_flush needs
|
||||
* to be reset to 0 to allow GRO.
|
||||
*/
|
||||
if (qdf_atomic_read(&hdd_ctx->dp_agg_param.rx_aggregation) &&
|
||||
hdd_ctx->dp_agg_param.gro_force_flush[rx_ctx_id])
|
||||
hdd_ctx->dp_agg_param.gro_force_flush[rx_ctx_id] = 0;
|
||||
|
||||
adapter->hdd_stats.tx_rx_stats.rx_non_aggregated++;
|
||||
|
||||
/* Account for GRO/LRO ineligible packets, mostly UDP */
|
||||
|
Loading…
Reference in New Issue
Block a user