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
commit ff2ac2e1e5
4 changed files with 141 additions and 148 deletions

View file

@ -192,20 +192,42 @@ void hdd_disable_host_offloads(hdd_adapter_t *adapter,
enum pmo_offload_trigger trigger);
/**
* hdd_conf_mc_addr_filtering_enable() - enable MC address list in FW
* @pAdapter: adapter whose MC list is being set
* hdd_enable_mc_addr_filtering() - enable MC address list in FW
* @adapter: adapter whose MC list is being set
* @trigger: trigger reason for request
*
* Return: nothing
*/
#ifdef WLAN_FEATURE_PACKET_FILTERING
void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set);
#else
static inline void
wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set)
{
}
#endif
void hdd_enable_mc_addr_filtering(hdd_adapter_t *adapter,
enum pmo_offload_trigger trigger);
/**
* hdd_disable_mc_addr_filtering() - disable MC address list in FW
* @adapter: adapter whose MC list is being set
* @trigger: trigger reason for request
*
* 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,
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:
{
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
* 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;
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)
{
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
int mc_count;
int i = 0, status;
struct netdev_hw_addr *ha;
hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
static const uint8_t ipv6_router_solicitation[]
= {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
struct pmo_mc_addr_list_params *mc_list_request = NULL;
struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
int mc_count = 0;
ENTER_DEV(dev);
if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
return;
goto out;
status = wlan_hdd_validate_context(hdd_ctx);
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) {
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 {
mc_count = netdev_mc_count(dev);
hdd_notice("mc_count : %u", mc_count);
if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
if (mc_count > pmo_ucfg_max_mc_addr_supported(psoc)) {
hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
WLAN_HDD_MAX_MC_ADDR_LIST);
wlan_hdd_set_mc_addr_list(adapter, false);
adapter->mc_addr_list.mc_cnt = 0;
return;
pmo_ucfg_max_mc_addr_supported(psoc));
hdd_disable_and_flush_mc_addr_list(adapter,
pmo_mc_list_change_notify);
goto out;
}
adapter->mc_addr_list.mc_cnt = mc_count;
netdev_for_each_mc_addr(ha, dev) {
hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
i, MAC_ADDR_ARRAY(ha->addr));
if (i == mc_count)
break;
/*
* Skip following addresses:
* 1)IPv6 router solicitation address
* 2)Any other address pattern if its set during
* RXFILTER REMOVE driver command based on
* addr_filter_pattern
*/
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]));
memset(&(mc_list_request->mc_addr[i].bytes),
0, ETH_ALEN);
memcpy(&(mc_list_request->mc_addr[i].bytes),
ha->addr, ETH_ALEN);
hdd_info("mlist[%d] = %pM", i,
mc_list_request->mc_addr[i].bytes);
i++;
}
}
if (hdd_ctx->config->active_mode_offload) {
hdd_info("enable mc filtering");
wlan_hdd_set_mc_addr_list(adapter, true);
mc_list_request->psoc = psoc;
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 {
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();
return;
}
/**
* hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
* @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_enable_arp_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:
EXIT();
@ -572,7 +572,7 @@ void hdd_disable_host_offloads(hdd_adapter_t *adapter,
hdd_conf_gtk_offload(adapter, false);
hdd_disable_arp_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:
EXIT();
@ -927,108 +927,86 @@ out:
}
#ifdef WLAN_FEATURE_PACKET_FILTERING
/**
* 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)
void hdd_enable_mc_addr_filtering(hdd_adapter_t *adapter,
enum pmo_offload_trigger trigger)
{
uint8_t i;
tpSirRcvFltMcAddrList pMulticastAddrs = NULL;
tHalHandle hHal = NULL;
hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
hdd_context_t *hdd_ctx = (hdd_context_t *)adapter->pHddCtx;
QDF_STATUS status;
struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
ENTER();
if (wlan_hdd_validate_context(hdd_ctx))
goto out;
if (wlan_hdd_validate_context(pHddCtx))
return;
hHal = pHddCtx->hHal;
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);
status = pmo_ucfg_enable_mc_addr_filtering_in_fwr(psoc,
adapter->sessionId, trigger);
if (status != QDF_STATUS_SUCCESS)
hdd_info("failed to enable mc list status %d", status);
out:
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