qcacld-3.0: Add support for mc addr list in PMO component
Add support for mc address list in PMO component. Change-Id: I711ff4a1394258400573ff6658605b1650832b0f CRs-Fixed: 2005103
This commit is contained in:
@@ -192,20 +192,42 @@ void hdd_disable_host_offloads(hdd_adapter_t *adapter,
|
|||||||
enum pmo_offload_trigger trigger);
|
enum pmo_offload_trigger trigger);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hdd_conf_mc_addr_filtering_enable() - enable MC address list in FW
|
* hdd_enable_mc_addr_filtering() - enable MC address list in FW
|
||||||
* @pAdapter: adapter whose MC list is being set
|
* @adapter: adapter whose MC list is being set
|
||||||
* @trigger: trigger reason for request
|
* @trigger: trigger reason for request
|
||||||
*
|
*
|
||||||
* Return: nothing
|
* Return: nothing
|
||||||
*/
|
*/
|
||||||
#ifdef WLAN_FEATURE_PACKET_FILTERING
|
void hdd_enable_mc_addr_filtering(hdd_adapter_t *adapter,
|
||||||
void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set);
|
enum pmo_offload_trigger trigger);
|
||||||
#else
|
|
||||||
static inline void
|
/**
|
||||||
wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set)
|
* hdd_disable_mc_addr_filtering() - disable MC address list in FW
|
||||||
{
|
* @adapter: adapter whose MC list is being set
|
||||||
}
|
* @trigger: trigger reason for request
|
||||||
#endif
|
*
|
||||||
|
* Return: nothing
|
||||||
|
*/
|
||||||
|
void hdd_disable_mc_addr_filtering(hdd_adapter_t *adapter,
|
||||||
|
enum pmo_offload_trigger trigger);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hdd_cache_mc_addr_list() - API to cache MC address list
|
||||||
|
* @mc_list_config: set of mc address list configurations
|
||||||
|
*
|
||||||
|
* Return: 0 on success else error code
|
||||||
|
*/
|
||||||
|
int hdd_cache_mc_addr_list(struct pmo_mc_addr_list_params *mc_list_config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hdd_disable_and_flush_mc_addr_list() - API to Disable & Flush cached MC list
|
||||||
|
* @adapter: adapter whose MC list is being set
|
||||||
|
* @trigger: trigger reason for request
|
||||||
|
*
|
||||||
|
* Return: nothing
|
||||||
|
*/
|
||||||
|
void hdd_disable_and_flush_mc_addr_list(hdd_adapter_t *adapter,
|
||||||
|
enum pmo_offload_trigger trigger);
|
||||||
|
|
||||||
int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
|
int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
|
||||||
struct cfg80211_wowlan *wow);
|
struct cfg80211_wowlan *wow);
|
||||||
|
@@ -4771,13 +4771,14 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
|
|||||||
case eCSR_ROAM_DISASSOCIATED:
|
case eCSR_ROAM_DISASSOCIATED:
|
||||||
{
|
{
|
||||||
hdd_info("****eCSR_ROAM_DISASSOCIATED****");
|
hdd_info("****eCSR_ROAM_DISASSOCIATED****");
|
||||||
qdf_ret_status =
|
|
||||||
hdd_dis_connect_handler(pAdapter, pRoamInfo, roamId,
|
|
||||||
roamStatus, roamResult);
|
|
||||||
/* Call to clear any MC Addr List filter applied after
|
/* Call to clear any MC Addr List filter applied after
|
||||||
* successful connection.
|
* successful connection.
|
||||||
*/
|
*/
|
||||||
wlan_hdd_set_mc_addr_list(pAdapter, false);
|
hdd_disable_and_flush_mc_addr_list(pAdapter,
|
||||||
|
pmo_peer_disconnect);
|
||||||
|
qdf_ret_status =
|
||||||
|
hdd_dis_connect_handler(pAdapter, pRoamInfo, roamId,
|
||||||
|
roamStatus, roamResult);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case eCSR_ROAM_IBSS_LEAVE:
|
case eCSR_ROAM_IBSS_LEAVE:
|
||||||
|
@@ -2309,81 +2309,73 @@ void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
|
|||||||
static void __hdd_set_multicast_list(struct net_device *dev)
|
static void __hdd_set_multicast_list(struct net_device *dev)
|
||||||
{
|
{
|
||||||
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
|
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
|
||||||
int mc_count;
|
|
||||||
int i = 0, status;
|
int i = 0, status;
|
||||||
struct netdev_hw_addr *ha;
|
struct netdev_hw_addr *ha;
|
||||||
hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
|
hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
|
||||||
static const uint8_t ipv6_router_solicitation[]
|
struct pmo_mc_addr_list_params *mc_list_request = NULL;
|
||||||
= {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
|
struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
|
||||||
|
int mc_count = 0;
|
||||||
|
|
||||||
ENTER_DEV(dev);
|
ENTER_DEV(dev);
|
||||||
|
|
||||||
if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
|
if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
status = wlan_hdd_validate_context(hdd_ctx);
|
status = wlan_hdd_validate_context(hdd_ctx);
|
||||||
if (0 != status)
|
if (0 != status)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
|
mc_list_request = qdf_mem_malloc(sizeof(*mc_list_request));
|
||||||
|
if (!mc_list_request) {
|
||||||
|
hdd_notice("Cannot allocate mc_list_request");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (dev->flags & IFF_ALLMULTI) {
|
if (dev->flags & IFF_ALLMULTI) {
|
||||||
hdd_notice("allow all multicast frames");
|
hdd_notice("allow all multicast frames");
|
||||||
adapter->mc_addr_list.mc_cnt = 0;
|
hdd_disable_and_flush_mc_addr_list(adapter,
|
||||||
|
pmo_mc_list_change_notify);
|
||||||
} else {
|
} else {
|
||||||
mc_count = netdev_mc_count(dev);
|
mc_count = netdev_mc_count(dev);
|
||||||
hdd_notice("mc_count : %u", mc_count);
|
if (mc_count > pmo_ucfg_max_mc_addr_supported(psoc)) {
|
||||||
|
|
||||||
if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
|
|
||||||
hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
|
hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
|
||||||
WLAN_HDD_MAX_MC_ADDR_LIST);
|
pmo_ucfg_max_mc_addr_supported(psoc));
|
||||||
wlan_hdd_set_mc_addr_list(adapter, false);
|
hdd_disable_and_flush_mc_addr_list(adapter,
|
||||||
adapter->mc_addr_list.mc_cnt = 0;
|
pmo_mc_list_change_notify);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter->mc_addr_list.mc_cnt = mc_count;
|
|
||||||
|
|
||||||
netdev_for_each_mc_addr(ha, dev) {
|
netdev_for_each_mc_addr(ha, dev) {
|
||||||
hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
|
hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
|
||||||
i, MAC_ADDR_ARRAY(ha->addr));
|
i, MAC_ADDR_ARRAY(ha->addr));
|
||||||
|
|
||||||
if (i == mc_count)
|
if (i == mc_count)
|
||||||
break;
|
break;
|
||||||
/*
|
memset(&(mc_list_request->mc_addr[i].bytes),
|
||||||
* Skip following addresses:
|
0, ETH_ALEN);
|
||||||
* 1)IPv6 router solicitation address
|
memcpy(&(mc_list_request->mc_addr[i].bytes),
|
||||||
* 2)Any other address pattern if its set during
|
ha->addr, ETH_ALEN);
|
||||||
* RXFILTER REMOVE driver command based on
|
hdd_info("mlist[%d] = %pM", i,
|
||||||
* addr_filter_pattern
|
mc_list_request->mc_addr[i].bytes);
|
||||||
*/
|
|
||||||
if ((!memcmp(ha->addr, ipv6_router_solicitation,
|
|
||||||
ETH_ALEN)) ||
|
|
||||||
(adapter->addr_filter_pattern && (!memcmp(ha->addr,
|
|
||||||
&adapter->addr_filter_pattern, 1)))) {
|
|
||||||
hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
|
|
||||||
MAC_ADDR_ARRAY(ha->addr));
|
|
||||||
adapter->mc_addr_list.mc_cnt--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&(adapter->mc_addr_list.addr[i][0]), 0,
|
|
||||||
ETH_ALEN);
|
|
||||||
memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
|
|
||||||
ETH_ALEN);
|
|
||||||
hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i,
|
|
||||||
MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hdd_ctx->config->active_mode_offload) {
|
|
||||||
hdd_info("enable mc filtering");
|
mc_list_request->psoc = psoc;
|
||||||
wlan_hdd_set_mc_addr_list(adapter, true);
|
mc_list_request->vdev_id = adapter->sessionId;
|
||||||
|
mc_list_request->count = mc_count;
|
||||||
|
status = hdd_cache_mc_addr_list(mc_list_request);
|
||||||
|
if (status == 0) {
|
||||||
|
hdd_enable_mc_addr_filtering(adapter,
|
||||||
|
pmo_mc_list_change_notify);
|
||||||
} else {
|
} else {
|
||||||
hdd_info("skip mc filtering enable it during cfg80211 suspend");
|
hdd_err("error while caching mc list");
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
if (mc_list_request)
|
||||||
|
qdf_mem_free(mc_list_request);
|
||||||
EXIT();
|
EXIT();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
|
* hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
|
||||||
* @dev: pointer to net_device
|
* @dev: pointer to net_device
|
||||||
|
@@ -546,7 +546,7 @@ void hdd_enable_host_offloads(hdd_adapter_t *adapter,
|
|||||||
hdd_conf_gtk_offload(adapter, true);
|
hdd_conf_gtk_offload(adapter, true);
|
||||||
hdd_enable_arp_offload(adapter, trigger);
|
hdd_enable_arp_offload(adapter, trigger);
|
||||||
hdd_enable_ns_offload(adapter, trigger);
|
hdd_enable_ns_offload(adapter, trigger);
|
||||||
wlan_hdd_set_mc_addr_list(adapter, true);
|
hdd_enable_mc_addr_filtering(adapter, trigger);
|
||||||
out:
|
out:
|
||||||
EXIT();
|
EXIT();
|
||||||
|
|
||||||
@@ -572,7 +572,7 @@ void hdd_disable_host_offloads(hdd_adapter_t *adapter,
|
|||||||
hdd_conf_gtk_offload(adapter, false);
|
hdd_conf_gtk_offload(adapter, false);
|
||||||
hdd_disable_arp_offload(adapter, trigger);
|
hdd_disable_arp_offload(adapter, trigger);
|
||||||
hdd_disable_ns_offload(adapter, trigger);
|
hdd_disable_ns_offload(adapter, trigger);
|
||||||
wlan_hdd_set_mc_addr_list(adapter, false);
|
hdd_disable_mc_addr_filtering(adapter, trigger);
|
||||||
out:
|
out:
|
||||||
EXIT();
|
EXIT();
|
||||||
|
|
||||||
@@ -927,108 +927,86 @@ out:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WLAN_FEATURE_PACKET_FILTERING
|
void hdd_enable_mc_addr_filtering(hdd_adapter_t *adapter,
|
||||||
/**
|
enum pmo_offload_trigger trigger)
|
||||||
* wlan_hdd_set_mc_addr_list() - set MC address list in FW
|
|
||||||
* @pAdapter: adapter whose MC list is being set
|
|
||||||
* @set: flag which indicates if addresses are being set or cleared
|
|
||||||
*/
|
|
||||||
void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set)
|
|
||||||
{
|
{
|
||||||
uint8_t i;
|
hdd_context_t *hdd_ctx = (hdd_context_t *)adapter->pHddCtx;
|
||||||
tpSirRcvFltMcAddrList pMulticastAddrs = NULL;
|
QDF_STATUS status;
|
||||||
tHalHandle hHal = NULL;
|
struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
|
||||||
hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
|
|
||||||
hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
|
|
||||||
|
|
||||||
ENTER();
|
ENTER();
|
||||||
|
if (wlan_hdd_validate_context(hdd_ctx))
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (wlan_hdd_validate_context(pHddCtx))
|
status = pmo_ucfg_enable_mc_addr_filtering_in_fwr(psoc,
|
||||||
return;
|
adapter->sessionId, trigger);
|
||||||
|
if (status != QDF_STATUS_SUCCESS)
|
||||||
hHal = pHddCtx->hHal;
|
hdd_info("failed to enable mc list status %d", status);
|
||||||
|
out:
|
||||||
if (NULL == hHal) {
|
|
||||||
hdd_err("HAL Handle is NULL");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sta_ctx) {
|
|
||||||
hdd_err("sta_ctx is NULL");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if INI is enabled or not, other wise just return */
|
|
||||||
if (!pHddCtx->config->fEnableMCAddrList) {
|
|
||||||
hdd_notice("gMCAddrListEnable is not enabled in INI");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pMulticastAddrs = qdf_mem_malloc(sizeof(tSirRcvFltMcAddrList));
|
|
||||||
if (NULL == pMulticastAddrs) {
|
|
||||||
hdd_err("Could not allocate Memory");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pMulticastAddrs->action = set;
|
|
||||||
|
|
||||||
if (set) {
|
|
||||||
/*
|
|
||||||
* Following pre-conditions should be satisfied before we
|
|
||||||
* configure the MC address list.
|
|
||||||
*/
|
|
||||||
if (pAdapter->mc_addr_list.mc_cnt &&
|
|
||||||
(((pAdapter->device_mode == QDF_STA_MODE ||
|
|
||||||
pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
|
|
||||||
hdd_conn_is_connected(sta_ctx)) ||
|
|
||||||
(WLAN_HDD_IS_NDI(pAdapter) &&
|
|
||||||
WLAN_HDD_IS_NDI_CONNECTED(pAdapter)))) {
|
|
||||||
|
|
||||||
pMulticastAddrs->ulMulticastAddrCnt =
|
|
||||||
pAdapter->mc_addr_list.mc_cnt;
|
|
||||||
|
|
||||||
for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++) {
|
|
||||||
memcpy(pMulticastAddrs->multicastAddr[i].bytes,
|
|
||||||
pAdapter->mc_addr_list.addr[i],
|
|
||||||
sizeof(pAdapter->mc_addr_list.addr[i]));
|
|
||||||
hdd_info("%s multicast filter: addr ="
|
|
||||||
MAC_ADDRESS_STR,
|
|
||||||
set ? "setting" : "clearing",
|
|
||||||
MAC_ADDR_ARRAY(pMulticastAddrs->
|
|
||||||
multicastAddr[i].bytes));
|
|
||||||
}
|
|
||||||
/* Set multicast filter */
|
|
||||||
sme_8023_multicast_list(hHal, pAdapter->sessionId,
|
|
||||||
pMulticastAddrs);
|
|
||||||
} else {
|
|
||||||
hdd_info("MC address list not sent to FW, cnt: %d",
|
|
||||||
pAdapter->mc_addr_list.mc_cnt);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Need to clear only if it was previously configured */
|
|
||||||
if (pAdapter->mc_addr_list.isFilterApplied) {
|
|
||||||
pMulticastAddrs->ulMulticastAddrCnt =
|
|
||||||
pAdapter->mc_addr_list.mc_cnt;
|
|
||||||
for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++) {
|
|
||||||
memcpy(pMulticastAddrs->multicastAddr[i].bytes,
|
|
||||||
pAdapter->mc_addr_list.addr[i],
|
|
||||||
sizeof(pAdapter->mc_addr_list.addr[i]));
|
|
||||||
}
|
|
||||||
sme_8023_multicast_list(hHal, pAdapter->sessionId,
|
|
||||||
pMulticastAddrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
/* MAddrCnt is MulticastAddrCnt */
|
|
||||||
hdd_notice("smeSessionId:%d; set:%d; MCAdddrCnt :%d",
|
|
||||||
pAdapter->sessionId, set,
|
|
||||||
pMulticastAddrs->ulMulticastAddrCnt);
|
|
||||||
|
|
||||||
pAdapter->mc_addr_list.isFilterApplied = set ? true : false;
|
|
||||||
qdf_mem_free(pMulticastAddrs);
|
|
||||||
|
|
||||||
EXIT();
|
EXIT();
|
||||||
return;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdd_disable_mc_addr_filtering(hdd_adapter_t *adapter,
|
||||||
|
enum pmo_offload_trigger trigger)
|
||||||
|
{
|
||||||
|
hdd_context_t *hdd_ctx = (hdd_context_t *)adapter->pHddCtx;
|
||||||
|
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||||
|
struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
|
||||||
|
|
||||||
|
ENTER();
|
||||||
|
if (wlan_hdd_validate_context(hdd_ctx))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
status = pmo_ucfg_disable_mc_addr_filtering_in_fwr(psoc,
|
||||||
|
adapter->sessionId, trigger);
|
||||||
|
if (status != QDF_STATUS_SUCCESS)
|
||||||
|
hdd_info("failed to disable mc list status %d", status);
|
||||||
|
out:
|
||||||
|
EXIT();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int hdd_cache_mc_addr_list(struct pmo_mc_addr_list_params *mc_list_config)
|
||||||
|
{
|
||||||
|
QDF_STATUS status;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ENTER();
|
||||||
|
/* cache mc addr list */
|
||||||
|
status = pmo_ucfg_cache_mc_addr_list(mc_list_config);
|
||||||
|
if (status != QDF_STATUS_SUCCESS) {
|
||||||
|
hdd_info("fail to cache mc list status %d", status);
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
EXIT();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hdd_disable_and_flush_mc_addr_list(hdd_adapter_t *adapter,
|
||||||
|
enum pmo_offload_trigger trigger)
|
||||||
|
{
|
||||||
|
hdd_context_t *hdd_ctx = (hdd_context_t *)adapter->pHddCtx;
|
||||||
|
struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
|
||||||
|
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
ENTER();
|
||||||
|
/* disable mc list first */
|
||||||
|
status = pmo_ucfg_disable_mc_addr_filtering_in_fwr(psoc,
|
||||||
|
adapter->sessionId, trigger);
|
||||||
|
if (status != QDF_STATUS_SUCCESS)
|
||||||
|
hdd_info("fail to disable mc list");
|
||||||
|
|
||||||
|
/* flush mc list */
|
||||||
|
status = pmo_ucfg_flush_mc_addr_list(psoc, adapter->sessionId);
|
||||||
|
if (status != QDF_STATUS_SUCCESS)
|
||||||
|
hdd_info("fail to flush mc list status %d", status);
|
||||||
|
EXIT();
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hdd_conf_suspend_ind() - Send Suspend notification
|
* hdd_conf_suspend_ind() - Send Suspend notification
|
||||||
|
Reference in New Issue
Block a user