qcacld-3.0: Integrate DSC (nan)

The Driver Synchronization Core (DSC) is a set of synchronization
primitives for use by the driver's orchestration layer. It provides APIs
for ensuring safe state transitions (including bring up and tear down)
of major driver objects: a single driver, associated psocs, and their
associated vdevs.

As part of integrating the DSC APIs into OSIF, protect NAN datapath and
NAN discovery.

Change-Id: Icf24c8f7717cd1ca92616c781f06dacdd69c01f0
CRs-Fixed: 2398340
This commit is contained in:
Dustin Brown 2019-02-06 15:27:15 -08:00 • committed by nshrivas
commit 1b899ef904
3 changed files with 264 additions and 52 deletions

View file

@ -157,11 +157,19 @@ int wlan_hdd_cfg80211_nan_ext_request(struct wiphy *wiphy,
int data_len)
{
int ret;
struct osif_psoc_sync *psoc_sync;
int errno;
errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
if (errno)
return errno;
cds_ssr_protect(__func__);
ret = __wlan_hdd_cfg80211_nan_ext_request(wiphy, wdev, data, data_len);
errno = __wlan_hdd_cfg80211_nan_ext_request(wiphy, wdev,
data, data_len);
cds_ssr_unprotect(__func__);
return ret;
osif_psoc_sync_op_stop(psoc_sync);
return errno;
}

View file

