qcacld-3.0: Hold APF set instruction context till completion

Once Driver receives APF sub-command QCA_WLAN_SET_PACKET_FILTER,
it posts the message to SME and returns the context. In case
where vdev restarts before sending the APF command to WMI,
driver will drop it since Firmware cannot accept the command
while vdev is down. Upper layer will have no knowledge of this
failure since there is no acknowledgment mechanism for a
successful APF command sent to the Firmware. Once the vdev is up
again, upper layer will send next APF instructions and driver
will allow then to the Firmware. This is problematic since
Firmware cannot operate with the partial APF instructions since
the initial part was dropped.

Hold the vendor command context till the command is successfully
sent to the Firmware. Propagate the errors to the upper layer.

Change-Id: If3cd6fbc85f83c0d78e735e96c00011cd2fd9347
CRs-Fixed: 2350640
This commit is contained in:
Nachiket Kukade 2018-11-19 19:18:27 +05:30 committed by nshrivas
parent a5a24bf6f4
commit 4f68658ef8
3 changed files with 26 additions and 67 deletions

View File

@ -221,7 +221,7 @@ static int hdd_set_reset_apf_offload(struct hdd_context *hdd_ctx,
struct nlattr **tb,
struct hdd_adapter *adapter)
{
struct sir_apf_set_offload *apf_set_offload;
struct sir_apf_set_offload apf_set_offload = {0};
QDF_STATUS status;
int prog_len;
int ret = 0;
@ -234,19 +234,15 @@ static int hdd_set_reset_apf_offload(struct hdd_context *hdd_ctx,
return -ENOTSUPP;
}
apf_set_offload = qdf_mem_malloc(sizeof(*apf_set_offload));
if (!apf_set_offload)
return -ENOMEM;
/* Parse and fetch apf packet size */
if (!tb[APF_PACKET_SIZE]) {
hdd_err("attr apf packet size failed");
ret = -EINVAL;
goto fail;
}
apf_set_offload->total_length = nla_get_u32(tb[APF_PACKET_SIZE]);
apf_set_offload.total_length = nla_get_u32(tb[APF_PACKET_SIZE]);
if (!apf_set_offload->total_length) {
if (!apf_set_offload.total_length) {
hdd_debug("APF reset packet filter received");
goto post_sme;
}
@ -259,20 +255,20 @@ static int hdd_set_reset_apf_offload(struct hdd_context *hdd_ctx,
}
prog_len = nla_len(tb[APF_PROGRAM]);
apf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
apf_set_offload.program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
if (!apf_set_offload->program) {
if (!apf_set_offload.program) {
ret = -ENOMEM;
goto fail;
}
apf_set_offload->current_length = prog_len;
nla_memcpy(apf_set_offload->program, tb[APF_PROGRAM], prog_len);
apf_set_offload->session_id = adapter->session_id;
apf_set_offload.current_length = prog_len;
nla_memcpy(apf_set_offload.program, tb[APF_PROGRAM], prog_len);
apf_set_offload.session_id = adapter->session_id;
hdd_debug("APF set instructions");
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
apf_set_offload->program, prog_len);
apf_set_offload.program, prog_len);
/* Parse and fetch filter Id */
if (!tb[APF_FILTER_ID]) {
@ -280,7 +276,7 @@ static int hdd_set_reset_apf_offload(struct hdd_context *hdd_ctx,
ret = -EINVAL;
goto fail;
}
apf_set_offload->filter_id = nla_get_u32(tb[APF_FILTER_ID]);
apf_set_offload.filter_id = nla_get_u32(tb[APF_FILTER_ID]);
/* Parse and fetch current offset */
if (!tb[APF_CURRENT_OFFSET]) {
@ -288,16 +284,17 @@ static int hdd_set_reset_apf_offload(struct hdd_context *hdd_ctx,
ret = -EINVAL;
goto fail;
}
apf_set_offload->current_offset = nla_get_u32(tb[APF_CURRENT_OFFSET]);
apf_set_offload.current_offset = nla_get_u32(tb[APF_CURRENT_OFFSET]);
post_sme:
hdd_debug("Posting APF SET/RESET to SME, session_id: %d APF Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d",
apf_set_offload->session_id, apf_set_offload->version,
apf_set_offload->filter_id, apf_set_offload->total_length,
apf_set_offload->current_length,
apf_set_offload->current_offset);
apf_set_offload.session_id, apf_set_offload.version,
apf_set_offload.filter_id, apf_set_offload.total_length,
apf_set_offload.current_length,
apf_set_offload.current_offset);
status = sme_set_apf_instructions(hdd_ctx->mac_handle, apf_set_offload);
status = sme_set_apf_instructions(hdd_ctx->mac_handle,
&apf_set_offload);
if (!QDF_IS_STATUS_SUCCESS(status)) {
hdd_err("sme_set_apf_instructions failed(err=%d)", status);
ret = -EINVAL;
@ -306,9 +303,8 @@ post_sme:
hdd_exit();
fail:
if (apf_set_offload->current_length)
qdf_mem_free(apf_set_offload->program);
qdf_mem_free(apf_set_offload);
if (apf_set_offload.current_length)
qdf_mem_free(apf_set_offload.program);
if (!ret)
hdd_ctx->apf_enabled_v2 = true;

View File

@ -14580,49 +14580,16 @@ QDF_STATUS sme_get_apf_capabilities(mac_handle_t mac_handle,
QDF_STATUS sme_set_apf_instructions(mac_handle_t mac_handle,
struct sir_apf_set_offload *req)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle);
struct scheduler_msg cds_msg = {0};
struct sir_apf_set_offload *set_offload;
void *wma_handle;
set_offload = qdf_mem_malloc(sizeof(*set_offload) +
req->current_length);
if (!set_offload)
return QDF_STATUS_E_NOMEM;
set_offload->session_id = req->session_id;
set_offload->filter_id = req->filter_id;
set_offload->current_offset = req->current_offset;
set_offload->total_length = req->total_length;
set_offload->current_length = req->current_length;
if (set_offload->total_length) {
set_offload->program = ((uint8_t *)set_offload) +
sizeof(*set_offload);
qdf_mem_copy(set_offload->program, req->program,
set_offload->current_length);
}
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
/* Serialize the req through MC thread */
cds_msg.bodyptr = set_offload;
cds_msg.type = WDA_APF_SET_INSTRUCTIONS_REQ;
status = scheduler_post_message(QDF_MODULE_ID_SME,
QDF_MODULE_ID_WMA,
QDF_MODULE_ID_WMA, &cds_msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Post APF set offload msg fail"));
status = QDF_STATUS_E_FAILURE;
qdf_mem_free(set_offload);
}
sme_release_global_lock(&mac_ctx->sme);
} else {
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock failed"));
qdf_mem_free(set_offload);
"wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
return status;
return wma_set_apf_instructions(wma_handle, req);
}
QDF_STATUS sme_set_apf_enable_disable(mac_handle_t mac_handle, uint8_t vdev_id,

View File

@ -8516,10 +8516,6 @@ static QDF_STATUS wma_mc_process_msg(struct scheduler_msg *msg)
case WDA_APF_GET_CAPABILITIES_REQ:
wma_get_apf_capabilities(wma_handle);
break;
case WDA_APF_SET_INSTRUCTIONS_REQ:
wma_set_apf_instructions(wma_handle, msg->bodyptr);
qdf_mem_free(msg->bodyptr);
break;
case SIR_HAL_POWER_DBG_CMD:
wma_process_hal_pwr_dbg_cmd(wma_handle,
msg->bodyptr);