diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index eb2be0d304830cfc08e652ee20fa3893f50da30b..b28219003121bda4a78ae6dc31e777e6cfd61a15 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2399,7 +2399,7 @@ void iwlagn_stop_device(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); iwl_disable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); - iwl_synchronize_irq(priv); + trans_sync_irq(priv); /* device going down, Stop using ICT table */ iwl_disable_ict(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 598f16486aa6c9f202386bc248b702ee693af281..c91e0104a7aa7b7238e7dd107cdb11b56bf13694 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3734,7 +3734,7 @@ void __devexit iwl_remove(struct iwl_priv * priv) iwl_disable_interrupts(priv); spin_unlock_irqrestore(&priv->lock, flags); - iwl_synchronize_irq(priv); + trans_sync_irq(priv); iwl_dealloc_ucode(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 70188550a4fa07aebb312c30d458b2610bc7df27..fe5451eee82facf4964ab3c96ae3ef4cfbeb8eee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -118,14 +118,6 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv); void iwl_free_isr_ict(struct iwl_priv *priv); irqreturn_t iwl_isr_ict(int irq, void *data); -/* call this function to flush any scheduled tasklet */ -static inline void iwl_synchronize_irq(struct iwl_priv *priv) -{ - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(priv->bus.irq); - tasklet_kill(&priv->irq_tasklet); -} - static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) { hdr->op_code = cmd; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b38b00cebd2d77bde428ac61f9b4e690013d1991..cb6801c38fd57801ecfb50f1a76fe3689f61dc62 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1243,6 +1243,10 @@ struct iwl_trans; * @tx_free: frees the tx memory * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* + * @sync_irq: the upper layer will typically disable interrupt and call this + * handler. After this handler returns, it is guaranteed that all + * the ISR / tasklet etc... have finished running and the transport + * layer shall not pass any Rx. * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... */ @@ -1264,6 +1268,7 @@ struct iwl_trans_ops { struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, struct iwl_rxon_context *ctx); + void (*sync_irq)(struct iwl_priv *priv); void (*free)(struct iwl_priv *priv); }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index ecdda6d57b161db526bc8843cae5617d7cbce39c..ca96902871006a408850e763807a5643cc947e7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -705,6 +705,13 @@ static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, return 0; } +static void iwl_trans_sync_irq(struct iwl_priv *priv) +{ + /* wait to make sure we flush pending tasklet*/ + synchronize_irq(priv->bus.irq); + tasklet_kill(&priv->irq_tasklet); +} + static void iwl_trans_free(struct iwl_priv *priv) { free_irq(priv->bus.irq, priv); @@ -726,6 +733,7 @@ static const struct iwl_trans_ops trans_ops = { .get_tx_cmd = iwl_trans_get_tx_cmd, .tx = iwl_trans_tx, + .sync_irq = iwl_trans_sync_irq, .free = iwl_trans_free, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index f8133ea90aff308154f0986fd12071fb5ef8d93d..886730ecf3094df945e0fcfd69642c2f76bf737f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -115,6 +115,11 @@ static inline int trans_tx(struct iwl_priv *priv, struct sk_buff *skb, return priv->trans.ops->tx(priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); } +static inline void trans_sync_irq(struct iwl_priv *priv) +{ + priv->trans.ops->sync_irq(priv); +} + static inline void trans_free(struct iwl_priv *priv) { priv->trans.ops->free(priv);