Skip to content

Commit e6f5b93

Browse files
Michael Bueschlinvjw
Michael Buesch
authored andcommitted
b43: Add QOS support
This adds QOS support to the b43 driver. QOS can be disabled on driver level with a module parameter for debugging purposes. Signed-off-by: Michael Buesch <[email protected]> Signed-off-by: John W. Linville <[email protected]>
1 parent e5f98f2 commit e6f5b93

File tree

7 files changed

+262
-91
lines changed

7 files changed

+262
-91
lines changed

drivers/net/wireless/b43/b43.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@
9999
#define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */
100100
#define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */
101101
#define B43_MMIO_RNG 0x65A
102+
#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
103+
#define B43_MMIO_IFSCTL_USE_EDCF 0x0004
102104
#define B43_MMIO_POWERUP_DELAY 0x6A8
103105

104106
/* SPROM boardflags_lo values */
@@ -621,6 +623,35 @@ struct b43_key {
621623
u8 algorithm;
622624
};
623625

626+
/* SHM offsets to the QOS data structures for the 4 different queues. */
627+
#define B43_QOS_PARAMS(queue) (B43_SHM_SH_EDCFQ + \
628+
(B43_NR_QOSPARAMS * sizeof(u16) * (queue)))
629+
#define B43_QOS_BACKGROUND B43_QOS_PARAMS(0)
630+
#define B43_QOS_BESTEFFORT B43_QOS_PARAMS(1)
631+
#define B43_QOS_VIDEO B43_QOS_PARAMS(2)
632+
#define B43_QOS_VOICE B43_QOS_PARAMS(3)
633+
634+
/* QOS parameter hardware data structure offsets. */
635+
#define B43_NR_QOSPARAMS 22
636+
enum {
637+
B43_QOSPARAM_TXOP = 0,
638+
B43_QOSPARAM_CWMIN,
639+
B43_QOSPARAM_CWMAX,
640+
B43_QOSPARAM_CWCUR,
641+
B43_QOSPARAM_AIFS,
642+
B43_QOSPARAM_BSLOTS,
643+
B43_QOSPARAM_REGGAP,
644+
B43_QOSPARAM_STATUS,
645+
};
646+
647+
/* QOS parameters for a queue. */
648+
struct b43_qos_params {
649+
/* The QOS parameters */
650+
struct ieee80211_tx_queue_params p;
651+
/* Does this need to get uploaded to hardware? */
652+
bool need_hw_update;
653+
};
654+
624655
struct b43_wldev;
625656

626657
/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
@@ -673,6 +704,12 @@ struct b43_wl {
673704
struct sk_buff *current_beacon;
674705
bool beacon0_uploaded;
675706
bool beacon1_uploaded;
707+
708+
/* The current QOS parameters for the 4 queues.
709+
* This is protected by the irq_lock. */
710+
struct b43_qos_params qos_params[4];
711+
/* Workqueue for updating QOS parameters in hardware. */
712+
struct work_struct qos_update_work;
676713
};
677714

678715
/* In-memory representation of a cached microcode file. */

drivers/net/wireless/b43/dma.c

Lines changed: 40 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -291,52 +291,6 @@ static inline int request_slot(struct b43_dmaring *ring)
291291
return slot;
292292
}
293293

