diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2011-08-26 02:11:20 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-08-29 15:30:31 -0400 |
commit | ae2c30bfcd29c6f1215d58a1c5663d58978011b8 (patch) | |
tree | 6f21ee56e23c2311100f54f49774a3442aa2e088 /drivers/net/wireless/iwlwifi/iwl-trans.c | |
parent | fd656935cd05f522d7db97386633f6a0d7751218 (diff) |
iwlagn: stop the device before freeing it
When we remove the module, we free all the tx and rx resources.
Before doing that, we'd better stop the tx / rx activity. Calling
iwl_trans_stop_device in iwl_remove helps also to remove a few API
functions:
* rx_free: happens in iwl_trans_free
* tx_free: happens in iwl_trans_free
* disable_sync_irq: happens in iwl_trans_stop_device
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-trans.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.c | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index ac401b805c69..0a3dd6bfd26a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c | |||
@@ -555,7 +555,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) | |||
555 | return 0; | 555 | return 0; |
556 | 556 | ||
557 | error: | 557 | error: |
558 | iwl_trans_tx_free(trans); | 558 | iwl_trans_pcie_tx_free(trans); |
559 | 559 | ||
560 | return ret; | 560 | return ret; |
561 | } | 561 | } |
@@ -603,7 +603,7 @@ static int iwl_tx_init(struct iwl_trans *trans) | |||
603 | error: | 603 | error: |
604 | /*Upon error, free only if we allocated something */ | 604 | /*Upon error, free only if we allocated something */ |
605 | if (alloc) | 605 | if (alloc) |
606 | iwl_trans_tx_free(trans); | 606 | iwl_trans_pcie_tx_free(trans); |
607 | return ret; | 607 | return ret; |
608 | } | 608 | } |
609 | 609 | ||
@@ -958,13 +958,28 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) | |||
958 | return 0; | 958 | return 0; |
959 | } | 959 | } |
960 | 960 | ||
961 | static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) | ||
962 | { | ||
963 | unsigned long flags; | ||
964 | struct iwl_trans_pcie *trans_pcie = | ||
965 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
966 | |||
967 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
968 | iwl_disable_interrupts(trans); | ||
969 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
970 | |||
971 | /* wait to make sure we flush pending tasklet*/ | ||
972 | synchronize_irq(bus(trans)->irq); | ||
973 | tasklet_kill(&trans_pcie->irq_tasklet); | ||
974 | } | ||
975 | |||
961 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | 976 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) |
962 | { | 977 | { |
963 | /* stop and reset the on-board processor */ | 978 | /* stop and reset the on-board processor */ |
964 | iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | 979 | iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); |
965 | 980 | ||
966 | /* tell the device to stop sending interrupts */ | 981 | /* tell the device to stop sending interrupts */ |
967 | iwl_trans_disable_sync_irq(trans); | 982 | iwl_trans_pcie_disable_sync_irq(trans); |
968 | 983 | ||
969 | /* device going down, Stop using ICT table */ | 984 | /* device going down, Stop using ICT table */ |
970 | iwl_disable_ict(trans); | 985 | iwl_disable_ict(trans); |
@@ -1208,23 +1223,10 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, | |||
1208 | } | 1223 | } |
1209 | } | 1224 | } |
1210 | 1225 | ||
1211 | static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) | ||
1212 | { | ||
1213 | unsigned long flags; | ||
1214 | struct iwl_trans_pcie *trans_pcie = | ||
1215 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1216 | |||
1217 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
1218 | iwl_disable_interrupts(trans); | ||
1219 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
1220 | |||
1221 | /* wait to make sure we flush pending tasklet*/ | ||
1222 | synchronize_irq(bus(trans)->irq); | ||
1223 | tasklet_kill(&trans_pcie->irq_tasklet); | ||
1224 | } | ||
1225 | |||
1226 | static void iwl_trans_pcie_free(struct iwl_trans *trans) | 1226 | static void iwl_trans_pcie_free(struct iwl_trans *trans) |
1227 | { | 1227 | { |
1228 | iwl_trans_pcie_tx_free(trans); | ||
1229 | iwl_trans_pcie_rx_free(trans); | ||
1228 | free_irq(bus(trans)->irq, trans); | 1230 | free_irq(bus(trans)->irq, trans); |
1229 | iwl_free_isr_ict(trans); | 1231 | iwl_free_isr_ict(trans); |
1230 | trans->shrd->trans = NULL; | 1232 | trans->shrd->trans = NULL; |
@@ -1860,9 +1862,6 @@ const struct iwl_trans_ops trans_ops_pcie = { | |||
1860 | 1862 | ||
1861 | .tx_start = iwl_trans_pcie_tx_start, | 1863 | .tx_start = iwl_trans_pcie_tx_start, |
1862 | 1864 | ||
1863 | .rx_free = iwl_trans_pcie_rx_free, | ||
1864 | .tx_free = iwl_trans_pcie_tx_free, | ||
1865 | |||
1866 | .send_cmd = iwl_trans_pcie_send_cmd, | 1865 | .send_cmd = iwl_trans_pcie_send_cmd, |
1867 | .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, | 1866 | .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, |
1868 | 1867 | ||
@@ -1875,7 +1874,6 @@ const struct iwl_trans_ops trans_ops_pcie = { | |||
1875 | 1874 | ||
1876 | .kick_nic = iwl_trans_pcie_kick_nic, | 1875 | .kick_nic = iwl_trans_pcie_kick_nic, |
1877 | 1876 | ||
1878 | .disable_sync_irq = iwl_trans_pcie_disable_sync_irq, | ||
1879 | .free = iwl_trans_pcie_free, | 1877 | .free = iwl_trans_pcie_free, |
1880 | 1878 | ||
1881 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, | 1879 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, |