aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2012-03-31 11:28:38 -0400
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2012-04-23 17:19:47 -0400
commit218733cf7d01fb6225e37a16818870d20c1d8771 (patch)
treef5b2afb03ced78868a9cad0599a1fb6b0aa4f8bd
parentd23f78e61f6b37159df6bfce7023500d731f61f3 (diff)
iwlwifi: provide proper API to disable all interrupts
Since the op_mode may go away, the transport needs to be able to be told not to update the op_mode at all (even for RF kill). Provide this API and use it in the proper places. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-mac80211.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c37
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h10
4 files changed, 35 insertions, 17 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 07df4326cdec..3024d8cc7aa3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1633,7 +1633,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1633 goto out_free_traffic_mem; 1633 goto out_free_traffic_mem;
1634 } 1634 }
1635 /* Reset chip to save power until we load uCode during "up". */ 1635 /* Reset chip to save power until we load uCode during "up". */
1636 iwl_trans_stop_hw(priv->trans); 1636 iwl_trans_stop_hw(priv->trans, false);
1637 1637
1638 if (iwl_eeprom_check_version(priv)) 1638 if (iwl_eeprom_check_version(priv))
1639 goto out_free_eeprom; 1639 goto out_free_eeprom;
@@ -1786,6 +1786,7 @@ void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
1786 1786
1787 dev_kfree_skb(priv->beacon_skb); 1787 dev_kfree_skb(priv->beacon_skb);
1788 1788
1789 iwl_trans_stop_hw(priv->trans, true);
1789 ieee80211_free_hw(priv->hw); 1790 ieee80211_free_hw(priv->hw);
1790} 1791}
1791 1792
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
index 2d7453de5c74..b309ede4f072 100644
--- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c
+++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
@@ -355,7 +355,7 @@ void iwlagn_mac_stop(struct ieee80211_hw *hw)
355 * even if interface is down, trans->down will leave the RF 355 * even if interface is down, trans->down will leave the RF
356 * kill interrupt enabled 356 * kill interrupt enabled
357 */ 357 */
358 iwl_trans_stop_hw(priv->trans); 358 iwl_trans_stop_hw(priv->trans, false);
359 359
360 IWL_DEBUG_MAC80211(priv, "leave\n"); 360 IWL_DEBUG_MAC80211(priv, "leave\n");
361} 361}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index 8e1cf97dfad2..2a9fb984526f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -1210,6 +1210,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
1210 iwl_disable_interrupts(trans); 1210 iwl_disable_interrupts(trans);
1211 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); 1211 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1212 1212
1213 iwl_enable_rfkill_int(trans);
1214
1213 /* wait to make sure we flush pending tasklet*/ 1215 /* wait to make sure we flush pending tasklet*/
1214 synchronize_irq(trans_pcie->irq); 1216 synchronize_irq(trans_pcie->irq);
1215 tasklet_kill(&trans_pcie->irq_tasklet); 1217 tasklet_kill(&trans_pcie->irq_tasklet);
@@ -1436,24 +1438,37 @@ error:
1436 return err; 1438 return err;
1437} 1439}
1438 1440
1439static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans) 1441static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
1442 bool op_mode_leaving)
1440{ 1443{
1441 bool hw_rfkill; 1444 bool hw_rfkill;
1445 unsigned long flags;
1446 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1442 1447
1443 iwl_apm_stop(trans); 1448 iwl_apm_stop(trans);
1444 1449
1445 iwl_write32(trans, CSR_INT, 0xFFFFFFFF); 1450 spin_lock_irqsave(&trans_pcie->irq_lock, flags);
1451 iwl_disable_interrupts(trans);
1452 spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
1446 1453
1447 /* Even if we stop the HW, we still want the RF kill interrupt */ 1454 iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
1448 iwl_enable_rfkill_int(trans);
1449 1455
1450 /* 1456 if (!op_mode_leaving) {
1451 * Check again since the RF kill state may have changed while all the 1457 /*
1452 * interrupts were disabled, in this case we couldn't receive the 1458 * Even if we stop the HW, we still want the RF kill
1453 * RF kill interrupt and update the state in the op_mode. 1459 * interrupt
1454 */ 1460 */
1455 hw_rfkill = iwl_is_rfkill_set(trans); 1461 iwl_enable_rfkill_int(trans);
1456 iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); 1462
1463 /*
1464 * Check again since the RF kill state may have changed while
1465 * all the interrupts were disabled, in this case we couldn't
1466 * receive the RF kill interrupt and update the state in the
1467 * op_mode.
1468 */
1469 hw_rfkill = iwl_is_rfkill_set(trans);
1470 iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
1471 }
1457} 1472}
1458 1473
1459static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, 1474static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 885c03659f26..d7c30325ce35 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -335,7 +335,8 @@ struct iwl_trans;
335 * @start_hw: starts the HW- from that point on, the HW can send interrupts 335 * @start_hw: starts the HW- from that point on, the HW can send interrupts
336 * May sleep 336 * May sleep
337 * @stop_hw: stops the HW- from that point on, the HW will be in low power but 337 * @stop_hw: stops the HW- from that point on, the HW will be in low power but
338 * will still issue interrupt if the HW RF kill is triggered. 338 * will still issue interrupt if the HW RF kill is triggered unless
339 * op_mode_leaving is true.
339 * May sleep 340 * May sleep
340 * @start_fw: allocates and inits all the resources for the transport 341 * @start_fw: allocates and inits all the resources for the transport
341 * layer. Also kick a fw image. 342 * layer. Also kick a fw image.
@@ -379,7 +380,7 @@ struct iwl_trans;
379struct iwl_trans_ops { 380struct iwl_trans_ops {
380 381
381 int (*start_hw)(struct iwl_trans *iwl_trans); 382 int (*start_hw)(struct iwl_trans *iwl_trans);
382 void (*stop_hw)(struct iwl_trans *iwl_trans); 383 void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving);
383 int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw); 384 int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw);
384 void (*fw_alive)(struct iwl_trans *trans); 385 void (*fw_alive)(struct iwl_trans *trans);
385 void (*stop_device)(struct iwl_trans *trans); 386 void (*stop_device)(struct iwl_trans *trans);
@@ -478,11 +479,12 @@ static inline int iwl_trans_start_hw(struct iwl_trans *trans)
478 return trans->ops->start_hw(trans); 479 return trans->ops->start_hw(trans);
479} 480}
480 481
481static inline void iwl_trans_stop_hw(struct iwl_trans *trans) 482static inline void iwl_trans_stop_hw(struct iwl_trans *trans,
483 bool op_mode_leaving)
482{ 484{
483 might_sleep(); 485 might_sleep();
484 486
485 trans->ops->stop_hw(trans); 487 trans->ops->stop_hw(trans, op_mode_leaving);
486 488
487 trans->state = IWL_TRANS_NO_FW; 489 trans->state = IWL_TRANS_NO_FW;
488} 490}