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 <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
e5f98f2df9
commit
e6f5b934fb
7 changed files with 262 additions and 91 deletions
|
@ -99,6 +99,8 @@
|
||||||
#define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */
|
#define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */
|
||||||
#define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */
|
#define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */
|
||||||
#define B43_MMIO_RNG 0x65A
|
#define B43_MMIO_RNG 0x65A
|
||||||
|
#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
|
||||||
|
#define B43_MMIO_IFSCTL_USE_EDCF 0x0004
|
||||||
#define B43_MMIO_POWERUP_DELAY 0x6A8
|
#define B43_MMIO_POWERUP_DELAY 0x6A8
|
||||||
|
|
||||||
/* SPROM boardflags_lo values */
|
/* SPROM boardflags_lo values */
|
||||||
|
@ -621,6 +623,35 @@ struct b43_key {
|
||||||
u8 algorithm;
|
u8 algorithm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* SHM offsets to the QOS data structures for the 4 different queues. */
|
||||||
|
#define B43_QOS_PARAMS(queue) (B43_SHM_SH_EDCFQ + \
|
||||||
|
(B43_NR_QOSPARAMS * sizeof(u16) * (queue)))
|
||||||
|
#define B43_QOS_BACKGROUND B43_QOS_PARAMS(0)
|
||||||
|
#define B43_QOS_BESTEFFORT B43_QOS_PARAMS(1)
|
||||||
|
#define B43_QOS_VIDEO B43_QOS_PARAMS(2)
|
||||||
|
#define B43_QOS_VOICE B43_QOS_PARAMS(3)
|
||||||
|
|
||||||
|
/* QOS parameter hardware data structure offsets. */
|
||||||
|
#define B43_NR_QOSPARAMS 22
|
||||||
|
enum {
|
||||||
|
B43_QOSPARAM_TXOP = 0,
|
||||||
|
B43_QOSPARAM_CWMIN,
|
||||||
|
B43_QOSPARAM_CWMAX,
|
||||||
|
B43_QOSPARAM_CWCUR,
|
||||||
|
B43_QOSPARAM_AIFS,
|
||||||
|
B43_QOSPARAM_BSLOTS,
|
||||||
|
B43_QOSPARAM_REGGAP,
|
||||||
|
B43_QOSPARAM_STATUS,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* QOS parameters for a queue. */
|
||||||
|
struct b43_qos_params {
|
||||||
|
/* The QOS parameters */
|
||||||
|
struct ieee80211_tx_queue_params p;
|
||||||
|
/* Does this need to get uploaded to hardware? */
|
||||||
|
bool need_hw_update;
|
||||||
|
};
|
||||||
|
|
||||||
struct b43_wldev;
|
struct b43_wldev;
|
||||||
|
|
||||||
/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
|
/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
|
||||||
|
@ -673,6 +704,12 @@ struct b43_wl {
|
||||||
struct sk_buff *current_beacon;
|
struct sk_buff *current_beacon;
|
||||||
bool beacon0_uploaded;
|
bool beacon0_uploaded;
|
||||||
bool beacon1_uploaded;
|
bool beacon1_uploaded;
|
||||||
|
|
||||||
|
/* The current QOS parameters for the 4 queues.
|
||||||
|
* This is protected by the irq_lock. */
|
||||||
|
struct b43_qos_params qos_params[4];
|
||||||
|
/* Workqueue for updating QOS parameters in hardware. */
|
||||||
|
struct work_struct qos_update_work;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* In-memory representation of a cached microcode file. */
|
/* In-memory representation of a cached microcode file. */
|
||||||
|
|
|
@ -291,52 +291,6 @@ static inline int request_slot(struct b43_dmaring *ring)
|
||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mac80211-queue to b43-ring mapping */
|
|
||||||
static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev,
|
|
||||||
int queue_priority)
|
|
||||||
{
|
|
||||||
struct b43_dmaring *ring;
|
|
||||||
|
|
||||||
/*FIXME: For now we always run on TX-ring-1 */
|
|
||||||
return dev->dma.tx_ring1;
|
|
||||||
|
|
||||||
/* 0 = highest priority */
|
|
||||||
switch (queue_priority) {
|
|
||||||
default:
|
|
||||||
B43_WARN_ON(1);
|
|
||||||
/* fallthrough */
|
|
||||||
case 0:
|
|
||||||
ring = dev->dma.tx_ring3;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
ring = dev->dma.tx_ring2;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
ring = dev->dma.tx_ring1;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
ring = dev->dma.tx_ring0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ring;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* b43-ring to mac80211-queue mapping */
|
|
||||||
static inline int txring_to_priority(struct b43_dmaring *ring)
|
|
||||||
{
|
|
||||||
static const u8 idx_to_prio[] = { 3, 2, 1, 0, };
|
|
||||||
unsigned int index;
|
|
||||||
|
|
||||||
/*FIXME: have only one queue, for now */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
index = ring->index;
|
|
||||||
if (B43_WARN_ON(index >= ARRAY_SIZE(idx_to_prio)))
|
|
||||||
index = 0;
|
|
||||||
return idx_to_prio[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx)
|
static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx)
|
||||||
{
|
{
|
||||||
static const u16 map64[] = {
|
static const u16 map64[] = {
|
||||||
|
@ -1272,6 +1226,37 @@ static inline int should_inject_overflow(struct b43_dmaring *ring)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Static mapping of mac80211's queues (priorities) to b43 DMA rings. */
|
||||||
|
static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev,
|
||||||
|
u8 queue_prio)
|
||||||
|
{
|
||||||
|
struct b43_dmaring *ring;
|
||||||
|
|
||||||
|
if (b43_modparam_qos) {
|
||||||
|
/* 0 = highest priority */
|
||||||
|
switch (queue_prio) {
|
||||||
|
default:
|
||||||
|
B43_WARN_ON(1);
|
||||||
|
/* fallthrough */
|
||||||
|
case 0:
|
||||||
|
ring = dev->dma.tx_ring3; /* AC_VO */
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ring = dev->dma.tx_ring2; /* AC_VI */
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ring = dev->dma.tx_ring1; /* AC_BE */
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ring = dev->dma.tx_ring0; /* AC_BK */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ring = dev->dma.tx_ring1;
|
||||||
|
|
||||||
|
return ring;
|
||||||
|
}
|
||||||
|
|
||||||
int b43_dma_tx(struct b43_wldev *dev,
|
int b43_dma_tx(struct b43_wldev *dev,
|
||||||
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
|
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
|
||||||
{
|
{
|
||||||
|
@ -1294,7 +1279,7 @@ int b43_dma_tx(struct b43_wldev *dev,
|
||||||
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
||||||
} else {
|
} else {
|
||||||
/* Decide by priority where to put this frame. */
|
/* Decide by priority where to put this frame. */
|
||||||
ring = priority_to_txring(dev, ctl->queue);
|
ring = select_ring_by_priority(dev, ctl->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&ring->lock, flags);
|
spin_lock_irqsave(&ring->lock, flags);
|
||||||
|
@ -1309,6 +1294,11 @@ int b43_dma_tx(struct b43_wldev *dev,
|
||||||
* That would be a mac80211 bug. */
|
* That would be a mac80211 bug. */
|
||||||
B43_WARN_ON(ring->stopped);
|
B43_WARN_ON(ring->stopped);
|
||||||
|
|
||||||
|
/* Assign the queue number to the ring (if not already done before)
|
||||||
|
* so TX status handling can use it. The queue to ring mapping is
|
||||||
|
* static, so we don't need to store it per frame. */
|
||||||
|
ring->queue_prio = ctl->queue;
|
||||||
|
|
||||||
err = dma_tx_fragment(ring, skb, ctl);
|
err = dma_tx_fragment(ring, skb, ctl);
|
||||||
if (unlikely(err == -ENOKEY)) {
|
if (unlikely(err == -ENOKEY)) {
|
||||||
/* Drop this packet, as we don't have the encryption key
|
/* Drop this packet, as we don't have the encryption key
|
||||||
|
@ -1325,7 +1315,7 @@ int b43_dma_tx(struct b43_wldev *dev,
|
||||||
if ((free_slots(ring) < SLOTS_PER_PACKET) ||
|
if ((free_slots(ring) < SLOTS_PER_PACKET) ||
|
||||||
should_inject_overflow(ring)) {
|
should_inject_overflow(ring)) {
|
||||||
/* This TX ring is full. */
|
/* This TX ring is full. */
|
||||||
ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring));
|
ieee80211_stop_queue(dev->wl->hw, ctl->queue);
|
||||||
ring->stopped = 1;
|
ring->stopped = 1;
|
||||||
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
|
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
|
||||||
b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
|
b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
|
||||||
|
@ -1404,7 +1394,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
||||||
dev->stats.last_tx = jiffies;
|
dev->stats.last_tx = jiffies;
|
||||||
if (ring->stopped) {
|
if (ring->stopped) {
|
||||||
B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET);
|
B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET);
|
||||||
ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring));
|
ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
|
||||||
ring->stopped = 0;
|
ring->stopped = 0;
|
||||||
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
|
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
|
||||||
b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
|
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,
|
||||||
|
|
||||||
for (i = 0; i < nr_queues; i++) {
|
for (i = 0; i < nr_queues; i++) {
|
||||||
data = &(stats->data[i]);
|
data = &(stats->data[i]);
|
||||||
ring = priority_to_txring(dev, i);
|
ring = select_ring_by_priority(dev, i);
|
||||||
|
|
||||||
spin_lock_irqsave(&ring->lock, flags);
|
spin_lock_irqsave(&ring->lock, flags);
|
||||||
data->len = ring->used_slots / SLOTS_PER_PACKET;
|
data->len = ring->used_slots / SLOTS_PER_PACKET;
|
||||||
|
|
|
@ -245,6 +245,9 @@ struct b43_dmaring {
|
||||||
enum b43_dmatype type;
|
enum b43_dmatype type;
|
||||||
/* Boolean. Is this ring stopped at ieee80211 level? */
|
/* Boolean. Is this ring stopped at ieee80211 level? */
|
||||||
bool stopped;
|
bool stopped;
|
||||||
|
/* The QOS priority assigned to this ring. Only used for TX rings.
|
||||||
|
* This is the mac80211 "queue" value. */
|
||||||
|
u8 queue_prio;
|
||||||
/* Lock, only used for TX. */
|
/* Lock, only used for TX. */
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
struct b43_wldev *dev;
|
struct b43_wldev *dev;
|
||||||
|
|
|
@ -78,6 +78,11 @@ static int modparam_nohwcrypt;
|
||||||
module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
|
module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
|
||||||
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
|
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
|
||||||
|
|
||||||
|
int b43_modparam_qos = 1;
|
||||||
|
module_param_named(qos, b43_modparam_qos, int, 0444);
|
||||||
|
MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
|
||||||
|
|
||||||
|
|
||||||
static const struct ssb_device_id b43_ssb_tbl[] = {
|
static const struct ssb_device_id b43_ssb_tbl[] = {
|
||||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
|
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
|
||||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
|
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
|
||||||
|
@ -2708,10 +2713,178 @@ out:
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Locking: wl->irq_lock */
|
||||||
|
static void b43_qos_params_upload(struct b43_wldev *dev,
|
||||||
|
const struct ieee80211_tx_queue_params *p,
|
||||||
|
u16 shm_offset)
|
||||||
|
{
|
||||||
|
u16 params[B43_NR_QOSPARAMS];
|
||||||
|
int cw_min, cw_max, aifs, bslots, tmp;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
const u16 aCWmin = 0x0001;
|
||||||
|
const u16 aCWmax = 0x03FF;
|
||||||
|
|
||||||
|
/* Calculate the default values for the parameters, if needed. */
|
||||||
|
switch (shm_offset) {
|
||||||
|
case B43_QOS_VOICE:
|
||||||
|
aifs = (p->aifs == -1) ? 2 : p->aifs;
|
||||||
|
cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 4 - 1) : p->cw_min;
|
||||||
|
cw_max = (p->cw_max == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_max;
|
||||||
|
break;
|
||||||
|
case B43_QOS_VIDEO:
|
||||||
|
aifs = (p->aifs == -1) ? 2 : p->aifs;
|
||||||
|
cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_min;
|
||||||
|
cw_max = (p->cw_max == 0) ? aCWmin : p->cw_max;
|
||||||
|
break;
|
||||||
|
case B43_QOS_BESTEFFORT:
|
||||||
|
aifs = (p->aifs == -1) ? 3 : p->aifs;
|
||||||
|
cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min;
|
||||||
|
cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max;
|
||||||
|
break;
|
||||||
|
case B43_QOS_BACKGROUND:
|
||||||
|
aifs = (p->aifs == -1) ? 7 : p->aifs;
|
||||||
|
cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min;
|
||||||
|
cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
B43_WARN_ON(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cw_min <= 0)
|
||||||
|
cw_min = aCWmin;
|
||||||
|
if (cw_max <= 0)
|
||||||
|
cw_max = aCWmin;
|
||||||
|
bslots = b43_read16(dev, B43_MMIO_RNG) % cw_min;
|
||||||
|
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
params[B43_QOSPARAM_TXOP] = p->txop * 32;
|
||||||
|
params[B43_QOSPARAM_CWMIN] = cw_min;
|
||||||
|
params[B43_QOSPARAM_CWMAX] = cw_max;
|
||||||
|
params[B43_QOSPARAM_CWCUR] = cw_min;
|
||||||
|
params[B43_QOSPARAM_AIFS] = aifs;
|
||||||
|
params[B43_QOSPARAM_BSLOTS] = bslots;
|
||||||
|
params[B43_QOSPARAM_REGGAP] = bslots + aifs;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(params); i++) {
|
||||||
|
if (i == B43_QOSPARAM_STATUS) {
|
||||||
|
tmp = b43_shm_read16(dev, B43_SHM_SHARED,
|
||||||
|
shm_offset + (i * 2));
|
||||||
|
/* Mark the parameters as updated. */
|
||||||
|
tmp |= 0x100;
|
||||||
|
b43_shm_write16(dev, B43_SHM_SHARED,
|
||||||
|
shm_offset + (i * 2),
|
||||||
|
tmp);
|
||||||
|
} else {
|
||||||
|
b43_shm_write16(dev, B43_SHM_SHARED,
|
||||||
|
shm_offset + (i * 2),
|
||||||
|
params[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the QOS parameters in hardware. */
|
||||||
|
static void b43_qos_update(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
struct b43_wl *wl = dev->wl;
|
||||||
|
struct b43_qos_params *params;
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Mapping of mac80211 queues to b43 SHM offsets. */
|
||||||
|
static const u16 qos_shm_offsets[] = {
|
||||||
|
[0] = B43_QOS_VOICE,
|
||||||
|
[1] = B43_QOS_VIDEO,
|
||||||
|
[2] = B43_QOS_BESTEFFORT,
|
||||||
|
[3] = B43_QOS_BACKGROUND,
|
||||||
|
};
|
||||||
|
BUILD_BUG_ON(ARRAY_SIZE(qos_shm_offsets) != ARRAY_SIZE(wl->qos_params));
|
||||||
|
|
||||||
|
b43_mac_suspend(dev);
|
||||||
|
spin_lock_irqsave(&wl->irq_lock, flags);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
|
||||||
|
params = &(wl->qos_params[i]);
|
||||||
|
if (params->need_hw_update) {
|
||||||
|
b43_qos_params_upload(dev, &(params->p),
|
||||||
|
qos_shm_offsets[i]);
|
||||||
|
params->need_hw_update = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&wl->irq_lock, flags);
|
||||||
|
b43_mac_enable(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void b43_qos_clear(struct b43_wl *wl)
|
||||||
|
{
|
||||||
|
struct b43_qos_params *params;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
|
||||||
|
params = &(wl->qos_params[i]);
|
||||||
|
|
||||||
|
memset(&(params->p), 0, sizeof(params->p));
|
||||||
|
params->p.aifs = -1;
|
||||||
|
params->need_hw_update = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the core's QOS capabilities */
|
||||||
|
static void b43_qos_init(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
struct b43_wl *wl = dev->wl;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Upload the current QOS parameters. */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++)
|
||||||
|
wl->qos_params[i].need_hw_update = 1;
|
||||||
|
b43_qos_update(dev);
|
||||||
|
|
||||||
|
/* Enable QOS support. */
|
||||||
|
b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
|
||||||
|
b43_write16(dev, B43_MMIO_IFSCTL,
|
||||||
|
b43_read16(dev, B43_MMIO_IFSCTL)
|
||||||
|
| B43_MMIO_IFSCTL_USE_EDCF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void b43_qos_update_work(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct b43_wl *wl = container_of(work, struct b43_wl, qos_update_work);
|
||||||
|
struct b43_wldev *dev;
|
||||||
|
|
||||||
|
mutex_lock(&wl->mutex);
|
||||||
|
dev = wl->current_dev;
|
||||||
|
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED)))
|
||||||
|
b43_qos_update(dev);
|
||||||
|
mutex_unlock(&wl->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
static int b43_op_conf_tx(struct ieee80211_hw *hw,
|
static int b43_op_conf_tx(struct ieee80211_hw *hw,
|
||||||
int queue,
|
int _queue,
|
||||||
const struct ieee80211_tx_queue_params *params)
|
const struct ieee80211_tx_queue_params *params)
|
||||||
{
|
{
|
||||||
|
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned int queue = (unsigned int)_queue;
|
||||||
|
struct b43_qos_params *p;
|
||||||
|
|
||||||
|
if (queue >= ARRAY_SIZE(wl->qos_params)) {
|
||||||
|
/* Queue not available or don't support setting
|
||||||
|
* params on this queue. Return success to not
|
||||||
|
* confuse mac80211. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&wl->irq_lock, flags);
|
||||||
|
p = &(wl->qos_params[queue]);
|
||||||
|
memcpy(&(p->p), params, sizeof(p->p));
|
||||||
|
p->need_hw_update = 1;
|
||||||
|
spin_unlock_irqrestore(&wl->irq_lock, flags);
|
||||||
|
|
||||||
|
queue_work(hw->workqueue, &wl->qos_update_work);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3732,6 +3905,7 @@ static int b43_op_start(struct ieee80211_hw *hw)
|
||||||
memset(wl->mac_addr, 0, ETH_ALEN);
|
memset(wl->mac_addr, 0, ETH_ALEN);
|
||||||
wl->filter_flags = 0;
|
wl->filter_flags = 0;
|
||||||
wl->radiotap_enabled = 0;
|
wl->radiotap_enabled = 0;
|
||||||
|
b43_qos_clear(wl);
|
||||||
|
|
||||||
/* First register RFkill.
|
/* First register RFkill.
|
||||||
* LEDs that are registered later depend on it. */
|
* LEDs that are registered later depend on it. */
|
||||||
|
@ -3773,6 +3947,7 @@ static void b43_op_stop(struct ieee80211_hw *hw)
|
||||||
struct b43_wldev *dev = wl->current_dev;
|
struct b43_wldev *dev = wl->current_dev;
|
||||||
|
|
||||||
b43_rfkill_exit(dev);
|
b43_rfkill_exit(dev);
|
||||||
|
cancel_work_sync(&(wl->qos_update_work));
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
if (b43_status(dev) >= B43_STAT_STARTED)
|
if (b43_status(dev) >= B43_STAT_STARTED)
|
||||||
|
@ -4133,7 +4308,7 @@ static int b43_wireless_init(struct ssb_device *dev)
|
||||||
hw->max_signal = 100;
|
hw->max_signal = 100;
|
||||||
hw->max_rssi = -110;
|
hw->max_rssi = -110;
|
||||||
hw->max_noise = -110;
|
hw->max_noise = -110;
|
||||||
hw->queues = 1; /* FIXME: hardware has more queues */
|
hw->queues = b43_modparam_qos ? 4 : 1;
|
||||||
SET_IEEE80211_DEV(hw, dev->dev);
|
SET_IEEE80211_DEV(hw, dev->dev);
|
||||||
if (is_valid_ether_addr(sprom->et1mac))
|
if (is_valid_ether_addr(sprom->et1mac))
|
||||||
SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
|
SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
|
||||||
|
@ -4149,6 +4324,7 @@ static int b43_wireless_init(struct ssb_device *dev)
|
||||||
spin_lock_init(&wl->shm_lock);
|
spin_lock_init(&wl->shm_lock);
|
||||||
mutex_init(&wl->mutex);
|
mutex_init(&wl->mutex);
|
||||||
INIT_LIST_HEAD(&wl->devlist);
|
INIT_LIST_HEAD(&wl->devlist);
|
||||||
|
INIT_WORK(&wl->qos_update_work, b43_qos_update_work);
|
||||||
|
|
||||||
ssb_set_devtypedata(dev, wl);
|
ssb_set_devtypedata(dev, wl);
|
||||||
b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
|
b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
|
||||||
|
|
|
@ -38,6 +38,10 @@
|
||||||
/* Magic helper macro to pad structures. Ignore those above. It's magic. */
|
/* Magic helper macro to pad structures. Ignore those above. It's magic. */
|
||||||
#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
|
#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
|
||||||
|
|
||||||
|
|
||||||
|
extern int b43_modparam_qos;
|
||||||
|
|
||||||
|
|
||||||
/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
|
/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
|
||||||
static inline u8 b43_freq_to_channel_5ghz(int freq)
|
static inline u8 b43_freq_to_channel_5ghz(int freq)
|
||||||
{
|
{
|
||||||
|
|
|
@ -705,30 +705,3 @@ void b43_tx_resume(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
b43_dma_tx_resume(dev);
|
b43_dma_tx_resume(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void upload_qos_parms(struct b43_wldev *dev,
|
|
||||||
const u16 * parms, u16 offset)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < B43_NR_QOSPARMS; i++) {
|
|
||||||
b43_shm_write16(dev, B43_SHM_SHARED,
|
|
||||||
offset + (i * 2), parms[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Initialize the QoS parameters */
|
|
||||||
void b43_qos_init(struct b43_wldev *dev)
|
|
||||||
{
|
|
||||||
/* FIXME: This function must probably be called from the mac80211
|
|
||||||
* config callback. */
|
|
||||||
return;
|
|
||||||
|
|
||||||
b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
|
|
||||||
//FIXME kill magic
|
|
||||||
b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4);
|
|
||||||
|
|
||||||
/*TODO: We might need some stack support here to get the values. */
|
|
||||||
}
|
|
||||||
|
|
|
@ -302,18 +302,6 @@ void b43_handle_hwtxstatus(struct b43_wldev *dev,
|
||||||
void b43_tx_suspend(struct b43_wldev *dev);
|
void b43_tx_suspend(struct b43_wldev *dev);
|
||||||
void b43_tx_resume(struct b43_wldev *dev);
|
void b43_tx_resume(struct b43_wldev *dev);
|
||||||
|
|
||||||
#define B43_NR_QOSPARMS 22
|
|
||||||
enum {
|
|
||||||
B43_QOSPARM_TXOP = 0,
|
|
||||||
B43_QOSPARM_CWMIN,
|
|
||||||
B43_QOSPARM_CWMAX,
|
|
||||||
B43_QOSPARM_CWCUR,
|
|
||||||
B43_QOSPARM_AIFS,
|
|
||||||
B43_QOSPARM_BSLOTS,
|
|
||||||
B43_QOSPARM_REGGAP,
|
|
||||||
B43_QOSPARM_STATUS,
|
|
||||||
};
|
|
||||||
void b43_qos_init(struct b43_wldev *dev);
|
|
||||||
|
|
||||||
/* Helper functions for converting the key-table index from "firmware-format"
|
/* Helper functions for converting the key-table index from "firmware-format"
|
||||||
* to "raw-format" and back. The firmware API changed for this at some revision.
|
* to "raw-format" and back. The firmware API changed for this at some revision.
|
||||||
|
|
Loading…
Add table
Reference in a new issue