qcacld-3.0: Add capability to disable checksum for legacy links

Due to latency concerns on GEN1 PCIe attach checksum offload and TSO
features cannot be enabled for 802.11A/B/G legacy mode connections.
So add INI option to dynamically disable/enable checksum offload and TSO
based on the connection type.
Use netdev_update_features kernel API to adjust the netdev features
dynamically for existing registered netdev.

change-id: I0e44cb1789516e1bcee619be3581d826f45f265b
CRs-Fixed: 2732090
Esse commit está contido em:
Manjunathappa Prakash
2020-07-06 03:04:09 -07:00
commit de snandini
commit ef666adfcf
6 arquivos alterados com 245 adições e 13 exclusões

Ver arquivo

@@ -427,6 +427,8 @@ static void cds_cdp_cfg_attach(struct wlan_objmgr_psoc *psoc)
cfg_get(psoc, CFG_DP_NAN_TCP_UDP_CKSUM_OFFLOAD);
cdp_cfg.p2p_ip_tcp_udp_checksum_offload =
cfg_get(psoc, CFG_DP_P2P_TCP_UDP_CKSUM_OFFLOAD);
cdp_cfg.legacy_mode_csum_disable =
cfg_get(psoc, CFG_DP_LEGACY_MODE_CSUM_DISABLE);
cdp_cfg.ce_classify_enabled =
cfg_get(psoc, CFG_DP_CE_CLASSIFY_ENABLE);
cdp_cfg.tso_enable = cfg_get(psoc, CFG_DP_TSO);

Ver arquivo

