aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2011-08-26 02:11:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-29 15:30:31 -0400
commitae2c30bfcd29c6f1215d58a1c5663d58978011b8 (patch)
tree6f21ee56e23c2311100f54f49774a3442aa2e088 /drivers/net
parentfd656935cd05f522d7db97386633f6a0d7751218 (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')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c42
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h23
3 files changed, 22 insertions, 54 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 65a6db5e9a2d..e19ff11c8dc8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3443,20 +3443,13 @@ void __devexit iwl_remove(struct iwl_priv * priv)
3443 priv->mac80211_registered = 0; 3443 priv->mac80211_registered = 0;
3444 } 3444 }
3445 3445
3446 /* Reset to low power before unloading driver. */
3447 iwl_apm_stop(priv);
3448
3449 iwl_tt_exit(priv); 3446 iwl_tt_exit(priv);
3450 3447
3451 /* make sure we flush any pending irq or 3448 /*This will stop the queues, move the device to low power state */
3452 * tasklet for the driver */ 3449 iwl_trans_stop_device(trans(priv));
3453 iwl_trans_disable_sync_irq(trans(priv));
3454 3450
3455 iwl_dealloc_ucode(priv); 3451 iwl_dealloc_ucode(priv);
3456 3452
3457 iwl_trans_rx_free(trans(priv));
3458 iwl_trans_tx_free(trans(priv));
3459
3460 iwl_eeprom_free(priv); 3453 iwl_eeprom_free(priv);
3461 3454
3462 /*netif_stop_queue(dev); */ 3455 /*netif_stop_queue(dev); */
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
557error: 557error:
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)
603error: 603error:
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
961static 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
961static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) 976static 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
1211static 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
1226static void iwl_trans_pcie_free(struct iwl_trans *trans) 1226static 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,
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 0da6ad593f05..e72e4809a410 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -88,8 +88,6 @@ struct iwl_shared;
88 * @tx_start: starts and configures all the Tx fifo - usually done once the fw 88 * @tx_start: starts and configures all the Tx fifo - usually done once the fw
89 * is alive. 89 * is alive.
90 * @stop_device:stops the whole device (embedded CPU put to reset) 90 * @stop_device:stops the whole device (embedded CPU put to reset)
91 * @rx_free: frees the rx memory
92 * @tx_free: frees the tx memory
93 * @send_cmd:send a host command 91 * @send_cmd:send a host command
94 * @send_cmd_pdu:send a host command: flags can be CMD_* 92 * @send_cmd_pdu:send a host command: flags can be CMD_*
95 * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use 93 * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use
@@ -99,9 +97,6 @@ struct iwl_shared;
99 * ready and a successful ADDBA response has been received. 97 * ready and a successful ADDBA response has been received.
100 * @txq_agg_disable: de-configure a Tx queue to send AMPDUs 98 * @txq_agg_disable: de-configure a Tx queue to send AMPDUs
101 * @kick_nic: remove the RESET from the embedded CPU and let it run 99 * @kick_nic: remove the RESET from the embedded CPU and let it run
102 * @disable_sync_irq: Disable and sync: after this handler returns, it is
103 * guaranteed that all the ISR / tasklet etc... have finished running
104 * and the transport layer shall not pass any Rx.
105 * @free: release all the ressource for the transport layer itself such as 100 * @free: release all the ressource for the transport layer itself such as
106 * irq, tasklet etc... 101 * irq, tasklet etc...
107 * @dbgfs_register: add the dbgfs files under this directory. Files will be 102 * @dbgfs_register: add the dbgfs files under this directory. Files will be
@@ -117,8 +112,6 @@ struct iwl_trans_ops {
117 int (*prepare_card_hw)(struct iwl_trans *trans); 112 int (*prepare_card_hw)(struct iwl_trans *trans);
118 void (*stop_device)(struct iwl_trans *trans); 113 void (*stop_device)(struct iwl_trans *trans);
119 void (*tx_start)(struct iwl_trans *trans); 114 void (*tx_start)(struct iwl_trans *trans);
120 void (*tx_free)(struct iwl_trans *trans);
121 void (*rx_free)(struct iwl_trans *trans);
122 115
123 int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); 116 int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
124 117
@@ -138,7 +131,6 @@ struct iwl_trans_ops {
138 131
139 void (*kick_nic)(struct iwl_trans *trans); 132 void (*kick_nic)(struct iwl_trans *trans);
140 133
141 void (*disable_sync_irq)(struct iwl_trans *trans);
142 void (*free)(struct iwl_trans *trans); 134 void (*free)(struct iwl_trans *trans);
143 135
144 int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); 136 int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
@@ -187,16 +179,6 @@ static inline void iwl_trans_tx_start(struct iwl_trans *trans)
187 trans->ops->tx_start(trans); 179 trans->ops->tx_start(trans);
188} 180}
189 181
190static inline void iwl_trans_rx_free(struct iwl_trans *trans)
191{
192 trans->ops->rx_free(trans);
193}
194
195static inline void iwl_trans_tx_free(struct iwl_trans *trans)
196{
197 trans->ops->tx_free(trans);
198}
199
200static inline int iwl_trans_send_cmd(struct iwl_trans *trans, 182static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
201 struct iwl_host_cmd *cmd) 183 struct iwl_host_cmd *cmd)
202{ 184{
@@ -247,11 +229,6 @@ static inline void iwl_trans_kick_nic(struct iwl_trans *trans)
247 trans->ops->kick_nic(trans); 229 trans->ops->kick_nic(trans);
248} 230}
249 231
250static inline void iwl_trans_disable_sync_irq(struct iwl_trans *trans)
251{
252 trans->ops->disable_sync_irq(trans);
253}
254
255static inline void iwl_trans_free(struct iwl_trans *trans) 232static inline void iwl_trans_free(struct iwl_trans *trans)
256{ 233{
257 trans->ops->free(trans); 234 trans->ops->free(trans);