Merge branch 'android-msm-wahoo-4.4-pi' into android-msm-wahoo-4.4-pi-qpr1
Bug: 112376366
Change-Id: Ia5a0b9f736d8c3cfc82e8dcfe69f2e842d4ffa46
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 6675f6f..eaf5e36 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -10,6 +10,7 @@
* GNU General Public License for more details.
*/
+#include <linux/module.h>
#include <linux/device.h>
#include <linux/ipc_logging.h>
#include <linux/regmap.h>
@@ -61,6 +62,11 @@
} while (0)
#define NUM_LOG_PAGES 10
+static bool enable_ovh = true;
+module_param_named(
+ enable_ovh, enable_ovh, bool, 0600
+);
+
static bool is_secure(struct smb_charger *chg, int addr)
{
if (addr == SHIP_MODE_REG || addr == FREQ_CLK_DIV_REG)
@@ -3598,7 +3604,7 @@
struct smb_charger *chg,
u8 stat)
{
- if (!chg->port_overheat_mitigation_enabled)
+ if (!chg->port_overheat_mitigation_enabled || !enable_ovh)
return;
cancel_delayed_work_sync(&chg->port_overheat_work);
@@ -4842,7 +4848,7 @@
smblib_err(chg, "USB port overheat detected, temp=%d\n", temp);
if (chg->port_overheat &&
- temp < chg->port_overheat_mitigation_end_temp) {
+ (temp < chg->port_overheat_mitigation_end_temp || !enable_ovh)) {
/* check if the cable is still there */
mutex_lock(&chg->typec_pr_lock);
rc = port_overheat_probe_cc_status_locked(chg, &attached);
@@ -4853,7 +4859,7 @@
goto rerun;
}
/* temperature drops and cable unplugged */
- if (!attached) {
+ if (!attached || !enable_ovh) {
smblib_err(chg, "Port overheat mitigation ends.\n");
rc = port_overheat_mitigation_end(chg);
if (rc < 0) {
@@ -4865,7 +4871,7 @@
}
chg->port_overheat = false;
}
- } else if (!chg->port_overheat &&
+ } else if (!chg->port_overheat && enable_ovh &&
temp > chg->port_overheat_mitigation_begin_temp) {
smblib_err(chg, "Port overheat mitigation begins.\n");
rc = port_overheat_mitigation_begin(chg);
diff --git a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h
index b6bf79e..baa5f61 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h
+++ b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h
@@ -412,26 +412,6 @@
unsigned int magic;
};
-struct linkspeedContext {
- struct completion completion;
- hdd_adapter_t *pAdapter;
- unsigned int magic;
-};
-
-/**
- * struct random_mac_context - Context used with hdd_random_mac_callback
- * @random_mac_completion: Event on which hdd_set_random_mac will wait
- * @adapter: Pointer to adapter
- * @magic: For valid context this is set to ACTION_FRAME_RANDOM_CONTEXT_MAGIC
- * @set_random_addr: Status of random filter set
- */
-struct random_mac_context {
- struct completion random_mac_completion;
- hdd_adapter_t *adapter;
- unsigned int magic;
- bool set_random_addr;
-};
-
extern spinlock_t hdd_context_lock;
extern struct mutex hdd_init_deinit_lock;
@@ -439,12 +419,9 @@
#define PEER_INFO_CONTEXT_MAGIC 0x50494E46 /* PEER_INFO(PINF) */
#define POWER_CONTEXT_MAGIC 0x504F5752 /* POWR */
#define SNR_CONTEXT_MAGIC 0x534E5200 /* SNR */
-#define LINK_CONTEXT_MAGIC 0x4C494E4B /* LINKSPEED */
#define LINK_STATUS_MAGIC 0x4C4B5354 /* LINKSTATUS(LNST) */
-#define TEMP_CONTEXT_MAGIC 0x74656d70 /* TEMP (temperature) */
#define APF_CONTEXT_MAGIC 0x4575354 /* APF */
#define POWER_STATS_MAGIC 0x14111990
-#define RCPI_CONTEXT_MAGIC 0x7778888 /* RCPI */
#define ACTION_FRAME_RANDOM_CONTEXT_MAGIC 0x87878787
/* MAX OS Q block time value in msec
@@ -1325,8 +1302,9 @@
struct net_device_stats stats;
/** HDD statistics*/
hdd_stats_t hdd_stats;
- /** linkspeed statistics */
- tSirLinkSpeedInfo ls_stats;
+
+ /* estimated link speed */
+ u32 estimated_linkspeed;
/* SAP peer station info */
struct sir_peer_sta_info peer_sta_info;
@@ -1495,14 +1473,8 @@
/* Time stamp for start RoC request */
uint64_t start_roc_ts;
- /* State for synchronous OCB requests to WMI */
- struct sir_ocb_set_config_response ocb_set_config_resp;
- struct sir_ocb_get_tsf_timer_response ocb_get_tsf_timer_resp;
- struct sir_dcc_get_stats_response *dcc_get_stats_resp;
- struct sir_dcc_update_ndl_response dcc_update_ndl_resp;
-
- /* MAC addresses used for OCB interfaces */
#ifdef WLAN_FEATURE_DSRC
+ /* MAC addresses used for OCB interfaces */
struct qdf_mac_addr ocb_mac_address[QDF_MAX_CONCURRENCY_PERSONA];
int ocb_mac_addr_count;
#endif
diff --git a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_wext.h b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_wext.h
index 7f20207..775f76c 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_wext.h
+++ b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_wext.h
@@ -374,8 +374,20 @@
extern void *mem_alloc_copy_from_user_helper(const void *wrqu_data, size_t len);
-int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter,
- struct qdf_mac_addr mac_address);
+/**
+ * wlan_hdd_get_linkspeed_for_peermac() - Get link speed for a peer
+ * @adapter: adapter upon which the peer is active
+ * @mac_address: MAC address of the peer
+ * @linkspeed: pointer to memory where returned link speed is to be placed
+ *
+ * This function will send a query to SME for the linkspeed of the
+ * given peer, and then wait for the callback to be invoked.
+ *
+ * Return: 0 if linkspeed data is available, negative errno otherwise
+ */
+int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *adapter,
+ struct qdf_mac_addr *mac_address,
+ uint32_t *linkspeed);
void hdd_clear_roam_profile_ie(hdd_adapter_t *pAdapter);
uint8_t *wlan_hdd_get_vendor_oui_ie_ptr(uint8_t *oui, uint8_t oui_size,
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c
index eaef455..c410f7f 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c
@@ -3994,6 +3994,10 @@
return -EINVAL;
}
+struct peer_txrx_rate_priv {
+ struct sir_peer_info_ext peer_info_ext;
+};
+
/**
* hdd_get_peer_txrx_rate_cb() - get station's txrx rate callback
* @peer_info: pointer of peer information
@@ -4005,66 +4009,33 @@
static void hdd_get_peer_txrx_rate_cb(struct sir_peer_info_ext_resp *peer_info,
void *context)
{
- struct statsContext *get_txrx_rate_context;
- struct sir_peer_info_ext *txrx_rate;
- hdd_adapter_t *adapter;
- uint8_t staid;
+ struct hdd_request *request;
+ struct peer_txrx_rate_priv *priv;
- if ((peer_info == NULL) || (context == NULL)) {
- hdd_err("Bad param, peer_info [%pK] context [%pK]",
- peer_info, context);
- return;
- }
-
- spin_lock(&hdd_context_lock);
- /*
- * there is a race condition that exists between this callback
- * function and the caller since the caller could time out either
- * before or while this code is executing. we use a spinlock to
- * serialize these actions
- */
- get_txrx_rate_context = context;
- if (get_txrx_rate_context->magic != PEER_INFO_CONTEXT_MAGIC) {
- /*
- * the caller presumably timed out so there is nothing
- * we can do
- */
- spin_unlock(&hdd_context_lock);
- hdd_warn("Invalid context, magic [%08x]",
- get_txrx_rate_context->magic);
+ if (NULL == peer_info) {
+ hdd_err("Bad param, peer_info [%pK]", peer_info);
return;
}
if (!peer_info->count) {
- spin_unlock(&hdd_context_lock);
hdd_err("Fail to get remote peer info");
return;
}
- adapter = get_txrx_rate_context->pAdapter;
- txrx_rate = peer_info->info;
- if (hdd_softap_get_sta_id(adapter,
- &txrx_rate->peer_macaddr,
- &staid) != QDF_STATUS_SUCCESS) {
- spin_unlock(&hdd_context_lock);
- hdd_err("Station MAC address does not matching");
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("Obsolete request");
return;
}
- adapter->aStaInfo[staid].tx_rate = txrx_rate->tx_rate;
- adapter->aStaInfo[staid].rx_rate = txrx_rate->rx_rate;
- hdd_debug("%pM txrate %u rxrate %u",
- txrx_rate->peer_macaddr.bytes,
- adapter->aStaInfo[staid].tx_rate,
- adapter->aStaInfo[staid].rx_rate);
+ priv = hdd_request_priv(request);
- get_txrx_rate_context->magic = 0;
+ qdf_mem_copy(&priv->peer_info_ext,
+ peer_info->info,
+ sizeof(peer_info->info[0]));
- /* notify the caller */
- complete(&get_txrx_rate_context->completion);
-
- /* serialization is complete */
- spin_unlock(&hdd_context_lock);
+ hdd_request_complete(request);
+ hdd_request_put(request);
}
/**
@@ -4081,17 +4052,30 @@
{
QDF_STATUS status;
int ret;
- static struct statsContext context;
+ uint8_t staid;
+ void *cookie;
struct sir_peer_info_ext_req txrx_rate_req;
+ struct hdd_request *request;
+ struct peer_txrx_rate_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_STATS,
+ };
if (adapter == NULL) {
hdd_err("pAdapter is NULL");
return -EFAULT;
}
- init_completion(&context.completion);
- context.magic = PEER_INFO_CONTEXT_MAGIC;
- context.pAdapter = adapter;
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("%s: Request allocation failure",
+ __func__);
+ return -ENOMEM;
+ }
+
+ cookie = hdd_request_cookie(request);
+ priv = hdd_request_priv(request);
qdf_mem_copy(&(txrx_rate_req.peer_macaddr), &macaddress,
QDF_MAC_ADDR_SIZE);
@@ -4099,36 +4083,38 @@
txrx_rate_req.reset_after_request = 0;
status = sme_get_peer_info_ext(WLAN_HDD_GET_HAL_CTX(adapter),
&txrx_rate_req,
- &context,
+ cookie,
hdd_get_peer_txrx_rate_cb);
if (status != QDF_STATUS_SUCCESS) {
hdd_err("Unable to retrieve statistics for txrx_rate");
ret = -EFAULT;
} else {
- if (!wait_for_completion_timeout(&context.completion,
- msecs_to_jiffies(WLAN_WAIT_TIME_STATS))) {
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
hdd_err("SME timed out while retrieving txrx_rate");
ret = -EFAULT;
} else {
- ret = 0;
+ if (hdd_softap_get_sta_id(adapter,
+ &priv->peer_info_ext.peer_macaddr,
+ &staid) != QDF_STATUS_SUCCESS) {
+ hdd_err("Station MAC address does not matching");
+ ret = -EFAULT;
+ } else {
+ adapter->aStaInfo[staid].tx_rate =
+ priv->peer_info_ext.tx_rate;
+ adapter->aStaInfo[staid].rx_rate =
+ priv->peer_info_ext.rx_rate;
+
+ hdd_info("%pM tx rate %u rx rate %u",
+ priv->peer_info_ext.peer_macaddr.bytes,
+ adapter->aStaInfo[staid].tx_rate,
+ adapter->aStaInfo[staid].rx_rate);
+ ret = 0;
+ }
}
}
- /*
- * either we never sent a request, we sent a request and received a
- * response or we sent a request and timed out. if we never sent a
- * request or if we sent a request and got a response, we want to
- * clear the magic out of paranoia. if we timed out there is a
- * race condition such that the callback function could be
- * executing at the same time we are. of primary concern is if the
- * callback function had already verified the "magic" but had not
- * yet set the completion variable when a timeout occurred. we
- * serialize these activities by invalidating the magic while
- * holding a shared spinlock which will cause us to block if the
- * callback is currently executing
- */
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
+
+ hdd_request_put(request);
return ret;
}
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c
index 5607444..2de35cf 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c
@@ -5724,15 +5724,13 @@
hdd_err("Invalid peer macaddress");
return -EINVAL;
}
- errno = wlan_hdd_get_linkspeed_for_peermac(pHostapdAdapter,
- macAddress);
- if (errno) {
+ rc = wlan_hdd_get_linkspeed_for_peermac(pHostapdAdapter, &macAddress,
+ &link_speed);
+ if (rc) {
hdd_err("Unable to retrieve SME linkspeed: %d", errno);
- return errno;
+ return rc;
}
- link_speed = pHostapdAdapter->ls_stats.estLinkSpeed;
-
/* linkspeed in units of 500 kbps */
link_speed = link_speed / 500;
wrqu->data.length = len;
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c
index 115f18b..892da8f 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c
@@ -40,6 +40,7 @@
#include <linux/ctype.h>
#include "wma.h"
#include "wlan_hdd_napi.h"
+#include "wlan_hdd_request_manager.h"
#ifdef FEATURE_WLAN_ESE
#include <sme_api.h>
@@ -153,138 +154,82 @@
}
#ifdef FEATURE_WLAN_ESE
+struct tsm_priv {
+ tAniTrafStrmMetrics tsm_metrics;
+};
+
static void hdd_get_tsm_stats_cb(tAniTrafStrmMetrics tsm_metrics,
const uint32_t staId, void *context)
{
- struct statsContext *stats_context = NULL;
- hdd_adapter_t *adapter = NULL;
+ struct hdd_request *request;
+ struct tsm_priv *priv;
- if (NULL == context) {
- hdd_err("Bad param, context [%pK]", context);
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("Obsolete request");
return;
}
- /*
- * there is a race condition that exists between this callback
- * function and the caller since the caller could time out either
- * before or while this code is executing. we use a spinlock to
- * serialize these actions
- */
- spin_lock(&hdd_context_lock);
-
- stats_context = context;
- adapter = stats_context->pAdapter;
- if ((NULL == adapter) ||
- (STATS_CONTEXT_MAGIC != stats_context->magic)) {
- /*
- * the caller presumably timed out so there is
- * nothing we can do
- */
- spin_unlock(&hdd_context_lock);
- hdd_warn("Invalid context, adapter [%pK] magic [%08x]",
- adapter, stats_context->magic);
- return;
- }
-
- /* context is valid so caller is still waiting */
-
- /* paranoia: invalidate the magic */
- stats_context->magic = 0;
-
- /* copy over the tsm stats */
- adapter->tsmStats.UplinkPktQueueDly = tsm_metrics.UplinkPktQueueDly;
- qdf_mem_copy(adapter->tsmStats.UplinkPktQueueDlyHist,
- tsm_metrics.UplinkPktQueueDlyHist,
- sizeof(adapter->tsmStats.UplinkPktQueueDlyHist) /
- sizeof(adapter->tsmStats.UplinkPktQueueDlyHist[0]));
- adapter->tsmStats.UplinkPktTxDly = tsm_metrics.UplinkPktTxDly;
- adapter->tsmStats.UplinkPktLoss = tsm_metrics.UplinkPktLoss;
- adapter->tsmStats.UplinkPktCount = tsm_metrics.UplinkPktCount;
- adapter->tsmStats.RoamingCount = tsm_metrics.RoamingCount;
- adapter->tsmStats.RoamingDly = tsm_metrics.RoamingDly;
-
- /* notify the caller */
- complete(&stats_context->completion);
-
- /* serialization is complete */
- spin_unlock(&hdd_context_lock);
+ priv = hdd_request_priv(request);
+ priv->tsm_metrics = tsm_metrics;
+ hdd_request_complete(request);
+ hdd_request_put(request);
+ EXIT();
}
-static
-QDF_STATUS hdd_get_tsm_stats(hdd_adapter_t *adapter,
+static int hdd_get_tsm_stats(hdd_adapter_t *adapter,
const uint8_t tid,
tAniTrafStrmMetrics *tsm_metrics)
{
- hdd_station_ctx_t *hdd_sta_ctx = NULL;
- QDF_STATUS hstatus;
- QDF_STATUS vstatus = QDF_STATUS_SUCCESS;
- unsigned long rc;
- static struct statsContext context;
- hdd_context_t *hdd_ctx = NULL;
+ hdd_context_t *hdd_ctx;
+ hdd_station_ctx_t *hdd_sta_ctx;
+ QDF_STATUS status;
+ int ret;
+ void *cookie;
+ struct hdd_request *request;
+ struct tsm_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_STATS,
+ };
if (NULL == adapter) {
hdd_err("adapter is NULL");
- return QDF_STATUS_E_FAULT;
+ return -EINVAL;
}
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
- /* we are connected prepare our callback context */
- init_completion(&context.completion);
- context.pAdapter = adapter;
- context.magic = STATS_CONTEXT_MAGIC;
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("Request allocation failure");
+ return -ENOMEM;
+ }
+ cookie = hdd_request_cookie(request);
- /* query tsm stats */
- hstatus = sme_get_tsm_stats(hdd_ctx->hHal, hdd_get_tsm_stats_cb,
- hdd_sta_ctx->conn_info.staId[0],
- hdd_sta_ctx->conn_info.bssId,
- &context, hdd_ctx->pcds_context, tid);
- if (QDF_STATUS_SUCCESS != hstatus) {
- hdd_err("Unable to retrieve statistics");
- vstatus = QDF_STATUS_E_FAULT;
- } else {
- /* request was sent -- wait for the response */
- rc = wait_for_completion_timeout(&context.completion,
- msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
- if (!rc) {
- hdd_err("SME timed out while retrieving statistics");
- vstatus = QDF_STATUS_E_TIMEOUT;
- }
+ status = sme_get_tsm_stats(hdd_ctx->hHal, hdd_get_tsm_stats_cb,
+ hdd_sta_ctx->conn_info.staId[0],
+ hdd_sta_ctx->conn_info.bssId,
+ cookie, hdd_ctx->pcds_context, tid);
+ if (QDF_STATUS_SUCCESS != status) {
+ hdd_err("Unable to retrieve tsm statistics");
+ ret = qdf_status_to_os_return(status);
+ goto cleanup;
}
- /*
- * either we never sent a request, we sent a request and received a
- * response or we sent a request and timed out. if we never sent a
- * request or if we sent a request and got a response, we want to
- * clear the magic out of paranoia. if we timed out there is a
- * race condition such that the callback function could be
- * executing at the same time we are. of primary concern is if the
- * callback function had already verified the "magic" but had not
- * yet set the completion variable when a timeout occurred. we
- * serialize these activities by invalidating the magic while
- * holding a shared spinlock which will cause us to block if the
- * callback is currently executing
- */
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
-
- if (QDF_STATUS_SUCCESS == vstatus) {
- tsm_metrics->UplinkPktQueueDly =
- adapter->tsmStats.UplinkPktQueueDly;
- qdf_mem_copy(tsm_metrics->UplinkPktQueueDlyHist,
- adapter->tsmStats.UplinkPktQueueDlyHist,
- sizeof(adapter->tsmStats.UplinkPktQueueDlyHist) /
- sizeof(adapter->tsmStats.
- UplinkPktQueueDlyHist[0]));
- tsm_metrics->UplinkPktTxDly = adapter->tsmStats.UplinkPktTxDly;
- tsm_metrics->UplinkPktLoss = adapter->tsmStats.UplinkPktLoss;
- tsm_metrics->UplinkPktCount = adapter->tsmStats.UplinkPktCount;
- tsm_metrics->RoamingCount = adapter->tsmStats.RoamingCount;
- tsm_metrics->RoamingDly = adapter->tsmStats.RoamingDly;
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
+ hdd_err("SME timed out while retrieving tsm statistics");
+ goto cleanup;
}
- return vstatus;
+
+ priv = hdd_request_priv(request);
+ *tsm_metrics = priv->tsm_metrics;
+
+cleanup:
+ hdd_request_put(request);
+ return ret;
}
#endif /*FEATURE_WLAN_ESE */
@@ -5413,7 +5358,7 @@
int len = 0;
uint8_t tid = 0;
hdd_station_ctx_t *pHddStaCtx;
- tAniTrafStrmMetrics tsm_metrics;
+ tAniTrafStrmMetrics tsm_metrics = {0};
if ((QDF_STA_MODE != adapter->device_mode) &&
(QDF_P2P_CLIENT_MODE != adapter->device_mode)) {
@@ -5456,10 +5401,9 @@
}
hdd_debug("Received Command to get tsm stats tid = %d",
tid);
- if (QDF_STATUS_SUCCESS !=
- hdd_get_tsm_stats(adapter, tid, &tsm_metrics)) {
+ ret = hdd_get_tsm_stats(adapter, tid, &tsm_metrics);
+ if (ret) {
hdd_err("failed to get tsm stats");
- ret = -EFAULT;
goto exit;
}
hdd_debug(
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c
index cf2b709..4112efd 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c
@@ -1205,7 +1205,8 @@
if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
&value) == QDF_STATUS_SUCCESS) {
hdd_debug("Read MCS rate set");
-
+ if (cfg->num_rf_chains > SIZE_OF_SUPPORTED_MCS_SET)
+ cfg->num_rf_chains = SIZE_OF_SUPPORTED_MCS_SET;
if (pconfig->enable2x2) {
for (value = 0; value < cfg->num_rf_chains; value++)
mcs_set[value] =
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ocb.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ocb.c
index a613d10..f8ec040 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ocb.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ocb.c
@@ -37,6 +37,7 @@
#include "wlan_hdd_ocb.h"
#include "wlan_hdd_trace.h"
#include "wlan_tgt_def_config.h"
+#include "wlan_hdd_request_manager.h"
#include "sch_api.h"
#include "wma_api.h"
#include "ol_txrx.h"
@@ -50,20 +51,6 @@
/* Maximum time(ms) to wait for OCB operations */
#define WLAN_WAIT_TIME_OCB_CMD 1500
-#define HDD_OCB_MAGIC 0x489a154f
-
-/**
- * struct hdd_ocb_ctxt - Context for OCB operations
- * adapter: the ocb adapter
- * completion_evt: the completion event
- * status: status of the request
- */
-struct hdd_ocb_ctxt {
- uint32_t magic;
- hdd_adapter_t *adapter;
- struct completion completion_evt;
- int status;
-};
/**
* hdd_set_dot11p_config() - Set 802.11p config flag
@@ -348,6 +335,11 @@
return NULL;
}
+struct hdd_ocb_set_config_priv {
+ int status;
+};
+
+
/**
* hdd_ocb_set_config_callback() - OCB set config callback function
* @context_ptr: OCB call context
@@ -358,47 +350,27 @@
*/
static void hdd_ocb_set_config_callback(void *context_ptr, void *response_ptr)
{
- struct hdd_ocb_ctxt *context = context_ptr;
- struct sir_ocb_set_config_response *resp = response_ptr;
+ struct hdd_request *hdd_request;
+ struct hdd_ocb_set_config_priv *priv;
+ struct sir_ocb_set_config_response *response = response_ptr;
- if (!context)
+ hdd_request = hdd_request_get(context_ptr);
+ if (!hdd_request) {
+ hdd_err("Obsolete request");
return;
-
- if (resp && resp->status)
- hdd_warn("Operation failed: %d", resp->status);
-
- spin_lock(&hdd_context_lock);
- if (context->magic == HDD_OCB_MAGIC) {
- hdd_adapter_t *adapter = context->adapter;
-
- if (!resp) {
- context->status = -EINVAL;
- complete(&context->completion_evt);
- spin_unlock(&hdd_context_lock);
- return;
- }
-
- context->adapter->ocb_set_config_resp = *resp;
- spin_unlock(&hdd_context_lock);
- if (!resp->status) {
- /*
- * OCB set config command successful.
- * Open the TX data path
- */
- if (!hdd_ocb_register_sta(adapter)) {
- wlan_hdd_netif_queue_control(adapter,
- WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
- WLAN_CONTROL_PATH);
- }
- }
-
- spin_lock(&hdd_context_lock);
- if (context->magic == HDD_OCB_MAGIC)
- complete(&context->completion_evt);
- spin_unlock(&hdd_context_lock);
- } else {
- spin_unlock(&hdd_context_lock);
}
+ priv = hdd_request_priv(hdd_request);
+
+ if (response && response->status)
+ hdd_warn("Operation failed: %d", response->status);
+
+ if (response && (0 == response->status))
+ priv->status = 0;
+ else
+ priv->status = -EINVAL;
+
+ hdd_request_complete(hdd_request);
+ hdd_request_put(hdd_request);
}
/**
@@ -412,59 +384,70 @@
struct sir_ocb_config *config)
{
int rc;
- QDF_STATUS qdf_status;
- struct hdd_ocb_ctxt context = {0};
+ QDF_STATUS status;
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ void *cookie;
+ struct hdd_request *hdd_request;
+ struct hdd_ocb_set_config_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
+ };
if (hdd_ocb_validate_config(adapter, config)) {
hdd_err("The configuration is invalid");
return -EINVAL;
}
- init_completion(&context.completion_evt);
- context.adapter = adapter;
- context.magic = HDD_OCB_MAGIC;
+ hdd_request = hdd_request_alloc(¶ms);
+ if (!hdd_request) {
+ hdd_err("Request allocation failure");
+ return -ENOMEM;
+ }
+ cookie = hdd_request_cookie(hdd_request);
- hdd_info("Disabling queues");
+ hdd_debug("Disabling queues");
wlan_hdd_netif_queue_control(adapter,
WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
WLAN_CONTROL_PATH);
- /* Call the SME API to set the config */
- qdf_status = sme_ocb_set_config(
- ((hdd_context_t *)adapter->pHddCtx)->hHal, &context,
- hdd_ocb_set_config_callback, config);
- if (qdf_status != QDF_STATUS_SUCCESS) {
- hdd_err("Error calling SME function.");
- /* Convert from qdf_status to errno */
- return -EINVAL;
+ status = sme_ocb_set_config(hdd_ctx->hHal, cookie,
+ hdd_ocb_set_config_callback,
+ config);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ hdd_err("Failed to set channel config.");
+ /* Convert from eHalStatus to errno */
+ rc = qdf_status_to_os_return(status);
+ goto end;
}
/* Wait for the function to complete. */
- rc = wait_for_completion_timeout(&context.completion_evt,
- msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD));
- if (rc == 0) {
- rc = -ETIMEDOUT;
- goto end;
- }
- rc = 0;
-
- if (context.status) {
- rc = context.status;
+ rc = hdd_request_wait_for_response(hdd_request);
+ if (rc) {
+ hdd_err("Operation timed out");
goto end;
}
- if (adapter->ocb_set_config_resp.status) {
- rc = -EINVAL;
+ priv = hdd_request_priv(hdd_request);
+ rc = priv->status;
+ if (rc) {
+ hdd_err("Operation failed: %d", rc);
goto end;
}
+ /*
+ * OCB set config command successful.
+ * Open the TX data path
+ */
+ if (!hdd_ocb_register_sta(adapter))
+ wlan_hdd_netif_queue_control(adapter,
+ WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
+ WLAN_CONTROL_PATH);
+
/* fall through */
end:
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
- if (rc)
- hdd_err("Operation failed: %d", rc);
+ hdd_request_put(hdd_request);
+
return rc;
}
@@ -1314,6 +1297,11 @@
return ret;
}
+struct hdd_ocb_get_tsf_timer_priv {
+ struct sir_ocb_get_tsf_timer_response response;
+ int status;
+};
+
/**
* hdd_ocb_get_tsf_timer_callback() - Callback to get TSF command
* @context_ptr: request context
@@ -1322,23 +1310,67 @@
static void hdd_ocb_get_tsf_timer_callback(void *context_ptr,
void *response_ptr)
{
- struct hdd_ocb_ctxt *context = context_ptr;
+ struct hdd_request *hdd_request;
+ struct hdd_ocb_get_tsf_timer_priv *priv;
struct sir_ocb_get_tsf_timer_response *response = response_ptr;
- if (!context)
+ hdd_request = hdd_request_get(context_ptr);
+ if (!hdd_request) {
+ hdd_err("Obsolete request");
return;
-
- spin_lock(&hdd_context_lock);
- if (context->magic == HDD_OCB_MAGIC) {
- if (response) {
- context->adapter->ocb_get_tsf_timer_resp = *response;
- context->status = 0;
- } else {
- context->status = -EINVAL;
- }
- complete(&context->completion_evt);
}
- spin_unlock(&hdd_context_lock);
+
+ if (response) {
+ priv->response = *response;
+ priv->status = 0;
+ } else {
+ priv->status = -EINVAL;
+ }
+ hdd_request_complete(hdd_request);
+ hdd_request_put(hdd_request);
+}
+
+static int
+hdd_ocb_get_tsf_timer_reply(struct wiphy *wiphy,
+ struct sir_ocb_get_tsf_timer_response *response)
+{
+ uint32_t nl_buf_len;
+ struct sk_buff *nl_resp;
+ int rc;
+
+ /* Allocate the buffer for the response. */
+ nl_buf_len = NLMSG_HDRLEN;
+ nl_buf_len += 2 * (NLA_HDRLEN + sizeof(uint32_t));
+ nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len);
+ if (!nl_resp) {
+ hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
+ return -ENOMEM;
+ }
+
+ /* Populate the response. */
+ rc = nla_put_u32(nl_resp,
+ QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH,
+ response->timer_high);
+ if (rc)
+ goto end;
+ rc = nla_put_u32(nl_resp,
+ QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW,
+ response->timer_low);
+ if (rc)
+ goto end;
+
+ /* Send the response. */
+ rc = cfg80211_vendor_cmd_reply(nl_resp);
+ nl_resp = NULL;
+ if (rc) {
+ hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc);
+ goto end;
+ }
+end:
+ if (nl_resp)
+ kfree_skb(nl_resp);
+
+ return rc;
}
/**
@@ -1356,18 +1388,25 @@
const void *data,
int data_len)
{
- struct sk_buff *nl_resp = 0;
hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
struct net_device *dev = wdev->netdev;
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
- int rc = -EINVAL;
+ int rc;
struct sir_ocb_get_tsf_timer request = {0};
- struct hdd_ocb_ctxt context = {0};
+ QDF_STATUS status;
+ void *cookie;
+ struct hdd_request *hdd_request;
+ struct hdd_ocb_get_tsf_timer_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
+ };
ENTER_DEV(dev);
- if (wlan_hdd_validate_context(hdd_ctx))
- return -EINVAL;
+ rc = wlan_hdd_validate_context(hdd_ctx);
+ if (rc)
+ return rc;
if (adapter->device_mode != QDF_OCB_MODE) {
hdd_err("Device not in OCB mode!");
@@ -1379,77 +1418,52 @@
return -EINVAL;
}
- /* Initialize the callback context */
- init_completion(&context.completion_evt);
- context.adapter = adapter;
- context.magic = HDD_OCB_MAGIC;
+ hdd_request = hdd_request_alloc(¶ms);
+ if (!hdd_request) {
+ hdd_err("Request allocation failure");
+ return -ENOMEM;
+ }
+ cookie = hdd_request_cookie(hdd_request);
request.vdev_id = adapter->sessionId;
/* Call the SME function */
- rc = sme_ocb_get_tsf_timer(hdd_ctx->hHal, &context,
- hdd_ocb_get_tsf_timer_callback,
- &request);
+ status = sme_ocb_get_tsf_timer(hdd_ctx->hHal, cookie,
+ hdd_ocb_get_tsf_timer_callback,
+ &request);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ hdd_err("Failed to get tsf timer.");
+ rc = qdf_status_to_os_return(status);
+ goto end;
+ }
+
+ rc = hdd_request_wait_for_response(hdd_request);
if (rc) {
- hdd_err("Error calling SME function");
- /* Need to convert from qdf_status to errno. */
- return -EINVAL;
- }
-
- rc = wait_for_completion_timeout(&context.completion_evt,
- msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD));
- if (rc == 0) {
hdd_err("Operation timed out");
- rc = -ETIMEDOUT;
- goto end;
- }
- rc = 0;
-
- if (context.status) {
- hdd_err("Operation failed: %d", context.status);
- rc = context.status;
goto end;
}
- /* Allocate the buffer for the response. */
- nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
- 2 * sizeof(uint32_t) + NLMSG_HDRLEN);
-
- if (!nl_resp) {
- hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
- rc = -ENOMEM;
+ priv = hdd_request_priv(hdd_request);
+ rc = priv->status;
+ if (rc) {
+ hdd_err("Operation failed: %d", rc);
goto end;
}
hdd_debug("Got TSF timer response, high=%d, low=%d",
- adapter->ocb_get_tsf_timer_resp.timer_high,
- adapter->ocb_get_tsf_timer_resp.timer_low);
-
- /* Populate the response. */
- rc = nla_put_u32(nl_resp,
- QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH,
- adapter->ocb_get_tsf_timer_resp.timer_high);
- if (rc)
- goto end;
- rc = nla_put_u32(nl_resp,
- QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW,
- adapter->ocb_get_tsf_timer_resp.timer_low);
- if (rc)
- goto end;
+ priv->response.timer_high,
+ priv->response.timer_low);
/* Send the response. */
- rc = cfg80211_vendor_cmd_reply(nl_resp);
- nl_resp = NULL;
+ rc = hdd_ocb_get_tsf_timer_reply(wiphy, &priv->response);
if (rc) {
- hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc);
+ hdd_err("hdd_ocb_get_tsf_timer_reply failed: %d", rc);
goto end;
}
+ /* fall through */
end:
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
- if (nl_resp)
- kfree_skb(nl_resp);
+ hdd_request_put(hdd_request);
+
return rc;
}
@@ -1477,6 +1491,19 @@
return ret;
}
+struct hdd_dcc_stats_priv {
+ struct sir_dcc_get_stats_response *response;
+ int status;
+};
+
+static void hdd_dcc_get_stats_dealloc(void *context_ptr)
+{
+ struct hdd_dcc_stats_priv *priv = context_ptr;
+
+ qdf_mem_free(priv->response);
+ priv->response = NULL;
+}
+
/**
* hdd_dcc_get_stats_callback() - Callback to get stats command
* @context_ptr: request context
@@ -1484,46 +1511,86 @@
*/
static void hdd_dcc_get_stats_callback(void *context_ptr, void *response_ptr)
{
- struct hdd_ocb_ctxt *context = context_ptr;
+ struct hdd_request *hdd_request;
+ struct hdd_dcc_stats_priv *priv;
struct sir_dcc_get_stats_response *response = response_ptr;
struct sir_dcc_get_stats_response *hdd_resp;
- if (!context)
+ hdd_request = hdd_request_get(context_ptr);
+ if (!hdd_request) {
+ hdd_err("Obsolete request");
return;
-
- spin_lock(&hdd_context_lock);
- if (context->magic == HDD_OCB_MAGIC) {
- if (response) {
- /*
- * If the response is hanging around from the previous
- * request, delete it
- */
- if (context->adapter->dcc_get_stats_resp) {
- qdf_mem_free(
- context->adapter->dcc_get_stats_resp);
- }
- context->adapter->dcc_get_stats_resp =
- qdf_mem_malloc(sizeof(
- *context->adapter->dcc_get_stats_resp) +
- response->channel_stats_array_len);
- if (context->adapter->dcc_get_stats_resp) {
- hdd_resp = context->adapter->dcc_get_stats_resp;
- *hdd_resp = *response;
- hdd_resp->channel_stats_array =
- (void *)hdd_resp + sizeof(*hdd_resp);
- qdf_mem_copy(hdd_resp->channel_stats_array,
- response->channel_stats_array,
- response->channel_stats_array_len);
- context->status = 0;
- } else {
- context->status = -ENOMEM;
- }
- } else {
- context->status = -EINVAL;
- }
- complete(&context->completion_evt);
}
- spin_unlock(&hdd_context_lock);
+
+ priv = hdd_request_priv(hdd_request);
+ if (!response) {
+ priv->status = -EINVAL;
+ goto end;
+ }
+
+ priv->response = qdf_mem_malloc(sizeof(*response) +
+ response->channel_stats_array_len);
+ if (!priv->response) {
+ priv->status = -ENOMEM;
+ goto end;
+ }
+
+ hdd_resp = priv->response;
+ *hdd_resp = *response;
+ hdd_resp->channel_stats_array = (void *)hdd_resp + sizeof(*hdd_resp);
+ qdf_mem_copy(hdd_resp->channel_stats_array,
+ response->channel_stats_array,
+ response->channel_stats_array_len);
+ priv->status = 0;
+
+end:
+ hdd_request_complete(hdd_request);
+ hdd_request_put(hdd_request);
+}
+
+static int
+hdd_dcc_get_stats_send_reply(struct wiphy *wiphy,
+ struct sir_dcc_get_stats_response *response)
+{
+ uint32_t nl_buf_len;
+ struct sk_buff *nl_resp;
+ int rc;
+
+ /* Allocate the buffer for the response. */
+ nl_buf_len = NLMSG_HDRLEN;
+ nl_buf_len += NLA_HDRLEN + sizeof(uint32_t);
+ nl_buf_len += NLA_HDRLEN + response->channel_stats_array_len;
+ nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len);
+ if (!nl_resp) {
+ hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
+ return -ENOMEM;
+ }
+
+ /* Populate the response. */
+ rc = nla_put_u32(nl_resp,
+ QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT,
+ response->num_channels);
+ if (rc)
+ goto end;
+ rc = nla_put(nl_resp,
+ QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY,
+ response->channel_stats_array_len,
+ response->channel_stats_array);
+ if (rc)
+ goto end;
+
+ /* Send the response. */
+ rc = cfg80211_vendor_cmd_reply(nl_resp);
+ nl_resp = NULL;
+ if (rc) {
+ hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc);
+ goto end;
+ }
+end:
+ if (nl_resp)
+ kfree_skb(nl_resp);
+
+ return rc;
}
/**
@@ -1547,15 +1614,23 @@
struct net_device *dev = wdev->netdev;
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_MAX + 1];
- struct sk_buff *nl_resp = 0;
- int rc = -EINVAL;
+ int rc;
struct sir_dcc_get_stats request = {0};
- struct hdd_ocb_ctxt context = {0};
+ QDF_STATUS status;
+ void *cookie;
+ struct hdd_request *hdd_request;
+ struct hdd_dcc_stats_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
+ .dealloc = hdd_dcc_get_stats_dealloc,
+ };
ENTER_DEV(dev);
- if (wlan_hdd_validate_context(hdd_ctx))
- return -EINVAL;
+ rc = wlan_hdd_validate_context(hdd_ctx);
+ if (rc)
+ return rc;
if (adapter->device_mode != QDF_OCB_MODE) {
hdd_err("Device not in OCB mode!");
@@ -1588,10 +1663,12 @@
request_array = nla_data(
tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY]);
- /* Initialize the callback context */
- init_completion(&context.completion_evt);
- context.adapter = adapter;
- context.magic = HDD_OCB_MAGIC;
+ hdd_request = hdd_request_alloc(¶ms);
+ if (!hdd_request) {
+ hdd_err("Request allocation failure");
+ return -ENOMEM;
+ }
+ cookie = hdd_request_cookie(hdd_request);
request.vdev_id = adapter->sessionId;
request.channel_count = channel_count;
@@ -1599,76 +1676,40 @@
request.request_array = request_array;
/* Call the SME function. */
- rc = sme_dcc_get_stats(hdd_ctx->hHal, &context,
- hdd_dcc_get_stats_callback,
- &request);
- if (rc) {
- hdd_err("Error calling SME function");
- /* Need to convert from qdf_status to errno. */
- return -EINVAL;
+ status = sme_dcc_get_stats(hdd_ctx->hHal, cookie,
+ hdd_dcc_get_stats_callback,
+ &request);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ hdd_err("Error calling SME function.");
+ rc = qdf_status_to_os_return(status);
+ goto end;
}
/* Wait for the function to complete. */
- rc = wait_for_completion_timeout(&context.completion_evt,
- msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD));
- if (rc == 0) {
+ rc = hdd_request_wait_for_response(hdd_request);
+ if (rc) {
+ hdd_err("Operation timed out");
+ goto end;
+ }
+
+ priv = hdd_request_priv(hdd_request);
+ rc = priv->status;
+ if (rc) {
hdd_err("Operation failed: %d", rc);
- rc = -ETIMEDOUT;
goto end;
}
- if (context.status) {
- hdd_err("There was error: %d", context.status);
- rc = context.status;
- goto end;
- }
-
- if (!adapter->dcc_get_stats_resp) {
- hdd_err("The response was NULL");
- rc = -EINVAL;
- goto end;
- }
-
- /* Allocate the buffer for the response. */
- nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(uint32_t) +
- adapter->dcc_get_stats_resp->channel_stats_array_len +
- NLMSG_HDRLEN);
- if (!nl_resp) {
- hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
- rc = -ENOMEM;
- goto end;
- }
-
- /* Populate the response. */
- rc = nla_put_u32(nl_resp,
- QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT,
- adapter->dcc_get_stats_resp->num_channels);
- if (rc)
- goto end;
- rc = nla_put(nl_resp,
- QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY,
- adapter->dcc_get_stats_resp->channel_stats_array_len,
- adapter->dcc_get_stats_resp->channel_stats_array);
- if (rc)
- goto end;
-
/* Send the response. */
- rc = cfg80211_vendor_cmd_reply(nl_resp);
- nl_resp = NULL;
+ rc = hdd_dcc_get_stats_send_reply(wiphy, priv->response);
if (rc) {
- hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc);
+ hdd_err("hdd_dcc_get_stats_send_reply failed: %d", rc);
goto end;
}
/* fall through */
end:
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- qdf_mem_free(adapter->dcc_get_stats_resp);
- adapter->dcc_get_stats_resp = NULL;
- spin_unlock(&hdd_context_lock);
- if (nl_resp)
- kfree_skb(nl_resp);
+ hdd_request_put(hdd_request);
+
return rc;
}
@@ -1779,6 +1820,10 @@
return ret;
}
+struct hdd_dcc_update_ndl_priv {
+ int status;
+};
+
/**
* hdd_dcc_update_ndl_callback() - Callback to update NDL command
* @context_ptr: request context
@@ -1786,23 +1831,22 @@
*/
static void hdd_dcc_update_ndl_callback(void *context_ptr, void *response_ptr)
{
- struct hdd_ocb_ctxt *context = context_ptr;
+ struct hdd_request *hdd_request;
+ struct hdd_dcc_update_ndl_priv *priv;
struct sir_dcc_update_ndl_response *response = response_ptr;
- if (!context)
+ hdd_request = hdd_request_get(context_ptr);
+ if (!hdd_request) {
+ hdd_err("Obsolete request");
return;
-
- spin_lock(&hdd_context_lock);
- if (context->magic == HDD_OCB_MAGIC) {
- if (response) {
- context->adapter->dcc_update_ndl_resp = *response;
- context->status = 0;
- } else {
- context->status = -EINVAL;
- }
- complete(&context->completion_evt);
}
- spin_unlock(&hdd_context_lock);
+ priv = hdd_request_priv(hdd_request);
+ if (response && (0 == response->status))
+ priv->status = 0;
+ else
+ priv->status = -EINVAL;
+ hdd_request_complete(hdd_request);
+ hdd_request_put(hdd_request);
}
/**
@@ -1829,17 +1873,25 @@
void *ndl_channel_array;
uint32_t ndl_active_state_array_len;
void *ndl_active_state_array;
- int rc = -EINVAL;
- struct hdd_ocb_ctxt context = {0};
+ int rc;
+ QDF_STATUS status;
+ void *cookie;
+ struct hdd_request *hdd_request;
+ struct hdd_dcc_update_ndl_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
+ };
ENTER_DEV(dev);
- if (wlan_hdd_validate_context(hdd_ctx))
- goto end;
+ rc = wlan_hdd_validate_context(hdd_ctx);
+ if (rc)
+ return rc;
if (adapter->device_mode != QDF_OCB_MODE) {
hdd_err("Device not in OCB mode!");
- goto end;
+ return -EINVAL;
}
if (!wma_is_vdev_up(adapter->sessionId)) {
@@ -1851,7 +1903,7 @@
if (hdd_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_MAX, data,
data_len, qca_wlan_vendor_dcc_update_ndl)) {
hdd_err("Invalid ATTR");
- goto end;
+ return -EINVAL;
}
/* Verify that the parameter is present */
@@ -1873,10 +1925,12 @@
ndl_active_state_array = nla_data(
tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY]);
- /* Initialize the callback context */
- init_completion(&context.completion_evt);
- context.adapter = adapter;
- context.magic = HDD_OCB_MAGIC;
+ hdd_request = hdd_request_alloc(¶ms);
+ if (!hdd_request) {
+ hdd_err("Request allocation failure");
+ return -ENOMEM;
+ }
+ cookie = hdd_request_cookie(hdd_request);
/* Copy the parameters to the request structure. */
request.vdev_id = adapter->sessionId;
@@ -1887,43 +1941,33 @@
request.dcc_ndl_active_state_list = ndl_active_state_array;
/* Call the SME function */
- rc = sme_dcc_update_ndl(hdd_ctx->hHal, &context,
- hdd_dcc_update_ndl_callback,
- &request);
- if (rc) {
+ status = sme_dcc_update_ndl(hdd_ctx->hHal, cookie,
+ hdd_dcc_update_ndl_callback,
+ &request);
+ if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("Error calling SME function.");
- /* Convert from qdf_status to errno */
- return -EINVAL;
+ rc = qdf_status_to_os_return(status);
+ goto end;
}
/* Wait for the function to complete. */
- rc = wait_for_completion_timeout(&context.completion_evt,
- msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD));
- if (rc == 0) {
+ rc = hdd_request_wait_for_response(hdd_request);
+ if (rc) {
hdd_err("Operation timed out");
- rc = -ETIMEDOUT;
- goto end;
- }
- rc = 0;
-
- if (context.status) {
- hdd_err("Operation failed: %d", context.status);
- rc = context.status;
goto end;
}
- if (adapter->dcc_update_ndl_resp.status) {
- hdd_err("Operation returned: %d",
- adapter->dcc_update_ndl_resp.status);
- rc = -EINVAL;
+ priv = hdd_request_priv(hdd_request);
+ rc = priv->status;
+ if (rc) {
+ hdd_err("Operation failed: %d", rc);
goto end;
}
/* fall through */
end:
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
+ hdd_request_put(hdd_request);
+
return rc;
}
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c
index 18871727..e3259d3 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c
@@ -53,6 +53,7 @@
#include "cds_sched.h"
#include "cds_concurrency.h"
#include "cds_utils.h"
+#include "wlan_hdd_request_manager.h"
/* Ms to Time Unit Micro Sec */
#define MS_TO_TU_MUS(x) ((x) * 1024)
@@ -180,6 +181,10 @@
return false;
}
+struct random_mac_priv {
+ bool set_random_addr;
+};
+
/**
* hdd_random_mac_callback() - Callback invoked from wmi layer
* @set_random_addr: Status of random mac filter set operation
@@ -192,31 +197,20 @@
*/
static void hdd_random_mac_callback(bool set_random_addr, void *context)
{
- struct random_mac_context *rnd_ctx;
- hdd_adapter_t *adapter;
+ struct hdd_request *request;
+ struct random_mac_priv *priv;
- if (!context) {
- hdd_err("Bad param, pContext");
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("invalid request");
return;
}
- rnd_ctx = context;
- adapter = rnd_ctx->adapter;
+ priv = hdd_request_priv(request);
+ priv->set_random_addr = set_random_addr;
- spin_lock(&hdd_context_lock);
- if ((!adapter) ||
- (rnd_ctx->magic != ACTION_FRAME_RANDOM_CONTEXT_MAGIC)) {
- spin_unlock(&hdd_context_lock);
- hdd_err("Invalid context, magic [%08x]", rnd_ctx->magic);
- return;
- }
-
- rnd_ctx->magic = 0;
- if (set_random_addr)
- rnd_ctx->set_random_addr = true;
-
- complete(&rnd_ctx->random_mac_completion);
- spin_unlock(&hdd_context_lock);
+ hdd_request_complete(request);
+ hdd_request_put(request);
}
/**
@@ -231,11 +225,17 @@
uint8_t *random_mac_addr,
uint32_t freq)
{
- struct random_mac_context context;
hdd_context_t *hdd_ctx;
QDF_STATUS sme_status;
unsigned long rc;
+ void *cookie;
bool status = false;
+ struct hdd_request *request;
+ struct random_mac_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_SET_RND,
+ };
ENTER();
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
@@ -244,30 +244,33 @@
return false;
}
- init_completion(&context.random_mac_completion);
- context.adapter = adapter;
- context.magic = ACTION_FRAME_RANDOM_CONTEXT_MAGIC;
- context.set_random_addr = false;
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("Request allocation failure");
+ return false;
+ }
+
+ cookie = hdd_request_cookie(request);
sme_status = sme_set_random_mac(hdd_ctx->hHal, hdd_random_mac_callback,
adapter->sessionId, random_mac_addr, freq,
- &context);
+ cookie);
if (sme_status != QDF_STATUS_SUCCESS) {
hdd_err("Unable to set random mac");
} else {
- rc = wait_for_completion_timeout(&context.random_mac_completion,
- msecs_to_jiffies(WLAN_WAIT_TIME_SET_RND));
- if (!rc)
+ rc = hdd_request_wait_for_response(request);
+ if (rc) {
hdd_err("SME timed out while setting random mac");
+ } else {
+ priv = hdd_request_priv(request);
+ status = priv->set_random_addr;
+ }
}
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- status = context.set_random_addr;
- spin_unlock(&hdd_context_lock);
-
+ hdd_request_put(request);
EXIT();
+
return status;
}
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c
index c8d1d45..b9f52a1 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c
@@ -34,6 +34,7 @@
#include "hif.h"
#include "wlan_hdd_hostapd.h"
#include "wlan_hdd_debugfs_llstat.h"
+#include "wlan_hdd_request_manager.h"
#include "wma_api.h"
#include "wma.h"
@@ -3794,77 +3795,58 @@
flags);
}
+struct peer_info_priv {
+ struct sir_peer_sta_ext_info peer_sta_ext_info;
+};
+
/**
* wlan_hdd_get_peer_info_cb() - get peer info callback
* @sta_info: pointer of peer information
* @context: get peer info callback context
*
- * This function will fill stats info of AP Context
+ * This function will fill stats info to peer info priv
*
*/
static void wlan_hdd_get_peer_info_cb(struct sir_peer_info_ext_resp *sta_info,
- void *context)
+ void *context)
{
- struct statsContext *get_peer_info_context;
- struct sir_peer_info_ext *peer_info;
- hdd_adapter_t *adapter;
- hdd_ap_ctx_t *ap_ctx;
+ struct hdd_request *request;
+ struct peer_info_priv *priv;
+ uint8_t sta_num;
- if ((sta_info == NULL) || (context == NULL)) {
- hdd_err("Bad param, sta_info [%pK] context [%pK]",
- sta_info, context);
- return;
- }
-
- spin_lock(&hdd_context_lock);
- /*
- * there is a race condition that exists between this callback
- * function and the caller since the caller could time out either
- * before or while this code is executing. we use a spinlock to
- * serialize these actions
- */
- get_peer_info_context = context;
- if (PEER_INFO_CONTEXT_MAGIC !=
- get_peer_info_context->magic) {
- /*
- * the caller presumably timed out so there is nothing
- * we can do
- */
- spin_unlock(&hdd_context_lock);
- hdd_warn("Invalid context, magic [%08x]",
- get_peer_info_context->magic);
+ if (!sta_info) {
+ hdd_err("Bad param, sta_info [%pK]",
+ sta_info);
return;
}
if (!sta_info->count) {
- spin_unlock(&hdd_context_lock);
hdd_err("Fail to get remote peer info");
return;
}
- adapter = get_peer_info_context->pAdapter;
- ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
- qdf_mem_zero(&ap_ctx->txrx_stats,
- sizeof(ap_ctx->txrx_stats));
+ if (sta_info->count > MAX_PEER_STA) {
+ hdd_warn("Exceed max peer number %d", sta_info->count);
+ sta_num = MAX_PEER_STA;
+ } else {
+ sta_num = sta_info->count;
+ }
- peer_info = sta_info->info;
- ap_ctx->txrx_stats.tx_packets = peer_info->tx_packets;
- ap_ctx->txrx_stats.tx_bytes = peer_info->tx_bytes;
- ap_ctx->txrx_stats.rx_packets = peer_info->rx_packets;
- ap_ctx->txrx_stats.rx_bytes = peer_info->rx_bytes;
- ap_ctx->txrx_stats.tx_retries = peer_info->tx_retries;
- ap_ctx->txrx_stats.tx_failed = peer_info->tx_failed;
- ap_ctx->txrx_stats.rssi =
- peer_info->rssi + WLAN_HDD_TGT_NOISE_FLOOR_DBM;
- wlan_hdd_fill_rate_info(ap_ctx, peer_info);
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("Obsolete request");
+ return;
+ }
- get_peer_info_context->magic = 0;
+ priv = hdd_request_priv(request);
- /* notify the caller */
- complete(&get_peer_info_context->completion);
+ priv->peer_sta_ext_info.sta_num = sta_num;
+ qdf_mem_copy(&priv->peer_sta_ext_info.info,
+ sta_info->info,
+ sta_num * sizeof(sta_info->info[0]));
- /* serialization is complete */
- spin_unlock(&hdd_context_lock);
+ hdd_request_complete(request);
+ hdd_request_put(request);
}
/**
@@ -3880,54 +3862,77 @@
struct qdf_mac_addr macaddress)
{
QDF_STATUS status;
+ void *cookie;
int ret;
- static struct statsContext context;
+ hdd_ap_ctx_t *ap_ctx = NULL;
struct sir_peer_info_ext_req peer_info_req;
+ struct hdd_request *request;
+ struct peer_info_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_STATS,
+ };
- if (adapter == NULL) {
- hdd_err("pAdapter is NULL");
+ if (!adapter) {
+ hdd_err("adapter is NULL");
return -EFAULT;
}
- init_completion(&context.completion);
- context.magic = PEER_INFO_CONTEXT_MAGIC;
- context.pAdapter = adapter;
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("Request allocation failure");
+ return -ENOMEM;
+ }
- qdf_mem_copy(&(peer_info_req.peer_macaddr), &macaddress,
- QDF_MAC_ADDR_SIZE);
+ cookie = hdd_request_cookie(request);
+ priv = hdd_request_priv(request);
+
+ qdf_mem_copy(&peer_info_req.peer_macaddr, &macaddress,
+ QDF_MAC_ADDR_SIZE);
peer_info_req.sessionid = adapter->sessionId;
peer_info_req.reset_after_request = 0;
status = sme_get_peer_info_ext(WLAN_HDD_GET_HAL_CTX(adapter),
- &peer_info_req,
- &context,
- wlan_hdd_get_peer_info_cb);
+ &peer_info_req,
+ cookie,
+ wlan_hdd_get_peer_info_cb);
if (status != QDF_STATUS_SUCCESS) {
hdd_err("Unable to retrieve statistics for peer info");
ret = -EFAULT;
} else {
- if (!wait_for_completion_timeout(&context.completion,
- msecs_to_jiffies(WLAN_WAIT_TIME_STATS))) {
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
hdd_err("SME timed out while retrieving peer info");
ret = -EFAULT;
- } else
+ } else {
+ /* only support one peer by now */
+ ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
+ qdf_mem_zero(&ap_ctx->txrx_stats,
+ sizeof(struct hdd_fw_txrx_stats));
+
+ ap_ctx->txrx_stats.tx_packets =
+ priv->peer_sta_ext_info.info[0].tx_packets;
+ ap_ctx->txrx_stats.tx_bytes =
+ priv->peer_sta_ext_info.info[0].tx_bytes;
+ ap_ctx->txrx_stats.rx_packets =
+ priv->peer_sta_ext_info.info[0].rx_packets;
+ ap_ctx->txrx_stats.rx_bytes =
+ priv->peer_sta_ext_info.info[0].rx_bytes;
+ ap_ctx->txrx_stats.tx_retries =
+ priv->peer_sta_ext_info.info[0].tx_retries;
+ ap_ctx->txrx_stats.tx_failed =
+ priv->peer_sta_ext_info.info[0].tx_failed;
+ ap_ctx->txrx_stats.rssi =
+ priv->peer_sta_ext_info.info[0].rssi +
+ WLAN_HDD_TGT_NOISE_FLOOR_DBM;
+ wlan_hdd_fill_rate_info(ap_ctx,
+ &priv->peer_sta_ext_info.info[0]);
ret = 0;
+
+ }
}
- /*
- * either we never sent a request, we sent a request and received a
- * response or we sent a request and timed out. if we never sent a
- * request or if we sent a request and got a response, we want to
- * clear the magic out of paranoia. if we timed out there is a
- * race condition such that the callback function could be
- * executing at the same time we are. of primary concern is if the
- * callback function had already verified the "magic" but had not
- * yet set the completion variable when a timeout occurred. we
- * serialize these activities by invalidating the magic while
- * holding a shared spinlock which will cause us to block if the
- * callback is currently executing
- */
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
+
+ hdd_request_put(request);
+
return ret;
}
@@ -4939,59 +4944,37 @@
/**
* wlan_hdd_get_rcpi_cb() - callback function for rcpi response
- * @context: Pointer to rcpi context
- * @rcpi_req: Pointer to rcpi response
+ * @context: used to refer cookie in hdd request manager
+ * @mac_addr: destination mac address for which RCPI is computed
+ * @rcpi: RCPI value from firmware
+ * @status: status of RCPI computation
*
* Return: None
*/
static void wlan_hdd_get_rcpi_cb(void *context, struct qdf_mac_addr mac_addr,
int32_t rcpi, QDF_STATUS status)
{
- hdd_adapter_t *adapter;
- struct statsContext *rcpi_context;
+ struct hdd_request *request;
+ struct rcpi_info *priv;
- if (!context) {
- hdd_err("No rcpi context");
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("Obsolete RCPI request");
return;
}
- rcpi_context = context;
- adapter = rcpi_context->pAdapter;
- if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
- hdd_err("Invalid adapter magic");
- return;
+ priv = hdd_request_priv(request);
+ priv->mac_addr = mac_addr;
+
+ if (!QDF_IS_STATUS_SUCCESS(status)) {
+ priv->rcpi = 0;
+ hdd_err("Error in computing RCPI");
+ } else {
+ priv->rcpi = rcpi;
}
- /*
- * there is a race condition that exists between this callback
- * function and the caller since the caller could time out
- * either before or while this code is executing. we use a
- * spinlock to serialize these actions
- */
- spin_lock(&hdd_context_lock);
- if (rcpi_context->magic != RCPI_CONTEXT_MAGIC) {
- /*
- * the caller presumably timed out so there is nothing
- * we can do
- */
- spin_unlock(&hdd_context_lock);
- hdd_warn("Invalid RCPI context magic");
- return;
- }
-
- rcpi_context->magic = 0;
- adapter->rcpi.mac_addr = mac_addr;
- if (status != QDF_STATUS_SUCCESS)
- /* peer rcpi is not available for requested mac addr */
- adapter->rcpi.rcpi = 0;
- else
- adapter->rcpi.rcpi = rcpi;
-
- /* notify the caller */
- complete(&rcpi_context->completion);
-
- /* serialization is complete */
- spin_unlock(&hdd_context_lock);
+ hdd_request_complete(request);
+ hdd_request_put(request);
}
/**
@@ -5009,12 +4992,17 @@
enum rcpi_measurement_type measurement_type)
{
hdd_context_t *hdd_ctx;
- static struct statsContext rcpi_context;
- int status = 0;
- unsigned long rc;
+ int status = 0, ret = 0;
struct qdf_mac_addr mac_addr;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
struct sme_rcpi_req *rcpi_req;
+ void *cookie;
+ struct rcpi_info *priv;
+ struct hdd_request *request;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_RCPI,
+ };
bool reassoc;
ENTER();
@@ -5060,47 +5048,51 @@
return -EINVAL;
}
- init_completion(&rcpi_context.completion);
- rcpi_context.pAdapter = adapter;
- rcpi_context.magic = RCPI_CONTEXT_MAGIC;
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("Request allocation failure");
+ qdf_mem_free(rcpi_req);
+ return -ENOMEM;
+ }
+ cookie = hdd_request_cookie(request);
rcpi_req->mac_addr = mac_addr;
rcpi_req->session_id = adapter->sessionId;
rcpi_req->measurement_type = measurement_type;
rcpi_req->rcpi_callback = wlan_hdd_get_rcpi_cb;
- rcpi_req->rcpi_context = &rcpi_context;
+ rcpi_req->rcpi_context = cookie;
qdf_status = sme_get_rcpi(hdd_ctx->hHal, rcpi_req);
- if (qdf_status != QDF_STATUS_SUCCESS) {
+ if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
hdd_err("Unable to retrieve RCPI");
status = qdf_status_to_os_return(qdf_status);
- } else {
- /* request was sent -- wait for the response */
- rc = wait_for_completion_timeout(&rcpi_context.completion,
- msecs_to_jiffies(WLAN_WAIT_TIME_RCPI));
- if (!rc) {
- hdd_err("SME timed out while retrieving RCPI");
- status = -EINVAL;
- }
+ goto out;
}
+
+ /* request was sent -- wait for the response */
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
+ hdd_err("SME timed out while retrieving RCPI");
+ status = -EINVAL;
+ goto out;
+ }
+
+ /* update the adapter with the fresh results */
+ priv = hdd_request_priv(request);
+ adapter->rcpi.mac_addr = priv->mac_addr;
+ adapter->rcpi.rcpi = priv->rcpi;
+
+ if (qdf_mem_cmp(&mac_addr, &priv->mac_addr, sizeof(mac_addr))) {
+ hdd_err("mis match of mac addr from call-back");
+ status = -EINVAL;
+ goto out;
+ }
+
+ *rcpi_value = adapter->rcpi.rcpi;
+ hdd_debug("RCPI = %d", *rcpi_value);
+out:
qdf_mem_free(rcpi_req);
-
- spin_lock(&hdd_context_lock);
- rcpi_context.magic = 0;
- spin_unlock(&hdd_context_lock);
-
- if (status) {
- hdd_err("rcpi computation is failed");
- } else {
- if (qdf_mem_cmp(&mac_addr, &adapter->rcpi.mac_addr,
- sizeof(mac_addr))) {
- hdd_err("mac addr is not matching from call-back");
- status = -EINVAL;
- } else {
- *rcpi_value = adapter->rcpi.rcpi;
- hdd_debug("RCPI = %d", *rcpi_value);
- }
- }
+ hdd_request_put(request);
EXIT();
return status;
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c
index a384cab..aeadc0f 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c
@@ -52,6 +52,7 @@
#include <wlan_hdd_wmm.h>
#include "utils_api.h"
#include "wlan_hdd_p2p.h"
+#include "wlan_hdd_request_manager.h"
#ifdef FEATURE_WLAN_TDLS
#include "wlan_hdd_tdls.h"
#endif
@@ -94,6 +95,7 @@
#include "wlan_hdd_lro.h"
#include "cds_utils.h"
#include "wlan_hdd_packet_filter_api.h"
+#include "wlan_hdd_request_manager.h"
#define HDD_FINISH_ULA_TIME_OUT 800
#define HDD_SET_MCBC_FILTERS_TO_FW 1
@@ -3448,129 +3450,37 @@
return rsnType;
}
+struct rssi_priv {
+ int8_t rssi;
+};
+
/**
* hdd_get_rssi_cb() - "Get RSSI" callback function
* @rssi: Current RSSI of the station
- * @staId: ID of the station
- * @pContext: opaque context originally passed to SME. HDD always passes
+ * @sta_id: ID of the station
+ * @context: opaque context originally passed to SME. HDD always passes
* a &struct statsContext
*
* Return: None
*/
-static void hdd_get_rssi_cb(int8_t rssi, uint32_t staId, void *pContext)
+static void hdd_get_rssi_cb(int8_t rssi, uint32_t sta_id, void *context)
{
- struct statsContext *pStatsContext;
- hdd_adapter_t *pAdapter;
- hdd_station_ctx_t *pHddStaCtx;
+ struct hdd_request *request;
+ struct rssi_priv *priv;
- if (NULL == pContext) {
- hdd_err("Bad param");
+ hdd_info("%s: rssi [%d] sta_id [%d] context [%pK]\n",
+ __func__, (int)rssi, (int)sta_id, context);
+
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("%s: Obsolete request", __func__);
return;
}
- pStatsContext = pContext;
- pAdapter = pStatsContext->pAdapter;
-
- if (!pAdapter) {
- hdd_err("Invalid pAdapter");
- return;
- }
-
- pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
-
- pAdapter->rssi = rssi;
-
- /* for new connection there might be no valid previous RSSI
- * Do not keep hdd_get_rssi_snr_by_bssid under spin_lock
- * because it accesses scan cache in pMac which is mutex
- * protected
- */
- if (!pAdapter->rssi)
- hdd_get_rssi_snr_by_bssid(pAdapter,
- pHddStaCtx->conn_info.bssId.bytes,
- &pAdapter->rssi, NULL);
-
-
- /* there is a race condition that exists between this callback
- * function and the caller since the caller could time out
- * either before or while this code is executing. we use a
- * spinlock to serialize these actions
- */
- spin_lock(&hdd_context_lock);
-
- if (pStatsContext->magic != PEER_INFO_CONTEXT_MAGIC) {
- /* the caller presumably timed out so there is nothing
- * we can do
- */
- spin_unlock(&hdd_context_lock);
- hdd_warn("Invalid context, magic [%08x]",
- pStatsContext->magic);
- return;
- }
-
- /* context is valid so caller is still waiting */
-
- /* paranoia: invalidate the magic */
- pStatsContext->magic = 0;
- /* notify the caller */
- complete(&pStatsContext->completion);
-
- /* serialization is complete */
- spin_unlock(&hdd_context_lock);
-}
-
-/**
- * hdd_get_snr_cb() - "Get SNR" callback function
- * @snr: Current SNR of the station
- * @staId: ID of the station
- * @pContext: opaque context originally passed to SME. HDD always passes
- * a &struct statsContext
- *
- * Return: None
- */
-static void hdd_get_snr_cb(int8_t snr, uint32_t staId, void *pContext)
-{
- struct statsContext *pStatsContext;
- hdd_adapter_t *pAdapter;
-
- if (NULL == pContext) {
- hdd_err("Bad param");
- return;
- }
-
- pStatsContext = pContext;
- pAdapter = pStatsContext->pAdapter;
-
- /* there is a race condition that exists between this callback
- * function and the caller since the caller could time out
- * either before or while this code is executing. we use a
- * spinlock to serialize these actions
- */
- spin_lock(&hdd_context_lock);
-
- if ((NULL == pAdapter) || (SNR_CONTEXT_MAGIC != pStatsContext->magic)) {
- /* the caller presumably timed out so there is nothing
- * we can do
- */
- spin_unlock(&hdd_context_lock);
- hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]",
- pAdapter, pStatsContext->magic);
- return;
- }
-
- /* context is valid so caller is still waiting */
-
- /* paranoia: invalidate the magic */
- pStatsContext->magic = 0;
-
- /* copy over the snr */
- pAdapter->snr = snr;
-
- /* notify the caller */
- complete(&pStatsContext->completion);
-
- /* serialization is complete */
- spin_unlock(&hdd_context_lock);
+ priv = hdd_request_priv(request);
+ priv->rssi = rssi;
+ hdd_request_complete(request);
+ hdd_request_put(request);
}
/**
@@ -3582,11 +3492,17 @@
*/
QDF_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, int8_t *rssi_value)
{
- static struct statsContext context;
hdd_context_t *pHddCtx;
hdd_station_ctx_t *pHddStaCtx;
QDF_STATUS hstatus;
- unsigned long rc;
+ int ret;
+ void *cookie;
+ struct hdd_request *request;
+ struct rssi_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_STATS,
+ };
if (NULL == pAdapter) {
hdd_err("Invalid context, pAdapter");
@@ -3616,44 +3532,52 @@
return QDF_STATUS_SUCCESS;
}
- init_completion(&context.completion);
- context.pAdapter = pAdapter;
- context.magic = PEER_INFO_CONTEXT_MAGIC;
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("%s: Request allocation failure, return cached RSSI",
+ __func__);
+ *rssi_value = pAdapter->rssi;
+ return QDF_STATUS_SUCCESS;
+ }
+ cookie = hdd_request_cookie(request);
hstatus = sme_get_rssi(pHddCtx->hHal, hdd_get_rssi_cb,
pHddStaCtx->conn_info.staId[0],
pHddStaCtx->conn_info.bssId, pAdapter->rssi,
- &context, pHddCtx->pcds_context);
+ cookie, pHddCtx->pcds_context);
if (QDF_STATUS_SUCCESS != hstatus) {
hdd_err("Unable to retrieve RSSI");
/* we'll returned a cached value below */
} else {
/* request was sent -- wait for the response */
- rc = wait_for_completion_timeout(&context.completion,
- msecs_to_jiffies
- (WLAN_WAIT_TIME_STATS));
- if (!rc) {
- hdd_err("SME timed out while retrieving RSSI");
- /* we'll now returned a cached value below */
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
+ hdd_warn("SME timed out while retrieving RSSI");
+ /* we'll returned a cached value below */
+ } else {
+ /* update the adapter with the fresh results */
+ priv = hdd_request_priv(request);
+
+ pAdapter->rssi = priv->rssi;
+
+ /*
+ * for new connection there might be no valid previous
+ * RSSI.
+ */
+ if (!pAdapter->rssi) {
+ hdd_get_rssi_snr_by_bssid(pAdapter,
+ pHddStaCtx->conn_info.bssId.bytes,
+ &pAdapter->rssi, NULL);
+ }
}
}
- /* either we never sent a request, we sent a request and
- * received a response or we sent a request and timed out. if
- * we never sent a request or if we sent a request and got a
- * response, we want to clear the magic out of paranoia. if
- * we timed out there is a race condition such that the
- * callback function could be executing at the same time we
- * are. of primary concern is if the callback function had
- * already verified the "magic" but had not yet set the
- * completion variable when a timeout occurred. we serialize
- * these activities by invalidating the magic while holding a
- * shared spinlock which will cause us to block if the
- * callback is currently executing
+ /*
+ * either we never sent a request, we sent a request and
+ * received a response or we sent a request and timed out.
+ * regardless we are done with the request.
*/
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
+ hdd_request_put(request);
*rssi_value = pAdapter->rssi;
hdd_debug("RSSI = %d", *rssi_value);
@@ -3661,6 +3585,40 @@
return QDF_STATUS_SUCCESS;
}
+struct snr_priv {
+ int8_t snr;
+};
+
+/**
+ * hdd_get_snr_cb() - "Get SNR" callback function
+ * @snr: Current SNR of the station
+ * @sta_id: ID of the station
+ * @context: opaque context originally passed to SME. HDD always passes
+ * a cookie for the request context
+ *
+ * Return: None
+ */
+static void hdd_get_snr_cb(int8_t snr, uint32_t sta_id, void *context)
+{
+ struct hdd_request *request;
+ struct snr_priv *priv;
+
+ hdd_info("%s: snr [%d] sta_id [%d] context [%pK]\n",
+ __func__, (int)snr, (int)sta_id, context);
+
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("%s: Obsolete request", __func__);
+ return;
+ }
+
+ /* propagate response back to requesting thread */
+ priv = hdd_request_priv(request);
+ priv->snr = snr;
+ hdd_request_complete(request);
+ hdd_request_put(request);
+}
+
/**
* wlan_hdd_get_snr() - Get the current SNR
* @pAdapter: adapter upon which the measurement is requested
@@ -3670,12 +3628,18 @@
*/
QDF_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, int8_t *snr)
{
- static struct statsContext context;
hdd_context_t *pHddCtx;
hdd_station_ctx_t *pHddStaCtx;
QDF_STATUS hstatus;
- unsigned long rc;
int valid;
+ int ret;
+ void *cookie;
+ struct hdd_request *request;
+ struct snr_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_STATS,
+ };
ENTER();
@@ -3692,182 +3656,130 @@
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
- init_completion(&context.completion);
- context.pAdapter = pAdapter;
- context.magic = SNR_CONTEXT_MAGIC;
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("%s: Request allocation failure", __func__);
+ return QDF_STATUS_E_FAULT;
+ }
+ cookie = hdd_request_cookie(request);
hstatus = sme_get_snr(pHddCtx->hHal, hdd_get_snr_cb,
pHddStaCtx->conn_info.staId[0],
- pHddStaCtx->conn_info.bssId, &context);
+ pHddStaCtx->conn_info.bssId, cookie);
if (QDF_STATUS_SUCCESS != hstatus) {
hdd_err("Unable to retrieve RSSI");
/* we'll returned a cached value below */
} else {
/* request was sent -- wait for the response */
- rc = wait_for_completion_timeout(&context.completion,
- msecs_to_jiffies
- (WLAN_WAIT_TIME_STATS));
- if (!rc) {
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
hdd_err("SME timed out while retrieving SNR");
/* we'll now returned a cached value below */
+ } else {
+ /* update the adapter with the fresh results */
+ priv = hdd_request_priv(request);
+ pAdapter->snr = priv->snr;
}
}
- /* either we never sent a request, we sent a request and
- * received a response or we sent a request and timed out. if
- * we never sent a request or if we sent a request and got a
- * response, we want to clear the magic out of paranoia. if
- * we timed out there is a race condition such that the
- * callback function could be executing at the same time we
- * are. of primary concern is if the callback function had
- * already verified the "magic" but had not yet set the
- * completion variable when a timeout occurred. we serialize
- * these activities by invalidating the magic while holding a
- * shared spinlock which will cause us to block if the
- * callback is currently executing
+ /*
+ * either we never sent a request, we sent a request and
+ * received a response or we sent a request and timed out.
+ * regardless we are done with the request.
*/
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
+ hdd_request_put(request);
*snr = pAdapter->snr;
EXIT();
return QDF_STATUS_SUCCESS;
}
-/**
- * hdd_get_link_speed_cb() - Get link speed callback function
- * @pLinkSpeed: pointer to the link speed record
- * @pContext: pointer to the user context passed to SME
- *
- * This function is passed as the callback function to
- * sme_get_link_speed() by wlan_hdd_get_linkspeed_for_peermac(). By
- * agreement a &struct linkspeedContext is passed as @pContext. If
- * the context is valid, then the contents of @pLinkSpeed are copied
- * into the adapter record referenced by @pContext where they can be
- * subsequently retrieved. If the context is invalid, then this
- * function does nothing since it is assumed the caller has already
- * timed-out and destroyed the context.
- *
- * Return: None.
- */
+struct linkspeed_priv {
+ tSirLinkSpeedInfo linkspeed_info;
+};
+
static void
-hdd_get_link_speed_cb(tSirLinkSpeedInfo *pLinkSpeed, void *pContext)
+hdd_get_link_speed_cb(tSirLinkSpeedInfo *linkspeed_info, void *context)
{
- struct linkspeedContext *pLinkSpeedContext;
- hdd_adapter_t *pAdapter;
+ struct hdd_request *request;
+ struct linkspeed_priv *priv;
- if ((NULL == pLinkSpeed) || (NULL == pContext)) {
- hdd_err("Bad param, pLinkSpeed [%pK] pContext [%pK]",
- pLinkSpeed, pContext);
- return;
- }
- spin_lock(&hdd_context_lock);
- pLinkSpeedContext = pContext;
- pAdapter = pLinkSpeedContext->pAdapter;
-
- /* there is a race condition that exists between this callback
- * function and the caller since the caller could time out either
- * before or while this code is executing. we use a spinlock to
- * serialize these actions
- */
-
- if ((NULL == pAdapter) ||
- (LINK_CONTEXT_MAGIC != pLinkSpeedContext->magic)) {
- /* the caller presumably timed out so there is nothing
- * we can do
- */
- spin_unlock(&hdd_context_lock);
- hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]",
- pAdapter, pLinkSpeedContext->magic);
+ if (!linkspeed_info) {
+ hdd_err("NULL linkspeed");
return;
}
- /* context is valid so caller is still waiting */
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("Obsolete request");
+ return;
+ }
- /* paranoia: invalidate the magic */
- pLinkSpeedContext->magic = 0;
-
- /* copy over the stats. do so as a struct copy */
- pAdapter->ls_stats = *pLinkSpeed;
-
- /* notify the caller */
- complete(&pLinkSpeedContext->completion);
-
- /* serialization is complete */
- spin_unlock(&hdd_context_lock);
+ priv = hdd_request_priv(request);
+ priv->linkspeed_info = *linkspeed_info;
+ hdd_request_complete(request);
+ hdd_request_put(request);
}
-/**
- * wlan_hdd_get_linkspeed_for_peermac() - Get link speed for a peer
- * @pAdapter: adapter upon which the peer is active
- * @macAddress: MAC address of the peer
- *
- * This function will send a query to SME for the linkspeed of the
- * given peer, and then wait for the callback to be invoked.
- *
- * Return: Errno
- */
-int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter,
- struct qdf_mac_addr macAddress)
+int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *adapter,
+ struct qdf_mac_addr *mac_address,
+ uint32_t *linkspeed)
{
+ int ret;
QDF_STATUS status;
- int errno;
- unsigned long rc;
- static struct linkspeedContext context;
- tSirLinkSpeedInfo *linkspeed_req;
+ void *cookie;
+ tSirLinkSpeedInfo *linkspeed_info;
+ struct hdd_request *request;
+ struct linkspeed_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_STATS,
+ };
- if (NULL == pAdapter) {
- hdd_err("pAdapter is NULL");
+ if ((!adapter) || (!linkspeed)) {
+ hdd_err("NULL argument");
return -EINVAL;
}
- linkspeed_req = qdf_mem_malloc(sizeof(*linkspeed_req));
- if (NULL == linkspeed_req) {
- hdd_err("Request Buffer Alloc Fail");
- return -ENOMEM;
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("Request allocation failure");
+ ret = -ENOMEM;
+ goto return_cached_value;
}
- init_completion(&context.completion);
- context.pAdapter = pAdapter;
- context.magic = LINK_CONTEXT_MAGIC;
+ cookie = hdd_request_cookie(request);
+ priv = hdd_request_priv(request);
- qdf_copy_macaddr(&linkspeed_req->peer_macaddr, &macAddress);
- status = sme_get_link_speed(WLAN_HDD_GET_HAL_CTX(pAdapter),
- linkspeed_req,
- &context, hdd_get_link_speed_cb);
- qdf_mem_free(linkspeed_req);
- errno = qdf_status_to_os_return(status);
- if (errno) {
+ linkspeed_info = &priv->linkspeed_info;
+ qdf_copy_macaddr(&linkspeed_info->peer_macaddr, mac_address);
+ status = sme_get_link_speed(WLAN_HDD_GET_HAL_CTX(adapter),
+ linkspeed_info,
+ cookie, hdd_get_link_speed_cb);
+ if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("Unable to retrieve statistics for link speed");
- } else {
- rc = wait_for_completion_timeout
- (&context.completion,
- msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
- if (!rc) {
- hdd_err("SME timed out while retrieving link speed");
- errno = -ETIMEDOUT;
- }
+ ret = qdf_status_to_os_return(status);
+ goto cleanup;
}
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
+ hdd_err("SME timed out while retrieving link speed");
+ goto cleanup;
+ }
+ adapter->estimated_linkspeed = linkspeed_info->estLinkSpeed;
- /* either we never sent a request, we sent a request and
- * received a response or we sent a request and timed out. if
- * we never sent a request or if we sent a request and got a
- * response, we want to clear the magic out of paranoia. if
- * we timed out there is a race condition such that the
- * callback function could be executing at the same time we
- * are. of primary concern is if the callback function had
- * already verified the "magic" but had not yet set the
- * completion variable when a timeout occurred. we serialize
- * these activities by invalidating the magic while holding a
- * shared spinlock which will cause us to block if the
- * callback is currently executing
+cleanup:
+ /*
+ * either we never sent a request, we sent a request and
+ * received a response or we sent a request and timed out.
+ * regardless we are done with the request.
*/
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
+ hdd_request_put(request);
- return errno;
+return_cached_value:
+ *linkspeed = adapter->estimated_linkspeed;
+
+ return ret;
}
/**
@@ -3908,12 +3820,12 @@
qdf_copy_macaddr(&bssid, &hdd_stactx->conn_info.bssId);
- errno = wlan_hdd_get_linkspeed_for_peermac(sta_adapter, bssid);
+ errno = wlan_hdd_get_linkspeed_for_peermac(sta_adapter, &bssid,
+ link_speed);
if (errno) {
hdd_err("Unable to retrieve SME linkspeed: %d", errno);
return errno;
}
- *link_speed = sta_adapter->ls_stats.estLinkSpeed;
/* linkspeed in units of 500 kbps */
*link_speed = (*link_speed) / 500;
}
@@ -3921,6 +3833,10 @@
return 0;
}
+struct peer_rssi_priv {
+ struct sir_peer_sta_info peer_sta_info;
+};
+
/**
* hdd_get_peer_rssi_cb() - get peer station's rssi callback
* @sta_rssi: pointer of peer information
@@ -3933,72 +3849,41 @@
static void hdd_get_peer_rssi_cb(struct sir_peer_info_resp *sta_rssi,
void *context)
{
- struct statsContext *get_rssi_context;
+ struct hdd_request *request;
struct sir_peer_info *rssi_info;
- uint8_t peer_num, i;
- hdd_adapter_t *padapter;
- hdd_station_info_t *stainfo;
+ struct peer_rssi_priv *priv;
+ uint8_t peer_num;
- if ((sta_rssi == NULL) || (context == NULL)) {
- hdd_err("Bad param, sta_rssi [%pK] context [%pK]",
- sta_rssi, context);
+ if (sta_rssi == NULL) {
+ hdd_err("Bad param, sta_rssi [%pK]", sta_rssi);
return;
}
- spin_lock(&hdd_context_lock);
- /*
- * there is a race condition that exists between this callback
- * function and the caller since the caller could time out either
- * before or while this code is executing. we use a spinlock to
- * serialize these actions
- */
- get_rssi_context = (struct statsContext *)context;
- padapter = get_rssi_context->pAdapter;
- if (get_rssi_context->magic != PEER_INFO_CONTEXT_MAGIC ||
- !padapter) {
- /*
- * the caller presumably timed out so there is nothing
- * we can do
- */
- spin_unlock(&hdd_context_lock);
- hdd_warn("Invalid context, magic [%08x], adapter [%pK]",
- get_rssi_context->magic, padapter);
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("Obsolete request.");
return;
}
+ priv = hdd_request_priv(request);
+
peer_num = sta_rssi->count;
rssi_info = sta_rssi->info;
- get_rssi_context->magic = 0;
hdd_debug("%d peers", peer_num);
if (peer_num > MAX_PEER_STA) {
- hdd_warn("Exceed max peer sta to handle one time %d", peer_num);
+ hdd_warn("Exceed max peer sta to handle one time %d",
+ peer_num);
peer_num = MAX_PEER_STA;
}
- qdf_mem_copy(padapter->peer_sta_info.info, rssi_info,
- peer_num * sizeof(*rssi_info));
- padapter->peer_sta_info.sta_num = peer_num;
+ qdf_mem_copy(priv->peer_sta_info.info, rssi_info,
+ peer_num * sizeof(*rssi_info));
+ priv->peer_sta_info.sta_num = peer_num;
- for (i = 0; i < peer_num; i++) {
- stainfo = hdd_get_stainfo(padapter->cache_sta_info,
- rssi_info[i].peer_macaddr);
- if (stainfo) {
- stainfo->rssi = rssi_info[i].rssi;
- stainfo->tx_rate = rssi_info[i].tx_rate;
- stainfo->rx_rate = rssi_info[i].rx_rate;
- hdd_info("rssi:%d tx_rate:%u rx_rate:%u %pM",
- stainfo->rssi, stainfo->tx_rate,
- stainfo->rx_rate, stainfo->macAddrSTA.bytes);
- }
- }
-
- /* notify the caller */
- complete(&get_rssi_context->completion);
-
- /* serialization is complete */
- spin_unlock(&hdd_context_lock);
+ hdd_request_complete(request);
+ hdd_request_put(request);
}
int wlan_hdd_get_peer_rssi(hdd_adapter_t *adapter,
@@ -4006,62 +3891,55 @@
int request_source)
{
QDF_STATUS status;
+ void *cookie;
int ret;
- static struct statsContext context;
struct sir_peer_info_req rssi_req;
+ struct hdd_request *request;
+ struct peer_rssi_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_STATS,
+ };
if (!adapter || !macaddress) {
- hdd_err("pAdapter [%pK], macaddress [%pK]", adapter, macaddress);
+ hdd_err("adapter [%pK], macaddress [%pK]",
+ adapter, macaddress);
return -EFAULT;
}
- init_completion(&context.completion);
- context.magic = PEER_INFO_CONTEXT_MAGIC;
- context.pAdapter = adapter;
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("Request allocation failure");
+ return -ENOMEM;
+ }
+
+ cookie = hdd_request_cookie(request);
qdf_mem_copy(&(rssi_req.peer_macaddr), macaddress,
- QDF_MAC_ADDR_SIZE);
+ QDF_MAC_ADDR_SIZE);
rssi_req.sessionid = adapter->sessionId;
status = sme_get_peer_info(WLAN_HDD_GET_HAL_CTX(adapter),
- rssi_req,
- &context,
- hdd_get_peer_rssi_cb);
+ rssi_req,
+ cookie,
+ hdd_get_peer_rssi_cb);
if (status != QDF_STATUS_SUCCESS) {
hdd_err("Unable to retrieve statistics for rssi");
ret = -EFAULT;
- }
-
- else if (request_source != HDD_WLAN_GET_PEER_RSSI_SOURCE_DRIVER) {
- if (!wait_for_completion_timeout(&context.completion,
- msecs_to_jiffies(WLAN_WAIT_TIME_STATS))) {
+ } else if (request_source != HDD_WLAN_GET_PEER_RSSI_SOURCE_DRIVER) {
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
hdd_err("SME timed out while retrieving rssi");
ret = -EFAULT;
} else {
+ priv = hdd_request_priv(request);
+ adapter->peer_sta_info = priv->peer_sta_info;
ret = 0;
}
- goto set_magic;
} else {
ret = 0;
- return ret;
}
-set_magic:
- /*
- * either we never sent a request, we sent a request and received a
- * response or we sent a request and timed out. if we never sent a
- * request or if we sent a request and got a response, we want to
- * clear the magic out of paranoia. if we timed out there is a
- * race condition such that the callback function could be
- * executing at the same time we are. of primary concern is if the
- * callback function had already verified the "magic" but had not
- * yet set the completion variable when a timeout occurred. we
- * serialize these activities by invalidating the magic while
- * holding a shared spinlock which will cause us to block if the
- * callback is currently executing
- */
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
+ hdd_request_put(request);
return ret;
}
@@ -6087,60 +5965,43 @@
return ret;
}
+struct class_a_stats {
+ tCsrGlobalClassAStatsInfo class_a_stats;
+};
+
/**
* hdd_get_class_a_statistics_cb() - Get Class A stats callback function
- * @pStats: pointer to Class A stats
- * @pContext: user context originally registered with SME
+ * @stats: pointer to Class A stats
+ * @context: user context originally registered with SME (always the
+ * cookie from the request context)
*
* Return: None
*/
-static void hdd_get_class_a_statistics_cb(void *pStats, void *pContext)
+static void hdd_get_class_a_statistics_cb(void *stats, void *context)
{
- struct statsContext *pStatsContext;
- tCsrGlobalClassAStatsInfo *pClassAStats;
- hdd_adapter_t *pAdapter;
+ struct hdd_request *request;
+ struct class_a_stats *priv;
+ tCsrGlobalClassAStatsInfo *returned_stats;
- if ((NULL == pStats) || (NULL == pContext)) {
- hdd_err("Bad param, pStats [%pK] pContext [%pK]",
- pStats, pContext);
+ ENTER();
+ if ((NULL == stats) || (NULL == context)) {
+ hdd_err("Bad param, stats [%p] context [%p]",
+ stats, context);
return;
}
- pClassAStats = pStats;
- pStatsContext = pContext;
- pAdapter = pStatsContext->pAdapter;
-
- /* there is a race condition that exists between this callback
- * function and the caller since the caller could time out
- * either before or while this code is executing. we use a
- * spinlock to serialize these actions
- */
- spin_lock(&hdd_context_lock);
-
- if ((NULL == pAdapter) ||
- (STATS_CONTEXT_MAGIC != pStatsContext->magic)) {
- /* the caller presumably timed out so there is nothing
- * we can do
- */
- spin_unlock(&hdd_context_lock);
- hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]",
- pAdapter, pStatsContext->magic);
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("Obsolete request");
return;
}
- /* context is valid so caller is still waiting */
-
- /* paranoia: invalidate the magic */
- pStatsContext->magic = 0;
-
- /* copy over the stats. do so as a struct copy */
- pAdapter->hdd_stats.ClassA_stat = *pClassAStats;
-
- /* notify the caller */
- complete(&pStatsContext->completion);
-
- /* serialization is complete */
- spin_unlock(&hdd_context_lock);
+ returned_stats = stats;
+ priv = hdd_request_priv(request);
+ priv->class_a_stats = *returned_stats;
+ hdd_request_complete(request);
+ hdd_request_put(request);
+ EXIT();
}
/**
@@ -6153,8 +6014,14 @@
{
hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
QDF_STATUS hstatus;
- unsigned long rc;
- static struct statsContext context;
+ int ret;
+ void *cookie;
+ struct hdd_request *request;
+ struct class_a_stats *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_STATS,
+ };
if (NULL == pAdapter) {
hdd_err("pAdapter is NULL");
@@ -6166,10 +6033,13 @@
return QDF_STATUS_SUCCESS;
}
- /* we are connected so prepare our callback context */
- init_completion(&context.completion);
- context.pAdapter = pAdapter;
- context.magic = STATS_CONTEXT_MAGIC;
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("Request allocation failure");
+ return QDF_STATUS_E_NOMEM;
+ }
+ cookie = hdd_request_cookie(request);
+
/* query only for Class A statistics (which include link speed) */
hstatus = sme_get_statistics(WLAN_HDD_GET_HAL_CTX(pAdapter),
eCSR_HDD, SME_GLOBAL_CLASSA_STATS,
@@ -6177,100 +6047,80 @@
0, /* not periodic */
false, /* non-cached results */
pHddStaCtx->conn_info.staId[0],
- &context, pAdapter->sessionId);
+ cookie, pAdapter->sessionId);
if (QDF_STATUS_SUCCESS != hstatus) {
hdd_debug("Unable to retrieve Class A statistics");
- /* we'll returned a cached value below */
- } else {
- /* request was sent -- wait for the response */
- rc = wait_for_completion_timeout
- (&context.completion,
- msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
- if (!rc)
- hdd_warn("SME timed out while retrieving Class A statistics");
+ goto return_cached_results;
+ }
+ /* request was sent -- wait for the response */
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
+ hdd_warn("SME timed out while retrieving Class A statistics");
+ goto return_cached_results;
}
- /* either we never sent a request, we sent a request and
- * received a response or we sent a request and timed out. if
- * we never sent a request or if we sent a request and got a
- * response, we want to clear the magic out of paranoia. if
- * we timed out there is a race condition such that the
- * callback function could be executing at the same time we
- * are. of primary concern is if the callback function had
- * already verified the "magic" but had not yet set the
- * completion variable when a timeout occurred. we serialize
- * these activities by invalidating the magic while holding a
- * shared spinlock which will cause us to block if the
- * callback is currently executing
- */
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
+ /* update the adapter with the fresh results */
+ priv = hdd_request_priv(request);
+ pAdapter->hdd_stats.ClassA_stat = priv->class_a_stats;
- /* either callback updated pAdapter stats or it has cached data */
+return_cached_results:
+ /*
+ * either we never sent a request, we sent a request and
+ * received a response or we sent a request and timed out.
+ * regardless we are done with the request.
+ */
+ hdd_request_put(request);
+
return QDF_STATUS_SUCCESS;
}
+struct station_stats {
+ tCsrSummaryStatsInfo summary_stats;
+ tCsrGlobalClassAStatsInfo class_a_stats;
+ struct csr_per_chain_rssi_stats_info per_chain_rssi_stats;
+};
+
/**
* hdd_get_station_statistics_cb() - Get stats callback function
- * @pStats: pointer to Class A stats
- * @pContext: user context originally registered with SME
+ * @stats: pointer to combined station stats
+ * @context: user context originally registered with SME (always the
+ * cookie from the request context)
*
* Return: None
*/
-static void hdd_get_station_statistics_cb(void *pStats, void *pContext)
+static void hdd_get_station_statistics_cb(void *stats, void *context)
{
- struct statsContext *pStatsContext;
- tCsrSummaryStatsInfo *pSummaryStats;
- tCsrGlobalClassAStatsInfo *pClassAStats;
+ struct hdd_request *request;
+ struct station_stats *priv;
+ tCsrSummaryStatsInfo *summary_stats;
+ tCsrGlobalClassAStatsInfo *class_a_stats;
struct csr_per_chain_rssi_stats_info *per_chain_rssi_stats;
- hdd_adapter_t *pAdapter;
- if ((NULL == pStats) || (NULL == pContext)) {
- hdd_err("Bad param, pStats [%pK] pContext [%pK]",
- pStats, pContext);
+ if ((NULL == stats) || (NULL == context)) {
+ hdd_err("Bad param, pStats [%p] pContext [%p]",
+ stats, context);
return;
}
- /* there is a race condition that exists between this callback
- * function and the caller since the caller could time out
- * either before or while this code is executing. we use a
- * spinlock to serialize these actions
- */
- spin_lock(&hdd_context_lock);
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("Obsolete request");
+ return;
+ }
- pSummaryStats = (tCsrSummaryStatsInfo *) pStats;
- pClassAStats = (tCsrGlobalClassAStatsInfo *) (pSummaryStats + 1);
+ summary_stats = (tCsrSummaryStatsInfo *) stats;
+ class_a_stats = (tCsrGlobalClassAStatsInfo *) (summary_stats + 1);
per_chain_rssi_stats = (struct csr_per_chain_rssi_stats_info *)
- (pClassAStats + 1);
- pStatsContext = pContext;
- pAdapter = pStatsContext->pAdapter;
- if ((NULL == pAdapter) ||
- (STATS_CONTEXT_MAGIC != pStatsContext->magic)) {
- /* the caller presumably timed out so there is nothing
- * we can do
- */
- spin_unlock(&hdd_context_lock);
- hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]",
- pAdapter, pStatsContext->magic);
- return;
- }
-
- /* context is valid so caller is still waiting */
-
- /* paranoia: invalidate the magic */
- pStatsContext->magic = 0;
+ (class_a_stats + 1);
+ priv = hdd_request_priv(request);
/* copy over the stats. do so as a struct copy */
- pAdapter->hdd_stats.summary_stat = *pSummaryStats;
- pAdapter->hdd_stats.ClassA_stat = *pClassAStats;
- pAdapter->hdd_stats.per_chain_rssi_stats = *per_chain_rssi_stats;
+ priv->summary_stats = *summary_stats;
+ priv->class_a_stats = *class_a_stats;
+ priv->per_chain_rssi_stats = *per_chain_rssi_stats;
- /* notify the caller */
- complete(&pStatsContext->completion);
-
- /* serialization is complete */
- spin_unlock(&hdd_context_lock);
+ hdd_request_complete(request);
+ hdd_request_put(request);
}
/**
@@ -6283,18 +6133,26 @@
{
hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
QDF_STATUS hstatus;
- unsigned long rc;
- static struct statsContext context;
+ int ret;
+ void *cookie;
+ struct hdd_request *request;
+ struct station_stats *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_STATS,
+ };
if (NULL == pAdapter) {
hdd_err("pAdapter is NULL");
return QDF_STATUS_SUCCESS;
}
- /* we are connected so prepare our callback context */
- init_completion(&context.completion);
- context.pAdapter = pAdapter;
- context.magic = STATS_CONTEXT_MAGIC;
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("Request allocation failure");
+ return QDF_STATUS_E_NOMEM;
+ }
+ cookie = hdd_request_cookie(request);
/* query only for Summary & Class A statistics */
hstatus = sme_get_statistics(WLAN_HDD_GET_HAL_CTX(pAdapter),
@@ -6306,36 +6164,32 @@
0, /* not periodic */
false, /* non-cached results */
pHddStaCtx->conn_info.staId[0],
- &context, pAdapter->sessionId);
+ cookie, pAdapter->sessionId);
if (QDF_STATUS_SUCCESS != hstatus) {
hdd_err("Unable to retrieve statistics");
/* we'll return with cached values */
} else {
/* request was sent -- wait for the response */
- rc = wait_for_completion_timeout
- (&context.completion,
- msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
-
- if (!rc)
- hdd_err("SME timed out while retrieving statistics");
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
+ hdd_warn("SME timed out while retrieving statistics");
+ /* we'll returned a cached value below */
+ } else {
+ /* update the adapter with the fresh results */
+ priv = hdd_request_priv(request);
+ pAdapter->hdd_stats.summary_stat = priv->summary_stats;
+ pAdapter->hdd_stats.ClassA_stat = priv->class_a_stats;
+ pAdapter->hdd_stats.per_chain_rssi_stats =
+ priv->per_chain_rssi_stats;
+ }
}
- /* either we never sent a request, we sent a request and
- * received a response or we sent a request and timed out. if
- * we never sent a request or if we sent a request and got a
- * response, we want to clear the magic out of paranoia. if
- * we timed out there is a race condition such that the
- * callback function could be executing at the same time we
- * are. of primary concern is if the callback function had
- * already verified the "magic" but had not yet set the
- * completion variable when a timeout occurred. we serialize
- * these activities by invalidating the magic while holding a
- * shared spinlock which will cause us to block if the
- * callback is currently executing
+ /*
+ * either we never sent a request, we sent a request and
+ * received a response or we sent a request and timed out.
+ * regardless we are done with the request.
*/
- spin_lock(&hdd_context_lock);
- context.magic = 0;
- spin_unlock(&hdd_context_lock);
+ hdd_request_put(request);
/* either callback updated pAdapter stats or it has cached data */
return QDF_STATUS_SUCCESS;
@@ -7587,10 +7441,14 @@
return retval;
}
+struct temperature_priv {
+ int temperature;
+};
+
/**
* hdd_get_temperature_cb() - "Get Temperature" callback function
* @temperature: measured temperature
- * @pContext: callback context
+ * @context: callback context
*
* This function is passed to sme_get_temperature() as the callback
* function to be invoked when the temperature measurement is
@@ -7598,30 +7456,24 @@
*
* Return: None
*/
-static void hdd_get_temperature_cb(int temperature, void *pContext)
+static void hdd_get_temperature_cb(int temperature, void *context)
{
- struct statsContext *pTempContext;
- hdd_adapter_t *pAdapter;
+ struct hdd_request *request;
+ struct temperature_priv *priv;
ENTER();
- if (NULL == pContext) {
- hdd_err("pContext is NULL");
- return;
- }
- pTempContext = pContext;
- pAdapter = pTempContext->pAdapter;
- spin_lock(&hdd_context_lock);
- if ((NULL == pAdapter) || (TEMP_CONTEXT_MAGIC != pTempContext->magic)) {
- spin_unlock(&hdd_context_lock);
- hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]",
- pAdapter, pTempContext->magic);
- return;
- }
- if (temperature != 0)
- pAdapter->temperature = temperature;
- complete(&pTempContext->completion);
- spin_unlock(&hdd_context_lock);
+ request = hdd_request_get(context);
+ if (!request) {
+ hdd_err("Obsolete request");
+ return;
+ }
+
+ priv = hdd_request_priv(request);
+ priv->temperature = temperature;
+ hdd_request_complete(request);
+ hdd_request_put(request);
+
EXIT();
}
@@ -7634,35 +7486,54 @@
* returned, otherwise a negative errno is returned.
*
*/
-int wlan_hdd_get_temperature(hdd_adapter_t *pAdapter, int *temperature)
+int wlan_hdd_get_temperature(hdd_adapter_t *p_adapter, int *temperature)
{
QDF_STATUS status;
- static struct statsContext tempContext;
- unsigned long rc;
+ int ret;
+ void *cookie;
+ struct hdd_request *request;
+ struct temperature_priv *priv;
+ static const struct hdd_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_STATS,
+ };
ENTER();
- if (NULL == pAdapter) {
+ if (!p_adapter) {
hdd_err("pAdapter is NULL");
return -EPERM;
}
- init_completion(&tempContext.completion);
- tempContext.pAdapter = pAdapter;
- tempContext.magic = TEMP_CONTEXT_MAGIC;
- status = sme_get_temperature(WLAN_HDD_GET_HAL_CTX(pAdapter),
- &tempContext, hdd_get_temperature_cb);
+
+ request = hdd_request_alloc(¶ms);
+ if (!request) {
+ hdd_err("Request allocation failure");
+ return -ENOMEM;
+ }
+ cookie = hdd_request_cookie(request);
+ status = sme_get_temperature(WLAN_HDD_GET_HAL_CTX(p_adapter),
+ cookie, hdd_get_temperature_cb);
if (QDF_STATUS_SUCCESS != status) {
hdd_err("Unable to retrieve temperature");
} else {
- rc = wait_for_completion_timeout(&tempContext.completion,
- msecs_to_jiffies
- (WLAN_WAIT_TIME_STATS));
- if (!rc)
+ ret = hdd_request_wait_for_response(request);
+ if (ret) {
hdd_err("SME timed out while retrieving temperature");
+ } else {
+ /* update the adapter with the fresh results */
+ priv = hdd_request_priv(request);
+ if (priv->temperature)
+ p_adapter->temperature = priv->temperature;
+ }
}
- spin_lock(&hdd_context_lock);
- tempContext.magic = 0;
- spin_unlock(&hdd_context_lock);
- *temperature = pAdapter->temperature;
+
+ /*
+ * either we never sent a request, we sent a request and
+ * received a response or we sent a request and timed out.
+ * regardless we are done with the request.
+ */
+ hdd_request_put(request);
+
+ *temperature = p_adapter->temperature;
EXIT();
return 0;
}
diff --git a/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h b/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h
index 13b0d49..7ed3f2e 100644
--- a/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h
+++ b/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h
@@ -41,9 +41,9 @@
#define QWLAN_VERSION_MAJOR 5
#define QWLAN_VERSION_MINOR 2
#define QWLAN_VERSION_PATCH 1
-#define QWLAN_VERSION_EXTRA "J"
+#define QWLAN_VERSION_EXTRA "K"
#define QWLAN_VERSION_BUILD 1
-#define QWLAN_VERSIONSTR "5.2.1.1J.1"
+#define QWLAN_VERSIONSTR "5.2.1.1K"
#endif /* QWLAN_VERSION_H */
diff --git a/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h b/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h
index f797380..4212816 100644
--- a/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h
+++ b/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h
@@ -4549,6 +4549,17 @@
struct sir_peer_info info[MAX_PEER_STA];
};
+/**
+ * @sta_num: number of peer station which has valid info
+ * @info: peer extended information
+ *
+ * all SAP peer station's extended information retrieved
+ */
+struct sir_peer_sta_ext_info {
+ uint8_t sta_num;
+ struct sir_peer_info_ext info[MAX_PEER_STA];
+};
+
typedef struct sSirAddPeriodicTxPtrn {
/* MAC Address for the adapter */
struct qdf_mac_addr mac_address;
diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c
index 57c2624..018dde3 100644
--- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c
+++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c
@@ -349,6 +349,13 @@
pe_debug("tlv type %x len %u total %u",
tlv->type, tlv->length, data_len);
+
+ if (tlv->length > (data_len - 2)) {
+ pe_err("tlv len %d greater data_len %d",
+ tlv->length, data_len);
+ return 0;
+ }
+
switch (tlv->type) {
case SIR_FILS_EAP_TLV_KEYNAME_NAI:
auth_info->keyname = qdf_mem_malloc(tlv->length);
diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c
index dddffac..0c5681d 100644
--- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c
+++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c
@@ -5808,8 +5808,18 @@
if (update_ie->append) {
/*
* In case of append, allocate new memory
- * with combined length
+ * with combined length.
+ * Multiple back to back append commands
+ * can lead to a huge length.So, check
+ * for the validity of the length.
*/
+ if (addn_ie->probeRespDataLen >
+ (USHRT_MAX - update_ie->ieBufferlength)) {
+ pe_err("IE Length overflow, curr:%d, new:%d",
+ addn_ie->probeRespDataLen,
+ update_ie->ieBufferlength);
+ goto end;
+ }
new_length = update_ie->ieBufferlength +
addn_ie->probeRespDataLen;
new_ptr = qdf_mem_malloc(new_length);
diff --git a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c
index e9d9713..4c83e58 100644
--- a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c
+++ b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c
@@ -344,7 +344,7 @@
pBufRemaining += len + 2;
len += 2;
while (len < nBuf) {
- pIe = find_ie_defn(pCtx, pBufRemaining, nBuf + len, IEs);
+ pIe = find_ie_defn(pCtx, pBufRemaining, nBuf - len, IEs);
if (NULL == pIe)
break;
if (pIe->eid == pIeFirst->eid)
@@ -353,6 +353,8 @@
pBufRemaining += *(pBufRemaining + 1) + 2;
}
+ if ((len > 0xFF) || (len > nBuf))
+ return DOT11F_INTERNAL_ERROR;
*pnConsumed = len;
return DOT11F_PARSE_SUCCESS;
@@ -9984,11 +9986,15 @@
}
if (pIe) {
- if (nBufRemaining < pIe->minSize - pIe->noui - 2U) {
- FRAMES_LOG3(pCtx, FRLOGW, FRFL("The IE %s must be "
- "at least %d bytes in size, but there are onl"
- "y %d bytes remaining in this frame.\n"),
- pIe->name, pIe->minSize, nBufRemaining);
+ if ((nBufRemaining < pIe->minSize - pIe->noui - 2U) ||
+ (len < pIe->minSize - pIe->noui - 2U)) {
+ FRAMES_LOG4(pCtx, FRLOGW, FRFL("The IE %s must "
+ "be at least %d bytes in size, but "
+ "there are only %d bytes remaining in "
+ "this frame or the IE reports a size "
+ "of %d bytes.\n"),
+ pIe->name, pIe->minSize, nBufRemaining,
+ (len + pIe->noui + 2U));
FRAMES_DUMP(pCtx, FRLOG1, pBuf, nBuf);
status |= DOT11F_INCOMPLETE_IE;
FRAMES_DBG_BREAK();
diff --git a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c
index 7e7d13d..d575705 100644
--- a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c
+++ b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c
@@ -2360,6 +2360,7 @@
tDot11fIEfils_indication *fils_indication)
{
uint8_t *data;
+ uint8_t remaining_data = fils_indication->num_variable_data;
data = fils_indication->variable_data;
fils_ind->is_present = true;
@@ -2372,18 +2373,37 @@
fils_ind->is_pk_auth_supported =
fils_indication->is_pk_auth_supported;
if (fils_indication->is_cache_id_present) {
+ if (remaining_data < SIR_CACHE_IDENTIFIER_LEN) {
+ pe_err("Failed to copy Cache Identifier, Invalid remaining data %d",
+ remaining_data);
+ return;
+ }
fils_ind->cache_identifier.is_present = true;
qdf_mem_copy(fils_ind->cache_identifier.identifier,
data, SIR_CACHE_IDENTIFIER_LEN);
data = data + SIR_CACHE_IDENTIFIER_LEN;
+ remaining_data = remaining_data - SIR_CACHE_IDENTIFIER_LEN;
}
if (fils_indication->is_hessid_present) {
+ if (remaining_data < SIR_HESSID_LEN) {
+ pe_err("Failed to copy HESSID, Invalid remaining data %d",
+ remaining_data);
+ return;
+ }
fils_ind->hessid.is_present = true;
qdf_mem_copy(fils_ind->hessid.hessid,
data, SIR_HESSID_LEN);
data = data + SIR_HESSID_LEN;
+ remaining_data = remaining_data - SIR_HESSID_LEN;
}
if (fils_indication->realm_identifiers_cnt) {
+ if (remaining_data < (fils_indication->realm_identifiers_cnt *
+ SIR_REALM_LEN)) {
+ pe_err("Failed to copy Realm Identifier, Invalid remaining data %d realm_cnt %d",
+ remaining_data,
+ fils_indication->realm_identifiers_cnt);
+ return;
+ }
fils_ind->realm_identifier.is_present = true;
fils_ind->realm_identifier.realm_cnt =
fils_indication->realm_identifiers_cnt;
@@ -3173,8 +3193,7 @@
for (cnt = 0; cnt < ar->num_WMMTSPEC; cnt++) {
qdf_mem_copy(&pAssocRsp->TSPECInfo[cnt],
&ar->WMMTSPEC[cnt],
- (sizeof(tDot11fIEWMMTSPEC) *
- ar->num_WMMTSPEC));
+ sizeof(tDot11fIEWMMTSPEC));
}
pAssocRsp->tspecPresent = true;
}
diff --git a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/utils_parser.c b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/utils_parser.c
index f8aa5659..26bf304 100644
--- a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/utils_parser.c
+++ b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/utils_parser.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -140,7 +140,7 @@
{
/* This is awful, I know, but the old code just rammed the IE into */
/* an opaque array. Note that we need to explicitly add the vendorIE and OUI ! */
- uint8_t curAddIELen = pOld->length;
+ uint16_t curAddIELen = pOld->length;
pOld->length = curAddIELen + pNew->num_data + 6;
pOld->addIEdata[curAddIELen++] = 0xdd;
@@ -159,7 +159,7 @@
{
/* This is awful, I know, but the old code just rammed the IE into */
/* an opaque array. Note that we need to explicitly add the vendorIE and OUI ! */
- uint8_t curAddIELen = pOld->length;
+ uint16_t curAddIELen = pOld->length;
pOld->length = curAddIELen + pNew->num_data + 6;
pOld->addIEdata[curAddIELen++] = 0xdd;
@@ -179,7 +179,7 @@
{
/* This is awful, I know, but the old code just rammed the IE into */
/* an opaque array. Note that we need to explicitly add the vendorIE and OUI ! */
- uint8_t curAddIELen = pOld->length;
+ uint16_t curAddIELen = pOld->length;
pOld->length = curAddIELen + pNew->num_data + 6;
pOld->addIEdata[curAddIELen++] = 0xdd;
diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c
index 88aa4dd..b1e125a 100644
--- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c
+++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c
@@ -11812,9 +11812,10 @@
pIbssLog->eventId = WLAN_IBSS_EVENT_COALESCING;
if (pNewBss) {
qdf_copy_macaddr(&pIbssLog->bssid, &pNewBss->bssId);
- if (pNewBss->ssId.length)
- qdf_mem_copy(pIbssLog->ssid, pNewBss->ssId.ssId,
- pNewBss->ssId.length);
+ if (pNewBss->ssId.length > HOST_LOG_MAX_SSID_SIZE)
+ pNewBss->ssId.length = HOST_LOG_MAX_SSID_SIZE;
+ qdf_mem_copy(pIbssLog->ssid, pNewBss->ssId.ssId,
+ pNewBss->ssId.length);
pIbssLog->operatingChannel = pNewBss->channelNumber;
}
if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int(mac_ctx,
diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c
index c9b74e3..73d42db 100644
--- a/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c
+++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c
@@ -10685,7 +10685,9 @@
encrypt_decrypt_rsp_params.vdev_id = data_event->vdev_id;
encrypt_decrypt_rsp_params.status = data_event->status;
- if (data_event->data_length > param_buf->num_enc80211_frame) {
+ if ((data_event->data_length > param_buf->num_enc80211_frame) ||
+ (data_event->data_length > WMI_SVC_MSG_MAX_SIZE - WMI_TLV_HDR_SIZE -
+ sizeof(*data_event))) {
WMA_LOGE("FW msg data_len %d more than TLV hdr %d",
data_event->data_length,
param_buf->num_enc80211_frame);
diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c
index ea1b718..1e12bb3 100644
--- a/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c
+++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c
@@ -3297,6 +3297,13 @@
cds_pkt_return_packet(rx_pkt);
return -EINVAL;
}
+ if (qdf_nbuf_len(wbuf) < (sizeof(*wh) + IEEE80211_CCMP_HEADERLEN +
+ IEEE80211_CCMP_MICLEN)) {
+ WMA_LOGE("Buffer length less than expected %d ",
+ (int)qdf_nbuf_len(wbuf));
+ cds_pkt_return_packet(rx_pkt);
+ return -EINVAL;
+ }
orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
/* Pointer to head of CCMP header */
@@ -3481,6 +3488,7 @@
}
#define RATE_LIMIT 16
+#define RESERVE_BYTES 100
/**
* wma_mgmt_rx_process() - process management rx frame.
* @handle: wma handle
@@ -3616,9 +3624,28 @@
qdf_mem_free(rx_pkt);
return -EINVAL;
}
-
- /* Why not just use rx_event->hdr.buf_len? */
- wbuf = qdf_nbuf_alloc(NULL, roundup(hdr->buf_len, 4), 0, 4, false);
+ /*
+ * Allocate the memory for this rx packet, add extra 100 bytes for:-
+ *
+ * 1. Filling the missing RSN capabilites by some APs, which fill the
+ * RSN IE length as extra 2 bytes but dont fill the IE data with
+ * capabilities, resulting in failure in unpack core due to length
+ * mismatch. Check sir_validate_and_rectify_ies for more info.
+ *
+ * 2. In the API wma_process_rmf_frame(), the driver trims the CCMP
+ * header by overwriting the IEEE header to memory occupied by CCMP
+ * header, but an overflow is possible if the memory allocated to
+ * frame is less than the sizeof(struct ieee80211_frame) +CCMP
+ * HEADER len, so allocating 100 bytes would solve this issue too.
+ *
+ * 3. CCMP header is pointing to orig_hdr +
+ * sizeof(struct ieee80211_frame) which could also result in OOB
+ * access, if the data len is less than
+ * sizeof(struct ieee80211_frame), allocating extra bytes would
+ * result in solving this issue too.
+ */
+ wbuf = qdf_nbuf_alloc(NULL, roundup(hdr->buf_len + RESERVE_BYTES,
+ 4), 0, 4, false);
if (!wbuf) {
WMA_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)",
__func__, hdr->buf_len);
@@ -3629,6 +3656,9 @@
qdf_nbuf_put_tail(wbuf, hdr->buf_len);
qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
wh = (struct ieee80211_frame *)qdf_nbuf_data(wbuf);
+ qdf_mem_zero(((uint8_t *)wh + hdr->buf_len), roundup(hdr->buf_len +
+ RESERVE_BYTES, 4) -
+ hdr->buf_len);
rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(wbuf);
rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 6d9d2c7..18b68f0 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -327,10 +327,12 @@
irq = gpio_to_irq(ctrl_pdata->disp_err_detect_gpio);
- if (enable)
+ if (enable) {
enable_irq(irq);
- else
+ } else {
disable_irq(irq);
+ cancel_delayed_work_sync(&ctrl_pdata->err_int_work);
+ }
pr_debug(" %s : enable(%d)\n", __func__, enable);
}
@@ -522,8 +524,6 @@
gpio_set_value(ctrl_pdata->lcd_mode_sel_gpio, 0);
gpio_free(ctrl_pdata->lcd_mode_sel_gpio);
}
- if (pinfo->err_detect_enabled)
- mdss_dsi_err_detect_irq_control(ctrl_pdata, false);
}
exit:
@@ -1091,6 +1091,9 @@
goto end;
}
+ if (pinfo->err_detect_enabled)
+ mdss_dsi_err_detect_irq_control(ctrl, false);
+
if (ctrl->off_cmds.cmd_cnt)
mdss_dsi_panel_cmds_send(ctrl, &ctrl->off_cmds, CMD_REQ_COMMIT);
diff --git a/drivers/video/fbdev/msm/mdss_dsi_status.c b/drivers/video/fbdev/msm/mdss_dsi_status.c
index c6801ea..9089340 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_status.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_status.c
@@ -177,23 +177,35 @@
int disp_read_err_register(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
struct dcs_cmd_req cmdreq;
- char rx_buf[1] = {0x0};
+ /*
+ * setting a non-zero default value, if for some reason unable to read
+ * back the value it should be treated as failure
+ */
+ char rx_buf[1] = {0xFF};
char err_read_dcs_cmd[2] = {0x9F, 0x00}; /* DTYPE_DCS_READ */
struct dsi_cmd_desc err_read_dsi_cmd_desc = {
{DTYPE_DCS_READ, 1, 0, 1, 5, sizeof(err_read_dcs_cmd)},
err_read_dcs_cmd
};
+ int ret;
memset(&cmdreq, 0, sizeof(cmdreq));
cmdreq.cmds = &err_read_dsi_cmd_desc;
cmdreq.cmds_cnt = 1;
+ /* make sure there is no ongoing transfer while checking error status */
cmdreq.flags = CMD_REQ_RX | CMD_REQ_COMMIT | CMD_REQ_HS_MODE |
- CMD_CLK_CTRL;
+ CMD_CLK_CTRL | CMD_REQ_MDP_IDLE;
cmdreq.rlen = 1;
cmdreq.cb = NULL;
cmdreq.rbuf = rx_buf;
- mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq);
+ ret = mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq);
+ if (ret != cmdreq.rlen) {
+ pr_warn("%s: unable to read panel status (%d)\n",
+ __func__, ret);
+ return -EINVAL;
+ }
+
pr_info("%s: Reg[0x%x]=0x%x\n", __func__,
err_read_dcs_cmd[0], rx_buf[0]);