@@ -1116,6 +1116,8 @@ struct hdd_context;
any UDP packet.
* @gro_disallowed: Flag to check if GRO is enabled or disable for adapter
* @gro_flushed: Flag to indicate if GRO explicit flush is done or not
* @handle_feature_update: Handle feature update only if it is triggered
* by hdd_netdev_feature_update
*/
struct hdd_adapter {
/* Magic cookie for adapter sanity verification. Note that this
@@ -1412,6 +1414,7 @@ struct hdd_adapter {
#endif
uint8_t gro_disallowed[DP_MAX_RX_THREADS];
uint8_t gro_flushed[DP_MAX_RX_THREADS];
bool handle_feature_update;
};
#define WLAN_HDD_GET_STATION_CTX_PTR(adapter) (&(adapter)->session.station)
@@ -3304,6 +3307,36 @@ static inline void hdd_set_sg_flags(struct hdd_context *hdd_ctx,
void hdd_set_netdev_flags(struct hdd_adapter *adapter);
#ifdef FEATURE_TSO
/**
* hdd_get_tso_csum_feature_flags() - Return TSO and csum flags if enabled
*
* Return: Enabled feature flags set, 0 on failure
*/
static inline netdev_features_t hdd_get_tso_csum_feature_flags(void)
{
netdev_features_t netdev_features = 0;
ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
if (!soc) {
hdd_err("soc handle is NULL");
return 0;
}
if (cdp_cfg_get(soc, cfg_dp_enable_ip_tcp_udp_checksum_offload)) {
netdev_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
if (cdp_cfg_get(soc, cfg_dp_tso_enable)) {
/*
* Enable TSO only if IP/UDP/TCP TX checksum flag is
* enabled.
*/
netdev_features |= NETIF_F_TSO | NETIF_F_TSO6 |
NETIF_F_SG;
}
}
return netdev_features;
}
/**
* hdd_set_tso_flags() - enable TSO flags in the network device
* @hdd_ctx: HDD context
@@ -3317,19 +3350,9 @@ void hdd_set_netdev_flags(struct hdd_adapter *adapter);
static inline void hdd_set_tso_flags(struct hdd_context *hdd_ctx,
struct net_device *wlan_dev)
{
if (cdp_cfg_get(cds_get_context(QDF_MODULE_ID_SOC),
cfg_dp_tso_enable) &&
cdp_cfg_get(cds_get_context(QDF_MODULE_ID_SOC),
cfg_dp_enable_ip_tcp_udp_checksum_offload)){
/*
* We want to enable TSO only if IP/UDP/TCP TX checksum flag is
* enabled.
*/
hdd_debug("TSO Enabled");
wlan_dev->features |=
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_SG;
}
hdd_debug("TSO Enabled");
wlan_dev->features |= hdd_get_tso_csum_feature_flags();
}
#else
static inline void hdd_set_tso_flags(struct hdd_context *hdd_ctx,
@@ -3337,6 +3360,11 @@ static inline void hdd_set_tso_flags(struct hdd_context *hdd_ctx,
{
hdd_set_sg_flags(hdd_ctx, wlan_dev);
}
static inline netdev_features_t hdd_get_tso_csum_feature_flags(void)
{
return 0;
}
#endif /* FEATURE_TSO */
/**
@@ -4517,4 +4545,14 @@ static inline void hdd_beacon_latency_event_cb(uint32_t latency_level)
}
#endif
/**
* hdd_netdev_feature_update - Update the netdev features
* @net_dev: Handle to net_device
*
* This func holds the rtnl_lock. Do not call with rtnl_lock held.
*
* Return: None
*/
void hdd_netdev_update_features(struct hdd_adapter *adapter);
#endif /* end #if !defined(WLAN_HDD_MAIN_H) */

Ver arquivo

@@ -1599,6 +1599,8 @@ static void hdd_send_association_event(struct net_device *dev,
if (ucfg_pkt_capture_get_pktcap_mode(hdd_ctx->psoc))
ucfg_pkt_capture_record_channel(adapter->vdev);
hdd_netdev_update_features(adapter);
} else { /* Not Associated */
hdd_nofl_info("%s(vdevid-%d): disconnected", dev->name,
adapter->vdev_id);

Ver arquivo

@@ -24011,6 +24011,21 @@ hdd_convert_cfgdot11mode_to_80211mode(enum csr_cfgdot11mode mode)
}
}
bool hdd_is_legacy_connection(struct hdd_adapter *adapter)
{
struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
int connection_mode;
connection_mode = hdd_convert_cfgdot11mode_to_80211mode(
sta_ctx->conn_info.dot11mode);
if (connection_mode == QCA_WLAN_802_11_MODE_11A ||
connection_mode == QCA_WLAN_802_11_MODE_11B ||
connection_mode == QCA_WLAN_802_11_MODE_11G)
return true;
else
return false;
}
static int __wlan_hdd_cfg80211_get_channel(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct cfg80211_chan_def *chandef)

Ver arquivo

@@ -851,4 +851,13 @@ static inline void hdd_send_update_owe_info_event(struct hdd_adapter *adapter,
{
}
#endif
/**
* hdd_is_legacy_connection() - Is adapter connection is legacy
* @adapter: Handle to hdd_adapter
*
* Return: true if connection mode is legacy, false otherwise.
*/
bool hdd_is_legacy_connection(struct hdd_adapter *adapter);
#endif

Ver arquivo

@@ -192,6 +192,7 @@
#include "wlan_coex_ucfg_api.h"
#include "wlan_cm_roam_api.h"
#include "wlan_cm_roam_ucfg_api.h"
#include <cdp_txrx_ctrl.h>
#ifdef MODULE
#define WLAN_MODULE_NAME module_name(THIS_MODULE)
@@ -1026,6 +1027,9 @@ static int __hdd_netdev_notifier_call(struct net_device *net_dev,
*/
wlan_cfg80211_cleanup_scan_queue(hdd_ctx->pdev, net_dev);
break;
case NETDEV_FEAT_CHANGE:
hdd_debug("vdev %d netdev Feature 0x%llx\n",
adapter->vdev_id, net_dev->features);
default:
break;
@@ -4748,11 +4752,173 @@ static const struct ethtool_ops wlan_ethtool_ops = {
};
#endif
/**
* __hdd_fix_features - Adjust the feature flags needed to be updated
* @net_dev: Handle to net_device
* @features: Currently enabled feature flags
*
* Return: Adjusted feature flags on success, old feature on failure
*/
static netdev_features_t __hdd_fix_features(struct net_device *net_dev,
netdev_features_t features)
{
netdev_features_t feature_change_req = features;
netdev_features_t feature_tso_csum;
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
if (!adapter->handle_feature_update) {
hdd_debug("Not triggered by hdd_netdev_update_features");
return features;
}
feature_tso_csum = hdd_get_tso_csum_feature_flags();
if (hdd_is_legacy_connection(adapter))
/* Disable checksum and TSO */
feature_change_req &= ~feature_tso_csum;
else
/* Enable checksum and TSO */
feature_change_req |= feature_tso_csum;
hdd_debug("vdev mode %d current features 0x%llx, requesting feature change 0x%llx",
adapter->device_mode, net_dev->features,
feature_change_req);
return feature_change_req;
}
/**
* hdd_fix_features() - Wrapper for __hdd_fix_features to protect it from SSR
* @net_dev: Pointer to net_device structure
* @features: Updated features set
*
* Adjusts the feature request, do not update the device yet.
*
* Return: updated feature for success, incoming feature as is on failure
*/
static netdev_features_t hdd_fix_features(struct net_device *net_dev,
netdev_features_t features)
{
int errno;
int changed_features = features;
struct osif_vdev_sync *vdev_sync;
errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
if (errno)
return features;
changed_features = __hdd_fix_features(net_dev, features);
osif_vdev_sync_op_stop(vdev_sync);
return changed_features;
}
/**
* __hdd_set_features - Update device config for resultant change in feature
* @net_dev: Handle to net_device
* @features: Existing + requested feature after resolving the dependency
*
* Return: 0 on success, non zero error on failure
*/
static int __hdd_set_features(struct net_device *net_dev,
netdev_features_t features)
{
struct hdd_adapter *adapter = netdev_priv(net_dev);
cdp_config_param_type vdev_param;
ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
if (!adapter->handle_feature_update) {
hdd_debug("Not triggered by hdd_netdev_update_features");
return 0;
}
if (!soc) {
hdd_err("soc handle is NULL");
return 0;
}
hdd_debug("vdev mode %d vdev_id %d current features 0x%llx, changed features 0x%llx",
adapter->device_mode, adapter->vdev_id, net_dev->features,
features);
if (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))
vdev_param.cdp_enable_tx_checksum = true;
else
vdev_param.cdp_enable_tx_checksum = false;
if (cdp_txrx_set_vdev_param(soc, adapter->vdev_id, CDP_ENABLE_CSUM,
vdev_param))
hdd_debug("Failed to set DP vdev params");
return 0;
}
/**
* hdd_set_features() - Wrapper for __hdd_set_features to protect it from SSR
* @net_dev: Pointer to net_device structure
* @features: Updated features set
*
* Is called to update device configurations for changed features.
*
* Return: 0 for success, non-zero for failure
*/
static int hdd_set_features(struct net_device *net_dev,
netdev_features_t features)
{
int errno;
struct osif_vdev_sync *vdev_sync;
errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
if (errno)
return errno;
errno = __hdd_set_features(net_dev, features);
osif_vdev_sync_op_stop(vdev_sync);
return errno;
}
void hdd_netdev_update_features(struct hdd_adapter *adapter)
{
struct net_device *net_dev = adapter->dev;
ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
bool request_feature_update = false;
if (!soc) {
hdd_err("soc handle is NULL");
return;
}
if (!cdp_cfg_get(soc, cfg_dp_disable_legacy_mode_csum_offload))
return;
switch (adapter->device_mode) {
case QDF_STA_MODE:
if (cdp_cfg_get(soc, cfg_dp_enable_ip_tcp_udp_checksum_offload))
request_feature_update = true;
break;
default:
break;
}
if (request_feature_update) {
hdd_debug("Update net_dev features for device mode %d",
adapter->device_mode);
rtnl_lock();
adapter->handle_feature_update = true;
netdev_update_features(net_dev);
adapter->handle_feature_update = false;
rtnl_unlock();
}
}
static const struct net_device_ops wlan_drv_ops = {
.ndo_open = hdd_open,
.ndo_stop = hdd_stop,
.ndo_uninit = hdd_uninit,
.ndo_start_xmit = hdd_hard_start_xmit,
.ndo_fix_features = hdd_fix_features,
.ndo_set_features = hdd_set_features,
.ndo_tx_timeout = hdd_tx_timeout,
.ndo_get_stats = hdd_get_stats,
.ndo_do_ioctl = hdd_ioctl,