diff options
Diffstat (limited to 'drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c')
-rw-r--r-- | drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c | 491 |
1 files changed, 305 insertions, 186 deletions
diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c index 55eb2c43e756..6369f17e08d3 100644 --- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c @@ -2241,6 +2241,12 @@ static int wma_vdev_stop_ind(tp_wma_handle wma, u_int8_t *buf) goto free_req_msg; } + /* Clear arp and ns offload cache */ + vos_mem_zero(&iface->ns_offload_req, + sizeof(iface->ns_offload_req)); + vos_mem_zero(&iface->arp_offload_req, + sizeof(iface->arp_offload_req)); + #ifdef QCA_IBSS_SUPPORT if ( wma_is_vdev_in_ibss_mode(wma, resp_event->vdev_id)) wma_delete_all_ibss_peers(wma, resp_event->vdev_id); @@ -21136,7 +21142,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data, WMA_LOGD("wow_buf_pkt_len: %u", buf_len); if (buf_len >= ADF_NBUF_TRAC_IPV4_OFFSET) - WMA_LOGE("Src_mac: " MAC_ADDRESS_STR " Dst_mac: " MAC_ADDRESS_STR, + WMA_LOGE("SA: " MAC_ADDRESS_STR " DA: " MAC_ADDRESS_STR, MAC_ADDR_ARRAY(data + ADF_NBUF_SRC_MAC_OFFSET), MAC_ADDR_ARRAY(data)); else @@ -21148,7 +21154,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data, case ADF_PROTO_EAPOL_M2: case ADF_PROTO_EAPOL_M3: case ADF_PROTO_EAPOL_M4: - WMA_LOGE("WOW Wakeup: %s rcvd", + WMA_LOGE("WOW %s rcvd", wma_pkt_proto_subtype_to_string(proto_subtype)); if (buf_len >= WMA_EAPOL_INFO_GET_MIN_LEN) { pkt_len = (uint16_t)(*(uint16_t *)(data + @@ -21169,7 +21175,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data, case ADF_PROTO_DHCP_RELEASE: case ADF_PROTO_DHCP_INFORM: case ADF_PROTO_DHCP_DECLINE: - WMA_LOGE("WOW Wakeup: %s rcvd", + WMA_LOGE("WOW %s rcvd", wma_pkt_proto_subtype_to_string(proto_subtype)); if (buf_len >= WMA_DHCP_INFO_GET_MIN_LEN) { pkt_len = (uint16_t)(*(uint16_t *)(data + @@ -21184,13 +21190,13 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data, case ADF_PROTO_ARP_REQ: case ADF_PROTO_ARP_RES: - WMA_LOGE("WOW Wakeup: %s rcvd", + WMA_LOGE("WOW %s rcvd", wma_pkt_proto_subtype_to_string(proto_subtype)); break; case ADF_PROTO_ICMP_REQ: case ADF_PROTO_ICMP_RES: - WMA_LOGE("WOW Wakeup: %s rcvd", + WMA_LOGE("WOW %s rcvd", wma_pkt_proto_subtype_to_string(proto_subtype)); if (buf_len >= WMA_IPV4_PKT_INFO_GET_MIN_LEN) { pkt_len = (uint16_t)(*(uint16_t *)(data + @@ -21205,14 +21211,14 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data, case ADF_PROTO_ICMPV6_REQ: case ADF_PROTO_ICMPV6_RES: - WMA_LOGE("WOW Wakeup: %s rcvd", + WMA_LOGE("WOW %s rcvd", wma_pkt_proto_subtype_to_string(proto_subtype)); if (buf_len >= WMA_IPV6_PKT_INFO_GET_MIN_LEN) { pkt_len = (uint16_t)(*(uint16_t *)(data + IPV6_PKT_LEN_OFFSET)); seq_num = (uint16_t)(*(uint16_t *)(data + ICMPV6_SEQ_NUM_OFFSET)); - WMA_LOGE("Pkt_len: %u, Seq_num: %u", + WMA_LOGE("len: %u, SN: %u", adf_os_cpu_to_be16(pkt_len), adf_os_cpu_to_be16(seq_num)); } @@ -21220,7 +21226,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data, case ADF_PROTO_IPV4_UDP: case ADF_PROTO_IPV4_TCP: - WMA_LOGE("WOW Wakeup: %s rcvd", + WMA_LOGE("WOW %s rcvd", wma_pkt_proto_subtype_to_string(proto_subtype)); if (buf_len >= WMA_IPV4_PKT_INFO_GET_MIN_LEN) { pkt_len = (uint16_t)(*(uint16_t *)(data + @@ -21229,15 +21235,14 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data, IPV4_SRC_PORT_OFFSET)); dst_port = (uint16_t)(*(uint16_t *)(data + IPV4_DST_PORT_OFFSET)); - WMA_LOGE("Pkt_len: %u", - adf_os_cpu_to_be16(pkt_len)); - WMA_LOGE("src_port: %u, dst_port: %u", + WMA_LOGE("len: %u sport: %u dport: %u", + adf_os_cpu_to_be16(pkt_len), adf_os_cpu_to_be16(src_port), adf_os_cpu_to_be16(dst_port)); if (proto_subtype == ADF_PROTO_IPV4_TCP) { tcp_seq_num = (uint32_t)(*(uint32_t *)(data + IPV4_TCP_SEQ_NUM_OFFSET)); - WMA_LOGE("TCP_seq_num: %u", + WMA_LOGD("TCP SN: %u", adf_os_cpu_to_be32(tcp_seq_num)); } } @@ -21245,7 +21250,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data, case ADF_PROTO_IPV6_UDP: case ADF_PROTO_IPV6_TCP: - WMA_LOGE("WOW Wakeup: %s rcvd", + WMA_LOGE("WOW %s rcvd", wma_pkt_proto_subtype_to_string(proto_subtype)); if (buf_len >= WMA_IPV6_PKT_INFO_GET_MIN_LEN) { pkt_len = (uint16_t)(*(uint16_t *)(data + @@ -21254,15 +21259,14 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data, IPV6_SRC_PORT_OFFSET)); dst_port = (uint16_t)(*(uint16_t *)(data + IPV6_DST_PORT_OFFSET)); - WMA_LOGE("Pkt_len: %u", - adf_os_cpu_to_be16(pkt_len)); - WMA_LOGE("src_port: %u, dst_port: %u", + WMA_LOGE("len: %u sport: %u dport: %u", + adf_os_cpu_to_be16(pkt_len), adf_os_cpu_to_be16(src_port), adf_os_cpu_to_be16(dst_port)); if (proto_subtype == ADF_PROTO_IPV6_TCP) { tcp_seq_num = (uint32_t)(*(uint32_t *)(data + IPV6_TCP_SEQ_NUM_OFFSET)); - WMA_LOGE("TCP_seq_num: %u", + WMA_LOGD("TCP SN: %u", adf_os_cpu_to_be32(tcp_seq_num)); } } @@ -21270,8 +21274,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data, default: end: - WMA_LOGE("wow_buf_pkt_len: %u", buf_len); - WMA_LOGE("Unknown Packet or Insufficient packet buffer"); + WMA_LOGE("Unknown Packet or Insufficient packet buffer (len=%u)", buf_len); break; } } @@ -21407,12 +21410,10 @@ static int wma_wow_wakeup_host_event(void *handle, u_int8_t *event, wake_info = param_buf->fixed_param; - if ((wake_info->wake_reason != WOW_REASON_UNSPECIFIED) || - (wake_info->wake_reason == WOW_REASON_UNSPECIFIED && - !wmi_get_runtime_pm_inprogress(wma->wmi_handle))) - WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d", - wma_wow_wake_reason_str(wake_info->wake_reason, wma), + if (!wmi_get_runtime_pm_inprogress(wma->wmi_handle)) + WMA_LOGA("WOW (%d) %s vdev:%d", wake_info->wake_reason, + wma_wow_wake_reason_str(wake_info->wake_reason, wma), wake_info->vdev_id); vos_event_set(&wma->wma_resume_event); @@ -24604,8 +24605,12 @@ static VOS_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle, uint8_t vdev_id = 0; int i; - if(mcbc_param->ulMulticastAddrCnt <= 0) { - WMA_LOGW("Number of multicast addresses is 0"); + if (mcbc_param->ulMulticastAddrCnt <= 0 || + mcbc_param->ulMulticastAddrCnt > + CFG_TGT_MAX_MULTICAST_FILTER_ENTRIES) { + WMA_LOGE("Number of multicast addresses is: %u", + mcbc_param->ulMulticastAddrCnt); + WARN_ON(1); return VOS_STATUS_E_FAILURE; } @@ -24782,208 +24787,322 @@ out: } #endif -/* - * Function : wma_enable_arp_ns_offload - * Description : To configure ARP NS off load data to firmware - * when target goes to wow mode. - * Args : @wma - wma handle, @tpSirHostOffloadReq - - * pHostOffloadParams,@bool bArpOnly - * Returns : Returns Failure or Success based on WMI cmd. - * Comments : Since firware expects ARP and NS to be configured - * at a time, Arp info is cached in wma and send along - * with NS info to make both work. +/** + * wma_fill_arp_offload_params() - Fill ARP offload data + * @wma: wma handle + * @tpSirHostOffloadReq: offload request + * @buf_ptr: buffer pointer + * + * To fill ARP offload data to firmware + * when target goes to wow mode. + * + * Return: None + */ +static void wma_fill_arp_offload_params(tp_wma_handle wma, + tpSirHostOffloadReq hostoffloadreq, uint8_t **buf_ptr) +{ + + int32_t i; + WMI_ARP_OFFLOAD_TUPLE *arp_tuple; + bool enableOrDisable = hostoffloadreq->enableOrDisable; + + WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC, + (WMI_MAX_ARP_OFFLOADS*sizeof(WMI_ARP_OFFLOAD_TUPLE))); + *buf_ptr += WMI_TLV_HDR_SIZE; + for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) { + arp_tuple = (WMI_ARP_OFFLOAD_TUPLE *)*buf_ptr; + WMITLV_SET_HDR(&arp_tuple->tlv_header, + WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE, + WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE)); + + /* Fill data for ARP and NS in the first tupple for LA */ + if ((enableOrDisable & SIR_OFFLOAD_ENABLE) && (i == 0)) { + /* Copy the target ip addr and flags */ + arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID; + A_MEMCPY(&arp_tuple->target_ipaddr, + hostoffloadreq->params.hostIpv4Addr, + SIR_IPV4_ADDR_LEN); + WMA_LOGD("ARPOffload IP4 address: %pI4", + hostoffloadreq->params.hostIpv4Addr); + } + *buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE); + } +} + +#ifdef WLAN_NS_OFFLOAD +/** + * wma_fill_ns_offload_params() - Fill NS offload data + * @wma: wma handle + * @tpSirHostOffloadReq: offload request + * @buf_ptr: buffer pointer + * + * To fill NS offload data to firmware + * when target goes to wow mode. + * + * Return: None */ -static VOS_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, tpSirHostOffloadReq pHostOffloadParams, bool bArpOnly) +static void wma_fill_ns_offload_params(tp_wma_handle wma, + tpSirHostOffloadReq hostoffloadreq, uint8_t **buf_ptr) { + int32_t i; + WMI_NS_OFFLOAD_TUPLE *ns_tuple; + tSirNsOffloadReq ns_req; + + ns_req = hostoffloadreq->nsOffloadInfo; + WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC, + (WMI_MAX_NS_OFFLOADS*sizeof(WMI_NS_OFFLOAD_TUPLE))); + *buf_ptr += WMI_TLV_HDR_SIZE; + for (i = 0; i < WMI_MAX_NS_OFFLOADS; i++) { + ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)*buf_ptr; + WMITLV_SET_HDR(&ns_tuple->tlv_header, + WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE, + (sizeof(WMI_NS_OFFLOAD_TUPLE) - WMI_TLV_HDR_SIZE)); + + /* + * Fill data only for NS offload in the first ARP tuple for LA + */ + if ((hostoffloadreq->enableOrDisable & SIR_OFFLOAD_ENABLE)) { + ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID; + /* Copy the target/solicitation/remote ip addr */ + if (ns_req.targetIPv6AddrValid[i]) + A_MEMCPY(&ns_tuple->target_ipaddr[0], + &ns_req.targetIPv6Addr[i], + sizeof(WMI_IPV6_ADDR)); + A_MEMCPY(&ns_tuple->solicitation_ipaddr, + &ns_req.selfIPv6Addr[i], + sizeof(WMI_IPV6_ADDR)); + if (ns_req.target_ipv6_addr_type[i]) { + ns_tuple->flags |= + WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST; + } + WMA_LOGD("Index %d NS solicitedIp %pI6, targetIp %pI6", + i, &ns_req.selfIPv6Addr[i], + &ns_req.targetIPv6Addr[i]); + + /* target MAC is optional, check if it is valid, + * if this is not valid, the target will use the known + * local MAC address rather than the tuple + */ + WMI_CHAR_ARRAY_TO_MAC_ADDR( + ns_req.selfMacAddr, + &ns_tuple->target_mac); + if ((ns_tuple->target_mac.mac_addr31to0 != 0) || + (ns_tuple->target_mac.mac_addr47to32 != 0)) { + ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID; + } + } + *buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE); + } +} + + +/** + * wma_fill_nsoffload_ext() - Fill NS offload ext data + * @wma: wma handle + * @tpSirHostOffloadReq: offload request + * @buf_ptr: buffer pointer + * + * To fill extended NS offload extended data to firmware + * when target goes to wow mode. + * + * Return: None + */ +static void wma_fill_nsoffload_ext(tp_wma_handle wma, tpSirHostOffloadReq + hostoffloadreq, uint8_t **buf_ptr) +{ + int32_t i; + WMI_NS_OFFLOAD_TUPLE *ns_tuple; + uint32_t count, num_ns_ext_tuples; + tSirNsOffloadReq ns_req; + + ns_req = hostoffloadreq->nsOffloadInfo; + count = hostoffloadreq->num_ns_offload_count; + num_ns_ext_tuples = hostoffloadreq->num_ns_offload_count - + WMI_MAX_NS_OFFLOADS; + + /* Populate extended NS offload tuples */ + WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC, + (num_ns_ext_tuples * sizeof(WMI_NS_OFFLOAD_TUPLE))); + *buf_ptr += WMI_TLV_HDR_SIZE; + for (i = WMI_MAX_NS_OFFLOADS; i < count; i++) { + ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)*buf_ptr; + WMITLV_SET_HDR(&ns_tuple->tlv_header, + WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE, + (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE)); + + /* + * Fill data only for NS offload in the first ARP tuple for LA + */ + if ((hostoffloadreq->enableOrDisable & SIR_OFFLOAD_ENABLE)) { + ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID; + /* Copy the target/solicitation/remote ip addr */ + if (ns_req.targetIPv6AddrValid[i]) + A_MEMCPY(&ns_tuple->target_ipaddr[0], + &ns_req.targetIPv6Addr[i], + sizeof(WMI_IPV6_ADDR)); + A_MEMCPY(&ns_tuple->solicitation_ipaddr, + &ns_req.selfIPv6Addr[i], + sizeof(WMI_IPV6_ADDR)); + if (ns_req.target_ipv6_addr_type[i]) { + ns_tuple->flags |= + WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST; + } + WMA_LOGD("Index %d NS solicitedIp %pI6, targetIp %pI6", + i, &ns_req.selfIPv6Addr[i], + &ns_req.targetIPv6Addr[i]); + + /* target MAC is optional, check if it is valid, + * if this is not valid, the target will use the + * known local MAC address rather than the tuple + */ + WMI_CHAR_ARRAY_TO_MAC_ADDR( + ns_req.selfMacAddr, + &ns_tuple->target_mac); + if ((ns_tuple->target_mac.mac_addr31to0 != 0) || + (ns_tuple->target_mac.mac_addr47to32 != 0)) { + ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID; + } + } + *buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE); + } +} +#else +static inline void wma_fill_ns_offload_params(tp_wma_handle wma, + tpSirHostOffloadReq hostoffloadreq, uint8_t **buf_ptr) +{ + return; +} + +static inline void wma_fill_nsoffload_ext(tp_wma_handle wma, + tpSirHostOffloadReq hostoffloadreq, uint8_t **buf_ptr) +{ + return; +} +#endif + + +/** + * wma_enable_arp_ns_offload() - enable ARP NS offload + * @wma: wma handle + * @tpSirHostOffloadReq: offload request + * @config_arp: flag + * + * To configure ARP NS off load data to firmware + * when target goes to wow mode. + * + * Return: VOS Status + */ +static VOS_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, + tpSirHostOffloadReq hostoffloadreq, bool config_arp) +{ int32_t res; WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd; - WMI_NS_OFFLOAD_TUPLE *ns_tuple; - WMI_ARP_OFFLOAD_TUPLE *arp_tuple; A_UINT8* buf_ptr; wmi_buf_t buf; int32_t len; + VOS_STATUS status = VOS_STATUS_SUCCESS; u_int8_t vdev_id; + tpSirHostOffloadReq ns_offload_req; + tpSirHostOffloadReq arp_offload_req; uint32_t count = 0, num_ns_ext_tuples = 0; /* Get the vdev id */ - if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssId, &vdev_id)) { - WMA_LOGE("vdev handle is invalid for %pM", pHostOffloadParams->bssId); - vos_mem_free(pHostOffloadParams); - return VOS_STATUS_E_INVAL; + if (!wma_find_vdev_by_bssid(wma, hostoffloadreq->bssId, &vdev_id)) { + WMA_LOGE("Invalid vdev handle for %pM", hostoffloadreq->bssId); + status = VOS_STATUS_E_FAILURE; + goto err_vdev; } if (!wma->interfaces[vdev_id].vdev_up) { - WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id); - vos_mem_free(pHostOffloadParams); - return VOS_STATUS_E_FAILURE; + status = VOS_STATUS_E_FAILURE; + goto err_vdev; } - if (!bArpOnly) - count = pHostOffloadParams->num_ns_offload_count; + /* + * config_arp is true means arp request comes from upper layer + * Hence ns request need to used from wma cached request. + */ + if (config_arp) { + arp_offload_req = hostoffloadreq; + ns_offload_req = &wma->interfaces[vdev_id].ns_offload_req; + count = ns_offload_req->num_ns_offload_count; + } else { + ns_offload_req = hostoffloadreq; + arp_offload_req = &wma->interfaces[vdev_id].arp_offload_req; + count = hostoffloadreq->num_ns_offload_count; + } len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) + - WMI_TLV_HDR_SIZE + // TLV place holder size for array of NS tuples + WMI_TLV_HDR_SIZE + /* Add size for array of NS tuples */ WMI_MAX_NS_OFFLOADS*sizeof(WMI_NS_OFFLOAD_TUPLE) + - WMI_TLV_HDR_SIZE + // TLV place holder size for array of ARP tuples + WMI_TLV_HDR_SIZE + /* Add size for array of ARP tuples */ WMI_MAX_ARP_OFFLOADS*sizeof(WMI_ARP_OFFLOAD_TUPLE); - /* - * If there are more than WMI_MAX_NS_OFFLOADS addresses then allocate - * extra length for extended NS offload tuples which follows ARP offload - * tuples. Host needs to fill this structure in following format: - * 2 NS ofload tuples - * 2 ARP offload tuples - * N numbers of extended NS offload tuples if HDD has given more than - * 2 NS offload addresses - */ - if (!bArpOnly && count > WMI_MAX_NS_OFFLOADS) { + if (count > WMI_MAX_NS_OFFLOADS) { num_ns_ext_tuples = count - WMI_MAX_NS_OFFLOADS; - len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples * - sizeof(WMI_NS_OFFLOAD_TUPLE); + len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples + * sizeof(WMI_NS_OFFLOAD_TUPLE); } buf = wmi_buf_alloc(wma->wmi_handle, len); if (!buf) { WMA_LOGE("%s: wmi_buf_alloc failed", __func__); - vos_mem_free(pHostOffloadParams); - return VOS_STATUS_E_NOMEM; + status = VOS_STATUS_E_NOMEM; + goto err_vdev; } buf_ptr = (A_UINT8*)wmi_buf_data(buf); + cmd = (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *)buf_ptr; WMITLV_SET_HDR(&cmd->tlv_header, - WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param, - WMITLV_GET_STRUCT_TLVLEN(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param)); + WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param)); cmd->flags = 0; cmd->vdev_id = vdev_id; - if (!bArpOnly) - cmd->num_ns_ext_tuples = num_ns_ext_tuples; - - WMA_LOGD("ARP NS Offload vdev_id: %d",cmd->vdev_id); - - /* Have copy of arp info to send along with NS, Since FW expects - * both ARP and NS info in single cmd */ - if(bArpOnly) - vos_mem_copy(&wma->mArpInfo, pHostOffloadParams, sizeof(tSirHostOffloadReq)); + cmd->num_ns_ext_tuples = num_ns_ext_tuples; buf_ptr += sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param); - WMITLV_SET_HDR(buf_ptr,WMITLV_TAG_ARRAY_STRUC,(WMI_MAX_NS_OFFLOADS*sizeof(WMI_NS_OFFLOAD_TUPLE))); - buf_ptr += WMI_TLV_HDR_SIZE; - for(i = 0; i < WMI_MAX_NS_OFFLOADS; i++ ){ - ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)buf_ptr; - WMITLV_SET_HDR(&ns_tuple->tlv_header, - WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE, - (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE)); - - /* Fill data only for NS offload in the first ARP tuple for LA */ - if (!bArpOnly && - ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) { - ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID; - -#ifdef WLAN_NS_OFFLOAD - /*Copy the target/solicitation/remote ip addr */ - if(pHostOffloadParams->nsOffloadInfo.targetIPv6AddrValid[i]) - A_MEMCPY(&ns_tuple->target_ipaddr[0], - &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i], sizeof(WMI_IPV6_ADDR)); - A_MEMCPY(&ns_tuple->solicitation_ipaddr, - &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i], sizeof(WMI_IPV6_ADDR)); - if(pHostOffloadParams->nsOffloadInfo.target_ipv6_addr_type[i]) - ns_tuple->flags |= WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST; - WMA_LOGD("Index %d NS solicitedIp: %pI6, targetIp: %pI6", i, - &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i], - &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i]); - - /* target MAC is optional, check if it is valid, if this is not valid, - * the target will use the known local MAC address rather than the tuple */ - WMI_CHAR_ARRAY_TO_MAC_ADDR(pHostOffloadParams->nsOffloadInfo.selfMacAddr, - &ns_tuple->target_mac); -#endif - if ((ns_tuple->target_mac.mac_addr31to0 != 0) || - (ns_tuple->target_mac.mac_addr47to32 != 0)) - { - ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID; - } - } - buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE); - } - - WMITLV_SET_HDR(buf_ptr,WMITLV_TAG_ARRAY_STRUC,(WMI_MAX_ARP_OFFLOADS*sizeof(WMI_ARP_OFFLOAD_TUPLE))); - buf_ptr += WMI_TLV_HDR_SIZE; - for(i = 0; i < WMI_MAX_ARP_OFFLOADS; i++){ - arp_tuple = (WMI_ARP_OFFLOAD_TUPLE *)buf_ptr; - WMITLV_SET_HDR(&arp_tuple->tlv_header, - WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE, - WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE)); - - /* Fill data for ARP and NS in the first tupple for LA */ - if ((wma->mArpInfo.enableOrDisable & SIR_OFFLOAD_ENABLE) && (i==0)) { - /*Copy the target ip addr and flags*/ - arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID; - A_MEMCPY(&arp_tuple->target_ipaddr,wma->mArpInfo.params.hostIpv4Addr, - SIR_IPV4_ADDR_LEN); - WMA_LOGD("ARPOffload IP4 address: %pI4", - wma->mArpInfo.params.hostIpv4Addr); - } - buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE); - } - - /* Populate extended NS offload tuples */ - WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, - (num_ns_ext_tuples*sizeof(WMI_NS_OFFLOAD_TUPLE))); - buf_ptr += WMI_TLV_HDR_SIZE; - - if (num_ns_ext_tuples) { - for(i = WMI_MAX_NS_OFFLOADS; i < count; i++ ){ - ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)buf_ptr; - WMITLV_SET_HDR(&ns_tuple->tlv_header, - WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE, - (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE)); - - /* Fill data only for NS offload in the first ARP tuple for LA */ - if (!bArpOnly && - ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) { - ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID; -#ifdef WLAN_NS_OFFLOAD - /*Copy the target/solicitation/remote ip addr */ - if(pHostOffloadParams->nsOffloadInfo.targetIPv6AddrValid[i]) - A_MEMCPY(&ns_tuple->target_ipaddr[0], - &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i], - sizeof(WMI_IPV6_ADDR)); - A_MEMCPY(&ns_tuple->solicitation_ipaddr, - &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i], - sizeof(WMI_IPV6_ADDR)); - if(pHostOffloadParams->nsOffloadInfo.target_ipv6_addr_type[i]) - ns_tuple->flags |= WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST; - WMA_LOGD("Index %d NS solicitedIp: %pI6, targetIp: %pI6", i, - &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i], - &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i]); - - /* target MAC is optional, check if it is valid, if this is not valid, - * the target will use the known local MAC address rather than the tuple */ - WMI_CHAR_ARRAY_TO_MAC_ADDR(pHostOffloadParams->nsOffloadInfo.selfMacAddr, - &ns_tuple->target_mac); -#endif - if ((ns_tuple->target_mac.mac_addr31to0 != 0) || - (ns_tuple->target_mac.mac_addr47to32 != 0)) { - ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID; - } - } - buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE); - } + if (config_arp) + WMA_LOGD(" %s: ARP Offload vdev_id: %d enable: %d ns_count: %u", + __func__, cmd->vdev_id, + hostoffloadreq->enableOrDisable, + hostoffloadreq->num_ns_offload_count); + else + WMA_LOGD(" %s: NS Offload vdev_id: %d enable: %d ns_count: %u", + __func__, cmd->vdev_id, + hostoffloadreq->enableOrDisable, + hostoffloadreq->num_ns_offload_count); + + wma_fill_ns_offload_params(wma, ns_offload_req, &buf_ptr); + wma_fill_arp_offload_params(wma, arp_offload_req, &buf_ptr); + if (count > WMI_MAX_NS_OFFLOADS) + wma_fill_nsoffload_ext(wma, ns_offload_req, &buf_ptr); + + res = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_SET_ARP_NS_OFFLOAD_CMDID); + if (res) { + WMA_LOGE("Failed to enable ARP NDP/NSffload"); + goto err_cmd_send; } - res = wmi_unified_cmd_send(wma->wmi_handle, buf, len, WMI_SET_ARP_NS_OFFLOAD_CMDID); - if(res) { - WMA_LOGE("Failed to enable ARP NDP/NSffload"); - wmi_buf_free(buf); - vos_mem_free(pHostOffloadParams); - return VOS_STATUS_E_FAILURE; + if (config_arp) { + vos_mem_copy(&wma->interfaces[vdev_id].arp_offload_req, + hostoffloadreq, sizeof(tSirHostOffloadReq)); + } else { + vos_mem_copy(&wma->interfaces[vdev_id].ns_offload_req, + hostoffloadreq, sizeof(tSirHostOffloadReq)); } - vos_mem_free(pHostOffloadParams); - return VOS_STATUS_SUCCESS; + vos_mem_free(hostoffloadreq); + return status; +err_cmd_send: + wmi_buf_free(buf); +err_vdev: + vos_mem_free(hostoffloadreq); + return status; } typedef struct { |