b43: Remove unnecessary MMIO accesses in the interrupt hotpath.
[openwrt-10.03/.git] / package / mac80211 / patches / 530-b43-optimize-hotpath-mmio.patch
1 Index: compat-wireless-2009-03-31/drivers/net/wireless/b43/b43.h
2 ===================================================================
3 --- compat-wireless-2009-03-31.orig/drivers/net/wireless/b43/b43.h      2009-04-08 20:27:37.000000000 +0200
4 +++ compat-wireless-2009-03-31/drivers/net/wireless/b43/b43.h   2009-04-08 20:28:14.000000000 +0200
5 @@ -778,8 +778,8 @@ struct b43_wldev {
6         /* Reason code of the last interrupt. */
7         u32 irq_reason;
8         u32 dma_reason[6];
9 -       /* saved irq enable/disable state bitfield. */
10 -       u32 irq_savedstate;
11 +       /* The currently active generic-interrupt mask. */
12 +       u32 irq_mask;
13         /* Link Quality calculation context. */
14         struct b43_noise_calculation noisecalc;
15         /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
16 Index: compat-wireless-2009-03-31/drivers/net/wireless/b43/main.c
17 ===================================================================
18 --- compat-wireless-2009-03-31.orig/drivers/net/wireless/b43/main.c     2009-04-08 20:22:24.000000000 +0200
19 +++ compat-wireless-2009-03-31/drivers/net/wireless/b43/main.c  2009-04-08 20:41:43.000000000 +0200
20 @@ -673,32 +673,6 @@ static void b43_short_slot_timing_disabl
21         b43_set_slot_time(dev, 20);
22  }
23  
24 -/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
25 - * Returns the _previously_ enabled IRQ mask.
26 - */
27 -static inline u32 b43_interrupt_enable(struct b43_wldev *dev, u32 mask)
28 -{
29 -       u32 old_mask;
30 -
31 -       old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
32 -       b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask | mask);
33 -
34 -       return old_mask;
35 -}
36 -
37 -/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
38 - * Returns the _previously_ enabled IRQ mask.
39 - */
40 -static inline u32 b43_interrupt_disable(struct b43_wldev *dev, u32 mask)
41 -{
42 -       u32 old_mask;
43 -
44 -       old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
45 -       b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
46 -
47 -       return old_mask;
48 -}
49 -
50  /* Synchronize IRQ top- and bottom-half.
51   * IRQs must be masked before calling this.
52   * This must not be called with the irq_lock held.
53 @@ -1593,7 +1567,7 @@ static void handle_irq_beacon(struct b43
54         /* This is the bottom half of the asynchronous beacon update. */
55  
56         /* Ignore interrupt in the future. */
57 -       dev->irq_savedstate &= ~B43_IRQ_BEACON;
58 +       dev->irq_mask &= ~B43_IRQ_BEACON;
59  
60         cmd = b43_read32(dev, B43_MMIO_MACCMD);
61         beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
62 @@ -1602,7 +1576,7 @@ static void handle_irq_beacon(struct b43
63         /* Schedule interrupt manually, if busy. */
64         if (beacon0_valid && beacon1_valid) {
65                 b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
66 -               dev->irq_savedstate |= B43_IRQ_BEACON;
67 +               dev->irq_mask |= B43_IRQ_BEACON;
68                 return;
69         }
70  
71 @@ -1641,11 +1615,9 @@ static void b43_beacon_update_trigger_wo
72         if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
73                 spin_lock_irq(&wl->irq_lock);
74                 /* update beacon right away or defer to irq */
75 -               dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
76                 handle_irq_beacon(dev);
77                 /* The handler might have updated the IRQ mask. */
78 -               b43_write32(dev, B43_MMIO_GEN_IRQ_MASK,
79 -                           dev->irq_savedstate);
80 +               b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
81                 mmiowb();
82                 spin_unlock_irq(&wl->irq_lock);
83         }
84 @@ -1879,7 +1851,7 @@ static void b43_interrupt_tasklet(struct
85         if (reason & B43_IRQ_TX_OK)
86                 handle_irq_transmit_status(dev);
87  
88 -       b43_interrupt_enable(dev, dev->irq_savedstate);
89 +       b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
90         mmiowb();
91         spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
92  }
93 @@ -1893,7 +1865,9 @@ static void b43_interrupt_ack(struct b43
94         b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);
95         b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);
96         b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);
97 +/* Unused ring
98         b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
99 +*/
100  }
101  
102  /* Interrupt handler top-half */
103 @@ -1903,18 +1877,19 @@ static irqreturn_t b43_interrupt_handler
104         struct b43_wldev *dev = dev_id;
105         u32 reason;
106  
107 -       if (!dev)
108 -               return IRQ_NONE;
109 +       B43_WARN_ON(!dev);
110  
111         spin_lock(&dev->wl->irq_lock);
112  
113 -       if (b43_status(dev) < B43_STAT_STARTED)
114 +       if (unlikely(b43_status(dev) < B43_STAT_STARTED)) {
115 +               /* This can only happen on shared IRQ lines. */
116                 goto out;
117 +       }
118         reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
119         if (reason == 0xffffffff)       /* shared IRQ */
120                 goto out;
121         ret = IRQ_HANDLED;
122 -       reason &= b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
123 +       reason &= dev->irq_mask;
124         if (!reason)
125                 goto out;
126  
127 @@ -1928,16 +1903,18 @@ static irqreturn_t b43_interrupt_handler
128             & 0x0001DC00;
129         dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON)
130             & 0x0000DC00;
131 +/* Unused ring
132         dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON)
133             & 0x0000DC00;
134 +*/
135  
136         b43_interrupt_ack(dev, reason);
137         /* disable all IRQs. They are enabled again in the bottom half. */
138 -       dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
139 +       b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
140         /* save the reason code and call our bottom half. */
141         dev->irq_reason = reason;
142         tasklet_schedule(&dev->isr_tasklet);
143 -      out:
144 +out:
145         mmiowb();
146         spin_unlock(&dev->wl->irq_lock);
147  
148 @@ -3799,7 +3776,7 @@ static void b43_wireless_core_stop(struc
149          * setting the status to INITIALIZED, as the interrupt handler
150          * won't care about IRQs then. */
151         spin_lock_irqsave(&wl->irq_lock, flags);
152 -       dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
153 +       b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
154         b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */
155         spin_unlock_irqrestore(&wl->irq_lock, flags);
156         b43_synchronize_irq(dev);
157 @@ -3840,7 +3817,7 @@ static int b43_wireless_core_start(struc
158  
159         /* Start data flow (TX/RX). */
160         b43_mac_enable(dev);
161 -       b43_interrupt_enable(dev, dev->irq_savedstate);
162 +       b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
163  
164         /* Start maintainance work */
165         b43_periodic_tasks_setup(dev);
166 @@ -3998,9 +3975,9 @@ static void setup_struct_wldev_for_init(
167         /* IRQ related flags */
168         dev->irq_reason = 0;
169         memset(dev->dma_reason, 0, sizeof(dev->dma_reason));
170 -       dev->irq_savedstate = B43_IRQ_MASKTEMPLATE;
171 +       dev->irq_mask = B43_IRQ_MASKTEMPLATE;
172         if (b43_modparam_verbose < B43_VERBOSITY_DEBUG)
173 -               dev->irq_savedstate &= ~B43_IRQ_PHY_TXERR;
174 +               dev->irq_mask &= ~B43_IRQ_PHY_TXERR;
175  
176         dev->mac_suspended = 1;
177