qcacld-3.0: Update linkspeed state to F/W for roaming dp part
To avoid unmeaningful roaming, when low RSSI trigger, only roam when rx linkspeed is also bad. Steps: 1. F/W indicates feature supported by: wmi_service_linkspeed_roam_trigger_support 2. App sets vdev rx link speed threshold by vendor cmd. 3. Bus_bw_work gets rx link speed from data path periodically. 4. If found rx link speed change from good to poor, or poor to good, send to F/W. 5. F/W low rssi roaming is triggered only when both RSSI and link speed are poor. Change-Id: I2c2a22c1f24a730783ee09455f4d70b099d9bff1 CRs-Fixed: 3255036
This commit is contained in:

committed by
Madan Koyyalamudi

parent
c4459eb18e
commit
71eb93c537
@@ -252,9 +252,22 @@ struct wlan_dp_conn_info {
|
||||
uint8_t is_authenticated;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct link_monitoring - link speed monitoring related info
|
||||
* @enabled: Is link speed monitoring feature enabled
|
||||
* @rx_linkspeed_threshold: link speed good/bad threshold
|
||||
* @is_link_speed_good: true means link speed good, false means bad
|
||||
*/
|
||||
struct link_monitoring {
|
||||
uint8_t enabled;
|
||||
uint32_t rx_linkspeed_threshold;
|
||||
uint8_t is_rx_linkspeed_good;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wlan_dp_intf - DP interface object related info
|
||||
* @dp_ctx: DP context reference
|
||||
* @link_monitoring: Link monitoring related info
|
||||
* @mac_addr: Device MAC address
|
||||
* @device_mode: Device Mode
|
||||
* @intf_id: Interface ID
|
||||
@@ -277,6 +290,8 @@ struct wlan_dp_conn_info {
|
||||
struct wlan_dp_intf {
|
||||
struct wlan_dp_psoc_context *dp_ctx;
|
||||
|
||||
struct link_monitoring link_monitoring;
|
||||
|
||||
struct qdf_mac_addr mac_addr;
|
||||
|
||||
enum QDF_OPMODE device_mode;
|
||||
|
@@ -39,6 +39,8 @@
|
||||
#include "wlan_mlme_ucfg_api.h"
|
||||
#include <i_qdf_net_stats.h>
|
||||
#include "wlan_dp_txrx.h"
|
||||
#include "cdp_txrx_host_stats.h"
|
||||
#include "wlan_cm_roam_api.h"
|
||||
|
||||
#ifdef FEATURE_BUS_BANDWIDTH_MGR
|
||||
/**
|
||||
@@ -1697,6 +1699,96 @@ dp_rx_check_qdisc_for_intf(struct wlan_dp_intf *dp_intf)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define NO_RX_PKT_LINK_SPEED_AGEOUT_COUNT 50
|
||||
static void
|
||||
dp_link_monitoring(struct wlan_dp_psoc_context *dp_ctx,
|
||||
struct wlan_dp_intf *dp_intf)
|
||||
{
|
||||
struct cdp_peer_stats *peer_stats;
|
||||
QDF_STATUS status;
|
||||
ol_txrx_soc_handle soc;
|
||||
struct wlan_objmgr_peer *bss_peer;
|
||||
static uint32_t no_rx_times;
|
||||
uint64_t rx_packets;
|
||||
uint32_t link_speed;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct link_monitoring link_mon;
|
||||
|
||||
/*
|
||||
* If throughput is high, link speed should be good, don't check it
|
||||
* to avoid performance penalty
|
||||
*/
|
||||
soc = cds_get_context(QDF_MODULE_ID_SOC);
|
||||
if (cdp_get_bus_lvl_high(soc) == true)
|
||||
return;
|
||||
|
||||
link_mon = dp_intf->link_monitoring;
|
||||
if (!dp_ctx->dp_ops.link_monitoring_cb)
|
||||
return;
|
||||
|
||||
psoc = dp_ctx->psoc;
|
||||
/* If no rx packets received for N sec, set link speed to poor */
|
||||
if (link_mon.is_rx_linkspeed_good) {
|
||||
rx_packets = DP_BW_GET_DIFF(QDF_NET_DEV_STATS_RX_PKTS(&dp_intf->stats),
|
||||
dp_intf->prev_rx_packets);
|
||||
if (!rx_packets)
|
||||
no_rx_times++;
|
||||
else
|
||||
no_rx_times = 0;
|
||||
if (no_rx_times >= NO_RX_PKT_LINK_SPEED_AGEOUT_COUNT) {
|
||||
no_rx_times = 0;
|
||||
dp_ctx->dp_ops.link_monitoring_cb(psoc,
|
||||
dp_intf->intf_id,
|
||||
false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Get rx link speed from dp peer */
|
||||
peer_stats = qdf_mem_malloc(sizeof(*peer_stats));
|
||||
if (!peer_stats)
|
||||
return;
|
||||
bss_peer = wlan_vdev_get_bsspeer(dp_intf->vdev);
|
||||
if (!bss_peer) {
|
||||
dp_debug("Invalid bss peer");
|
||||
qdf_mem_free(peer_stats);
|
||||
return;
|
||||
}
|
||||
status = cdp_host_get_peer_stats(soc, dp_intf->intf_id,
|
||||
bss_peer->macaddr,
|
||||
peer_stats);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
qdf_mem_free(peer_stats);
|
||||
return;
|
||||
}
|
||||
/* Convert rx linkspeed from kbps to mbps to compare with threshold */
|
||||
link_speed = peer_stats->rx.last_rx_rate / 1000;
|
||||
|
||||
/*
|
||||
* When found current rx link speed becomes good(above threshold) or
|
||||
* poor, update to firmware.
|
||||
* If the current RX link speed is above the threshold, low rssi
|
||||
* roaming is not needed. If linkspeed_threshold is set to 0, the
|
||||
* firmware will not consider RX link speed in the roaming decision,
|
||||
* driver will send rx link speed poor state to firmware.
|
||||
*/
|
||||
if (!link_mon.rx_linkspeed_threshold) {
|
||||
dp_ctx->dp_ops.link_monitoring_cb(psoc, dp_intf->intf_id,
|
||||
false);
|
||||
} else if (link_speed > link_mon.rx_linkspeed_threshold &&
|
||||
!link_mon.is_rx_linkspeed_good) {
|
||||
dp_ctx->dp_ops.link_monitoring_cb(psoc, dp_intf->intf_id,
|
||||
true);
|
||||
link_mon.is_rx_linkspeed_good = true;
|
||||
} else if (link_speed < link_mon.rx_linkspeed_threshold &&
|
||||
link_mon.is_rx_linkspeed_good) {
|
||||
dp_ctx->dp_ops.link_monitoring_cb(psoc, dp_intf->intf_id,
|
||||
false);
|
||||
link_mon.is_rx_linkspeed_good = false;
|
||||
}
|
||||
|
||||
qdf_mem_free(peer_stats);
|
||||
}
|
||||
|
||||
/**
|
||||
* __dp_bus_bw_work_handler() - Bus bandwidth work handler
|
||||
* @dp_ctx: handle to DP context
|
||||
@@ -1770,10 +1862,12 @@ static void __dp_bus_bw_work_handler(struct wlan_dp_psoc_context *dp_ctx)
|
||||
dp_intf->prev_tx_bytes);
|
||||
|
||||
if (dp_intf->device_mode == QDF_STA_MODE &&
|
||||
ucfg_cm_is_vdev_active(vdev))
|
||||
ucfg_cm_is_vdev_active(vdev)) {
|
||||
dp_ctx->dp_ops.dp_send_mscs_action_frame(ctx,
|
||||
dp_intf->intf_id);
|
||||
|
||||
if (dp_intf->link_monitoring.enabled)
|
||||
dp_link_monitoring(dp_ctx, dp_intf);
|
||||
}
|
||||
if (dp_intf->device_mode == QDF_SAP_MODE ||
|
||||
dp_intf->device_mode == QDF_P2P_GO_MODE ||
|
||||
dp_intf->device_mode == QDF_NDI_MODE) {
|
||||
@@ -1821,6 +1915,7 @@ static void __dp_bus_bw_work_handler(struct wlan_dp_psoc_context *dp_ctx)
|
||||
QDF_NET_DEV_STATS_TX_BYTES(&dp_intf->stats);
|
||||
qdf_spin_unlock_bh(&dp_ctx->bus_bw_lock);
|
||||
connected = true;
|
||||
|
||||
dp_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
|
||||
}
|
||||
|
||||
|
@@ -587,6 +587,7 @@ union wlan_tp_data {
|
||||
* @os_if_dp_nud_stats_info: osif callback to print nud stats info
|
||||
* @dp_get_pause_map: Callback API to get pause map count
|
||||
* @dp_nud_failure_work: Callback API to handle NUD failuire work
|
||||
* @link_monitoring_cb: Callback API to handle link speed change
|
||||
*/
|
||||
struct wlan_dp_psoc_callbacks {
|
||||
hdd_cb_handle callback_ctx;
|
||||
@@ -666,6 +667,9 @@ struct wlan_dp_psoc_callbacks {
|
||||
void (*os_if_dp_nud_stats_info)(struct wlan_objmgr_vdev *vdev);
|
||||
uint32_t (*dp_get_pause_map)(hdd_cb_handle context, uint8_t vdev_id);
|
||||
void (*dp_nud_failure_work)(hdd_cb_handle context, uint8_t vdev_id);
|
||||
void (*link_monitoring_cb)(struct wlan_objmgr_psoc *psoc,
|
||||
uint8_t vdev_id,
|
||||
bool is_link_speed_good);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -1222,4 +1222,13 @@ void ucfg_dp_event_eapol_log(qdf_nbuf_t nbuf, enum qdf_proto_dir dir);
|
||||
QDF_STATUS
|
||||
ucfg_dp_softap_inspect_dhcp_packet(struct wlan_objmgr_vdev *vdev,
|
||||
qdf_nbuf_t nbuf, enum qdf_proto_dir dir);
|
||||
|
||||
void
|
||||
dp_ucfg_enable_link_monitoring(struct wlan_objmgr_psoc *psoc,
|
||||
struct wlan_objmgr_vdev *vdev,
|
||||
uint32_t threshold);
|
||||
|
||||
void
|
||||
dp_ucfg_disable_link_monitoring(struct wlan_objmgr_psoc *psoc,
|
||||
struct wlan_objmgr_vdev *vdev);
|
||||
#endif /* _WLAN_DP_UCFG_API_H_ */
|
||||
|
@@ -1915,6 +1915,7 @@ void ucfg_dp_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc,
|
||||
cb_obj->os_if_dp_nud_stats_info;
|
||||
dp_ctx->dp_ops.osif_dp_process_mic_error =
|
||||
cb_obj->osif_dp_process_mic_error;
|
||||
dp_ctx->dp_ops.link_monitoring_cb = cb_obj->link_monitoring_cb;
|
||||
}
|
||||
|
||||
void ucfg_dp_register_event_handler(struct wlan_objmgr_psoc *psoc,
|
||||
@@ -2153,3 +2154,34 @@ ucfg_dp_softap_inspect_dhcp_packet(struct wlan_objmgr_vdev *vdev,
|
||||
|
||||
return dp_softap_inspect_dhcp_packet(dp_intf, nbuf, dir);
|
||||
}
|
||||
|
||||
void
|
||||
dp_ucfg_enable_link_monitoring(struct wlan_objmgr_psoc *psoc,
|
||||
struct wlan_objmgr_vdev *vdev,
|
||||
uint32_t threshold)
|
||||
{
|
||||
struct wlan_dp_intf *dp_intf;
|
||||
|
||||
dp_intf = dp_get_vdev_priv_obj(vdev);
|
||||
if (unlikely(!dp_intf)) {
|
||||
dp_err("DP interface not found");
|
||||
return;
|
||||
}
|
||||
dp_intf->link_monitoring.rx_linkspeed_threshold = threshold;
|
||||
dp_intf->link_monitoring.enabled = true;
|
||||
}
|
||||
|
||||
void
|
||||
dp_ucfg_disable_link_monitoring(struct wlan_objmgr_psoc *psoc,
|
||||
struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct wlan_dp_intf *dp_intf;
|
||||
|
||||
dp_intf = dp_get_vdev_priv_obj(vdev);
|
||||
if (unlikely(!dp_intf)) {
|
||||
dp_err("DP interface not found");
|
||||
return;
|
||||
}
|
||||
dp_intf->link_monitoring.enabled = false;
|
||||
dp_intf->link_monitoring.rx_linkspeed_threshold = 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user