]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
iwlegacy: do not grab nic access if rfkill
authorStanislaw Gruszka <sgruszka@redhat.com>
Mon, 13 Feb 2012 10:23:24 +0000 (11:23 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 22 Feb 2012 19:51:16 +0000 (14:51 -0500)
If rfkill is on il_grab_nic_access() fail and we can not write to the
various registers during stop procedure. Write to those registers
unconditionally instead.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlegacy/3945-mac.c
drivers/net/wireless/iwlegacy/3945.c
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlegacy/common.h

index 002cf4fd5a553a3297c51d9346754f3078b12ad7..ee91ab2e38583ebb70fe99e541ecfe6a8750b8b1 100644 (file)
@@ -2286,16 +2286,25 @@ __il3945_down(struct il_priv *il)
            test_bit(S_FW_ERROR, &il->status) << S_FW_ERROR |
            test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
 
+       /*
+        * We disabled and synchronized interrupt, and priv->mutex is taken, so
+        * here is the only thread which will program device registers, but
+        * still have lockdep assertions, so we are taking reg_lock.
+        */
+       spin_lock_irq(&il->reg_lock);
+       /* FIXME: il_grab_nic_access if rfkill is off ? */
+
        il3945_hw_txq_ctx_stop(il);
        il3945_hw_rxq_stop(il);
-
        /* Power-down device's busmaster DMA clocks */
-       il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+       _il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
        udelay(5);
-
        /* Stop the device, and put it in low power state */
-       il_apm_stop(il);
+       _il_apm_stop(il);
 
+       spin_unlock_irq(&il->reg_lock);
+
+       il3945_hw_txq_ctx_free(il);
 exit:
        memset(&il->card_alive, 0, sizeof(struct il_alive_resp));
 
index 95ebd43ae5371afee7c9dbfbef15adca553cba11..103251dba4592689b431364b445e0ffc13a01554 100644 (file)
@@ -1016,18 +1016,17 @@ il3945_hw_txq_ctx_stop(struct il_priv *il)
        int txq_id;
 
        /* stop SCD */
-       il_wr_prph(il, ALM_SCD_MODE_REG, 0);
-       il_wr_prph(il, ALM_SCD_TXFACT_REG, 0);
+       _il_wr_prph(il, ALM_SCD_MODE_REG, 0);
+       _il_wr_prph(il, ALM_SCD_TXFACT_REG, 0);
 
        /* reset TFD queues */
        for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
-               il_wr(il, FH39_TCSR_CONFIG(txq_id), 0x0);
-               il_poll_bit(il, FH39_TSSR_TX_STATUS,
-                           FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
-                           1000);
+               _il_wr(il, FH39_TCSR_CONFIG(txq_id), 0x0);
+               _il_poll_bit(il, FH39_TSSR_TX_STATUS,
+                            FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
+                            FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
+                            1000);
        }
-
-       il3945_hw_txq_ctx_free(il);
 }
 
 /**
@@ -2176,12 +2175,14 @@ il3945_txpower_set_from_eeprom(struct il_priv *il)
 int
 il3945_hw_rxq_stop(struct il_priv *il)
 {
-       int rc;
+       int ret;
 
-       il_wr(il, FH39_RCSR_CONFIG(0), 0);
-       rc = il_poll_bit(il, FH39_RSSR_STATUS,
-                        FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-       if (rc < 0)
+       _il_wr(il, FH39_RCSR_CONFIG(0), 0);
+       ret = _il_poll_bit(il, FH39_RSSR_STATUS,
+                          FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE,
+                          FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE,
+                          1000);
+       if (ret < 0)
                IL_ERR("Can't stop Rx DMA.\n");
 
        return 0;
index 8930e7aa13a75d8a4d6dc9a32c62edf7956206b8..5ebf7615808dc54867dc45df77e2295aebc56ff0 100644 (file)
@@ -441,11 +441,15 @@ il4965_rx_queue_free(struct il_priv *il, struct il_rx_queue *rxq)
 int
 il4965_rxq_stop(struct il_priv *il)
 {
+       int ret;
 
-       /* stop Rx DMA */
-       il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-       il_poll_bit(il, FH49_MEM_RSSR_RX_STATUS_REG,
-                   FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+       _il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+       ret = _il_poll_bit(il, FH49_MEM_RSSR_RX_STATUS_REG,
+                          FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE,
+                          FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE,
+                          1000);
+       if (ret < 0)
+               IL_ERR("Can't stop Rx DMA.\n");
 
        return 0;
 }
@@ -2031,31 +2035,10 @@ il4965_txq_ctx_reset(struct il_priv *il)
        }
 }
 
-/**
- * il4965_txq_ctx_stop - Stop all Tx DMA channels
- */
 void
