aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig10
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/tx.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-7000.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-8000.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-devtrace.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw-file.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-nvm-parse.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-op-mode.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scd.h118
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h67
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex_legacy.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/constants.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c10
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c76
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-power.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h48
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c6
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c106
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c104
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h41
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/nvm.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/offloading.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c16
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c148
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/quota.c14
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c66
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rx.c21
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c50
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sf.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c94
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.h22
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/testmode.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c61
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.h8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tt.c24
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c23
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/drv.c2
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/internal.h8
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/rx.c1
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c2
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c137
57 files changed, 1053 insertions, 315 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 824f5e287783..267e48a2915e 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -85,6 +85,16 @@ config IWLWIFI_BCAST_FILTERING
If unsure, don't enable this option, as some programs might
expect incoming broadcasts for their normal operations.
+config IWLWIFI_UAPSD
+ bool "enable U-APSD by default"
+ depends on IWLMVM
+ help
+ Say Y here to enable U-APSD by default. This may cause
+ interoperability problems with some APs, manifesting in lower than
+ expected throughput due to those APs not enabling aggregation
+
+ If unsure, say N.
+
menu "Debugging Options"
config IWLWIFI_DEBUG
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index 3255a1723d17..d1ce3ce13591 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -580,7 +580,7 @@ turn_off:
* time, or we hadn't time to drain the AC queues.
*/
if (agg_state == IWL_AGG_ON)
- iwl_trans_txq_disable(priv->trans, txq_id);
+ iwl_trans_txq_disable(priv->trans, txq_id, true);
else
IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n",
agg_state);
@@ -686,7 +686,7 @@ int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif,
* time, or we hadn't time to drain the AC queues.
*/
if (agg_state == IWL_AGG_ON)
- iwl_trans_txq_disable(priv->trans, txq_id);
+ iwl_trans_txq_disable(priv->trans, txq_id, true);
else
IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n",
agg_state);
@@ -781,7 +781,7 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid)
"Can continue DELBA flow ssn = next_recl = %d\n",
tid_data->next_reclaimed);
iwl_trans_txq_disable(priv->trans,
- tid_data->agg.txq_id);
+ tid_data->agg.txq_id, true);
iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id);
tid_data->agg.state = IWL_AGG_OFF;
ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index d67a37a786aa..7e26d0dbfcf7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c
index e93c6972290b..23a67bfc086f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-8000.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index fe129c94ae3e..23d059af6476 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 295083510e72..0a70bcd241f5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -145,6 +145,7 @@ do { \
#define IWL_DL_HCMD 0x00000004
#define IWL_DL_STATE 0x00000008
/* 0x000000F0 - 0x00000010 */
+#define IWL_DL_QUOTA 0x00000010
#define IWL_DL_TE 0x00000020
#define IWL_DL_EEPROM 0x00000040
#define IWL_DL_RADIO 0x00000080
@@ -189,6 +190,7 @@ do { \
#define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a)
#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
+#define IWL_DEBUG_QUOTA(p, f, a...) IWL_DEBUG(p, IWL_DL_QUOTA, f, ## a)
#define IWL_DEBUG_TE(p, f, a...) IWL_DEBUG(p, IWL_DL_TE, f, ## a)
#define IWL_DEBUG_EEPROM(d, f, a...) IWL_DEBUG_DEV(d, IWL_DL_EEPROM, f, ## a)
#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c
index 23e7351e02de..90987d6f348e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c
+++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c
@@ -36,15 +36,8 @@
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite8);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_tx);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event);
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_wrap_event);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_info);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_warn);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_crit);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_err);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dbg);
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 77e3178040b2..aefd94cb6e91 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1254,7 +1256,9 @@ struct iwl_mod_params iwlwifi_mod_params = {
.bt_coex_active = true,
.power_level = IWL_POWER_INDEX_1,
.wd_disable = true,
- .uapsd_disable = false,
+#ifndef CONFIG_IWLWIFI_UAPSD
+ .uapsd_disable = true,
+#endif /* CONFIG_IWLWIFI_UAPSD */
/* the rest are 0 by default */
};
IWL_EXPORT_SYMBOL(iwlwifi_mod_params);
@@ -1370,7 +1374,11 @@ MODULE_PARM_DESC(nvm_file, "NVM file name");
module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable,
bool, S_IRUGO);
+#ifdef CONFIG_IWLWIFI_UAPSD
MODULE_PARM_DESC(uapsd_disable, "disable U-APSD functionality (default: N)");
+#else
+MODULE_PARM_DESC(uapsd_disable, "disable U-APSD functionality (default: Y)");
+#endif
/*
* set bt_coex_active to true, uCode will do kill/defer
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h
index 3c72cb710b0c..be4f8972241a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
index de5994a776c7..e30a41d04c8b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
index 929a8063354c..401f7be36b93 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index 1bb5193c5b1b..f68cba4e0444 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -125,6 +127,8 @@ enum iwl_ucode_tlv_flag {
* @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.
* @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit.
* @IWL_UCODE_TLV_API_LMAC_SCAN: This ucode uses LMAC unified scan API.
+ * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time
+ * longer than the passive one, which is essential for fragmented scan.
*/
enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0),
@@ -133,6 +137,7 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_CSA_FLOW = BIT(4),
IWL_UCODE_TLV_API_DISABLE_STA_TX = BIT(5),
IWL_UCODE_TLV_API_LMAC_SCAN = BIT(6),
+ IWL_UCODE_TLV_API_FRAGMENTED_SCAN = BIT(8),
};
/**
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index 018af2957d3b..8e7af798abd1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index 99785c892f96..b6d666ee8359 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 47033a35a402..1560f4576c7d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -281,6 +283,7 @@
#define SCD_CHAINEXT_EN (SCD_BASE + 0x244)
#define SCD_AGGR_SEL (SCD_BASE + 0x248)
#define SCD_INTERRUPT_MASK (SCD_BASE + 0x108)
+#define SCD_EN_CTRL (SCD_BASE + 0x254)
static inline unsigned int SCD_QUEUE_WRPTR(unsigned int chnl)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-scd.h b/drivers/net/wireless/iwlwifi/iwl-scd.h
new file mode 100644
index 000000000000..6c622b21bba7
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-scd.h
@@ -0,0 +1,118 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2014 Intel Mobile Communications GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 Intel Mobile Communications GmbH
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+#ifndef __iwl_scd_h__
+#define __iwl_scd_h__
+
+#include "iwl-trans.h"
+#include "iwl-io.h"
+#include "iwl-prph.h"
+
+
+static inline void iwl_scd_txq_set_inactive(struct iwl_trans *trans,
+ u16 txq_id)
+{
+ iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id),
+ (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
+ (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
+}
+
+static inline void iwl_scd_txq_set_chain(struct iwl_trans *trans,
+ u16 txq_id)
+{
+ iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id));
+}
+
+static inline void iwl_scd_txq_enable_agg(struct iwl_trans *trans,
+ u16 txq_id)
+{
+ iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
+}
+
+static inline void iwl_scd_txq_disable_agg(struct iwl_trans *trans,
+ u16 txq_id)
+{
+ iwl_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
+}
+
+static inline void iwl_scd_disable_agg(struct iwl_trans *trans)
+{
+ iwl_set_bits_prph(trans, SCD_AGGR_SEL, 0);
+}
+
+static inline void iwl_scd_activate_fifos(struct iwl_trans *trans)
+{
+ iwl_write_prph(trans, SCD_TXFACT, IWL_MASK(0, 7));
+}
+
+static inline void iwl_scd_deactivate_fifos(struct iwl_trans *trans)
+{
+ iwl_write_prph(trans, SCD_TXFACT, 0);
+}
+
+static inline void iwl_scd_enable_set_active(struct iwl_trans *trans,
+ u32 value)
+{
+ iwl_write_prph(trans, SCD_EN_CTRL, value);
+}
+#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 656371a668da..c89985a58803 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -401,6 +403,14 @@ struct iwl_trans_dump_data {
struct iwl_trans;
+struct iwl_trans_txq_scd_cfg {
+ u8 fifo;
+ s8 sta_id;
+ u8 tid;
+ bool aggregate;
+ int frame_limit;
+};
+
/**
* struct iwl_trans_ops - transport specific operations
*
@@ -437,7 +447,9 @@ struct iwl_trans;
* Must be atomic
* @txq_enable: setup a queue. To setup an AC queue, use the
* iwl_trans_ac_txq_enable wrapper. fw_alive must have been called before
- * this one. The op_mode must not configure the HCMD queue. May sleep.
+ * this one. The op_mode must not configure the HCMD queue. The scheduler
+ * configuration may be %NULL, in which case the hardware will not be
+ * configured. May sleep.
* @txq_disable: de-configure a Tx queue to send AMPDUs
* Must be atomic
* @wait_tx_queue_empty: wait until tx queues are empty. May sleep.
@@ -492,9 +504,10 @@ struct iwl_trans_ops {
void (*reclaim)(struct iwl_trans *trans, int queue, int ssn,
struct sk_buff_head *skbs);
- void (*txq_enable)(struct iwl_trans *trans, int queue, int fifo,
- int sta_id, int tid, int frame_limit, u16 ssn);
- void (*txq_disable)(struct iwl_trans *trans, int queue);
+ void (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn,
+ const struct iwl_trans_txq_scd_cfg *cfg);
+ void (*txq_disable)(struct iwl_trans *trans, int queue,
+ bool configure_scd);
int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm);
@@ -766,29 +779,57 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue,
trans->ops->reclaim(trans, queue, ssn, skbs);
}
-static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue)
+static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue,
+ bool configure_scd)
{
- trans->ops->txq_disable(trans, queue);
+ trans->ops->txq_disable(trans, queue, configure_scd);
}
-static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
- int fifo, int sta_id, int tid,
- int frame_limit, u16 ssn)
+static inline void
+iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn,
+ const struct iwl_trans_txq_scd_cfg *cfg)
{
might_sleep();
if (unlikely((trans->state != IWL_TRANS_FW_ALIVE)))
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
- trans->ops->txq_enable(trans, queue, fifo, sta_id, tid,
- frame_limit, ssn);
+ trans->ops->txq_enable(trans, queue, ssn, cfg);
+}
+
+static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
+ int fifo, int sta_id, int tid,
+ int frame_limit, u16 ssn)
+{
+ struct iwl_trans_txq_scd_cfg cfg = {
+ .fifo = fifo,
+ .sta_id = sta_id,
+ .tid = tid,
+ .frame_limit = frame_limit,
+ .aggregate = sta_id >= 0,
+ };
+
+ iwl_trans_txq_enable_cfg(trans, queue, ssn, &cfg);
}
static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
int fifo)
{
- iwl_trans_txq_enable(trans, queue, fifo, -1,
- IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0);
+ struct iwl_trans_txq_scd_cfg cfg = {
+ .fifo = fifo,
+ .sta_id = -1,
+ .tid = IWL_MAX_TID_COUNT,
+ .frame_limit = IWL_FRAME_LIMIT,
+ .aggregate = false,
+ };
+
+ iwl_trans_txq_enable_cfg(trans, queue, 0, &cfg);
+}
+
+static inline void
+iwl_trans_txq_enable_no_scd(struct iwl_trans *trans, int queue, u16 ssn)
+{
+ iwl_trans_txq_enable_cfg(trans, queue, ssn, NULL);
}
static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans,
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c
index 2291bbcaaeab..2262d6dc61ae 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
index a3be33359927..585c0ab4a3ec 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h
index ca79f7160573..dd00e8f7f765 100644
--- a/drivers/net/wireless/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/iwlwifi/mvm/constants.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index 645b3cfc29a5..c17be0fb7283 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -700,7 +702,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return ret;
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], ap_sta);
- ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false);
+ ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
if (ret)
return ret;
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
index 2e90ff795c13..d919b4ebc83c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -119,6 +121,10 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
IWL_DEBUG_POWER(mvm, "uapsd_misbehaving_enable=%d\n", val);
dbgfs_pm->uapsd_misbehaving = val;
break;
+ case MVM_DEBUGFS_PM_USE_PS_POLL:
+ IWL_DEBUG_POWER(mvm, "use_ps_poll=%d\n", val);
+ dbgfs_pm->use_ps_poll = val;
+ break;
}
}
@@ -169,6 +175,10 @@ static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
if (sscanf(buf + 18, "%d", &val) != 1)
return -EINVAL;
param = MVM_DEBUGFS_PM_UAPSD_MISBEHAVING;
+ } else if (!strncmp("use_ps_poll=", buf, 12)) {
+ if (sscanf(buf + 12, "%d", &val) != 1)
+ return -EINVAL;
+ param = MVM_DEBUGFS_PM_USE_PS_POLL;
} else {
return -EINVAL;
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 7d18f466fbb3..d98ee109c5e9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -257,6 +259,70 @@ static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
return count;
}
+static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_mvm *mvm = file->private_data;
+ char buf[16];
+ int pos;
+
+ if (!mvm->temperature_test)
+ pos = scnprintf(buf , sizeof(buf), "disabled\n");
+ else
+ pos = scnprintf(buf , sizeof(buf), "%d\n", mvm->temperature);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+/*
+ * Set NIC Temperature
+ * Cause the driver to ignore the actual NIC temperature reported by the FW
+ * Enable: any value between IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -
+ * IWL_MVM_DEBUG_SET_TEMPERATURE_MAX
+ * Disable: IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE
+ */
+static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,
+ char *buf, size_t count,
+ loff_t *ppos)
+{
+ int temperature;
+
+ if (kstrtoint(buf, 10, &temperature))
+ return -EINVAL;
+ /* not a legal temperature */
+ if ((temperature > IWL_MVM_DEBUG_SET_TEMPERATURE_MAX &&
+ temperature != IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) ||
+ temperature < IWL_MVM_DEBUG_SET_TEMPERATURE_MIN)
+ return -EINVAL;
+
+ mutex_lock(&mvm->mutex);
+ if (temperature == IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) {
+ if (!mvm->temperature_test)
+ goto out;
+
+ mvm->temperature_test = false;
+ /* Since we can't read the temp while awake, just set
+ * it to zero until we get the next RX stats from the
+ * firmware.
+ */
+ mvm->temperature = 0;
+ } else {
+ mvm->temperature_test = true;
+ mvm->temperature = temperature;
+ }
+ IWL_DEBUG_TEMP(mvm, "%sabling debug set temperature (temp = %d)\n",
+ mvm->temperature_test ? "En" : "Dis" ,
+ mvm->temperature);
+ /* handle the temperature change */
+ iwl_mvm_tt_handler(mvm);
+
+out:
+ mutex_unlock(&mvm->mutex);
+
+ return count;
+}
+
static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -1296,6 +1362,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
MVM_DEBUGFS_READ_FILE_OPS(stations);
MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
@@ -1336,6 +1403,8 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
+ MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir,
+ S_IWUSR | S_IRUSR);
MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
@@ -1380,6 +1449,13 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
goto err;
#endif
+ if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR,
+ mvm->debugfs_dir,
+ &mvm->low_latency_agg_frame_limit))
+ goto err;
+ if (!debugfs_create_u8("ps_disabled", S_IRUSR,
+ mvm->debugfs_dir, &mvm->ps_disabled))
+ goto err;
if (!debugfs_create_blob("nvm_hw", S_IRUSR,
mvm->debugfs_dir, &mvm->nvm_hw_blob))
goto err;
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.h b/drivers/net/wireless/iwlwifi/mvm/debugfs.h
index e3a9774af495..8c4190e7e027 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
index 69875716dcdb..816883f9ff94 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
index 13696fe419b7..e74cdf2132f8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index c3a8c86b550d..27dd86395b39 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index c02a9e45ec5e..8f2216694004 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
index 47bd0406355d..21dd5b771660 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 95f5b3274efb..9c975f9ecfcb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,16 +75,20 @@
#include "fw-api-coex.h"
#include "fw-api-scan.h"
-/* maximal number of Tx queues in any platform */
-#define IWL_MVM_MAX_QUEUES 20
-
/* Tx queue numbers */
enum {
IWL_MVM_OFFCHANNEL_QUEUE = 8,
IWL_MVM_CMD_QUEUE = 9,
};
-#define IWL_MVM_CMD_FIFO 7
+enum iwl_mvm_tx_fifo {
+ IWL_MVM_TX_FIFO_BK = 0,
+ IWL_MVM_TX_FIFO_BE,
+ IWL_MVM_TX_FIFO_VI,
+ IWL_MVM_TX_FIFO_VO,
+ IWL_MVM_TX_FIFO_MCAST = 5,
+ IWL_MVM_TX_FIFO_CMD = 7,
+};
#define IWL_MVM_STATION_COUNT 16
@@ -184,6 +190,8 @@ enum {
REPLY_RX_MPDU_CMD = 0xc1,
BA_NOTIF = 0xc5,
+ MARKER_CMD = 0xcb,
+
/* BT Coex */
BT_COEX_PRIO_TABLE = 0xcc,
BT_COEX_PROT_ENV = 0xcd,
@@ -1307,6 +1315,38 @@ struct iwl_bcast_filter_cmd {
struct iwl_fw_bcast_mac macs[NUM_MAC_INDEX_DRIVER];
} __packed; /* BCAST_FILTERING_HCMD_API_S_VER_1 */
+/*
+ * enum iwl_mvm_marker_id - maker ids
+ *
+ * The ids for different type of markers to insert into the usniffer logs
+ */
+enum iwl_mvm_marker_id {
+ MARKER_ID_TX_FRAME_LATENCY = 1,
+}; /* MARKER_ID_API_E_VER_1 */
+
+/**
+ * struct iwl_mvm_marker - mark info into the usniffer logs
+ *
+ * (MARKER_CMD = 0xcb)
+ *
+ * Mark the UTC time stamp into the usniffer logs together with additional
+ * metadata, so the usniffer output can be parsed.
+ * In the command response the ucode will return the GP2 time.
+ *
+ * @dw_len: The amount of dwords following this byte including this byte.
+ * @marker_id: A unique marker id (iwl_mvm_marker_id).
+ * @reserved: reserved.
+ * @timestamp: in milliseconds since 1970-01-01 00:00:00 UTC
+ * @metadata: additional meta data that will be written to the unsiffer log
+ */
+struct iwl_mvm_marker {
+ u8 dwLen;
+ u8 markerId;
+ __le16 reserved;
+ __le64 timestamp;
+ __le32 metadata[0];
+} __packed; /* MARKER_API_S_VER_1 */
+
struct mvm_statistics_dbg {
__le32 burst_check;
__le32 burst_count;
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 883e702152d5..21d606028ca6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -242,10 +244,10 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
mvm->queue_to_mac80211[i] = i;
else
mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
- atomic_set(&mvm->queue_stop_count[i], 0);
}
- mvm->transport_queue_stop = 0;
+ for (i = 0; i < IEEE80211_MAX_QUEUES; i++)
+ atomic_set(&mvm->mac80211_queue_stop_count[i], 0);
mvm->ucode_loaded = true;
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 0e523e28cabf..9cbb192f680e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -81,7 +83,7 @@ struct iwl_mvm_mac_iface_iterator_data {
struct ieee80211_vif *vif;
unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)];
unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)];
- unsigned long used_hw_queues[BITS_TO_LONGS(IWL_MVM_MAX_QUEUES)];
+ u32 used_hw_queues;
enum iwl_tsf_id preferred_tsf;
bool found_vif;
};
@@ -192,12 +194,31 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
data->preferred_tsf = NUM_TSF_IDS;
}
+/*
+ * Get the mask of the queues used by the vif
+ */
+u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
+{
+ u32 qmask = 0, ac;
+
+ if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
+ return BIT(IWL_MVM_OFFCHANNEL_QUEUE);
+
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+ qmask |= BIT(vif->hw_queue[ac]);
+
+ if (vif->type == NL80211_IFTYPE_AP)
+ qmask |= BIT(vif->cab_queue);
+
+ return qmask;
+}
+
static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_mvm_mac_iface_iterator_data *data = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- u32 ac;
/* Iterator may already find the interface being added -- skip it */
if (vif == data->vif) {
@@ -206,12 +227,7 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
}
/* Mark the queues used by the vif */
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
- __set_bit(vif->hw_queue[ac], data->used_hw_queues);
-
- if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE)
- __set_bit(vif->cab_queue, data->used_hw_queues);
+ data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(data->mvm, vif);
/* Mark MAC IDs as used by clearing the available bit, and
* (below) mark TSFs as used if their existing use is not
@@ -225,24 +241,6 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
iwl_mvm_mac_tsf_id_iter(_data, mac, vif);
}
-/*
- * Get the mask of the queus used by the vif
- */
-u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- u32 qmask = 0, ac;
-
- if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
- return BIT(IWL_MVM_OFFCHANNEL_QUEUE);
-
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
- qmask |= BIT(vif->hw_queue[ac]);
-
- return qmask;
-}
-
void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
@@ -277,15 +275,15 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
.available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
/* no preference yet */
.preferred_tsf = NUM_TSF_IDS,
- .used_hw_queues = {
+ .used_hw_queues =
BIT(IWL_MVM_OFFCHANNEL_QUEUE) |
BIT(mvm->aux_queue) |
- BIT(IWL_MVM_CMD_QUEUE)
- },
+ BIT(IWL_MVM_CMD_QUEUE),
.found_vif = false,
};
u32 ac;
int ret, i;
+ unsigned long used_hw_queues;
/*
* Allocate a MAC ID and a TSF for this MAC, along with the queues
@@ -368,9 +366,11 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
return 0;
}
+ used_hw_queues = data.used_hw_queues;
+
/* Find available queues, and allocate them to the ACs */
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- u8 queue = find_first_zero_bit(data.used_hw_queues,
+ u8 queue = find_first_zero_bit(&used_hw_queues,
mvm->first_agg_queue);
if (queue >= mvm->first_agg_queue) {
@@ -379,13 +379,13 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
goto exit_fail;
}
- __set_bit(queue, data.used_hw_queues);
+ __set_bit(queue, &used_hw_queues);
vif->hw_queue[ac] = queue;
}
/* Allocate the CAB queue for softAP and GO interfaces */
if (vif->type == NL80211_IFTYPE_AP) {
- u8 queue = find_first_zero_bit(data.used_hw_queues,
+ u8 queue = find_first_zero_bit(&used_hw_queues,
mvm->first_agg_queue);
if (queue >= mvm->first_agg_queue) {
@@ -452,14 +452,16 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
switch (vif->type) {
case NL80211_IFTYPE_P2P_DEVICE:
- iwl_trans_txq_disable(mvm->trans, IWL_MVM_OFFCHANNEL_QUEUE);
+ iwl_trans_txq_disable(mvm->trans, IWL_MVM_OFFCHANNEL_QUEUE,
+ true);
break;
case NL80211_IFTYPE_AP:
- iwl_trans_txq_disable(mvm->trans, vif->cab_queue);
+ iwl_trans_txq_disable(mvm->trans, vif->cab_queue, true);
/* fall through */
default:
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- iwl_trans_txq_disable(mvm->trans, vif->hw_queue[ac]);
+ iwl_trans_txq_disable(mvm->trans, vif->hw_queue[ac],
+ true);
}
}
@@ -586,6 +588,7 @@ static void iwl_mvm_mac_ctxt_set_ht_flags(struct iwl_mvm *mvm,
static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_mac_ctx_cmd *cmd,
+ const u8 *bssid_override,
u32 action)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -593,6 +596,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
bool ht_enabled = !!(vif->bss_conf.ht_operation_mode &
IEEE80211_HT_OP_MODE_PROTECTION);
u8 cck_ack_rates, ofdm_ack_rates;
+ const u8 *bssid = bssid_override ?: vif->bss_conf.bssid;
int i;
cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
@@ -625,8 +629,9 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
cmd->tsf_id = cpu_to_le32(mvmvif->tsf_id);
memcpy(cmd->node_addr, vif->addr, ETH_ALEN);
- if (vif->bss_conf.bssid)
- memcpy(cmd->bssid_addr, vif->bss_conf.bssid, ETH_ALEN);
+
+ if (bssid)
+ memcpy(cmd->bssid_addr, bssid, ETH_ALEN);
else
eth_broadcast_addr(cmd->bssid_addr);
@@ -695,7 +700,8 @@ static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- u32 action, bool force_assoc_off)
+ u32 action, bool force_assoc_off,
+ const u8 *bssid_override)
{
struct iwl_mac_ctx_cmd cmd = {};
struct iwl_mac_data_sta *ctxt_sta;
@@ -703,7 +709,7 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
WARN_ON(vif->type != NL80211_IFTYPE_STATION);
/* Fill the common data for all mac context types */
- iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
+ iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, bssid_override, action);
if (vif->p2p) {
struct ieee80211_p2p_noa_attr *noa =
@@ -784,7 +790,7 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
- iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
+ iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
MAC_FILTER_IN_CONTROL_AND_MGMT |
@@ -805,7 +811,7 @@ static int iwl_mvm_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
WARN_ON(vif->type != NL80211_IFTYPE_ADHOC);
- iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
+ iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_BEACON |
MAC_FILTER_IN_PROBE_REQUEST);
@@ -844,7 +850,7 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
- iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
+ iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
@@ -1072,7 +1078,7 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p);
/* Fill the common data for all mac context types */
- iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
+ iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
/*
* pass probe requests and beacons from other APs (needed
@@ -1098,7 +1104,7 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
WARN_ON(vif->type != NL80211_IFTYPE_AP || !vif->p2p);
/* Fill the common data for all mac context types */
- iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
+ iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
/*
* pass probe requests and beacons from other APs (needed
@@ -1121,12 +1127,14 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
}
static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- u32 action, bool force_assoc_off)
+ u32 action, bool force_assoc_off,
+ const u8 *bssid_override)
{
switch (vif->type) {
case NL80211_IFTYPE_STATION:
return iwl_mvm_mac_ctxt_cmd_sta(mvm, vif, action,
- force_assoc_off);
+ force_assoc_off,
+ bssid_override);
break;
case NL80211_IFTYPE_AP:
if (!vif->p2p)
@@ -1157,7 +1165,7 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return -EIO;
ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD,
- true);
+ true, NULL);
if (ret)
return ret;
@@ -1169,7 +1177,7 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
}
int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- bool force_assoc_off)
+ bool force_assoc_off, const u8 *bssid_override)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -1178,7 +1186,7 @@ int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return -EIO;
return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY,
- force_assoc_off);
+ force_assoc_off, bssid_override);
}
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 7c8796584c25..8d1d4b40b0a3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -776,6 +778,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
iwl_trans_stop_device(mvm->trans);
mvm->scan_status = IWL_MVM_SCAN_NONE;
+ mvm->ps_disabled = false;
/* just in case one was running */
ieee80211_remain_on_channel_expired(mvm->hw);
@@ -803,6 +806,9 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
* ucode_down ref until reconfig is complete */
iwl_mvm_unref_all_except(mvm, IWL_MVM_REF_UCODE_DOWN);
+ /* clear any stale d0i3 state */
+ clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
+
mvm->vif_count = 0;
mvm->rx_ba_sessions = 0;
}
@@ -880,7 +886,7 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
/* async_handlers_list is empty and will stay empty: HW is stopped */
/* the fw is stopped, the aux sta is dead: clean up driver state */
- iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta);
+ iwl_mvm_del_aux_sta(mvm);
mutex_unlock(&mvm->mutex);
@@ -965,10 +971,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
*/
if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC) {
- u32 qmask = iwl_mvm_mac_get_queues_mask(mvm, vif);
- ret = iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta,
- qmask,
- ieee80211_vif_type_p2p(vif));
+ ret = iwl_mvm_alloc_bcast_sta(mvm, vif);
if (ret) {
IWL_ERR(mvm, "Failed to allocate bcast sta\n");
goto out_release;
@@ -1016,7 +1019,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
if (ret)
goto out_unref_phy;
- ret = iwl_mvm_add_bcast_sta(mvm, vif, &mvmvif->bcast_sta);
+ ret = iwl_mvm_add_bcast_sta(mvm, vif);
if (ret)
goto out_unbind;
@@ -1057,14 +1060,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
- u32 tfd_msk = 0, ac;
-
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
- tfd_msk |= BIT(vif->hw_queue[ac]);
-
- if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE)
- tfd_msk |= BIT(vif->cab_queue);
+ u32 tfd_msk = iwl_mvm_mac_get_queues_mask(mvm, vif);
if (tfd_msk) {
mutex_lock(&mvm->mutex);
@@ -1120,13 +1116,13 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
mvm->noa_duration = 0;
}
#endif
- iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta);
+ iwl_mvm_dealloc_bcast_sta(mvm, vif);
goto out_release;
}
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
mvm->p2p_device_vif = NULL;
- iwl_mvm_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
+ iwl_mvm_rm_bcast_sta(mvm, vif);
iwl_mvm_binding_remove_vif(mvm, vif);
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
mvmvif->phy_ctxt = NULL;
@@ -1445,10 +1441,23 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc)
iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
- ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false);
+ /*
+ * If we're not associated yet, take the (new) BSSID before associating
+ * so the firmware knows. If we're already associated, then use the old
+ * BSSID here, and we'll send a cleared one later in the CHANGED_ASSOC
+ * branch for disassociation below.
+ */
+ if (changes & BSS_CHANGED_BSSID && !mvmvif->associated)
+ memcpy(mvmvif->bssid, bss_conf->bssid, ETH_ALEN);
+
+ ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, mvmvif->bssid);
if (ret)
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
+ /* after sending it once, adopt mac80211 data */
+ memcpy(mvmvif->bssid, bss_conf->bssid, ETH_ALEN);
+ mvmvif->associated = bss_conf->assoc;
+
if (changes & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) {
/* add quota for this interface */
@@ -1476,13 +1485,17 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
*/
u32 dur = (11 * vif->bss_conf.beacon_int) / 10;
iwl_mvm_protect_session(mvm, vif, dur, dur,
- 5 * dur);
+ 5 * dur, false);
}
iwl_mvm_sf_update(mvm, vif, false);
iwl_mvm_power_vif_assoc(mvm, vif);
- if (vif->p2p)
+ if (vif->p2p) {
iwl_mvm_ref(mvm, IWL_MVM_REF_P2P_CLIENT);
+ iwl_mvm_update_smps(mvm, vif,
+ IWL_MVM_SMPS_REQ_PROT,
+ IEEE80211_SMPS_DYNAMIC);
+ }
} else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
/*
* If update fails - SF might be running in associated
@@ -1506,6 +1519,13 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
if (vif->p2p)
iwl_mvm_unref(mvm, IWL_MVM_REF_P2P_CLIENT);
+
+ /* this will take the cleared BSSID from bss_conf */
+ ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+ if (ret)
+ IWL_ERR(mvm,
+ "failed to update MAC %pM (clear after unassoc)\n",
+ vif->addr);
}
iwl_mvm_recalc_multicast(mvm);
@@ -1601,7 +1621,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
/* Send the bcast station. At this stage the TBTT and DTIM time events
* are added and applied to the scheduler */
- ret = iwl_mvm_send_bcast_sta(mvm, vif, &mvmvif->bcast_sta);
+ ret = iwl_mvm_send_add_bcast_sta(mvm, vif);
if (ret)
goto out_unbind;
@@ -1617,7 +1637,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
if (vif->p2p && mvm->p2p_device_vif)
- iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
+ iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL);
iwl_mvm_ref(mvm, IWL_MVM_REF_AP_IBSS);
@@ -1633,7 +1653,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
out_quota_failed:
iwl_mvm_power_update_mac(mvm);
mvmvif->ap_ibss_active = false;
- iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
+ iwl_mvm_send_rm_bcast_sta(mvm, vif);
out_unbind:
iwl_mvm_binding_remove_vif(mvm, vif);
out_remove:
@@ -1675,10 +1695,10 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
if (vif->p2p && mvm->p2p_device_vif)
- iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
+ iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL);
iwl_mvm_update_quotas(mvm, NULL);
- iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
+ iwl_mvm_send_rm_bcast_sta(mvm, vif);
iwl_mvm_binding_remove_vif(mvm, vif);
iwl_mvm_power_update_mac(mvm);
@@ -1702,7 +1722,7 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT |
BSS_CHANGED_BANDWIDTH) &&
- iwl_mvm_mac_ctxt_changed(mvm, vif, false))
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL))
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
/* Need to send a new beacon template to the FW */
@@ -2113,7 +2133,7 @@ static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw,
int ret;
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false);
+ ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
mutex_unlock(&mvm->mutex);
return ret;
}
@@ -2141,7 +2161,7 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
/* Try really hard to protect the session and hear a beacon */
- iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500);
+ iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500, false);
mutex_unlock(&mvm->mutex);
iwl_mvm_unref(mvm, IWL_MVM_REF_PREPARE_TX);
@@ -2162,7 +2182,7 @@ static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
/* Protect the session to hear the TDLS setup response on the channel */
- iwl_mvm_protect_session(mvm, vif, duration, duration, 100);
+ iwl_mvm_protect_session(mvm, vif, duration, duration, 100, true);
mutex_unlock(&mvm->mutex);
iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
@@ -2700,7 +2720,10 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
ret = 0;
goto out;
case NL80211_IFTYPE_STATION:
+ break;
case NL80211_IFTYPE_MONITOR:
+ /* always disable PS when a monitor interface is active */
+ mvmvif->ps_disabled = true;
break;
default:
ret = -EINVAL;
@@ -2732,7 +2755,20 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
if ((vif->type == NL80211_IFTYPE_AP) ||
(switching_chanctx && (vif->type == NL80211_IFTYPE_STATION))) {
iwl_mvm_update_quotas(mvm, NULL);
- iwl_mvm_mac_ctxt_changed(mvm, vif, false);
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+ }
+
+ if (vif->csa_active && vif->type == NL80211_IFTYPE_STATION) {
+ struct iwl_mvm_sta *mvmsta;
+
+ mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
+ mvmvif->ap_sta_id);
+
+ if (WARN_ON(!mvmsta))
+ goto out;
+
+ /* TODO: only re-enable after the first beacon */
+ iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
}
goto out;
@@ -2766,6 +2802,7 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_vif *disabled_vif = NULL;
+ struct iwl_mvm_sta *mvmsta;
lockdep_assert_held(&mvm->mutex);
@@ -2776,6 +2813,7 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
goto out;
case NL80211_IFTYPE_MONITOR:
mvmvif->monitor_active = false;
+ mvmvif->ps_disabled = false;
break;
case NL80211_IFTYPE_AP:
/* This part is triggered only during CSA */
@@ -2796,7 +2834,13 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
disabled_vif = vif;
- iwl_mvm_mac_ctxt_changed(mvm, vif, true);
+ mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
+ mvmvif->ap_sta_id);
+
+ if (!WARN_ON(!mvmsta))
+ iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, true);
+
+ iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL);
break;
default:
break;
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 2e73d3bd7757..e292de96e09a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -103,14 +105,6 @@
*/
#define IWL_MVM_CS_UNBLOCK_TX_TIMEOUT 3
-enum iwl_mvm_tx_fifo {
- IWL_MVM_TX_FIFO_BK = 0,
- IWL_MVM_TX_FIFO_BE,
- IWL_MVM_TX_FIFO_VI,
- IWL_MVM_TX_FIFO_VO,
- IWL_MVM_TX_FIFO_MCAST = 5,
-};
-
extern const struct ieee80211_ops iwl_mvm_hw_ops;
/**
@@ -203,6 +197,7 @@ enum iwl_dbgfs_pm_mask {
MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7),
MVM_DEBUGFS_PM_SNOOZE_ENABLE = BIT(8),
MVM_DEBUGFS_PM_UAPSD_MISBEHAVING = BIT(9),
+ MVM_DEBUGFS_PM_USE_PS_POLL = BIT(10),
};
struct iwl_dbgfs_pm {
@@ -215,6 +210,7 @@ struct iwl_dbgfs_pm {
u32 lprx_rssi_threshold;
bool snooze_ena;
bool uapsd_misbehaving;
+ bool use_ps_poll;
int mask;
};
@@ -253,6 +249,7 @@ struct iwl_dbgfs_bf {
enum iwl_mvm_smps_type_request {
IWL_MVM_SMPS_REQ_BT_COEX,
IWL_MVM_SMPS_REQ_TT,
+ IWL_MVM_SMPS_REQ_PROT,
NUM_IWL_MVM_SMPS_REQ,
};
@@ -315,6 +312,9 @@ struct iwl_mvm_vif_bf_data {
* @id: between 0 and 3
* @color: to solve races upon MAC addition and removal
* @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA
+ * @bssid: BSSID for this (client) interface
+ * @associated: indicates that we're currently associated, used only for
+ * managing the firmware state in iwl_mvm_bss_info_changed_station()
* @uploaded: indicates the MAC context has been added to the device
* @ap_ibss_active: indicates that AP/IBSS is configured and that the interface
* should get quota etc.
@@ -323,6 +323,7 @@ struct iwl_mvm_vif_bf_data {
* interface should get quota etc.
* @low_latency: indicates that this interface is in low-latency mode
* (VMACLowLatencyMode)
+ * @ps_disabled: indicates that this interface requires PS to be disabled
* @queue_params: QoS params for this MAC
* @bcast_sta: station used for broadcast packets. Used by the following
* vifs: P2P_DEVICE, GO and AP.
@@ -335,11 +336,15 @@ struct iwl_mvm_vif {
u16 color;
u8 ap_sta_id;
+ u8 bssid[ETH_ALEN];
+ bool associated;
+
bool uploaded;
bool ap_ibss_active;
bool pm_enabled;
bool monitor_active;
bool low_latency;
+ bool ps_disabled;
struct iwl_mvm_vif_bf_data bf_data;
u32 ap_beacon_time;
@@ -512,6 +517,10 @@ enum {
D0I3_PENDING_WAKEUP,
};
+#define IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE 0xff
+#define IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -100
+#define IWL_MVM_DEBUG_SET_TEMPERATURE_MAX 200
+
struct iwl_mvm {
/* for logger access */
struct device *dev;
@@ -553,9 +562,8 @@ struct iwl_mvm {
struct mvm_statistics_rx rx_stats;
- unsigned long transport_queue_stop;
u8 queue_to_mac80211[IWL_MAX_HW_QUEUES];
- atomic_t queue_stop_count[IWL_MAX_HW_QUEUES];
+ atomic_t mac80211_queue_stop_count[IEEE80211_MAX_QUEUES];
const char *nvm_file_name;
struct iwl_nvm_data *nvm_data;
@@ -694,6 +702,12 @@ struct iwl_mvm {
/* Thermal Throttling and CTkill */
struct iwl_mvm_tt_mgmt thermal_throttle;
s32 temperature; /* Celsius */
+ /*
+ * Debug option to set the NIC temperature. This option makes the
+ * driver think this is the actual NIC temperature, and ignore the
+ * real temperature that is received from the fw
+ */
+ bool temperature_test; /* Debug test temperature is enabled */
#ifdef CONFIG_NL80211_TESTMODE
u32 noa_duration;
@@ -706,7 +720,7 @@ struct iwl_mvm {
u8 last_agg_queue;
/* Indicate if device power save is allowed */
- bool ps_disabled;
+ u8 ps_disabled; /* u8 instead of bool to ease debugfs_create_* usage */
struct ieee80211_vif __rcu *csa_vif;
struct ieee80211_vif __rcu *csa_tx_blocked_vif;
@@ -714,6 +728,8 @@ struct iwl_mvm {
/* system time of last beacon (for AP/GO interface) */
u32 ap_last_beacon_gp2;
+
+ u8 low_latency_agg_frame_limit;
};
/* Extract MVM priv from op_mode and _hw */
@@ -878,7 +894,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- bool force_assoc_off);
+ bool force_assoc_off, const u8 *bssid_override);
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
@@ -968,6 +984,7 @@ int rs_pretty_print_rate(char *buf, const u32 rate);
/* power management */
int iwl_mvm_power_update_device(struct iwl_mvm *mvm);
int iwl_mvm_power_update_mac(struct iwl_mvm *mvm);
+int iwl_mvm_power_update_ps(struct iwl_mvm *mvm);
int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
char *buf, int bufsz);
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index cfdd314fdd5d..4fafd4bd89f4 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/offloading.c b/drivers/net/wireless/iwlwifi/mvm/offloading.c
index 9bfb95e89cfb..adcbf4c8edd8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/offloading.c
+++ b/drivers/net/wireless/iwlwifi/mvm/offloading.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index 610dbcb0dc27..87f278cc9b2c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -415,6 +417,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->first_agg_queue = 12;
}
mvm->sf_state = SF_UNINIT;
+ mvm->low_latency_agg_frame_limit = 1;
mutex_init(&mvm->mutex);
mutex_init(&mvm->d0i3_suspend_mutex);
@@ -456,7 +459,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
trans_cfg.command_names = iwl_mvm_cmd_strings;
trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE;
- trans_cfg.cmd_fifo = IWL_MVM_CMD_FIFO;
+ trans_cfg.cmd_fifo = IWL_MVM_TX_FIFO_CMD;
snprintf(mvm->hw->wiphy->fw_version,
sizeof(mvm->hw->wiphy->fw_version),
@@ -494,7 +497,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
goto out_free;
/*
- * Even if nvm exists in the nvm_file driver should read agin the nvm
+ * Even if nvm exists in the nvm_file driver should read again the nvm
* from the nic because there might be entries that exist in the OTP
* and not in the file.
* for nics with no_power_up_nic_in_init: rely completley on nvm_file
@@ -700,14 +703,13 @@ static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
return;
- if (atomic_inc_return(&mvm->queue_stop_count[mq]) > 1) {
+ if (atomic_inc_return(&mvm->mac80211_queue_stop_count[mq]) > 1) {
IWL_DEBUG_TX_QUEUES(mvm,
"queue %d (mac80211 %d) already stopped\n",
queue, mq);
return;
}
- set_bit(mq, &mvm->transport_queue_stop);
ieee80211_stop_queue(mvm->hw, mq);
}
@@ -719,15 +721,13 @@ static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int queue)
if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
return;
- if (atomic_dec_return(&mvm->queue_stop_count[mq]) > 0) {
+ if (atomic_dec_return(&mvm->mac80211_queue_stop_count[mq]) > 0) {
IWL_DEBUG_TX_QUEUES(mvm,
- "queue %d (mac80211 %d) already awake\n",
+ "queue %d (mac80211 %d) still stopped\n",
queue, mq);
return;
}
- clear_bit(mq, &mvm->transport_queue_stop);
-
ieee80211_wake_queue(mvm->hw, mq);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
index 6cc243f7cf60..12283b55ee84 100644
--- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index 2b2d10800a55..e7a6626fe839 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -198,8 +200,15 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
}
}
- if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
+ if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ /* set advanced pm flag with no uapsd ACs to enable ps-poll */
+ if (mvmvif->dbgfs_pm.use_ps_poll)
+ cmd->flags |=
+ cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
+#endif
return;
+ }
cmd->flags |= cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK);
@@ -497,13 +506,31 @@ struct iwl_power_vifs {
bool p2p_tdls;
};
-static void iwl_mvm_power_iterator(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
+static void iwl_mvm_power_disable_pm_iterator(void *_data, u8* mac,
+ struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_power_vifs *power_iterator = _data;
mvmvif->pm_enabled = false;
+}
+
+static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8* mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ bool *disable_ps = _data;
+
+ if (mvmvif->phy_ctxt)
+ if (mvmvif->phy_ctxt->id < MAX_PHYS)
+ *disable_ps |= mvmvif->ps_disabled;
+}
+
+static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_power_vifs *power_iterator = _data;
+
switch (ieee80211_vif_type_p2p(vif)) {
case NL80211_IFTYPE_P2P_DEVICE:
break;
@@ -559,9 +586,8 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
}
}
-static void
-iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
- struct iwl_power_vifs *vifs)
+static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
+ struct iwl_power_vifs *vifs)
{
struct iwl_mvm_vif *bss_mvmvif = NULL;
struct iwl_mvm_vif *p2p_mvmvif = NULL;
@@ -571,10 +597,11 @@ iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
- /* get vifs info + set pm_enable to false */
+ /* set pm_enable to false */
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_power_iterator, vifs);
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_power_disable_pm_iterator,
+ NULL);
if (vifs->bss_vif)
bss_mvmvif = iwl_mvm_vif_from_mac80211(vifs->bss_vif);
@@ -817,32 +844,92 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
return ret;
}
-int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
+static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
+{
+ bool disable_ps;
+ int ret;
+
+ /* disable PS if CAM */
+ disable_ps = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
+ /* ...or if any of the vifs require PS to be off */
+ ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_power_ps_disabled_iterator,
+ &disable_ps);
+
+ /* update device power state if it has changed */
+ if (mvm->ps_disabled != disable_ps) {
+ bool old_ps_disabled = mvm->ps_disabled;
+
+ mvm->ps_disabled = disable_ps;
+ ret = iwl_mvm_power_update_device(mvm);
+ if (ret) {
+ mvm->ps_disabled = old_ps_disabled;
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
+ struct iwl_power_vifs *vifs)
{
struct iwl_mvm_vif *mvmvif;
+ bool ba_enable;
+
+ if (!vifs->bf_vif)
+ return 0;
+
+ mvmvif = iwl_mvm_vif_from_mac80211(vifs->bf_vif);
+
+ ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled ||
+ !vifs->bf_vif->bss_conf.ps ||
+ iwl_mvm_vif_low_latency(mvmvif));
+
+ return iwl_mvm_update_beacon_abort(mvm, vifs->bf_vif, ba_enable);
+}
+
+int iwl_mvm_power_update_ps(struct iwl_mvm *mvm)
+{
+ struct iwl_power_vifs vifs = {
+ .mvm = mvm,
+ };
+ int ret;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ /* get vifs info */
+ ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_power_get_vifs_iterator, &vifs);
+
+ ret = iwl_mvm_power_set_ps(mvm);
+ if (ret)
+ return ret;
+
+ return iwl_mvm_power_set_ba(mvm, &vifs);
+}
+
+int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
+{
struct iwl_power_vifs vifs = {
.mvm = mvm,
};
- bool ba_enable;
int ret;
lockdep_assert_held(&mvm->mutex);
+ /* get vifs info */
+ ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_power_get_vifs_iterator, &vifs);
+
iwl_mvm_power_set_pm(mvm, &vifs);
- /* disable PS if CAM */
- if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) {
- mvm->ps_disabled = true;
- } else {
- /* don't update device power state unless we add / remove monitor */
- if (vifs.monitor_vif) {
- if (vifs.monitor_active)
- mvm->ps_disabled = true;
- ret = iwl_mvm_power_update_device(mvm);
- if (ret)
- return ret;
- }
- }
+ ret = iwl_mvm_power_set_ps(mvm);
+ if (ret)
+ return ret;
if (vifs.bss_vif) {
ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);
@@ -856,16 +943,7 @@ int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
return ret;
}
- if (!vifs.bf_vif)
- return 0;
-
- mvmvif = iwl_mvm_vif_from_mac80211(vifs.bf_vif);
-
- ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled ||
- !vifs.bf_vif->bss_conf.ps ||
- iwl_mvm_vif_low_latency(mvmvif));
-
- return iwl_mvm_update_beacon_abort(mvm, vifs.bf_vif, ba_enable);
+ return iwl_mvm_power_set_ba(mvm, &vifs);
}
int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c
index 4e20b3ce2b6a..5fd502db03d1 100644
--- a/drivers/net/wireless/iwlwifi/mvm/quota.c
+++ b/drivers/net/wireless/iwlwifi/mvm/quota.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -161,6 +163,9 @@ static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
quota *= (beacon_int - mvm->noa_duration);
quota /= beacon_int;
+ IWL_DEBUG_QUOTA(mvm, "quota: adjust for NoA from %d to %d\n",
+ le32_to_cpu(cmd->quotas[i].quota), quota);
+
cmd->quotas[i].quota = cpu_to_le32(quota);
}
#endif
@@ -222,6 +227,9 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
quota = (QUOTA_100 - QUOTA_LOWLAT_MIN) / n_non_lowlat;
quota_rem = QUOTA_100 - n_non_lowlat * quota -
QUOTA_LOWLAT_MIN;
+ IWL_DEBUG_QUOTA(mvm,
+ "quota: low-latency binding active, remaining quota per other binding: %d\n",
+ quota);
} else if (num_active_macs) {
/*
* There are 0 or more than 1 low latency bindings, or all the
@@ -230,6 +238,9 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
*/
quota = QUOTA_100 / num_active_macs;
quota_rem = QUOTA_100 % num_active_macs;
+ IWL_DEBUG_QUOTA(mvm,
+ "quota: splitting evenly per binding: %d\n",
+ quota);
} else {
/* values don't really matter - won't be used */
quota = 0;
@@ -271,6 +282,9 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
for (i = 0; i < MAX_BINDINGS; i++) {
if (le32_to_cpu(cmd.quotas[i].quota) != 0) {
le32_add_cpu(&cmd.quotas[i].quota, quota_rem);
+ IWL_DEBUG_QUOTA(mvm,
+ "quota: giving remainder of %d to binding %d\n",
+ quota_rem, i);
break;
}
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index c70e959bf0e3..17002cf437db 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -1,6 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -2678,6 +2679,7 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
int i;
int num_rates = ARRAY_SIZE(lq_cmd->rs_table);
__le32 ucode_rate_le32 = cpu_to_le32(ucode_rate);
+ u8 ant = (ucode_rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS;
for (i = 0; i < num_rates; i++)
lq_cmd->rs_table[i] = ucode_rate_le32;
@@ -2688,6 +2690,13 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
lq_cmd->mimo_delim = num_rates - 1;
else
lq_cmd->mimo_delim = 0;
+
+ lq_cmd->reduced_tpc = 0;
+
+ if (num_of_ant(ant) == 1)
+ lq_cmd->single_stream_ant_msk = ant;
+
+ lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
}
#endif /* CONFIG_MAC80211_DEBUGFS */
@@ -2811,31 +2820,55 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
const struct rs_rate *initial_rate)
{
struct iwl_lq_cmd *lq_cmd = &lq_sta->lq;
- u8 ant = initial_rate->ant;
+ struct iwl_mvm_sta *mvmsta;
+ struct iwl_mvm_vif *mvmvif;
+
+ lq_cmd->agg_disable_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
+ lq_cmd->agg_time_limit =
+ cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
#ifdef CONFIG_MAC80211_DEBUGFS
if (lq_sta->pers.dbg_fixed_rate) {
rs_build_rates_table_from_fixed(mvm, lq_cmd,
lq_sta->band,
lq_sta->pers.dbg_fixed_rate);
- lq_cmd->reduced_tpc = 0;
- ant = (lq_sta->pers.dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) >>
- RATE_MCS_ANT_POS;
- } else
+ return;
+ }
#endif
- rs_build_rates_table(mvm, lq_sta, initial_rate);
+ if (WARN_ON_ONCE(!sta || !initial_rate))
+ return;
- if (num_of_ant(ant) == 1)
- lq_cmd->single_stream_ant_msk = ant;
+ rs_build_rates_table(mvm, lq_sta, initial_rate);
- lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
- lq_cmd->agg_disable_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
+ if (num_of_ant(initial_rate->ant) == 1)
+ lq_cmd->single_stream_ant_msk = initial_rate->ant;
- lq_cmd->agg_time_limit =
- cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
+
+ if (num_of_ant(initial_rate->ant) == 1)
+ lq_cmd->single_stream_ant_msk = initial_rate->ant;
+
+ lq_cmd->agg_frame_cnt_limit = mvmsta->max_agg_bufsize;
- if (sta)
- lq_cmd->agg_time_limit =
+ /*
+ * In case of low latency, tell the firwmare to leave a frame in the
+ * Tx Fifo so that it can start a transaction in the same TxOP. This
+ * basically allows the firmware to send bursts.
+ */
+ if (iwl_mvm_vif_low_latency(mvmvif)) {
+ lq_cmd->agg_frame_cnt_limit--;
+
+ if (mvm->low_latency_agg_frame_limit)
+ lq_cmd->agg_frame_cnt_limit =
+ min(lq_cmd->agg_frame_cnt_limit,
+ mvm->low_latency_agg_frame_limit);
+ }
+
+ if (mvmsta->vif->p2p)
+ lq_cmd->flags |= LQ_FLAG_USE_RTS_MSK;
+
+ lq_cmd->agg_time_limit =
cpu_to_le16(iwl_mvm_coex_agg_time_limit(mvm, sta));
}
@@ -2932,10 +2965,7 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm,
lq_sta->lq.sta_id, lq_sta->pers.dbg_fixed_rate);
if (lq_sta->pers.dbg_fixed_rate) {
- struct rs_rate rate;
- rs_rate_from_ucode_rate(lq_sta->pers.dbg_fixed_rate,
- lq_sta->band, &rate);
- rs_fill_lq_cmd(mvm, NULL, lq_sta, &rate);
+ rs_fill_lq_cmd(mvm, NULL, lq_sta, NULL);
iwl_mvm_send_lq_cmd(lq_sta->pers.drv, &lq_sta->lq, false);
}
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index 4b98987fc413..48144e3ad527 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -491,10 +493,29 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
.mvm = mvm,
};
+ /*
+ * set temperature debug enabled - ignore FW temperature updates
+ * and use the user set temperature.
+ */
+ if (mvm->temperature_test) {
+ if (mvm->temperature < le32_to_cpu(common->temperature))
+ IWL_DEBUG_TEMP(mvm,
+ "Ignoring FW temperature update that is greater than the debug set temperature (debug temp = %d, fw temp = %d)\n",
+ mvm->temperature,
+ le32_to_cpu(common->temperature));
+ /*
+ * skip iwl_mvm_tt_handler since we are in
+ * temperature debug mode and we are ignoring
+ * the new temperature value
+ */
+ goto update;
+ }
+
if (mvm->temperature != le32_to_cpu(common->temperature)) {
mvm->temperature = le32_to_cpu(common->temperature);
iwl_mvm_tt_handler(mvm);
}
+update:
iwl_mvm_update_rx_statistics(mvm, stats);
ieee80211_iterate_active_interfaces(mvm->hw,
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 004b1f5d0314..bf9c63dc4a7d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -279,6 +281,7 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
{
bool global_bound = false;
enum ieee80211_band band;
+ u8 frag_passive_dwell = 0;
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
@@ -288,12 +291,36 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
if (!global_bound)
goto not_bound;
- params->suspend_time = 100;
- params->max_out_time = 600;
+ params->suspend_time = 30;
+ params->max_out_time = 170;
if (iwl_mvm_low_latency(mvm)) {
- params->suspend_time = 250;
- params->max_out_time = 250;
+ if (mvm->fw->ucode_capa.api[0] &
+ IWL_UCODE_TLV_API_FRAGMENTED_SCAN) {
+ params->suspend_time = 105;
+ params->max_out_time = 70;
+ frag_passive_dwell = 20;
+ } else {
+ params->suspend_time = 120;
+ params->max_out_time = 120;
+ }
+ }
+
+ if (frag_passive_dwell && (mvm->fw->ucode_capa.api[0] &
+ IWL_UCODE_TLV_API_FRAGMENTED_SCAN)) {
+ /*
+ * P2P device scan should not be fragmented to avoid negative
+ * impact on P2P device discovery. Configure max_out_time to be
+ * equal to dwell time on passive channel. Take a longest
+ * possible value, one that corresponds to 2GHz band
+ */
+ if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
+ u32 passive_dwell =
+ iwl_mvm_get_passive_dwell(IEEE80211_BAND_2GHZ);
+ params->max_out_time = passive_dwell;
+ } else {
+ params->passive_fragmented = true;
+ }
}
if (flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
@@ -302,7 +329,11 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
not_bound:
for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) {
- params->dwell[band].passive = iwl_mvm_get_passive_dwell(band);
+ if (params->passive_fragmented)
+ params->dwell[band].passive = frag_passive_dwell;
+ else
+ params->dwell[band].passive =
+ iwl_mvm_get_passive_dwell(band);
params->dwell[band].active = iwl_mvm_get_active_dwell(band,
n_ssids);
}
@@ -1100,10 +1131,11 @@ iwl_mvm_build_generic_unified_scan_cmd(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params)
{
memset(cmd, 0, ksize(cmd));
- cmd->active_dwell = (u8)params->dwell[IEEE80211_BAND_2GHZ].active;
- cmd->passive_dwell = (u8)params->dwell[IEEE80211_BAND_2GHZ].passive;
- /* TODO: Use params; now fragmented isn't used. */
- cmd->fragmented_dwell = 0;
+ cmd->active_dwell = params->dwell[IEEE80211_BAND_2GHZ].active;
+ cmd->passive_dwell = params->dwell[IEEE80211_BAND_2GHZ].passive;
+ if (params->passive_fragmented)
+ cmd->fragmented_dwell =
+ params->dwell[IEEE80211_BAND_2GHZ].passive;
cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm);
cmd->max_out_time = cpu_to_le32(params->max_out_time);
cmd->suspend_time = cpu_to_le32(params->suspend_time);
diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c
index 7edfd15efc9d..d1922afe06f4 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sf.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sf.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 763548880399..dd9f3a4347f6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -250,10 +252,14 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
if (ret)
return ret;
- /* The first station added is the AP, the others are TDLS STAs */
- if (vif->type == NL80211_IFTYPE_STATION &&
- mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
- mvmvif->ap_sta_id = sta_id;
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ if (!sta->tdls) {
+ WARN_ON(mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT);
+ mvmvif->ap_sta_id = sta_id;
+ } else {
+ WARN_ON(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT);
+ }
+ }
rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], sta);
@@ -458,8 +464,9 @@ int iwl_mvm_rm_sta_id(struct iwl_mvm *mvm,
return ret;
}
-int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta,
- u32 qmask, enum nl80211_iftype iftype)
+static int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
+ struct iwl_mvm_int_sta *sta,
+ u32 qmask, enum nl80211_iftype iftype)
{
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype);
@@ -474,7 +481,8 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta,
return 0;
}
-void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta)
+static void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm,
+ struct iwl_mvm_int_sta *sta)
{
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta->sta_id], NULL);
memset(sta, 0, sizeof(struct iwl_mvm_int_sta));
@@ -544,6 +552,13 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
return ret;
}
+void iwl_mvm_del_aux_sta(struct iwl_mvm *mvm)
+{
+ lockdep_assert_held(&mvm->mutex);
+
+ iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta);
+}
+
/*
* Send the add station command for the vif's broadcast station.
* Assumes that the station was already allocated.
@@ -552,10 +567,10 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
* @vif: the interface to which the broadcast station is added
* @bsta: the broadcast station to add.
*/
-int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct iwl_mvm_int_sta *bsta)
+int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_int_sta *bsta = &mvmvif->bcast_sta;
static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const u8 *baddr = _baddr;
@@ -573,19 +588,40 @@ int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
/* Send the FW a request to remove the station from it's internal data
* structures, but DO NOT remove the entry from the local data structures. */
-int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm,
- struct iwl_mvm_int_sta *bsta)
+int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
lockdep_assert_held(&mvm->mutex);
- ret = iwl_mvm_rm_sta_common(mvm, bsta->sta_id);
+ ret = iwl_mvm_rm_sta_common(mvm, mvmvif->bcast_sta.sta_id);
if (ret)
IWL_WARN(mvm, "Failed sending remove station\n");
return ret;
}
+int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ u32 qmask;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ qmask = iwl_mvm_mac_get_queues_mask(mvm, vif);
+
+ /*
+ * The firmware defines the TFD queue mask to only be relevant
+ * for *unicast* queues, so the multicast (CAB) queue shouldn't
+ * be included.
+ */
+ if (vif->type == NL80211_IFTYPE_AP)
+ qmask &= ~BIT(vif->cab_queue);
+
+ return iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, qmask,
+ ieee80211_vif_type_p2p(vif));
+}
+
/* Allocate a new station entry for the broadcast station to the given vif,
* and send it to the FW.
* Note that each P2P mac should have its own broadcast station.
@@ -593,45 +629,47 @@ int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm,
* @mvm: the mvm component
* @vif: the interface to which the broadcast station is added
* @bsta: the broadcast station to add. */
-int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct iwl_mvm_int_sta *bsta)
+int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- static const u8 baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- u32 qmask;
+ struct iwl_mvm_int_sta *bsta = &mvmvif->bcast_sta;
int ret;
lockdep_assert_held(&mvm->mutex);
- qmask = iwl_mvm_mac_get_queues_mask(mvm, vif);
- ret = iwl_mvm_allocate_int_sta(mvm, bsta, qmask,
- ieee80211_vif_type_p2p(vif));
+ ret = iwl_mvm_alloc_bcast_sta(mvm, vif);
if (ret)
return ret;
- ret = iwl_mvm_add_int_sta_common(mvm, bsta, baddr,
- mvmvif->id, mvmvif->color);
+ ret = iwl_mvm_send_add_bcast_sta(mvm, vif);
if (ret)
iwl_mvm_dealloc_int_sta(mvm, bsta);
+
return ret;
}
+void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta);
+}
+
/*
* Send the FW a request to remove the station from it's internal data
* structures, and in addition remove it from the local data structure.
*/
-int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *bsta)
+int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
int ret;
lockdep_assert_held(&mvm->mutex);
- ret = iwl_mvm_rm_sta_common(mvm, bsta->sta_id);
- if (ret)
- return ret;
+ ret = iwl_mvm_send_rm_bcast_sta(mvm, vif);
+
+ iwl_mvm_dealloc_bcast_sta(mvm, vif);
- iwl_mvm_dealloc_int_sta(mvm, bsta);
return ret;
}
@@ -910,7 +948,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}
tid_data->ssn = 0xffff;
- iwl_trans_txq_disable(mvm->trans, txq_id);
+ iwl_trans_txq_disable(mvm->trans, txq_id, true);
/* fall through */
case IWL_AGG_STARTING:
case IWL_EMPTYING_HW_QUEUE_ADDBA:
@@ -965,7 +1003,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
- iwl_trans_txq_disable(mvm->trans, tid_data->txq_id);
+ iwl_trans_txq_disable(mvm->trans, tid_data->txq_id, true);
}
mvm->queue_to_mac80211[tid_data->txq_id] =
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h
index 3b1c8bd6cb54..aeb3a7f80ceb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -387,17 +389,15 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid);
int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm);
-int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta,
- u32 qmask, enum nl80211_iftype iftype);
-void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm,
- struct iwl_mvm_int_sta *sta);
-int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct iwl_mvm_int_sta *bsta);
-int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm,
- struct iwl_mvm_int_sta *bsta);
-int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct iwl_mvm_int_sta *bsta);
-int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *bsta);
+void iwl_mvm_del_aux_sta(struct iwl_mvm *mvm);
+
+int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+
void iwl_mvm_sta_drained_wk(struct work_struct *wk);
void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
struct ieee80211_sta *sta);
diff --git a/drivers/net/wireless/iwlwifi/mvm/testmode.h b/drivers/net/wireless/iwlwifi/mvm/testmode.h
index 0241665925f7..79ab6beb6b26 100644
--- a/drivers/net/wireless/iwlwifi/mvm/testmode.h
+++ b/drivers/net/wireless/iwlwifi/mvm/testmode.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index 33e5041f1efc..447d3b1003df 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -348,6 +350,38 @@ unlock:
return 0;
}
+static bool iwl_mvm_te_notif(struct iwl_notif_wait_data *notif_wait,
+ struct iwl_rx_packet *pkt, void *data)
+{
+ struct iwl_mvm *mvm =
+ container_of(notif_wait, struct iwl_mvm, notif_wait);
+ struct iwl_mvm_time_event_data *te_data = data;
+ struct iwl_time_event_notif *resp;
+ int resp_len = iwl_rx_packet_payload_len(pkt);
+
+ if (WARN_ON(pkt->hdr.cmd != TIME_EVENT_NOTIFICATION))
+ return true;
+
+ if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {
+ IWL_ERR(mvm, "Invalid TIME_EVENT_NOTIFICATION response\n");
+ return true;
+ }
+
+ resp = (void *)pkt->data;
+
+ /* te_data->uid is already set in the TIME_EVENT_CMD response */
+ if (le32_to_cpu(resp->unique_id) != te_data->uid)
+ return false;
+
+ IWL_DEBUG_TE(mvm, "TIME_EVENT_NOTIFICATION response - UID = 0x%x\n",
+ te_data->uid);
+ if (!resp->status)
+ IWL_ERR(mvm,
+ "TIME_EVENT_NOTIFICATION received but not executed\n");
+
+ return true;
+}
+
static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data)
{
@@ -441,10 +475,12 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,
void iwl_mvm_protect_session(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 duration, u32 min_duration,
- u32 max_delay)
+ u32 max_delay, bool wait_for_notif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
+ const u8 te_notif_response[] = { TIME_EVENT_NOTIFICATION };
+ struct iwl_notification_wait wait_te_notif;
struct iwl_time_event_cmd time_cmd = {};
lockdep_assert_held(&mvm->mutex);
@@ -489,7 +525,28 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
TE_V2_NOTIF_HOST_EVENT_END |
T2_V2_START_IMMEDIATELY);
- iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
+ if (!wait_for_notif) {
+ iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
+ return;
+ }
+
+ /*
+ * Create notification_wait for the TIME_EVENT_NOTIFICATION to use
+ * right after we send the time event
+ */
+ iwl_init_notification_wait(&mvm->notif_wait, &wait_te_notif,
+ te_notif_response,
+ ARRAY_SIZE(te_notif_response),
+ iwl_mvm_te_notif, te_data);
+
+ /* If TE was sent OK - wait for the notification that started */
+ if (iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd)) {
+ IWL_ERR(mvm, "Failed to add TE to protect session\n");
+ iwl_remove_notification(&mvm->notif_wait, &wait_te_notif);
+ } else if (iwl_wait_notification(&mvm->notif_wait, &wait_te_notif,
+ TU_TO_JIFFIES(max_delay))) {
+ IWL_ERR(mvm, "Failed to protect session until TE\n");
+ }
}
/*
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h
index 2f48a90d4ad3..bee3b2446b35 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.h
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -124,10 +126,12 @@
* @min_duration: will start a new session if the current session will end
* in less than min_duration.
* @max_delay: maximum delay before starting the time event (in TU)
+ * @wait_for_notif: true if it is required that a time event notification be
+ * waited for (that the time event has been scheduled before returning)
*
* This function can be used to start a session protection which means that the
* fw will stay on the channel for %duration_ms milliseconds. This function
- * will block (sleep) until the session starts. This function can also be used
+ * can block (sleep) until the session starts. This function can also be used
* to extend a currently running session.
* This function is meant to be used for BSS association for example, where we
* want to make sure that the fw stays on the channel during the association.
@@ -135,7 +139,7 @@
void iwl_mvm_protect_session(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 duration, u32 min_duration,
- u32 max_delay);
+ u32 max_delay, bool wait_for_notif);
/**
* iwl_mvm_stop_session_protection - cancel the session protection.
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index 0464599c111e..c3e1fe4282f1 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -314,14 +316,26 @@ static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm)
{
u32 duration = mvm->thermal_throttle.params->ct_kill_duration;
+ if (test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status))
+ return;
+
IWL_ERR(mvm, "Enter CT Kill\n");
iwl_mvm_set_hw_ctkill_state(mvm, true);
- schedule_delayed_work(&mvm->thermal_throttle.ct_kill_exit,
- round_jiffies_relative(duration * HZ));
+
+ /* Don't schedule an exit work if we're in test mode, since
+ * the temperature will not change unless we manually set it
+ * again (or disable testing).
+ */
+ if (!mvm->temperature_test)
+ schedule_delayed_work(&mvm->thermal_throttle.ct_kill_exit,
+ round_jiffies_relative(duration * HZ));
}
static void iwl_mvm_exit_ctkill(struct iwl_mvm *mvm)
{
+ if (!test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status))
+ return;
+
IWL_ERR(mvm, "Exit CT Kill\n");
iwl_mvm_set_hw_ctkill_state(mvm, false);
}
@@ -444,6 +458,12 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm)
return;
}
+ if (params->support_ct_kill &&
+ temperature <= tt->params->ct_kill_exit) {
+ iwl_mvm_exit_ctkill(mvm);
+ return;
+ }
+
if (params->support_dynamic_smps) {
if (!tt->dynamic_smps &&
temperature >= params->dynamic_smps_entry) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index dbc870713882..963edb8656ad 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -482,7 +484,7 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
IWL_DEBUG_TX_QUEUES(mvm,
"Can continue DELBA flow ssn = next_recl = %d\n",
tid_data->next_reclaimed);
- iwl_trans_txq_disable(mvm->trans, tid_data->txq_id);
+ iwl_trans_txq_disable(mvm->trans, tid_data->txq_id, true);
tid_data->state = IWL_AGG_OFF;
/*
* we can't hold the mutex - but since we are after a sequence
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index ac249da8a22b..1958f298ac8b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -387,15 +389,19 @@ struct iwl_error_event_table {
struct iwl_umac_error_event_table {
u32 valid; /* (nonzero) valid, (0) log is empty */
u32 error_id; /* type of error */
- u32 pc; /* program counter */
u32 blink1; /* branch link */
u32 blink2; /* branch link */
u32 ilink1; /* interrupt link */
u32 ilink2; /* interrupt link */
u32 data1; /* error-specific data */
u32 data2; /* error-specific data */
- u32 line; /* source code line of error */
- u32 umac_ver; /* umac version */
+ u32 data3; /* error-specific data */
+ u32 umac_fw_ver; /* UMAC version */
+ u32 umac_fw_api_ver; /* UMAC FW API ver */
+ u32 frame_pointer; /* core register 27*/
+ u32 stack_pointer; /* core register 28 */
+ u32 cmd_header; /* latest host cmd sent to UMAC */
+ u32 nic_isr_pref; /* ISR status register */
} __packed;
#define ERROR_START_OFFSET (1 * sizeof(u32))
@@ -409,7 +415,7 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm)
base = mvm->umac_error_event_table;
- if (base < 0x800000 || base >= 0x80C000) {
+ if (base < 0x800000) {
IWL_ERR(mvm,
"Not valid error log pointer 0x%08X for %s uCode\n",
base,
@@ -428,14 +434,19 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm)
IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id,
desc_lookup(table.error_id));
- IWL_ERR(mvm, "0x%08X | umac uPc\n", table.pc);
IWL_ERR(mvm, "0x%08X | umac branchlink1\n", table.blink1);
IWL_ERR(mvm, "0x%08X | umac branchlink2\n", table.blink2);
IWL_ERR(mvm, "0x%08X | umac interruptlink1\n", table.ilink1);
IWL_ERR(mvm, "0x%08X | umac interruptlink2\n", table.ilink2);
IWL_ERR(mvm, "0x%08X | umac data1\n", table.data1);
IWL_ERR(mvm, "0x%08X | umac data2\n", table.data2);
- IWL_ERR(mvm, "0x%08X | umac version\n", table.umac_ver);
+ IWL_ERR(mvm, "0x%08X | umac data3\n", table.data3);
+ IWL_ERR(mvm, "0x%08X | umac version\n", table.umac_fw_ver);
+ IWL_ERR(mvm, "0x%08X | umac api version\n", table.umac_fw_api_ver);
+ IWL_ERR(mvm, "0x%08X | frame pointer\n", table.frame_pointer);
+ IWL_ERR(mvm, "0x%08X | stack pointer\n", table.stack_pointer);
+ IWL_ERR(mvm, "0x%08X | last host cmd\n", table.cmd_header);
+ IWL_ERR(mvm, "0x%08X | isr status reg\n", table.nic_isr_pref);
}
void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index f0e722ced080..dbbbf23082a2 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 78f72c34438a..a4fedc4a7448 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -1,6 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -364,9 +365,10 @@ int iwl_pcie_tx_init(struct iwl_trans *trans);
void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr);
int iwl_pcie_tx_stop(struct iwl_trans *trans);
void iwl_pcie_tx_free(struct iwl_trans *trans);
-void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
- int sta_id, int tid, int frame_limit, u16 ssn);
-void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue);
+void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int queue, u16 ssn,
+ const struct iwl_trans_txq_scd_cfg *cfg);
+void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue,
+ bool configure_scd);
int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_device_cmd *dev_cmd, int txq_id);
void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans);
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index a2698e5e062c..702f47fb16fe 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -1,6 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 06e04aaf61ee..3076e0e9a490 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 6acccb19c4f3..a6336b4aa3a4 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1,6 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -34,6 +35,7 @@
#include "iwl-csr.h"
#include "iwl-prph.h"
#include "iwl-io.h"
+#include "iwl-scd.h"
#include "iwl-op-mode.h"
#include "internal.h"
/* FIXME: need to abstract out TX command (once we know what it looks like) */
@@ -644,17 +646,6 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
memset(txq, 0, sizeof(*txq));
}
-/*
- * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
- */
-static void iwl_pcie_txq_set_sched(struct iwl_trans *trans, u32 mask)
-{
- struct iwl_trans_pcie __maybe_unused *trans_pcie =
- IWL_TRANS_GET_PCIE_TRANS(trans);
-
- iwl_write_prph(trans, SCD_TXFACT, mask);
-}
-
void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -692,7 +683,7 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
trans_pcie->cmd_fifo);
/* Activate all Tx DMA/FIFO channels */
- iwl_pcie_txq_set_sched(trans, IWL_MASK(0, 7));
+ iwl_scd_activate_fifos(trans);
/* Enable DMA channel */
for (chan = 0; chan < FH_TCSR_CHNL_NUM; chan++)
@@ -745,7 +736,7 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans)
/* Turn off all Tx DMA fifos */
spin_lock(&trans_pcie->irq_lock);
- iwl_pcie_txq_set_sched(trans, 0);
+ iwl_scd_deactivate_fifos(trans);
/* Stop each Tx DMA channel, and wait for it to be idle */
for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
@@ -886,7 +877,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
spin_lock(&trans_pcie->irq_lock);
/* Turn off all Tx DMA fifos */
- iwl_write_prph(trans, SCD_TXFACT, 0);
+ iwl_scd_deactivate_fifos(trans);
/* Tell NIC where to find the "keep warm" buffer */
iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
@@ -1072,55 +1063,52 @@ static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid,
return 0;
}
-static inline void iwl_pcie_txq_set_inactive(struct iwl_trans *trans,
- u16 txq_id)
-{
- /* Simply stop the queue, but don't change any configuration;
- * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
- iwl_write_prph(trans,
- SCD_QUEUE_STATUS_BITS(txq_id),
- (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
- (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
-}
-
/* Receiver address (actually, Rx station's index into station table),
* combined with Traffic ID (QOS priority), in format used by Tx Scheduler */
#define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid))
-void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
- int sta_id, int tid, int frame_limit, u16 ssn)
+void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
+ const struct iwl_trans_txq_scd_cfg *cfg)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ int fifo = -1;
if (test_and_set_bit(txq_id, trans_pcie->queue_used))
WARN_ONCE(1, "queue %d already used - expect issues", txq_id);
- /* Stop this Tx queue before configuring it */
- iwl_pcie_txq_set_inactive(trans, txq_id);
+ if (cfg) {
+ fifo = cfg->fifo;
- /* Set this queue as a chain-building queue unless it is CMD queue */
- if (txq_id != trans_pcie->cmd_queue)
- iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id));
+ /* Disable the scheduler prior configuring the cmd queue */
+ if (txq_id == trans_pcie->cmd_queue)
+ iwl_scd_enable_set_active(trans, 0);
- /* If this queue is mapped to a certain station: it is an AGG queue */
- if (sta_id >= 0) {
- u16 ra_tid = BUILD_RAxTID(sta_id, tid);
+ /* Stop this Tx queue before configuring it */
+ iwl_scd_txq_set_inactive(trans, txq_id);
- /* Map receiver-address / traffic-ID to this queue */
- iwl_pcie_txq_set_ratid_map(trans, ra_tid, txq_id);
+ /* Set this queue as a chain-building queue unless it is CMD */
+ if (txq_id != trans_pcie->cmd_queue)
+ iwl_scd_txq_set_chain(trans, txq_id);
- /* enable aggregations for the queue */
- iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
- trans_pcie->txq[txq_id].ampdu = true;
- } else {
- /*
- * disable aggregations for the queue, this will also make the
- * ra_tid mapping configuration irrelevant since it is now a
- * non-AGG queue.
- */
- iwl_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
+ if (cfg->aggregate) {
+ u16 ra_tid = BUILD_RAxTID(cfg->sta_id, cfg->tid);
+
+ /* Map receiver-address / traffic-ID to this queue */
+ iwl_pcie_txq_set_ratid_map(trans, ra_tid, txq_id);
+
+ /* enable aggregations for the queue */
+ iwl_scd_txq_enable_agg(trans, txq_id);
+ trans_pcie->txq[txq_id].ampdu = true;
+ } else {
+ /*
+ * disable aggregations for the queue, this will also
+ * make the ra_tid mapping configuration irrelevant
+ * since it is now a non-AGG queue.
+ */
+ iwl_scd_txq_disable_agg(trans, txq_id);
- ssn = trans_pcie->txq[txq_id].q.read_ptr;
+ ssn = trans_pcie->txq[txq_id].q.read_ptr;
+ }
}
/* Place first TFD at index corresponding to start sequence number.
@@ -1128,32 +1116,43 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
trans_pcie->txq[txq_id].q.read_ptr = (ssn & 0xff);
trans_pcie->txq[txq_id].q.write_ptr = (ssn & 0xff);
- iwl_write_direct32(trans, HBUS_TARG_WRPTR,
- (ssn & 0xff) | (txq_id << 8));
- iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn);
+ if (cfg) {
+ u8 frame_limit = cfg->frame_limit;
+
+ iwl_write_direct32(trans, HBUS_TARG_WRPTR,
+ (ssn & 0xff) | (txq_id << 8));
+ iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn);
- /* Set up Tx window size and frame limit for this queue */
- iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr +
- SCD_CONTEXT_QUEUE_OFFSET(txq_id), 0);
- iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr +
+ /* Set up Tx window size and frame limit for this queue */
+ iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr +
+ SCD_CONTEXT_QUEUE_OFFSET(txq_id), 0);
+ iwl_trans_write_mem32(trans,
+ trans_pcie->scd_base_addr +
SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
- SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
+ SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
((frame_limit << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
- SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
-
- /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
- iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id),
- (1 << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
- (fifo << SCD_QUEUE_STTS_REG_POS_TXF) |
- (1 << SCD_QUEUE_STTS_REG_POS_WSL) |
- SCD_QUEUE_STTS_REG_MSK);
+ SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
+
+ /* Set up status area in SRAM, map to Tx DMA/FIFO, activate */
+ iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id),
+ (1 << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
+ (cfg->fifo << SCD_QUEUE_STTS_REG_POS_TXF) |
+ (1 << SCD_QUEUE_STTS_REG_POS_WSL) |
+ SCD_QUEUE_STTS_REG_MSK);
+
+ /* enable the scheduler for this queue (only) */
+ if (txq_id == trans_pcie->cmd_queue)
+ iwl_scd_enable_set_active(trans, BIT(txq_id));
+ }
+
trans_pcie->txq[txq_id].active = true;
IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d on FIFO %d WrPtr: %d\n",
txq_id, fifo, ssn & 0xff);
}
-void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
+void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id,
+ bool configure_scd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
u32 stts_addr = trans_pcie->scd_base_addr +
@@ -1172,10 +1171,12 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
return;
}
- iwl_pcie_txq_set_inactive(trans, txq_id);
+ if (configure_scd) {
+ iwl_scd_txq_set_inactive(trans, txq_id);
- iwl_trans_write_mem(trans, stts_addr, (void *)zero_val,
- ARRAY_SIZE(zero_val));
+ iwl_trans_write_mem(trans, stts_addr, (void *)zero_val,
+ ARRAY_SIZE(zero_val));
+ }
iwl_pcie_txq_unmap(trans, txq_id);
trans_pcie->txq[txq_id].ampdu = false;