Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 111317
b: refs/heads/master
c: 18c8ade
h: refs/heads/master
i:
  111315: 774f88a
v: v3
  • Loading branch information
Michael Buesch authored and John W. Linville committed Aug 29, 2008
1 parent 9bda261 commit 2126ba1
Show file tree
Hide file tree
Showing 10 changed files with 342 additions and 122 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ef1a628d83fc0423c36e773281162be790503168
refs/heads/master: 18c8adeb0244f823ba78a51e23f813fe68bc3c54
10 changes: 10 additions & 0 deletions trunk/drivers/net/wireless/b43/b43.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ enum {
#define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */
#define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5Ghz channel */
#define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */
/* TSSI information */
#define B43_SHM_SH_TSSI_CCK 0x0058 /* TSSI for last 4 CCK frames (32bit) */
#define B43_SHM_SH_TSSI_OFDM_A 0x0068 /* TSSI for last 4 OFDM frames (32bit) */
#define B43_SHM_SH_TSSI_OFDM_G 0x0070 /* TSSI for last 4 OFDM frames (32bit) */
#define B43_TSSI_MAX 0x7F /* Max value for one TSSI value */
/* SHM_SHARED TX FIFO variables */
#define B43_SHM_SH_SIZE01 0x0098 /* TX FIFO size for FIFO 0 (low) and 1 (high) */
#define B43_SHM_SH_SIZE23 0x009A /* TX FIFO size for FIFO 2 and 3 */
Expand Down Expand Up @@ -648,6 +653,11 @@ struct b43_wl {
struct b43_qos_params qos_params[4];
/* Workqueue for updating QOS parameters in hardware. */
struct work_struct qos_update_work;

/* Work for adjustment of the transmission power.
* This is scheduled when we determine that the actual TX output
* power doesn't match what we want. */
struct work_struct txpower_adjust_work;
};

/* In-memory representation of a cached microcode file. */
Expand Down
18 changes: 13 additions & 5 deletions trunk/drivers/net/wireless/b43/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2805,6 +2805,9 @@ static void b43_periodic_every60sec(struct b43_wldev *dev)

if (ops->pwork_60sec)
ops->pwork_60sec(dev);

/* Force check the TX power emission now. */
b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME);
}

static void b43_periodic_every30sec(struct b43_wldev *dev)
Expand Down Expand Up @@ -2835,8 +2838,6 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
if (phy->ops->pwork_15sec)
phy->ops->pwork_15sec(dev);

phy->ops->xmitpower(dev);

atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
wmb();
}
Expand Down Expand Up @@ -3382,10 +3383,13 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)

/* Adjust the desired TX power level. */
if (conf->power_level != 0) {
if (conf->power_level != phy->power_level) {
phy->power_level = conf->power_level;
phy->ops->xmitpower(dev);
spin_lock_irqsave(&wl->irq_lock, flags);
if (conf->power_level != phy->desired_txpower) {
phy->desired_txpower = conf->power_level;
b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME |
B43_TXPWR_IGNORE_TSSI);
}
spin_unlock_irqrestore(&wl->irq_lock, flags);
}

/* Antennas for RX and management frame TX. */
Expand Down Expand Up @@ -3785,6 +3789,7 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
struct b43_phy *phy)
{
phy->hardware_power_control = !!modparam_hwpctl;
phy->next_txpwr_check_time = jiffies;
/* PHY TX errors counter. */
atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
}
Expand Down Expand Up @@ -4204,6 +4209,8 @@ static void b43_op_stop(struct ieee80211_hw *hw)
b43_wireless_core_stop(dev);
b43_wireless_core_exit(dev);
mutex_unlock(&wl->mutex);

cancel_work_sync(&(wl->txpower_adjust_work));
}

static int b43_op_set_retry_limit(struct ieee80211_hw *hw,
Expand Down Expand Up @@ -4581,6 +4588,7 @@ static int b43_wireless_init(struct ssb_device *dev)
INIT_LIST_HEAD(&wl->devlist);
INIT_WORK(&wl->qos_update_work, b43_qos_update_work);
INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);

ssb_set_devtypedata(dev, wl);
b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
Expand Down
15 changes: 9 additions & 6 deletions trunk/drivers/net/wireless/b43/nphy.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,16 @@ void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
{//TODO
}

void b43_nphy_xmitpower(struct b43_wldev *dev)
static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
{//TODO
}

static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
bool ignore_tssi)
{//TODO
return B43_TXPWR_RES_DONE;
}

static void b43_chantab_radio_upload(struct b43_wldev *dev,
const struct b43_nphy_channeltab_entry *e)
{
Expand Down Expand Up @@ -602,10 +608,6 @@ static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
return 36;
}

static void b43_nphy_op_xmitpower(struct b43_wldev *dev)
{//TODO
}

