qcacld-3.0: Add support for pdev ops

Send Radio HWCAP, ESP INFO, OP channels and OP class info
to EasyMesh stack.

Change-Id: I8995c6a087d12cd4cf7933f75aef5090c59ca56a
CRs-Fixed: 3078072
This commit is contained in:
Rachit Kankane
2021-07-09 17:50:54 +05:30
committed by Madan Koyyalamudi
parent eb353fd028
commit 9acfc6b4d4
2 changed files with 280 additions and 9 deletions

View File

@@ -32,6 +32,8 @@
#include <wlan_reg_ucfg_api.h>
#include <ieee80211_external.h>
#define INVALID_WIDTH 0xFF
/**
* struct son_callbacks - struct containing callback to non-converged driver
* @os_if_is_acs_in_progress: whether acs is in progress or not

View File

@@ -776,15 +776,6 @@ enum ieee80211_phymode os_if_son_get_phymode(struct wlan_objmgr_vdev *vdev)
}
qdf_export_symbol(os_if_son_get_phymode);
QDF_STATUS os_if_son_pdev_ops(struct wlan_objmgr_pdev *pdev,
enum wlan_mlme_pdev_param type,
void *data, void *ret)
{
return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(os_if_son_pdev_ops);
QDF_STATUS os_if_son_vdev_ops(struct wlan_objmgr_vdev *vdev,
enum wlan_mlme_vdev_param type,
void *data, void *ret)
@@ -939,3 +930,281 @@ void os_if_son_modify_acl(struct wlan_objmgr_vdev *vdev,
}
qdf_export_symbol(os_if_son_modify_acl);
static
int os_if_son_reg_get_ap_hw_cap(struct wlan_objmgr_pdev *pdev,
struct wlan_radio_basic_capabilities *hwcap)
{
QDF_STATUS status;
uint8_t idx;
uint8_t max_supp_op_class = REG_MAX_SUPP_OPER_CLASSES;
uint8_t n_opclasses = 0;
/* nsoc = Number of supported operating classes */
uint8_t nsoc = 0;
struct regdmn_ap_cap_opclass_t *reg_ap_cap;
if (!pdev || !hwcap)
return nsoc;
reg_ap_cap = qdf_mem_malloc(max_supp_op_class * sizeof(*reg_ap_cap));
if (!reg_ap_cap) {
osif_err("Memory allocation failure");
return nsoc;
}
status = wlan_reg_get_opclass_details(pdev, reg_ap_cap, &n_opclasses,
max_supp_op_class, true);
if (status == QDF_STATUS_E_FAILURE) {
osif_err("Failed to get SAP regulatory capabilities");
goto end_reg_get_ap_hw_cap;
}
osif_debug("n_opclasses: %u", n_opclasses);
for (idx = 0; reg_ap_cap[idx].op_class && idx < n_opclasses; idx++) {
osif_debug("idx: %d op_class: %u ch_width: %d max_tx_pwr_dbm: %u",
idx, reg_ap_cap[idx].op_class,
reg_ap_cap[idx].ch_width,
reg_ap_cap[idx].max_tx_pwr_dbm);
if (reg_ap_cap[idx].ch_width == BW_160_MHZ)
continue;
hwcap->opclasses[nsoc].opclass = reg_ap_cap[idx].op_class;
hwcap->opclasses[nsoc].max_tx_pwr_dbm =
reg_ap_cap[idx].max_tx_pwr_dbm;
hwcap->opclasses[nsoc].num_non_oper_chan =
reg_ap_cap[idx].num_non_supported_chan;
qdf_mem_copy(hwcap->opclasses[nsoc].non_oper_chan_num,
reg_ap_cap[idx].non_sup_chan_list,
reg_ap_cap[idx].num_non_supported_chan);
hwcap->wlan_radio_basic_capabilities_valid = 1;
nsoc++;
}
hwcap->num_supp_op_classes = nsoc;
end_reg_get_ap_hw_cap:
qdf_mem_free(reg_ap_cap);
return nsoc;
}
static void os_if_son_reg_get_op_channels(struct wlan_objmgr_pdev *pdev,
struct wlan_op_chan *op_chan,
bool dfs_required)
{
QDF_STATUS status;
uint8_t idx;
uint8_t max_supp_op_class = REG_MAX_SUPP_OPER_CLASSES;
uint8_t n_opclasses = 0;
/* nsoc = Number of supported operating classes */
uint8_t nsoc = 0;
struct regdmn_ap_cap_opclass_t *reg_ap_cap =
qdf_mem_malloc(max_supp_op_class * sizeof(*reg_ap_cap));
if (!reg_ap_cap) {
osif_err("Memory allocation failure");
return;
}
status = wlan_reg_get_opclass_details(pdev, reg_ap_cap, &n_opclasses,
max_supp_op_class, true);
if (status == QDF_STATUS_E_FAILURE) {
osif_err("Failed to get SAP regulatory capabilities");
goto end_reg_get_op_channels;
}
osif_debug("n_opclasses: %u op_chan->opclass: %u",
n_opclasses, op_chan->opclass);
for (idx = 0; reg_ap_cap[idx].op_class && idx < n_opclasses; idx++) {
osif_debug("idx: %d op_class: %u ch_width: %d max_tx_pwr_dbm: %u",
idx, reg_ap_cap[idx].op_class,
reg_ap_cap[idx].ch_width,
reg_ap_cap[idx].max_tx_pwr_dbm);
if ((reg_ap_cap[idx].ch_width == BW_160_MHZ) ||
(op_chan->opclass != reg_ap_cap[idx].op_class))
continue;
if (reg_ap_cap[idx].op_class == op_chan->opclass) {
switch (reg_ap_cap[idx].ch_width) {
case BW_20_MHZ:
case BW_25_MHZ:
op_chan->ch_width = CH_WIDTH_20MHZ;
break;
case BW_40_MHZ:
op_chan->ch_width = CH_WIDTH_40MHZ;
break;
case BW_80_MHZ:
if (reg_ap_cap[idx].behav_limit ==
BIT(BEHAV_BW80_PLUS))
op_chan->ch_width = CH_WIDTH_80P80MHZ;
else
op_chan->ch_width = CH_WIDTH_80MHZ;
break;
case BW_160_MHZ:
op_chan->ch_width = CH_WIDTH_160MHZ;
break;
default:
op_chan->ch_width = INVALID_WIDTH;
break;
}
op_chan->num_oper_chan =
reg_ap_cap[idx].num_supported_chan;
qdf_mem_copy(op_chan->oper_chan_num,
reg_ap_cap[idx].sup_chan_list,
reg_ap_cap[idx].num_supported_chan);
osif_debug("num of supported channel: %u",
op_chan->num_oper_chan);
}
}
/*
* TBD: DFS channel support needs to be added
* Variable nsoc will be update whenever we add DFS
* channel support for Easymesh.
*/
op_chan->num_supp_op_classes = nsoc;
end_reg_get_op_channels:
qdf_mem_free(reg_ap_cap);
}
/* size of sec chan offset element */
#define IEEE80211_SEC_CHAN_OFFSET_BYTES 3
/* no secondary channel */
#define IEEE80211_SEC_CHAN_OFFSET_SCN 0
/* secondary channel above */
#define IEEE80211_SEC_CHAN_OFFSET_SCA 1
/* secondary channel below */
#define IEEE80211_SEC_CHAN_OFFSET_SCB 3
static void os_if_son_reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
struct wlan_op_class *op_class)
{
QDF_STATUS status;
uint8_t i;
uint8_t idx;
uint8_t n_opclasses = 0;
uint8_t chan_idx;
uint8_t max_supp_op_class = REG_MAX_SUPP_OPER_CLASSES;
struct regdmn_ap_cap_opclass_t *reg_ap_cap =
qdf_mem_malloc(max_supp_op_class * sizeof(*reg_ap_cap));
if (!reg_ap_cap) {
osif_err("Memory allocation failure");
return;
}
status = wlan_reg_get_opclass_details(pdev, reg_ap_cap, &n_opclasses,
max_supp_op_class, true);
if (status == QDF_STATUS_E_FAILURE) {
osif_err("Failed to get SAP regulatory capabilities");
goto end_reg_get_opclass_details;
}
osif_debug("n_opclasses: %u", n_opclasses);
for (idx = 0; reg_ap_cap[idx].op_class && idx < n_opclasses; idx++) {
osif_debug("idx: %d op_class: %u ch_width: %d",
idx, reg_ap_cap[idx].op_class,
reg_ap_cap[idx].ch_width);
if ((op_class->opclass != reg_ap_cap[idx].op_class) ||
(reg_ap_cap[idx].ch_width == BW_160_MHZ))
continue;
switch (reg_ap_cap[idx].ch_width) {
case BW_20_MHZ:
case BW_25_MHZ:
op_class->ch_width = CH_WIDTH_20MHZ;
break;
case BW_40_MHZ:
op_class->ch_width = CH_WIDTH_40MHZ;
break;
case BW_80_MHZ:
if (reg_ap_cap[idx].behav_limit == BIT(BEHAV_BW80_PLUS))
op_class->ch_width = CH_WIDTH_80P80MHZ;
else
op_class->ch_width = CH_WIDTH_80MHZ;
break;
case BW_160_MHZ:
op_class->ch_width = CH_WIDTH_160MHZ;
break;
default:
op_class->ch_width = CH_WIDTH_INVALID;
break;
}
switch (reg_ap_cap[idx].behav_limit) {
case BIT(BEHAV_NONE):
op_class->sc_loc = IEEE80211_SEC_CHAN_OFFSET_SCN;
break;
case BIT(BEHAV_BW40_LOW_PRIMARY):
op_class->sc_loc = IEEE80211_SEC_CHAN_OFFSET_SCA;
break;
case BIT(BEHAV_BW40_HIGH_PRIMARY):
op_class->sc_loc = IEEE80211_SEC_CHAN_OFFSET_SCB;
break;
case BIT(BEHAV_BW80_PLUS):
op_class->sc_loc = IEEE80211_SEC_CHAN_OFFSET_SCN;
break;
default:
op_class->sc_loc = IEEE80211_SEC_CHAN_OFFSET_SCN;
break;
}
osif_debug("num_supported_chan: %u num_non_supported_chan: %u",
reg_ap_cap[idx].num_supported_chan,
reg_ap_cap[idx].num_non_supported_chan);
i = 0;
chan_idx = 0;
while ((i < reg_ap_cap[idx].num_supported_chan) &&
(chan_idx < MAX_CHANNELS_PER_OP_CLASS))
op_class->channels[chan_idx++] =
reg_ap_cap[idx].sup_chan_list[i++];
i = 0;
while ((i < reg_ap_cap[idx].num_non_supported_chan) &&
(chan_idx < MAX_CHANNELS_PER_OP_CLASS))
op_class->channels[chan_idx++] =
reg_ap_cap[idx].non_sup_chan_list[i++];
op_class->num_chan = chan_idx;
}
end_reg_get_opclass_details:
qdf_mem_free(reg_ap_cap);
}
QDF_STATUS os_if_son_pdev_ops(struct wlan_objmgr_pdev *pdev,
enum wlan_mlme_pdev_param type,
void *data, void *ret)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
union wlan_mlme_pdev_data *in = (union wlan_mlme_pdev_data *)data;
union wlan_mlme_pdev_data *out = (union wlan_mlme_pdev_data *)ret;
wlan_esp_data *esp_info;
if (!out)
return QDF_STATUS_E_INVAL;
osif_debug("Type: %d", type);
switch (type) {
case PDEV_GET_ESP_INFO:
esp_info = &out->esp_info;
/* BA Window Size of 16 */
esp_info->per_ac[WME_AC_BE].ba_window_size = ba_window_size_16;
esp_info->per_ac[WME_AC_BE].est_air_time_fraction = 0;
/* Default : 250us PPDU Duration in native format */
esp_info->per_ac[WME_AC_BE].data_ppdu_dur_target =
MAP_DEFAULT_PPDU_DURATION * MAP_PPDU_DURATION_UNITS;
break;
case PDEV_GET_CAPABILITY:
os_if_son_reg_get_ap_hw_cap(pdev, &out->cap);
break;
case PDEV_GET_OPERABLE_CHAN:
memcpy(&out->op_chan, &in->op_chan,
sizeof(struct wlan_op_chan));
os_if_son_reg_get_op_channels(pdev, &out->op_chan,
in->op_chan.dfs_required);
break;
case PDEV_GET_OPERABLE_CLASS:
memcpy(&out->op_class, &in->op_class,
sizeof(struct wlan_op_class));
os_if_son_reg_get_opclass_details(pdev, &out->op_class);
break;
default:
break;
}
return status;
}
qdf_export_symbol(os_if_son_pdev_ops);