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:

commit de
snandini

pai
6146f6409d
commit
ef666adfcf
@@ -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);
|
||||
|
@@ -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) */
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
Referência em uma nova issue
Block a user