b43: implement PPR (Power Per Rate) management/API
PATCH 1/2 b43: implement PPR (Power Per Rate) management/API
Broadcom hardware supports auto-adjustment of TX power depending on the currently used rate. So far all calculations were handled without any helpers (API) using big arrays and magic offsets.
It seems Broadcom recently decided to clean this up by developing PPR. Their wlc_ppr.h can be found in open parts of the SDK.
As we plan to implement support for rate-based TX power it makes sense to also implement our version of PPR as well.
--- drivers/net/wireless/b43/Makefile | 1 + drivers/net/wireless/b43/b43.h | 7 ++ drivers/net/wireless/b43/ppr.c | 210 ++++++++++++++++++++++++++++++++++++++ drivers/net/wireless/b43/ppr.h | 21 ++++ 4 files changed, 239 insertions(+) create mode 100644 drivers/net/wireless/b43/ppr.c create mode 100644 drivers/net/wireless/b43/ppr.h
drivers/net/wireless/b43/Makefile +1 -0
@@ -18,6 +18,7 @@ b43-y += xmit.o b43-y += dma.o b43-y += pio.o b43-y += rfkill.o +b43-y += ppr.o b43-$(CONFIG_B43_LEDS) += leds.o b43-$(CONFIG_B43_PCMCIA) += pcmcia.o b43-$(CONFIG_B43_SDIO) += sdio.o
drivers/net/wireless/b43/b43.h +7 -0
@@ -791,6 +791,13 @@ struct b43_firmware {bool pcm_request_failed; }; +enum b43_band { +B43_BAND_2G =0 , +B43_BAND_5G_LO =1 , +B43_BAND_5G_MI =2 , +B43_BAND_5G_HI =3 , +}; +/* Device (802.11 core) initialization status. */ enum {B43_STAT_UNINIT =0 ,/* Uninitialized. */
drivers/net/wireless/b43/ppr.c new file +210 -0
210 lines not on this page · raw message
drivers/net/wireless/b43/ppr.h new file +21 -0
@@ -0,0 +1,21 @@ +#ifndef LINUX_B43_PPR_H_ +#define LINUX_B43_PPR_H_ + +#include <linux/types.h> + +struct b43_ppr ; +struct b43_wldev ; +enum b43_band ; + +struct b43_ppr *b43_ppr_alloc (struct b43_wldev *dev); +void b43_ppr_clear (struct b43_wldev *dev,struct b43_ppr *ppr); + +void b43_ppr_add (struct b43_wldev *dev,struct b43_ppr *ppr,int diff); +void b43_ppr_apply_max (struct b43_wldev *dev,struct b43_ppr *ppr,u8 max); +void b43_ppr_apply_min (struct b43_wldev *dev,struct b43_ppr *ppr,u8 min); +u8 b43_ppr_get_max (struct b43_wldev *dev,struct b43_ppr *ppr); + +bool b43_ppr_load_max_from_sprom (struct b43_wldev *dev,struct b43_ppr *ppr, +enum b43_band band); + +#endif /* LINUX_B43_PPR_H_ */
Signature · 1 line
1.8.4.5
PATCH 2/2 b43: N-PHY: support setting custom TX power
---
This is based on top of
[PATCH 7/7] b43: enable radio 0x2057 rev 14 support (AKA BCM43217) (not sure if applies cleanly otherwise)
--- drivers/net/wireless/b43/b43.h | 1 + drivers/net/wireless/b43/phy_n.c | 88 ++++++++++++++++++++++++++++++++++------ drivers/net/wireless/b43/phy_n.h | 3 ++ 3 files changed, 80 insertions(+), 12 deletions(-)
drivers/net/wireless/b43/b43.h +1 -0
@@ -457,6 +457,7 @@ enum {#define B43_MACCTL_RADIOLOCK 0x00080000/* Radio lock */ #define B43_MACCTL_BEACPROMISC 0x00100000/* Beacon Promiscuous */ #define B43_MACCTL_KEEP_BADPLCP 0x00200000/* Keep frames with bad PLCP */ +#define B43_MACCTL_PHY_LOCK 0x00200000#define B43_MACCTL_KEEP_CTL 0x00400000/* Keep control frames */ #define B43_MACCTL_KEEP_BAD 0x00800000/* Keep bad frames (FCS) */ #define B43_MACCTL_PROMISC 0x01000000/* Promiscuous mode */
drivers/net/wireless/b43/phy_n.c +76 -12
128 lines not on this page · raw message
drivers/net/wireless/b43/phy_n.h +3 -0
@@ -967,6 +967,9 @@ struct b43_phy_n {struct b43_phy_n_txpwrindex txpwrindex[2 ];struct b43_phy_n_pwr_ctl_info pwr_ctl_info[2 ];struct b43_chanspec txiqlocal_chanspec; +struct b43_ppr *tx_pwr_max_ppr; +u16 tx_pwr_last_recalc_freq; +int tx_pwr_last_recalc_limit;u8 txrx_chain;u16 tx_rx_cal_phy_saveregs[11 ];
Signature · 1 line
1.8.4.5
PATCH 2/2 b43: N-PHY: support setting custom TX power
Quoted 5 lines · Rafa? Mi?ecki
Signed-off-by Rafa? Mi?ecki <[email protected]>---
This is based on top of
[PATCH 7/7] b43: enable radio0x2057rev 14 support (AKA BCM43217) (not sure if applies cleanly otherwise)
Forgot to say. I've tested this on BCM4321, BCM4322, BCM43224, BCM43217 and BCM43228. No performance regressions observed, so I guess my code doesn't do anything stupid ;)
PATCH 2/2 b43: N-PHY: support setting custom TX power
In reply to Rafał Miłeckidrivers/net/wireless/b43/phy_n.c static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) · line 5925
Quoted 9 lines · On Sun, 20 Jul 2014 13:00:22 +0200 Rafa? Mi?ecki <[email protected]> wrote:
drivers/net/wireless/b43/phy_n.c +9
-0+/* Apply */ + tx_pwr_state = nphy->txpwrctrl; +b43_mac_suspend (dev); +b43_nphy_tx_power_ctl_setup (dev); +if (dev->dev->core_rev ==11 || dev->dev->core_rev ==12 ) { +b43_maskset32 (dev,B43_MMIO_MACCTL , ~0 ,B43_MACCTL_PHY_LOCK ); +b43_read32 (dev,B43_MMIO_MACCTL ); +udelay (1 ); + }
You could probably write a function b43_phy_lock/unlock() similar to b43_mac_suspend/enable to make this more readable.
The PHY_LOCK bit is related to the mac-suspend bit, after all. These are both used to lock the firmware in one way or the other.
Quoted 12 lines
drivers/net/wireless/b43/phy_n.c +10
-0+b43_nphy_tx_power_ctrl (dev, nphy->txpwrctrl); +if (dev->dev->core_rev ==11 || dev->dev->core_rev ==12 ) +b43_maskset32 (dev,B43_MMIO_MACCTL , ~B43_MACCTL_PHY_LOCK ,0 ); +b43_mac_enable (dev); + + nphy->tx_pwr_last_recalc_freq = channel->center_freq; + nphy->tx_pwr_last_recalc_limit = phy->desired_txpower; + +return B43_TXPWR_RES_DONE ; +}
drivers/net/wireless/b43/phy_n.c const struct b43_phy_operations b43_phyops_n = { · line 6659
Quoted 4 lines
drivers/net/wireless/b43/phy_n.c +0
-1@@ -6656,5 +6721,4 @@ const struct b43_phy_operations b43_phyops_n = { .switch_channel = b43_nphy_op_switch_channel, .get_default_chan = b43_nphy_op_get_default_chan, .recalc_txpower = b43_nphy_op_recalc_txpower, - .adjust_txpower = b43_nphy_op_adjust_txpower,
recalc_txpower once was designed to just recalculate the txpower and not write it to hardware. adjust_txpower was supposed to write it to hardware afterwards. That had to do with some locking foo and stuff I forgot (AFAIR these callbacks are called in different contexts, but I may be wrong).
But I don't think it really matters. Just as a general hint here.
Signature · 8 lines
Michael -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: not available URL: <http://lists.infradead.org/pipermail/b43-dev/attachments/20140720/0e185e01/attachment.sig>
PATCH 2/2 b43: N-PHY: support setting custom TX power
Quoted 13 lines · Michael B?sch
drivers/net/wireless/b43/phy_n.c const struct b43_phy_operations b43_phyops_n = { · line 6659
Quoted 5 lines · On Sun, 20 Jul 2014 13:00:22 +0200 Rafa? Mi?ecki <[email protected]> wrote:
drivers/net/wireless/b43/phy_n.c +0
-1@@ -6656,5 +6721,4 @@ const struct b43_phy_operations b43_phyops_n = { .switch_channel = b43_nphy_op_switch_channel, .get_default_chan = b43_nphy_op_get_default_chan, .recalc_txpower = b43_nphy_op_recalc_txpower, - .adjust_txpower = b43_nphy_op_adjust_txpower,
recalc_txpoweronce was designed to just recalculate the txpower and not write it to hardware.adjust_txpowerwas supposed to write it to hardware afterwards. That had to do with some locking foo and stuff I forgot (AFAIR these callbacks are called in different contexts, but I may be wrong).
But I don't think it really matters. Just as a general hint here.
Yeah, I noticed that and was starring at it for a long time.
First of all I verified if @config is allowed to sleep. It is, so our "recalc_txpower" can sleep as well if it needs to.
I think that using adjust_txpower on G-PHY could have something to do with the way TX power is controlled on these devices. They don't have hardware (firmware?) power control, so much more has to be done in the driver. It's probably what Broadcom calls a "software" TX power recalc. If you take a look at
[PATCH] Staging: Add initial release of brcm80211 - Broadcom 802.11n wireless LAN driver.
you will see there was a wlc_phy_txpower_target_set with following calls:wlc_phy_txpower_recalc_target(pi); wlc_phy_cal_txpower_recalc_sw(pi);
The second was an empty function, most probably because Broadcom stripped it our of G-PHY code before releasing.
In N-PHY world there are two registers for setting TX power: 0x1E7 and 0x222 (one per core) and two for reading current state: 0x1ED and 0x1EE. However you don't really touch them unless you're doing some initialization/calibration. For most of the time hardware is supposed to adjust TX power, you simply tell the firmware what should it be (this is what 0x1EA register is for).
In G-PHY you were setting that manually, so you could indeed need some hacks to avoid some conflict or sth. This should not be needed for N-PHY.
Signature · 1 line
Rafa?
PATCH 2/2 b43: N-PHY: support setting custom TX power
Quoted 15 lines · On Sun, 20 Jul 2014 13:50:39 +0200 Rafa? Mi?ecki <[email protected]> wrote:
Quoted 13 lines · Michael B?sch
drivers/net/wireless/b43/phy_n.c const struct b43_phy_operations b43_phyops_n = { · line 6659
Quoted 5 lines · On Sun, 20 Jul 2014 13:00:22 +0200 Rafa? Mi?ecki <[email protected]> wrote:
drivers/net/wireless/b43/phy_n.c +0
-1@@ -6656,5 +6721,4 @@ const struct b43_phy_operations b43_phyops_n = { .switch_channel = b43_nphy_op_switch_channel, .get_default_chan = b43_nphy_op_get_default_chan, .recalc_txpower = b43_nphy_op_recalc_txpower, - .adjust_txpower = b43_nphy_op_adjust_txpower,
recalc_txpoweronce was designed to just recalculate the txpower and not write it to hardware.adjust_txpowerwas supposed to write it to hardware afterwards. That had to do with some locking foo and stuff I forgot (AFAIR these callbacks are called in different contexts, but I may be wrong).
But I don't think it really matters. Just as a general hint here.
Quoted 7 lines
Yeah, I noticed that and was starring at it for a long time.
First of all I verified if @config is allowed to sleep. It is, so our "
recalc_txpower" can sleep as well if it needs to.I think that using
adjust_txpoweron G-PHY could have something to do with the way TX power is controlled on these devices. They don't have
adjustment of txpower may be very expensive there. So I think this was the reason I split it in half and let the heavier part run in workqueue context or something. Also recalc used to be called from interrupt tasklet. Not sure if that's still the case anymore, though.
Quoted 6 lines
In N-PHY world there are two registers for setting TX power:
0x1E7and0x222(one per core) and two for reading current state:0x1EDand0x1EE. However you don't really touch them unless you're doing some initialization/calibration. For most of the time hardware is supposed to adjust TX power, you simply tell the firmware what should it be (this is what0x1EAregister is for).
Yeah looks fine.
Signature · 8 lines
Michael -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: not available URL: <http://lists.infradead.org/pipermail/b43-dev/attachments/20140720/af004587/attachment.sig>
PATCH 2/2 b43: N-PHY: support setting custom TX power
In reply to Rafał MiłeckiQuoted 11 lines · Rafa? Mi?ecki
Signed-off-by Rafa? Mi?ecki <[email protected]>---
This is based on top of
[PATCH 7/7] b43: enable radio0x2057rev 14 support (AKA BCM43217) (not sure if applies cleanly otherwise)--- drivers/net/wireless/b43/b43.h | 1 + drivers/net/wireless/b43/phy_n.c | 88 ++++++++++++++++++++++++++++++++++------ drivers/net/wireless/b43/phy_n.h | 3 ++ 3 files changed, 80 insertions(+), 12 deletions(-)
(snip)
drivers/net/wireless/b43/phy_n.h struct b43_phy_n { · line 970
Quoted 9 lines
drivers/net/wireless/b43/phy_n.h +1
-0@@ -967,6 +967,9 @@ struct b43_phy_n {struct b43_phy_n_txpwrindex txpwrindex[2 ];struct b43_phy_n_pwr_ctl_info pwr_ctl_info[2 ];struct b43_chanspec txiqlocal_chanspec; +struct b43_ppr *tx_pwr_max_ppr;
Why not just make this a struct member? As far as I can tell, it will always be allocated, and you would lose one alloc/free call, and probably one pointer dereference.
Quoted 7 lines
drivers/net/wireless/b43/phy_n.h +2
-1+u16 tx_pwr_last_recalc_freq; +int tx_pwr_last_recalc_limit;u8 txrx_chain;u16 tx_rx_cal_phy_saveregs[11 ]; --1.8.4.5
Jonas
PATCH 2/2 b43: N-PHY: support setting custom TX power
Quoted 14 lines · Jonas Gorski
drivers/net/wireless/b43/phy_n.h struct b43_phy_n { · line 970
Quoted 9 lines · Rafa? Mi?ecki
drivers/net/wireless/b43/phy_n.h +1
-0@@ -967,6 +967,9 @@ struct b43_phy_n {struct b43_phy_n_txpwrindex txpwrindex[2 ];struct b43_phy_n_pwr_ctl_info pwr_ctl_info[2 ];struct b43_chanspec txiqlocal_chanspec; +struct b43_ppr *tx_pwr_max_ppr;Why not just make this a struct member? As far as I can tell, it will always be allocated, and you would lose one alloc/free call, and probably one pointer dereference.
My idea was to prevent driver parts from knowing PPR implementation details. Just to don't mess with its internals and allow redesigning in the future. That is why I put "struct b43_ppr_rates" in .c file and all other driver parts use a pointer only.
Seriously, I doubt in the sense of posting RFCs :P
Signature · 1 line
Rafa?
PATCH 2/2 b43: N-PHY: support setting custom TX power
Quoted 16 lines · Rafa? Mi?ecki
Quoted 14 lines · Jonas Gorski
drivers/net/wireless/b43/phy_n.h struct b43_phy_n { · line 970
Quoted 9 lines · Rafa? Mi?ecki
drivers/net/wireless/b43/phy_n.h +1
-0@@ -967,6 +967,9 @@ struct b43_phy_n {struct b43_phy_n_txpwrindex txpwrindex[2 ];struct b43_phy_n_pwr_ctl_info pwr_ctl_info[2 ];struct b43_chanspec txiqlocal_chanspec; +struct b43_ppr *tx_pwr_max_ppr;Why not just make this a struct member? As far as I can tell, it will always be allocated, and you would lose one alloc/free call, and probably one pointer dereference.
Quoted 4 lines
My idea was to prevent driver parts from knowing PPR implementation details. Just to don't mess with its internals and allow redesigning in the future. That is why I put "struct
b43_ppr_rates" in .c file and all other driver parts use a pointer only.
If this were a library used by several drivers I could understand. But hiding things from yourself? Seriously? ;P
Quoted 2 lines
Seriously, I doubt in the sense of posting RFCs :P
I know that feel :p. I usually try to do a thorough code review if I review, and was missing the time when you posted the RFC. Also I'm usually a bit more lenient with RFCs as I assume this is usually a request for commenting on the intend of the code, and less for finding nitpicks/bugs.
Jonas
PATCH 1/2 b43: implement PPR (Power Per Rate) management/API
In reply to Rafał MiłeckiQuoted 14 lines · On Sun, 20 Jul 2014 13:00:21 +0200 Rafa? Mi?ecki <[email protected]> wrote:
drivers/net/wireless/b43/ppr.c new file +14
-0+#define B43_PPR_CCK_RATES_NUM 4 +#define B43_PPR_OFDM_RATES_NUM 8 +#define B43_PPR_MCS_RATES_NUM 8 + +#define B43_PPR_RATES_NUM (B43_PPR_CCK_RATES_NUM + \ + B43_PPR_OFDM_RATES_NUM * 2 + \ + B43_PPR_MCS_RATES_NUM * 4) + +struct b43_ppr_rates { +u8 cck[B43_PPR_CCK_RATES_NUM ]; +u8 ofdm[B43_PPR_OFDM_RATES_NUM ]; +u8 ofdm_20_cdd[B43_PPR_OFDM_RATES_NUM ]; +u8 mcs_20[B43_PPR_MCS_RATES_NUM ];/* SISO */ +u8 mcs_20_cdd[B43_PPR_MCS_RATES_NUM ];
drivers/net/wireless/b43/ppr.c line 27
Quoted 10 lines
drivers/net/wireless/b43/ppr.c new file +10
-0+u8 mcs_20_stbc[B43_PPR_MCS_RATES_NUM ]; +u8 mcs_20_sdm[B43_PPR_MCS_RATES_NUM ]; +} __packed; + +struct b43_ppr { +/* All powers are in qdbm (Q5.2) */ +union { +u8 __all_rates[B43_PPR_RATES_NUM ]; +struct b43_ppr_rates rates; + } __packed;
I don't think this union has to be packed.
And most likely struct b43_ppr_rates is ok without packing, too.
You could probably remove it there and add a BUILD_BUG which checks something like (pseudocode):
BUILD_BUG_ON(offsetof(struct b43_ppr_rates.mcs_20_sdm) != B43_PPR_CCK_RATES_NUM + B43_PPR_OFDM_RATES_NUM * 2 + B43_PPR_MCS_RATES_NUM * 3);
Removing packed will produce much nicer code.
Signature · 8 lines
Michael -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: not available URL: <http://lists.infradead.org/pipermail/b43-dev/attachments/20140720/9a30ee67/attachment.sig>
PATCH 1/2 b43: implement PPR (Power Per Rate) management/API
Quoted 33 lines · Michael B?sch
Quoted 14 lines · On Sun, 20 Jul 2014 13:00:21 +0200 Rafa? Mi?ecki <[email protected]> wrote:
drivers/net/wireless/b43/ppr.c new file +14
-0+#define B43_PPR_CCK_RATES_NUM 4 +#define B43_PPR_OFDM_RATES_NUM 8 +#define B43_PPR_MCS_RATES_NUM 8 + +#define B43_PPR_RATES_NUM (B43_PPR_CCK_RATES_NUM + \ + B43_PPR_OFDM_RATES_NUM * 2 + \ + B43_PPR_MCS_RATES_NUM * 4) + +struct b43_ppr_rates { +u8 cck[B43_PPR_CCK_RATES_NUM ]; +u8 ofdm[B43_PPR_OFDM_RATES_NUM ]; +u8 ofdm_20_cdd[B43_PPR_OFDM_RATES_NUM ]; +u8 mcs_20[B43_PPR_MCS_RATES_NUM ];/* SISO */ +u8 mcs_20_cdd[B43_PPR_MCS_RATES_NUM ];drivers/net/wireless/b43/ppr.c line 27
Quoted 10 lines
drivers/net/wireless/b43/ppr.c new file +10
-0+u8 mcs_20_stbc[B43_PPR_MCS_RATES_NUM ]; +u8 mcs_20_sdm[B43_PPR_MCS_RATES_NUM ]; +} __packed; + +struct b43_ppr { +/* All powers are in qdbm (Q5.2) */ +union { +u8 __all_rates[B43_PPR_RATES_NUM ]; +struct b43_ppr_rates rates; + } __packed;I don't think this union has to be packed.
And most likely structb43_ppr_ratesis ok without packing, too.
You could probably remove it there and add aBUILD_BUGwhich checks something like (pseudocode):
BUILD_BUG_ON(offsetof(struct b43_ppr_rates.mcs_20_sdm) !=B43_PPR_CCK_RATES_NUM+B43_PPR_OFDM_RATES_NUM* 2 +B43_PPR_MCS_RATES_NUM* 3);
Quoted 1 line
Removing packed will produce much nicer code.
Thanks for your comments. I'll rework this.
John: please wait for V2
Btw. I was waiting for comments since Monday you slug (just kidding!) ;)
Signature · 1 line
Rafa?
PATCH 1/2 b43: implement PPR (Power Per Rate) management/API
In reply to Rafał MiłeckiQuoted 7 lines · Rafa? Mi?ecki
Broadcom hardware supports auto-adjustment of TX power depending on the currently used rate. So far all calculations were handled without any helpers (API) using big arrays and magic offsets.
It seems Broadcom recently decided to clean this up by developing PPR. Theirwlc_ppr.hcan be found in open parts of the SDK.
As we plan to implement support for rate-based TX power it makes sense to also implement our version of PPR as well.
Nice one.
Quoted 15 lines
Signed-off-by Rafa? Mi?ecki <[email protected]>--- drivers/net/wireless/b43/Makefile | 1 + drivers/net/wireless/b43/b43.h | 7 ++ drivers/net/wireless/b43/ppr.c | 210 ++++++++++++++++++++++++++++++++++++++ drivers/net/wireless/b43/ppr.h | 21 ++++ 4 files changed, 239 insertions(+) create mode 100644 drivers/net/wireless/b43/ppr.c create mode 100644 drivers/net/wireless/b43/ppr.hdrivers/net/wireless/b43/Makefile +0
-0
drivers/net/wireless/b43/Makefile b43-y += xmit.o · line 21
Quoted 4 lines
drivers/net/wireless/b43/Makefile +1
-0@@ -18,6 +18,7 @@ b43-y += xmit.o b43-y += dma.o b43-y += pio.o b43-y += rfkill.o +b43-y += ppr.o
Is this only used for N-PHY, or also for others? If not, it might make sense to only include it if N-PHY support is selected. Not sure if it's large enough to matter much.
Quoted 27 lines
drivers/net/wireless/b43/Makefile +0
-0b43-$(CONFIG_B43_LEDS) += leds.o b43-$(CONFIG_B43_PCMCIA) += pcmcia.o b43-$(CONFIG_B43_SDIO) += sdio.odrivers/net/wireless/b43/b43.h +7
-0@@ -791,6 +791,13 @@ struct b43_firmware {bool pcm_request_failed; }; +enum b43_band { +B43_BAND_2G =0 , +B43_BAND_5G_LO =1 , +B43_BAND_5G_MI =2 , +B43_BAND_5G_HI =3 , +}; +/* Device (802.11 core) initialization status. */ enum {B43_STAT_UNINIT =0 ,/* Uninitialized. */ drivers/net/wireless/b43/ppr.c new file +0
-0
drivers/net/wireless/b43/ppr.c line 2
Quoted 2 lines
drivers/net/wireless/b43/ppr.c new file +2
-0@@ -0,0 +1,210 @@ +#include "ppr.h" +#include "b43.h"
This file could use a license/copyright header. It looks a bit odd without one.
Quoted 8 lines
drivers/net/wireless/b43/ppr.c new file +8
-0+ +#define B43_PPR_CCK_RATES_NUM 4 +#define B43_PPR_OFDM_RATES_NUM 8 +#define B43_PPR_MCS_RATES_NUM 8 + +#define B43_PPR_RATES_NUM (B43_PPR_CCK_RATES_NUM + \ + B43_PPR_OFDM_RATES_NUM * 2 + \ + B43_PPR_MCS_RATES_NUM * 4)
drivers/net/wireless/b43/ppr.c line 20
Quoted 10 lines
drivers/net/wireless/b43/ppr.c new file +10
-0+ +struct b43_ppr_rates { +u8 cck[B43_PPR_CCK_RATES_NUM ]; +u8 ofdm[B43_PPR_OFDM_RATES_NUM ]; +u8 ofdm_20_cdd[B43_PPR_OFDM_RATES_NUM ]; +u8 mcs_20[B43_PPR_MCS_RATES_NUM ];/* SISO */ +u8 mcs_20_cdd[B43_PPR_MCS_RATES_NUM ]; +u8 mcs_20_stbc[B43_PPR_MCS_RATES_NUM ]; +u8 mcs_20_sdm[B43_PPR_MCS_RATES_NUM ]; +} __packed;
not sure if __packed makes a difference if *all* members are u8.
drivers/net/wireless/b43/ppr.c line 27
Quoted 7 lines
drivers/net/wireless/b43/ppr.c new file +7
-0+ +struct b43_ppr { +/* All powers are in qdbm (Q5.2) */ +union { +u8 __all_rates[B43_PPR_RATES_NUM ]; +struct b43_ppr_rates rates; + } __packed;
Same here.
Quoted 58 lines
drivers/net/wireless/b43/ppr.c new file +58
-0+}; + +#define ppr_for_each_entry (ppr, i, entry) \ + for (i = 0, entry = &(ppr)->__all_rates[i]; \ + i < B43_PPR_RATES_NUM; \ + i++, entry++) + +struct b43_ppr *b43_ppr_alloc (struct b43_wldev *dev) +{ +return kzalloc (sizeof (struct b43_ppr ),GFP_KERNEL ); +} + +void b43_ppr_clear (struct b43_wldev *dev,struct b43_ppr *ppr) +{ +memset (ppr,0 ,sizeof (*ppr)); +} + +void b43_ppr_add (struct b43_wldev *dev,struct b43_ppr *ppr,int diff) +{ +int i; +u8 *rate; + +ppr_for_each_entry (ppr, i, rate) { + *rate =clamp_val (*rate + diff,0 ,127 ); + } +} + +void b43_ppr_apply_max (struct b43_wldev *dev,struct b43_ppr *ppr,u8 max) +{ +int i; +u8 *rate; + +ppr_for_each_entry (ppr, i, rate) { + *rate =min (*rate, max); + } +} + +void b43_ppr_apply_min (struct b43_wldev *dev,struct b43_ppr *ppr,u8 min) +{ +int i; +u8 *rate; + +ppr_for_each_entry (ppr, i, rate) { + *rate =max (*rate, min); + } +} + +u8 b43_ppr_get_max (struct b43_wldev *dev,struct b43_ppr *ppr) +{ +u8 res =0 ; +int i; +u8 *rate; + +ppr_for_each_entry (ppr, i, rate) { + res =max (*rate, res); + } + +return res;
drivers/net/wireless/b43/ppr.c line 95
Quoted 10 lines
drivers/net/wireless/b43/ppr.c new file +10
-0+} + +bool b43_ppr_load_max_from_sprom (struct b43_wldev *dev,struct b43_ppr *ppr, +enum b43_band band) +{ +struct b43_ppr_rates *rates = &ppr->rates; +struct ssb_sprom *sprom = dev->dev->bus_sprom; +struct b43_phy *phy = &dev->phy; +u8 maxpwr, off; +u32 *sprom_ofdm_po;
sprom->ofdm2gpo is a single u32, you gain nothing by using a pointer and dereferencing it (actually you will double your stack usage on 64 bit system).
Quoted 29 lines
drivers/net/wireless/b43/ppr.c new file +29
-0+u16 *sprom_mcs_po; +u8 extra_cdd_po, extra_stbc_po; +int i; + +switch (band) { +case B43_BAND_2G : + maxpwr =min (sprom->core_pwr_info[0 ].maxpwr_2g, + sprom->core_pwr_info[1 ].maxpwr_2g); + sprom_ofdm_po = &sprom->ofdm2gpo; + sprom_mcs_po = sprom->mcs2gpo; + extra_cdd_po = (sprom->cddpo >>0 ) &0xf ; + extra_stbc_po = (sprom->stbcpo >>0 ) &0xf ; +break ; +case B43_BAND_5G_LO : + maxpwr =min (sprom->core_pwr_info[0 ].maxpwr_5gl, + sprom->core_pwr_info[1 ].maxpwr_5gl); + sprom_ofdm_po = &sprom->ofdm5glpo; + sprom_mcs_po = sprom->mcs5glpo; + extra_cdd_po = (sprom->cddpo >>8 ) &0xf ; + extra_stbc_po = (sprom->stbcpo >>8 ) &0xf ; +break ; +case B43_BAND_5G_MI : + maxpwr =min (sprom->core_pwr_info[0 ].maxpwr_5g, + sprom->core_pwr_info[1 ].maxpwr_5g); + sprom_ofdm_po = &sprom->ofdm5gpo; + sprom_mcs_po = sprom->mcs5gpo; + extra_cdd_po = (sprom->cddpo >>4 ) &0xf ; + extra_stbc_po = (sprom->stbcpo >>4 ) &0xf ; +break ;
drivers/net/wireless/b43/ppr.c line 134
Quoted 10 lines
drivers/net/wireless/b43/ppr.c new file +10
-0+case B43_BAND_5G_HI : + maxpwr =min (sprom->core_pwr_info[0 ].maxpwr_5gh, + sprom->core_pwr_info[1 ].maxpwr_5gh); + sprom_ofdm_po = &sprom->ofdm5ghpo; + sprom_mcs_po = sprom->mcs5ghpo; + extra_cdd_po = (sprom->cddpo >>12 ) &0xf ; + extra_stbc_po = (sprom->stbcpo >>12 ) &0xf ; +break ; +default : +BUG_ON (1 );
Is it really that critical that it should halt the system? Maybe a WARN_ON[_ONCE](1); is enough.
Quoted 19 lines
drivers/net/wireless/b43/ppr.c new file +19
-0+return false; + } + +if (band ==B43_BAND_2G ) { +for (i =0 ; i <4 ; i++) { + off = ((sprom->cck2gpo >> (i *4 )) &0xF ) *2 ; + rates->cck[i] = maxpwr - off; + } + } + +/* OFDM */ +for (i =0 ; i <8 ; i++) { + off = ((*sprom_ofdm_po >> (i *4 )) &0xF ) *2 ; + rates->ofdm[i] = maxpwr - off; + } + +/* MCS 20 SISO */ + rates->mcs_20[0 ] = rates->ofdm[0 ]; + rates->mcs_20[1 ] = rates->ofdm[2 ];
drivers/net/wireless/b43/ppr.c line 163
Quoted 10 lines
drivers/net/wireless/b43/ppr.c new file +10
-0+ rates->mcs_20[2 ] = rates->ofdm[3 ]; + rates->mcs_20[3 ] = rates->ofdm[4 ]; + rates->mcs_20[4 ] = rates->ofdm[5 ]; + rates->mcs_20[5 ] = rates->ofdm[6 ]; + rates->mcs_20[6 ] = rates->ofdm[7 ]; + rates->mcs_20[7 ] = rates->ofdm[7 ]; + +/* MCS 20 CDD */ +for (i =0 ; i <4 ; i++) { + off = ((sprom_mcs_po[0 ] >> (i *4 )) &0xF ) *2 ;
You should decide whether to use upper case or lower case hex (above is all lower).
drivers/net/wireless/b43/ppr.c line 172
Quoted 9 lines
drivers/net/wireless/b43/ppr.c new file +9
-0+ rates->mcs_20_cdd[i] = maxpwr - off; +if (phy->type ==B43_PHYTYPE_N && phy->rev >=3 ) + rates->mcs_20_cdd[i] -= extra_cdd_po; + } +for (i =0 ; i <4 ; i++) { + off = ((sprom_mcs_po[1 ] >> (i *4 )) &0xF ) *2 ; + rates->mcs_20_cdd[4 + i] = maxpwr - off; +if (phy->type ==B43_PHYTYPE_N && phy->rev >=3 ) + rates->mcs_20_cdd[i] -= extra_cdd_po;
Did you intend to reduce rates->mcs_20_cdd[4 + i] here?
Quoted 14 lines
drivers/net/wireless/b43/ppr.c new file +14
-0+ } + +/* OFDM 20 CDD */ + rates->ofdm_20_cdd[0 ] = rates->mcs_20_cdd[0 ]; + rates->ofdm_20_cdd[1 ] = rates->mcs_20_cdd[0 ]; + rates->ofdm_20_cdd[2 ] = rates->mcs_20_cdd[1 ]; + rates->ofdm_20_cdd[3 ] = rates->mcs_20_cdd[2 ]; + rates->ofdm_20_cdd[4 ] = rates->mcs_20_cdd[3 ]; + rates->ofdm_20_cdd[5 ] = rates->mcs_20_cdd[4 ]; + rates->ofdm_20_cdd[6 ] = rates->mcs_20_cdd[5 ]; + rates->ofdm_20_cdd[7 ] = rates->mcs_20_cdd[6 ]; + +/* MCS 20 STBC */ +for (i =0 ; i <4 ; i++) {
drivers/net/wireless/b43/ppr.c line 196
Quoted 10 lines
drivers/net/wireless/b43/ppr.c new file +10
-0+ off = ((sprom_mcs_po[0 ] >> (i *4 )) &0xF ) *2 ; + rates->mcs_20_stbc[i] = maxpwr - off; +if (phy->type ==B43_PHYTYPE_N && phy->rev >=3 ) + rates->mcs_20_stbc[i] -= extra_stbc_po; + } +for (i =0 ; i <4 ; i++) { + off = ((sprom_mcs_po[1 ] >> (i *4 )) &0xF ) *2 ; + rates->mcs_20_stbc[4 + i] = maxpwr - off; +if (phy->type ==B43_PHYTYPE_N && phy->rev >=3 ) + rates->mcs_20_stbc[i] -= extra_stbc_po;
Same question here, did you intend rates->mcs_20_stbc[4 + i]?
drivers/net/wireless/b43/ppr.c line 206
Quoted 10 lines
drivers/net/wireless/b43/ppr.c new file +10
-0+ } + +/* MCS 20 SDM */ +for (i =0 ; i <4 ; i++) { + off = ((sprom_mcs_po[2 ] >> (i *4 )) &0xF ) *2 ; + rates->mcs_20_sdm[i] = maxpwr - off; + } +for (i =0 ; i <4 ; i++) { + off = ((sprom_mcs_po[3 ] >> (i *4 )) &0xF ) *2 ; + rates->mcs_20_sdm[4 + i] = maxpwr - off;
I guess you did ;-)
drivers/net/wireless/b43/ppr.c line 210
Quoted 4 lines
drivers/net/wireless/b43/ppr.c new file +4
-0+ } + +return true; +}
Rest looks fine.
Jonas