iwlagn: move the tasklet / irq to the transport layer
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Mon, 4 Jul 2011 05:58:19 +0000 (08:58 +0300)
committerWey-Yi Guy <wey-yi.w.guy@intel.com>
Sat, 16 Jul 2011 14:36:49 +0000 (07:36 -0700)
PCIe doesn't provide any ISR registration API, whereas other buses do.
Hence, we need to move the tasklet and irq to the transport layer to allow this
flexibility.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
drivers/net/wireless/iwlwifi/iwl-agn-ict.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-agn.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-trans.c
drivers/net/wireless/iwlwifi/iwl-trans.h

index f1b40ec1c873d083c97bdd5c2e25db907af1ba33..9a2eb1e426b503a5abc46f16a89064e77e727761 100644 (file)
@@ -49,6 +49,10 @@ void iwl_free_isr_ict(struct iwl_priv *priv)
                                  priv->_agn.ict_tbl_vir,
                                  priv->_agn.ict_tbl_dma);
                priv->_agn.ict_tbl_vir = NULL;
+               memset(&priv->_agn.ict_tbl_dma, 0,
+                       sizeof(priv->_agn.ict_tbl_dma));
+               memset(&priv->_agn.aligned_ict_tbl_dma, 0,
+                       sizeof(priv->_agn.aligned_ict_tbl_dma));
        }
 }
 
index 38a1e4f58829ec151402de9d66684059981e25a2..598f16486aa6c9f202386bc248b702ee693af281 100644 (file)
@@ -625,7 +625,7 @@ static void iwl_rx_handle(struct iwl_priv *priv)
 }
 
 /* tasklet for iwlagn interrupt */
-static void iwl_irq_tasklet(struct iwl_priv *priv)
+void iwl_irq_tasklet(struct iwl_priv *priv)
 {
        u32 inta = 0;
        u32 handled = 0;
@@ -3227,9 +3227,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
        init_timer(&priv->watchdog);
        priv->watchdog.data = (unsigned long)priv;
        priv->watchdog.function = iwl_bg_watchdog;
-
-       tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-               iwl_irq_tasklet, (unsigned long)priv);
 }
 
 static void iwl_cancel_deferred_work(struct iwl_priv *priv)
@@ -3548,8 +3545,6 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
        priv->bus.ops->set_drv_data(&priv->bus, priv);
        priv->bus.dev = priv->bus.ops->get_dev(&priv->bus);
 
-       iwl_trans_register(&priv->trans);
-
        /* At this point both hw and priv are allocated. */
 
        SET_IEEE80211_DEV(hw, priv->bus.dev);
@@ -3558,6 +3553,10 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
        priv->cfg = cfg;
        priv->inta_mask = CSR_INI_SET_MASK;
 
+       err = iwl_trans_register(priv);
+       if (err)
+               goto out_free_priv;
+
        /* is antenna coupling more than 35dB ? */
        priv->bt_ant_couple_ok =
                (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
@@ -3652,15 +3651,6 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
        /********************
         * 7. Setup services
         ********************/
-       iwl_alloc_isr_ict(priv);
-
-       err = request_irq(priv->bus.irq, iwl_isr_ict, IRQF_SHARED,
-                         DRV_NAME, priv);
-       if (err) {
-               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq);
-               goto out_uninit_drv;
-       }
-
        iwl_setup_deferred_work(priv);
        iwl_setup_rx_handlers(priv);
        iwl_testmode_init(priv);
@@ -3691,19 +3681,18 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
 
        return 0;
 
- out_destroy_workqueue:
+out_destroy_workqueue:
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
-       free_irq(priv->bus.irq, priv);
-       iwl_free_isr_ict(priv);
- out_uninit_drv:
        iwl_uninit_drv(priv);
- out_free_eeprom:
+out_free_eeprom:
        iwl_eeprom_free(priv);
- out_free_traffic_mem:
+out_free_traffic_mem:
        iwl_free_traffic_mem(priv);
+       trans_free(priv);
+out_free_priv:
        ieee80211_free_hw(priv->hw);
