aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/phy_common.c
diff options
context:
space:
mode:
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}