On Sun, Jan 19, 2014 at 10:52 PM, Hauke Mehrtens <hauke@xxxxxxxxxx> wrote: > Hi, > > when I insmoding iwldvm.ko from backports-201400117 my kernel freezes > and does not show any error message. This problem started with > backports-20140106, backports-20131224 works for me. > > I am using the Ubuntu kernel 3.5.0-45 someone else with the same problem > uses kernel 3.2.0. I am using a Intel 6300. > Someone reported that an Atheros card worked, so this is probably a > problem in iwlwifi. > patch attached
From 281e6beddf3d46661b6c1dd7a4dedfde78bdf6ed Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach <emmanuel.grumbach@xxxxxxxxx> Date: Mon, 20 Jan 2014 09:50:29 +0200 Subject: [PATCH] iwlwifi: pcie: don't panic on host commands in iwldvm My commit: None of the devices supported by iwldvm have support for shadow registers. This means that we wake the NIC when we send host commands when we increment the write pointer on the host commands ring. This happened even before my bad commit mentionned below. Since my commit below, we wake up the NIC regardless of shadow register support. This means that in iwldvm (when the NIC doesn't support shadow register), we wake up the NIC twice: pcie_enqueue_hcmd: wake up the NIC iwl_pcie_txq_inc_wr_ptr: wake up the NIC - no shadow reg support Since waking up the NIC means that we need to a spinlock, this obviously leads to a recursive spinlock and hence a freeze. Fixes: b9439491055a ("iwlwifi: pcie: keep the NIC awake when commands are in flight") Reported-by: Janusz Dziedzic <janusz.dziedzic@xxxxxxxxx> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@xxxxxxxxx> --- drivers/net/wireless/iwlwifi/pcie/tx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 270509e..0b1a93e 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -294,13 +294,14 @@ static void iwl_pcie_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, */ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u32 reg = 0; int txq_id = txq->q.id; if (txq->need_update == 0) return; - if (trans->cfg->base_params->shadow_reg_enable) { + if (trans->cfg->base_params->shadow_reg_enable || txq_id == trans_pcie->cmd_queue) { /* shadow register enabled */ iwl_write32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); -- 1.8.3.2