Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[cascardo/linux.git] / drivers / net / wireless / iwlwifi / iwl-core.c
index 7284100..112149e 100644 (file)
@@ -1670,9 +1670,9 @@ EXPORT_SYMBOL(iwl_set_tx_power);
 void iwl_free_isr_ict(struct iwl_priv *priv)
 {
        if (priv->ict_tbl_vir) {
-               pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) +
-                                       PAGE_SIZE, priv->ict_tbl_vir,
-                                       priv->ict_tbl_dma);
+               dma_free_coherent(&priv->pci_dev->dev,
+                                 (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+                                 priv->ict_tbl_vir, priv->ict_tbl_dma);
                priv->ict_tbl_vir = NULL;
        }
 }
@@ -1688,9 +1688,9 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv)
        if (priv->cfg->use_isr_legacy)
                return 0;
        /* allocate shrared data table */
-       priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) *
-                                                 ICT_COUNT) + PAGE_SIZE,
-                                                 &priv->ict_tbl_dma);
+       priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev,
+                                       (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+                                       &priv->ict_tbl_dma, GFP_KERNEL);
        if (!priv->ict_tbl_vir)
                return -ENOMEM;
 
@@ -3334,7 +3334,7 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
 }
 EXPORT_SYMBOL(iwl_dump_fh);
 
-void iwl_force_rf_reset(struct iwl_priv *priv)
+static void iwl_force_rf_reset(struct iwl_priv *priv)
 {
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
@@ -3356,7 +3356,50 @@ void iwl_force_rf_reset(struct iwl_priv *priv)
        iwl_internal_short_hw_scan(priv);
        return;
 }
-EXPORT_SYMBOL(iwl_force_rf_reset);
+
+
+int iwl_force_reset(struct iwl_priv *priv, int mode)
+{
+       struct iwl_force_reset *force_reset;
+
+       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+               return -EINVAL;
+
+       if (mode >= IWL_MAX_FORCE_RESET) {
+               IWL_DEBUG_INFO(priv, "invalid reset request.\n");
+               return -EINVAL;
+       }
+       force_reset = &priv->force_reset[mode];
+       force_reset->reset_request_count++;
+       if (force_reset->last_force_reset_jiffies &&
+           time_after(force_reset->last_force_reset_jiffies +
+           force_reset->reset_duration, jiffies)) {
+               IWL_DEBUG_INFO(priv, "force reset rejected\n");
+               force_reset->reset_reject_count++;
+               return -EAGAIN;
+       }
+       force_reset->reset_success_count++;
+       force_reset->last_force_reset_jiffies = jiffies;
+       IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
+       switch (mode) {
+       case IWL_RF_RESET:
+               iwl_force_rf_reset(priv);
+               break;
+       case IWL_FW_RESET:
+               IWL_ERR(priv, "On demand firmware reload\n");
+               /* Set the FW error flag -- cleared on iwl_down */
+               set_bit(STATUS_FW_ERROR, &priv->status);
+               wake_up_interruptible(&priv->wait_command_queue);
+               /*
+                * Keep the restart process from trying to send host
+                * commands by clearing the INIT status bit
+                */
+               clear_bit(STATUS_READY, &priv->status);
+               queue_work(priv->workqueue, &priv->restart);
+               break;
+       }
+       return 0;
+}
 
 #ifdef CONFIG_PM