Merge "qca-wifi: Multi-Link Repeater Enhancements"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
4207ea2ebb
@@ -21,6 +21,7 @@
|
||||
#include <qdf_module.h>
|
||||
#include <qdf_list.h>
|
||||
#include <qdf_util.h>
|
||||
#include <qdf_lock.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/version.h>
|
||||
@@ -34,8 +35,7 @@
|
||||
#include "if_upperproto.h"
|
||||
|
||||
|
||||
#define QCA_MULTI_LINK_FAST_LANE_LIST_SIZE 6
|
||||
#define QCA_MULTI_LINK_NO_BACKHAUL_LIST_SIZE 32
|
||||
#define QCA_MULTI_LINK_RADIO_LIST_SIZE 6
|
||||
|
||||
/**
|
||||
* qca_multi_link_needs_enq - rptr return status
|
||||
@@ -61,15 +61,55 @@ typedef enum qca_multi_link_status {
|
||||
} qca_multi_link_status_t;
|
||||
|
||||
/**
|
||||
* struct qca_multi_link_list_node - rptr list node
|
||||
* @list: linked list node
|
||||
* @wiphy: wiphy pointer
|
||||
* struct qca_multi_link_statistics - rptr drop statistics
|
||||
*/
|
||||
struct qca_multi_link_list_node {
|
||||
typedef struct qca_multi_link_statistics {
|
||||
uint32_t ap_rx_sec_sta_null;
|
||||
uint32_t sta_rx_sec_sta_mcast_no_fdb;
|
||||
uint32_t sta_rx_sec_sta_mcast_dup_pkts;
|
||||
uint32_t sta_rx_sec_sta_mcast_drop_sec;
|
||||
uint32_t sta_rx_sec_sta_mcast_drop;
|
||||
uint32_t sta_rx_sec_sta_ucast_src_eth;
|
||||
uint32_t sta_rx_sec_sta_ucast_src_dif_band;
|
||||
uint32_t sta_rx_sec_sta_ucast_no_ap;
|
||||
uint32_t sta_rx_pri_sta_mcast_no_fdb;
|
||||
uint32_t sta_rx_pri_sta_mcast_drop;
|
||||
uint32_t sta_tx_sec_sta_alwys_prim;
|
||||
uint32_t sta_tx_sec_sta_mcast_no_fdb;
|
||||
uint32_t sta_tx_sec_sta_src_eth;
|
||||
uint32_t sta_tx_sec_sta_mcast_drop_sec;
|
||||
uint32_t sta_tx_sec_sta_drop_dif_band;
|
||||
uint32_t sta_tx_pri_sta_drop_no_fdb;
|
||||
uint32_t sta_tx_pri_sta_drop_dif_band;
|
||||
} qca_ml_global_stats_t;
|
||||
|
||||
/**
|
||||
* struct qca_multi_link_radio_list_node - rptr list node
|
||||
* @node: linked list node
|
||||
* @wiphy: wiphy pointer
|
||||
* @no_backhaul: is no_backhaul radio
|
||||
* @is_fast_lane: is fast_lane radio
|
||||
* @sta_dev: radio's station net device
|
||||
*/
|
||||
typedef struct qca_multi_link_radio_list_node {
|
||||
qdf_list_node_t node;
|
||||
struct wiphy *wiphy;
|
||||
};
|
||||
bool no_backhaul;
|
||||
bool is_fast_lane;
|
||||
struct net_device *sta_dev;
|
||||
} qca_multi_link_radio_node_t;
|
||||
|
||||
/**
|
||||
* struct qca_multi_link_parameters - rptr list node
|
||||
* @rptr_processing_enable: repeater is enabled
|
||||
* @loop_detected: is loop detected
|
||||
* @always_primary: is always primary flag enabled
|
||||
* @force_client_mcast_traffic: is force client mcast flag enabled
|
||||
* @drop_secondary_mcast: is drop secondary mcast flag enabled
|
||||
* @primary_wiphy: primary radio pointer
|
||||
* @total_stavaps_up: total number of backhauls
|
||||
* @radio_list: list of radio participating in repeater
|
||||
*/
|
||||
typedef struct qca_multi_link_parameters {
|
||||
bool rptr_processing_enable;
|
||||
bool loop_detected;
|
||||
@@ -78,12 +118,13 @@ typedef struct qca_multi_link_parameters {
|
||||
bool drop_secondary_mcast;
|
||||
struct wiphy *primary_wiphy;
|
||||
uint8_t total_stavaps_up;
|
||||
qdf_list_t no_backhaul_list;
|
||||
qdf_list_t fast_lane_list;
|
||||
qdf_list_t radio_list;
|
||||
qdf_spinlock_t radio_lock;
|
||||
qca_ml_global_stats_t qca_ml_stats;
|
||||
} qca_multi_link_parameters_t;
|
||||
|
||||
void qca_multi_link_init_module(void);
|
||||
void qca_multi_link_deinit_module(void);
|
||||
void qca_multi_link_init_module(void);
|
||||
uint8_t qca_multi_link_get_num_sta(void);
|
||||
void qca_multi_link_append_num_sta(bool inc_or_dec);
|
||||
bool qca_multi_link_is_dbdc_processing_reqd(struct net_device *net_dev);
|
||||
@@ -93,10 +134,15 @@ void qca_multi_link_set_always_primary(bool val);
|
||||
void qca_multi_link_set_dbdc_enable(bool val);
|
||||
struct wiphy *qca_multi_link_get_primary_radio(void);
|
||||
void qca_multi_link_set_primary_radio(struct wiphy *primary_wiphy);
|
||||
bool qca_multi_link_add_fastlane_radio(struct wiphy *fl_wiphy);
|
||||
bool qca_multi_link_remove_radio(struct wiphy *wiphy);
|
||||
bool qca_multi_link_add_radio(struct wiphy *wiphy);
|
||||
bool qca_multi_link_remove_fastlane_radio(struct wiphy *fl_wiphy);
|
||||
bool qca_multi_link_add_no_backhaul_radio(struct wiphy *no_bl_wiphy);
|
||||
bool qca_multi_link_add_fastlane_radio(struct wiphy *fl_wiphy);
|
||||
bool qca_multi_link_remove_no_backhaul_radio(struct wiphy *no_bl_wiphy);
|
||||
bool qca_multi_link_add_no_backhaul_radio(struct wiphy *no_bl_wiphy);
|
||||
bool qca_multi_link_remove_station_vap(struct wiphy *wiphy);
|
||||
bool qca_multi_link_add_station_vap(struct wiphy *wiphy,
|
||||
struct net_device *sta_dev);
|
||||
bool qca_multi_link_ap_rx(struct net_device *net_dev, qdf_nbuf_t nbuf);
|
||||
bool qca_multi_link_sta_rx(struct net_device *net_dev, qdf_nbuf_t nbuf);
|
||||
bool qca_multi_link_sta_tx(struct net_device *net_dev, qdf_nbuf_t nbuf);
|
||||
|
@@ -19,66 +19,69 @@
|
||||
static bool is_initialized;
|
||||
qca_multi_link_parameters_t qca_multi_link_cfg;
|
||||
|
||||
static inline bool is_fast_lane_radio(struct wiphy *fl_wiphy)
|
||||
static inline qca_multi_link_radio_node_t *
|
||||
qca_multi_link_find_radio_node(struct wiphy *wiphy)
|
||||
{
|
||||
qdf_list_node_t *node = NULL, *next_node = NULL;
|
||||
|
||||
if (!fl_wiphy) {
|
||||
return false;
|
||||
if (!wiphy) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
|
||||
FL(" Radio wiphy pointer is NULL\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (qdf_list_empty(&qca_multi_link_cfg.fast_lane_list)) {
|
||||
return false;
|
||||
if (qdf_list_empty(&qca_multi_link_cfg.radio_list)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL(" Radio list is empty\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qdf_list_peek_front(&qca_multi_link_cfg.fast_lane_list,
|
||||
qdf_list_peek_front(&qca_multi_link_cfg.radio_list,
|
||||
(qdf_list_node_t **)&next_node);
|
||||
while (next_node) {
|
||||
struct qca_multi_link_list_node *fast_lane_node
|
||||
= (struct qca_multi_link_list_node *)next_node;
|
||||
if (fast_lane_node->wiphy == fl_wiphy) {
|
||||
return true;
|
||||
qca_multi_link_radio_node_t *radio_node
|
||||
= (qca_multi_link_radio_node_t *)next_node;
|
||||
if (radio_node->wiphy == wiphy) {
|
||||
return radio_node;
|
||||
} else {
|
||||
node = next_node;
|
||||
next_node = NULL;
|
||||
if ((qdf_list_peek_next(&qca_multi_link_cfg.fast_lane_list, node, &next_node))
|
||||
if ((qdf_list_peek_next(&qca_multi_link_cfg.radio_list,
|
||||
node, (qdf_list_node_t **)&next_node))
|
||||
!= QDF_STATUS_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool is_fast_lane_radio(struct wiphy *fl_wiphy)
|
||||
{
|
||||
qca_multi_link_radio_node_t *radio_node = NULL;
|
||||
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node = qca_multi_link_find_radio_node(fl_wiphy);
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
if (!radio_node) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
return radio_node->is_fast_lane;
|
||||
}
|
||||
|
||||
static inline bool is_no_backhaul_radio(struct wiphy *no_bl_wiphy)
|
||||
{
|
||||
qdf_list_node_t *node = NULL, *next_node = NULL;
|
||||
qca_multi_link_radio_node_t *radio_node = NULL;
|
||||
|
||||
if (!no_bl_wiphy) {
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node = qca_multi_link_find_radio_node(no_bl_wiphy);
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
if (!radio_node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (qdf_list_empty(&qca_multi_link_cfg.no_backhaul_list)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_list_peek_front(&qca_multi_link_cfg.no_backhaul_list,
|
||||
(qdf_list_node_t **)&next_node);
|
||||
while (next_node) {
|
||||
struct qca_multi_link_list_node *no_bl_node
|
||||
= (struct qca_multi_link_list_node *)next_node;
|
||||
if (no_bl_node->wiphy == no_bl_wiphy) {
|
||||
return true;
|
||||
} else {
|
||||
node = next_node;
|
||||
next_node = NULL;
|
||||
if ((qdf_list_peek_next(&qca_multi_link_cfg.no_backhaul_list, node, &next_node))
|
||||
!= QDF_STATUS_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return radio_node->no_backhaul;
|
||||
}
|
||||
|
||||
static inline bool is_other_fast_lane_radio_primary(struct wiphy *fl_wiphy)
|
||||
@@ -89,20 +92,24 @@ static inline bool is_other_fast_lane_radio_primary(struct wiphy *fl_wiphy)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (qdf_list_empty(&qca_multi_link_cfg.fast_lane_list)) {
|
||||
if (qdf_list_empty(&qca_multi_link_cfg.radio_list)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_list_peek_front(&qca_multi_link_cfg.fast_lane_list,
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
qdf_list_peek_front(&qca_multi_link_cfg.radio_list,
|
||||
(qdf_list_node_t **)&next_node);
|
||||
while (next_node) {
|
||||
struct qca_multi_link_list_node *fast_lane_node
|
||||
= (struct qca_multi_link_list_node *)next_node;
|
||||
if ((fast_lane_node->wiphy != fl_wiphy)
|
||||
&& (fast_lane_node->wiphy == qca_multi_link_cfg.primary_wiphy)) {
|
||||
qca_multi_link_radio_node_t *radio_node
|
||||
= (qca_multi_link_radio_node_t *)next_node;
|
||||
if ((radio_node->wiphy != fl_wiphy) &&
|
||||
(radio_node->is_fast_lane) &&
|
||||
(radio_node->wiphy == qca_multi_link_cfg.primary_wiphy)) {
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -202,6 +209,26 @@ static inline bool qca_multi_link_drop_always_primary(bool is_primary, qdf_nbuf_
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* qca_multi_link_get_station_vap() - get the radio station vap pointer for a radio
|
||||
* @primary_wiphy: wiphy pointer of radio device
|
||||
*
|
||||
* Return: station vap netdevice pointer
|
||||
*/
|
||||
static struct net_device *qca_multi_link_get_station_vap(struct wiphy *wiphy)
|
||||
{
|
||||
qca_multi_link_radio_node_t *radio_node = NULL;
|
||||
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node = qca_multi_link_find_radio_node(wiphy);
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
if (!radio_node || !radio_node->sta_dev) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return radio_node->sta_dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* qca_multi_link_deinit_module() - De-initialize the repeater base structute
|
||||
* Return: void
|
||||
@@ -214,9 +241,9 @@ void qca_multi_link_deinit_module(void)
|
||||
qca_multi_link_cfg.total_stavaps_up = 0;
|
||||
qca_multi_link_cfg.loop_detected = 0;
|
||||
qca_multi_link_cfg.primary_wiphy = NULL;
|
||||
qdf_list_destroy(&qca_multi_link_cfg.fast_lane_list);
|
||||
qdf_list_destroy(&qca_multi_link_cfg.no_backhaul_list);
|
||||
qdf_list_destroy(&qca_multi_link_cfg.radio_list);
|
||||
is_initialized = false;
|
||||
qdf_spinlock_destroy(&qca_multi_link_cfg.radio_lock);
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_INFO,
|
||||
FL("\n******QCA RPtr De-Init Done***********\n"));
|
||||
@@ -238,9 +265,10 @@ void qca_multi_link_init_module(void)
|
||||
qca_multi_link_cfg.total_stavaps_up = 0;
|
||||
qca_multi_link_cfg.loop_detected = 0;
|
||||
qca_multi_link_cfg.primary_wiphy = NULL;
|
||||
qdf_list_create(&qca_multi_link_cfg.fast_lane_list, QCA_MULTI_LINK_FAST_LANE_LIST_SIZE);
|
||||
qdf_list_create(&qca_multi_link_cfg.no_backhaul_list, QCA_MULTI_LINK_NO_BACKHAUL_LIST_SIZE);
|
||||
qdf_list_create(&qca_multi_link_cfg.radio_list, QCA_MULTI_LINK_RADIO_LIST_SIZE);
|
||||
qdf_spinlock_create(&qca_multi_link_cfg.radio_lock);
|
||||
|
||||
memset(&qca_multi_link_cfg.qca_ml_stats, 0x0, sizeof(qca_multi_link_radio_node_t));
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_INFO,
|
||||
FL("\n******QCA Repeater Initialization Done***********\n"));
|
||||
}
|
||||
@@ -299,7 +327,8 @@ qdf_export_symbol(qca_multi_link_append_num_sta);
|
||||
bool qca_multi_link_is_dbdc_processing_reqd(struct net_device *net_dev)
|
||||
{
|
||||
if (qca_multi_link_cfg.total_stavaps_up > 2)
|
||||
return (qca_multi_link_cfg.loop_detected && qca_multi_link_cfg.rptr_processing_enable);
|
||||
return (qca_multi_link_cfg.loop_detected &&
|
||||
qca_multi_link_cfg.rptr_processing_enable);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -382,11 +411,89 @@ void qca_multi_link_set_primary_radio(struct wiphy *primary_wiphy)
|
||||
}
|
||||
qca_multi_link_cfg.primary_wiphy = primary_wiphy;
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_INFO,
|
||||
FL("\nSetting primary radio for wiphy%p\n"), primary_wiphy);
|
||||
FL("\n******Setting primary radio for wiphy****%p\n"), primary_wiphy);
|
||||
}
|
||||
|
||||
qdf_export_symbol(qca_multi_link_set_primary_radio);
|
||||
|
||||
/**
|
||||
* qca_multi_link_remove_radio() - remove the radio pointer from repeater list
|
||||
* @primary_wiphy: wiphy pointer of radio device
|
||||
*
|
||||
* Return: false: addition not successful
|
||||
* true: addition is successful
|
||||
*/
|
||||
bool qca_multi_link_remove_radio(struct wiphy *wiphy)
|
||||
{
|
||||
qca_multi_link_radio_node_t *radio_node = NULL;
|
||||
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node = qca_multi_link_find_radio_node(wiphy);
|
||||
if (!radio_node) {
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_list_remove_node(&qca_multi_link_cfg.radio_list, &radio_node->node);
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
qdf_mem_free(radio_node);
|
||||
return true;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qca_multi_link_remove_radio);
|
||||
|
||||
/**
|
||||
* qca_multi_link_add_radio() - add the radio pointer to repeater list
|
||||
* @primary_wiphy: wiphy pointer of radio device
|
||||
*
|
||||
* Return: false: addition not successful
|
||||
* true: addition is successful
|
||||
*/
|
||||
bool qca_multi_link_add_radio(struct wiphy *wiphy)
|
||||
{
|
||||
qca_multi_link_radio_node_t *radio_node = NULL;
|
||||
|
||||
if (!wiphy) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
|
||||
FL(" Radio could not be set - wiphy is NULL\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if Radio is already present in reppeater list.
|
||||
*/
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node = qca_multi_link_find_radio_node(wiphy);
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
if (radio_node) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
|
||||
FL(" Radio node already present\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
radio_node = qdf_mem_malloc(sizeof(qca_multi_link_radio_node_t));
|
||||
if (!radio_node) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("Could not allocate node for wiphy%p\n"), wiphy);
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node->wiphy = wiphy;
|
||||
if (qdf_list_insert_front(&qca_multi_link_cfg.radio_list, &radio_node->node)
|
||||
== QDF_STATUS_SUCCESS) {
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("Adding radio node for wiphy%p\n"), wiphy);
|
||||
return true;
|
||||
}
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
qdf_mem_free(radio_node);
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qca_multi_link_add_radio);
|
||||
|
||||
/**
|
||||
* qca_multi_link_add_fastlane_radio() - add the fast lane radio pointer to list
|
||||
* @primary_wiphy: wiphy pointer of fast-lane radio device
|
||||
@@ -396,28 +503,19 @@ qdf_export_symbol(qca_multi_link_set_primary_radio);
|
||||
*/
|
||||
bool qca_multi_link_add_fastlane_radio(struct wiphy *fl_wiphy)
|
||||
{
|
||||
struct qca_multi_link_list_node *fast_lane_node;
|
||||
qca_multi_link_radio_node_t *radio_node = NULL;
|
||||
|
||||
if (!fl_wiphy) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
|
||||
FL(" Fast lane radio could not be set - wiphy is NULL\n"));
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node = qca_multi_link_find_radio_node(fl_wiphy);
|
||||
if (!radio_node) {
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
fast_lane_node = qdf_mem_malloc(sizeof(struct qca_multi_link_list_node));
|
||||
if (!fast_lane_node) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("Could not allocate fast-lane node for wiphy%p\n"), fl_wiphy);
|
||||
return false;
|
||||
}
|
||||
|
||||
fast_lane_node->wiphy = fl_wiphy;
|
||||
if (qdf_list_insert_front(&qca_multi_link_cfg.fast_lane_list, &fast_lane_node->node)
|
||||
== QDF_STATUS_SUCCESS) {
|
||||
radio_node->is_fast_lane = true;
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qca_multi_link_add_fastlane_radio);
|
||||
|
||||
@@ -430,33 +528,18 @@ qdf_export_symbol(qca_multi_link_add_fastlane_radio);
|
||||
*/
|
||||
bool qca_multi_link_remove_fastlane_radio(struct wiphy *fl_wiphy)
|
||||
{
|
||||
qdf_list_node_t *node = NULL, *next_node = NULL;
|
||||
qca_multi_link_radio_node_t *radio_node = NULL;
|
||||
|
||||
if (!fl_wiphy) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
|
||||
FL(" Fast lane radio could not be removed - wiphy is NULL\n"));
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node = qca_multi_link_find_radio_node(fl_wiphy);
|
||||
if (!radio_node) {
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_list_peek_front(&qca_multi_link_cfg.fast_lane_list,
|
||||
(qdf_list_node_t **)&next_node);
|
||||
while (next_node) {
|
||||
struct qca_multi_link_list_node *fast_lane_node
|
||||
= (struct qca_multi_link_list_node *)next_node;
|
||||
if (fast_lane_node->wiphy == fl_wiphy) {
|
||||
qdf_list_remove_node(&qca_multi_link_cfg.fast_lane_list, next_node);
|
||||
qdf_mem_free(fast_lane_node);
|
||||
radio_node->is_fast_lane = false;
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return true;
|
||||
} else {
|
||||
node = next_node;
|
||||
next_node = NULL;
|
||||
if ((qdf_list_peek_next(&qca_multi_link_cfg.fast_lane_list, node,
|
||||
(qdf_list_node_t **)&next_node)) != QDF_STATUS_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qca_multi_link_remove_fastlane_radio);
|
||||
@@ -470,28 +553,19 @@ qdf_export_symbol(qca_multi_link_remove_fastlane_radio);
|
||||
*/
|
||||
bool qca_multi_link_add_no_backhaul_radio(struct wiphy *no_bl_wiphy)
|
||||
{
|
||||
struct qca_multi_link_list_node *no_bl_node;
|
||||
qca_multi_link_radio_node_t *radio_node = NULL;
|
||||
|
||||
if (!no_bl_wiphy) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
|
||||
FL(" No backhaul radio could not be set - wiphy is NULL\n"));
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node = qca_multi_link_find_radio_node(no_bl_wiphy);
|
||||
if (!radio_node) {
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
no_bl_node = qdf_mem_malloc(sizeof(struct qca_multi_link_list_node));
|
||||
if (!no_bl_node) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("Could not allocate back-haul node for wiphy%p\n"), no_bl_node);
|
||||
return false;
|
||||
}
|
||||
|
||||
no_bl_node->wiphy = no_bl_wiphy;
|
||||
if (qdf_list_insert_front(&qca_multi_link_cfg.no_backhaul_list, &no_bl_node->node)
|
||||
== QDF_STATUS_SUCCESS) {
|
||||
radio_node->no_backhaul = true;
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qca_multi_link_add_no_backhaul_radio);
|
||||
|
||||
@@ -504,37 +578,81 @@ qdf_export_symbol(qca_multi_link_add_no_backhaul_radio);
|
||||
*/
|
||||
bool qca_multi_link_remove_no_backhaul_radio(struct wiphy *no_bl_wiphy)
|
||||
{
|
||||
qdf_list_node_t *node = NULL, *next_node = NULL;
|
||||
qca_multi_link_radio_node_t *radio_node = NULL;
|
||||
|
||||
if (!no_bl_wiphy) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
|
||||
FL(" No backhaul radio could not be removed - wiphy is NULL\n"));
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node = qca_multi_link_find_radio_node(no_bl_wiphy);
|
||||
if (!radio_node) {
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_list_peek_front(&qca_multi_link_cfg.no_backhaul_list,
|
||||
(qdf_list_node_t **)&next_node);
|
||||
while (next_node) {
|
||||
struct qca_multi_link_list_node *no_bl_node
|
||||
= (struct qca_multi_link_list_node *)next_node;
|
||||
if (no_bl_node->wiphy == no_bl_wiphy) {
|
||||
qdf_list_remove_node(&qca_multi_link_cfg.no_backhaul_list, next_node);
|
||||
qdf_mem_free(no_bl_node);
|
||||
radio_node->no_backhaul = false;
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return true;
|
||||
} else {
|
||||
node = next_node;
|
||||
next_node = NULL;
|
||||
if ((qdf_list_peek_next(&qca_multi_link_cfg.no_backhaul_list, node, &next_node))
|
||||
!= QDF_STATUS_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qca_multi_link_remove_no_backhaul_radio);
|
||||
|
||||
/**
|
||||
* qca_multi_link_remove_station_vap() - remove the radio station vap pointer for a radio
|
||||
* @primary_wiphy: wiphy pointer of radio device
|
||||
*
|
||||
* Return: false: addition not successful
|
||||
* true: addition is successful
|
||||
*/
|
||||
bool qca_multi_link_remove_station_vap(struct wiphy *wiphy)
|
||||
{
|
||||
qca_multi_link_radio_node_t *radio_node = NULL;
|
||||
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node = qca_multi_link_find_radio_node(wiphy);
|
||||
if (!radio_node) {
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
radio_node->sta_dev = NULL;
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qca_multi_link_remove_station_vap);
|
||||
|
||||
/**
|
||||
* qca_multi_link_add_station_vap() - add the station vap pointer for a radio
|
||||
* @primary_wiphy: wiphy pointer of radio device
|
||||
*
|
||||
* Return: false: addition not successful
|
||||
* true: addition is successful
|
||||
*/
|
||||
bool qca_multi_link_add_station_vap(struct wiphy *wiphy, struct net_device *sta_dev)
|
||||
{
|
||||
qca_multi_link_radio_node_t *radio_node = NULL;
|
||||
|
||||
qdf_spin_lock(&qca_multi_link_cfg.radio_lock);
|
||||
radio_node = qca_multi_link_find_radio_node(wiphy);
|
||||
if (!radio_node) {
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (radio_node->sta_dev) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
|
||||
FL("STA Device already mapped for wiphy%p\n"), wiphy);
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
radio_node->sta_dev = sta_dev;
|
||||
qdf_spin_unlock(&qca_multi_link_cfg.radio_lock);
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("STA Device mapped for wiphy%p\n"), wiphy);
|
||||
return true;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qca_multi_link_add_station_vap);
|
||||
|
||||
/**
|
||||
* qca_multi_link_secondary_ap_rx() - Processing for frames recieved on Secondary AP VAP
|
||||
* @net_device: net device handle
|
||||
@@ -599,13 +717,16 @@ static qca_multi_link_status_t qca_multi_link_secondary_ap_rx(struct net_device
|
||||
/*
|
||||
* Find the station vap corresponding to the AP vap.
|
||||
*/
|
||||
sta_dev = qca_multi_link_tbl_find_sta_or_ap(ap_dev, 1);
|
||||
sta_dev = qca_multi_link_get_station_vap(ap_wiphy);
|
||||
if (!sta_dev) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("Null STA device found %pM - Give to bridge\n"), eh->ether_shost);
|
||||
qca_multi_link_cfg.qca_ml_stats.ap_rx_sec_sta_null++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
qca_multi_link_tbl_add_or_refresh_entry(ap_dev, eh->ether_shost,
|
||||
QCA_MULTI_LINK_ENTRY_USER_ADDED);
|
||||
dev_hold(sta_dev);
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("shost %pM dhost %pM \n"), eh->ether_shost, eh->ether_dhost);
|
||||
@@ -728,6 +849,7 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_rx(struct net_device
|
||||
* Always drop mcast packets on secondary radio when loop has been detected.
|
||||
*/
|
||||
if (qca_multi_link_cfg.loop_detected) {
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_sec_sta_mcast_drop++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -746,6 +868,7 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_rx(struct net_device
|
||||
*/
|
||||
return QCA_MULTI_LINK_PKT_ALLOW;
|
||||
} else {
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_sec_sta_mcast_no_fdb++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
}
|
||||
@@ -769,10 +892,12 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_rx(struct net_device
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_INFO, FL("\n****Wifi Rptr Loop Detected****\n"));
|
||||
}
|
||||
}
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_sec_sta_mcast_dup_pkts++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
if (qca_multi_link_drop_secondary_mcast(nbuf)) {
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_sec_sta_mcast_drop_sec++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -787,6 +912,7 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_rx(struct net_device
|
||||
return QCA_MULTI_LINK_PKT_ALLOW;
|
||||
}
|
||||
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_sec_sta_mcast_drop++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -807,6 +933,7 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_rx(struct net_device
|
||||
* on secondary stations.
|
||||
*/
|
||||
if (!qca_ml_entry.qal_fdb_ieee80211_ptr) {
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_sec_sta_ucast_src_eth++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -828,6 +955,7 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_rx(struct net_device
|
||||
return QCA_MULTI_LINK_PKT_CONSUMED;
|
||||
}
|
||||
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_sec_sta_ucast_src_dif_band++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
} else {
|
||||
|
||||
@@ -843,7 +971,8 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_rx(struct net_device
|
||||
ap_dev = qca_multi_link_tbl_find_sta_or_ap(sta_dev, 0);
|
||||
if (!ap_dev) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
|
||||
FL("Null AP device found %pM - Give to bridge\n"), eh->ether_shost);
|
||||
FL("Null AP device found %pM - Drop\n"), eh->ether_shost);
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_sec_sta_ucast_no_ap++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -913,6 +1042,7 @@ static qca_multi_link_status_t qca_multi_link_primary_sta_rx(struct net_device *
|
||||
*/
|
||||
return QCA_MULTI_LINK_PKT_ALLOW;
|
||||
}
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_pri_sta_mcast_no_fdb++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -931,13 +1061,15 @@ static qca_multi_link_status_t qca_multi_link_primary_sta_rx(struct net_device *
|
||||
* Drop the loopback mcast packets from ethernet devices behind the repeater.
|
||||
*/
|
||||
if (!qca_ml_entry.qal_fdb_ieee80211_ptr) {
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_pri_sta_mcast_drop++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
if (qca_ml_entry.qal_fdb_ieee80211_ptr->wiphy != sta_wiphy) {
|
||||
if (qca_ml_entry.qal_fdb_is_local &&
|
||||
(qca_ml_entry.qal_fdb_ieee80211_ptr->iftype
|
||||
== NL80211_IFTYPE_STATION)) {
|
||||
if (!qca_multi_link_cfg.loop_detected) {
|
||||
if (qca_ml_entry.qal_fdb_is_local
|
||||
&& (qca_ml_entry.qal_fdb_ieee80211_ptr->iftype == NL80211_IFTYPE_STATION)) {
|
||||
qca_multi_link_cfg.loop_detected = true;
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_INFO,
|
||||
FL("\n****Wifi Rptr Loop Detected****\n"));
|
||||
@@ -954,6 +1086,7 @@ static qca_multi_link_status_t qca_multi_link_primary_sta_rx(struct net_device *
|
||||
return QCA_MULTI_LINK_PKT_ALLOW;
|
||||
}
|
||||
}
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_pri_sta_mcast_drop++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -966,6 +1099,7 @@ static qca_multi_link_status_t qca_multi_link_primary_sta_rx(struct net_device *
|
||||
return QCA_MULTI_LINK_PKT_ALLOW;
|
||||
}
|
||||
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_rx_pri_sta_mcast_drop++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -1052,6 +1186,7 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_tx(struct net_device
|
||||
qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
|
||||
|
||||
if (qca_multi_link_drop_always_primary(false, nbuf)) {
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_tx_sec_sta_alwys_prim++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -1075,6 +1210,7 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_tx(struct net_device
|
||||
if (!is_mcast) {
|
||||
return QCA_MULTI_LINK_PKT_ALLOW;
|
||||
}
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_tx_sec_sta_mcast_no_fdb++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -1083,6 +1219,7 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_tx(struct net_device
|
||||
* ieee80211_ptr pointer will be NULL for ethernet devices.
|
||||
* Packets from ethernet devices or bridge are allowed only on Primary radio.
|
||||
*/
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_tx_sec_sta_src_eth++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -1095,6 +1232,7 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_tx(struct net_device
|
||||
}
|
||||
|
||||
if (qca_multi_link_drop_secondary_mcast(nbuf)) {
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_tx_sec_sta_mcast_drop_sec++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -1105,6 +1243,7 @@ static qca_multi_link_status_t qca_multi_link_secondary_sta_tx(struct net_device
|
||||
if (qca_ml_entry.qal_fdb_ieee80211_ptr->wiphy != sta_dev->ieee80211_ptr->wiphy) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG, FL("STA TX: Diff Band Primary drop\
|
||||
shost %pM dhost %pM \n"), eh->ether_shost, eh->ether_dhost);
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_tx_sec_sta_drop_dif_band++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -1152,6 +1291,7 @@ static qca_multi_link_status_t qca_multi_link_primary_sta_tx(struct net_device *
|
||||
* as they will be received from bridge only.
|
||||
*/
|
||||
if (qal_status != QDF_STATUS_SUCCESS) {
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_tx_pri_sta_drop_no_fdb++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -1186,6 +1326,7 @@ static qca_multi_link_status_t qca_multi_link_primary_sta_tx(struct net_device *
|
||||
if (qca_ml_entry.qal_fdb_ieee80211_ptr->wiphy != sta_dev->ieee80211_ptr->wiphy) {
|
||||
QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG, FL("STA TX: Diff Band Primary drop\
|
||||
shost %pM dhost %pM \n"), eh->ether_shost, eh->ether_dhost);
|
||||
qca_multi_link_cfg.qca_ml_stats.sta_tx_pri_sta_drop_dif_band++;
|
||||
return QCA_MULTI_LINK_PKT_DROP;
|
||||
}
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "qca_multi_link_tbl.h"
|
||||
#include "qca_multi_link.h"
|
||||
#include "qdf_module.h"
|
||||
#include "qdf_trace.h"
|
||||
|
||||
@@ -179,6 +180,10 @@ QDF_STATUS qca_multi_link_tbl_delete_entry(struct net_device *net_dev, uint8_t *
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!qca_multi_link_is_dbdc_processing_reqd(net_dev)) {
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 24)
|
||||
fdb_port = br_port_get_rcu(net_dev);
|
||||
if (!fdb_port) {
|
||||
|
Reference in New Issue
Block a user