const struct b43_phy_operations b43_phyops_n = {
.allocate = b43_nphy_op_allocate,
.init = b43_nphy_op_init,
Expand All @@ -617,5 +619,6 @@ const struct b43_phy_operations b43_phyops_n = {
.software_rfkill = b43_nphy_op_software_rfkill,
.switch_channel = b43_nphy_op_switch_channel,
.get_default_chan = b43_nphy_op_get_default_chan,
.xmitpower = b43_nphy_op_xmitpower,
.recalc_txpower = b43_nphy_op_recalc_txpower,
.adjust_txpower = b43_nphy_op_adjust_txpower,
};
11 changes: 9 additions & 2 deletions trunk/drivers/net/wireless/b43/phy_a.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,10 +505,16 @@ static void b43_aphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
b43_hf_write(dev, hf);
}

static void b43_aphy_op_xmitpower(struct b43_wldev *dev)
static void b43_aphy_op_adjust_txpower(struct b43_wldev *dev)
{//TODO
}

static enum b43_txpwr_result b43_aphy_op_recalc_txpower(struct b43_wldev *dev,
bool ignore_tssi)
{//TODO
return B43_TXPWR_RES_DONE;
}

static void b43_aphy_op_pwork_15sec(struct b43_wldev *dev)
{//TODO
}
Expand All @@ -530,7 +536,8 @@ const struct b43_phy_operations b43_phyops_a = {
.switch_channel = b43_aphy_op_switch_channel,
.get_default_chan = b43_aphy_op_get_default_chan,
.set_rx_antenna = b43_aphy_op_set_rx_antenna,
.xmitpower = b43_aphy_op_xmitpower,
.recalc_txpower = b43_aphy_op_recalc_txpower,
.adjust_txpower = b43_aphy_op_adjust_txpower,
.pwork_15sec = b43_aphy_op_pwork_15sec,
.pwork_60sec = b43_aphy_op_pwork_60sec,
};
91 changes: 91 additions & 0 deletions trunk/drivers/net/wireless/b43/phy_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,3 +274,94 @@ void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state)
phy->ops->software_rfkill(dev, state);
phy->radio_on = (state == RFKILL_STATE_UNBLOCKED);
}

/**
* b43_phy_txpower_adjust_work - TX power workqueue.
*
* Workqueue for updating the TX power parameters in hardware.
*/
void b43_phy_txpower_adjust_work(struct work_struct *work)
{
struct b43_wl *wl = container_of(work, struct b43_wl,
txpower_adjust_work);
struct b43_wldev *dev;

mutex_lock(&wl->mutex);
dev = wl->current_dev;

if (likely(dev && (b43_status(dev) >= B43_STAT_STARTED)))
dev->phy.ops->adjust_txpower(dev);

mutex_unlock(&wl->mutex);
}

/* Called with wl->irq_lock locked */
void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
{
struct b43_phy *phy = &dev->phy;
unsigned long now = jiffies;
enum b43_txpwr_result result;

if (!(flags & B43_TXPWR_IGNORE_TIME)) {
/* Check if it's time for a TXpower check. */
if (time_before(now, phy->next_txpwr_check_time))
return; /* Not yet */
}
/* The next check will be needed in two seconds, or later. */
phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));

if ((dev->dev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
(dev->dev->bus->boardinfo.type == SSB_BOARD_BU4306))
return; /* No software txpower adjustment needed */

result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI));
if (result == B43_TXPWR_RES_DONE)
return; /* We are done. */
B43_WARN_ON(result != B43_TXPWR_RES_NEED_ADJUST);
B43_WARN_ON(phy->ops->adjust_txpower == NULL);

/* We must adjust the transmission power in hardware.
* Schedule b43_phy_txpower_adjust_work(). */
queue_work(dev->wl->hw->workqueue, &dev->wl->txpower_adjust_work);
}

int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
{
const bool is_ofdm = (shm_offset != B43_SHM_SH_TSSI_CCK);
unsigned int a, b, c, d;
unsigned int average;
u32 tmp;

tmp = b43_shm_read32(dev, B43_SHM_SHARED, shm_offset);
a = tmp & 0xFF;
b = (tmp >> 8) & 0xFF;
c = (tmp >> 16) & 0xFF;
d = (tmp >> 24) & 0xFF;
if (a == 0 || a == B43_TSSI_MAX ||
b == 0 || b == B43_TSSI_MAX ||
c == 0 || c == B43_TSSI_MAX ||
d == 0 || d == B43_TSSI_MAX)
return -ENOENT;
/* The values are OK. Clear them. */
tmp = B43_TSSI_MAX | (B43_TSSI_MAX << 8) |
(B43_TSSI_MAX << 16) | (B43_TSSI_MAX << 24);
b43_shm_write32(dev, B43_SHM_SHARED, shm_offset, tmp);

if (is_ofdm) {
a = (a + 32) & 0x3F;
b = (b + 32) & 0x3F;
c = (c + 32) & 0x3F;
d = (d + 32) & 0x3F;
}

/* Get the average of the values with 0.5 added to each value. */
average = (a + b + c + d + 2) / 4;
if (is_ofdm) {
/* Adjust for CCK-boost */
if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO)
& B43_HF_CCKBOOST)
average = (average >= 13) ? (average - 13) : 0;
}

