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:
Mukul Sharma
2017-01-16 15:51:29 +05:30
committed by qcabuildsw
parent 3ba26b8747
commit ff2ac2e1e5
4 changed files with 151 additions and 158 deletions

View File

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

View File

@@ -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:

View File

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

View File

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