- out:
+out:
        return err;
 }
 
@@ -3754,7 +3743,6 @@ void __devexit iwl_remove(struct iwl_priv * priv)
 
        iwl_eeprom_free(priv);
 
-
        /*netif_stop_queue(dev); */
        flush_workqueue(priv->workqueue);
 
@@ -3765,13 +3753,12 @@ void __devexit iwl_remove(struct iwl_priv * priv)
        priv->workqueue = NULL;
        iwl_free_traffic_mem(priv);
 
-       free_irq(priv->bus.irq, priv);
+       trans_free(priv);
+
        priv->bus.ops->set_drv_data(&priv->bus, NULL);
 
        iwl_uninit_drv(priv);
 
-       iwl_free_isr_ict(priv);
-
        dev_kfree_skb(priv->beacon_skb);
 
        ieee80211_free_hw(priv->hw);
index aed86c6cd933d056ec159e7f4b6de61242864c8d..70188550a4fa07aebb312c30d458b2610bc7df27 100644 (file)
@@ -188,6 +188,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
 void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
 
 /* rx */
+void iwl_irq_tasklet(struct iwl_priv *priv);
 void iwlagn_rx_queue_restock(struct iwl_priv *priv);
 void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority);
 void iwlagn_rx_replenish(struct iwl_priv *priv);
index 173fad2ab240ebaca1f17d91003e16294bc9b8b7..b38b00cebd2d77bde428ac61f9b4e690013d1991 100644 (file)
@@ -1243,6 +1243,8 @@ 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_*
+ * @free: release all the ressource for the transport layer itself such as
+ *        irq, tasklet etc...
  */
 struct iwl_trans_ops {
        int (*rx_init)(struct iwl_priv *priv);
@@ -1261,6 +1263,8 @@ struct iwl_trans_ops {
        int (*tx)(struct iwl_priv *priv, struct sk_buff *skb,
                struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu,
                struct iwl_rxon_context *ctx);
+
+       void (*free)(struct iwl_priv *priv);
 };
 
 struct iwl_trans {
index acd2a5feec93f031c5a50abc4e313893fb28d598..ecdda6d57b161db526bc8843cae5617d7cbce39c 100644 (file)
@@ -705,6 +705,12 @@ static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb,
        return 0;
 }
 
+static void iwl_trans_free(struct iwl_priv *priv)
+{
+       free_irq(priv->bus.irq, priv);
+       iwl_free_isr_ict(priv);
+}
+
 static const struct iwl_trans_ops trans_ops = {
        .rx_init = iwl_trans_rx_init,
        .rx_stop = iwl_trans_rx_stop,
@@ -719,9 +725,28 @@ static const struct iwl_trans_ops trans_ops = {
 
        .get_tx_cmd = iwl_trans_get_tx_cmd,
        .tx = iwl_trans_tx,
+
+       .free = iwl_trans_free,
 };
 
-void iwl_trans_register(struct iwl_trans *trans)
+int iwl_trans_register(struct iwl_priv *priv)
 {
-       trans->ops = &trans_ops;
+       int err;
+
+       priv->trans.ops = &trans_ops;
+
+       iwl_alloc_isr_ict(priv);
+
+       err = request_irq(priv->bus.irq, iwl_isr_ict, IRQF_SHARED,
+               DRV_NAME, priv);
+       if (err) {
+               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq);
+               iwl_free_isr_ict(priv);
+               return err;
+       }
+
+       tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+               iwl_irq_tasklet, (unsigned long)priv);
+
+       return 0;
 }
index f10bee8c1f88d55512914bcd00baf987377a201b..f8133ea90aff308154f0986fd12071fb5ef8d93d 100644 (file)
@@ -115,4 +115,9 @@ 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);
 }
 
-void iwl_trans_register(struct iwl_trans *trans);
+static inline void trans_free(struct iwl_priv *priv)
+{
+       priv->trans.ops->free(priv);
+}
+
+int iwl_trans_register(struct iwl_priv *priv);