qcacmn: Cache ARP/NS offload request at wma layer

qcacld-2.0 to qcacmn propagation

As Current WMI interface need both the ARP/NS configuration
in single command. To support active offload host need to
cache the ARP/NS at wma layer so host can fill the other
request and configure down to firmware complete request
(ARP+NS).

Change-Id: Ie0a57d216379817ff0ae48f4f582c9108e8ecca1
CRs-Fixed: 1067683
This commit is contained in:
Mukul Sharma
2016-09-07 20:31:47 +05:30
committed by qcabuildsw
parent 1d5f5ab6a4
commit 3a5eedb68c
2 changed files with 218 additions and 146 deletions

View File

@@ -3141,14 +3141,16 @@ QDF_STATUS wmi_unified_pdev_set_dual_mac_config_cmd(void *wmi_hdl,
* Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
*/ */
QDF_STATUS wmi_unified_enable_arp_ns_offload_cmd(void *wmi_hdl, QDF_STATUS wmi_unified_enable_arp_ns_offload_cmd(void *wmi_hdl,
struct host_offload_req_param *param, bool arp_only, struct host_offload_req_param *arp_offload_req,
struct host_offload_req_param *ns_offload_req,
bool arp_only,
uint8_t vdev_id) uint8_t vdev_id)
{ {
wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl; wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl;
if (wmi_handle->ops->send_enable_arp_ns_offload_cmd) if (wmi_handle->ops->send_enable_arp_ns_offload_cmd)
return wmi_handle->ops->send_enable_arp_ns_offload_cmd(wmi_handle, return wmi_handle->ops->send_enable_arp_ns_offload_cmd(wmi_handle,
param, arp_only, arp_offload_req, ns_offload_req, arp_only,
vdev_id); vdev_id);
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;

View File

@@ -10087,41 +10087,236 @@ QDF_STATUS send_pdev_set_dual_mac_config_cmd_tlv(wmi_unified_t wmi_handle,
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
/**
* fill_arp_offload_params_tlv() - Fill ARP offload data
* @wmi_handle: wmi handle
* @offload_req: offload request
* @buf_ptr: buffer pointer
*
* To fill ARP offload data to firmware
* when target goes to wow mode.
*
* Return: None
*/
static void fill_arp_offload_params_tlv(wmi_unified_t wmi_handle,
struct host_offload_req_param *offload_req, uint8_t **buf_ptr)
{
int i;
WMI_ARP_OFFLOAD_TUPLE *arp_tuple;
bool enable_or_disable = offload_req->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 ((enable_or_disable & WMI_OFFLOAD_ENABLE) && (i == 0)) {
/* Copy the target ip addr and flags */
arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID;
qdf_mem_copy(&arp_tuple->target_ipaddr,
offload_req->params.hostIpv4Addr,
WMI_IPV4_ADDR_LEN);
WMI_LOGD("ARPOffload IP4 address: %pI4",
offload_req->params.hostIpv4Addr);
}
*buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE);
}
}
#ifdef WLAN_NS_OFFLOAD
/**
* fill_ns_offload_params_tlv() - Fill NS offload data
* @wmi|_handle: wmi handle
* @offload_req: offload request
* @buf_ptr: buffer pointer
*
* To fill NS offload data to firmware
* when target goes to wow mode.
*
* Return: None
*/
static void fill_ns_offload_params_tlv(wmi_unified_t wmi_handle,
struct host_offload_req_param *offload_req, uint8_t **buf_ptr)
{
int i;
WMI_NS_OFFLOAD_TUPLE *ns_tuple;
struct ns_offload_req_params ns_req;
ns_req = offload_req->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 ((offload_req->enableOrDisable & WMI_OFFLOAD_ENABLE)) {
ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
/* Copy the target/solicitation/remote ip addr */
if (ns_req.targetIPv6AddrValid[i])
qdf_mem_copy(&ns_tuple->target_ipaddr[0],
&ns_req.targetIPv6Addr[i],
sizeof(WMI_IPV6_ADDR));
qdf_mem_copy(&ns_tuple->solicitation_ipaddr,
&ns_req.selfIPv6Addr[i],
sizeof(WMI_IPV6_ADDR));
if (ns_req.target_ipv6_addr_ac_type[i]) {
ns_tuple->flags |=
WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
}
WMI_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.self_macaddr.bytes,
&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);
}
}
/**
* fill_nsoffload_ext_tlv() - Fill NS offload ext data
* @wmi: wmi handle
* @offload_req: 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 fill_nsoffload_ext_tlv(wmi_unified_t wmi_handle,
struct host_offload_req_param *offload_req, uint8_t **buf_ptr)
{
int i;
WMI_NS_OFFLOAD_TUPLE *ns_tuple;
uint32_t count, num_ns_ext_tuples;
struct ns_offload_req_params ns_req;
ns_req = offload_req->nsOffloadInfo;
count = offload_req->num_ns_offload_count;
num_ns_ext_tuples = offload_req->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 ((offload_req->enableOrDisable & WMI_OFFLOAD_ENABLE)) {
ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
/* Copy the target/solicitation/remote ip addr */
if (ns_req.targetIPv6AddrValid[i])
qdf_mem_copy(&ns_tuple->target_ipaddr[0],
&ns_req.targetIPv6Addr[i],
sizeof(WMI_IPV6_ADDR));
qdf_mem_copy(&ns_tuple->solicitation_ipaddr,
&ns_req.selfIPv6Addr[i],
sizeof(WMI_IPV6_ADDR));
if (ns_req.target_ipv6_addr_ac_type[i]) {
ns_tuple->flags |=
WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
}
WMI_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.self_macaddr.bytes,
&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 void fill_ns_offload_params_tlv(wmi_unified_t wmi_handle,
struct host_offload_req_param *offload_req, uint8_t **buf_ptr)
{
return;
}
static void fill_nsoffload_ext_tlv(wmi_unified_t wmi_handle,
struct host_offload_req_param *offload_req, uint8_t **buf_ptr)
{
return;
}
#endif
/** /**
* send_enable_arp_ns_offload_cmd_tlv() - enable ARP NS offload * send_enable_arp_ns_offload_cmd_tlv() - enable ARP NS offload
* @wma: wmi handle * @wma: wmi handle
* @tpSirHostOffloadReq: offload request * @arp_offload_req: arp offload request
* @ns_offload_req: ns offload request
* @arp_only: flag * @arp_only: flag
* *
* To configure ARP NS off load data to firmware * To configure ARP NS off load data to firmware
* when target goes to wow mode. * when target goes to wow mode.
* *
* Return: CDF Status * Return: QDF Status
*/ */
QDF_STATUS send_enable_arp_ns_offload_cmd_tlv(wmi_unified_t wmi_handle, QDF_STATUS send_enable_arp_ns_offload_cmd_tlv(wmi_unified_t wmi_handle,
struct host_offload_req_param *param, bool arp_only, struct host_offload_req_param *arp_offload_req,
struct host_offload_req_param *ns_offload_req,
bool arp_only,
uint8_t vdev_id) uint8_t vdev_id)
{ {
int32_t i;
int32_t res; int32_t res;
WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd; 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; A_UINT8 *buf_ptr;
wmi_buf_t buf; wmi_buf_t buf;
int32_t len; int32_t len;
uint32_t count = 0, num_ns_ext_tuples = 0; uint32_t count = 0, num_ns_ext_tuples = 0;
count = ns_offload_req->num_ns_offload_count;
if (!arp_only)
count = param->num_ns_offload_count;
/* /*
* TLV place holder size for array of NS tuples * TLV place holder size for array of NS tuples
* TLV place holder size for array of ARP tuples * TLV place holder size for array of ARP tuples
*/ */
len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) + WMI_TLV_HDR_SIZE + len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) +
WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE) + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE +
WMI_MAX_ARP_OFFLOADS * sizeof(WMI_ARP_OFFLOAD_TUPLE); WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE) +
WMI_TLV_HDR_SIZE +
WMI_MAX_ARP_OFFLOADS * sizeof(WMI_ARP_OFFLOAD_TUPLE);
/* /*
* If there are more than WMI_MAX_NS_OFFLOADS addresses then allocate * If there are more than WMI_MAX_NS_OFFLOADS addresses then allocate
@@ -10132,10 +10327,10 @@ QDF_STATUS send_enable_arp_ns_offload_cmd_tlv(wmi_unified_t wmi_handle,
* N numbers of extended NS offload tuples if HDD has given more than * N numbers of extended NS offload tuples if HDD has given more than
* 2 NS offload addresses * 2 NS offload addresses
*/ */
if (!arp_only && count > WMI_MAX_NS_OFFLOADS) { if (count > WMI_MAX_NS_OFFLOADS) {
num_ns_ext_tuples = count - WMI_MAX_NS_OFFLOADS; num_ns_ext_tuples = count - WMI_MAX_NS_OFFLOADS;
len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples * len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples
sizeof(WMI_NS_OFFLOAD_TUPLE); * sizeof(WMI_NS_OFFLOAD_TUPLE);
} }
buf = wmi_buf_alloc(wmi_handle, len); buf = wmi_buf_alloc(wmi_handle, len);
@@ -10152,140 +10347,15 @@ QDF_STATUS send_enable_arp_ns_offload_cmd_tlv(wmi_unified_t wmi_handle,
(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param)); (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param));
cmd->flags = 0; cmd->flags = 0;
cmd->vdev_id = vdev_id; cmd->vdev_id = vdev_id;
if (!arp_only) cmd->num_ns_ext_tuples = num_ns_ext_tuples;
cmd->num_ns_ext_tuples = num_ns_ext_tuples;
WMI_LOGD("ARP NS Offload vdev_id: %d", cmd->vdev_id); WMI_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 (arp_only)
qdf_mem_copy(&wmi_handle->arp_info, param,
sizeof(struct host_offload_req_param));
buf_ptr += sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param); buf_ptr += sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param);
WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, fill_ns_offload_params_tlv(wmi_handle, ns_offload_req, &buf_ptr);
(WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE))); fill_arp_offload_params_tlv(wmi_handle, arp_offload_req, &buf_ptr);
buf_ptr += WMI_TLV_HDR_SIZE; if (num_ns_ext_tuples)
for (i = 0; i < WMI_MAX_NS_OFFLOADS; i++) { fill_nsoffload_ext_tlv(wmi_handle, ns_offload_req, &buf_ptr);
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 (!arp_only &&
((param->enableOrDisable & WMI_OFFLOAD_ENABLE))) {
ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
#ifdef WLAN_NS_OFFLOAD
/*Copy the target/solicitation/remote ip addr */
if (param->nsOffloadInfo.
targetIPv6AddrValid[i])
A_MEMCPY(&ns_tuple->target_ipaddr[0],
&param->nsOffloadInfo.
targetIPv6Addr[i],
sizeof(WMI_IPV6_ADDR));
A_MEMCPY(&ns_tuple->solicitation_ipaddr,
&param->nsOffloadInfo.
selfIPv6Addr[i], sizeof(WMI_IPV6_ADDR));
if (param->nsOffloadInfo.
target_ipv6_addr_ac_type[i])
ns_tuple->flags |=
WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
WMI_LOGD("NS solicitedIp: %pI6, targetIp: %pI6",
&param->nsOffloadInfo.selfIPv6Addr[i],
&param->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(param->
nsOffloadInfo.self_macaddr.bytes,
&ns_tuple->target_mac);
#endif /* WLAN_NS_OFFLOAD */
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 ((wmi_handle->arp_info.enableOrDisable & WMI_OFFLOAD_ENABLE)
&& (i == 0)) {
/*Copy the target ip addr and flags */
arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID;
A_MEMCPY(&arp_tuple->target_ipaddr,
wmi_handle->arp_info.params.hostIpv4Addr,
WMI_IPV4_ADDR_LEN);
WMI_LOGD("ARPOffload IP4 address: %pI4",
wmi_handle->arp_info.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 (!arp_only &&
((param->enableOrDisable &
WMI_OFFLOAD_ENABLE))) {
ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
#ifdef WLAN_NS_OFFLOAD
/*Copy the target/solicitation/remote ip addr */
if (param->nsOffloadInfo.targetIPv6AddrValid[i])
A_MEMCPY(&ns_tuple->target_ipaddr[0],
&param->nsOffloadInfo.targetIPv6Addr[i],
sizeof(WMI_IPV6_ADDR));
A_MEMCPY(&ns_tuple->solicitation_ipaddr,
&param->nsOffloadInfo.selfIPv6Addr[i],
sizeof(WMI_IPV6_ADDR));
if (param->nsOffloadInfo.
target_ipv6_addr_ac_type[i])
ns_tuple->flags |=
WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
WMI_LOGD("Index %d NS solicitedIp: %pI6, targetIp: %pI6", i,
&param->nsOffloadInfo.selfIPv6Addr[i],
&param->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(
param->nsOffloadInfo.self_macaddr.bytes,
&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);
}
}
res = wmi_unified_cmd_send(wmi_handle, buf, len, res = wmi_unified_cmd_send(wmi_handle, buf, len,
WMI_SET_ARP_NS_OFFLOAD_CMDID); WMI_SET_ARP_NS_OFFLOAD_CMDID);