iwlagn: move the tasklet / irq to the transport layer

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>
This commit is contained in:
Emmanuel Grumbach 2011-07-04 08:58:19 +03:00 committed by Wey-Yi Guy
parent 47c1b49601
commit 34c1b7ba12
6 changed files with 55 additions and 29 deletions

View 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));
}
}

View 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);

View 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);

View 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 {

View 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;
}

View 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);