qcacld-3.0: API for Clear Channel Assessment
Add a vendor command to report statistics to userspace for clear channel assessment. Change-Id: I5c8ddc14f6661d2af7e4f3a9e1c9c844fd4cd16d CRs-Fixed: 2773536
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include <osif_sync.h>
|
||||
#include <wlan_hdd_main.h>
|
||||
#include <wlan_hdd_object_manager.h>
|
||||
#include <wlan_dcs_ucfg_api.h>
|
||||
#include <wlan_cp_stats_mc_ucfg_api.h>
|
||||
#include <sme_api.h>
|
||||
#include <wma_api.h>
|
||||
@@ -57,6 +58,9 @@
|
||||
#define MEDIUM_ASSESS_MAX \
|
||||
QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MAX
|
||||
|
||||
#define DEFAULT_CCA_PERIOD 10 /* seconds */
|
||||
#define CCA_GET_RSSI_INTERVAL 1000 /* 1 second */
|
||||
|
||||
#define REPORT_DISABLE 0
|
||||
#define REPORT_ENABLE 1
|
||||
|
||||
@@ -71,7 +75,147 @@ hdd_medium_assess_policy[MEDIUM_ASSESS_MAX + 1] = {
|
||||
[CONGESTION_REPORT_INTERVAL] = {.type = NLA_U8},
|
||||
};
|
||||
|
||||
/*
|
||||
* get_cca_report_len() - Calculate length for CCA report
|
||||
* to allocate skb buffer
|
||||
*
|
||||
* Return: skb buffer length
|
||||
*/
|
||||
static int get_cca_report_len(void)
|
||||
{
|
||||
uint32_t data_len = NLMSG_HDRLEN;
|
||||
|
||||
/* QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TYPE */
|
||||
data_len += nla_total_size(sizeof(uint8_t));
|
||||
|
||||
/* QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TOTAL_CYCLE_COUNT */
|
||||
data_len += nla_total_size(sizeof(uint32_t));
|
||||
|
||||
/* QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IDLE_COUNT */
|
||||
data_len += nla_total_size(sizeof(uint32_t));
|
||||
|
||||
/* QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IBSS_RX_COUNT */
|
||||
data_len += nla_total_size(sizeof(uint32_t));
|
||||
|
||||
/* QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_OBSS_RX_COUNT */
|
||||
data_len += nla_total_size(sizeof(uint32_t));
|
||||
|
||||
/* QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MAX_IBSS_RSSI */
|
||||
data_len += nla_total_size(sizeof(uint32_t));
|
||||
|
||||
/* QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MIN_IBSS_RSSI */
|
||||
data_len += nla_total_size(sizeof(uint32_t));
|
||||
|
||||
return data_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_cca_notification_cb() - cca notification callback function
|
||||
* @vdev_id: vdev id
|
||||
* @stats: dcs im stats
|
||||
* @status: status of cca statistics
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_cca_notification_cb(uint8_t vdev_id,
|
||||
struct wlan_host_dcs_im_user_stats *stats,
|
||||
int status)
|
||||
{
|
||||
struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
|
||||
struct hdd_adapter *adapter;
|
||||
struct sk_buff *event;
|
||||
|
||||
if (wlan_hdd_validate_context(hdd_ctx))
|
||||
return;
|
||||
|
||||
adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
|
||||
if (!adapter) {
|
||||
hdd_err("Failed to find adapter of vdev %d", vdev_id);
|
||||
return;
|
||||
}
|
||||
|
||||
event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
|
||||
get_cca_report_len(),
|
||||
QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS_INDEX,
|
||||
GFP_KERNEL);
|
||||
if (!event) {
|
||||
hdd_err("cfg80211_vendor_event_alloc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nla_put_u8(event, MEDIUM_ASSESS_TYPE,
|
||||
QCA_WLAN_MEDIUM_ASSESS_CCA) ||
|
||||
nla_put_u32(event, TOTAL_CYCLE_COUNT, stats->cycle_count) ||
|
||||
nla_put_u32(event, IDLE_COUNT,
|
||||
stats->cycle_count - stats->rxclr_count) ||
|
||||
nla_put_u32(event, IBSS_RX_COUNT, stats->my_bss_rx_cycle_count) ||
|
||||
nla_put_u32(event, OBSS_RX_COUNT,
|
||||
stats->rx_frame_count - stats->my_bss_rx_cycle_count) ||
|
||||
nla_put_u32(event, MAX_IBSS_RSSI, stats->max_rssi) ||
|
||||
nla_put_u32(event, MIN_IBSS_RSSI, stats->min_rssi)) {
|
||||
hdd_err("nla put failed");
|
||||
kfree_skb(event);
|
||||
return;
|
||||
}
|
||||
|
||||
cfg80211_vendor_event(event, GFP_KERNEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_medium_assess_cca() - clear channel assessment
|
||||
* @hdd_ctx: pointer to HDD context
|
||||
* @adapter: pointer to adapter
|
||||
* @tb: list of attributes
|
||||
*
|
||||
* Return: success(0) or reason code for failure
|
||||
*/
|
||||
static int hdd_medium_assess_cca(struct hdd_context *hdd_ctx,
|
||||
struct hdd_adapter *adapter,
|
||||
struct nlattr **tb)
|
||||
{
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
uint32_t cca_period = DEFAULT_CCA_PERIOD;
|
||||
uint8_t pdev_id, dcs_enable;
|
||||
int status = 0;
|
||||
|
||||
vdev = hdd_objmgr_get_vdev(adapter);
|
||||
if (!vdev)
|
||||
return -EINVAL;
|
||||
|
||||
pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
|
||||
|
||||
dcs_enable = ucfg_get_dcs_enable(hdd_ctx->psoc, pdev_id);
|
||||
if (!(dcs_enable & CAP_DCS_WLANIM)) {
|
||||
hdd_err_rl("DCS_WLANIM is not enabled");
|
||||
status = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (qdf_atomic_read(&adapter->session.ap.acs_in_progress)) {
|
||||
hdd_err_rl("ACS is in progress");
|
||||
status = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (tb[PERIOD])
|
||||
cca_period = nla_get_u32(tb[PERIOD]);
|
||||
if (cca_period == 0)
|
||||
cca_period = DEFAULT_CCA_PERIOD;
|
||||
|
||||
ucfg_dcs_reset_user_stats(hdd_ctx->psoc, pdev_id);
|
||||
ucfg_dcs_register_user_cb(hdd_ctx->psoc, pdev_id, adapter->vdev_id,
|
||||
hdd_cca_notification_cb);
|
||||
/* dcs is already enabled and dcs event is reported every second
|
||||
* set the user request counter to collect user stats
|
||||
*/
|
||||
ucfg_dcs_set_user_request(hdd_ctx->psoc, pdev_id, cca_period);
|
||||
|
||||
out:
|
||||
hdd_objmgr_put_vdev(vdev);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_congestion_report_len() - Calculate length for congestion report
|
||||
* to allocate skb buffer
|
||||
*
|
||||
@@ -277,6 +421,7 @@ static int __hdd_cfg80211_medium_assess(struct wiphy *wiphy,
|
||||
|
||||
switch (type) {
|
||||
case QCA_WLAN_MEDIUM_ASSESS_CCA:
|
||||
status = hdd_medium_assess_cca(hdd_ctx, adapter, tb);
|
||||
break;
|
||||
case QCA_WLAN_MEDIUM_ASSESS_CONGESTION_REPORT:
|
||||
status = hdd_medium_assess_congestion_report(hdd_ctx, adapter,
|
||||
|
Reference in New Issue
Block a user