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:
parent
a5a24bf6f4
commit
4f68658ef8
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user