diff options
Diffstat (limited to 'package/kernel/mac80211/patches/319-ath9k_htc-add-new-WMI_REG_RMW_CMDID-command.patch')
-rw-r--r-- | package/kernel/mac80211/patches/319-ath9k_htc-add-new-WMI_REG_RMW_CMDID-command.patch | 307 |
1 files changed, 0 insertions, 307 deletions
diff --git a/package/kernel/mac80211/patches/319-ath9k_htc-add-new-WMI_REG_RMW_CMDID-command.patch b/package/kernel/mac80211/patches/319-ath9k_htc-add-new-WMI_REG_RMW_CMDID-command.patch deleted file mode 100644 index 6af69ebd2a..0000000000 --- a/package/kernel/mac80211/patches/319-ath9k_htc-add-new-WMI_REG_RMW_CMDID-command.patch +++ /dev/null @@ -1,307 +0,0 @@ -From: Oleksij Rempel <linux@rempel-privat.de> -Date: Sun, 22 Mar 2015 19:29:46 +0100 -Subject: [PATCH] ath9k_htc: add new WMI_REG_RMW_CMDID command - -Since usb bus add extra delay on each request, a command -with read + write requests is too expensive. We can dramtically -reduce usb load by moving this command to firmware. - -In my tests, this patch will reduce channel scan time -for about 5-10 seconds. - -Signed-off-by: Oleksij Rempel <linux@rempel-privat.de> -Signed-off-by: Kalle Valo <kvalo@codeaurora.org> ---- - ---- a/drivers/net/wireless/ath/ath.h -+++ b/drivers/net/wireless/ath/ath.h -@@ -131,6 +131,9 @@ struct ath_ops { - void (*enable_write_buffer)(void *); - void (*write_flush) (void *); - u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr); -+ void (*enable_rmw_buffer)(void *); -+ void (*rmw_flush) (void *); -+ - }; - - struct ath_common; ---- a/drivers/net/wireless/ath/ath9k/htc.h -+++ b/drivers/net/wireless/ath/ath9k/htc.h -@@ -444,6 +444,10 @@ static inline void ath9k_htc_stop_btcoex - #define OP_BT_SCAN BIT(4) - #define OP_TSF_RESET BIT(6) - -+enum htc_op_flags { -+ HTC_FWFLAG_NO_RMW, -+}; -+ - struct ath9k_htc_priv { - struct device *dev; - struct ieee80211_hw *hw; -@@ -482,6 +486,7 @@ struct ath9k_htc_priv { - bool reconfig_beacon; - unsigned int rxfilter; - unsigned long op_flags; -+ unsigned long fw_flags; - - struct ath9k_hw_cal_data caldata; - struct ath_spec_scan_priv spec_priv; ---- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c -+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c -@@ -376,17 +376,139 @@ static void ath9k_regwrite_flush(void *h - mutex_unlock(&priv->wmi->multi_write_mutex); - } - --static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) -+static void ath9k_reg_rmw_buffer(void *hw_priv, -+ u32 reg_offset, u32 set, u32 clr) -+{ -+ struct ath_hw *ah = (struct ath_hw *) hw_priv; -+ struct ath_common *common = ath9k_hw_common(ah); -+ struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; -+ u32 rsp_status; -+ int r; -+ -+ mutex_lock(&priv->wmi->multi_rmw_mutex); -+ -+ /* Store the register/value */ -+ priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].reg = -+ cpu_to_be32(reg_offset); -+ priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].set = -+ cpu_to_be32(set); -+ priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].clr = -+ cpu_to_be32(clr); -+ -+ priv->wmi->multi_rmw_idx++; -+ -+ /* If the buffer is full, send it out. */ -+ if (priv->wmi->multi_rmw_idx == MAX_RMW_CMD_NUMBER) { -+ r = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID, -+ (u8 *) &priv->wmi->multi_rmw, -+ sizeof(struct register_write) * priv->wmi->multi_rmw_idx, -+ (u8 *) &rsp_status, sizeof(rsp_status), -+ 100); -+ if (unlikely(r)) { -+ ath_dbg(common, WMI, -+ "REGISTER RMW FAILED, multi len: %d\n", -+ priv->wmi->multi_rmw_idx); -+ } -+ priv->wmi->multi_rmw_idx = 0; -+ } -+ -+ mutex_unlock(&priv->wmi->multi_rmw_mutex); -+} -+ -+static void ath9k_reg_rmw_flush(void *hw_priv) - { -- u32 val; -+ struct ath_hw *ah = (struct ath_hw *) hw_priv; -+ struct ath_common *common = ath9k_hw_common(ah); -+ struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; -+ u32 rsp_status; -+ int r; -+ -+ if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags)) -+ return; -+ -+ atomic_dec(&priv->wmi->m_rmw_cnt); -+ -+ mutex_lock(&priv->wmi->multi_rmw_mutex); -+ -+ if (priv->wmi->multi_rmw_idx) { -+ r = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID, -+ (u8 *) &priv->wmi->multi_rmw, -+ sizeof(struct register_rmw) * priv->wmi->multi_rmw_idx, -+ (u8 *) &rsp_status, sizeof(rsp_status), -+ 100); -+ if (unlikely(r)) { -+ ath_dbg(common, WMI, -+ "REGISTER RMW FAILED, multi len: %d\n", -+ priv->wmi->multi_rmw_idx); -+ } -+ priv->wmi->multi_rmw_idx = 0; -+ } - -- val = ath9k_regread(hw_priv, reg_offset); -- val &= ~clr; -- val |= set; -- ath9k_regwrite(hw_priv, val, reg_offset); -+ mutex_unlock(&priv->wmi->multi_rmw_mutex); -+} -+ -+static void ath9k_enable_rmw_buffer(void *hw_priv) -+{ -+ struct ath_hw *ah = (struct ath_hw *) hw_priv; -+ struct ath_common *common = ath9k_hw_common(ah); -+ struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; -+ -+ if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags)) -+ return; -+ -+ atomic_inc(&priv->wmi->m_rmw_cnt); -+} -+ -+static u32 ath9k_reg_rmw_single(void *hw_priv, -+ u32 reg_offset, u32 set, u32 clr) -+{ -+ struct ath_hw *ah = (struct ath_hw *) hw_priv; -+ struct ath_common *common = ath9k_hw_common(ah); -+ struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; -+ struct register_rmw buf, buf_ret; -+ int ret; -+ u32 val = 0; -+ -+ buf.reg = cpu_to_be32(reg_offset); -+ buf.set = cpu_to_be32(set); -+ buf.clr = cpu_to_be32(clr); -+ -+ ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID, -+ (u8 *) &buf, sizeof(buf), -+ (u8 *) &buf_ret, sizeof(buf_ret), -+ 100); -+ if (unlikely(ret)) { -+ ath_dbg(common, WMI, "REGISTER RMW FAILED:(0x%04x, %d)\n", -+ reg_offset, ret); -+ } - return val; - } - -+static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) -+{ -+ struct ath_hw *ah = (struct ath_hw *) hw_priv; -+ struct ath_common *common = ath9k_hw_common(ah); -+ struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; -+ -+ if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags)) { -+ u32 val; -+ -+ val = REG_READ(ah, reg_offset); -+ val &= ~clr; -+ val |= set; -+ REG_WRITE(ah, reg_offset, val); -+ -+ return 0; -+ } -+ -+ if (atomic_read(&priv->wmi->m_rmw_cnt)) -+ ath9k_reg_rmw_buffer(hw_priv, reg_offset, set, clr); -+ else -+ ath9k_reg_rmw_single(hw_priv, reg_offset, set, clr); -+ -+ return 0; -+} -+ - static void ath_usb_read_cachesize(struct ath_common *common, int *csz) - { - *csz = L1_CACHE_BYTES >> 2; -@@ -501,6 +623,8 @@ static int ath9k_init_priv(struct ath9k_ - ah->reg_ops.write = ath9k_regwrite; - ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer; - ah->reg_ops.write_flush = ath9k_regwrite_flush; -+ ah->reg_ops.enable_rmw_buffer = ath9k_enable_rmw_buffer; -+ ah->reg_ops.rmw_flush = ath9k_reg_rmw_flush; - ah->reg_ops.rmw = ath9k_reg_rmw; - priv->ah = ah; - -@@ -686,6 +810,12 @@ static int ath9k_init_firmware_version(s - return -EINVAL; - } - -+ if (priv->fw_version_major == 1 && priv->fw_version_minor < 4) -+ set_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags); -+ -+ dev_info(priv->dev, "FW RMW support: %s\n", -+ test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags) ? "Off" : "On"); -+ - return 0; - } - ---- a/drivers/net/wireless/ath/ath9k/hw.h -+++ b/drivers/net/wireless/ath/ath9k/hw.h -@@ -100,6 +100,18 @@ - (_ah)->reg_ops.write_flush((_ah)); \ - } while (0) - -+#define ENABLE_REG_RMW_BUFFER(_ah) \ -+ do { \ -+ if ((_ah)->reg_ops.enable_rmw_buffer) \ -+ (_ah)->reg_ops.enable_rmw_buffer((_ah)); \ -+ } while (0) -+ -+#define REG_RMW_BUFFER_FLUSH(_ah) \ -+ do { \ -+ if ((_ah)->reg_ops.rmw_flush) \ -+ (_ah)->reg_ops.rmw_flush((_ah)); \ -+ } while (0) -+ - #define PR_EEP(_s, _val) \ - do { \ - len += scnprintf(buf + len, size - len, "%20s : %10d\n",\ ---- a/drivers/net/wireless/ath/ath9k/wmi.c -+++ b/drivers/net/wireless/ath/ath9k/wmi.c -@@ -61,6 +61,8 @@ static const char *wmi_cmd_to_name(enum - return "WMI_REG_READ_CMDID"; - case WMI_REG_WRITE_CMDID: - return "WMI_REG_WRITE_CMDID"; -+ case WMI_REG_RMW_CMDID: -+ return "WMI_REG_RMW_CMDID"; - case WMI_RC_STATE_CHANGE_CMDID: - return "WMI_RC_STATE_CHANGE_CMDID"; - case WMI_RC_RATE_UPDATE_CMDID: -@@ -101,6 +103,7 @@ struct wmi *ath9k_init_wmi(struct ath9k_ - spin_lock_init(&wmi->event_lock); - mutex_init(&wmi->op_mutex); - mutex_init(&wmi->multi_write_mutex); -+ mutex_init(&wmi->multi_rmw_mutex); - init_completion(&wmi->cmd_wait); - INIT_LIST_HEAD(&wmi->pending_tx_events); - tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet, ---- a/drivers/net/wireless/ath/ath9k/wmi.h -+++ b/drivers/net/wireless/ath/ath9k/wmi.h -@@ -112,6 +112,7 @@ enum wmi_cmd_id { - WMI_TX_STATS_CMDID, - WMI_RX_STATS_CMDID, - WMI_BITRATE_MASK_CMDID, -+ WMI_REG_RMW_CMDID, - }; - - enum wmi_event_id { -@@ -125,12 +126,19 @@ enum wmi_event_id { - }; - - #define MAX_CMD_NUMBER 62 -+#define MAX_RMW_CMD_NUMBER 15 - - struct register_write { - __be32 reg; - __be32 val; - }; - -+struct register_rmw { -+ __be32 reg; -+ __be32 set; -+ __be32 clr; -+} __packed; -+ - struct ath9k_htc_tx_event { - int count; - struct __wmi_event_txstatus txs; -@@ -156,10 +164,18 @@ struct wmi { - - spinlock_t wmi_lock; - -+ /* multi write section */ - atomic_t mwrite_cnt; - struct register_write multi_write[MAX_CMD_NUMBER]; - u32 multi_write_idx; - struct mutex multi_write_mutex; -+ -+ /* multi rmw section */ -+ atomic_t m_rmw_cnt; -+ struct register_rmw multi_rmw[MAX_RMW_CMD_NUMBER]; -+ u32 multi_rmw_idx; -+ struct mutex multi_rmw_mutex; -+ - }; - - struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv); |