return average;
}
75 changes: 72 additions & 3 deletions trunk/drivers/net/wireless/b43/phy_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ enum {
B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO,
};

/**
* enum b43_txpwr_result - Return value for the recalc_txpower PHY op.
*
* @B43_TXPWR_RES_NEED_ADJUST: Values changed. Hardware adjustment is needed.
* @B43_TXPWR_RES_DONE: No more work to do. Everything is done.
*/
enum b43_txpwr_result {
B43_TXPWR_RES_NEED_ADJUST,
B43_TXPWR_RES_DONE,
};

/**
* struct b43_phy_operations - Function pointers for PHY ops.
*
Expand Down Expand Up @@ -96,8 +107,23 @@ enum {
* @interf_mitigation: Switch the Interference Mitigation mode.
* Can be NULL, if not supported.
*
* @xmitpower: FIXME REMOVEME
* @recalc_txpower: Recalculate the transmission power parameters.
* This callback has to recalculate the TX power settings,
* but does not need to write them to the hardware, yet.
* Returns enum b43_txpwr_result to indicate whether the hardware
* needs to be adjusted.
* If B43_TXPWR_NEED_ADJUST is returned, @adjust_txpower
* will be called later.
* If the parameter "ignore_tssi" is true, the TSSI values should
* be ignored and a recalculation of the power settings should be
* done even if the TSSI values did not change.
* This callback is called with wl->irq_lock held and must not sleep.
* Must not be NULL.
* @adjust_txpower: Write the previously calculated TX power settings
* (from @recalc_txpower) to the hardware.
* This function may sleep.
* Can be NULL, if (and ONLY if) @recalc_txpower _always_
* returns B43_TXPWR_RES_DONE.
*
* @pwork_15sec: Periodic work. Called every 15 seconds.
* Can be NULL, if not required.
Expand Down Expand Up @@ -127,7 +153,9 @@ struct b43_phy_operations {
enum b43_interference_mitigation new_mode);

/* Transmission power adjustment */
void (*xmitpower)(struct b43_wldev *dev);
enum b43_txpwr_result (*recalc_txpower)(struct b43_wldev *dev,
bool ignore_tssi);
void (*adjust_txpower)(struct b43_wldev *dev);

/* Misc */
void (*pwork_15sec)(struct b43_wldev *dev);
Expand Down Expand Up @@ -183,11 +211,15 @@ struct b43_phy {

/* Desired TX power level (in dBm).
* This is set by the user and adjusted in b43_phy_xmitpower(). */
u8 power_level;
int desired_txpower;

/* Hardware Power Control enabled? */
bool hardware_power_control;

/* The time (in absolute jiffies) when the next TX power output
* check is needed. */
unsigned long next_txpwr_check_time;

/* current channel */
unsigned int channel;

Expand Down Expand Up @@ -309,4 +341,41 @@ int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel);
*/
void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state);

/**
* b43_phy_txpower_check - Check TX power output.
*
* Compare the current TX power output to the desired power emission
* and schedule an adjustment in case it mismatches.
* Requires wl->irq_lock locked.
*
* @flags: OR'ed enum b43_phy_txpower_check_flags flags.
* See the docs below.
*/
void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags);
/**
* enum b43_phy_txpower_check_flags - Flags for b43_phy_txpower_check()
*
* @B43_TXPWR_IGNORE_TIME: Ignore the schedule time and force-redo
* the check now.
* @B43_TXPWR_IGNORE_TSSI: Redo the recalculation, even if the average
* TSSI did not change.
*/
enum b43_phy_txpower_check_flags {
B43_TXPWR_IGNORE_TIME = (1 << 0),
B43_TXPWR_IGNORE_TSSI = (1 << 1),
};

struct work_struct;
void b43_phy_txpower_adjust_work(struct work_struct *work);

/**
* b43_phy_shm_tssi_read - Read the average of the last 4 TSSI from SHM.
*
* @shm_offset: The SHM address to read the values from.
*
* Returns the average of the 4 TSSI values, or a negative error code.
*/
int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset);


#endif /* LINUX_B43_PHY_COMMON_H_ */
Loading

0 comments on commit 2126ba1

Please sign in to comment.