@ -408,20 +408,13 @@ static int __wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
int wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
struct wireless_dev *wdev, const void *data, int data_len)
{
struct osif_psoc_sync *psoc_sync;
int errno;
errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
if (errno)
return errno;
cds_ssr_protect(__func__);
errno = __wlan_hdd_cfg80211_process_ndp_cmd(wiphy, wdev,
data, data_len);
cds_ssr_unprotect(__func__);
osif_psoc_sync_op_stop(psoc_sync);
return errno;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@ -20,6 +20,7 @@
* DOC: defines nan component os interface APIs
*/
#include "osif_sync.h"
#include "qdf_str.h"
#include "qdf_trace.h"
#include "qdf_types.h"
@ -168,22 +169,17 @@ vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1] = {
},
};
static int os_if_nan_process_ndi_create(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
static int __os_if_nan_process_ndi_create(struct wlan_objmgr_psoc *psoc,
char *iface_name,
struct nlattr **tb)
{
int ret;
char *iface_name;
QDF_STATUS status;
uint16_t transaction_id;
struct wlan_objmgr_vdev *nan_vdev;
struct nan_callbacks cb_obj;
cfg80211_debug("enter");
if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
cfg80211_err("Interface name string is unavailable");
return -EINVAL;
}
iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
nan_vdev = wlan_util_get_vdev_by_ifname(psoc, iface_name, WLAN_NAN_ID);
if (nan_vdev) {
@ -215,6 +211,116 @@ static int os_if_nan_process_ndi_create(struct wlan_objmgr_psoc *psoc,
return cb_obj.ndi_start(iface_name, transaction_id);
}
static int
osif_nla_str(struct nlattr **tb, size_t attr_id, char **out_str)
{
if (!tb || !tb[attr_id])
return -EINVAL;
*out_str = nla_data(tb[attr_id]);
return 0;
}
static int
osif_device_from_psoc(struct wlan_objmgr_psoc *psoc, struct device **out_dev)
{
qdf_device_t qdf_dev;
if (!psoc)
return -EINVAL;
qdf_dev = wlan_psoc_get_qdf_dev(psoc);
if (!qdf_dev || !qdf_dev->dev)
return -EINVAL;
*out_dev = qdf_dev->dev;
return 0;
}
static int osif_net_dev_from_vdev(struct wlan_objmgr_vdev *vdev,
struct net_device **out_net_dev)
{
struct vdev_osif_priv *priv;
if (!vdev)
return -EINVAL;
priv = wlan_vdev_get_ospriv(vdev);
if (!priv || !priv->wdev || !priv->wdev->netdev)
return -EINVAL;
*out_net_dev = priv->wdev->netdev;
return 0;
}
static int osif_net_dev_from_ifname(struct wlan_objmgr_psoc *psoc,
char *iface_name,
struct net_device **out_net_dev)
{
struct wlan_objmgr_vdev *vdev;
struct net_device *net_dev;
int errno;
vdev = wlan_util_get_vdev_by_ifname(psoc, iface_name, WLAN_NAN_ID);
if (!vdev)
return -EINVAL;
errno = osif_net_dev_from_vdev(vdev, &net_dev);
wlan_objmgr_vdev_release_ref(vdev, WLAN_NAN_ID);
if (errno)
return errno;
*out_net_dev = net_dev;
return 0;
}
static int os_if_nan_process_ndi_create(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
{
struct device *dev;
struct net_device *net_dev;
struct osif_vdev_sync *vdev_sync;
char *ifname;
int errno;
errno = osif_nla_str(tb, QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR, &ifname);
if (errno)
return errno;
errno = osif_device_from_psoc(psoc, &dev);
if (errno)
return errno;
errno = osif_vdev_sync_create_with_trans(dev, &vdev_sync);
if (errno)
return errno;
errno = __os_if_nan_process_ndi_create(psoc, ifname, tb);
if (errno)
goto destroy_sync;
errno = osif_net_dev_from_ifname(psoc, ifname, &net_dev);
if (errno)
goto destroy_sync;
osif_vdev_sync_register(net_dev, vdev_sync);
osif_vdev_sync_trans_stop(vdev_sync);
return 0;
destroy_sync:
osif_vdev_sync_trans_stop(vdev_sync);
osif_vdev_sync_destroy(vdev_sync);
return errno;
}
static void os_if_nan_vdev_delete_peer(struct wlan_objmgr_psoc *psoc,
void *peer, void *nan_vdev)
{
@ -226,24 +332,17 @@ static void os_if_nan_vdev_delete_peer(struct wlan_objmgr_psoc *psoc,
}
}
static int os_if_nan_process_ndi_delete(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
static int __os_if_nan_process_ndi_delete(struct wlan_objmgr_psoc *psoc,
char *iface_name,
struct nlattr **tb)
{
uint8_t vdev_id;
char *iface_name;
QDF_STATUS status;
uint32_t num_peers;
uint16_t transaction_id;
struct nan_callbacks cb_obj;
struct wlan_objmgr_vdev *nan_vdev = NULL;
if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
cfg80211_err("Interface name string is unavailable");
return -EINVAL;
}
iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) {
cfg80211_err("Transaction id is unavailable");
return -EINVAL;
@ -285,6 +384,45 @@ static int os_if_nan_process_ndi_delete(struct wlan_objmgr_psoc *psoc,
return cb_obj.ndi_delete(vdev_id, iface_name, transaction_id);
}
static int os_if_nan_process_ndi_delete(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
{
struct net_device *net_dev;
struct osif_vdev_sync *vdev_sync;
char *ifname;
int errno;
errno = osif_nla_str(tb, QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR, &ifname);
if (errno)
return errno;
errno = osif_net_dev_from_ifname(psoc, ifname, &net_dev);
if (errno)
return errno;
errno = osif_vdev_sync_trans_start_wait(net_dev, &vdev_sync);
if (errno)
return errno;
osif_vdev_sync_unregister(net_dev);
osif_vdev_sync_wait_for_ops(vdev_sync);
errno = __os_if_nan_process_ndi_delete(psoc, ifname, tb);
if (errno)
goto reregister;
osif_vdev_sync_trans_stop(vdev_sync);
osif_vdev_sync_destroy(vdev_sync);
return 0;
reregister:
osif_vdev_sync_register(net_dev, vdev_sync);
osif_vdev_sync_trans_stop(vdev_sync);
return errno;
}
/**
* os_if_nan_parse_security_params() - parse vendor attributes for security
* params.
@ -351,7 +489,7 @@ static int os_if_nan_parse_security_params(struct nlattr **tb,
}
/**
* os_if_nan_process_ndp_initiator_req() - NDP initiator request handler
* __os_if_nan_process_ndp_initiator_req() - NDP initiator request handler
* @ctx: hdd context
* @tb: parsed NL attribute list
*
@ -371,22 +509,16 @@ static int os_if_nan_parse_security_params(struct nlattr **tb,
*
* Return: 0 on success or error code on failure
*/
static int os_if_nan_process_ndp_initiator_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
static int __os_if_nan_process_ndp_initiator_req(struct wlan_objmgr_psoc *psoc,
char *iface_name,
struct nlattr **tb)
{
int ret = 0;
char *iface_name;
QDF_STATUS status;
enum nan_datapath_state state;
struct wlan_objmgr_vdev *nan_vdev;
struct nan_datapath_initiator_req req = {0};
if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
cfg80211_err("Interface name string is unavailable");
return -EINVAL;
}
iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
nan_vdev = wlan_util_get_vdev_by_ifname(psoc, iface_name, WLAN_NAN_ID);
if (!nan_vdev) {
cfg80211_err("NAN data interface %s not available", iface_name);
@ -499,8 +631,35 @@ initiator_req_failed:
return ret;
}
static int os_if_nan_process_ndp_initiator_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
{
struct net_device *net_dev;
struct osif_vdev_sync *vdev_sync;
char *ifname;
int errno;
errno = osif_nla_str(tb, QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR, &ifname);
if (errno)
return errno;
errno = osif_net_dev_from_ifname(psoc, ifname, &net_dev);
if (errno)
return errno;
errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
if (errno)
return errno;
errno = __os_if_nan_process_ndp_initiator_req(psoc, ifname, tb);
osif_vdev_sync_op_stop(vdev_sync);
return errno;
}
/**
* os_if_nan_process_ndp_responder_req() - NDP responder request handler
* __os_if_nan_process_ndp_responder_req() - NDP responder request handler
* @nan_ctx: hdd context
* @tb: parsed NL attribute list
*
@ -518,11 +677,11 @@ initiator_req_failed:
*
* Return: 0 on success or error code on failure
*/
static int os_if_nan_process_ndp_responder_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
static int __os_if_nan_process_ndp_responder_req(struct wlan_objmgr_psoc *psoc,
char *iface_name,
struct nlattr **tb)
{
int ret = 0;
char *iface_name;
QDF_STATUS status;
enum nan_datapath_state state;
struct wlan_objmgr_vdev *nan_vdev = NULL;
@ -535,12 +694,6 @@ static int os_if_nan_process_ndp_responder_req(struct wlan_objmgr_psoc *psoc,
req.ndp_rsp = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE]);
if (req.ndp_rsp == NAN_DATAPATH_RESPONSE_ACCEPT) {
if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
cfg80211_err("Interface not provided");
return -ENODEV;
}
iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
/* Check for an existing NAN interface */
nan_vdev = wlan_util_get_vdev_by_ifname(psoc, iface_name,
WLAN_NAN_ID);
@ -662,8 +815,35 @@ responder_req_failed:
}
static int os_if_nan_process_ndp_responder_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
{
struct net_device *net_dev;
struct osif_vdev_sync *vdev_sync;
char *ifname;
int errno;
errno = osif_nla_str(tb, QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR, &ifname);
if (errno)
return errno;
errno = osif_net_dev_from_ifname(psoc, ifname, &net_dev);
if (errno)
return errno;
errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
if (errno)
return errno;
errno = __os_if_nan_process_ndp_responder_req(psoc, ifname, tb);
osif_vdev_sync_op_stop(vdev_sync);
return errno;
}
/**
* os_if_nan_process_ndp_end_req() - NDP end request handler
* __os_if_nan_process_ndp_end_req() - NDP end request handler
* @psoc: pointer to psoc object
*
* @tb: parsed NL attribute list
@ -672,8 +852,8 @@ responder_req_failed:
*
* Return: 0 on success or error code on failure
*/
static int os_if_nan_process_ndp_end_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
static int __os_if_nan_process_ndp_end_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
{
int ret = 0;
QDF_STATUS status;
@ -722,6 +902,37 @@ static int os_if_nan_process_ndp_end_req(struct wlan_objmgr_psoc *psoc,
return ret;
}
static int os_if_nan_process_ndp_end_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb)
{
struct wlan_objmgr_vdev *vdev;
struct net_device *net_dev;
struct osif_vdev_sync *vdev_sync;
int errno;
vdev = wlan_objmgr_get_vdev_by_opmode_from_psoc(psoc, QDF_NDI_MODE,
WLAN_NAN_ID);
if (!vdev)
return -EINVAL;
errno = osif_net_dev_from_vdev(vdev, &net_dev);
wlan_objmgr_vdev_release_ref(vdev, WLAN_NAN_ID);
if (errno)
return errno;
errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
if (errno)
return errno;
errno = __os_if_nan_process_ndp_end_req(psoc, tb);
osif_vdev_sync_op_stop(vdev_sync);
return errno;
}
int os_if_nan_process_ndp_cmd(struct wlan_objmgr_psoc *psoc,
const void *data, int data_len)
{