qcacld-3.0: Send roam control status to userspace upon querying

Userspace may configure and enable roam control and query for
the status. Add provision to send the same as vendor cmd reply

Change-Id: I7b82f85fa560c974eedc5115276bd87a84f9d3a0
CRs-Fixed: 2508802
This commit is contained in:
Srinivas Dasari 2019-08-20 11:43:06 +05:30 • committed by nshrivas
commit 9ad9e25ed6
3 changed files with 199 additions and 1 deletions

View file

@ -1512,7 +1512,10 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
},
BCN_RECV_FEATURE_VENDOR_EVENTS
[QCA_NL80211_VENDOR_SUBCMD_ROAM_INDEX] = {
.vendor_id = QCA_NL80211_VENDOR_ID,
.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
},
};
/**
@ -4115,6 +4118,7 @@ hdd_send_roam_scan_channel_freq_list_to_sme(struct hdd_context *hdd_ctx,
static const struct nla_policy
roam_control_policy[QCA_ATTR_ROAM_CONTROL_MAX + 1] = {
[QCA_ATTR_ROAM_CONTROL_ENABLE] = {.type = NLA_U8},
[QCA_ATTR_ROAM_CONTROL_STATUS] = {.type = NLA_U8},
[PARAM_FREQ_LIST_SCHEME] = {.type = NLA_NESTED},
[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD] = {.type = NLA_U32},
[QCA_ATTR_ROAM_CONTROL_CLEAR_ALL] = {.type = NLA_FLAG},
@ -4304,6 +4308,7 @@ hdd_set_roam_with_control_config(struct hdd_context *hdd_ctx,
struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1], *attr;
uint32_t value;
hdd_enter();
/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
hdd_err("Attribute CONTROL_CONFIG is not present");
@ -4433,6 +4438,157 @@ hdd_clear_roam_control_config(struct hdd_context *hdd_ctx,
return 0;
}
/**
* hdd_roam_control_config_buf_size() - Calculate the skb size to be allocated
* @hdd_ctx: HDD context
* @tb: List of attributes to be populated
*
* Calculate the buffer size to be allocated based on the attributes
* mentioned in tb.
*
* Return: buffer size to be allocated
*/
static uint16_t
hdd_roam_control_config_buf_size(struct hdd_context *hdd_ctx,
struct nlattr **tb)
{
uint16_t skb_len = 0;
if (tb[QCA_ATTR_ROAM_CONTROL_STATUS])
skb_len += NLA_HDRLEN + sizeof(uint8_t);
return skb_len;
}
/**
* hdd_roam_control_config_fill_data() - Fill the data requested by userspace
* @hdd_ctx: HDD context
* @vdev_id: vdev id
* @skb: SK buffer
* @tb: List of attributes
*
* Get the data corresponding to the attribute list specified in tb and
* update the same to skb by populating the same attributes.
*
* Return: 0 on success; error number on failure
*/
static int
hdd_roam_control_config_fill_data(struct hdd_context *hdd_ctx, uint8_t vdev_id,
struct sk_buff *skb, struct nlattr **tb)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint8_t roam_control;
struct nlattr *config;
config = nla_nest_start(skb, PARAM_ROAM_CONTROL_CONFIG);
if (!config)
return -EINVAL;
if (tb[QCA_ATTR_ROAM_CONTROL_STATUS]) {
status = sme_get_roam_config_status(hdd_ctx->mac_handle,
vdev_id,
&roam_control);
if (QDF_IS_STATUS_ERROR(status))
goto out;
hdd_debug("Roam control: %s",
roam_control ? "Enabled" : "Disabled");
if (nla_put_u8(skb, QCA_ATTR_ROAM_CONTROL_STATUS,
roam_control)) {
hdd_info("failed to put vendor_roam_control");
return -ENOMEM;
}
}
nla_nest_end(skb, config);
out:
return qdf_status_to_os_return(status);
}
/**
* hdd_send_roam_control_config() - Send the roam config as vendor cmd reply
* @mac_handle: Opaque handle to the MAC context
* @vdev_id: vdev id
* @tb: List of attributes
*
* Parse the attributes list tb and get the data corresponding to the
* attributes specified in tb. Send them as a vendor response.
*
* Return: 0 on success; error number on failure
*/
static int
hdd_send_roam_control_config(struct hdd_context *hdd_ctx,
uint8_t vdev_id,
struct nlattr **tb)
{
struct sk_buff *skb;
uint16_t skb_len;
int status;
hdd_enter();
skb_len = hdd_roam_control_config_buf_size(hdd_ctx, tb);
if (!skb_len) {
hdd_err("No data requested");
return -EINVAL;
}
skb_len += NLMSG_HDRLEN;
skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, skb_len);
if (!skb) {
hdd_info("cfg80211_vendor_cmd_alloc_reply_skb failed");
return -ENOMEM;
}
status = hdd_roam_control_config_fill_data(hdd_ctx, vdev_id, skb, tb);
if (status)
goto fail;
hdd_exit();
return cfg80211_vendor_cmd_reply(skb);
fail:
hdd_err("nla put fail");
kfree_skb(skb);
return status;
}
/**
* hdd_get_roam_control_config() - Send requested roam config to userspace
* @hdd_ctx: HDD context
* @tb: list of attributes
* @vdev_id: vdev id
*
* Return: 0 on success; error number on failure
*/
static int hdd_get_roam_control_config(struct hdd_context *hdd_ctx,
struct nlattr **tb,
uint8_t vdev_id)
{
QDF_STATUS status;
struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
hdd_enter();
/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
hdd_err("Attribute CONTROL_CONFIG is not present");
return -EINVAL;
}
if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
tb[PARAM_ROAM_CONTROL_CONFIG],
roam_control_policy)) {
hdd_err("nla_parse failed");
return -EINVAL;
}
status = hdd_send_roam_control_config(hdd_ctx, vdev_id, tb2);
if (status) {
hdd_err("failed to enable/disable roam control");
return status;
}
return qdf_status_to_os_return(status);
}
#undef PARAM_ROAM_CONTROL_CONFIG
#undef PARAM_FREQ_LIST_SCHEME_MAX
#undef PARAM_FREQ_LIST_SCHEME
@ -4590,6 +4746,11 @@ static int hdd_set_ext_roam_params(struct hdd_context *hdd_ctx,
if (ret)
goto fail;
break;
case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET:
ret = hdd_get_roam_control_config(hdd_ctx, tb, vdev_id);
if (ret)
goto fail;
break;
}
return 0;

