qcacld-3.0: Update connected VDEV channel bandwidth

Host receives QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH vendor
command indication to update STA adapter channel width.

On receiving channel width update indication from upper layer,
first host updates internally and send new channel width value
to FW via WMI_VDEV_PARAM_CHWIDTH_WITH_NOTIFY.

Target firmware should take care of notifying associated peers
(except TDLS) about change in bandwidth, through OMN/OMI
notification before performing bandwidth update internally.

Change-Id: I517ed1fbf8d074e511f8fb43c9c1dac824c9f084
CRs-Fixed: 3469473
This commit is contained in:
abhinav kumar
2023-04-10 00:21:43 +05:30
committed by Madan Koyyalamudi
parent 076551fd20
commit 80fc700acf
5 changed files with 249 additions and 0 deletions

View File

@@ -1071,6 +1071,22 @@ enum phy_ch_width wlan_mlme_convert_vht_op_bw_to_phy_ch_width(
void wlan_mlme_chan_stats_scan_event_cb(struct wlan_objmgr_vdev *vdev,
struct scan_event *event, void *arg);
/**
* wlan_mlme_send_ch_width_update_with_notify() - update connected VDEV
* channel bandwidth
* @psoc: pointer to psoc object
* @vdev: pointer to vdev object
* @vdev_id: vdev id
* @ch_width: channel width to update
*
* Return: none
*/
QDF_STATUS
wlan_mlme_send_ch_width_update_with_notify(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_vdev *vdev,
uint8_t vdev_id,
enum phy_ch_width ch_width);
#ifdef WLAN_FEATURE_11BE
/**
* mlme_update_tgt_eht_caps_in_cfg() - Update tgt eht cap in mlme component

View File

@@ -4589,6 +4589,30 @@ QDF_STATUS
ucfg_mlme_set_vdev_traffic_low_latency(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, bool set);
/**
* ucfg_mlme_send_ch_width_update_with_notify() - Send chwidth with notify
* capability of FW
* @psoc: pointer to psoc object
* @vdev_id: Vdev id
* @ch_width: channel width to update
*
* Return: QDF_STATUS
*/
QDF_STATUS
ucfg_mlme_send_ch_width_update_with_notify(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id,
enum phy_ch_width ch_width);
/**
* ucfg_mlme_is_chwidth_with_notify_supported() - Get chwidth with notify
* capability of FW
* @psoc: pointer to psoc object
*
* Return: true if chwidth with notify feature supported
*/
bool
ucfg_mlme_is_chwidth_with_notify_supported(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_mlme_connected_chan_stats_request() - process connected channel stats
* request

View File

@@ -35,6 +35,7 @@
#include "wlan_psoc_mlme_api.h"
#include "wlan_action_oui_main.h"
#include "target_if.h"
#include "wlan_vdev_mgr_tgt_if_tx_api.h"
/* quota in milliseconds */
#define MCC_DUTY_CYCLE 70
@@ -6682,6 +6683,121 @@ void wlan_mlme_chan_stats_scan_event_cb(struct wlan_objmgr_vdev *vdev,
mlme_send_scan_done_complete_cb(event->vdev_id);
}
static QDF_STATUS
wlan_mlme_update_vdev_chwidth_with_notify(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_vdev *vdev,
uint8_t vdev_id,
enum phy_ch_width ch_width)
{
struct vdev_mlme_obj *vdev_mlme;
struct vdev_set_params param = {0};
QDF_STATUS status;
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
if (!vdev_mlme)
return QDF_STATUS_E_FAILURE;
param.param_id = wmi_vdev_param_chwidth_with_notify;
param.vdev_id = vdev_id;
param.param_value = ch_width;
status = tgt_vdev_mgr_set_param_send(vdev_mlme, &param);
policy_mgr_handle_ml_sta_link_on_traffic_type_change(psoc, vdev);
return status;
}
static QDF_STATUS wlan_mlme_update_ch_width(struct wlan_objmgr_vdev *vdev,
uint8_t vdev_id,
enum phy_ch_width ch_width)
{
struct wlan_channel *des_chan;
struct wlan_channel *bss_chan;
uint16_t curr_op_freq;
struct ch_params ch_params = {0};
struct wlan_objmgr_pdev *pdev;
des_chan = wlan_vdev_mlme_get_des_chan(vdev);
if (!des_chan)
return QDF_STATUS_E_FAILURE;
bss_chan = wlan_vdev_mlme_get_bss_chan(vdev);
if (!bss_chan)
return QDF_STATUS_E_FAILURE;
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
mlme_err("vdev %d: Pdev is NULL", vdev_id);
return QDF_STATUS_E_INVAL;
}
ch_params.ch_width = ch_width;
curr_op_freq = des_chan->ch_freq;
wlan_reg_set_channel_params_for_pwrmode(pdev, curr_op_freq,
0, &ch_params,
REG_CURRENT_PWR_MODE);
des_chan->ch_width = ch_width;
des_chan->ch_freq_seg1 = ch_params.center_freq_seg0;
des_chan->ch_freq_seg2 = ch_params.center_freq_seg1;
des_chan->ch_cfreq1 = ch_params.mhz_freq_seg0;
des_chan->ch_cfreq2 = ch_params.mhz_freq_seg1;
qdf_mem_copy(bss_chan, des_chan, sizeof(struct wlan_channel));
mlme_legacy_debug("vdev id %d freq %d seg0 %d seg1 %d ch_width %d mhz seg0 %d mhz seg1 %d",
vdev_id, curr_op_freq, ch_params.center_freq_seg0,
ch_params.center_freq_seg1, ch_params.ch_width,
ch_params.mhz_freq_seg0, ch_params.mhz_freq_seg1);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
wlan_mlme_send_ch_width_update_with_notify(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_vdev *vdev,
uint8_t vdev_id,
enum phy_ch_width ch_width)
{
QDF_STATUS status;
enum phy_ch_width associated_ch_width;
struct wlan_channel *des_chan;
des_chan = wlan_vdev_mlme_get_des_chan(vdev);
if (!des_chan)
return QDF_STATUS_E_INVAL;
if (wlan_reg_is_24ghz_ch_freq(des_chan->ch_freq)) {
mlme_debug("vdev %d: CW:%d update not supported for freq:%d",
vdev_id, ch_width, des_chan->ch_freq);
return QDF_STATUS_E_NOSUPPORT;
}
associated_ch_width = wlan_cm_get_associated_ch_width(psoc, vdev_id);
if (ch_width > associated_ch_width) {
mlme_debug("vdev %d: Invalid new chwidth:%d, assoc ch_width:%d",
vdev_id, ch_width, associated_ch_width);
return QDF_STATUS_E_INVAL;
}
/* update ch width to internal host structure */
status = wlan_mlme_update_ch_width(vdev, vdev_id, ch_width);
if (QDF_IS_STATUS_ERROR(status)) {
mlme_err("vdev %d: Failed to update CW:%d to host, status:%d",
vdev_id, ch_width, status);
return status;
}
/* update ch width to fw */
status = wlan_mlme_update_vdev_chwidth_with_notify(psoc, vdev, vdev_id,
ch_width);
if (QDF_IS_STATUS_ERROR(status))
mlme_err("vdev %d: Failed to update CW:%d to fw, status:%d",
vdev_id, ch_width, status);
return status;
}
enum phy_ch_width wlan_mlme_convert_vht_op_bw_to_phy_ch_width(
uint8_t channel_width)
{

View File

@@ -373,6 +373,46 @@ void ucfg_mlme_connected_chan_stats_request(struct wlan_objmgr_psoc *psoc,
mlme_connected_chan_stats_request(psoc, vdev_id);
}
bool
ucfg_mlme_is_chwidth_with_notify_supported(struct wlan_objmgr_psoc *psoc)
{
return wlan_psoc_nif_fw_ext2_cap_get(psoc,
WLAN_VDEV_PARAM_CHWIDTH_WITH_NOTIFY_SUPPORT);
}
QDF_STATUS
ucfg_mlme_send_ch_width_update_with_notify(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id,
enum phy_ch_width ch_width)
{
struct wlan_objmgr_vdev *vdev;
QDF_STATUS status;
enum QDF_OPMODE mode;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
WLAN_MLME_OBJMGR_ID);
if (!vdev) {
mlme_legacy_err("vdev %d: vdev not found", vdev_id);
return QDF_STATUS_E_FAILURE;
}
mode = wlan_vdev_mlme_get_opmode(vdev);
if (mode != QDF_STA_MODE) {
mlme_legacy_debug("vdev %d: mode %d, CW update not supported",
vdev_id, mode);
status = QDF_STATUS_E_NOSUPPORT;
goto release;
}
status = wlan_mlme_send_ch_width_update_with_notify(psoc, vdev,
vdev_id, ch_width);
release:
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
return status;
}
QDF_STATUS
ucfg_mlme_set_vdev_traffic_low_latency(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, bool set)

View File

@@ -52,6 +52,7 @@
#include <wma_api.h>
#include "wlan_hdd_object_manager.h"
#include "wlan_dp_ucfg_api.h"
#include "wlan_cmn.h"
#ifndef WLAN_MAC_ADDR_UPDATE_DISABLE
/**
@@ -2151,6 +2152,45 @@ int hdd_set_rx_stbc(struct hdd_adapter *adapter, int value)
return ret;
}
/**
* hdd_convert_chwidth_to_phy_chwidth() - convert channel width of type enum
* eSirMacHTChannelWidth to enum phy_ch_width
* @chwidth: channel width of type enum eSirMacHTChannelWidth
*
* Return: channel width of type enum phy_ch_width
*/
static enum phy_ch_width
hdd_convert_chwidth_to_phy_chwidth(enum eSirMacHTChannelWidth chwidth)
{
enum phy_ch_width ch_width = CH_WIDTH_INVALID;
switch (chwidth) {
case eHT_CHANNEL_WIDTH_20MHZ:
ch_width = CH_WIDTH_20MHZ;
break;
case eHT_CHANNEL_WIDTH_40MHZ:
ch_width = CH_WIDTH_40MHZ;
break;
case eHT_CHANNEL_WIDTH_80MHZ:
ch_width = CH_WIDTH_80MHZ;
break;
case eHT_CHANNEL_WIDTH_160MHZ:
ch_width = CH_WIDTH_160MHZ;
break;
case eHT_CHANNEL_WIDTH_80P80MHZ:
ch_width = CH_WIDTH_80P80MHZ;
break;
case eHT_CHANNEL_WIDTH_320MHZ:
ch_width = CH_WIDTH_320MHZ;
break;
default:
hdd_debug("Invalid channel width %d", chwidth);
break;
}
return ch_width;
}
int hdd_update_channel_width(struct hdd_adapter *adapter,
enum eSirMacHTChannelWidth chwidth,
uint32_t bonding_mode)
@@ -2158,6 +2198,8 @@ int hdd_update_channel_width(struct hdd_adapter *adapter,
struct hdd_context *hdd_ctx;
struct sme_config_params *sme_config;
int ret;
enum phy_ch_width ch_width;
QDF_STATUS status;
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
if (!hdd_ctx) {
@@ -2165,6 +2207,17 @@ int hdd_update_channel_width(struct hdd_adapter *adapter,
return -EINVAL;
}
if (ucfg_mlme_is_chwidth_with_notify_supported(hdd_ctx->psoc)) {
ch_width = hdd_convert_chwidth_to_phy_chwidth(chwidth);
hdd_debug("vdev %d : process update ch width request to %d",
adapter->deflink->vdev_id, ch_width);
status =
ucfg_mlme_send_ch_width_update_with_notify(hdd_ctx->psoc,
adapter->deflink->vdev_id, ch_width);
if (QDF_IS_STATUS_ERROR(status))
return -EIO;
}
sme_config = qdf_mem_malloc(sizeof(*sme_config));
if (!sme_config)
return -ENOMEM;