294-
/* Mac80211-queue to b43-ring mapping */
295-
static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev,
296-
int queue_priority)
297-
{
298-
struct b43_dmaring *ring;
299-
300-
/*FIXME: For now we always run on TX-ring-1 */
301-
return dev->dma.tx_ring1;
302-
303-
/* 0 = highest priority */
304-
switch (queue_priority) {
305-
default:
306-
B43_WARN_ON(1);
307-
/* fallthrough */
308-
case 0:
309-
ring = dev->dma.tx_ring3;
310-
break;
311-
case 1:
312-
ring = dev->dma.tx_ring2;
313-
break;
314-
case 2:
315-
ring = dev->dma.tx_ring1;
316-
break;
317-
case 3:
318-
ring = dev->dma.tx_ring0;
319-
break;
320-
}
321-
322-
return ring;
323-
}
324-
325-
/* b43-ring to mac80211-queue mapping */
326-
static inline int txring_to_priority(struct b43_dmaring *ring)
327-
{
328-
static const u8 idx_to_prio[] = { 3, 2, 1, 0, };
329-
unsigned int index;
330-
331-
/*FIXME: have only one queue, for now */
332-
return 0;
333-
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-
}
339-
340294
static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx)
341295
{
342296
static const u16 map64[] = {
@@ -1272,6 +1226,37 @@ static inline int should_inject_overflow(struct b43_dmaring *ring)
12721226
return 0;
12731227
}
12741228

1229+
/* Static mapping of mac80211's queues (priorities) to b43 DMA rings. */
1230+
static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev,
1231+
u8 queue_prio)
1232+
{
1233+
struct b43_dmaring *ring;
1234+
1235+
if (b43_modparam_qos) {
1236+
/* 0 = highest priority */
1237+
switch (queue_prio) {
1238+
default:
1239+
B43_WARN_ON(1);
1240+
/* fallthrough */
1241+
case 0:
1242+
ring = dev->dma.tx_ring3; /* AC_VO */
1243+
break;
1244+
case 1:
1245+
ring = dev->dma.tx_ring2; /* AC_VI */
1246+
break;
1247+
case 2:
1248+
ring = dev->dma.tx_ring1; /* AC_BE */
1249+
break;
1250+
case 3:
1251+
ring = dev->dma.tx_ring0; /* AC_BK */
1252+
break;
1253+
}
1254+
} else
1255+
ring = dev->dma.tx_ring1;
1256+
1257+
return ring;
1258+
}
1259+
12751260
int b43_dma_tx(struct b43_wldev *dev,
12761261
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
12771262
{
@@ -1294,7 +1279,7 @@ int b43_dma_tx(struct b43_wldev *dev,
12941279
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
12951280
} else {
12961281
/* Decide by priority where to put this frame. */
1297-
ring = priority_to_txring(dev, ctl->queue);
1282+
ring = select_ring_by_priority(dev, ctl->queue);
12981283
}
12991284

13001285
spin_lock_irqsave(&ring->lock, flags);
@@ -1309,6 +1294,11 @@ int b43_dma_tx(struct b43_wldev *dev,
13091294
* That would be a mac80211 bug. */
13101295
B43_WARN_ON(ring->stopped);
13111296

1297+
/* Assign the queue number to the ring (if not already done before)
1298+
* so TX status handling can use it. The queue to ring mapping is
1299+
* static, so we don't need to store it per frame. */
1300+
ring->queue_prio = ctl->queue;
1301+
13121302
err = dma_tx_fragment(ring, skb, ctl);
13131303
if (unlikely(err == -ENOKEY)) {
13141304
/* Drop this packet, as we don't have the encryption key
@@ -1325,7 +1315,7 @@ int b43_dma_tx(struct b43_wldev *dev,
13251315
if ((free_slots(ring) < SLOTS_PER_PACKET) ||
13261316
should_inject_overflow(ring)) {
13271317
/* This TX ring is full. */
1328-
ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring));
1318+
ieee80211_stop_queue(dev->wl->hw, ctl->queue);
13291319
ring->stopped = 1;
13301320
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
13311321
b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
@@ -1404,7 +1394,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
14041394
dev->stats.last_tx = jiffies;
14051395
if (ring->stopped) {
14061396
B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET);
1407-
ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring));
1397+
ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
14081398
ring->stopped = 0;
14091399
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
14101400
b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
@@ -1425,7 +1415,7 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev,
14251415

14261416
for (i = 0; i < nr_queues; i++) {
14271417
data = &(stats->data[i]);
1428-
ring = priority_to_txring(dev, i);
1418+
ring = select_ring_by_priority(dev, i);
14291419

14301420
spin_lock_irqsave(&ring->lock, flags);
14311421
data->len = ring->used_slots / SLOTS_PER_PACKET;

drivers/net/wireless/b43/dma.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ struct b43_dmaring {
245245
enum b43_dmatype type;
246246
/* Boolean. Is this ring stopped at ieee80211 level? */
247247
bool stopped;
248+
/* The QOS priority assigned to this ring. Only used for TX rings.
249+
* This is the mac80211 "queue" value. */
250+
u8 queue_prio;
248251
/* Lock, only used for TX. */
249252
spinlock_t lock;
250253
struct b43_wldev *dev;

0 commit comments

Comments
 (0)