aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/phy_common.c
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-08-28 13:33:40 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-29 16:24:13 -0400
commit18c8adeb0244f823ba78a51e23f813fe68bc3c54 (patch)
tree1b294669d04c207d8e90b5807780fe4eb81778d9 /drivers/net/wireless/b43/phy_common.c
parentef1a628d83fc0423c36e773281162be790503168 (diff)
b43: Rewrite TX power adjustment
This patch rewrites the TX power recalculation algorithms to scale better with changed enviromnent. If there's low TX traffic, the power will be checked against the desired values every 60 seconds. If there is high TX traffic, the check is redone every 2 seconds. This improves the reaction times a lot and confuses the rate control less. It will also reduce the time it initially takes to tune to a new TX power value. With the old algorithm it could take about 30 to 45 seconds to settle to a new power value. This will happen in about two to four seconds now. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/b43/phy_common.c')
-rw-r--r--drivers/net/wireless/b43/phy_common.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 45074c05d51d..5a550a7af2e9 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -274,3 +274,94 @@ void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state)
274 phy->ops->software_rfkill(dev, state); 274 phy->ops->software_rfkill(dev, state);
275 phy->radio_on = (state == RFKILL_STATE_UNBLOCKED); 275 phy->radio_on = (state == RFKILL_STATE_UNBLOCKED);
276} 276}
277
278/**
279 * b43_phy_txpower_adjust_work - TX power workqueue.
280 *
281 * Workqueue for updating the TX power parameters in hardware.
282 */
283void b43_phy_txpower_adjust_work(struct work_struct *work)
284{
285 struct b43_wl *wl = container_of(work, struct b43_wl,
286 txpower_adjust_work);
287 struct b43_wldev *dev;
288
289 mutex_lock(&wl->mutex);
290 dev = wl->current_dev;
291
292 if (likely(dev && (b43_status(dev) >= B43_STAT_STARTED)))
293 dev->phy.ops->adjust_txpower(dev);
294
295 mutex_unlock(&wl->mutex);
296}
297
298/* Called with wl->irq_lock locked */
299void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
300{
301 struct b43_phy *phy = &dev->phy;
302 unsigned long now = jiffies;
303 enum b43_txpwr_result result;
304
305 if (!(flags & B43_TXPWR_IGNORE_TIME)) {
306 /* Check if it's time for a TXpower check. */
307 if (time_before(now, phy->next_txpwr_check_time))
308 return; /* Not yet */
309 }
310 /* The next check will be needed in two seconds, or later. */
311 phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));
312
313 if ((dev->dev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
314 (dev->dev->bus->boardinfo.type == SSB_BOARD_BU4306))
315 return; /* No software txpower adjustment needed */
316
317 result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI));
318 if (result == B43_TXPWR_RES_DONE)
319 return; /* We are done. */
320 B43_WARN_ON(result != B43_TXPWR_RES_NEED_ADJUST);
321 B43_WARN_ON(phy->ops->adjust_txpower == NULL);
322
323 /* We must adjust the transmission power in hardware.
324 * Schedule b43_phy_txpower_adjust_work(). */
325 queue_work(dev->wl->hw->workqueue, &dev->wl->txpower_adjust_work);
326}
327
328int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
329{
330 const bool is_ofdm = (shm_offset != B43_SHM_SH_TSSI_CCK);
331 unsigned int a, b, c, d;
332 unsigned int average;
333 u32 tmp;
334
335 tmp = b43_shm_read32(dev, B43_SHM_SHARED, shm_offset);
336 a = tmp & 0xFF;
337 b = (tmp >> 8) & 0xFF;
338 c = (tmp >> 16) & 0xFF;
339 d = (tmp >> 24) & 0xFF;
340 if (a == 0 || a == B43_TSSI_MAX ||
341 b == 0 || b == B43_TSSI_MAX ||
342 c == 0 || c == B43_TSSI_MAX ||
343 d == 0 || d == B43_TSSI_MAX)
344 return -ENOENT;
345 /* The values are OK. Clear them. */
346 tmp = B43_TSSI_MAX | (B43_TSSI_MAX << 8) |
347 (B43_TSSI_MAX << 16) | (B43_TSSI_MAX << 24);
348 b43_shm_write32(dev, B43_SHM_SHARED, shm_offset, tmp);
349
350 if (is_ofdm) {
351 a = (a + 32) & 0x3F;
352 b = (b + 32) & 0x3F;
353 c = (c + 32) & 0x3F;
354 d = (d + 32) & 0x3F;
355 }
356
357 /* Get the average of the values with 0.5 added to each value. */
358 average = (a + b + c + d + 2) / 4;
359 if (is_ofdm) {
360 /* Adjust for CCK-boost */
361 if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO)
362 & B43_HF_CCKBOOST)
363 average = (average >= 13) ? (average - 13) : 0;
364 }
365
366 return average;
367}