Browse Source

qcacld-3.0: Add support for set multicast filter command

Add support for WMI_SET_MULTIPLE_MCAST_FILTER_CMDID command
that can add/delete multiple mcast filters.

CRs-Fixed: 2096595
Change-Id: I3dc93c603a5a6676d97b5911a716277c7bef0ef8
Poddar, Siddarth 7 years ago
parent
commit
f7c49e73b7

+ 14 - 5
components/pmo/core/src/wlan_pmo_mc_addr_filtering.c

@@ -149,8 +149,13 @@ QDF_STATUS pmo_core_set_mc_filter_req(struct wlan_objmgr_vdev *vdev,
 
 	PMO_ENTER();
 
-	for (i = 0; i < mc_list->mc_cnt; i++) {
-		pmo_tgt_set_mc_filter_req(vdev, mc_list->mc_addr[i]);
+	if (pmo_tgt_get_multiple_mc_filter_support(vdev)) {
+		pmo_debug("FW supports multiple mcast filter");
+		pmo_tgt_set_multiple_mc_filter_req(vdev, mc_list);
+	} else {
+		pmo_debug("FW does not support multiple mcast filter");
+		for (i = 0; i < mc_list->mc_cnt; i++)
+			pmo_tgt_set_mc_filter_req(vdev, mc_list->mc_addr[i]);
 	}
 
 	PMO_EXIT();
@@ -164,9 +169,13 @@ QDF_STATUS pmo_core_clear_mc_filter_req(struct wlan_objmgr_vdev *vdev,
 	int i;
 
 	PMO_ENTER();
-
-	for (i = 0; i < mc_list->mc_cnt; i++) {
-		pmo_tgt_clear_mc_filter_req(vdev, mc_list->mc_addr[i]);
+	if (pmo_tgt_get_multiple_mc_filter_support(vdev)) {
+		pmo_debug("FW supports multiple mcast filter");
+		pmo_tgt_clear_multiple_mc_filter_req(vdev, mc_list);
+	} else {
+		pmo_debug("FW does not support multiple mcast filter");
+		for (i = 0; i < mc_list->mc_cnt; i++)
+			pmo_tgt_clear_mc_filter_req(vdev, mc_list->mc_addr[i]);
 	}
 
 	PMO_EXIT();

+ 12 - 0
components/pmo/dispatcher/inc/wlan_pmo_mc_addr_filtering_public_struct.h

@@ -30,6 +30,7 @@
 #include "wlan_pmo_common_public_struct.h"
 
 #define PMO_MAX_MC_ADDR_LIST 32
+#define PMO_MAX_NUM_MULTICAST_ADDRESS 240
 
 /**
  * struct pmo_mc_addr_list_params -pmo mc address list request params
@@ -57,4 +58,15 @@ struct pmo_mc_addr_list {
 	struct qdf_mac_addr mc_addr[PMO_MAX_MC_ADDR_LIST];
 };
 
+/**
+ * struct mcast_filter_params - mcast filter parameters
+ * @multicast_addr_cnt: num of addresses
+ * @multicast_addr: address array
+ * @action: operation to perform
+ */
+struct pmo_mcast_filter_params {
+	uint32_t multicast_addr_cnt;
+	struct qdf_mac_addr multicast_addr[PMO_MAX_NUM_MULTICAST_ADDRESS];
+	uint8_t action;
+};
 #endif /* end  of _WLAN_PMO_MC_ADDR_FILTERING_STRUCT_H_ */

+ 11 - 0
components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h

@@ -78,6 +78,9 @@ int (*pmo_pld_auto_resume_cb)(void);
  * @send_enhance_mc_offload_req: fp to send enhanced multicast offload request
  * @send_set_mc_filter_req: fp to send set mc filter request
  * @send_clear_mc_filter_req: fp to send clear mc filter request
+ * @get_multiple_mc_filter_support: fp to get mc filter support
+ * @send_set_multiple_mc_filter_req: fp to send set multiple mc filter request
+ * @send_clear_multiple_mc_filter_req: fp to send clear multiple mc filter req
  * @send_ra_filter_req: fp to send ra filter request
  * @send_gtk_offload_req: fp to send gtk offload request command
  * @send_get_gtk_rsp_cmd: fp to send get gtk response request cmd to firmware
@@ -134,6 +137,14 @@ struct wlan_pmo_tx_ops {
 	QDF_STATUS (*send_clear_mc_filter_req)(
 			struct wlan_objmgr_vdev *vdev,
 			struct qdf_mac_addr multicast_addr);
+	bool (*get_multiple_mc_filter_support)(
+			struct wlan_objmgr_psoc *psoc);
+	QDF_STATUS(*send_set_multiple_mc_filter_req)(
+			struct wlan_objmgr_vdev *vdev,
+			struct pmo_mc_addr_list *mc_list);
+	QDF_STATUS(*send_clear_multiple_mc_filter_req)(
+			struct wlan_objmgr_vdev *vdev,
+			struct pmo_mc_addr_list *mc_list);
 	QDF_STATUS (*send_ra_filter_req)(
 			struct wlan_objmgr_vdev *vdev,
 			uint8_t default_pattern, uint16_t rate_limit_interval);

+ 29 - 0
components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h

@@ -170,6 +170,35 @@ QDF_STATUS pmo_tgt_set_mc_filter_req(struct wlan_objmgr_vdev *vdev,
 QDF_STATUS pmo_tgt_clear_mc_filter_req(struct wlan_objmgr_vdev *vdev,
 		struct qdf_mac_addr multicast_addr);
 
+/**
+ * pmo_tgt_get_multiple_mc_filter_support() - get multiple mcast filter support
+ * @vdev: objmgr vdev
+ *
+ * Return: true if FW supports else false
+ */
+bool pmo_tgt_get_multiple_mc_filter_support(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * pmo_tgt_set_multiple_mc_filter_req() - Set multiple mcast filter cmd to fw
+ * @vdev: objmgr vdev
+ * @mc_list: mcast address list
+ *
+ * Return: QDF_STATUS_SUCCESS for success or error code
+ */
+QDF_STATUS pmo_tgt_set_multiple_mc_filter_req(struct wlan_objmgr_vdev *vdev,
+		struct pmo_mc_addr_list *mc_list);
+
+/**
+ * pmo_tgt_clear_multiple_mc_filter_req() - clear multiple mcast filter
+ *					    to fw
+ * @vdev: objmgr vdev
+ * @mc_list: mcast address list
+ *
+ * Return: QDF_STATUS_SUCCESS for success or error code
+ */
+QDF_STATUS pmo_tgt_clear_multiple_mc_filter_req(struct wlan_objmgr_vdev *vdev,
+		struct pmo_mc_addr_list *mc_list);
+
 /**
  * pmo_tgt_send_enhance_multicast_offload_req() - send enhance mc offload req
  * @vdev: the vdev to configure

+ 74 - 0
components/pmo/dispatcher/src/wlan_pmo_tgt_mc_addr_filtering.c

@@ -80,4 +80,78 @@ out:
 	return status;
 }
 
+bool pmo_tgt_get_multiple_mc_filter_support(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_pmo_tx_ops pmo_tx_ops;
+	struct wlan_objmgr_psoc *psoc;
+
+	PMO_ENTER();
+
+	psoc = pmo_vdev_get_psoc(vdev);
+
+	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
+	if (!pmo_tx_ops.get_multiple_mc_filter_support) {
+		pmo_err("get_multiple_mc_filter_support is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	return pmo_tx_ops.get_multiple_mc_filter_support(psoc);
+}
+
+QDF_STATUS pmo_tgt_set_multiple_mc_filter_req(struct wlan_objmgr_vdev *vdev,
+		struct pmo_mc_addr_list *mc_list)
+{
+	QDF_STATUS status;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_pmo_tx_ops pmo_tx_ops;
+
+	PMO_ENTER();
+
+	psoc = pmo_vdev_get_psoc(vdev);
+
+	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
+	if (!pmo_tx_ops.send_set_multiple_mc_filter_req) {
+		pmo_err("send_set_multiple_mc_filter_req is null");
+		status = QDF_STATUS_E_NULL_VALUE;
+		goto out;
+	}
+
+	status = pmo_tx_ops.send_set_multiple_mc_filter_req(
+			vdev, mc_list);
+	if (status != QDF_STATUS_SUCCESS)
+		pmo_err("Failed to add/clear multiple mc filter");
+out:
+	PMO_EXIT();
+
+	return status;
+}
+
+QDF_STATUS pmo_tgt_clear_multiple_mc_filter_req(struct wlan_objmgr_vdev *vdev,
+		struct pmo_mc_addr_list *mc_list)
+{
+	QDF_STATUS status;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_pmo_tx_ops pmo_tx_ops;
+
+	PMO_ENTER();
+
+	psoc = pmo_vdev_get_psoc(vdev);
+
+	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
+	if (!pmo_tx_ops.send_clear_multiple_mc_filter_req) {
+		pmo_err("send_clear_multiple_mc_filter_req is null");
+		status = QDF_STATUS_E_NULL_VALUE;
+		goto out;
+	}
+
+	status = pmo_tx_ops.send_clear_multiple_mc_filter_req(
+			vdev, mc_list);
+	if (status != QDF_STATUS_SUCCESS)
+		pmo_err("Failed to add/clear multiple mc filter");
+out:
+	PMO_EXIT();
+
+	return status;
+}
+
 

+ 34 - 0
components/target_if/pmo/inc/target_if_pmo.h

@@ -100,6 +100,40 @@ QDF_STATUS target_if_pmo_set_mc_filter_req(struct wlan_objmgr_vdev *vdev,
 QDF_STATUS target_if_pmo_clear_mc_filter_req(struct wlan_objmgr_vdev *vdev,
 		struct qdf_mac_addr multicast_addr);
 
+/**
+ * target_if_pmo_get_multiple_mc_filter_support() - get multiple mc filter
+ *						    request fw support
+ * @psoc: the psoc containing the vdev to configure
+ *
+ * Return: true if fw supports else false
+ */
+bool target_if_pmo_get_multiple_mc_filter_support(
+		struct wlan_objmgr_psoc *psoc);
+
+/**
+ * target_if_pmo_set_multiple_mc_filter_req() - set multiple mcast filter
+ *						command to fw
+ * @vdev: objmgr vdev handle
+ * @multicastAddr: mcast address
+ *
+ * Return: 0 for success or error code
+ */
+QDF_STATUS target_if_pmo_set_multiple_mc_filter_req(
+		struct wlan_objmgr_vdev *vdev,
+		struct pmo_mc_addr_list *mc_list);
+
+/**
+ * target_if_pmo_clear_multiple_mc_filter_req() - clear multiple mcast
+ *						  filter command to fw
+ * @vdev: objmgr vdev handle
+ * @multicastAddr: mcast address
+ *
+ * Return: 0 for success or error code
+ */
+QDF_STATUS target_if_pmo_clear_multiple_mc_filter_req(
+		struct wlan_objmgr_vdev *vdev,
+		struct pmo_mc_addr_list *mc_list);
+
 /**
  * target_if_pmo_send_ra_filter_req() - set RA filter pattern in fw
  * @vdev: objmgr vdev handle

+ 6 - 0
components/target_if/pmo/src/target_if_pmo_main.c

@@ -49,6 +49,12 @@ void target_if_pmo_register_tx_ops(struct wlan_pmo_tx_ops *pmo_tx_ops)
 		target_if_pmo_set_mc_filter_req;
 	pmo_tx_ops->send_clear_mc_filter_req =
 		target_if_pmo_clear_mc_filter_req;
+	pmo_tx_ops->get_multiple_mc_filter_support =
+		target_if_pmo_get_multiple_mc_filter_support;
+	pmo_tx_ops->send_set_multiple_mc_filter_req =
+		target_if_pmo_set_multiple_mc_filter_req;
+	pmo_tx_ops->send_clear_multiple_mc_filter_req =
+		target_if_pmo_clear_multiple_mc_filter_req;
 	pmo_tx_ops->send_ra_filter_req =
 		target_if_pmo_send_ra_filter_req;
 	pmo_tx_ops->send_gtk_offload_req =

+ 83 - 0
components/target_if/pmo/src/target_if_pmo_mc_addr_filtering.c

@@ -88,4 +88,87 @@ QDF_STATUS target_if_pmo_clear_mc_filter_req(
 
 }
 
+bool target_if_pmo_get_multiple_mc_filter_support(
+		struct wlan_objmgr_psoc *psoc)
+{
+	return WMI_SERVICE_IS_ENABLED(psoc->service_param.service_bitmap,
+				      WMI_SERVICE_MULTIPLE_MCAST_FILTER_SET);
+}
+
+QDF_STATUS target_if_pmo_set_multiple_mc_filter_req(
+		struct wlan_objmgr_vdev *vdev,
+		struct pmo_mc_addr_list *mc_list)
+{
+	uint8_t vdev_id;
+	struct wlan_objmgr_psoc *psoc;
+	struct pmo_mcast_filter_params filter_params;
+	QDF_STATUS status;
+
+	if (!vdev) {
+		target_if_err("vdev ptr passed is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	vdev_id = wlan_vdev_get_id(vdev);
+	if (!psoc) {
+		target_if_err("psoc handle is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	filter_params.multicast_addr_cnt = mc_list->mc_cnt;
+	qdf_mem_copy(filter_params.multicast_addr,
+		     mc_list->mc_addr,
+		     mc_list->mc_cnt * ATH_MAC_LEN);
+	/* add one/multiple mc list */
+	filter_params.action = 1;
+
+	status = wmi_unified_multiple_add_clear_mcbc_filter_cmd(
+			GET_WMI_HDL_FROM_PSOC(psoc),
+			vdev_id,
+			&filter_params);
+	if (status)
+		target_if_err("Failed to send add/clear mcbc filter cmd");
+
+	return status;
+}
+
+QDF_STATUS target_if_pmo_clear_multiple_mc_filter_req(
+		struct wlan_objmgr_vdev *vdev,
+		struct pmo_mc_addr_list *mc_list)
+{
+	uint8_t vdev_id;
+	struct wlan_objmgr_psoc *psoc;
+	struct pmo_mcast_filter_params filter_params;
+	QDF_STATUS status;
+
+	if (!vdev) {
+		target_if_err("vdev ptr passed is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	vdev_id = wlan_vdev_get_id(vdev);
+	if (!psoc) {
+		target_if_err("psoc handle is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	filter_params.multicast_addr_cnt = mc_list->mc_cnt;
+	qdf_mem_copy(filter_params.multicast_addr,
+		     mc_list->mc_addr,
+		     mc_list->mc_cnt * ATH_MAC_LEN);
+	/* delete one/multiple mc list */
+	filter_params.action = 0;
+
+	status = wmi_unified_multiple_add_clear_mcbc_filter_cmd(
+			GET_WMI_HDL_FROM_PSOC(psoc),
+			vdev_id,
+			&filter_params);
+	if (status)
+		target_if_err("Failed to send add/clear mcbc filter cmd");
+
+	return status;
+}
+