From 5a12a07e4495d1e4d79382e05c9d6e8b4d9fa4ec Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 1 Dec 2014 09:34:13 +0200 Subject: iwlwifi: dvm: fix flush support for old firmware Since the commit below, iwldvm sends the FLUSH command to the firmware. All the devices that use iwldvm have a firmware that expects the _v3 version of this command, besides 5150. 5150's latest available firmware still expects a _v2 version of the FLUSH command. This means that since the commit below, we had a mismatch for this specific device only. This mismatch led to the NMI below: Loaded firmware version: 8.24.2.2 Start IWL Error Log Dump: Status: 0x0000004C, count: 5 0x00000004 | NMI_INTERRUPT_WDG 0x000006F4 | uPc 0x000005BA | branchlink1 0x000006F8 | branchlink2 0x000008C2 | interruptlink1 0x00005B02 | interruptlink2 0x00000002 | data1 0x07030000 | data2 0x00000068 | line 0x3E80510C | beacon time 0x728A0EF4 | tsf low 0x0000002A | tsf hi 0x00000000 | time gp1 0x01BDC977 | time gp2 0x00000000 | time gp3 0x00010818 | uCode version 0x00000000 | hw version 0x00484704 | board version 0x00000002 | hcmd 0x2FF23080 | isr0 0x0103E000 | isr1 0x0000001A | isr2 0x1443FCC3 | isr3 0x11800112 | isr4 0x00000068 | isr_pref 0x000000D4 | wait_event 0x00000000 | l2p_control 0x00000007 | l2p_duration 0x00103040 | l2p_mhvalid 0x00000007 | l2p_addr_match 0x00000000 | lmpm_pmg_sel 0x00000000 | timestamp 0x00000200 | flow_handler This was reported here: https://bugzilla.kernel.org/show_bug.cgi?id=88961 Cc: Fixes: a0855054e59b ("iwlwifi: dvm: drop non VO frames when flushing") Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/dvm/lib.c | 47 +++++++++++++++++----------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/dvm/lib.c') diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 02e4ede..1d2223d 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c @@ -137,37 +137,38 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, */ int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk) { - struct iwl_txfifo_flush_cmd flush_cmd; - struct iwl_host_cmd cmd = { - .id = REPLY_TXFIFO_FLUSH, - .len = { sizeof(struct iwl_txfifo_flush_cmd), }, - .data = { &flush_cmd, }, + struct iwl_txfifo_flush_cmd_v3 flush_cmd_v3 = { + .flush_control = cpu_to_le16(IWL_DROP_ALL), + }; + struct iwl_txfifo_flush_cmd_v2 flush_cmd_v2 = { + .flush_control = cpu_to_le16(IWL_DROP_ALL), }; - memset(&flush_cmd, 0, sizeof(flush_cmd)); + u32 queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK | + IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | IWL_SCD_MGMT_MSK; - flush_cmd.queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK | - IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | - IWL_SCD_MGMT_MSK; if ((priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))) - flush_cmd.queue_control |= IWL_PAN_SCD_VO_MSK | - IWL_PAN_SCD_VI_MSK | - IWL_PAN_SCD_BE_MSK | - IWL_PAN_SCD_BK_MSK | - IWL_PAN_SCD_MGMT_MSK | - IWL_PAN_SCD_MULTICAST_MSK; + queue_control |= IWL_PAN_SCD_VO_MSK | IWL_PAN_SCD_VI_MSK | + IWL_PAN_SCD_BE_MSK | IWL_PAN_SCD_BK_MSK | + IWL_PAN_SCD_MGMT_MSK | + IWL_PAN_SCD_MULTICAST_MSK; if (priv->nvm_data->sku_cap_11n_enable) - flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK; + queue_control |= IWL_AGG_TX_QUEUE_MSK; if (scd_q_msk) - flush_cmd.queue_control = cpu_to_le32(scd_q_msk); - - IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", - flush_cmd.queue_control); - flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL); - - return iwl_dvm_send_cmd(priv, &cmd); + queue_control = scd_q_msk; + + IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", queue_control); + flush_cmd_v3.queue_control = cpu_to_le32(queue_control); + flush_cmd_v2.queue_control = cpu_to_le16((u16)queue_control); + + if (IWL_UCODE_API(priv->fw->ucode_ver) > 2) + return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0, + sizeof(flush_cmd_v3), + &flush_cmd_v3); + return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0, + sizeof(flush_cmd_v2), &flush_cmd_v2); } void iwlagn_dev_txfifo_flush(struct iwl_priv *priv) -- cgit v1.1