Răsfoiți Sursa

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
Dustin Brown 6 ani în urmă
părinte
comite
1b899ef904
3 a modificat fișierele cu 264 adăugiri și 52 ștergeri
  1. 11 3
      core/hdd/src/wlan_hdd_nan.c
  2. 0 7
      core/hdd/src/wlan_hdd_nan_datapath.c
  3. 253 42
      os_if/nan/src/os_if_nan.c

+ 11 - 3
core/hdd/src/wlan_hdd_nan.c

@@ -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;
 }

+ 0 - 7
core/hdd/src/wlan_hdd_nan_datapath.c

@@ -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;
 }
 

+ 253 - 42
os_if/nan/src/os_if_nan.c

@@ -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)
 {