aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/mwl8k.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 3f55aa0c8db3..13b0e32b051a 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -204,6 +204,9 @@ struct mwl8k_priv {
204 204
205 /* Tasklet to perform TX reclaim. */ 205 /* Tasklet to perform TX reclaim. */
206 struct tasklet_struct poll_tx_task; 206 struct tasklet_struct poll_tx_task;
207
208 /* Tasklet to perform RX. */
209 struct tasklet_struct poll_rx_task;
207}; 210};
208 211
209/* Per interface specific private data */ 212/* Per interface specific private data */
@@ -2971,14 +2974,14 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
2971 tasklet_schedule(&priv->poll_tx_task); 2974 tasklet_schedule(&priv->poll_tx_task);
2972 } 2975 }
2973 2976
2974 if (status)
2975 iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
2976
2977 if (status & MWL8K_A2H_INT_RX_READY) { 2977 if (status & MWL8K_A2H_INT_RX_READY) {
2978 while (rxq_process(hw, 0, 1)) 2978 status &= ~MWL8K_A2H_INT_RX_READY;
2979 rxq_refill(hw, 0, 1); 2979 tasklet_schedule(&priv->poll_rx_task);
2980 } 2980 }
2981 2981
2982 if (status)
2983 iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
2984
2982 if (status & MWL8K_A2H_INT_OPC_DONE) { 2985 if (status & MWL8K_A2H_INT_OPC_DONE) {
2983 if (priv->hostcmd_wait != NULL) 2986 if (priv->hostcmd_wait != NULL)
2984 complete(priv->hostcmd_wait); 2987 complete(priv->hostcmd_wait);
@@ -3022,6 +3025,24 @@ static void mwl8k_tx_poll(unsigned long data)
3022 } 3025 }
3023} 3026}
3024 3027
3028static void mwl8k_rx_poll(unsigned long data)
3029{
3030 struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
3031 struct mwl8k_priv *priv = hw->priv;
3032 int limit;
3033
3034 limit = 32;
3035 limit -= rxq_process(hw, 0, limit);
3036 limit -= rxq_refill(hw, 0, limit);
3037
3038 if (limit) {
3039 writel(~MWL8K_A2H_INT_RX_READY,
3040 priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
3041 } else {
3042 tasklet_schedule(&priv->poll_rx_task);
3043 }
3044}
3045
3025 3046
3026/* 3047/*
3027 * Core driver operations. 3048 * Core driver operations.
@@ -3057,8 +3078,9 @@ static int mwl8k_start(struct ieee80211_hw *hw)
3057 return -EIO; 3078 return -EIO;
3058 } 3079 }
3059 3080
3060 /* Enable tx reclaim tasklet */ 3081 /* Enable TX reclaim and RX tasklets. */
3061 tasklet_enable(&priv->poll_tx_task); 3082 tasklet_enable(&priv->poll_tx_task);
3083 tasklet_enable(&priv->poll_rx_task);
3062 3084
3063 /* Enable interrupts */ 3085 /* Enable interrupts */
3064 iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); 3086 iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
@@ -3092,6 +3114,7 @@ static int mwl8k_start(struct ieee80211_hw *hw)
3092 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); 3114 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
3093 free_irq(priv->pdev->irq, hw); 3115 free_irq(priv->pdev->irq, hw);
3094 tasklet_disable(&priv->poll_tx_task); 3116 tasklet_disable(&priv->poll_tx_task);
3117 tasklet_disable(&priv->poll_rx_task);
3095 } 3118 }
3096 3119
3097 return rc; 3120 return rc;
@@ -3115,8 +3138,9 @@ static void mwl8k_stop(struct ieee80211_hw *hw)
3115 if (priv->beacon_skb != NULL) 3138 if (priv->beacon_skb != NULL)
3116 dev_kfree_skb(priv->beacon_skb); 3139 dev_kfree_skb(priv->beacon_skb);
3117 3140
3118 /* Stop tx reclaim tasklet */ 3141 /* Stop TX reclaim and RX tasklets. */
3119 tasklet_disable(&priv->poll_tx_task); 3142 tasklet_disable(&priv->poll_tx_task);
3143 tasklet_disable(&priv->poll_rx_task);
3120 3144
3121 /* Return all skbs to mac80211 */ 3145 /* Return all skbs to mac80211 */
3122 for (i = 0; i < MWL8K_TX_QUEUES; i++) 3146 for (i = 0; i < MWL8K_TX_QUEUES; i++)
@@ -3873,9 +3897,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
3873 /* Finalize join worker */ 3897 /* Finalize join worker */
3874 INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); 3898 INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
3875 3899
3876 /* TX reclaim tasklet */ 3900 /* TX reclaim and RX tasklets. */
3877 tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); 3901 tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw);
3878 tasklet_disable(&priv->poll_tx_task); 3902 tasklet_disable(&priv->poll_tx_task);
3903 tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw);
3904 tasklet_disable(&priv->poll_rx_task);
3879 3905
3880 /* Power management cookie */ 3906 /* Power management cookie */
3881 priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); 3907 priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma);
@@ -3904,7 +3930,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
3904 3930
3905 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); 3931 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
3906 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); 3932 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
3907 iowrite32(MWL8K_A2H_INT_TX_DONE, 3933 iowrite32(MWL8K_A2H_INT_TX_DONE | MWL8K_A2H_INT_RX_READY,
3908 priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); 3934 priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL);
3909 iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); 3935 iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
3910 3936
@@ -4032,8 +4058,9 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev)
4032 4058
4033 ieee80211_unregister_hw(hw); 4059 ieee80211_unregister_hw(hw);
4034 4060
4035 /* Remove tx reclaim tasklet */ 4061 /* Remove TX reclaim and RX tasklets. */
4036 tasklet_kill(&priv->poll_tx_task); 4062 tasklet_kill(&priv->poll_tx_task);
4063 tasklet_kill(&priv->poll_rx_task);
4037 4064
4038 /* Stop hardware */ 4065 /* Stop hardware */
4039 mwl8k_hw_reset(priv); 4066 mwl8k_hw_reset(priv);