qcacmn: Implement ndp schedule update and channel info in ndp confirm

Add support for ndp schedule update event and provide channel information
in ndp confirm event.

Change-Id: Ic2c073dd4f220627cc2bd1a2d52d858136b6b450
CRs-Fixed: 2180310
This commit is contained in:
Naveen Rawat
2018-01-09 17:54:41 -08:00
committed by nshrivas
parent 94763f5261
commit 366330a417

View File

@@ -122,6 +122,14 @@ vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1] = {
.type = NLA_BINARY,
.len = NAN_MAX_SERVICE_NAME_LEN
},
[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO] = {
.type = NLA_BINARY,
.len = NAN_CH_INFO_MAX_LEN
},
[QCA_WLAN_VENDOR_ATTR_NDP_NSS] = {
.type = NLA_U32,
.len = sizeof(uint32_t)
},
};
static int os_if_nan_process_ndi_create(struct wlan_objmgr_psoc *psoc,
@@ -1023,6 +1031,7 @@ ndp_indication_nla_failed:
static inline uint32_t osif_ndp_get_ndp_confirm_ind_len(
struct nan_datapath_confirm_event *ndp_confirm)
{
uint32_t ch_info_len = 0;
uint32_t data_len = NLMSG_HDRLEN;
data_len += nla_total_size(vendor_attr_policy[
@@ -1042,9 +1051,62 @@ static inline uint32_t osif_ndp_get_ndp_confirm_ind_len(
data_len +=
nla_total_size(ndp_confirm->ndp_info.ndp_app_info_len);
/* ch_info is a nested array of following attributes */
ch_info_len += nla_total_size(
vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL].len);
ch_info_len += nla_total_size(
vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH].len);
ch_info_len += nla_total_size(
vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_NDP_NSS].len);
if (ndp_confirm->num_channels)
data_len += ndp_confirm->num_channels *
nla_total_size(ch_info_len);
return data_len;
}
static QDF_STATUS os_if_ndp_confirm_pack_ch_info(struct sk_buff *event,
struct nan_datapath_confirm_event *ndp_confirm)
{
int idx = 0;
struct nlattr *ch_array, *ch_element;
cfg80211_debug("num_ch: %d", ndp_confirm->num_channels);
if (!ndp_confirm->num_channels)
return QDF_STATUS_SUCCESS;
ch_array = nla_nest_start(event, QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO);
if (!ch_array)
return QDF_STATUS_E_FAULT;
for (idx = 0; idx < ndp_confirm->num_channels; idx++) {
cfg80211_debug("ch[%d]: freq: %d, width: %d, nss: %d",
idx, ndp_confirm->ch[idx].channel,
ndp_confirm->ch[idx].ch_width,
ndp_confirm->ch[idx].nss);
ch_element = nla_nest_start(event, idx);
if (!ch_element)
return QDF_STATUS_E_FAULT;
if (nla_put_u32(event, QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL,
ndp_confirm->ch[idx].channel))
return QDF_STATUS_E_FAULT;
if (nla_put_u32(event, QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH,
ndp_confirm->ch[idx].ch_width))
return QDF_STATUS_E_FAULT;
if (nla_put_u32(event, QCA_WLAN_VENDOR_ATTR_NDP_NSS,
ndp_confirm->ch[idx].nss))
return QDF_STATUS_E_FAULT;
nla_nest_end(event, ch_element);
}
nla_nest_end(event, ch_array);
return QDF_STATUS_SUCCESS;
}
/**
* os_if_ndp_confirm_ind_handler() - NDP confirm indication handler
* @vdev: pointer to vdev object
@@ -1062,20 +1124,20 @@ static inline uint32_t osif_ndp_get_ndp_confirm_ind_len(
*
* Return: none
*/
static void os_if_ndp_confirm_ind_handler(struct wlan_objmgr_vdev *vdev,
struct nan_datapath_confirm_event *ndp_confirm)
static void
os_if_ndp_confirm_ind_handler(struct wlan_objmgr_vdev *vdev,
struct nan_datapath_confirm_event *ndp_confirm)
{
int idx = 0;
uint8_t *ifname;
uint32_t data_len;
QDF_STATUS status;
qdf_size_t ifname_len;
uint32_t ndp_qos_config = 0;
struct nan_callbacks cb_obj;
struct sk_buff *vendor_event;
struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
struct pdev_osif_priv *os_priv = wlan_pdev_get_ospriv(pdev);
struct nan_callbacks cb_obj;
if (!ndp_confirm) {
cfg80211_err("Invalid NDP Initator response");
@@ -1156,12 +1218,19 @@ static void os_if_ndp_confirm_ind_handler(struct wlan_objmgr_vdev *vdev,
ndp_confirm->reason_code))
goto ndp_confirm_nla_failed;
if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_NUM_CHANNELS,
ndp_confirm->num_channels))
goto ndp_confirm_nla_failed;
status = os_if_ndp_confirm_pack_ch_info(vendor_event, ndp_confirm);
if (QDF_IS_STATUS_ERROR(status))
goto ndp_confirm_nla_failed;
cfg80211_vendor_event(vendor_event, GFP_ATOMIC);
cfg80211_debug("NDP confim sent, ndp instance id: %d, peer addr: %pM, ndp_cfg: %d, rsp_code: %d, reason_code: %d",
cfg80211_debug("NDP confim sent, ndp instance id: %d, peer addr: %pM rsp_code: %d, reason_code: %d",
ndp_confirm->ndp_instance_id,
ndp_confirm->peer_ndi_mac_addr.bytes,
ndp_qos_config, ndp_confirm->rsp_code,
ndp_confirm->reason_code);
ndp_confirm->rsp_code, ndp_confirm->reason_code);
cfg80211_debug("NDP confim, ndp app info dump");
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
@@ -1620,6 +1689,168 @@ static void os_if_ndp_iface_delete_rsp_handler(struct wlan_objmgr_psoc *psoc,
cb_obj.drv_ndi_delete_rsp_handler(vdev_id);
}
static inline uint32_t osif_ndp_get_ndp_sch_update_ind_len(
struct nan_datapath_sch_update_event *sch_update)
{
uint32_t ch_info_len = 0;
uint32_t data_len = NLMSG_HDRLEN;
data_len += nla_total_size(vendor_attr_policy[
QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD].len);
data_len += nla_total_size(vendor_attr_policy[
QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR].len);
if (sch_update->num_ndp_instances)
data_len += nla_total_size(sch_update->num_ndp_instances *
sizeof(uint32_t));
data_len += nla_total_size(vendor_attr_policy[
QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_REASON].len);
data_len += nla_total_size(vendor_attr_policy[
QCA_WLAN_VENDOR_ATTR_NDP_NUM_CHANNELS].len);
/* ch_info is a nested array of following attributes */
ch_info_len += nla_total_size(
vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL].len);
ch_info_len += nla_total_size(
vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH].len);
ch_info_len += nla_total_size(
vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_NDP_NSS].len);
if (sch_update->num_ndp_instances)
data_len += sch_update->num_ndp_instances *
nla_total_size(ch_info_len);
return data_len;
}
static QDF_STATUS os_if_ndp_sch_update_pack_ch_info(struct sk_buff *event,
struct nan_datapath_sch_update_event *sch_update)
{
int idx = 0;
struct nlattr *ch_array, *ch_element;
cfg80211_debug("num_ch: %d", sch_update->num_channels);
if (!sch_update->num_channels)
return QDF_STATUS_SUCCESS;
ch_array = nla_nest_start(event, QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO);
if (!ch_array)
return QDF_STATUS_E_FAULT;
for (idx = 0; idx < sch_update->num_channels; idx++) {
cfg80211_debug("ch[%d]: freq: %d, width: %d, nss: %d",
idx, sch_update->ch[idx].channel,
sch_update->ch[idx].ch_width,
sch_update->ch[idx].nss);
ch_element = nla_nest_start(event, idx);
if (!ch_element)
return QDF_STATUS_E_FAULT;
if (nla_put_u32(event, QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL,
sch_update->ch[idx].channel))
return QDF_STATUS_E_FAULT;
if (nla_put_u32(event, QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH,
sch_update->ch[idx].ch_width))
return QDF_STATUS_E_FAULT;
if (nla_put_u32(event, QCA_WLAN_VENDOR_ATTR_NDP_NSS,
sch_update->ch[idx].nss))
return QDF_STATUS_E_FAULT;
nla_nest_end(event, ch_element);
}
nla_nest_end(event, ch_array);
return QDF_STATUS_SUCCESS;
}
/**
* os_if_ndp_sch_update_ind_handler() - NDP schedule update handler
* @vdev: vdev object pointer
* @ind: sch update pointer
*
* Following vendor event is sent to cfg80211:
*
* Return: none
*/
static void os_if_ndp_sch_update_ind_handler(struct wlan_objmgr_vdev *vdev,
void *ind)
{
int idx = 0;
uint8_t *ifname;
QDF_STATUS status;
uint32_t data_len;
uint8_t ifname_len;
struct sk_buff *vendor_event;
struct nan_datapath_sch_update_event *sch_update = ind;
struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
struct pdev_osif_priv *os_priv = wlan_pdev_get_ospriv(pdev);
if (!sch_update) {
cfg80211_err("Invalid sch update params");
return;
}
ifname = wlan_util_vdev_get_if_name(vdev);
if (!ifname) {
cfg80211_err("ifname is null");
return;
}
ifname_len = qdf_str_len(ifname);
if (ifname_len > IFNAMSIZ) {
cfg80211_err("ifname(%d) too long", ifname_len);
return;
}
data_len = osif_ndp_get_ndp_sch_update_ind_len(sch_update);
vendor_event = cfg80211_vendor_event_alloc(os_priv->wiphy, NULL,
data_len, QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
GFP_ATOMIC);
if (!vendor_event) {
cfg80211_err("cfg80211_vendor_event_alloc failed");
return;
}
if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_IND))
goto ndp_sch_ind_nla_failed;
if (nla_put(vendor_event,
QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR,
QDF_MAC_ADDR_SIZE, sch_update->peer_addr.bytes))
goto ndp_sch_ind_nla_failed;
if (nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY,
sch_update->num_ndp_instances * sizeof(uint32_t),
sch_update->ndp_instances))
goto ndp_sch_ind_nla_failed;
if (nla_put_u32(vendor_event,
QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_REASON,
sch_update->flags))
goto ndp_sch_ind_nla_failed;
if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_NUM_CHANNELS,
sch_update->num_channels))
goto ndp_sch_ind_nla_failed;
status = os_if_ndp_sch_update_pack_ch_info(vendor_event, sch_update);
if (QDF_IS_STATUS_ERROR(status))
goto ndp_sch_ind_nla_failed;
cfg80211_debug("Flags: %d, num_instance_id: %d", sch_update->flags,
sch_update->num_ndp_instances);
for (idx = 0; idx < sch_update->num_ndp_instances; idx++)
cfg80211_debug("ndp_instance[%d]: %d", idx,
sch_update->ndp_instances[idx]);
cfg80211_vendor_event(vendor_event, GFP_ATOMIC);
return;
ndp_sch_ind_nla_failed:
cfg80211_err("nla_put api failed");
kfree_skb(vendor_event);
}
void os_if_nan_event_handler(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_vdev *vdev,
uint32_t type, void *msg)
@@ -1655,6 +1886,9 @@ void os_if_nan_event_handler(struct wlan_objmgr_psoc *psoc,
case NDP_PEER_DEPARTED:
os_if_peer_departed_ind_handler(vdev, msg);
break;
case NDP_SCHEDULE_UPDATE:
os_if_ndp_sch_update_ind_handler(vdev, msg);
break;
default:
break;
}