aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/b43/b43.h10
-rw-r--r--drivers/net/wireless/b43/dma.c82
-rw-r--r--drivers/net/wireless/b43/main.c42
3 files changed, 92 insertions, 42 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index c8295b35999a..c7eea30aa949 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -170,14 +170,17 @@ enum {
170#define B43_SHM_SH_SLOTT 0x0010 /* Slot time */ 170#define B43_SHM_SH_SLOTT 0x0010 /* Slot time */
171#define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */ 171#define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */
172#define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */ 172#define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */
173/* SHM_SHARED beacon variables */ 173/* SHM_SHARED beacon/AP variables */
174#define B43_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */ 174#define B43_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */
175#define B43_SHM_SH_BTL1 0x001A /* Beacon template length 1 */ 175#define B43_SHM_SH_BTL1 0x001A /* Beacon template length 1 */
176#define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */ 176#define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */
177#define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */ 177#define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */
178#define B43_SHM_SH_DTIMP 0x0012 /* DTIP period */
179#define B43_SHM_SH_MCASTCOOKIE 0x00A8 /* Last bcast/mcast frame ID */
178#define B43_SHM_SH_SFFBLIM 0x0044 /* Short frame fallback retry limit */ 180#define B43_SHM_SH_SFFBLIM 0x0044 /* Short frame fallback retry limit */
179#define B43_SHM_SH_LFFBLIM 0x0046 /* Long frame fallback retry limit */ 181#define B43_SHM_SH_LFFBLIM 0x0046 /* Long frame fallback retry limit */
180#define B43_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word (see PHY TX control) */ 182#define B43_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word (see PHY TX control) */
183#define B43_SHM_SH_EXTNPHYCTL 0x00B0 /* Extended bytes for beacon PHY control (N) */
181/* SHM_SHARED ACK/CTS control */ 184/* SHM_SHARED ACK/CTS control */
182#define B43_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word (see PHY TX control) */ 185#define B43_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word (see PHY TX control) */
183/* SHM_SHARED probe response variables */ 186/* SHM_SHARED probe response variables */
@@ -617,9 +620,12 @@ struct b43_wl {
617 /* Pointer to the ieee80211 hardware data structure */ 620 /* Pointer to the ieee80211 hardware data structure */
618 struct ieee80211_hw *hw; 621 struct ieee80211_hw *hw;
619 622
620 spinlock_t irq_lock;
621 struct mutex mutex; 623 struct mutex mutex;
624 spinlock_t irq_lock;
625 /* Lock for LEDs access. */
622 spinlock_t leds_lock; 626 spinlock_t leds_lock;
627 /* Lock for SHM access. */
628 spinlock_t shm_lock;
623 629
624 /* We can only have one operating interface (802.11 core) 630 /* We can only have one operating interface (802.11 core)
625 * at a time. General information about this interface follows. 631 * at a time. General information about this interface follows.
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 63217b1e312d..cf92853a2180 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -37,6 +37,8 @@
37#include <linux/pci.h> 37#include <linux/pci.h>
38#include <linux/delay.h> 38#include <linux/delay.h>
39#include <linux/skbuff.h> 39#include <linux/skbuff.h>
40#include <linux/etherdevice.h>
41
40 42
41/* 32bit DMA ops. */ 43/* 32bit DMA ops. */
42static 44static
@@ -315,26 +317,24 @@ static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev,
315 case 3: 317 case 3:
316 ring = dev->dma.tx_ring0; 318 ring = dev->dma.tx_ring0;
317 break; 319 break;
318 case 4:
319 ring = dev->dma.tx_ring4;
320 break;
321 case 5:
322 ring = dev->dma.tx_ring5;
323 break;
324 } 320 }
325 321
326 return ring; 322 return ring;
327} 323}
328 324
329/* Bcm43xx-ring to mac80211-queue mapping */ 325/* b43-ring to mac80211-queue mapping */
330static inline int txring_to_priority(struct b43_dmaring *ring) 326static inline int txring_to_priority(struct b43_dmaring *ring)
331{ 327{
332 static const u8 idx_to_prio[] = { 3, 2, 1, 0, 4, 5, }; 328 static const u8 idx_to_prio[] = { 3, 2, 1, 0, };
329 unsigned int index;
333 330
334/*FIXME: have only one queue, for now */ 331/*FIXME: have only one queue, for now */
335 return 0; 332 return 0;
336 333
337 return idx_to_prio[ring->index]; 334 index = ring->index;
335 if (B43_WARN_ON(index >= ARRAY_SIZE(idx_to_prio)))
336 index = 0;
337 return idx_to_prio[index];
338} 338}
339 339
340u16 b43_dmacontroller_base(int dma64bit, int controller_idx) 340u16 b43_dmacontroller_base(int dma64bit, int controller_idx)
@@ -1043,26 +1043,30 @@ static u16 generate_cookie(struct b43_dmaring *ring, int slot)
1043 * in the lower 12 bits. 1043 * in the lower 12 bits.
1044 * Note that the cookie must never be 0, as this 1044 * Note that the cookie must never be 0, as this
1045 * is a special value used in RX path. 1045 * is a special value used in RX path.
1046 * It can also not be 0xFFFF because that is special
1047 * for multicast frames.
1046 */ 1048 */
1047 switch (ring->index) { 1049 switch (ring->index) {
1048 case 0: 1050 case 0:
1049 cookie = 0xA000; 1051 cookie = 0x1000;
1050 break; 1052 break;
1051 case 1: 1053 case 1:
1052 cookie = 0xB000; 1054 cookie = 0x2000;
1053 break; 1055 break;
1054 case 2: 1056 case 2:
1055 cookie = 0xC000; 1057 cookie = 0x3000;
1056 break; 1058 break;
1057 case 3: 1059 case 3:
1058 cookie = 0xD000; 1060 cookie = 0x4000;
1059 break; 1061 break;
1060 case 4: 1062 case 4:
1061 cookie = 0xE000; 1063 cookie = 0x5000;
1062 break; 1064 break;
1063 case 5: 1065 case 5:
1064 cookie = 0xF000; 1066 cookie = 0x6000;
1065 break; 1067 break;
1068 default:
1069 B43_WARN_ON(1);
1066 } 1070 }
1067 B43_WARN_ON(slot & ~0x0FFF); 1071 B43_WARN_ON(slot & ~0x0FFF);
1068 cookie |= (u16) slot; 1072 cookie |= (u16) slot;
@@ -1078,22 +1082,22 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
1078 struct b43_dmaring *ring = NULL; 1082 struct b43_dmaring *ring = NULL;
1079 1083
1080 switch (cookie & 0xF000) { 1084 switch (cookie & 0xF000) {
1081 case 0xA000: 1085 case 0x1000:
1082 ring = dma->tx_ring0; 1086 ring = dma->tx_ring0;
1083 break; 1087 break;
1084 case 0xB000: 1088 case 0x2000:
1085 ring = dma->tx_ring1; 1089 ring = dma->tx_ring1;
1086 break; 1090 break;
1087 case 0xC000: 1091 case 0x3000:
1088 ring = dma->tx_ring2; 1092 ring = dma->tx_ring2;
1089 break; 1093 break;
1090 case 0xD000: 1094 case 0x4000:
1091 ring = dma->tx_ring3; 1095 ring = dma->tx_ring3;
1092 break; 1096 break;
1093 case 0xE000: 1097 case 0x5000:
1094 ring = dma->tx_ring4; 1098 ring = dma->tx_ring4;
1095 break; 1099 break;
1096 case 0xF000: 1100 case 0x6000:
1097 ring = dma->tx_ring5; 1101 ring = dma->tx_ring5;
1098 break; 1102 break;
1099 default: 1103 default:
@@ -1117,6 +1121,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1117 struct b43_dmadesc_meta *meta; 1121 struct b43_dmadesc_meta *meta;
1118 struct b43_dmadesc_meta *meta_hdr; 1122 struct b43_dmadesc_meta *meta_hdr;
1119 struct sk_buff *bounce_skb; 1123 struct sk_buff *bounce_skb;
1124 u16 cookie;
1120 1125
1121#define SLOTS_PER_PACKET 2 1126#define SLOTS_PER_PACKET 2
1122 B43_WARN_ON(skb_shinfo(skb)->nr_frags); 1127 B43_WARN_ON(skb_shinfo(skb)->nr_frags);
@@ -1127,9 +1132,9 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1127 memset(meta_hdr, 0, sizeof(*meta_hdr)); 1132 memset(meta_hdr, 0, sizeof(*meta_hdr));
1128 1133
1129 header = &(ring->txhdr_cache[slot * sizeof(struct b43_txhdr_fw4)]); 1134 header = &(ring->txhdr_cache[slot * sizeof(struct b43_txhdr_fw4)]);
1135 cookie = generate_cookie(ring, slot);
1130 b43_generate_txhdr(ring->dev, header, 1136 b43_generate_txhdr(ring->dev, header,
1131 skb->data, skb->len, ctl, 1137 skb->data, skb->len, ctl, cookie);
1132 generate_cookie(ring, slot));
1133 1138
1134 meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, 1139 meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
1135 sizeof(struct b43_txhdr_fw4), 1); 1140 sizeof(struct b43_txhdr_fw4), 1);
@@ -1169,14 +1174,20 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1169 1174
1170 ops->fill_descriptor(ring, desc, meta->dmaaddr, skb->len, 0, 1, 1); 1175 ops->fill_descriptor(ring, desc, meta->dmaaddr, skb->len, 0, 1, 1);
1171 1176
1177 if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
1178 /* Tell the firmware about the cookie of the last
1179 * mcast frame, so it can clear the more-data bit in it. */
1180 b43_shm_write16(ring->dev, B43_SHM_SHARED,
1181 B43_SHM_SH_MCASTCOOKIE, cookie);
1182 }
1172 /* Now transfer the whole frame. */ 1183 /* Now transfer the whole frame. */
1173 wmb(); 1184 wmb();
1174 ops->poke_tx(ring, next_slot(ring, slot)); 1185 ops->poke_tx(ring, next_slot(ring, slot));
1175 return 0; 1186 return 0;
1176 1187
1177 out_free_bounce: 1188out_free_bounce:
1178 dev_kfree_skb_any(skb); 1189 dev_kfree_skb_any(skb);
1179 out_unmap_hdr: 1190out_unmap_hdr:
1180 unmap_descbuffer(ring, meta_hdr->dmaaddr, 1191 unmap_descbuffer(ring, meta_hdr->dmaaddr,
1181 sizeof(struct b43_txhdr_fw4), 1); 1192 sizeof(struct b43_txhdr_fw4), 1);
1182 return err; 1193 return err;
@@ -1207,10 +1218,27 @@ int b43_dma_tx(struct b43_wldev *dev,
1207 struct sk_buff *skb, struct ieee80211_tx_control *ctl) 1218 struct sk_buff *skb, struct ieee80211_tx_control *ctl)
1208{ 1219{
1209 struct b43_dmaring *ring; 1220 struct b43_dmaring *ring;
1221 struct ieee80211_hdr *hdr;
1210 int err = 0; 1222 int err = 0;
1211 unsigned long flags; 1223 unsigned long flags;
1212 1224
1213 ring = priority_to_txring(dev, ctl->queue); 1225 if (unlikely(skb->len < 2 + 2 + 6)) {
1226 /* Too short, this can't be a valid frame. */
1227 return -EINVAL;
1228 }
1229
1230 hdr = (struct ieee80211_hdr *)skb->data;
1231 if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
1232 /* The multicast ring will be sent after the DTIM */
1233 ring = dev->dma.tx_ring4;
1234 /* Set the more-data bit. Ucode will clear it on
1235 * the last frame for us. */
1236 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
1237 } else {
1238 /* Decide by priority where to put this frame. */
1239 ring = priority_to_txring(dev, ctl->queue);
1240 }
1241
1214 spin_lock_irqsave(&ring->lock, flags); 1242 spin_lock_irqsave(&ring->lock, flags);
1215 B43_WARN_ON(!ring->tx); 1243 B43_WARN_ON(!ring->tx);
1216 if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) { 1244 if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) {
@@ -1238,7 +1266,7 @@ int b43_dma_tx(struct b43_wldev *dev,
1238 b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); 1266 b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
1239 } 1267 }
1240 } 1268 }
1241 out_unlock: 1269out_unlock:
1242 spin_unlock_irqrestore(&ring->lock, flags); 1270 spin_unlock_irqrestore(&ring->lock, flags);
1243 1271
1244 return err; 1272 return err;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 84b291144c37..345ac3862e11 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -252,13 +252,12 @@ static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val)
252 b43_write32(dev, B43_MMIO_RAM_DATA, val); 252 b43_write32(dev, B43_MMIO_RAM_DATA, val);
253} 253}
254 254
255static inline 255static inline void b43_shm_control_word(struct b43_wldev *dev,
256 void b43_shm_control_word(struct b43_wldev *dev, u16 routing, u16 offset) 256 u16 routing, u16 offset)
257{ 257{
258 u32 control; 258 u32 control;
259 259
260 /* "offset" is the WORD offset. */ 260 /* "offset" is the WORD offset. */
261
262 control = routing; 261 control = routing;
263 control <<= 16; 262 control <<= 16;
264 control |= offset; 263 control |= offset;
@@ -267,8 +266,11 @@ static inline
267 266
268u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) 267u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
269{ 268{
269 struct b43_wl *wl = dev->wl;
270 unsigned long flags;
270 u32 ret; 271 u32 ret;
271 272
273 spin_lock_irqsave(&wl->shm_lock, flags);
272 if (routing == B43_SHM_SHARED) { 274 if (routing == B43_SHM_SHARED) {
273 B43_WARN_ON(offset & 0x0001); 275 B43_WARN_ON(offset & 0x0001);
274 if (offset & 0x0003) { 276 if (offset & 0x0003) {
@@ -279,20 +281,25 @@ u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
279 b43_shm_control_word(dev, routing, (offset >> 2) + 1); 281 b43_shm_control_word(dev, routing, (offset >> 2) + 1);
280 ret |= b43_read16(dev, B43_MMIO_SHM_DATA); 282 ret |= b43_read16(dev, B43_MMIO_SHM_DATA);
281 283
282 return ret; 284 goto out;
283 } 285 }
284 offset >>= 2; 286 offset >>= 2;
285 } 287 }
286 b43_shm_control_word(dev, routing, offset); 288 b43_shm_control_word(dev, routing, offset);
287 ret = b43_read32(dev, B43_MMIO_SHM_DATA); 289 ret = b43_read32(dev, B43_MMIO_SHM_DATA);
290out:
291 spin_unlock_irqrestore(&wl->shm_lock, flags);
288 292
289 return ret; 293 return ret;
290} 294}
291 295
292u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset) 296u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset)
293{ 297{
298 struct b43_wl *wl = dev->wl;
299 unsigned long flags;
294 u16 ret; 300 u16 ret;
295 301
302 spin_lock_irqsave(&wl->shm_lock, flags);
296 if (routing == B43_SHM_SHARED) { 303 if (routing == B43_SHM_SHARED) {
297 B43_WARN_ON(offset & 0x0001); 304 B43_WARN_ON(offset & 0x0001);
298 if (offset & 0x0003) { 305 if (offset & 0x0003) {
@@ -300,55 +307,63 @@ u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset)
300 b43_shm_control_word(dev, routing, offset >> 2); 307 b43_shm_control_word(dev, routing, offset >> 2);
301 ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED); 308 ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);
302 309
303 return ret; 310 goto out;
304 } 311 }
305 offset >>= 2; 312 offset >>= 2;
306 } 313 }
307 b43_shm_control_word(dev, routing, offset); 314 b43_shm_control_word(dev, routing, offset);
308 ret = b43_read16(dev, B43_MMIO_SHM_DATA); 315 ret = b43_read16(dev, B43_MMIO_SHM_DATA);
316out:
317 spin_unlock_irqrestore(&wl->shm_lock, flags);
309 318
310 return ret; 319 return ret;
311} 320}
312 321
313void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) 322void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
314{ 323{
324 struct b43_wl *wl = dev->wl;
325 unsigned long flags;
326
327 spin_lock_irqsave(&wl->shm_lock, flags);
315 if (routing == B43_SHM_SHARED) { 328 if (routing == B43_SHM_SHARED) {
316 B43_WARN_ON(offset & 0x0001); 329 B43_WARN_ON(offset & 0x0001);
317 if (offset & 0x0003) { 330 if (offset & 0x0003) {
318 /* Unaligned access */ 331 /* Unaligned access */
319 b43_shm_control_word(dev, routing, offset >> 2); 332 b43_shm_control_word(dev, routing, offset >> 2);
320 mmiowb();
321 b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, 333 b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED,
322 (value >> 16) & 0xffff); 334 (value >> 16) & 0xffff);
323 mmiowb();
324 b43_shm_control_word(dev, routing, (offset >> 2) + 1); 335 b43_shm_control_word(dev, routing, (offset >> 2) + 1);
325 mmiowb();
326 b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff); 336 b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff);
327 return; 337 goto out;
328 } 338 }
329 offset >>= 2; 339 offset >>= 2;
330 } 340 }
331 b43_shm_control_word(dev, routing, offset); 341 b43_shm_control_word(dev, routing, offset);
332 mmiowb();
333 b43_write32(dev, B43_MMIO_SHM_DATA, value); 342 b43_write32(dev, B43_MMIO_SHM_DATA, value);
343out:
344 spin_unlock_irqrestore(&wl->shm_lock, flags);
334} 345}
335 346
336void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value) 347void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
337{ 348{
349 struct b43_wl *wl = dev->wl;
350 unsigned long flags;
351
352 spin_lock_irqsave(&wl->shm_lock, flags);
338 if (routing == B43_SHM_SHARED) { 353 if (routing == B43_SHM_SHARED) {
339 B43_WARN_ON(offset & 0x0001); 354 B43_WARN_ON(offset & 0x0001);
340 if (offset & 0x0003) { 355 if (offset & 0x0003) {
341 /* Unaligned access */ 356 /* Unaligned access */
342 b43_shm_control_word(dev, routing, offset >> 2); 357 b43_shm_control_word(dev, routing, offset >> 2);
343 mmiowb();
344 b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value); 358 b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value);
345 return; 359 goto out;
346 } 360 }
347 offset >>= 2; 361 offset >>= 2;
348 } 362 }
349 b43_shm_control_word(dev, routing, offset); 363 b43_shm_control_word(dev, routing, offset);
350 mmiowb();
351 b43_write16(dev, B43_MMIO_SHM_DATA, value); 364 b43_write16(dev, B43_MMIO_SHM_DATA, value);
365out:
366 spin_unlock_irqrestore(&wl->shm_lock, flags);
352} 367}
353 368
354/* Read HostFlags */ 369/* Read HostFlags */
@@ -3931,6 +3946,7 @@ static int b43_wireless_init(struct ssb_device *dev)
3931 wl->hw = hw; 3946 wl->hw = hw;
3932 spin_lock_init(&wl->irq_lock); 3947 spin_lock_init(&wl->irq_lock);
3933 spin_lock_init(&wl->leds_lock); 3948 spin_lock_init(&wl->leds_lock);
3949 spin_lock_init(&wl->shm_lock);
3934 mutex_init(&wl->mutex); 3950 mutex_init(&wl->mutex);
3935 INIT_LIST_HEAD(&wl->devlist); 3951 INIT_LIST_HEAD(&wl->devlist);
3936 3952