diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2010-01-08 12:32:18 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-01-12 14:02:10 -0500 |
commit | 67e2eb27958cae758ccbc86443c360ec285acc3e (patch) | |
tree | dfddb0fef0ff269269e16f42b51f64f24539c7e2 /drivers/net/wireless/mwl8k.c | |
parent | 1e9f9de3b17db3aa358f39d6932662324178350d (diff) |
mwl8k: move receive processing to tasklet
Like how TX reclaim is done in a tasklet, move receive processing
to tasklet context as well. This can have nice benefits for CPU
utilisation and throughput, especially at 3-stream rates.
(Use the same CLEAR_SEL trick as the TX reclaim tasklet does, to
avoid having to touch the interrupt mask registers.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 47 |
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 | ||
3028 | static 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); |