b43: Rewrite TX power adjustment
PATCH 1/1 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.
---
John, please queue for the next merge window.
drivers/net/wireless/b43/b43.h +10 -0
@@ -170,12 +170,17 @@ enum {#define B43_SHM_SH_RADAR 0x0066/* Radar register */ #define B43_SHM_SH_PHYTXNOI 0x006E/* PHY noise directly after TX (lower 8bit only) */ #define B43_SHM_SH_RFRXSP1 0x0072/* RF RX SP Register 1 */ #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 */ #define B43_SHM_SH_SIZE45 0x009C/* TX FIFO size for FIFO 4 and 5 */ #define B43_SHM_SH_SIZE67 0x009E/* TX FIFO size for FIFO 6 and 7 */ /* SHM_SHARED background noise */
@@ -645,12 +650,17 @@ struct b43_wl {/* 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; + +/* 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. */ struct b43_firmware_file {const char *filename;const struct firmware *data;
drivers/net/wireless/b43/main.c +13 -5
@@ -2802,12 +2802,15 @@ err_gpio_clean:static void b43_periodic_every60sec (struct b43_wldev *dev) {const struct b43_phy_operations *ops = dev->phy.ops;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) {/* Update device statistics. */ b43_calculate_link_quality (dev);
@@ -2832,14 +2835,12 @@ static void b43_periodic_every15sec(stru } }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 (); }static void do_periodic_work (struct b43_wldev *dev) {
@@ -3379,16 +3380,19 @@ static int b43_op_config(struct ieee8021 } dev->wl->radiotap_enabled = !!(conf->flags &IEEE80211_CONF_RADIOTAP );/* 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. */ antenna =b43_antenna_from_ieee80211 (dev, conf->antenna_sel_tx);b43_mgmtframe_txantenna (dev, antenna); antenna =b43_antenna_from_ieee80211 (dev, conf->antenna_sel_rx);
@@ -3782,12 +3786,13 @@ static int b43_phy_versioning(struct b43 }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 ); }static void setup_struct_wldev_for_init (struct b43_wldev *dev) {
@@ -4201,12 +4206,14 @@ static void b43_op_stop(struct ieee80211mutex_lock (&wl->mutex);if (b43_status (dev) >=B43_STAT_STARTED )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,u32 short_retry_limit,u32 long_retry_limit) {struct b43_wl *wl =hw_to_b43_wl (hw);
@@ -4578,12 +4585,13 @@ static int b43_wireless_init(struct ssb_spin_lock_init (&wl->leds_lock);spin_lock_init (&wl->shm_lock);mutex_init (&wl->mutex);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); err =0 ; out:return err;
drivers/net/wireless/b43/phy_common.c +91 -0
97 lines not on this page · raw message
drivers/net/wireless/b43/phy_common.h +72 -3
135 lines not on this page · raw message
drivers/net/wireless/b43/phy_g.c +120 -98
282 lines not on this page · raw message
drivers/net/wireless/b43/phy_g.h +15 -7
@@ -112,13 +112,12 @@ static inline bool b43_compare_bbatt(con#define B43_TXCTL_TXMIX 0x10/* TX Mixer Gain */ struct b43_txpower_lo_control ;struct b43_phy_g {bool initialised; -bool dyn_tssi_tbl;/* tssi2dbm is kmalloc()ed. */ /* ACI (adjacent channel interference) flags. */ bool aci_enable;bool aci_wlan_automatic;bool aci_hw_rssi;
@@ -132,33 +131,42 @@ struct b43_phy_g {u16 rfoverval; } radio_off_context;u16 minlowsig[2 ];u16 minlowsigpos[2 ]; -/* TSSI to dBm table in use */ +/* Pointer to the table used to convert a +* TSSI value to dBm-Q5.2 */ const s8 *tssi2dbm; +/* tssi2dbm is kmalloc()ed. Only used for free()ing. */ +bool dyn_tssi_tbl;/* Target idle TSSI */ int tgt_idle_tssi;/* Current idle TSSI */ int cur_idle_tssi; +/* The current average TSSI. +* Needs irq_lock, as it's updated in the IRQ path. */ +u8 average_tssi; +/* Current TX power level attenuation control values */ +struct b43_bbatt bbatt; +struct b43_rfatt rfatt; +u8 tx_control;/* B43_TXCTL_XXX */ +/* The calculated attenuation deltas that are used later +* when adjusting the actual power output. */ +int bbatt_delta; +int rfatt_delta;/* LocalOscillator control values. */ struct b43_txpower_lo_control *lo_control;/* Values from b43_calc_loopback_gain() */ s16 max_lb_gain;/* Maximum Loopback gain in hdB */ s16 trsw_rx_gain;/* TRSW RX gain in hdB */ s16 lna_lod_gain;/* LNA lod */ s16 lna_gain;/* LNA */ s16 pga_gain;/* PGA */ -/* Current TX power level attenuation control values */ -struct b43_bbatt bbatt; -struct b43_rfatt rfatt; -u8 tx_control;/* B43_TXCTL_XXX */ -/* Current Interference Mitigation mode */ int interfmode;/* Stack of saved values from the Interference Mitigation code. * Each value in the stack is layed out as follows: * bit 0-11: offset * bit 12-15: register ID
drivers/net/wireless/b43/xmit.c +2 -0
@@ -677,12 +677,14 @@ void b43_handle_txstatus(struct b43_wlde }if (b43_using_pio_transfers (dev))b43_pio_handle_txstatus (dev, status);else b43_dma_handle_txstatus (dev, status); + +b43_phy_txpower_check (dev,0 ); }/* Fill out the mac80211 TXstatus report based on the b43-specific * txstatus report data. This returns a boolean whether the frame was * successfully transmitted. */ bool b43_fill_txstatus_report(struct ieee80211_tx_info *report,
drivers/net/wireless/b43/nphy.c +9 -6
@@ -31,16 +31,22 @@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) {b43_radio_write16 (dev,B2055_PLL_REF , e->radio_pll_ref);b43_radio_write16 (dev,B2055_RF_PLLMOD0 , e->radio_rf_pllmod0);b43_radio_write16 (dev,B2055_RF_PLLMOD1 , e->radio_rf_pllmod1);
@@ -599,23 +605,20 @@ static unsigned int b43_nphy_op_get_defa {if (b43_current_band (dev->wl) ==IEEE80211_BAND_2GHZ )return 1 ;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, .exit = b43_nphy_op_exit, .phy_read = b43_nphy_op_read, .phy_write = b43_nphy_op_write, .radio_read = b43_nphy_op_radio_read, .radio_write = b43_nphy_op_radio_write, .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, };
drivers/net/wireless/b43/phy_a.c +9 -2
@@ -502,16 +502,22 @@ static void b43_aphy_op_set_rx_antenna(s } hf |=B43_HF_ANTDIVHELP ;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 }static void b43_aphy_op_pwork_60sec (struct b43_wldev *dev) {//TODO
@@ -527,10 +533,11 @@ const struct b43_phy_operations b43_phyo .radio_write = b43_aphy_op_radio_write, .supports_hwpctl = b43_aphy_op_supports_hwpctl, .software_rfkill = b43_aphy_op_software_rfkill, .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, };