-il4965_txq_ctx_stop(struct il_priv *il)
+il4965_txq_ctx_unmap(struct il_priv *il)
 {
-       int ch, txq_id;
-       unsigned long flags;
-
-       /* Turn off all Tx DMA fifos */
-       spin_lock_irqsave(&il->lock, flags);
-
-       il4965_txq_set_sched(il, 0);
-
-       /* Stop each Tx DMA channel, and wait for it to be idle */
-       for (ch = 0; ch < il->hw_params.dma_chnl_num; ch++) {
-               il_wr(il, FH49_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
-               if (il_poll_bit
-                   (il, FH49_TSSR_TX_STATUS_REG,
-                    FH49_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000))
-                       IL_ERR("Failing on timeout while stopping"
-                              " DMA channel %d [0x%08x]", ch,
-                              il_rd(il, FH49_TSSR_TX_STATUS_REG));
-       }
-       spin_unlock_irqrestore(&il->lock, flags);
+       int txq_id;
 
        if (!il->txq)
                return;
@@ -2068,6 +2051,30 @@ il4965_txq_ctx_stop(struct il_priv *il)
                        il_tx_queue_unmap(il, txq_id);
 }
 
+/**
+ * il4965_txq_ctx_stop - Stop all Tx DMA channels
+ */
+void
+il4965_txq_ctx_stop(struct il_priv *il)
+{
+       int ch, ret;
+
+       _il_wr_prph(il, IL49_SCD_TXFACT, 0);
+
+       /* Stop each Tx DMA channel, and wait for it to be idle */
+       for (ch = 0; ch < il->hw_params.dma_chnl_num; ch++) {
+               _il_wr(il, FH49_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
+               ret =
+                   _il_poll_bit(il, FH49_TSSR_TX_STATUS_REG,
+                                FH49_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
+                                FH49_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
+                                1000);
+               if (ret < 0)
+                       IL_ERR("Timeout stopping DMA channel %d [0x%08x]",
+                              ch, _il_rd(il, FH49_TSSR_TX_STATUS_REG));
+       }
+}
+
 /*
  * Find first available (lowest unused) Tx Queue, mark it "active".
  * Called only when finding queue for aggregation.
@@ -5398,19 +5405,27 @@ __il4965_down(struct il_priv *il)
            test_bit(S_FW_ERROR, &il->status) << S_FW_ERROR |
            test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
 
+       /*
+        * We disabled and synchronized interrupt, and priv->mutex is taken, so
+        * here is the only thread which will program device registers, but
+        * still have lockdep assertions, so we are taking reg_lock.
+        */
+       spin_lock_irq(&il->reg_lock);
+       /* FIXME: il_grab_nic_access if rfkill is off ? */
+
        il4965_txq_ctx_stop(il);
        il4965_rxq_stop(il);
-
        /* Power-down device's busmaster DMA clocks */
-       il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+       _il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
        udelay(5);
-
        /* Make sure (redundant) we've released our request to stay awake */
-       il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
+       _il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
        /* Stop the device, and put it in low power state */
-       il_apm_stop(il);
+       _il_apm_stop(il);
+
+       spin_unlock_irq(&il->reg_lock);
 
+       il4965_txq_ctx_unmap(il);
 exit:
        memset(&il->card_alive, 0, sizeof(struct il_alive_resp));
 
index 0d1a643d8b912cf04091b594b6878135437fde72..f343f27e50af14a1c8a66861af94624db50e1e25 100644 (file)
@@ -4126,12 +4126,12 @@ il_irq_handle_error(struct il_priv *il)
 EXPORT_SYMBOL(il_irq_handle_error);
 
 static int
-il_apm_stop_master(struct il_priv *il)
+_il_apm_stop_master(struct il_priv *il)
 {
        int ret = 0;
 
        /* stop device's busmaster DMA activity */
-       il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+       _il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
 
        ret =
            _il_poll_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
@@ -4145,15 +4145,17 @@ il_apm_stop_master(struct il_priv *il)
 }
 
 void
-il_apm_stop(struct il_priv *il)
+_il_apm_stop(struct il_priv *il)
 {
+       lockdep_assert_held(&il->reg_lock);
+
        D_INFO("Stop card, put in low power state\n");
 
        /* Stop device's DMA activity */
-       il_apm_stop_master(il);
+       _il_apm_stop_master(il);
 
        /* Reset the entire device */
-       il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+       _il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
 
        udelay(10);
 
@@ -4161,7 +4163,18 @@ il_apm_stop(struct il_priv *il)
         * Clear "initialization complete" bit to move adapter from
         * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
         */
-       il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+       _il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+}
+EXPORT_SYMBOL(_il_apm_stop);
+
+void
+il_apm_stop(struct il_priv *il)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&il->reg_lock, flags);
+       _il_apm_stop(il);
+       spin_unlock_irqrestore(&il->reg_lock, flags);
 }
 EXPORT_SYMBOL(il_apm_stop);
 
index a7794459d747288f15cf402b1da34835d84625ac..13bfd4394f91809d4f0a641263cf2dec925d696f 100644 (file)
@@ -1976,7 +1976,9 @@ il_is_ready_rf(struct il_priv *il)
 
 extern void il_send_bt_config(struct il_priv *il);
 extern int il_send_stats_request(struct il_priv *il, u8 flags, bool clear);
-void il_apm_stop(struct il_priv *il);
+extern void il_apm_stop(struct il_priv *il);
+extern void _il_apm_stop(struct il_priv *il);
+
 int il_apm_init(struct il_priv *il);
 
 int il_send_rxon_timing(struct il_priv *il);