View file

@ -3697,4 +3697,17 @@ QDF_STATUS sme_set_roam_triggers(mac_handle_t mac_handle,
QDF_STATUS sme_set_roam_config_enable(mac_handle_t mac_handle,
uint8_t vdev_id,
uint8_t roam_control_enable);
/**
* sme_get_roam_config_status() - Get roam config status from SME
* @mac_handle: Opaque handle to the MAC context
* @vdev_id: vdev id
* @config_status: Pointer of a buffer to fill the status
*
* Get the cached control roam config status in SME and copy to status.
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_get_roam_config_status(mac_handle_t mac_handle, uint8_t vdev_id,
uint8_t *config_status);
#endif /* #if !defined( __SME_API_H ) */

View file

@ -16137,3 +16137,27 @@ QDF_STATUS sme_set_roam_config_enable(mac_handle_t mac_handle,
return status;
}
QDF_STATUS sme_get_roam_config_status(mac_handle_t mac_handle,
uint8_t vdev_id,
uint8_t *config_status)
{
struct mac_context *mac = MAC_CONTEXT(mac_handle);
QDF_STATUS status;
if (vdev_id >= WLAN_MAX_VDEVS) {
sme_err("Invalid vdev_id: %d", vdev_id);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_ERROR(status)) {
sme_err("Failed to acquire sme lock; status: %d", status);
return status;
}
*config_status =
mac->roam.neighborRoamInfo[vdev_id].roam_control_enable;
sme_release_global_lock(&mac->sme);
return status;
}