From 5f0ce4f65d8f609160727daf7aa12e2a26de0c75 Mon Sep 17 00:00:00 2001 From: Nachiket Kukade Date: Fri, 15 Jun 2018 19:47:37 +0530 Subject: [PATCH] qcacld-3.0: Move APF context to per adapter APF commands are using a global context and so the current implementation can only entertain one command at a time. Since APF in Firmware is vdev specific, simultaneous APF commands on different vdev's should be supported. Move APF context inside hdd adapter to support simultaneous commands on multiple vdev's. Change-Id: Ife148065ebc6387af3a690cc0cb788e23066e67e CRs-Fixed: 2192408 --- core/hdd/inc/wlan_hdd_apf.h | 36 ++-------- core/hdd/inc/wlan_hdd_main.h | 33 ++++++++- core/hdd/src/wlan_hdd_apf.c | 130 ++++++++++++++++------------------- core/hdd/src/wlan_hdd_main.c | 32 +++++++-- 4 files changed, 123 insertions(+), 108 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_apf.h b/core/hdd/inc/wlan_hdd_apf.h index 8717d1df61b3..eeee39294123 100644 --- a/core/hdd/inc/wlan_hdd_apf.h +++ b/core/hdd/inc/wlan_hdd_apf.h @@ -46,30 +46,6 @@ #define WLAN_WAIT_TIME_APF_GET_CAPS 1000 #define WLAN_WAIT_TIME_APF_READ_MEM 10000 -/* - * struct hdd_apf_context - hdd Context for apf - * @magic: magic number - * @qdf_apf_event: Completion variable for APF get operations - * @capability_response: capabilities response received from fw - * @apf_enabled: True: APF Interpreter enabled, False: Disabled - * @cmd_in_progress: Flag that indicates an APF command is in progress - * @buf: Buffer to accumulate read memory chunks - * @buf_len: Length of the read memory requested - * @offset: APF work memory offset to fetch from - * @lock: APF Context lock - */ -struct hdd_apf_context { - unsigned int magic; - qdf_event_t qdf_apf_event; - struct sir_apf_get_offload capability_response; - bool apf_enabled; - bool cmd_in_progress; - uint8_t *buf; - uint32_t buf_len; - uint32_t offset; - qdf_spinlock_t lock; -}; - /** * wlan_hdd_cfg80211_apf_offload() - SSR Wrapper to APF Offload * @wiphy: wiphy structure pointer @@ -86,21 +62,23 @@ int wlan_hdd_cfg80211_apf_offload(struct wiphy *wiphy, /** * hdd_apf_context_init - APF Context initialization operations + * @adapter: hdd adapter * * Return: None */ -void hdd_apf_context_init(void); +void hdd_apf_context_init(struct hdd_adapter *adapter); /** * hdd_apf_context_destroy - APF Context de-init operations + * @adapter: hdd adapter * * Return: None */ -void hdd_apf_context_destroy(void); +void hdd_apf_context_destroy(struct hdd_adapter *adapter); /** * hdd_get_apf_capabilities_cb() - Callback function to get APF capabilities - * @hdd_context: hdd_context + * @hdd_context: pointer to the hdd context * @apf_get_offload: struct for get offload * * This function receives the response/data from the lower layer and @@ -113,11 +91,11 @@ void hdd_get_apf_capabilities_cb(void *hdd_context, struct sir_apf_get_offload *data); #else /* FEATURE_WLAN_APF */ -static inline void hdd_apf_context_init(void) +static inline void hdd_apf_context_init(struct hdd_adapter *adapter) { } -static inline void hdd_apf_context_destroy(void) +static inline void hdd_apf_context_destroy(struct hdd_adapter *adapter) { } diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index a3b6c510596a..3d7a0b9611f9 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -98,6 +98,31 @@ * Preprocessor definitions and constants */ +#ifdef FEATURE_WLAN_APF +/** + * struct hdd_apf_context - hdd Context for apf + * @magic: magic number + * @qdf_apf_event: Completion variable for APF get operations + * @capability_response: capabilities response received from fw + * @apf_enabled: True: APF Interpreter enabled, False: Disabled + * @cmd_in_progress: Flag that indicates an APF command is in progress + * @buf: Buffer to accumulate read memory chunks + * @buf_len: Length of the read memory requested + * @offset: APF work memory offset to fetch from + * @lock: APF Context lock + */ +struct hdd_apf_context { + unsigned int magic; + qdf_event_t qdf_apf_event; + bool apf_enabled; + bool cmd_in_progress; + uint8_t *buf; + uint32_t buf_len; + uint32_t offset; + qdf_spinlock_t lock; +}; +#endif /* FEATURE_WLAN_APF */ + /** Number of Tx Queues */ #if defined(QCA_LL_TX_FLOW_CONTROL_V2) || defined(QCA_HL_NETDEV_FLOW_CONTROL) #define NUM_TX_QUEUES 5 @@ -1413,6 +1438,9 @@ struct hdd_adapter { /* rcpi information */ struct rcpi_info rcpi; bool send_mode_change; +#ifdef FEATURE_WLAN_APF + struct hdd_apf_context apf_context; +#endif /* FEATURE_WLAN_APF */ }; #define WLAN_HDD_GET_STATION_CTX_PTR(adapter) (&(adapter)->session.station) @@ -1822,7 +1850,6 @@ struct hdd_context { struct completion set_antenna_mode_cmpl; /* Current number of TX X RX chains being used */ enum antenna_mode current_antenna_mode; - bool apf_enabled; /* the radio index assigned by cnss_logger */ int radio_index; @@ -1905,6 +1932,10 @@ struct hdd_context { #ifdef WLAN_SUPPORT_TWT enum twt_status twt_state; #endif +#ifdef FEATURE_WLAN_APF + bool apf_supported; + uint32_t apf_version; +#endif }; /** diff --git a/core/hdd/src/wlan_hdd_apf.c b/core/hdd/src/wlan_hdd_apf.c index c19b4e4b877a..a51290aeed94 100644 --- a/core/hdd/src/wlan_hdd_apf.c +++ b/core/hdd/src/wlan_hdd_apf.c @@ -26,8 +26,6 @@ #include "qca_vendor.h" #include "wlan_osif_request_manager.h" -struct hdd_apf_context apf_context; - /* * define short names for the global vendor params * used by __wlan_hdd_cfg80211_apf_offload() @@ -63,18 +61,19 @@ wlan_hdd_apf_offload_policy[APF_MAX + 1] = { [APF_PROG_LEN] = {.type = NLA_U32}, }; -void hdd_apf_context_init(void) +void hdd_apf_context_init(struct hdd_adapter *adapter) { - qdf_event_create(&apf_context.qdf_apf_event); - qdf_spinlock_create(&apf_context.lock); - apf_context.apf_enabled = true; + qdf_event_create(&adapter->apf_context.qdf_apf_event); + qdf_spinlock_create(&adapter->apf_context.lock); + adapter->apf_context.apf_enabled = true; } -void hdd_apf_context_destroy(void) +void hdd_apf_context_destroy(struct hdd_adapter *adapter) { - qdf_event_destroy(&apf_context.qdf_apf_event); - qdf_spinlock_destroy(&apf_context.lock); - qdf_mem_zero(&apf_context, sizeof(apf_context)); + qdf_event_destroy(&adapter->apf_context.qdf_apf_event); + qdf_spinlock_destroy(&adapter->apf_context.lock); + qdf_mem_zero(&adapter->apf_context, + sizeof(struct hdd_apf_context)); } struct apf_offload_priv { @@ -99,6 +98,8 @@ void hdd_get_apf_capabilities_cb(void *context, priv->apf_get_offload = *data; osif_request_complete(request); osif_request_put(request); + + hdd_exit(); } /** @@ -128,6 +129,7 @@ hdd_post_get_apf_capabilities_rsp(struct hdd_context *hdd_ctx, return -ENOMEM; } + hdd_ctx->apf_version = apf_get_offload->apf_version; hdd_debug("APF Version: %u APF max bytes: %u", apf_get_offload->apf_version, apf_get_offload->max_bytes_for_apf_inst); @@ -315,31 +317,27 @@ fail: /** * hdd_enable_disable_apf - Enable or Disable the APF interpreter - * @vdev_id: VDEV id - * @hdd_ctx: Hdd context + * @adapter: HDD Adapter * @apf_enable: true: Enable APF Int., false: disable APF Int. * * Return: 0 on success, errno on failure */ static int -hdd_enable_disable_apf(struct hdd_context *hdd_ctx, uint8_t vdev_id, - bool apf_enable) +hdd_enable_disable_apf(struct hdd_adapter *adapter, bool apf_enable) { QDF_STATUS status; hdd_enter(); - status = sme_set_apf_enable_disable(hdd_ctx->mac_handle, - vdev_id, apf_enable); + status = sme_set_apf_enable_disable(hdd_adapter_get_mac_handle(adapter), + adapter->session_id, apf_enable); if (!QDF_IS_STATUS_SUCCESS(status)) { hdd_err("Unable to post sme apf enable/disable message (status-%d)", status); return -EINVAL; } - qdf_spin_lock(&apf_context.lock); - apf_context.apf_enabled = apf_enable; - qdf_spin_unlock(&apf_context.lock); + adapter->apf_context.apf_enabled = apf_enable; hdd_exit(); return 0; @@ -347,9 +345,8 @@ hdd_enable_disable_apf(struct hdd_context *hdd_ctx, uint8_t vdev_id, /** * hdd_apf_write_memory - Write into the apf work memory - * @hdd_ctx: Hdd context + * @adapter: HDD Adapter * @tb: list of attributes - * @session_id: Session id * * This function writes code/data into the APF work memory and * provides program length that is passed on to the interpreter. @@ -357,23 +354,18 @@ hdd_enable_disable_apf(struct hdd_context *hdd_ctx, uint8_t vdev_id, * Return: 0 on success, errno on failure */ static int -hdd_apf_write_memory(struct hdd_context *hdd_ctx, struct nlattr **tb, - uint8_t session_id) +hdd_apf_write_memory(struct hdd_adapter *adapter, struct nlattr **tb) { struct wmi_apf_write_memory_params write_mem_params = {0}; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); QDF_STATUS status; int ret = 0; - bool apf_enabled; hdd_enter(); - write_mem_params.vdev_id = session_id; - qdf_spin_lock(&apf_context.lock); - apf_enabled = apf_context.apf_enabled; - qdf_spin_unlock(&apf_context.lock); - - if (apf_enabled) { + write_mem_params.vdev_id = adapter->session_id; + if (adapter->apf_context.apf_enabled) { hdd_err("Cannot get/set when APF interpreter is enabled"); return -EINVAL; } @@ -413,10 +405,9 @@ hdd_apf_write_memory(struct hdd_context *hdd_ctx, struct nlattr **tb, nla_memcpy(write_mem_params.buf, tb[APF_PROGRAM], write_mem_params.length); - write_mem_params.apf_version = - apf_context.capability_response.apf_version; + write_mem_params.apf_version = hdd_ctx->apf_version; - status = sme_apf_write_work_memory(hdd_ctx->mac_handle, + status = sme_apf_write_work_memory(hdd_adapter_get_mac_handle(adapter), &write_mem_params); if (!QDF_IS_STATUS_SUCCESS(status)) { hdd_err("Unable to retrieve APF caps"); @@ -434,7 +425,7 @@ hdd_apf_write_memory(struct hdd_context *hdd_ctx, struct nlattr **tb, * hdd_apf_read_memory_callback - HDD Callback for the APF read memory * operation * @context: Hdd context - * @read_mem_evt: APF read memory event response parameters + * @evt: APF read memory event response parameters * * Return: 0 on success, errno on failure */ @@ -443,7 +434,8 @@ hdd_apf_read_memory_callback(void *hdd_context, struct wmi_apf_read_memory_resp_event_params *evt) { struct hdd_context *hdd_ctx = hdd_context; - static struct hdd_apf_context *context = &apf_context; + struct hdd_adapter *adapter; + struct hdd_apf_context *context; uint8_t *buf_ptr; uint32_t pkt_offset; @@ -455,16 +447,16 @@ hdd_apf_read_memory_callback(void *hdd_context, return; } - qdf_spin_lock(&context->lock); + adapter = hdd_get_adapter_by_vdev(hdd_ctx, evt->vdev_id); + context = &adapter->apf_context; + if (context->magic != APF_CONTEXT_MAGIC) { /* The caller presumably timed out, nothing to do */ - qdf_spin_unlock(&context->lock); hdd_err("Caller timed out or corrupt magic, simply return"); return; } if (evt->offset < context->offset) { - qdf_spin_unlock(&context->lock); hdd_err("Offset in read event(%d) smaller than offset in request(%d)!", evt->offset, context->offset); return; @@ -478,7 +470,6 @@ hdd_apf_read_memory_callback(void *hdd_context, pkt_offset = evt->offset - context->offset; if (context->buf_len < pkt_offset + evt->length) { - qdf_spin_unlock(&context->lock); hdd_err("Read chunk exceeding allocated space"); return; } @@ -492,24 +483,21 @@ hdd_apf_read_memory_callback(void *hdd_context, qdf_event_set(&context->qdf_apf_event); } - qdf_spin_unlock(&context->lock); - hdd_exit(); } /** * hdd_apf_read_memory - Read part of the apf work memory - * @hdd_ctx: Hdd context + * @adapter: HDD Adapter * @tb: list of attributes - * @session_id: Session id * * Return: 0 on success, errno on failure */ -static int hdd_apf_read_memory(struct hdd_context *hdd_ctx, struct nlattr **tb, - uint8_t session_id) +static int hdd_apf_read_memory(struct hdd_adapter *adapter, struct nlattr **tb) { struct wmi_apf_read_memory_params read_mem_params = {0}; - static struct hdd_apf_context *context = &apf_context; + struct hdd_apf_context *context = &adapter->apf_context; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); QDF_STATUS status; unsigned long nl_buf_len = NLMSG_HDRLEN; int ret = 0; @@ -518,7 +506,7 @@ static int hdd_apf_read_memory(struct hdd_context *hdd_ctx, struct nlattr **tb, hdd_enter(); - read_mem_params.vdev_id = session_id; + read_mem_params.vdev_id = adapter->session_id; /* Read APF work memory offset */ if (!tb[APF_CURRENT_OFFSET]) { @@ -543,9 +531,7 @@ static int hdd_apf_read_memory(struct hdd_context *hdd_ctx, struct nlattr **tb, return -ENOMEM; } - qdf_spin_lock(&context->lock); if (context->apf_enabled) { - qdf_spin_unlock(&context->lock); hdd_err("Cannot get/set while interpreter is enabled"); return -EINVAL; } @@ -556,9 +542,8 @@ static int hdd_apf_read_memory(struct hdd_context *hdd_ctx, struct nlattr **tb, context->buf = bufptr; context->buf_len = read_mem_params.length; context->magic = APF_CONTEXT_MAGIC; - qdf_spin_unlock(&context->lock); - status = sme_apf_read_work_memory(hdd_ctx->mac_handle, + status = sme_apf_read_work_memory(hdd_adapter_get_mac_handle(adapter), &read_mem_params, hdd_apf_read_memory_callback); if (QDF_IS_STATUS_ERROR(status)) { @@ -573,9 +558,7 @@ static int hdd_apf_read_memory(struct hdd_context *hdd_ctx, struct nlattr **tb, WLAN_WAIT_TIME_APF_READ_MEM); if (QDF_IS_STATUS_ERROR(status)) { hdd_err("Target response timed out"); - qdf_spin_lock(&context->lock); context->magic = 0; - qdf_spin_unlock(&context->lock); ret = -ETIMEDOUT; goto fail; } @@ -628,11 +611,17 @@ __wlan_hdd_cfg80211_apf_offload(struct wiphy *wiphy, struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); struct nlattr *tb[APF_MAX + 1]; int ret_val = 0, apf_subcmd; - uint8_t session_id = adapter->session_id; - static struct hdd_apf_context *context = &apf_context; + struct hdd_apf_context *context; hdd_enter(); + if (!adapter) { + hdd_err("Adapter is null"); + return -EINVAL; + } + + context = &adapter->apf_context; + ret_val = wlan_hdd_validate_context(hdd_ctx); if (ret_val) return ret_val; @@ -642,8 +631,14 @@ __wlan_hdd_cfg80211_apf_offload(struct wiphy *wiphy, return -EINVAL; } - if (!hdd_ctx->apf_enabled) { - hdd_err("APF offload is not supported/enabled"); + if (!hdd_ctx->apf_supported) { + hdd_err("APF is not supported or disabled through INI"); + return -ENOTSUPP; + } + + if (!(adapter->device_mode == QDF_STA_MODE || + adapter->device_mode == QDF_P2P_CLIENT_MODE)) { + hdd_err("APF only supported in STA or P2P CLI modes!"); return -ENOTSUPP; } @@ -659,16 +654,11 @@ __wlan_hdd_cfg80211_apf_offload(struct wiphy *wiphy, } apf_subcmd = nla_get_u32(tb[APF_SUBCMD]); - if (!(adapter->device_mode == QDF_STA_MODE || - adapter->device_mode == QDF_P2P_CLIENT_MODE)) { - hdd_err("APF only supported in STA or P2P CLI modes!"); - return -ENOTSUPP; - } - + /* Do not allow simultaneous new APF commands on the same adapter */ qdf_spin_lock(&context->lock); if (context->cmd_in_progress) { qdf_spin_unlock(&context->lock); - hdd_err("Another APF cmd in progress, try again later!"); + hdd_err("Another cmd in progress for same session!"); return -EAGAIN; } context->cmd_in_progress = true; @@ -686,20 +676,16 @@ __wlan_hdd_cfg80211_apf_offload(struct wiphy *wiphy, /* APF 3.0 sub-commands */ case QCA_WLAN_WRITE_PACKET_FILTER: - ret_val = hdd_apf_write_memory(hdd_ctx, tb, session_id); + ret_val = hdd_apf_write_memory(adapter, tb); break; case QCA_WLAN_READ_PACKET_FILTER: - ret_val = hdd_apf_read_memory(hdd_ctx, tb, session_id); + ret_val = hdd_apf_read_memory(adapter, tb); break; case QCA_WLAN_ENABLE_PACKET_FILTER: - ret_val = hdd_enable_disable_apf(hdd_ctx, - session_id, - true); + ret_val = hdd_enable_disable_apf(adapter, true); break; case QCA_WLAN_DISABLE_PACKET_FILTER: - ret_val = hdd_enable_disable_apf(hdd_ctx, - session_id, - false); + ret_val = hdd_enable_disable_apf(adapter, false); break; default: hdd_err("Unknown APF Sub-command: %d", apf_subcmd); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 24041ac9dfe7..7111a7c396c2 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1860,6 +1860,29 @@ static int hdd_generate_macaddr_auto(struct hdd_context *hdd_ctx) return 0; } +#ifdef FEATURE_WLAN_APF +/** + * hdd_update_apf_support() - Update APF supported flag in hdd context + * @hdd_ctx: Pointer to hdd_ctx + * @cfg: target configuration + * + * Update the APF support flag in HDD Context using INI and target config. + * + * Return: None + */ +static void hdd_update_apf_support(struct hdd_context *hdd_ctx, + struct wma_tgt_cfg *cfg) +{ + hdd_ctx->apf_supported = (cfg->apf_enabled && + hdd_ctx->config->apf_packet_filter_enable); +} +#else +static void hdd_update_apf_support(struct hdd_context *hdd_ctx, + struct wma_tgt_cfg *cfg) +{ +} +#endif + /** * hdd_update_ra_rate_limit() - Update RA rate limit from target * configuration to cfg_ini in HDD @@ -2027,8 +2050,6 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg) hdd_debug("Init current antenna mode: %d", hdd_ctx->current_antenna_mode); - hdd_ctx->apf_enabled = (cfg->apf_enabled && - hdd_ctx->config->apf_packet_filter_enable); hdd_ctx->rcpi_enabled = cfg->rcpi_enabled; hdd_update_ra_rate_limit(hdd_ctx, cfg); @@ -2045,6 +2066,7 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg) if (QDF_IS_STATUS_ERROR(status)) hdd_err("fw update WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED to CFG fails"); + hdd_update_apf_support(hdd_ctx, cfg); hdd_debug("Target APF %d Host APF %d 8ss fw support %d txBFCsnValue %d", cfg->apf_enabled, hdd_ctx->config->apf_packet_filter_enable, @@ -4266,6 +4288,7 @@ static void hdd_cleanup_adapter(struct hdd_context *hdd_ctx, struct hdd_adapter hdd_nud_deinit_tracking(adapter); qdf_mutex_destroy(&adapter->disconnection_status_lock); + hdd_apf_context_destroy(adapter); hdd_debugfs_exit(adapter); @@ -4885,6 +4908,7 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio return NULL; } + hdd_apf_context_init(adapter); if (QDF_STATUS_SUCCESS == status) { policy_mgr_set_concurrency_mode(hdd_ctx->hdd_psoc, @@ -6828,8 +6852,6 @@ static int hdd_context_deinit(struct hdd_context *hdd_ctx) qdf_list_destroy(&hdd_ctx->hdd_adapters); - hdd_apf_context_destroy(); - return 0; } @@ -8760,8 +8782,6 @@ static int hdd_context_init(struct hdd_context *hdd_ctx) init_completion(&hdd_ctx->mc_sus_event_var); init_completion(&hdd_ctx->ready_to_suspend); - hdd_apf_context_init(); - qdf_spinlock_create(&hdd_ctx->connection_status_lock); qdf_spinlock_create(&hdd_ctx->sta_update_info_lock); qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);