diff options
author | Yin, Fengwei <fengwei.yin@linaro.org> | 2015-10-23 20:57:04 +0800 |
---|---|---|
committer | Yin, Fengwei <fengwei.yin@linaro.org> | 2015-10-23 20:57:04 +0800 |
commit | 385568061f26e2c1f925b2d1fd067cc45a2b50de (patch) | |
tree | f0e553e469d168ff609c2d7a8ba76af346a39a16 | |
parent | 5a6018da3c4915cda70e1ccebedf28d7042a2194 (diff) |
wcn36xx: enable arp offload.arp_offload
Signed-off-by: Yin, Fengwei <fengwei.yin@linaro.org>
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/main.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/smd.c | 84 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/smd.h | 4 |
3 files changed, 102 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index bbd4eca5e9f1..3caa75109710 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -587,6 +587,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf, u32 changed) { + int i; struct wcn36xx *wcn = hw->priv; struct sk_buff *skb = NULL; u16 tim_off, tim_len; @@ -596,6 +597,14 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", vif, changed); + pr_info("%s: mac bss info changed vif %p changed 0x%08x\n", __func__, + vif, changed); + + pr_info("%s: arp_addr_cnt: %d\n", __func__, bss_conf->arp_addr_cnt); + for (i = 0; i < bss_conf->arp_addr_cnt; i++) + pr_info("%s: ip[%d]: 0x%x\n", __func__, i, bss_conf->arp_addr_list[i]); + + if (changed & BSS_CHANGED_BEACON_INFO) { wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed dtim period %d\n", @@ -604,6 +613,11 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, vif_priv->dtim_period = bss_conf->dtim_period; } + if (changed & BSS_CHANGED_ARP_FILTER) { + pr_info("enable arp offload\n"); + wcn36xx_smd_arp_offload_enable(wcn, vif, bss_conf); + } + if (changed & BSS_CHANGED_PS) { wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss PS set %d\n", diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index d950f286a9d5..26ecd1b18608 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1696,6 +1696,89 @@ out: mutex_unlock(&wcn->hal_mutex); return ret; } + +/* Notice: This function should be called after associated, or else it + * will be invalid + */ +int wcn36xx_smd_arp_offload_enable(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) +{ + struct wcn36xx_hal_host_offload_req_msg msg_body; + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + int ret = 0; + + if (bss_conf->arp_addr_cnt == 0) { + pr_err("%s called before IP address is allocated\n", + __func__); + return -EINVAL; + } + + mutex_lock(&wcn->hal_mutex); + INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ); + + msg_body.host_offload_params.offload_Type = + WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD; + msg_body.host_offload_params.enable = + WCN36XX_HAL_OFFLOAD_ENABLE; +#define IPV4 msg_body.host_offload_params.u.host_ipv4_addr + IPV4[0] = bss_conf->arp_addr_list[0] & 0xff; + IPV4[1] = (bss_conf->arp_addr_list[0] >> 8) & 0xff; + IPV4[2] = (bss_conf->arp_addr_list[0] >> 16) & 0xff; + IPV4[3] = (bss_conf->arp_addr_list[0] >> 24) & 0xff; + pr_info("ip: %d.%d.%d.%d\n", IPV4[0], IPV4[1], IPV4[2], IPV4[3]); + msg_body.ns_offload_params.bss_index = vif_priv->bss_index; + + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); + + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); + if (ret) { + wcn36xx_err("Sending host offload req failed\n"); + } + + mutex_unlock(&wcn->hal_mutex); + return ret; +} + +int wcn36xx_smd_arp_offload_disable(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) +{ + struct wcn36xx_hal_host_offload_req_msg msg_body; + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; + int ret = 0; + + if (bss_conf->arp_addr_cnt == 0) { + pr_err("%s called before IP address is allocated\n", + __func__); + return -EINVAL; + } + + mutex_lock(&wcn->hal_mutex); + INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ); + + msg_body.host_offload_params.offload_Type = + WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD; + msg_body.host_offload_params.enable = + WCN36XX_HAL_OFFLOAD_DISABLE; +#define IP msg_body.host_offload_params.u.host_ipv4_addr + IP[0] = bss_conf->arp_addr_list[0] & 0xff; + IP[1] = (bss_conf->arp_addr_list[0] >> 8) & 0xff; + IP[2] = (bss_conf->arp_addr_list[0] >> 16) & 0xff; + IP[3] = (bss_conf->arp_addr_list[0] >> 24) & 0xff; + msg_body.ns_offload_params.bss_index = vif_priv->bss_index; + + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); + + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); + if (ret) { + wcn36xx_err("Sending host offload req failed\n"); + } + + mutex_unlock(&wcn->hal_mutex); + return ret; +} + /* Notice: This function should be called after associated, or else it * will be invalid */ @@ -2143,6 +2226,7 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: case WCN36XX_HAL_CH_SWITCH_RSP: case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: + case WCN36XX_HAL_HOST_OFFLOAD_RSP: memcpy(wcn->hal_buf, buf, len); wcn->hal_rsp_len = len; complete(&wcn->hal_rsp_compl); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index 8361f9e3995b..90eb9ec39927 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -136,4 +136,8 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index); int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index); int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); + +int wcn36xx_smd_arp_offload_enable(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf); #endif /* _SMD_H_ */ |