summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi/mvm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-03-11 07:51:59 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-03-11 07:51:59 -0700
commit0cb77508252e2d0e00c5ec7e57b4be9b3f7eb24d (patch)
treecb7ed9fbc7f8fdc6e727d60e2627799a7fd7a8cc /drivers/net/wireless/iwlwifi/mvm
parentffb6a445e7cdc03d67f8b9fb2f5afaafd8260b4b (diff)
parent9026c4927254f5bea695cc3ef2e255280e6a3011 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: 1) Missing cancel of work items in mac80211 MLME, from Ben Greear. 2) Fix DMA mapping handling in iwlwifi by using coherent DMA for command headers, from Johannes Berg. 3) Decrease the amount of pressure on the page allocator by using order 1 pages less in iwlwifi, from Emmanuel Grumbach. 4) Fix mesh PS broadcast OOPS in mac80211, from Marco Porsch. 5) Don't forget to recalculate idle state in mac80211 monitor interface, from Felix Fietkau. 6) Fix varargs in netfilter conntrack handler, from Joe Perches. 7) Need to reset entire chip when command queue fills up in iwlwifi, from Emmanuel Grumbach. 8) The TX antenna value must be valid when calibrations are performed in iwlwifi, fix from Dor Shaish. 9) Don't generate netfilter audit log entries when audit is disabled, from Gao Feng. 10) Deal with DMA unit hang on e1000e during power state transitions, from Bruce Allan. 11) Remove BUILD_BUG_ON check from igb driver, from Alexander Duyck. 12) Fix lockdep warning on i2c handling of igb driver, from Carolyn Wyborny. 13) Fix several TTY handling issues in IRDA ircomm tty driver, from Peter Hurley. 14) Several QFQ packet scheduler fixes from Paolo Valente. 15) When VXLAN encapsulates on transmit, we have to reset the netfilter state. From Zang MingJie. 16) Fix jiffie check in net_rx_action() so that we really cap the processing at 2HZ. From Eric Dumazet. 17) Fix erroneous trigger of IP option space exhaustion, when routers are pre-specified and we are looking to see if we can insert a timestamp, we will have the space. From David Ward. 18) Fix various issues in benet driver wrt waiting for firmware to finish POST after resets or errors. From Gavin Shan and Sathya Perla. 19) Fix TX locking in SFC driver, from Ben Hutchings. 20) Like the VXLAN fix above, when we encap in a TUN device we have to reset the netfilter state. This should fix several strange crashes reported by Dave Jones and others. From Eric Dumazet. 21) Don't forget to clean up MAC address resources when shutting down a port in mlx4 driver, from Yan Burman. 22) Fix divide by zero in vmxnet3 driver, from Bhavesh Davda. 23) Fix device statistic regression in tg3 when the driver is using phylib, from Nithin Sujir. 24) Fix info leak in several netlink handlers, from Mathias Krause. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (79 commits) 6lowpan: Fix endianness issue in is_addr_link_local(). rrunner.c: fix possible memory leak in rr_init_one() dcbnl: fix various netlink info leaks rtnl: fix info leak on RTM_GETLINK request for VF devices bridge: fix mdb info leaks tg3: Update link_up flag for phylib devices ipv6: stop multicast forwarding to process interface scoped addresses bridging: fix rx_handlers return code netlabel: fix build problems when CONFIG_IPV6=n drivers/isdn: checkng length to be sure not memory overflow net/rds: zero last byte for strncpy bnx2x: Fix SFP+ misconfiguration in iSCSI boot scenario bnx2x: Fix intermittent long KR2 link up time macvlan: Set IFF_UNICAST_FLT flag to prevent unnecessary promisc mode. team: unsyc the devices addresses when port is removed bridge: add missing vid to br_mdb_get() Fix: sparse warning in inet_csk_prepare_forced_close afkey: fix a typo MAINTAINERS: Update qlcnic maintainers list netlabel: correctly list all the static label mappings ...
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h18
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c133
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c18
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rx.c37
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c10
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c6
7 files changed, 64 insertions, 161 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 23eebda848b0..2adb61f103f4 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -762,18 +762,20 @@ struct iwl_phy_context_cmd {
#define IWL_RX_INFO_PHY_CNT 8
#define IWL_RX_INFO_AGC_IDX 1
#define IWL_RX_INFO_RSSI_AB_IDX 2
-#define IWL_RX_INFO_RSSI_C_IDX 3
-#define IWL_OFDM_AGC_DB_MSK 0xfe00
-#define IWL_OFDM_AGC_DB_POS 9
+#define IWL_OFDM_AGC_A_MSK 0x0000007f
+#define IWL_OFDM_AGC_A_POS 0
+#define IWL_OFDM_AGC_B_MSK 0x00003f80
+#define IWL_OFDM_AGC_B_POS 7
+#define IWL_OFDM_AGC_CODE_MSK 0x3fe00000
+#define IWL_OFDM_AGC_CODE_POS 20
#define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff
-#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
#define IWL_OFDM_RSSI_A_POS 0
+#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
+#define IWL_OFDM_RSSI_ALLBAND_A_POS 8
#define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000
-#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
#define IWL_OFDM_RSSI_B_POS 16
-#define IWL_OFDM_RSSI_INBAND_C_MSK 0x00ff
-#define IWL_OFDM_RSSI_ALLBAND_C_MSK 0xff00
-#define IWL_OFDM_RSSI_C_POS 0
+#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
+#define IWL_OFDM_RSSI_ALLBAND_B_POS 24
/**
* struct iwl_rx_phy_info - phy info
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index d3d959db03a9..500f818dba04 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -79,17 +79,8 @@
#define UCODE_VALID_OK cpu_to_le32(0x1)
/* Default calibration values for WkP - set to INIT image w/o running */
-static const u8 wkp_calib_values_bb_filter[] = { 0xbf, 0x00, 0x5f, 0x00, 0x2f,
- 0x00, 0x18, 0x00 };
-static const u8 wkp_calib_values_rx_dc[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f };
-static const u8 wkp_calib_values_tx_lo[] = { 0x00, 0x00, 0x00, 0x00 };
-static const u8 wkp_calib_values_tx_iq[] = { 0xff, 0x00, 0xff, 0x00, 0x00,
- 0x00 };
-static const u8 wkp_calib_values_rx_iq[] = { 0xff, 0x00, 0x00, 0x00 };
static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 };
static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 };
-static const u8 wkp_calib_values_xtal[] = { 0xd2, 0xd2 };
struct iwl_calib_default_data {
u16 size;
@@ -99,12 +90,7 @@ struct iwl_calib_default_data {
#define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf}
static const struct iwl_calib_default_data wkp_calib_default_data[12] = {
- [5] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_dc),
- [6] = CALIB_SIZE_N_DATA(wkp_calib_values_bb_filter),
- [7] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_lo),
- [8] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq),
[9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew),
- [10] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq),
[11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew),
};
@@ -241,20 +227,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
return 0;
}
-#define IWL_HW_REV_ID_RAINBOW 0x2
-#define IWL_PROJ_TYPE_LHP 0x5
-
-static u32 iwl_mvm_build_phy_cfg(struct iwl_mvm *mvm)
-{
- struct iwl_nvm_data *data = mvm->nvm_data;
- /* Temp calls to static definitions, will be changed to CSR calls */
- u8 hw_rev_id = IWL_HW_REV_ID_RAINBOW;
- u8 project_type = IWL_PROJ_TYPE_LHP;
-
- return data->radio_cfg_dash | (data->radio_cfg_step << 2) |
- (hw_rev_id << 4) | ((project_type & 0x7f) << 6) |
- (data->valid_tx_ant << 16) | (data->valid_rx_ant << 20);
-}
static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
{
@@ -262,7 +234,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
enum iwl_ucode_type ucode_type = mvm->cur_ucode;
/* Set parameters */
- phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_build_phy_cfg(mvm));
+ phy_cfg_cmd.phy_cfg = cpu_to_le32(mvm->fw->phy_config);
phy_cfg_cmd.calib_control.event_trigger =
mvm->fw->default_calib[ucode_type].event_trigger;
phy_cfg_cmd.calib_control.flow_trigger =
@@ -275,103 +247,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
sizeof(phy_cfg_cmd), &phy_cfg_cmd);
}
-/* Starting with the new PHY DB implementation - New calibs are enabled */
-/* Value - 0x405e7 */
-#define IWL_CALIB_DEFAULT_FLOW_INIT (IWL_CALIB_CFG_XTAL_IDX |\
- IWL_CALIB_CFG_TEMPERATURE_IDX |\
- IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
- IWL_CALIB_CFG_DC_IDX |\
- IWL_CALIB_CFG_BB_FILTER_IDX |\
- IWL_CALIB_CFG_LO_LEAKAGE_IDX |\
- IWL_CALIB_CFG_TX_IQ_IDX |\
- IWL_CALIB_CFG_RX_IQ_IDX |\
- IWL_CALIB_CFG_AGC_IDX)
-
-#define IWL_CALIB_DEFAULT_EVENT_INIT 0x0
-
-/* Value 0x41567 */
-#define IWL_CALIB_DEFAULT_FLOW_RUN (IWL_CALIB_CFG_XTAL_IDX |\
- IWL_CALIB_CFG_TEMPERATURE_IDX |\
- IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
- IWL_CALIB_CFG_BB_FILTER_IDX |\
- IWL_CALIB_CFG_DC_IDX |\
- IWL_CALIB_CFG_TX_IQ_IDX |\
- IWL_CALIB_CFG_RX_IQ_IDX |\
- IWL_CALIB_CFG_SENSITIVITY_IDX |\
- IWL_CALIB_CFG_AGC_IDX)
-
-#define IWL_CALIB_DEFAULT_EVENT_RUN (IWL_CALIB_CFG_XTAL_IDX |\
- IWL_CALIB_CFG_TEMPERATURE_IDX |\
- IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
- IWL_CALIB_CFG_TX_PWR_IDX |\
- IWL_CALIB_CFG_DC_IDX |\
- IWL_CALIB_CFG_TX_IQ_IDX |\
- IWL_CALIB_CFG_SENSITIVITY_IDX)
-
-/*
- * Sets the calibrations trigger values that will be sent to the FW for runtime
- * and init calibrations.
- * The ones given in the FW TLV are not correct.
- */
-static void iwl_set_default_calib_trigger(struct iwl_mvm *mvm)
-{
- struct iwl_tlv_calib_ctrl default_calib;
-
- /*
- * WkP FW TLV calib bits are wrong, overwrite them.
- * This defines the dynamic calibrations which are implemented in the
- * uCode both for init(flow) calculation and event driven calibs.
- */
-
- /* Init Image */
- default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_INIT);
- default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_INIT);
-
- if (default_calib.event_trigger !=
- mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger)
- IWL_ERR(mvm,
- "Updating the event calib for INIT image: 0x%x -> 0x%x\n",
- mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger,
- default_calib.event_trigger);
- if (default_calib.flow_trigger !=
- mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger)
- IWL_ERR(mvm,
- "Updating the flow calib for INIT image: 0x%x -> 0x%x\n",
- mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger,
- default_calib.flow_trigger);
-
- memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_INIT],
- &default_calib, sizeof(struct iwl_tlv_calib_ctrl));
- IWL_ERR(mvm,
- "Setting uCode init calibrations event 0x%x, trigger 0x%x\n",
- default_calib.event_trigger,
- default_calib.flow_trigger);
-
- /* Run time image */
- default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_RUN);
- default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_RUN);
-
- if (default_calib.event_trigger !=
- mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger)
- IWL_ERR(mvm,
- "Updating the event calib for RT image: 0x%x -> 0x%x\n",
- mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger,
- default_calib.event_trigger);
- if (default_calib.flow_trigger !=
- mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger)
- IWL_ERR(mvm,
- "Updating the flow calib for RT image: 0x%x -> 0x%x\n",
- mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger,
- default_calib.flow_trigger);
-
- memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_REGULAR],
- &default_calib, sizeof(struct iwl_tlv_calib_ctrl));
- IWL_ERR(mvm,
- "Setting uCode runtime calibs event 0x%x, trigger 0x%x\n",
- default_calib.event_trigger,
- default_calib.flow_trigger);
-}
-
static int iwl_set_default_calibrations(struct iwl_mvm *mvm)
{
u8 cmd_raw[16]; /* holds the variable size commands */
@@ -446,8 +321,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
WARN_ON(ret);
- /* Override the calibrations from TLV and the const of fw */
- iwl_set_default_calib_trigger(mvm);
+ /* Send TX valid antennas before triggering calibrations */
+ ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
+ if (ret)
+ goto error;
/* WkP doesn't have all calibrations, need to set default values */
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 537711b10478..bdae700c769e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -80,7 +80,8 @@
#define IWL_INVALID_MAC80211_QUEUE 0xff
#define IWL_MVM_MAX_ADDRESSES 2
-#define IWL_RSSI_OFFSET 44
+/* RSSI offset for WkP */
+#define IWL_RSSI_OFFSET 50
enum iwl_mvm_tx_fifo {
IWL_MVM_TX_FIFO_BK = 0,
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index aa59adf87db3..d0f9c1e0475e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -624,12 +624,8 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
ieee80211_free_txskb(mvm->hw, skb);
}
-static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
+static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
{
- struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
-
- iwl_mvm_dump_nic_error_log(mvm);
-
iwl_abort_notification_waits(&mvm->notif_wait);
/*
@@ -663,9 +659,21 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
}
}
+static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
+{
+ struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
+ iwl_mvm_dump_nic_error_log(mvm);
+
+ iwl_mvm_nic_restart(mvm);
+}
+
static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode)
{
+ struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
WARN_ON(1);
+ iwl_mvm_nic_restart(mvm);
}
static const struct iwl_op_mode_ops iwl_mvm_ops = {
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index 3f40ab05bbd8..b0b190d0ec23 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -131,33 +131,42 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
struct iwl_rx_phy_info *phy_info)
{
- u32 rssi_a, rssi_b, rssi_c, max_rssi, agc_db;
+ int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
+ int rssi_all_band_a, rssi_all_band_b;
+ u32 agc_a, agc_b, max_agc;
u32 val;
- /* Find max rssi among 3 possible receivers.
+ /* Find max rssi among 2 possible receivers.
* These values are measured by the Digital Signal Processor (DSP).
* They should stay fairly constant even as the signal strength varies,
* if the radio's Automatic Gain Control (AGC) is working right.
* AGC value (see below) will provide the "interesting" info.
*/
+ val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
+ agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS;
+ agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS;
+ max_agc = max_t(u32, agc_a, agc_b);
+
val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]);
rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS;
rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS;
- val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_C_IDX]);
- rssi_c = (val & IWL_OFDM_RSSI_INBAND_C_MSK) >> IWL_OFDM_RSSI_C_POS;
-
- val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
- agc_db = (val & IWL_OFDM_AGC_DB_MSK) >> IWL_OFDM_AGC_DB_POS;
+ rssi_all_band_a = (val & IWL_OFDM_RSSI_ALLBAND_A_MSK) >>
+ IWL_OFDM_RSSI_ALLBAND_A_POS;
+ rssi_all_band_b = (val & IWL_OFDM_RSSI_ALLBAND_B_MSK) >>
+ IWL_OFDM_RSSI_ALLBAND_B_POS;
- max_rssi = max_t(u32, rssi_a, rssi_b);
- max_rssi = max_t(u32, max_rssi, rssi_c);
+ /*
+ * dBm = rssi dB - agc dB - constant.
+ * Higher AGC (higher radio gain) means lower signal.
+ */
+ rssi_a_dbm = rssi_a - IWL_RSSI_OFFSET - agc_a;
+ rssi_b_dbm = rssi_b - IWL_RSSI_OFFSET - agc_b;
+ max_rssi_dbm = max_t(int, rssi_a_dbm, rssi_b_dbm);
- IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
- rssi_a, rssi_b, rssi_c, max_rssi, agc_db);
+ IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
+ rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b);
- /* dBm = max_rssi dB - agc dB - constant.
- * Higher AGC (higher radio gain) means lower signal. */
- return max_rssi - agc_db - IWL_RSSI_OFFSET;
+ return max_rssi_dbm;
}
/*
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 861a7f9f8e7f..274f44e2ef60 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -770,6 +770,16 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u16 txq_id;
int err;
+
+ /*
+ * If mac80211 is cleaning its state, then say that we finished since
+ * our state has been cleared anyway.
+ */
+ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
+ ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ return 0;
+ }
+
spin_lock_bh(&mvmsta->lock);
txq_id = tid_data->txq_id;
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 6b67ce3f679c..6645efe5c03e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -607,12 +607,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
/* Single frame failure in an AMPDU queue => send BAR */
if (txq_id >= IWL_FIRST_AMPDU_QUEUE &&
- !(info->flags & IEEE80211_TX_STAT_ACK)) {
- /* there must be only one skb in the skb_list */
- WARN_ON_ONCE(skb_freed > 1 ||
- !skb_queue_empty(&skbs));
+ !(info->flags & IEEE80211_TX_STAT_ACK))
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
- }
/* W/A FW bug: seq_ctl is wrong when the queue is flushed */
if (status == TX_STATUS_FAIL_FIFO_FLUSHED) {