[PATCH] ath10k: cache calibration data when the core is stopped.
Marty Faltesek
mfaltesek at google.com
Tue Sep 13 14:11:58 PDT 2016
Caching calibration data allows it to be accessed when the
device is not active.
Signed-off-by: Marty Faltesek <mfaltesek at google.com>
---
drivers/net/wireless/ath/ath10k/core.c | 47 ++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/core.h | 2 ++
drivers/net/wireless/ath/ath10k/debug.c | 51 +++++++++------------------------
drivers/net/wireless/ath/ath10k/debug.h | 1 +
drivers/net/wireless/ath/ath10k/mac.c | 1 +
5 files changed, 65 insertions(+), 37 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index c0b9797..c99ad9e 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1227,6 +1227,42 @@ success:
return 0;
}
+int
+ath10k_cal_data_alloc(struct ath10k *ar, void **buf)
+{
+ u32 hi_addr;
+ __le32 addr;
+ int ret;
+
+ vfree(*buf);
+ *buf = vmalloc(QCA988X_CAL_DATA_LEN);
+ if (!*buf) {
+ return -EAGAIN;
+ }
+
+ hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
+
+ ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
+
+ if (ret) {
+ ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
+ } else {
+ ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), *buf,
+ QCA988X_CAL_DATA_LEN);
+ if (ret) {
+ ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
+ }
+ }
+
+ if (ret) {
+ vfree(*buf);
+ *buf = NULL;
+ }
+
+ return ret;
+}
+
+
static int ath10k_download_cal_data(struct ath10k *ar)
{
int ret;
@@ -1714,6 +1750,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
INIT_LIST_HEAD(&ar->arvifs);
+ /*
+ * We are up now, so no need to cache calibration data.
+ */
+ vfree(ar->cal_data);
+ ar->cal_data = NULL;
+
return 0;
err_hif_stop:
@@ -1757,6 +1799,11 @@ void ath10k_core_stop(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex);
ath10k_debug_stop(ar);
+ /*
+ * Cache caclibration data while stopped.
+ */
+ ath10k_cal_data_alloc(ar, &ar->cal_data);
+
/* try to suspend target */
if (ar->state != ATH10K_STATE_RESTARTING &&
ar->state != ATH10K_STATE_UTF)
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 4d3f002..cce61c1 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -635,6 +635,8 @@ struct ath10k {
struct ath10k_htc htc;
struct ath10k_htt htt;
+ void *cal_data;
+
struct ath10k_hw_params {
u32 id;
u16 dev_id;
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 8b01e3e..7de0eb4 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1427,53 +1427,26 @@ static const struct file_operations fops_fw_dbglog = {
static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
{
struct ath10k *ar = inode->i_private;
- void *buf;
- u32 hi_addr;
- __le32 addr;
int ret;
mutex_lock(&ar->conf_mutex);
if (ar->state != ATH10K_STATE_ON &&
- ar->state != ATH10K_STATE_UTF) {
- ret = -ENETDOWN;
- goto err;
- }
-
- buf = vmalloc(QCA988X_CAL_DATA_LEN);
- if (!buf) {
- ret = -ENOMEM;
- goto err;
+ ar->state != ATH10K_STATE_UTF && ! ar->cal_data) {
+ mutex_unlock(&ar->conf_mutex);
+ return (-ENETDOWN);
}
- hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
-
- ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
- if (ret) {
- ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
- goto err_vfree;
- }
-
- ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
- QCA988X_CAL_DATA_LEN);
- if (ret) {
- ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
- goto err_vfree;
+ if (ar->cal_data) {
+ file->private_data = ar->cal_data;
+ mutex_unlock(&ar->conf_mutex);
+ return 0;
}
- file->private_data = buf;
-
- mutex_unlock(&ar->conf_mutex);
-
- return 0;
-
-err_vfree:
- vfree(buf);
-
-err:
+ ret = ath10k_cal_data_alloc(ar, &file->private_data);
mutex_unlock(&ar->conf_mutex);
- return ret;
+ return (ret);
}
static ssize_t ath10k_debug_cal_data_read(struct file *file,
@@ -1489,7 +1462,11 @@ static ssize_t ath10k_debug_cal_data_read(struct file *file,
static int ath10k_debug_cal_data_release(struct inode *inode,
struct file *file)
{
- vfree(file->private_data);
+ struct ath10k *ar = inode->i_private;
+
+ /* Free if it's not the cached version */
+ if (ar->cal_data != file->private_data)
+ vfree(file->private_data);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 3900934..1ae757c 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -59,6 +59,7 @@ enum ath10k_dbg_aggr_mode {
#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
extern unsigned int ath10k_debug_mask;
+extern int ath10k_cal_data_alloc(struct ath10k *ar, void **buf);
__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
__printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index eb36859..88fb27f 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6924,6 +6924,7 @@ struct ath10k *ath10k_mac_create(size_t priv_size)
void ath10k_mac_destroy(struct ath10k *ar)
{
+ vfree(ar->cal_data);
ieee80211_free_hw(ar->hw);
}
--
2.8.0.rc3.226.g39d4020
More information about the ath10k
mailing list