Hi John,
Here is pull request intended for 3.15.
I have here a whole bunch of various things. Trivial cleanups, debugfs handlers and new stuff for the new generation of devices along with new capabilities for monitor mode. We also have support for power save for dual interface mode, but that is not supported by the firmware currently available.
I had to merge wireless-next to get the new bits for monitor mode I added in mac80211-next.git.
Let me know if you have any issue.
Thanks!
The following changes since commit e57f1734d87aa0e9a00905ed08888f0c62f56227:
Starting
mwifiex: add key material v2 support (2014-02-12 15:36:26 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git for-john
for you to fetch changes up to 82b715c211a53e80a1db83b9b71995a05fe32908:
iwlwifi: mvm: fix a few wd_disable comments (2014-02-23 21:38:54 +0200)
----------------------------------------------------------------
Alexander Bondar (1):
iwlwifi: mvm: Enable power save on BSS and P2P client in DCM
Eliad Peller (3):
iwlwifi: pcie: clean iwl_pcie_[rt]xq_inc_wr_ptr a bit
iwlwifi: mvm: add debugfs for prph reg read/write
iwlwifi: mvm: fix a few wd_disable comments
Emmanuel Grumbach (4):
iwlwifi: mvm: propagate LDPC / STBC status to radiotap
iwlwifi: mvm: don't dump log of second CPU when not relevant
iwlwifi: pcie: stop the firmware when we restart it
iwlwifi: mvm: set immediate apply time bit in time events
Eran Harary (2):
iwlwifi: mvm: new NVM format in family 8000
iwlwifi: mvm: prepare infrastructure for more TLV flags
Eyal Shapira (1):
iwlwifi: mvm: add Rx frames statistics via debugfs
Eytan Lifshitz (1):
iwlwifi: mvm: fix possible memory leak
Inbal Hacohen (1):
iwlwifi: mvm: remove redundant define in fw.c
Johannes Berg (4):
iwlwifi: make various things const
iwlwifi: mvm: use IEEE80211_TX_CTRL_PORT_CTRL_PROTO flag
iwlwifi: remove iwl_fw_valid_(tx|rx)_ant inlines
iwlwifi: nvm: remove reading valid antennas from NVM
drivers/net/wireless/iwlwifi/dvm/agn.h | 4 +-
drivers/net/wireless/iwlwifi/dvm/devices.c | 2 +-
drivers/net/wireless/iwlwifi/dvm/mac80211.c | 2 +-
drivers/net/wireless/iwlwifi/dvm/rx.c | 2 +-
drivers/net/wireless/iwlwifi/iwl-drv.c | 53 ++++-
drivers/net/wireless/iwlwifi/iwl-drv.h | 14 ++
drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | 5 +-
drivers/net/wireless/iwlwifi/iwl-fw-file.h | 17 ++
drivers/net/wireless/iwlwifi/iwl-fw.h | 24 +--
drivers/net/wireless/iwlwifi/iwl-modparams.h | 2 +-
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 245 +++++++++++++++++------
drivers/net/wireless/iwlwifi/iwl-nvm-parse.h | 3 +-
drivers/net/wireless/iwlwifi/iwl-trans.h | 2 +-
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 2 +-
drivers/net/wireless/iwlwifi/mvm/debugfs.c | 118 ++++++++++-
drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | 3 +-
drivers/net/wireless/iwlwifi/mvm/fw-api.h | 5 +-
drivers/net/wireless/iwlwifi/mvm/fw.c | 14 +-
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 2 +-
drivers/net/wireless/iwlwifi/mvm/mac80211.c | 12 +-
drivers/net/wireless/iwlwifi/mvm/mvm.h | 35 +++-
drivers/net/wireless/iwlwifi/mvm/nvm.c | 67 +++++--
drivers/net/wireless/iwlwifi/mvm/ops.c | 2 +-
drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 4 +-
drivers/net/wireless/iwlwifi/mvm/power.c | 48 ++++-
drivers/net/wireless/iwlwifi/mvm/rs.c | 93 +++++++--
drivers/net/wireless/iwlwifi/mvm/rx.c | 21 ++
drivers/net/wireless/iwlwifi/mvm/scan.c | 4 +-
drivers/net/wireless/iwlwifi/mvm/time-event.c | 6 +-
drivers/net/wireless/iwlwifi/mvm/tx.c | 4 +-
drivers/net/wireless/iwlwifi/mvm/utils.c | 6 +-
drivers/net/wireless/iwlwifi/pcie/internal.h | 2 +-
drivers/net/wireless/iwlwifi/pcie/rx.c | 47 ++---
drivers/net/wireless/iwlwifi/pcie/tx.c | 68 +++----
34 files changed, 713 insertions(+), 225 deletions(-)
From: Emmanuel Grumbach <[email protected]>
This will allow to get sniffer captures with correct
settings for these HT / VHT capabilities.
Also set the corresponding HAVE_MCS / VHT_KNOWN bits in
the registration to mac80211.
Reviewed-by: Johannes Berg <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | 3 ++-
drivers/net/wireless/iwlwifi/mvm/mac80211.c | 4 ++++
drivers/net/wireless/iwlwifi/mvm/rs.c | 2 +-
drivers/net/wireless/iwlwifi/mvm/rx.c | 8 ++++++++
4 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h
index 8505721..39148b5 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h
@@ -257,7 +257,8 @@ enum {
/* Bit 17-18: (0) SS, (1) SS*2 */
#define RATE_MCS_STBC_POS 17
-#define RATE_MCS_STBC_MSK (1 << RATE_MCS_STBC_POS)
+#define RATE_MCS_HT_STBC_MSK (3 << RATE_MCS_STBC_POS)
+#define RATE_MCS_VHT_STBC_MSK (1 << RATE_MCS_STBC_POS)
/* Bit 19: (0) Beamforming is off, (1) Beamforming is on */
#define RATE_MCS_BF_POS 19
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 42f7046..2a1b4b6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -68,6 +68,7 @@
#include <linux/ip.h>
#include <linux/if_arp.h>
#include <net/mac80211.h>
+#include <net/ieee80211_radiotap.h>
#include <net/tcp.h>
#include "iwl-op-mode.h"
@@ -280,6 +281,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->queues = mvm->first_agg_queue;
hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
+ hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC |
+ IEEE80211_RADIOTAP_MCS_HAVE_STBC;
+ hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC;
hw->rate_control_algorithm = "iwl-mvm-rs";
/*
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 32bb807..a6d0ab1 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -2595,7 +2595,7 @@ static int rs_pretty_print_rate(char *buf, const u32 rate)
return sprintf(buf, "%s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s\n",
type, rs_pretty_ant(ant), bw, mcs, nss,
(rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ",
- (rate & RATE_MCS_STBC_MSK) ? "STBC " : "",
+ (rate & RATE_MCS_HT_STBC_MSK) ? "STBC " : "",
(rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "",
(rate & RATE_MCS_BF_MSK) ? "BF " : "",
(rate & RATE_MCS_ZLF_MSK) ? "ZLF " : "");
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index fa3c139..817d3e0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -368,15 +368,23 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
rx_status.flag |= RX_FLAG_SHORT_GI;
if (rate_n_flags & RATE_HT_MCS_GF_MSK)
rx_status.flag |= RX_FLAG_HT_GF;
+ if (rate_n_flags & RATE_MCS_LDPC_MSK)
+ rx_status.flag |= RX_FLAG_LDPC;
if (rate_n_flags & RATE_MCS_HT_MSK) {
+ u8 stbc = (rate_n_flags & RATE_MCS_HT_STBC_MSK) >>
+ RATE_MCS_STBC_POS;
rx_status.flag |= RX_FLAG_HT;
rx_status.rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
+ rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT;
} else if (rate_n_flags & RATE_MCS_VHT_MSK) {
+ u8 stbc = (rate_n_flags & RATE_MCS_VHT_STBC_MSK) >>
+ RATE_MCS_STBC_POS;
rx_status.vht_nss =
((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
RATE_VHT_MCS_NSS_POS) + 1;
rx_status.rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
rx_status.flag |= RX_FLAG_VHT;
+ rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT;
} else {
rx_status.rate_idx =
iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
--
1.7.9.5
From: Johannes Berg <[email protected]>
There are a number of things in the .data section that should
really be in .rodata, for example all ops structs and strings.
Mark everything const that can be, leaving the .data section
pretty much empty.
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/dvm/agn.h | 4 ++--
drivers/net/wireless/iwlwifi/dvm/devices.c | 2 +-
drivers/net/wireless/iwlwifi/dvm/mac80211.c | 2 +-
drivers/net/wireless/iwlwifi/dvm/rx.c | 2 +-
drivers/net/wireless/iwlwifi/iwl-trans.h | 2 +-
drivers/net/wireless/iwlwifi/mvm/mac80211.c | 2 +-
drivers/net/wireless/iwlwifi/mvm/mvm.h | 3 +--
drivers/net/wireless/iwlwifi/mvm/ops.c | 2 +-
drivers/net/wireless/iwlwifi/mvm/utils.c | 4 ++--
drivers/net/wireless/iwlwifi/pcie/internal.h | 2 +-
10 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index 562772d..c160dad 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -109,7 +109,7 @@ extern const struct iwl_dvm_cfg iwl_dvm_6030_cfg;
struct iwl_ucode_capabilities;
-extern struct ieee80211_ops iwlagn_hw_ops;
+extern const struct ieee80211_ops iwlagn_hw_ops;
static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
{
@@ -480,7 +480,7 @@ do { \
} while (0)
#endif /* CONFIG_IWLWIFI_DEBUG */
-extern const char *iwl_dvm_cmd_strings[REPLY_MAX];
+extern const char *const iwl_dvm_cmd_strings[REPLY_MAX];
static inline const char *iwl_dvm_get_cmd_string(u8 cmd)
{
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c
index 7b140e4..758c54e 100644
--- a/drivers/net/wireless/iwlwifi/dvm/devices.c
+++ b/drivers/net/wireless/iwlwifi/dvm/devices.c
@@ -317,7 +317,7 @@ static const struct iwl_sensitivity_ranges iwl5000_sensitivity = {
.nrg_th_cca = 62,
};
-static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
+static const struct iwl_sensitivity_ranges iwl5150_sensitivity = {
.min_nrg_cck = 95,
.auto_corr_min_ofdm = 90,
.auto_corr_min_ofdm_mrc = 170,
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index c24d1d3..f576089 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -1564,7 +1564,7 @@ static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "leave\n");
}
-struct ieee80211_ops iwlagn_hw_ops = {
+const struct ieee80211_ops iwlagn_hw_ops = {
.tx = iwlagn_mac_tx,
.start = iwlagn_mac_start,
.stop = iwlagn_mac_stop,
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c
index 7a1bc1c..cd83773 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rx.c
@@ -39,7 +39,7 @@
#define IWL_CMD_ENTRY(x) [x] = #x
-const char *iwl_dvm_cmd_strings[REPLY_MAX] = {
+const char *const iwl_dvm_cmd_strings[REPLY_MAX] = {
IWL_CMD_ENTRY(REPLY_ALIVE),
IWL_CMD_ENTRY(REPLY_ERROR),
IWL_CMD_ENTRY(REPLY_ECHO),
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 7b19274..8cdb0dd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -393,7 +393,7 @@ struct iwl_trans_config {
bool rx_buf_size_8k;
bool bc_table_dword;
unsigned int queue_watchdog_timeout;
- const char **command_names;
+ const char *const *command_names;
};
struct iwl_trans;
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index ba4dcab..42f7046 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -2233,7 +2233,7 @@ static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
}
#endif
-struct ieee80211_ops iwl_mvm_hw_ops = {
+const struct ieee80211_ops iwl_mvm_hw_ops = {
.tx = iwl_mvm_mac_tx,
.ampdu_action = iwl_mvm_mac_ampdu_action,
.start = iwl_mvm_mac_start,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index ebea5f2..bde8190 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -91,8 +91,7 @@ enum iwl_mvm_tx_fifo {
IWL_MVM_TX_FIFO_MCAST = 5,
};
-extern struct ieee80211_ops iwl_mvm_hw_ops;
-extern const struct iwl_mvm_power_ops pm_mac_ops;
+extern const struct ieee80211_ops iwl_mvm_hw_ops;
/**
* struct iwl_mvm_mod_params - module parameters for iwlmvm
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index a46f0b8..ae347fb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -245,7 +245,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
#undef RX_HANDLER
#define CMD(x) [x] = #x
-static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
+static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(MVM_ALIVE),
CMD(REPLY_ERROR),
CMD(INIT_COMPLETE_NOTIF),
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index f4598cb..2021b57 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -289,8 +289,8 @@ u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx)
return last_idx;
}
-static struct {
- char *name;
+static const struct {
+ const char *name;
u8 num;
} advanced_lookup[] = {
{ "NMI_INTERRUPT_WDG", 0x34 },
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index e851f26..3120bc5 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -304,7 +304,7 @@ struct iwl_trans_pcie {
bool bc_table_dword;
u32 rx_page_order;
- const char **command_names;
+ const char *const *command_names;
/* queue watchdog */
unsigned long wd_timeout;
--
1.7.9.5
From: Johannes Berg <[email protected]>
These inlines are pretty pointless now as they just return a
fixed struct value, remove them - the code even gets shorter.
Signed-off-by: Johannes Berg <[email protected]>
Reviewed-by: Eran Harary <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-fw.h | 10 ----------
drivers/net/wireless/iwlwifi/mvm/debugfs.c | 2 +-
drivers/net/wireless/iwlwifi/mvm/fw.c | 6 +++---
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 2 +-
drivers/net/wireless/iwlwifi/mvm/nvm.c | 4 ++--
drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 4 ++--
drivers/net/wireless/iwlwifi/mvm/rs.c | 18 +++++++++---------
drivers/net/wireless/iwlwifi/mvm/scan.c | 4 ++--
drivers/net/wireless/iwlwifi/mvm/tx.c | 2 +-
drivers/net/wireless/iwlwifi/mvm/utils.c | 2 +-
10 files changed, 22 insertions(+), 32 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index 7367107..af6b452 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -296,14 +296,4 @@ struct iwl_fw {
struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
};
-static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw)
-{
- return fw->valid_tx_ant;
-}
-
-static inline u8 iwl_fw_valid_rx_ant(const struct iwl_fw *fw)
-{
- return fw->valid_rx_ant;
-}
-
#endif /* __iwl_fw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 9b98337..3278b48 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -591,7 +591,7 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
return -EINVAL;
if (scan_rx_ant > ANT_ABC)
return -EINVAL;
- if (scan_rx_ant & ~iwl_fw_valid_rx_ant(mvm->fw))
+ if (scan_rx_ant & ~mvm->fw->valid_rx_ant)
return -EINVAL;
mvm->scan_rx_ant = scan_rx_ant;
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index bae75b3..4f398e6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -320,7 +320,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
}
/* Send TX valid antennas before triggering calibrations */
- ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
+ ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
if (ret)
goto error;
@@ -422,7 +422,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret)
IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
- ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
+ ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
if (ret)
goto error;
@@ -507,7 +507,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
goto error;
}
- ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
+ ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
if (ret)
goto error;
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 5c21aab..9ccec10 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -952,7 +952,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
TX_CMD_FLG_TSF);
mvm->mgmt_last_antenna_idx =
- iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
+ iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant,
mvm->mgmt_last_antenna_idx);
beacon_cmd.tx.rate_n_flags =
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index e80e81a..cf2d09f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -259,8 +259,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib,
regulatory, mac_override,
- iwl_fw_valid_tx_ant(mvm->fw),
- iwl_fw_valid_rx_ant(mvm->fw));
+ mvm->fw->valid_tx_ant,
+ mvm->fw->valid_rx_ant);
}
#define MAX_NVM_FILE_LEN 16384
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
index b7268c0..237efe0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
@@ -156,13 +156,13 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
idle_cnt = chains_static;
active_cnt = chains_dynamic;
- cmd->rxchain_info = cpu_to_le32(iwl_fw_valid_rx_ant(mvm->fw) <<
+ cmd->rxchain_info = cpu_to_le32(mvm->fw->valid_rx_ant <<
PHY_RX_CHAIN_VALID_POS);
cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
cmd->rxchain_info |= cpu_to_le32(active_cnt <<
PHY_RX_CHAIN_MIMO_CNT_POS);
- cmd->txchain_info = cpu_to_le32(iwl_fw_valid_tx_ant(mvm->fw));
+ cmd->txchain_info = cpu_to_le32(mvm->fw->valid_tx_ant);
}
/*
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index a6d0ab1..77c6e36 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -166,7 +166,7 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (sta->smps_mode == IEEE80211_SMPS_STATIC)
return false;
- if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 2)
+ if (num_of_ant(mvm->fw->valid_tx_ant) < 2)
return false;
if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta))
@@ -917,7 +917,7 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
if (num_of_ant(rate->ant) > 1)
- rate->ant = first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
+ rate->ant = first_antenna(mvm->fw->valid_tx_ant);
/* Relevant in both switching to SISO or Legacy */
rate->sgi = false;
@@ -1477,7 +1477,7 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column];
const struct rs_tx_column *next_col;
allow_column_func_t allow_func;
- u8 valid_ants = iwl_fw_valid_tx_ant(mvm->fw);
+ u8 valid_ants = mvm->fw->valid_tx_ant;
const u16 *expected_tpt_tbl;
s32 tpt, max_expected_tpt;
@@ -2089,7 +2089,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
i = lq_sta->last_txrate_idx;
- valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
+ valid_tx_ant = mvm->fw->valid_tx_ant;
if (!lq_sta->search_better_tbl)
active_tbl = lq_sta->active_tbl;
@@ -2319,7 +2319,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
/* These values will be overridden later */
lq_sta->lq.single_stream_ant_msk =
- first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
+ first_antenna(mvm->fw->valid_tx_ant);
lq_sta->lq.dual_stream_ant_msk = ANT_AB;
/* as default allow aggregation for all tids */
@@ -2445,7 +2445,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
memcpy(&rate, initial_rate, sizeof(rate));
- valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
+ valid_tx_ant = mvm->fw->valid_tx_ant;
if (is_siso(&rate)) {
num_rates = RS_INITIAL_SISO_NUM_RATES;
@@ -2676,9 +2676,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
desc += sprintf(buff+desc, "fixed rate 0x%X\n",
lq_sta->dbg_fixed_rate);
desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
- (iwl_fw_valid_tx_ant(mvm->fw) & ANT_A) ? "ANT_A," : "",
- (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "",
- (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : "");
+ (mvm->fw->valid_tx_ant & ANT_A) ? "ANT_A," : "",
+ (mvm->fw->valid_tx_ant & ANT_B) ? "ANT_B," : "",
+ (mvm->fw->valid_tx_ant & ANT_C) ? "ANT_C" : "");
desc += sprintf(buff+desc, "lq type %s\n",
(is_legacy(rate)) ? "legacy" :
is_vht(rate) ? "VHT" : "HT");
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index bf4e773..cea935b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -82,7 +82,7 @@ static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
if (mvm->scan_rx_ant != ANT_NONE)
rx_ant = mvm->scan_rx_ant;
else
- rx_ant = iwl_fw_valid_rx_ant(mvm->fw);
+ rx_ant = mvm->fw->valid_rx_ant;
rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS;
@@ -124,7 +124,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band,
u32 tx_ant;
mvm->scan_last_antenna_idx =
- iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
+ iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant,
mvm->scan_last_antenna_idx);
tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 852d9d8..b83ef6a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -207,7 +207,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx);
mvm->mgmt_last_antenna_idx =
- iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
+ iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant,
mvm->mgmt_last_antenna_idx);
rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index 2021b57..c81a7fb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -587,7 +587,7 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
lockdep_assert_held(&mvm->mutex);
/* SMPS is irrelevant for NICs that don't have at least 2 RX antenna */
- if (num_of_ant(iwl_fw_valid_rx_ant(mvm->fw)) == 1)
+ if (num_of_ant(mvm->fw->valid_rx_ant) == 1)
return;
if (vif->type == NL80211_IFTYPE_AP)
--
1.7.9.5
From: Eliad Peller <[email protected]>
The various code blocks in iwl_pcie_[rt]xq_inc_wr_ptr
finally do the same things, so just merge them
all and make the functions cleaner.
Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/pcie/rx.c | 47 +++++++++---------------
drivers/net/wireless/iwlwifi/pcie/tx.c | 63 +++++++++++++++-----------------
2 files changed, 47 insertions(+), 63 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 41f684d..cf49f6c 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -155,37 +155,26 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
if (rxq->need_update == 0)
goto exit_unlock;
- if (trans->cfg->base_params->shadow_reg_enable) {
- /* shadow register enabled */
- /* Device expects a multiple of 8 */
- rxq->write_actual = (rxq->write & ~0x7);
- iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual);
- } else {
- /* If power-saving is in use, make sure device is awake */
- if (test_bit(STATUS_TPOWER_PMI, &trans->status)) {
- reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
-
- if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
- IWL_DEBUG_INFO(trans,
- "Rx queue requesting wakeup,"
- " GP1 = 0x%x\n", reg);
- iwl_set_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- goto exit_unlock;
- }
-
- rxq->write_actual = (rxq->write & ~0x7);
- iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR,
- rxq->write_actual);
-
- /* Else device is assumed to be awake */
- } else {
- /* Device expects a multiple of 8 */
- rxq->write_actual = (rxq->write & ~0x7);
- iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR,
- rxq->write_actual);
+ /*
+ * explicitly wake up the NIC if:
+ * 1. shadow registers aren't enabled
+ * 2. there is a chance that the NIC is asleep
+ */
+ if (!trans->cfg->base_params->shadow_reg_enable &&
+ test_bit(STATUS_TPOWER_PMI, &trans->status)) {
+ reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
+
+ if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+ IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup, GP1 = 0x%x\n",
+ reg);
+ iwl_set_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ goto exit_unlock;
}
}
+
+ rxq->write_actual = round_down(rxq->write, 8);
+ iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual);
rxq->need_update = 0;
exit_unlock:
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 2541264..e476d9e 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -296,43 +296,38 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq)
if (txq->need_update == 0)
return;
- if (trans->cfg->base_params->shadow_reg_enable ||
- txq_id == trans_pcie->cmd_queue) {
- /* shadow register enabled */
- iwl_write32(trans, HBUS_TARG_WRPTR,
- txq->q.write_ptr | (txq_id << 8));
- } else {
- /* if we're trying to save power */
- if (test_bit(STATUS_TPOWER_PMI, &trans->status)) {
- /* wake up nic if it's powered down ...
- * uCode will wake up, and interrupt us again, so next
- * time we'll skip this part. */
- reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
-
- if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
- IWL_DEBUG_INFO(trans,
- "Tx queue %d requesting wakeup,"
- " GP1 = 0x%x\n", txq_id, reg);
- iwl_set_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- return;
- }
-
- IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id,
- txq->q.write_ptr);
-
- iwl_write_direct32(trans, HBUS_TARG_WRPTR,
- txq->q.write_ptr | (txq_id << 8));
-
+ /*
+ * explicitly wake up the NIC if:
+ * 1. shadow registers aren't enabled
+ * 2. NIC is woken up for CMD regardless of shadow outside this function
+ * 3. there is a chance that the NIC is asleep
+ */
+ if (!trans->cfg->base_params->shadow_reg_enable &&
+ txq_id != trans_pcie->cmd_queue &&
+ test_bit(STATUS_TPOWER_PMI, &trans->status)) {
/*
- * else not in power-save mode,
- * uCode will never sleep when we're
- * trying to tx (during RFKILL, we're not trying to tx).
+ * wake up nic if it's powered down ...
+ * uCode will wake up, and interrupt us again, so next
+ * time we'll skip this part.
*/
- } else
- iwl_write32(trans, HBUS_TARG_WRPTR,
- txq->q.write_ptr | (txq_id << 8));
+ reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
+
+ if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+ IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup, GP1 = 0x%x\n",
+ txq_id, reg);
+ iwl_set_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ return;
+ }
}
+
+ /*
+ * if not in power-save mode, uCode will never sleep when we're
+ * trying to tx (during RFKILL, we're not trying to tx).
+ */
+ IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, txq->q.write_ptr);
+ iwl_write32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8));
+
txq->need_update = 0;
}
--
1.7.9.5
From: Eyal Shapira <[email protected]>
Collect statistics regarding rates and aggregations in Rx
frames and export the data via debugfs.
Signed-off-by: Eyal Shapira <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/mvm/debugfs.c | 72 +++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/mvm/mvm.h | 29 +++++++++++
drivers/net/wireless/iwlwifi/mvm/rs.c | 73 +++++++++++++++++++++++++++-
drivers/net/wireless/iwlwifi/mvm/rx.c | 13 +++++
4 files changed, 185 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 3278b48..e0ff43e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -531,6 +531,76 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
}
#undef PRINT_STAT_LE32
+static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
+ char __user *user_buf, size_t count,
+ loff_t *ppos,
+ struct iwl_mvm_frame_stats *stats)
+{
+ char *buff;
+ int pos = 0, idx, i;
+ int ret;
+ size_t bufsz = 1024;
+
+ buff = kmalloc(bufsz, GFP_KERNEL);
+ if (!buff)
+ return -ENOMEM;
+
+ spin_lock_bh(&mvm->drv_stats_lock);
+ pos += scnprintf(buff + pos, bufsz - pos,
+ "Legacy/HT/VHT\t:\t%d/%d/%d\n",
+ stats->legacy_frames,
+ stats->ht_frames,
+ stats->vht_frames);
+ pos += scnprintf(buff + pos, bufsz - pos, "20/40/80\t:\t%d/%d/%d\n",
+ stats->bw_20_frames,
+ stats->bw_40_frames,
+ stats->bw_80_frames);
+ pos += scnprintf(buff + pos, bufsz - pos, "NGI/SGI\t\t:\t%d/%d\n",
+ stats->ngi_frames,
+ stats->sgi_frames);
+ pos += scnprintf(buff + pos, bufsz - pos, "SISO/MIMO2\t:\t%d/%d\n",
+ stats->siso_frames,
+ stats->mimo2_frames);
+ pos += scnprintf(buff + pos, bufsz - pos, "FAIL/SCSS\t:\t%d/%d\n",
+ stats->fail_frames,
+ stats->success_frames);
+ pos += scnprintf(buff + pos, bufsz - pos, "MPDUs agg\t:\t%d\n",
+ stats->agg_frames);
+ pos += scnprintf(buff + pos, bufsz - pos, "A-MPDUs\t\t:\t%d\n",
+ stats->ampdu_count);
+ pos += scnprintf(buff + pos, bufsz - pos, "Avg MPDUs/A-MPDU:\t%d\n",
+ stats->ampdu_count > 0 ?
+ (stats->agg_frames / stats->ampdu_count) : 0);
+
+ pos += scnprintf(buff + pos, bufsz - pos, "Last Rates\n");
+
+ idx = stats->last_frame_idx - 1;
+ for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) {
+ idx = (idx + 1) % ARRAY_SIZE(stats->last_rates);
+ if (stats->last_rates[idx] == 0)
+ continue;
+ pos += scnprintf(buff + pos, bufsz - pos, "Rate[%d]: ",
+ (int)(ARRAY_SIZE(stats->last_rates) - i));
+ pos += rs_pretty_print_rate(buff + pos, stats->last_rates[idx]);
+ }
+ spin_unlock_bh(&mvm->drv_stats_lock);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos);
+ kfree(buff);
+
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ struct iwl_mvm *mvm = file->private_data;
+
+ return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos,
+ &mvm->drv_rx_stats);
+}
+
static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
@@ -959,6 +1029,7 @@ MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
+MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
@@ -990,6 +1061,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
S_IRUSR | S_IWUSR);
MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR);
+ MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 823765e..5fb5109 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -425,6 +425,28 @@ struct iwl_mvm_tt_mgmt {
bool throttle;
};
+#define IWL_MVM_NUM_LAST_FRAMES_UCODE_RATES 8
+
+struct iwl_mvm_frame_stats {
+ u32 legacy_frames;
+ u32 ht_frames;
+ u32 vht_frames;
+ u32 bw_20_frames;
+ u32 bw_40_frames;
+ u32 bw_80_frames;
+ u32 bw_160_frames;
+ u32 sgi_frames;
+ u32 ngi_frames;
+ u32 siso_frames;
+ u32 mimo2_frames;
+ u32 agg_frames;
+ u32 ampdu_count;
+ u32 success_frames;
+ u32 fail_frames;
+ u32 last_rates[IWL_MVM_NUM_LAST_FRAMES_UCODE_RATES];
+ int last_frame_idx;
+};
+
struct iwl_mvm {
/* for logger access */
struct device *dev;
@@ -526,6 +548,9 @@ struct iwl_mvm {
struct debugfs_blob_wrapper nvm_sw_blob;
struct debugfs_blob_wrapper nvm_calib_blob;
struct debugfs_blob_wrapper nvm_prod_blob;
+
+ struct iwl_mvm_frame_stats drv_rx_stats;
+ spinlock_t drv_stats_lock;
#endif
struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX];
@@ -810,6 +835,10 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
/* rate scaling */
int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init);
+void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm,
+ struct iwl_mvm_frame_stats *stats,
+ u32 rate, bool agg);
+int rs_pretty_print_rate(char *buf, const u32 rate);
/* power management */
int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm);
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 77c6e36..399709f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -2240,6 +2240,73 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
}
}
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+static void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm,
+ struct iwl_mvm_frame_stats *stats)
+{
+ spin_lock_bh(&mvm->drv_stats_lock);
+ memset(stats, 0, sizeof(*stats));
+ spin_unlock_bh(&mvm->drv_stats_lock);
+}
+
+void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm,
+ struct iwl_mvm_frame_stats *stats,
+ u32 rate, bool agg)
+{
+ u8 nss = 0, mcs = 0;
+
+ spin_lock(&mvm->drv_stats_lock);
+
+ if (agg)
+ stats->agg_frames++;
+
+ stats->success_frames++;
+
+ switch (rate & RATE_MCS_CHAN_WIDTH_MSK) {
+ case RATE_MCS_CHAN_WIDTH_20:
+ stats->bw_20_frames++;
+ break;
+ case RATE_MCS_CHAN_WIDTH_40:
+ stats->bw_40_frames++;
+ break;
+ case RATE_MCS_CHAN_WIDTH_80:
+ stats->bw_80_frames++;
+ break;
+ default:
+ WARN_ONCE(1, "bad BW. rate 0x%x", rate);
+ }
+
+ if (rate & RATE_MCS_HT_MSK) {
+ stats->ht_frames++;
+ mcs = rate & RATE_HT_MCS_RATE_CODE_MSK;
+ nss = ((rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1;
+ } else if (rate & RATE_MCS_VHT_MSK) {
+ stats->vht_frames++;
+ mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;
+ nss = ((rate & RATE_VHT_MCS_NSS_MSK) >>
+ RATE_VHT_MCS_NSS_POS) + 1;
+ } else {
+ stats->legacy_frames++;
+ }
+
+ if (nss == 1)
+ stats->siso_frames++;
+ else if (nss == 2)
+ stats->mimo2_frames++;
+
+ if (rate & RATE_MCS_SGI_MSK)
+ stats->sgi_frames++;
+ else
+ stats->ngi_frames++;
+
+ stats->last_rates[stats->last_frame_idx] = rate;
+ stats->last_frame_idx = (stats->last_frame_idx + 1) %
+ ARRAY_SIZE(stats->last_rates);
+
+ spin_unlock(&mvm->drv_stats_lock);
+}
+#endif
+
/*
* Called after adding a new station to initialize rate scaling
*/
@@ -2334,7 +2401,9 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
#ifdef CONFIG_MAC80211_DEBUGFS
lq_sta->dbg_fixed_rate = 0;
#endif
-
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ iwl_mvm_reset_frame_stats(mvm, &mvm->drv_rx_stats);
+#endif
rs_initialize_lq(mvm, sta, lq_sta, band, init);
}
@@ -2546,7 +2615,7 @@ static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta,
}
#ifdef CONFIG_MAC80211_DEBUGFS
-static int rs_pretty_print_rate(char *buf, const u32 rate)
+int rs_pretty_print_rate(char *buf, const u32 rate)
{
char *type, *bw;
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index 817d3e0..6061553 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -77,6 +77,15 @@ int iwl_mvm_rx_rx_phy_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
memcpy(&mvm->last_phy_info, pkt->data, sizeof(mvm->last_phy_info));
mvm->ampdu_ref++;
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ if (mvm->last_phy_info.phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_AGG)) {
+ spin_lock(&mvm->drv_stats_lock);
+ mvm->drv_rx_stats.ampdu_count++;
+ spin_unlock(&mvm->drv_stats_lock);
+ }
+#endif
+
return 0;
}
@@ -391,6 +400,10 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
rx_status.band);
}
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ iwl_mvm_update_frame_stats(mvm, &mvm->drv_rx_stats, rate_n_flags,
+ rx_status.flag & RX_FLAG_AMPDU_DETAILS);
+#endif
iwl_mvm_pass_packet_to_mac80211(mvm, hdr, len, ampdu_status,
rxb, &rx_status);
return 0;
--
1.7.9.5
From: Alexander Bondar <[email protected]>
New FW enables support for power save on BSS and P2P client MACs
simultaneously when they function on different channels (DCM).
Enable this case in the driver after examining new TLV flag -
IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM. Still power management is not
allowed on both MACs if they function on a same channel.
Remove another redundant TLV flag - IWL_UCODE_TLV_FLAGS_P2P_PS that
is not in use anymore. Remove bound_vif_cnt as redundant.
Signed-off-by: Alexander Bondar <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-fw.h | 6 +--
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 2 +-
drivers/net/wireless/iwlwifi/mvm/mac80211.c | 6 ---
drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 -
drivers/net/wireless/iwlwifi/mvm/power.c | 48 ++++++++++++++++++++----
5 files changed, 44 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index f80ba58..b0d0998 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -92,8 +92,8 @@
* @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API
* @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command
* containing CAM (Continuous Active Mode) indication.
- * @IWL_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a
- * single bound interface).
+ * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and
+ * P2P client interfaces simultaneously if they are in different bindings.
* @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
* @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
* @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
@@ -118,7 +118,7 @@ enum iwl_ucode_tlv_flag {
IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17),
IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19),
IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20),
- IWL_UCODE_TLV_FLAGS_P2P_PS = BIT(21),
+ IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22),
IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24),
IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26),
IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29),
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
index 29b4396..f64e972 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
@@ -591,7 +591,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
(vif->type == NL80211_IFTYPE_STATION && vif->p2p &&
- mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS)))
+ mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)))
MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
S_IRUSR);
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 2a1b4b6..83da68c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -1305,7 +1305,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
mvmvif->ap_ibss_active = true;
/* power updated needs to be done before quotas */
- mvm->bound_vif_cnt++;
iwl_mvm_power_update_mac(mvm, vif);
ret = iwl_mvm_update_quotas(mvm, vif);
@@ -1324,7 +1323,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
return 0;
out_quota_failed:
- mvm->bound_vif_cnt--;
iwl_mvm_power_update_mac(mvm, vif);
mvmvif->ap_ibss_active = false;
iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
@@ -1361,7 +1359,6 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
iwl_mvm_binding_remove_vif(mvm, vif);
- mvm->bound_vif_cnt--;
iwl_mvm_power_update_mac(mvm, vif);
iwl_mvm_mac_ctxt_remove(mvm, vif);
@@ -2095,7 +2092,6 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
* Power state must be updated before quotas,
* otherwise fw will complain.
*/
- mvm->bound_vif_cnt++;
iwl_mvm_power_update_mac(mvm, vif);
/* Setting the quota at this stage is only required for monitor
@@ -2113,7 +2109,6 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
out_remove_binding:
iwl_mvm_binding_remove_vif(mvm, vif);
- mvm->bound_vif_cnt--;
iwl_mvm_power_update_mac(mvm, vif);
out_unlock:
mutex_unlock(&mvm->mutex);
@@ -2146,7 +2141,6 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
}
iwl_mvm_binding_remove_vif(mvm, vif);
- mvm->bound_vif_cnt--;
iwl_mvm_power_update_mac(mvm, vif);
out_unlock:
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 29d11d9..823765e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -587,8 +587,6 @@ struct iwl_mvm {
u8 first_agg_queue;
u8 last_agg_queue;
- u8 bound_vif_cnt;
-
/* Indicate if device power save is allowed */
bool ps_disabled;
/* Indicate if device power management is allowed */
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index 4da1ea4..def6ec5 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -425,7 +425,7 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
return 0;
if (vif->p2p &&
- !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS))
+ !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM))
return 0;
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
@@ -511,8 +511,11 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
struct iwl_power_constraint {
struct ieee80211_vif *bf_vif;
struct ieee80211_vif *bss_vif;
+ u16 bss_phyctx_id;
+ u16 p2p_phyctx_id;
bool pm_disabled;
bool ps_disabled;
+ struct iwl_mvm *mvm;
};
static void iwl_mvm_power_iterator(void *_data, u8 *mac,
@@ -520,6 +523,7 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_power_constraint *power_iterator = _data;
+ struct iwl_mvm *mvm = power_iterator->mvm;
switch (ieee80211_vif_type_p2p(vif)) {
case NL80211_IFTYPE_P2P_DEVICE:
@@ -539,11 +543,28 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
break;
case NL80211_IFTYPE_P2P_CLIENT:
- /* no BSS power mgmt if we have a P2P client*/
- power_iterator->pm_disabled = true;
+ if (mvmvif->phy_ctxt)
+ power_iterator->p2p_phyctx_id = mvmvif->phy_ctxt->id;
+
+ IWL_DEBUG_POWER(mvm, "p2p: p2p_id=%d, bss_id=%d\n",
+ power_iterator->p2p_phyctx_id,
+ power_iterator->bss_phyctx_id);
+ if (!(mvm->fw->ucode_capa.flags &
+ IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) {
+ /* no BSS power mgmt if we have a P2P client*/
+ power_iterator->pm_disabled = true;
+ } else if (power_iterator->p2p_phyctx_id < MAX_PHYS &&
+ power_iterator->bss_phyctx_id < MAX_PHYS &&
+ power_iterator->p2p_phyctx_id ==
+ power_iterator->bss_phyctx_id) {
+ power_iterator->pm_disabled = true;
+ }
break;
case NL80211_IFTYPE_STATION:
+ if (mvmvif->phy_ctxt)
+ power_iterator->bss_phyctx_id = mvmvif->phy_ctxt->id;
+
/* we should have only one BSS vif */
WARN_ON(power_iterator->bss_vif);
power_iterator->bss_vif = vif;
@@ -551,6 +572,17 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
if (mvmvif->bf_data.bf_enabled &&
!WARN_ON(power_iterator->bf_vif))
power_iterator->bf_vif = vif;
+
+ IWL_DEBUG_POWER(mvm, "bss: p2p_id=%d, bss_id=%d\n",
+ power_iterator->p2p_phyctx_id,
+ power_iterator->bss_phyctx_id);
+ if (mvm->fw->ucode_capa.flags &
+ IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM &&
+ (power_iterator->p2p_phyctx_id < MAX_PHYS &&
+ power_iterator->bss_phyctx_id < MAX_PHYS &&
+ power_iterator->p2p_phyctx_id ==
+ power_iterator->bss_phyctx_id))
+ power_iterator->pm_disabled = true;
break;
default:
@@ -572,16 +604,16 @@ iwl_mvm_power_get_global_constraint(struct iwl_mvm *mvm,
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_power_iterator, constraint);
-
- /* TODO: remove this and determine this variable in the iterator */
- if (mvm->bound_vif_cnt > 1)
- constraint->pm_disabled = true;
}
int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_power_constraint constraint = {};
+ struct iwl_power_constraint constraint = {
+ .p2p_phyctx_id = MAX_PHYS,
+ .bss_phyctx_id = MAX_PHYS,
+ .mvm = mvm,
+ };
bool ba_enable;
int ret;
--
1.7.9.5
From: Emmanuel Grumbach <[email protected]>
In case the firmware didn't assert but we want to restart
it, e.g. we didn't get the reply for a host command, or the
Tx queues are stuck, we should stop the firmware by
provoking an interrupt. This allows to better debug the
firmware in these bad scenarios.
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/pcie/tx.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index e476d9e..3b0c72c 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
le32_to_cpu(txq->scratchbufs[i].scratch));
- iwl_trans_fw_error(trans);
+ iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);
}
/*
@@ -1024,7 +1024,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
if (nfreed++ > 0) {
IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
idx, q->write_ptr, q->read_ptr);
- iwl_trans_fw_error(trans);
+ iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);
}
}
@@ -1583,6 +1583,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
get_cmd_string(trans_pcie, cmd->id));
ret = -ETIMEDOUT;
+ iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);
iwl_trans_fw_error(trans);
goto cancel;
--
1.7.9.5
On Sun, 2014-02-23 at 21:57 +0200, Emmanuel Grumbach wrote:
> From: Eyal Shapira <[email protected]>
>
> Collect statistics regarding rates and aggregations in Rx
> frames and export the data via debugfs.
[]
> diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
[]
> +static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
> + char __user *user_buf, size_t count,
> + loff_t *ppos,
> + struct iwl_mvm_frame_stats *stats)
> +{
> + char *buff;
> + int pos = 0, idx, i;
I think this would be shorter code using pos as a char *
> + int ret;
> + size_t bufsz = 1024;
I'd prefer #define or static const though the compiler
should do the same thing.
> + buff = kmalloc(bufsz, GFP_KERNEL);
> + if (!buff)
> + return -ENOMEM;
> +
> + spin_lock_bh(&mvm->drv_stats_lock);
pos = buff;
endpos = pos + bufsz;
> + pos += scnprintf(buff + pos, bufsz - pos,
> + "Legacy/HT/VHT\t:\t%d/%d/%d\n",
> + stats->legacy_frames,
> + stats->ht_frames,
> + stats->vht_frames);
pos += scnprintf(pos, endpos - pos, etc...
etc...
From: Eran Harary <[email protected]>
Support the changes below:
- Fields and sections structure were changed.
- the NVM file built from DWord instead of Words.
- sections header format was changed.
Signed-off-by: Eran Harary <[email protected]>
Reviewed-by: Johannes Berg <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-drv.c | 6 +
drivers/net/wireless/iwlwifi/iwl-drv.h | 14 ++
drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | 5 +-
drivers/net/wireless/iwlwifi/iwl-fw.h | 8 +-
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 239 ++++++++++++++++++-----
drivers/net/wireless/iwlwifi/iwl-nvm-parse.h | 3 +-
drivers/net/wireless/iwlwifi/mvm/fw-api.h | 4 +-
drivers/net/wireless/iwlwifi/mvm/nvm.c | 63 ++++--
8 files changed, 271 insertions(+), 71 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index b3bc30b..662d993 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -728,6 +728,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
if (tlv_len != sizeof(u32))
goto invalid_tlv_len;
drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data);
+ drv->fw.valid_tx_ant = (drv->fw.phy_config &
+ FW_PHY_CFG_TX_CHAIN) >>
+ FW_PHY_CFG_TX_CHAIN_POS;
+ drv->fw.valid_rx_ant = (drv->fw.phy_config &
+ FW_PHY_CFG_RX_CHAIN) >>
+ FW_PHY_CFG_RX_CHAIN_POS;
break;
case IWL_UCODE_TLV_SECURE_SEC_RT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h
index 592c01e..3c72cb7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.h
@@ -70,6 +70,20 @@
#define DRV_COPYRIGHT "Copyright(c) 2003- 2014 Intel Corporation"
#define DRV_AUTHOR "<[email protected]>"
+/* radio config bits (actual values from NVM definition) */
+#define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */
+#define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
+#define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
+#define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
+#define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
+#define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
+
+#define NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(x) (x & 0xF)
+#define NVM_RF_CFG_DASH_MSK_FAMILY_8000(x) ((x >> 4) & 0xF)
+#define NVM_RF_CFG_STEP_MSK_FAMILY_8000(x) ((x >> 8) & 0xF)
+#define NVM_RF_CFG_TYPE_MSK_FAMILY_8000(x) ((x >> 12) & 0xFFF)
+#define NVM_RF_CFG_TX_ANT_MSK_FAMILY_8000(x) ((x >> 24) & 0xF)
+#define NVM_RF_CFG_RX_ANT_MSK_FAMILY_8000(x) ((x >> 28) & 0xF)
/**
* DOC: Driver system flows - drv component
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
index e3c7dea..f0548b8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
@@ -81,16 +81,17 @@ struct iwl_nvm_data {
bool sku_cap_band_24GHz_enable;
bool sku_cap_band_52GHz_enable;
bool sku_cap_11n_enable;
+ bool sku_cap_11ac_enable;
bool sku_cap_amt_enable;
bool sku_cap_ipan_enable;
- u8 radio_cfg_type;
+ u16 radio_cfg_type;
u8 radio_cfg_step;
u8 radio_cfg_dash;
u8 radio_cfg_pnum;
u8 valid_tx_ant, valid_rx_ant;
- u16 nvm_version;
+ u32 nvm_version;
s8 max_tx_pwr_half_dbm;
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index b0d0998..7367107 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -288,6 +288,8 @@ struct iwl_fw {
struct iwl_tlv_calib_ctrl default_calib[IWL_UCODE_TYPE_MAX];
u32 phy_config;
+ u8 valid_tx_ant;
+ u8 valid_rx_ant;
bool mvm_fw;
@@ -296,14 +298,12 @@ struct iwl_fw {
static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw)
{
- return (fw->phy_config & FW_PHY_CFG_TX_CHAIN) >>
- FW_PHY_CFG_TX_CHAIN_POS;
+ return fw->valid_tx_ant;
}
static inline u8 iwl_fw_valid_rx_ant(const struct iwl_fw *fw)
{
- return (fw->phy_config & FW_PHY_CFG_RX_CHAIN) >>
- FW_PHY_CFG_RX_CHAIN_POS;
+ return fw->valid_rx_ant;
}
#endif /* __iwl_fw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index 4278097..df3ea60 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -71,7 +71,7 @@ enum wkp_nvm_offsets {
/* NVM HW-Section offset (in words) definitions */
HW_ADDR = 0x15,
-/* NVM SW-Section offset (in words) definitions */
+ /* NVM SW-Section offset (in words) definitions */
NVM_SW_SECTION = 0x1C0,
NVM_VERSION = 0,
RADIO_CFG = 1,
@@ -79,11 +79,32 @@ enum wkp_nvm_offsets {
N_HW_ADDRS = 3,
NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION,
-/* NVM calibration section offset (in words) definitions */
+ /* NVM calibration section offset (in words) definitions */
NVM_CALIB_SECTION = 0x2B8,
XTAL_CALIB = 0x316 - NVM_CALIB_SECTION
};
+enum family_8000_nvm_offsets {
+ /* NVM HW-Section offset (in words) definitions */
+ HW_ADDR0_FAMILY_8000 = 0x12,
+ HW_ADDR1_FAMILY_8000 = 0x16,
+ MAC_ADDRESS_OVERRIDE_FAMILY_8000 = 1,
+
+ /* NVM SW-Section offset (in words) definitions */
+ NVM_SW_SECTION_FAMILY_8000 = 0x1C0,
+ NVM_VERSION_FAMILY_8000 = 0,
+ RADIO_CFG_FAMILY_8000 = 2,
+ SKU_FAMILY_8000 = 4,
+ N_HW_ADDRS_FAMILY_8000 = 5,
+
+ /* NVM REGULATORY -Section offset (in words) definitions */
+ NVM_CHANNELS_FAMILY_8000 = 0,
+
+ /* NVM calibration section offset (in words) definitions */
+ NVM_CALIB_SECTION_FAMILY_8000 = 0x2B8,
+ XTAL_CALIB_FAMILY_8000 = 0x316 - NVM_CALIB_SECTION_FAMILY_8000
+};
+
/* SKU Capabilities (actual values from NVM definition) */
enum nvm_sku_bits {
NVM_SKU_CAP_BAND_24GHZ = BIT(0),
@@ -92,14 +113,6 @@ enum nvm_sku_bits {
NVM_SKU_CAP_11AC_ENABLE = BIT(3),
};
-/* radio config bits (actual values from NVM definition) */
-#define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */
-#define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */
-#define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */
-#define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */
-#define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */
-#define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
-
/*
* These are the channel numbers in the order that they are stored in the NVM
*/
@@ -112,7 +125,17 @@ static const u8 iwl_nvm_channels[] = {
149, 153, 157, 161, 165
};
+static const u8 iwl_nvm_channels_family_8000[] = {
+ /* 2.4 GHz */
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ /* 5 GHz */
+ 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
+ 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
+ 149, 153, 157, 161, 165, 169, 173, 177, 181
+};
+
#define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
+#define IWL_NUM_CHANNELS_FAMILY_8000 ARRAY_SIZE(iwl_nvm_channels_family_8000)
#define NUM_2GHZ_CHANNELS 14
#define FIRST_2GHZ_HT_MINUS 5
#define LAST_2GHZ_HT_PLUS 9
@@ -179,13 +202,23 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
struct ieee80211_channel *channel;
u16 ch_flags;
bool is_5ghz;
+ int num_of_ch;
+ const u8 *nvm_chan;
+
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ num_of_ch = IWL_NUM_CHANNELS;
+ nvm_chan = &iwl_nvm_channels[0];
+ } else {
+ num_of_ch = IWL_NUM_CHANNELS_FAMILY_8000;
+ nvm_chan = &iwl_nvm_channels_family_8000[0];
+ }
- for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) {
+ for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
if (!(ch_flags & NVM_CHANNEL_VALID)) {
IWL_DEBUG_EEPROM(dev,
"Ch. %d Flags %x [%sGHz] - No traffic\n",
- iwl_nvm_channels[ch_idx],
+ nvm_chan[ch_idx],
ch_flags,
(ch_idx >= NUM_2GHZ_CHANNELS) ?
"5.2" : "2.4");
@@ -195,7 +228,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
channel = &data->channels[n_channels];
n_channels++;
- channel->hw_value = iwl_nvm_channels[ch_idx];
+ channel->hw_value = nvm_chan[ch_idx];
channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ?
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
channel->center_freq =
@@ -206,11 +239,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
channel->flags = IEEE80211_CHAN_NO_HT40;
if (ch_idx < NUM_2GHZ_CHANNELS &&
(ch_flags & NVM_CHANNEL_40MHZ)) {
- if (iwl_nvm_channels[ch_idx] <= LAST_2GHZ_HT_PLUS)
+ if (nvm_chan[ch_idx] <= LAST_2GHZ_HT_PLUS)
channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
- if (iwl_nvm_channels[ch_idx] >= FIRST_2GHZ_HT_MINUS)
+ if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS)
channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
- } else if (iwl_nvm_channels[ch_idx] <= LAST_5GHZ_HT &&
+ } else if (nvm_chan[ch_idx] <= LAST_5GHZ_HT &&
(ch_flags & NVM_CHANNEL_40MHZ)) {
if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
@@ -302,14 +335,23 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
}
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
- struct iwl_nvm_data *data, const __le16 *nvm_sw,
- bool enable_vht, u8 tx_chains, u8 rx_chains)
+ struct iwl_nvm_data *data,
+ const __le16 *ch_section, bool enable_vht,
+ u8 tx_chains, u8 rx_chains)
{
- int n_channels = iwl_init_channel_map(dev, cfg, data,
- &nvm_sw[NVM_CHANNELS]);
+ int n_channels;
int n_used = 0;
struct ieee80211_supported_band *sband;
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ n_channels = iwl_init_channel_map(
+ dev, cfg, data,
+ &ch_section[NVM_CHANNELS]);
+ else
+ n_channels = iwl_init_channel_map(
+ dev, cfg, data,
+ &ch_section[NVM_CHANNELS_FAMILY_8000]);
+
sband = &data->bands[IEEE80211_BAND_2GHZ];
sband->band = IEEE80211_BAND_2GHZ;
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
@@ -335,35 +377,122 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
n_used, n_channels);
}
+static int iwl_get_sku(const struct iwl_cfg *cfg,
+ const __le16 *nvm_sw)
+{
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ return le16_to_cpup(nvm_sw + SKU);
+ else
+ return le32_to_cpup((__le32 *)(nvm_sw + SKU_FAMILY_8000));
+}
+
+static int iwl_get_nvm_version(const struct iwl_cfg *cfg,
+ const __le16 *nvm_sw)
+{
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ return le16_to_cpup(nvm_sw + NVM_VERSION);
+ else
+ return le32_to_cpup((__le32 *)(nvm_sw +
+ NVM_VERSION_FAMILY_8000));
+}
+
+static int iwl_get_radio_cfg(const struct iwl_cfg *cfg,
+ const __le16 *nvm_sw)
+{
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ return le16_to_cpup(nvm_sw + RADIO_CFG);
+ else
+ return le32_to_cpup((__le32 *)(nvm_sw + RADIO_CFG_FAMILY_8000));
+}
+
+#define N_HW_ADDRS_MASK_FAMILY_8000 0xF
+static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg,
+ const __le16 *nvm_sw)
+{
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ return le16_to_cpup(nvm_sw + N_HW_ADDRS);
+ else
+ return le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000))
+ & N_HW_ADDRS_MASK_FAMILY_8000;
+}
+
+static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
+ struct iwl_nvm_data *data,
+ u32 radio_cfg)
+{
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
+ data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
+ data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
+ data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg);
+ data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
+ data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
+ return;
+ }
+
+ /* set the radio configuration for family 8000 */
+ data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK_FAMILY_8000(radio_cfg);
+ data->radio_cfg_step = NVM_RF_CFG_STEP_MSK_FAMILY_8000(radio_cfg);
+ data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK_FAMILY_8000(radio_cfg);
+ data->radio_cfg_pnum = NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(radio_cfg);
+ data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK_FAMILY_8000(radio_cfg);
+ data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK_FAMILY_8000(radio_cfg);
+}
+
+static void iwl_set_hw_address(const struct iwl_cfg *cfg,
+ struct iwl_nvm_data *data,
+ const __le16 *nvm_sec)
+{
+ u8 hw_addr[ETH_ALEN];
+
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ memcpy(hw_addr, nvm_sec + HW_ADDR, ETH_ALEN);
+ else
+ memcpy(hw_addr, nvm_sec + MAC_ADDRESS_OVERRIDE_FAMILY_8000,
+ ETH_ALEN);
+
+ /* The byte order is little endian 16 bit, meaning 214365 */
+ data->hw_addr[0] = hw_addr[1];
+ data->hw_addr[1] = hw_addr[0];
+ data->hw_addr[2] = hw_addr[3];
+ data->hw_addr[3] = hw_addr[2];
+ data->hw_addr[4] = hw_addr[5];
+ data->hw_addr[5] = hw_addr[4];
+}
+
struct iwl_nvm_data *
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
const __le16 *nvm_hw, const __le16 *nvm_sw,
- const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains)
+ const __le16 *nvm_calib, const __le16 *regulatory,
+ const __le16 *mac_override, u8 tx_chains, u8 rx_chains)
{
struct iwl_nvm_data *data;
- u8 hw_addr[ETH_ALEN];
- u16 radio_cfg, sku;
-
- data = kzalloc(sizeof(*data) +
- sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS,
- GFP_KERNEL);
+ u32 sku;
+ u32 radio_cfg;
+
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ data = kzalloc(sizeof(*data) +
+ sizeof(struct ieee80211_channel) *
+ IWL_NUM_CHANNELS,
+ GFP_KERNEL);
+ else
+ data = kzalloc(sizeof(*data) +
+ sizeof(struct ieee80211_channel) *
+ IWL_NUM_CHANNELS_FAMILY_8000,
+ GFP_KERNEL);
if (!data)
return NULL;
- data->nvm_version = le16_to_cpup(nvm_sw + NVM_VERSION);
+ data->nvm_version = iwl_get_nvm_version(cfg, nvm_sw);
- radio_cfg = le16_to_cpup(nvm_sw + RADIO_CFG);
- data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
- data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
- data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
- data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg);
- data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
- data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
+ radio_cfg = iwl_get_radio_cfg(cfg, nvm_sw);
+ iwl_set_radio_cfg(cfg, data, radio_cfg);
- sku = le16_to_cpup(nvm_sw + SKU);
+ sku = iwl_get_sku(cfg, nvm_sw);
data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ;
data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ;
data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE;
+ data->sku_cap_11ac_enable = sku & NVM_SKU_CAP_11AC_ENABLE;
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
data->sku_cap_11n_enable = false;
@@ -380,22 +509,34 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
return NULL;
}
- data->n_hw_addrs = le16_to_cpup(nvm_sw + N_HW_ADDRS);
+ data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
- data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
- data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ /* Checking for required sections */
+ if (!nvm_calib) {
+ IWL_ERR_DEV(dev,
+ "Can't parse empty Calib NVM sections\n");
+ return NULL;
+ }
+ /* in family 8000 Xtal calibration values moved to OTP */
+ data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
+ data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
+ }
- /* The byte order is little endian 16 bit, meaning 214365 */
- memcpy(hw_addr, nvm_hw + HW_ADDR, ETH_ALEN);
- data->hw_addr[0] = hw_addr[1];
- data->hw_addr[1] = hw_addr[0];
- data->hw_addr[2] = hw_addr[3];
- data->hw_addr[3] = hw_addr[2];
- data->hw_addr[4] = hw_addr[5];
- data->hw_addr[5] = hw_addr[4];
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ iwl_set_hw_address(cfg, data, nvm_hw);
+
+ iwl_init_sbands(dev, cfg, data, nvm_sw,
+ sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains,
+ rx_chains);
+ } else {
+ /* MAC address in family 8000 */
+ iwl_set_hw_address(cfg, data, mac_override);
- iwl_init_sbands(dev, cfg, data, nvm_sw, sku & NVM_SKU_CAP_11AC_ENABLE,
- tx_chains, rx_chains);
+ iwl_init_sbands(dev, cfg, data, regulatory,
+ sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains,
+ rx_chains);
+ }
data->calib_version = 255;
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
index 0c4399a..c9c45a3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h
@@ -75,6 +75,7 @@
struct iwl_nvm_data *
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
const __le16 *nvm_hw, const __le16 *nvm_sw,
- const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains);
+ const __le16 *nvm_calib, const __le16 *regulatory,
+ const __le16 *mac_override, u8 tx_chains, u8 rx_chains);
#endif /* __iwl_nvm_parse_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index a7c88f1..4d808a9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -306,7 +306,6 @@ struct iwl_phy_cfg_cmd {
#define PHY_CFG_RX_CHAIN_B BIT(13)
#define PHY_CFG_RX_CHAIN_C BIT(14)
-#define NVM_MAX_NUM_SECTIONS 11
/* Target of the NVM_ACCESS_CMD */
enum {
@@ -318,8 +317,11 @@ enum {
/* Section types for NVM_ACCESS_CMD */
enum {
NVM_SECTION_TYPE_SW = 1,
+ NVM_SECTION_TYPE_REGULATORY = 3,
NVM_SECTION_TYPE_CALIBRATION = 4,
NVM_SECTION_TYPE_PRODUCTION = 5,
+ NVM_SECTION_TYPE_MAC_OVERRIDE = 11,
+ NVM_MAX_NUM_SECTIONS = 12,
};
/**
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index 2d5251b..e80e81a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -228,13 +228,23 @@ static struct iwl_nvm_data *
iwl_parse_nvm_sections(struct iwl_mvm *mvm)
{
struct iwl_nvm_section *sections = mvm->nvm_sections;
- const __le16 *hw, *sw, *calib;
+ const __le16 *hw, *sw, *calib, *regulatory, *mac_override;
/* Checking for required sections */
- if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
- !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
- IWL_ERR(mvm, "Can't parse empty NVM sections\n");
- return NULL;
+ if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
+ !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
+ IWL_ERR(mvm, "Can't parse empty NVM sections\n");
+ return NULL;
+ }
+ } else {
+ if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
+ !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data ||
+ !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
+ IWL_ERR(mvm,
+ "Can't parse empty family 8000 NVM sections\n");
+ return NULL;
+ }
}
if (WARN_ON(!mvm->cfg))
@@ -243,7 +253,12 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data;
sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data;
calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data;
+ regulatory = (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data;
+ mac_override =
+ (const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data;
+
return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib,
+ regulatory, mac_override,
iwl_fw_valid_tx_ant(mvm->fw),
iwl_fw_valid_rx_ant(mvm->fw));
}
@@ -285,6 +300,8 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
#define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
#define NVM_WORD2_ID(x) (x >> 12)
+#define NVM_WORD2_LEN_FAMILY_8000(x) (2 * ((x & 0xFF) << 8 | x >> 8))
+#define NVM_WORD1_ID_FAMILY_8000(x) (x >> 4)
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
@@ -335,8 +352,16 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
break;
}
- section_size = 2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1));
- section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2));
+ if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ section_size =
+ 2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1));
+ section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2));
+ } else {
+ section_size = 2 * NVM_WORD2_LEN_FAMILY_8000(
+ le16_to_cpu(file_sec->word2));
+ section_id = NVM_WORD1_ID_FAMILY_8000(
+ le16_to_cpu(file_sec->word1));
+ }
if (section_size > IWL_MAX_NVM_SECTION_SIZE) {
IWL_ERR(mvm, "ERROR - section too large (%d)\n",
@@ -406,6 +431,8 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
{
int ret, i, section;
u8 *nvm_buffer, *temp;
+ int nvm_to_read[NVM_MAX_NUM_SECTIONS];
+ int num_of_sections_to_read;
if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
return -EINVAL;
@@ -418,12 +445,20 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
return ret;
} else {
/* list of NVM sections we are allowed/need to read */
- int nvm_to_read[] = {
- mvm->cfg->nvm_hw_section_num,
- NVM_SECTION_TYPE_SW,
- NVM_SECTION_TYPE_CALIBRATION,
- NVM_SECTION_TYPE_PRODUCTION,
- };
+ if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
+ nvm_to_read[0] = mvm->cfg->nvm_hw_section_num;
+ nvm_to_read[1] = NVM_SECTION_TYPE_SW;
+ nvm_to_read[2] = NVM_SECTION_TYPE_CALIBRATION;
+ nvm_to_read[3] = NVM_SECTION_TYPE_PRODUCTION;
+ num_of_sections_to_read = 4;
+ } else {
+ nvm_to_read[0] = NVM_SECTION_TYPE_SW;
+ nvm_to_read[1] = NVM_SECTION_TYPE_CALIBRATION;
+ nvm_to_read[2] = NVM_SECTION_TYPE_PRODUCTION;
+ nvm_to_read[3] = NVM_SECTION_TYPE_REGULATORY;
+ nvm_to_read[4] = NVM_SECTION_TYPE_MAC_OVERRIDE;
+ num_of_sections_to_read = 5;
+ }
/* Read From FW NVM */
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
@@ -433,7 +468,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
GFP_KERNEL);
if (!nvm_buffer)
return -ENOMEM;
- for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
+ for (i = 0; i < num_of_sections_to_read; i++) {
section = nvm_to_read[i];
/* we override the constness for initial read */
ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
--
1.7.9.5
From: Inbal Hacohen <[email protected]>
This define is a leftover from dvm (in mvm, it
was replaced by MVM_UCODE_ALIVE_TIMEOUT).
Signed-off-by: Inbal Hacohen <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/mvm/fw.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 93e1b4d..7ce2006 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -369,8 +369,6 @@ out:
return ret;
}
-#define UCODE_CALIB_TIMEOUT (2*HZ)
-
int iwl_mvm_up(struct iwl_mvm *mvm)
{
int ret, i;
--
1.7.9.5
Hi Joe,
> >
> > Collect statistics regarding rates and aggregations in Rx frames and
> > export the data via debugfs.
> []
> > diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
> > b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
> []
> > +static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
> > + char __user *user_buf, size_t count,
> > + loff_t *ppos,
> > + struct iwl_mvm_frame_stats *stats)
> {
> > + char *buff;
> > + int pos = 0, idx, i;
>
> I think this would be shorter code using pos as a char *
>
> > + int ret;
> > + size_t bufsz = 1024;
>
> I'd prefer #define or static const though the compiler should do the same
> thing.
>
> > + buff = kmalloc(bufsz, GFP_KERNEL);
> > + if (!buff)
> > + return -ENOMEM;
> > +
> > + spin_lock_bh(&mvm->drv_stats_lock);
>
> pos = buff;
> endpos = pos + bufsz;
>
> > + pos += scnprintf(buff + pos, bufsz - pos,
> > + "Legacy/HT/VHT\t:\t%d/%d/%d\n",
> > + stats->legacy_frames,
> > + stats->ht_frames,
> > + stats->vht_frames);
>
> pos += scnprintf(pos, endpos - pos, etc...
>
> etc...
>
I prefer not to reset my trees at that stage - it'll be addressed in a new commit of top of this.
From: Emmanuel Grumbach <[email protected]>
Newer firmware support a new bit in the policy that allows
to request to apply the time event immediately. Add this bit
without removing the workarounds we used until now to support
older firmares.
Reviewed-by: Johannes Berg <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/mvm/fw-api.h | 1 +
drivers/net/wireless/iwlwifi/mvm/time-event.c | 6 ++++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 4d808a9..807fa52 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -712,6 +712,7 @@ enum {
TE_V2_NOTIF_HOST_FRAG_END = BIT(5),
TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6),
TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7),
+ T2_V2_START_IMMEDIATELY = BIT(11),
TE_V2_NOTIF_MSK = 0xff,
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index e145dd4..6133124 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -438,7 +438,8 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
time_cmd.duration = cpu_to_le32(duration);
time_cmd.repeat = 1;
time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
- TE_V2_NOTIF_HOST_EVENT_END);
+ TE_V2_NOTIF_HOST_EVENT_END |
+ T2_V2_START_IMMEDIATELY);
iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
}
@@ -553,7 +554,8 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration));
time_cmd.repeat = 1;
time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
- TE_V2_NOTIF_HOST_EVENT_END);
+ TE_V2_NOTIF_HOST_EVENT_END |
+ T2_V2_START_IMMEDIATELY);
return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
}
--
1.7.9.5
From: Eran Harary <[email protected]>
We use the TLV flags as a handshake between the firmware
and the driver. These flags allow the firmware to advertise
its capabilities and API version.
Since we are running short of bits, we add a new
infrastructure which is more scalable, yet backward
compatible.
We make now the difference between API changes and the
capabilities. Both can have an index which allows to scale
at will.
Signed-off-by: Eran Harary <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-drv.c | 44 ++++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-fw-file.h | 17 +++++++++++
drivers/net/wireless/iwlwifi/iwl-fw.h | 4 +++
3 files changed, 65 insertions(+)
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 662d993..d49e9b9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -404,6 +404,38 @@ static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data)
return 0;
}
+static int iwl_set_ucode_api_flags(struct iwl_drv *drv, const u8 *data,
+ struct iwl_ucode_capabilities *capa)
+{
+ const struct iwl_ucode_api *ucode_api = (void *)data;
+ u32 api_index = le32_to_cpu(ucode_api->api_index);
+
+ if (api_index >= IWL_API_ARRAY_SIZE) {
+ IWL_ERR(drv, "api_index larger than supported by driver\n");
+ return -EINVAL;
+ }
+
+ capa->api[api_index] = le32_to_cpu(ucode_api->api_flags);
+
+ return 0;
+}
+
+static int iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data,
+ struct iwl_ucode_capabilities *capa)
+{
+ const struct iwl_ucode_capa *ucode_capa = (void *)data;
+ u32 api_index = le32_to_cpu(ucode_capa->api_index);
+
+ if (api_index >= IWL_CAPABILITIES_ARRAY_SIZE) {
+ IWL_ERR(drv, "api_index larger than supported by driver\n");
+ return -EINVAL;
+ }
+
+ capa->capa[api_index] = le32_to_cpu(ucode_capa->api_capa);
+
+ return 0;
+}
+
static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
const struct firmware *ucode_raw,
struct iwl_firmware_pieces *pieces)
@@ -638,6 +670,18 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
*/
capa->flags = le32_to_cpup((__le32 *)tlv_data);
break;
+ case IWL_UCODE_TLV_API_CHANGES_SET:
+ if (tlv_len != sizeof(struct iwl_ucode_api))
+ goto invalid_tlv_len;
+ if (iwl_set_ucode_api_flags(drv, tlv_data, capa))
+ goto tlv_error;
+ break;
+ case IWL_UCODE_TLV_ENABLED_CAPABILITIES:
+ if (tlv_len != sizeof(struct iwl_ucode_capa))
+ goto invalid_tlv_len;
+ if (iwl_set_ucode_capabilities(drv, tlv_data, capa))
+ goto tlv_error;
+ break;
case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
if (tlv_len != sizeof(u32))
goto invalid_tlv_len;
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
index 88e2d6e..b45e576 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
@@ -126,6 +126,8 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26,
IWL_UCODE_TLV_NUM_OF_CPU = 27,
IWL_UCODE_TLV_CSCHEME = 28,
+ IWL_UCODE_TLV_API_CHANGES_SET = 29,
+ IWL_UCODE_TLV_ENABLED_CAPABILITIES = 30,
};
struct iwl_ucode_tlv {
@@ -158,4 +160,19 @@ struct iwl_tlv_ucode_header {
u8 data[0];
};
+/*
+ * ucode TLVs
+ *
+ * ability to get extension for: flags & capabilities from ucode binaries files
+ */
+struct iwl_ucode_api {
+ __le32 api_index;
+ __le32 api_flags;
+} __packed;
+
+struct iwl_ucode_capa {
+ __le32 api_index;
+ __le32 api_capa;
+} __packed;
+
#endif /* __iwl_fw_file_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index af6b452..f04ff87 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -165,11 +165,15 @@ enum iwl_ucode_sec {
* just an offset to the HW address.
*/
#define IWL_UCODE_SECTION_MAX 12
+#define IWL_API_ARRAY_SIZE 1
+#define IWL_CAPABILITIES_ARRAY_SIZE 1
struct iwl_ucode_capabilities {
u32 max_probe_length;
u32 standard_phy_calibration_size;
u32 flags;
+ u32 api[IWL_API_ARRAY_SIZE];
+ u32 capa[IWL_CAPABILITIES_ARRAY_SIZE];
};
/* one for each uCode image (inst/data, init/runtime/wowlan) */
--
1.7.9.5
From: Eliad Peller <[email protected]>
Allow reading/writing prph registers.
The address is set in the first argument
of the write operation. second argument
is optional and can be used for writing.
e.g.
echo '0xA01234 0x99' > /sys/kernel/debug/ieee80211/phy0/iwlwifi/iwlmvm/prph_reg
will write 0x99 into reg 0xA01234
cat /sys/kernel/debug/ieee80211/phy0/iwlwifi/iwlmvm/prph_reg
will show its current value (probably 0x99)
Signed-off-by: Eliad Peller <[email protected]>
Reviewed-by: Johannes Berg <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/mvm/debugfs.c | 44 ++++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 +
2 files changed, 45 insertions(+)
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 6853e5e..9b98337 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -907,6 +907,49 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
+static ssize_t
+iwl_dbgfs_prph_reg_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_mvm *mvm = file->private_data;
+ int pos = 0;
+ char buf[32];
+ const size_t bufsz = sizeof(buf);
+
+ if (!mvm->dbgfs_prph_reg_addr)
+ return -EINVAL;
+
+ pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
+ mvm->dbgfs_prph_reg_addr,
+ iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t
+iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
+ size_t count, loff_t *ppos)
+{
+ u8 args;
+ u32 value;
+
+ args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
+ /* if we only want to set the reg address - nothing more to do */
+ if (args == 1)
+ goto out;
+
+ /* otherwise, make sure we have both address and value */
+ if (args != 2)
+ return -EINVAL;
+
+ iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
+out:
+ return count;
+}
+
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
+
/* Device wide debugfs entries */
MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
@@ -951,6 +994,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir,
S_IWUSR | S_IRUSR);
+ MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index bde8190..29d11d9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -518,6 +518,7 @@ struct iwl_mvm {
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct dentry *debugfs_dir;
u32 dbgfs_sram_offset, dbgfs_sram_len;
+ u32 dbgfs_prph_reg_addr;
bool disable_power_off;
bool disable_power_off_d3;
--
1.7.9.5
From: Johannes Berg <[email protected]>
Instead of checking the SKB protocol against EAP, check the
IEEE80211_TX_CTRL_PORT_CTRL_PROTO flag that more generally
indicates whether or not the frame is a port control frame.
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/mvm/tx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 8d18bf2..852d9d8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -122,7 +122,7 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
* it
*/
WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
- } else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
+ } else if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO) {
tx_cmd->pm_frame_timeout = cpu_to_le16(2);
} else {
tx_cmd->pm_frame_timeout = 0;
--
1.7.9.5
From: Emmanuel Grumbach <[email protected]>
The new API for ALIVE notification was misunderstood.
Reviewed-by: Johannes Berg <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/mvm/fw.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 4f398e6..979b35b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -130,7 +130,6 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
} else {
palive2 = (void *)pkt->data;
- mvm->support_umac_log = true;
mvm->error_event_table =
le32_to_cpu(palive2->error_event_table_ptr);
mvm->log_event_table =
@@ -141,6 +140,9 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
alive_data->valid = le16_to_cpu(palive2->status) ==
IWL_ALIVE_STATUS_OK;
+ if (mvm->umac_error_event_table)
+ mvm->support_umac_log = true;
+
IWL_DEBUG_FW(mvm,
"Alive VER2 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
le16_to_cpu(palive2->status), palive2->ver_type,
--
1.7.9.5
From: Johannes Berg <[email protected]>
These values aren't used as the firmware values should be used,
so reading them is pointless and hides potential errors when
somebody uses these values. Leave them zero to make it clearer
that they can't be used. We can't remove the struct members as
the DVM driver does read the values from EEPROM/OTP and the
structure is shared between drivers.
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 17 -----------------
drivers/net/wireless/iwlwifi/mvm/fw.c | 2 --
2 files changed, 19 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index 80c4096..eeb3a83 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -425,8 +425,6 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg);
- data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
- data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
return;
}
@@ -435,8 +433,6 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
data->radio_cfg_step = NVM_RF_CFG_STEP_MSK_FAMILY_8000(radio_cfg);
data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK_FAMILY_8000(radio_cfg);
data->radio_cfg_pnum = NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(radio_cfg);
- data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK_FAMILY_8000(radio_cfg);
- data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK_FAMILY_8000(radio_cfg);
}
static void iwl_set_hw_address(const struct iwl_cfg *cfg,
@@ -496,19 +492,6 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
data->sku_cap_11n_enable = false;
- /* check overrides (some devices have wrong NVM) */
- if (cfg->valid_tx_ant)
- data->valid_tx_ant = cfg->valid_tx_ant;
- if (cfg->valid_rx_ant)
- data->valid_rx_ant = cfg->valid_rx_ant;
-
- if (!data->valid_tx_ant || !data->valid_rx_ant) {
- IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n",
- data->valid_tx_ant, data->valid_rx_ant);
- kfree(data);
- return NULL;
- }
-
data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 979b35b..93e1b4d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -358,8 +358,6 @@ out:
GFP_KERNEL);
if (!mvm->nvm_data)
return -ENOMEM;
- mvm->nvm_data->valid_rx_ant = 1;
- mvm->nvm_data->valid_tx_ant = 1;
mvm->nvm_data->bands[0].channels = mvm->nvm_data->channels;
mvm->nvm_data->bands[0].n_channels = 1;
mvm->nvm_data->bands[0].n_bitrates = 1;
--
1.7.9.5
From: Eliad Peller <[email protected]>
Few minor comments.
Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-drv.c | 3 +--
drivers/net/wireless/iwlwifi/iwl-modparams.h | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index d49e9b9..847a0ed 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -1351,8 +1351,7 @@ MODULE_PARM_DESC(antenna_coupling,
module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO);
MODULE_PARM_DESC(wd_disable,
- "Disable stuck queue watchdog timer 0=system default, "
- "1=disable, 2=enable (default: 0)");
+ "Disable stuck queue watchdog timer 0=system default, 1=disable (default: 1)");
module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO);
MODULE_PARM_DESC(nvm_file, "NVM file name");
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h
index 0a84ade..1d100f2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h
@@ -93,7 +93,7 @@ enum iwl_power_level {
* use IWL_DISABLE_HT_* constants
* @amsdu_size_8K: enable 8K amsdu size, default = 0
* @restart_fw: restart firmware, default = 1
- * @wd_disable: enable stuck queue check, default = 0
+ * @wd_disable: disable stuck queue check, default = 1
* @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0
* @power_save: disable power save, default = false
--
1.7.9.5
From: Eytan Lifshitz <[email protected]>
iwl_parse_nvm_data() doesn't free allocated memory if it is
fed with invalid parameter. Fix this.
Signed-off-by: Eytan Lifshitz <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index df3ea60..80c4096 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -516,6 +516,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
if (!nvm_calib) {
IWL_ERR_DEV(dev,
"Can't parse empty Calib NVM sections\n");
+ kfree(data);
return NULL;
}
/* in family 8000 Xtal calibration values moved to OTP */
--
1.7.9.5
On Sun, Feb 23, 2014 at 09:53:08PM +0200, Emmanuel Grumbach wrote:
> Hi John,
>
> Here is pull request intended for 3.15.
>
> I have here a whole bunch of various things. Trivial cleanups, debugfs handlers and new stuff for the new generation of devices along with new capabilities for monitor mode. We also have support for power save for dual interface mode, but that is not supported by the firmware currently available.
>
> I had to merge wireless-next to get the new bits for monitor mode I added in mac80211-next.git.
>
> Let me know if you have any issue.
> Thanks!
>
> The following changes since commit e57f1734d87aa0e9a00905ed08888f0c62f56227:
> Starting
> mwifiex: add key material v2 support (2014-02-12 15:36:26 -0500)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git for-john
>
> for you to fetch changes up to 82b715c211a53e80a1db83b9b71995a05fe32908:
>
> iwlwifi: mvm: fix a few wd_disable comments (2014-02-23 21:38:54 +0200)
Pulling now...
--
John W. Linville Someday the world will need a hero, and you
[email protected] might be all we have. Be ready.