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
parent ecfefa92f9
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 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__); 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__); 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, int wlan_hdd_cfg80211_process_ndp_cmd(struct wiphy *wiphy,
struct wireless_dev *wdev, const void *data, int data_len) struct wireless_dev *wdev, const void *data, int data_len)
{ {
struct osif_psoc_sync *psoc_sync;
int errno; int errno;
errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
if (errno)
return errno;
cds_ssr_protect(__func__); cds_ssr_protect(__func__);
errno = __wlan_hdd_cfg80211_process_ndp_cmd(wiphy, wdev, errno = __wlan_hdd_cfg80211_process_ndp_cmd(wiphy, wdev,
data, data_len); data, data_len);
cds_ssr_unprotect(__func__); cds_ssr_unprotect(__func__);
osif_psoc_sync_op_stop(psoc_sync);
return errno; 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 * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -20,6 +20,7 @@
* DOC: defines nan component os interface APIs * DOC: defines nan component os interface APIs
*/ */
#include "osif_sync.h"
#include "qdf_str.h" #include "qdf_str.h"
#include "qdf_trace.h" #include "qdf_trace.h"
#include "qdf_types.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, static int __os_if_nan_process_ndi_create(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb) char *iface_name,
struct nlattr **tb)
{ {
int ret; int ret;
char *iface_name;
QDF_STATUS status; QDF_STATUS status;
uint16_t transaction_id; uint16_t transaction_id;
struct wlan_objmgr_vdev *nan_vdev; struct wlan_objmgr_vdev *nan_vdev;
struct nan_callbacks cb_obj; struct nan_callbacks cb_obj;
cfg80211_debug("enter"); 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); nan_vdev = wlan_util_get_vdev_by_ifname(psoc, iface_name, WLAN_NAN_ID);
if (nan_vdev) { 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); 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, static void os_if_nan_vdev_delete_peer(struct wlan_objmgr_psoc *psoc,
void *peer, void *nan_vdev) 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, static int __os_if_nan_process_ndi_delete(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb) char *iface_name,
struct nlattr **tb)
{ {
uint8_t vdev_id; uint8_t vdev_id;
char *iface_name;
QDF_STATUS status; QDF_STATUS status;
uint32_t num_peers; uint32_t num_peers;
uint16_t transaction_id; uint16_t transaction_id;
struct nan_callbacks cb_obj; struct nan_callbacks cb_obj;
struct wlan_objmgr_vdev *nan_vdev = NULL; 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]) { if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) {
cfg80211_err("Transaction id is unavailable"); cfg80211_err("Transaction id is unavailable");
return -EINVAL; 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); 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 * os_if_nan_parse_security_params() - parse vendor attributes for security
* params. * 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 * @ctx: hdd context
* @tb: parsed NL attribute list * @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 * Return: 0 on success or error code on failure
*/ */
static int os_if_nan_process_ndp_initiator_req(struct wlan_objmgr_psoc *psoc, static int __os_if_nan_process_ndp_initiator_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb) char *iface_name,
struct nlattr **tb)
{ {
int ret = 0; int ret = 0;
char *iface_name;
QDF_STATUS status; QDF_STATUS status;
enum nan_datapath_state state; enum nan_datapath_state state;
struct wlan_objmgr_vdev *nan_vdev; struct wlan_objmgr_vdev *nan_vdev;
struct nan_datapath_initiator_req req = {0}; 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); nan_vdev = wlan_util_get_vdev_by_ifname(psoc, iface_name, WLAN_NAN_ID);
if (!nan_vdev) { if (!nan_vdev) {
cfg80211_err("NAN data interface %s not available", iface_name); cfg80211_err("NAN data interface %s not available", iface_name);
@@ -499,8 +631,35 @@ initiator_req_failed:
return ret; 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 * @nan_ctx: hdd context
* @tb: parsed NL attribute list * @tb: parsed NL attribute list
* *
@@ -518,11 +677,11 @@ initiator_req_failed:
* *
* Return: 0 on success or error code on failure * Return: 0 on success or error code on failure
*/ */
static int os_if_nan_process_ndp_responder_req(struct wlan_objmgr_psoc *psoc, static int __os_if_nan_process_ndp_responder_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb) char *iface_name,
struct nlattr **tb)
{ {
int ret = 0; int ret = 0;
char *iface_name;
QDF_STATUS status; QDF_STATUS status;
enum nan_datapath_state state; enum nan_datapath_state state;
struct wlan_objmgr_vdev *nan_vdev = NULL; 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]); req.ndp_rsp = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE]);
if (req.ndp_rsp == NAN_DATAPATH_RESPONSE_ACCEPT) { 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 */ /* Check for an existing NAN interface */
nan_vdev = wlan_util_get_vdev_by_ifname(psoc, iface_name, nan_vdev = wlan_util_get_vdev_by_ifname(psoc, iface_name,
WLAN_NAN_ID); 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 * @psoc: pointer to psoc object
* *
* @tb: parsed NL attribute list * @tb: parsed NL attribute list
@@ -672,8 +852,8 @@ responder_req_failed:
* *
* Return: 0 on success or error code on failure * Return: 0 on success or error code on failure
*/ */
static int os_if_nan_process_ndp_end_req(struct wlan_objmgr_psoc *psoc, static int __os_if_nan_process_ndp_end_req(struct wlan_objmgr_psoc *psoc,
struct nlattr **tb) struct nlattr **tb)
{ {
int ret = 0; int ret = 0;
QDF_STATUS status; QDF_STATUS status;
@@ -722,6 +902,37 @@ static int os_if_nan_process_ndp_end_req(struct wlan_objmgr_psoc *psoc,
return ret; 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, int os_if_nan_process_ndp_cmd(struct wlan_objmgr_psoc *psoc,
const void *data, int data_len) const void *data, int data_len)
{ {