diff --git a/components/pmo/core/src/wlan_pmo_mc_addr_filtering.c b/components/pmo/core/src/wlan_pmo_mc_addr_filtering.c index 3076632ab4..76c0c7ee0b 100644 --- a/components/pmo/core/src/wlan_pmo_mc_addr_filtering.c +++ b/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(); diff --git a/components/pmo/dispatcher/inc/wlan_pmo_mc_addr_filtering_public_struct.h b/components/pmo/dispatcher/inc/wlan_pmo_mc_addr_filtering_public_struct.h index 8607c17131..43d6e603bf 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_mc_addr_filtering_public_struct.h +++ b/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_ */ diff --git a/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h b/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h index 4be33ff9df..44b04e6988 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h +++ b/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); diff --git a/components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h b/components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h index 0ba54992e4..94a5992194 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h +++ b/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 diff --git a/components/pmo/dispatcher/src/wlan_pmo_tgt_mc_addr_filtering.c b/components/pmo/dispatcher/src/wlan_pmo_tgt_mc_addr_filtering.c index 9cc05636c1..8cb771a817 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_tgt_mc_addr_filtering.c +++ b/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; +} + diff --git a/components/target_if/pmo/inc/target_if_pmo.h b/components/target_if/pmo/inc/target_if_pmo.h index cb3bea6f5a..40d2349f7a 100644 --- a/components/target_if/pmo/inc/target_if_pmo.h +++ b/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 diff --git a/components/target_if/pmo/src/target_if_pmo_main.c b/components/target_if/pmo/src/target_if_pmo_main.c index 6e63d045e8..fb55fb144c 100644 --- a/components/target_if/pmo/src/target_if_pmo_main.c +++ b/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 = diff --git a/components/target_if/pmo/src/target_if_pmo_mc_addr_filtering.c b/components/target_if/pmo/src/target_if_pmo_mc_addr_filtering.c index bd3b29b8ae..978351b7c3 100644 --- a/components/target_if/pmo/src/target_if_pmo_mc_addr_filtering.c +++ b/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; +} +