Переглянути джерело

qcacld-3.0: Add support to send cfr data via nl events

User configures CFR data transport mode using vendor command
QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG and attr
QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE. Host sends
CFR data to userspace via relayfs if transport mode set is
QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS else if transport mode is set
to QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS, host sends CFR data
via NL events. By default transport mode is relayfs.
To get CFR data as unicast NL events, user configures PID of a
process using vendor attr
QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID. By default CFR
data NL events are broadcast.

Change-Id: Ifc2694fa3b21dc01f25da2219deb367375a48475
CRs-Fixed: 2953290
Abhishek Ambure 3 роки тому
батько
коміт
f8fd2ad264

+ 56 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -1680,6 +1680,7 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
 #ifdef WLAN_SUPPORT_TWT
 	FEATURE_TWT_VENDOR_EVENTS
 #endif
+	FEATURE_CFR_DATA_VENDOR_EVENTS
 };
 
 /**
@@ -6726,6 +6727,61 @@ wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
 #endif
 #endif /* FEATURE_CM_ENABLE */
 
+#ifdef WLAN_CFR_ENABLE
+void hdd_cfr_data_send_nl_event(uint8_t vdev_id, uint32_t pid,
+				const void *data, uint32_t data_len)
+{
+	uint32_t len, ret;
+	struct sk_buff *vendor_event;
+	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	struct hdd_adapter *adapter;
+	struct nlmsghdr *nlhdr = NULL;
+
+	if (!hdd_ctx) {
+		hdd_err("HDD context is NULL");
+		return;
+	}
+
+	adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
+	if (!adapter) {
+		hdd_err("adapter NULL for vdev id %d", vdev_id);
+		return;
+	}
+
+	len = nla_total_size(data_len) + NLMSG_HDRLEN;
+	vendor_event = cfg80211_vendor_event_alloc(
+			hdd_ctx->wiphy, &adapter->wdev, len,
+			QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG_INDEX,
+			GFP_KERNEL);
+
+	if (!vendor_event) {
+		hdd_err("cfg80211_vendor_event_alloc failed vdev id %d, data len %d",
+			vdev_id, data_len);
+		return;
+	}
+
+	ret = nla_put(vendor_event,
+		      QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA,
+		      data_len, data);
+	if (ret) {
+		hdd_err("CFR event put fails status %d", ret);
+		kfree_skb(vendor_event);
+		return;
+	}
+
+	if (pid) {
+		nlhdr = nlmsg_hdr(vendor_event);
+		if (nlhdr)
+			nlhdr->nlmsg_pid = pid;
+		else
+			hdd_err_rl("nlhdr is null");
+	}
+
+	hdd_debug("vdev id %d pid %d", vdev_id, pid);
+	cfg80211_vendor_event(vendor_event, GFP_KERNEL);
+}
+#endif
+
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 void hdd_send_roam_scan_ch_list_event(struct hdd_context *hdd_ctx,
 				      uint8_t vdev_id, uint16_t buf_len,

+ 22 - 0
core/hdd/src/wlan_hdd_cfg80211.h

@@ -525,6 +525,28 @@ void wlan_hdd_cfg80211_unlink_bss(struct hdd_adapter *adapter,
 
 void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter);
 
+#ifdef WLAN_CFR_ENABLE
+/*
+ * hdd_cfr_data_send_nl_event() - send cfr data through nl event
+ * @vdev_id: vdev id
+ * @pid: process pid to which send data event unicast way
+ * @data: pointer to the cfr data
+ * @data_len: length of data
+ *
+ * Return: void
+ */
+void hdd_cfr_data_send_nl_event(uint8_t vdev_id, uint32_t pid,
+				const void *data, uint32_t data_len);
+
+#define FEATURE_CFR_DATA_VENDOR_EVENTS                                  \
+[QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG_INDEX] = {              \
+        .vendor_id = QCA_NL80211_VENDOR_ID,                             \
+        .subcmd = QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG,       \
+},
+#else
+#define FEATURE_CFR_DATA_VENDOR_EVENTS
+#endif
+
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 /**
  * hdd_send_roam_scan_ch_list_event() - roam scan ch list event to user space

+ 56 - 0
core/hdd/src/wlan_hdd_cfr.c

@@ -70,8 +70,38 @@ const struct nla_policy cfr_config_policy[
 						.type = NLA_U32},
 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER] = {
 						.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE] = {
+						.type = NLA_U8},
+	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID] = {
+						.type = NLA_U32},
 };
 
+static void
+wlan_hdd_transport_mode_cfg(struct wlan_objmgr_pdev *pdev,
+			    uint8_t vdev_id, uint32_t pid,
+			    enum qca_wlan_vendor_cfr_data_transport_modes tx_mode)
+{
+	struct pdev_cfr *pa;
+
+	if (!pdev) {
+		hdd_err("failed to %s transport mode cb for cfr, pdev is NULL for vdev id %d",
+			tx_mode ? "register" : "deregister", vdev_id);
+		return;
+	}
+
+	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
+	if (!pa) {
+		hdd_err("cfr private obj is NULL for vdev id %d", vdev_id);
+		return;
+	}
+	pa->nl_cb.vdev_id = vdev_id;
+	pa->nl_cb.pid = pid;
+	if (tx_mode == QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS)
+		pa->nl_cb.cfr_nl_cb = hdd_cfr_data_send_nl_event;
+	else
+		pa->nl_cb.cfr_nl_cb = NULL;
+}
+
 #ifdef WLAN_ENH_CFR_ENABLE
 
 #define DEFAULT_CFR_NSS 0xff
@@ -175,6 +205,7 @@ wlan_cfg80211_cfr_set_group_config(struct wlan_objmgr_vdev *vdev,
 			  params.expected_data_subtype,
 			  params.expected_data_subtype);
 	}
+
 	if (!params.expected_mgmt_subtype ||
 	    !params.expected_ctrl_subtype ||
 		!params.expected_data_subtype) {
@@ -289,6 +320,31 @@ wlan_cfg80211_cfr_set_config(struct wlan_objmgr_vdev *vdev,
 		}
 	}
 
+	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE]) {
+		uint8_t transport_mode = 0xff;
+		uint32_t pid = 0;
+
+		if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID])
+			pid = nla_get_u32(tb[
+			QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID]);
+		else
+			hdd_debug("No PID received");
+
+		transport_mode = nla_get_u8(tb[
+			QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE]);
+
+		hdd_debug("tx mode attr %d, pid %d", transport_mode, pid);
+		if (transport_mode == QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS ||
+		    transport_mode == QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS) {
+			wlan_hdd_transport_mode_cfg(vdev->vdev_objmgr.wlan_pdev,
+						    vdev->vdev_objmgr.vdev_id,
+						    pid, transport_mode);
+		} else {
+			hdd_debug("invalid transport mode %d for vdev id %d",
+				  transport_mode, vdev->vdev_objmgr.vdev_id);
+		}
+	}
+
 	return 0;
 }