Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: Ath5k and proprietary extensions
From: Bob Copeland @ 2009-08-31 12:53 UTC (permalink / raw)
  To: Nick Kossifidis
  Cc: John W. Linville, Luis R. Rodriguez, proski, ath5k-devel,
	linux-wireless, ic.felix, Felix Fietkau
In-Reply-To: <40f31dec0908282151t245912f0ye79684d4a519f3c9@mail.gmail.com>

On Sat, Aug 29, 2009 at 07:51:29AM +0300, Nick Kossifidis wrote:
> Most code is there for half/quarter and (static) turbo operation, we
> just have to deal with pll programming, clock settings etc. Question
> is how do we use it, NL80211_CMD_TESTMODE is an option i guess and in
> case no one else thinks that we could use a channel width API (or
> extend what we have) for setting 5/10/40MHz width through cfg80211, we
> can just stick to NL80211_CMD_TESTMODE.

Well, we will have a channel width API, I think; several people
have expresed an interest in doing so.

Your summary is useful, and I really don't have any qualms about
keeping the non-standard stuff as long as someone has plans to
write the code to support it.  I personally have no interest
in using those features, but of course I only speak for me.

If we do remove turbo code for now, we can leave the initvals, as
they are such a pain to verify.  But I'm not sure half a page of
text is worth the churn.

-- 
Bob Copeland %% www.bobcopeland.com


^ permalink raw reply

* [PATCH] ath9k: Do an AHB reset before doing RTC reset
From: Vasanthakumar Thiagarajan @ 2009-08-31 12:18 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Luis.Rodriguez, Jouni.Malinen, ath9k-devel

Doing an RTC reset when DMA is active may corrupt memory,
make sure no DMA is active at this moment by doing an
AHB reset.

Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
---
 drivers/net/wireless/ath/ath9k/hw.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index e340dac..71f27f3 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1712,8 +1712,15 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
 	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
 		  AR_RTC_FORCE_WAKE_ON_INT);
 
+	if (!AR_SREV_9100(ah))
+		REG_WRITE(ah, AR_RC, AR_RC_AHB);
+
 	REG_WRITE(ah, AR_RTC_RESET, 0);
 	udelay(2);
+
+	if (!AR_SREV_9100(ah))
+		REG_WRITE(ah, AR_RC, 0);
+
 	REG_WRITE(ah, AR_RTC_RESET, 1);
 
 	if (!ath9k_hw_wait(ah,
-- 
1.5.5.1


^ permalink raw reply related

* Re: rtl8187b Problem with tx level
From: Tobias Schlemmer @ 2009-08-31  9:59 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <4A9B0479.209@lwfinger.net>

[-- Attachment #1: Type: text/plain, Size: 1888 bytes --]

Hi,

thank you for your quick answer.

Larry Finger schrieb:
> Tobias Schlemmer wrote:
>> Interestingly iwconfig always reports TX power of 20dBm, regardless of
>> the actual tx power, but always a TX rate of 1M. Setting the latter to a
>> higher value results in packet loss.
> 
> Where are you located? Your log says you are using the EU regulatory
> domain; however, that is no longer valid. You should add a line like
> 
> options cfg80211 ieee80211_regdom=XX
> 
> to /etc/modprobe.conf.local. From your name, I would guess the XX
> should be DE.

I guess, too. For some reason it is not corrected in some tutorials.

> It is likely that the 20 dBm is set by mac80211 as the maximum allowed
> by your local regulations. That value is in fact correct for most
> locations in the EU.

As far as I know, Germany has a maximum of 100mW, which should be 20dBm, 
if I'm right. This means the driver reports full power though the device 
actually seems to send with much less power. The power gets lost 
somewhere between this display and the antenna. Since there exists a 
working driver, I can hardly expect it on the hardware side.

I've attached the output of iwconfig for the two drivers. The 
proprietary works, the compat-wireless one even failed to authenticate 
(auth timeout) today. I don't know which tx power the proprietary driver 
uses. If you can tell me how to find out, I'll try that.

Some additional information: The automatic rate setting seems to work 
somehow. Last night it grow to 11M for a short time (reporting signal 
stregth of -3dBm).

Maybe, the tx power gets only reduced, but never increased. That's what 
the AP sees.

> My rtl8187b runs at a full 54 Mbs and operates at at least 15 m from
> my AP. I don't run AP firmware that lets me see the signal strength
> from the STA.

That dosn't surprise me. The archives don't talk about similar problems.

Tobias

[-- Attachment #2: iwconfig1 --]
[-- Type: text/plain, Size: 1483 bytes --]

wlan0     802.11b/g linked  ESSID:"Malter"  
          Mode:Managed  Channel=8  Access Point: 00:17:3F:7E:AB:08   
          Bit Rate=48 Mb/s   
          Retry:on   Fragment thr:off
          Link Quality=72/100  Signal level=-45 dBm  Noise level=-102 dBm
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0

filename:       /lib/modules/2.6.24-19-generic/kernel/drivers/nb/r8187.ko
description:    Linux driver for Realtek RTL8187 WiFi cards
author:         Andrea Merello <andreamrl@tiscali.it>
version:        V 1.1
license:        GPL
srcversion:     CE57E03B376EA9ED408E23E
alias:          usb:v0846p6A00d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0846p6100d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0BDAp8189d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0BDAp8187d*dc*dsc*dp*ic*isc*ip*
depends:        usbcore
vermagic:       2.6.24-19-generic SMP mod_unload 586 
parm:           ifname:charp
parm:           devname: Net interface name, wlan%d=default
parm:           channels: Channel bitmask for specific locales. NYI (int)

filename:       /lib/modules/2.6.24-19-generic/kernel/drivers/nb/r8187msh.ko
description:    Linux extension module for Realtek RTL8187 WiFi cards
author:         Stanley Chang <changsl@cs.nctu.edu.tw>
version:        V 11sD1.0
license:        Proprietary
srcversion:     4F5B438A81B73DDF03155C5
depends:        
vermagic:       2.6.24-19-generic SMP mod_unload 586 

[-- Attachment #3: iwconfig2 --]
[-- Type: text/plain, Size: 2123 bytes --]

wlan0     IEEE 802.11bg  ESSID:"Malter"  
          Mode:Managed  Frequency:2.447 GHz  Access Point: 00:17:3F:7E:AB:08   
          Bit Rate=1 Mb/s   Tx-Power=20 dBm   
          Retry  long limit:7   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality=69/70  Signal level=-41 dBm  
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0

filename:       /lib/modules/2.6.28-15-generic/updates/drivers/net/wireless/rtl818x/rtl8187.ko
license:        GPL
description:    RTL8187/RTL8187B USB wireless driver
author:         Larry Finger <Larry.Finger@lwfinger.net>
author:         Hin-Tak Leung <htl10@users.sourceforge.net>
author:         Herton Ronaldo Krzesinski <herton@mandriva.com.br>
author:         Andrea Merello <andreamrl@tiscali.it>
author:         Michael Wu <flamingice@sourmilk.net>
srcversion:     ACC7FDA7EFE2500D0DC1B50
alias:          usb:v1737p0073d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v1B75p8187d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v18E8p6232d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v13D1pABE6d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v1371p9401d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v114Bp0150d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0DF6p0028d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0DF6p000Dd*dc*dsc*dp*ic*isc*ip*
alias:          usb:v03F0pCA02d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0846p4260d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0846p6A00d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0846p6100d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0789p010Cd*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0769p11F2d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0BDAp8198d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0BDAp8197d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0BDAp8189d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0BDAp8187d*dc*dsc*dp*ic*isc*ip*
alias:          usb:v050Dp705Ed*dc*dsc*dp*ic*isc*ip*
alias:          usb:v0B05p171Dd*dc*dsc*dp*ic*isc*ip*
depends:        mac80211,eeprom_93cx6,cfg80211
vermagic:       2.6.28-15-generic SMP mod_unload modversions 586 

^ permalink raw reply

* Re: [PATCH] ar9170: added phy register initialisation from eeprom values
From: Chunkeey @ 2009-08-31  9:53 UTC (permalink / raw)
  To: Joerg Albert, John W. Linville
  Cc: Johannes Berg, linux-wireless@vger.kernel.org

> "Joerg Albert" <jal2@gmx.de> wrote:
>
> This patch adds the initialisation of some PHY registers
> from the modal_header[] values in the EEPROM (see otus/hal/hpmain.c, line 333 ff.)
> 
> Signed-off-by: Joerg Albert <jal2@gmx.de>

meh, no hardware... and only a shitty kiosk with web-interface here.
testing has to wait until the weekend.
 
> diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c
> index cb8b5cd..47a5e5c 100644
> --- a/drivers/net/wireless/ath/ar9170/phy.c
> +++ b/drivers/net/wireless/ath/ar9170/phy.c
> @@ -396,6 +396,131 @@ static struct ar9170_phy_init ar5416_phy_init[] = {
>  	{ 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, }
>  };
>  
> +/* look up a certain register in ar5416_phy_init[] and return the init. value
> +   for the band and bandwidth given. Return 0 if register address not found. */
See Documentation/CodingStyle - Chapter 8

The preferred style for long (multi-line) comments is:
/*
 * look up a certain register in ar5416_phy_init[] and return the init. value
 * for the band and bandwidth given. Return 0 if register address not found.
 */

> +u32 ar9170_get_default_phy_reg_val(int reg, bool is_2ghz, bool is_40mhz)
please consider this instead: 
static u32 ar9170_get_default_phy_reg_val(u32 reg, [...])
(static function, and reg is a u32)

> +{
> +	struct ar9170_phy_init *p;
> +	struct ar9170_phy_init *endp =
> +		ar5416_phy_init+ARRAY_SIZE(ar5416_phy_init);
(see Codingstyle: 3.1:  Spaces
  => Use one space around (on each side of) most binary [...] operators)

> +
> +	for (p = ar5416_phy_init; p < endp; p++)
a extra { } wouldn't hurt. The following statements also has multiple lines.

> +		if (p->reg == reg) {
> +			if (is_2ghz)
> +				return is_40mhz ? p->_2ghz_40 : p->_2ghz_20;
> +			else
> +				return is_40mhz ? p->_5ghz_40 : p->_5ghz_20;
> +		}
> +	return 0;
> +}
hmm, it's a bit odd to use pointers over a fixed array,
what about (unfortunately space and line damaged... and untested):

{
        unsigned int i;
        for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) {
                if (ar5416_phy_init[i].reg != reg)
                        continue;

                if (is_2ghz) {
                        if (is_40mhz)
                                return ar5416_phy_init[i]._2ghz_40;
                        else
                                return ar5416_phy_init[i]._2ghz_20;
                } else {
                        if (is_40mhz)
                                return ar5416_phy_init[i]._5ghz_40;
                        else
                                return ar5416_phy_init[i]._5ghz_20;
                }
        }
        return 0;
}
this follows the looks of the rest of the code. (e.g ar9170_init_phy)
(of course, either version should be fine.
 so stay with yours if you have doubts.)

> +/* initialize some phy regs from eeprom values in modal_header[]
> +   acc. to band and bandwith */
(multi-line comment, but I guess you know what do here now...)

> +static int ar9170_init_phy_from_eeprom(struct ar9170 *ar,
> +				bool is_2ghz, bool is_40mhz)
> +{
> +	const u8 xpd2pd[16] = {
> +		0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2,
> +		0x2, 0x3, 0x7, 0x2, 0xB, 0x2, 0x2, 0x2
> +	};
static const u8 xpd2pd ?

> +	u32 defval, newval; /* two separate for debugging the changes */
> +	/* pointer to the modal_header acc. to band */
> +	struct ar9170_eeprom_modal *m = ar->eeprom.modal_header +
> +		(is_2ghz ? 1 : 0);
what about:
struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz]; ?

> +	ar9170_regwrite_begin(ar);
> +
> +	/* ant common control (index 0) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c5964, is_2ghz, is_40mhz);
> +	newval = le32_to_cpu(m->antCtrlCommon);
> +	ar9170_regwrite(0x1c5964, newval);
> +
> +	/* ant control chain 0 (index 1) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c5960, is_2ghz, is_40mhz);
> +	newval = le32_to_cpu(m->antCtrlChain[0]);
> +	ar9170_regwrite(0x1c5960, newval);
> +
> +	/* ant control chain 2 (index 2) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c7960, is_2ghz, is_40mhz);
> +	newval = le32_to_cpu(m->antCtrlChain[1]);
> +	ar9170_regwrite(0x1c7960, newval);
> +
> +	/* SwSettle (index 3) */
> +	if (!is_40mhz) {
> +		defval = ar9170_get_default_phy_reg_val(0x1c5844,
> +							is_2ghz, is_40mhz);
> +		newval = (defval & ~0x3f80) | ((m->switchSettling & 0x7f)<<7);
(well )<<7 is a bit tight, but it looks like you ran out of space in this line?)
  
> +		ar9170_regwrite(0x1c5844, newval);
> +	}
> +
> +	/* adcDesired, pdaDesired (index 4) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c5850, is_2ghz, is_40mhz);
> +	newval = (defval & ~0xffff) | ((u8)m->pgaDesiredSize << 8) |
> +		((u8)m->adcDesiredSize);
> +	ar9170_regwrite(0x1c5850, newval);
> +
> +	/* TxEndToXpaOff, TxFrameToXpaOn (index 5) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c5834, is_2ghz, is_40mhz);
> +	newval = (m->txEndToXpaOff << 24) | (m->txEndToXpaOff << 16) |
> +		(m->txFrameToXpaOn << 8) | m->txFrameToXpaOn;
> +	ar9170_regwrite(0x1c5834, newval);
> +
> +	/* TxEndToRxOn (index 6) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c5828, is_2ghz, is_40mhz);
> +	newval = (defval & ~0xff0000) | (m->txEndToRxOn << 16);
> +	ar9170_regwrite(0x1c5828, newval);
> +
> +	/* thresh62 (index 7) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c8864, is_2ghz, is_40mhz);
> +	newval = (defval & ~0x7f000) | (m->thresh62 << 12);
> +	ar9170_regwrite(0x1c8864, newval);
> +
> +	/* tx/rx attenuation chain 0 (index 8) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c5848, is_2ghz, is_40mhz);
> +	newval = (defval & ~0x3f000) | ((m->txRxAttenCh[0] & 0x3f) << 12);
> +	ar9170_regwrite(0x1c5848, newval);
> +
> +	/* tx/rx attenuation chain 2 (index 9) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c7848, is_2ghz, is_40mhz);
> +	newval = (defval & ~0x3f000) | ((m->txRxAttenCh[1] & 0x3f) << 12);
> +	ar9170_regwrite(0x1c7848, newval);
> +
> +	/* tx/rx margin chain 0 (index 10) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c620c, is_2ghz, is_40mhz);
> +	newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[0] & 0x3f) << 18);
> +	/* bsw margin chain 0 for 5GHz only */
> +	if (!is_2ghz)
> +		newval = (newval & ~0x3c00) | ((m->bswMargin[0] & 0xf) << 10);
> +	ar9170_regwrite(0x1c620c, newval);
> +
> +	/* tx/rx margin chain 2 (index 11) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c820c, is_2ghz, is_40mhz);
> +	newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[1] & 0x3f) << 18);
> +	ar9170_regwrite(0x1c820c, newval);
> +
> +	/* iqCall, iqCallq chain 0 (index 12) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c5920, is_2ghz, is_40mhz);
> +	newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[0] & 0x3f) << 5) |
> +		((u8)m->iqCalQCh[0] & 0x1f);
> +	ar9170_regwrite(0x1c5920, newval);
> +
> +	/* iqCall, iqCallq chain 2 (index 13) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c7920, is_2ghz, is_40mhz);
> +	newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[1] & 0x3f) << 5) |
> +		((u8)m->iqCalQCh[1] & 0x1f);
> +	ar9170_regwrite(0x1c7920, newval);
> +
> +	/* xpd gain mask (index 14) */
> +	defval = ar9170_get_default_phy_reg_val(0x1c6258, is_2ghz, is_40mhz);
> +	newval = (defval & ~0xf0000) | (xpd2pd[m->xpdGain & 0xf] << 16);
> +	ar9170_regwrite(0x1c6258, newval);
(cannot test this now. it looks good, though.)
It's amazing how much **** you can _cut_ from the vendor driver.

BTW: does this patch help the 1-stage fw stability, or is it still broken?

Regards,
   Chr

________________________________________________________________
Neu: WEB.DE Doppel-FLAT mit Internet-Flatrate + Telefon-Flatrate
für nur 19,99 Euro/mtl.!* http://produkte.web.de/go/02/


^ permalink raw reply

* Re: memleaks, acpi + ext4 + tty
From: Luis R. Rodriguez @ 2009-08-31  8:23 UTC (permalink / raw)
  To: Catalin Marinas, John W. Linville, H. Peter Anvin
  Cc: linux-kernel, Aneesh Kumar K.V, Greg Kroah-Hartman,
	linux-wireless
In-Reply-To: <43e72e890908281509o44930348w581b865107ea3e98@mail.gmail.com>

On Fri, Aug 28, 2009 at 3:09 PM, Luis R. Rodriguez<mcgrof@gmail.com> wrote:
> On Fri, Aug 28, 2009 at 2:50 PM, Luis R. Rodriguez<mcgrof@gmail.com> wrote:
>> On Fri, Aug 28, 2009 at 9:52 AM, Luis R. Rodriguez<mcgrof@gmail.com> wrote:
>>> On Fri, Aug 28, 2009 at 9:32 AM, Catalin Marinas<catalin.marinas@arm.com> wrote:
>>>> "Luis R. Rodriguez" <mcgrof@gmail.com> wrote:
>>>>> I have an assorted collection of kmemleak reports for acpi, ext4 and
>>>>> tty, not sure how to read these yet to fix so figure I'd at least post
>>>>> them. To reproduce I can just dd=/dev/zero to some big file and played
>>>>> some video.
>>>>
>>>> If you do a few echo scan > /sys/kernel/debug/kmemleak, do they
>>>> disappear (i.e. transient false positives)?
>>>
>>> Sure, I will once on rc8.
>>>
>>>> Which kernel version is this?
>>>
>>> v2.6.31-rc7-33172-gf4a9f9a
>>>
>>> This is from wireless-testing, which has wireless patches on top of
>>> rc7. John just rebased to rc8 so will give that a shot at work.
>>>
>>>>> unreferenced object 0xffff88003e0015c0 (size 64):
>>>>>   comm "swapper", pid 1, jiffies 4294892352
>>>>>   backtrace:
>>>>>     [<ffffffff81121fad>] create_object+0x13d/0x2d0
>>>>>     [<ffffffff81122265>] kmemleak_alloc+0x25/0x60
>>>>>     [<ffffffff81118a03>] kmem_cache_alloc_node+0x193/0x200
>>>>>     [<ffffffff8152509e>] process_zones+0x70/0x1cd
>>>>>     [<ffffffff81525230>] pageset_cpuup_callback+0x35/0x92
>>>>>     [<ffffffff8152c9b7>] notifier_call_chain+0x47/0x90
>>>>>     [<ffffffff81078549>] __raw_notifier_call_chain+0x9/0x10
>>>>>     [<ffffffff81523f25>] _cpu_up+0x75/0x130
>>>>>     [<ffffffff8152403a>] cpu_up+0x5a/0x6a
>>>>>     [<ffffffff8181969e>] kernel_init+0xcc/0x1ba
>>>>>     [<ffffffff810130ca>] child_rip+0xa/0x20
>>>>>     [<ffffffffffffffff>] 0xffffffffffffffff
>>>>
>>>> Can't really tell. Maybe a false positive caused by kmemleak not
>>>> scanning the pgdata node_zones. Can you post your .config file?
>>>
>>> Sure, attached.
>>>
>>>>> unreferenced object 0xffff88003cb5f700 (size 64):
>>>>>   comm "swapper", pid 1, jiffies 4294892459
>>>>>   backtrace:
>>>>>     [<ffffffff81121fad>] create_object+0x13d/0x2d0
>>>>>     [<ffffffff81122265>] kmemleak_alloc+0x25/0x60
>>>>>     [<ffffffff81119f3b>] __kmalloc+0x16b/0x250
>>>>>     [<ffffffff812bb549>] kzalloc+0xf/0x11
>>>>>     [<ffffffff812bbb53>] acpi_add_single_object+0x58e/0xd3c
>>>>>     [<ffffffff812bc51c>] acpi_bus_scan+0x125/0x1af
>>>>>     [<ffffffff81842361>] acpi_scan_init+0xc8/0xe9
>>>>>     [<ffffffff8184211c>] acpi_init+0x21f/0x265
>>>>>     [<ffffffff8100a05b>] do_one_initcall+0x4b/0x1b0
>>>>>     [<ffffffff81819736>] kernel_init+0x164/0x1ba
>>>>>     [<ffffffff810130ca>] child_rip+0xa/0x20
>>>>>     [<ffffffffffffffff>] 0xffffffffffffffff
>>>>
>>>> I get ACPI reports as well and they may be real leaks. However, I
>>>> didn't have time to analyse the code (pretty complicated reference
>>>> counting).
>>>
>>> Heh OK thanks for reviewing them though.
>>>
>>>>> unreferenced object 0xffff880039571800 (size 1024):
>>>>>   comm "exe", pid 1168, jiffies 4294893410
>>>>>   backtrace:
>>>>>     [<ffffffff81121fad>] create_object+0x13d/0x2d0
>>>>>     [<ffffffff81122265>] kmemleak_alloc+0x25/0x60
>>>>>     [<ffffffff81119f3b>] __kmalloc+0x16b/0x250
>>>>>     [<ffffffff811e1d71>] ext4_mb_init+0x1a1/0x590
>>>>>     [<ffffffff811d2da3>] ext4_fill_super+0x1df3/0x26c0
>>>>>     [<ffffffff8112774f>] get_sb_bdev+0x16f/0x1b0
>>>>>     [<ffffffff811c8fd3>] ext4_get_sb+0x13/0x20
>>>>>     [<ffffffff81127216>] vfs_kern_mount+0x76/0x180
>>>>>     [<ffffffff8112738d>] do_kern_mount+0x4d/0x130
>>>>>     [<ffffffff8113fc57>] do_mount+0x307/0x8b0
>>>>>     [<ffffffff8114028f>] sys_mount+0x8f/0xe0
>>>>>     [<ffffffff81011f02>] system_call_fastpath+0x16/0x1b
>>>>>     [<ffffffffffffffff>] 0xffffffffffffffff
>>>>
>>>> The ext4 reports are real leaks and patch was posted here -
>>>> http://lkml.org/lkml/2009/7/15/62. However, it hasn't been merged into
>>>> mainline yet (I cc'ed Aneesh).
>>>>
>>>> The patch is merged in my "kmemleak-fixes" branch on
>>>> git://linux-arm.org/linux-2.6.git.
>>>
>>> Will try to suck them out and try them.
>>
>> OK -- tested rc8 + a pull of your tree into mine. The bootup was
>> really slow and something was just not going right. After a while
>> memleak complained it had 8 kmemleak logs but I was not able to get my
>> system usable enough to cat the file.
>>
>> In cases like these I wish I would hookup my ctrl-alt-del to kexec() a
>> safe kernel.
>>
>> After a long period of time it seems X wished it would start, it tried
>> and then flashed back to the tty. This kept repeating in a loop.
>>
>> I am not sure if the culprit was rc8 or the kmemleak branch merge --
>> I'll find out after I boot into rc8 in a few.
>
> rc8 busted my bootup, the issues are present with just
> wireless-testing. I highly doubt the issues are wireless-testing
> related so I will not bisect there. Since I am unable to get anything
> useful from the kernel to determine what may have gone sour, any
> suggestions on a path to bisect, or should I just do the whole tree?

I tried 2.6.31-rc8 from hpa's linux-2.6-allstable.git tree instead of
Linus [1] as I already had that tree, git describe says:

v2.6.31-rc8-15-gadda766

Testing this would be the same as testing Linus' blessed rc8 --
correct me I'm wrong. Contrary to what I expected this tree with the
same config works well!

I have compiled a fresh checkout of wireless-testing origin/master to
double check the issue and it is indeed only present on
wireless-testing. A diff stat between John's merge of 2.6.31-rc8 and
current master branch on wireless-testing [2] doesn't reveal much
other than wireless specific stuff, as expected, so it seems this may
after all be introduced in a recent patches in wireless-testing. I
still find this a bit odd given I see no others reporting major
issues. My boot doesn't go very far, it stalls for a while after input
devices are being detected, then it spits out a kmemleak warning about
13 kmemleaks. Here's a picture [3]. I didn't bother waiting as I did
last time for X to try to come up, something is really wrong. I'll
bisect wireless-testing in the morning, starting with a good marker at
merge-2009-08-28 as that is when John pulled 2.6.31-rc8 (and I confirm
a diff stat between that and v2.6.31-rc8 yields nothing as it should)
and current master as the bad marker. I have 9 steps to go, will leave
first step compiling overnight.

[1] git://git.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-allstable.git
[2] git diff --stat merge-2009-08-28..HEAD
[3] http://bombadil.infradead.org/~mcgrof/images/2009/08/lag-wl-2009-08-31.jpg
[4] git diff --stat merge-2009-08-28..v2.6.31-rc8

  Luis

^ permalink raw reply

* [PATCH] wireless: hostap, fix oops due to early probing interrupt
From: Tim Gardner @ 2009-08-31  2:18 UTC (permalink / raw)
  To: j; +Cc: linux-wireless

Jouni,

Did this ever get sent to you?

rtg

---------------------------------
>From a72eaafae9186632add4ed01a340b4f1b39cc672 Mon Sep 17 00:00:00 2001
From: Colin Ian King <colin.king@canonical.com>
Date: Wed, 19 Aug 2009 15:39:21 +0100
Subject: [PATCH] wireless: hostap, fix oops due to early probing interrupt

BugLink: https://bugs.launchpad.net/ubuntu/+bug/254837

Spurious shared interrupts or early probing interrupts can cause the
hostap interrupt handler to oops before the driver has fully configured
the IO base port addresses. In some cases the oops can be because
the hardware shares an interrupt line, on other cases it is due to a
race condition between probing for the hardware and configuring
the IO base port. The latter occurs because the probing is required to
determin the hardware port address which is only determined when the probe
can interrupt the hardware (catch 22).

This patch catches this pre-configured condition to avoid the oops.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Tim Gardner <tim.gardner@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
---
 drivers/net/wireless/hostap/hostap_hw.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index d4d857e..0212ee3 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -2628,6 +2628,15 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
 	int events = 0;
 	u16 ev;
 
+	/* Detect early interrupt before driver is fully configued */
+	if (!dev->base_addr) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
+			       dev->name);
+		}
+		return IRQ_HANDLED;
+	}
+
 	iface = netdev_priv(dev);
 	local = iface->local;
 
-- 
1.6.2.4


^ permalink raw reply related

* Inter 5300 AGN with unsupported EEPROM
From: Larry Finger @ 2009-08-30 23:32 UTC (permalink / raw)
  To: reinette chatre; +Cc: wireless

Reinette,

While helping on the openSUSE wireless forum, I ran across another
unit with the same unsupported EEPROM as in the thread at
http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=1997.

The thread at openSUSE is at
 http://forums.opensuse.org/network-internet/wireless/420589-intel-5300-wifi-minipci-card-asus-g71gx-rx05-bestbuy-3.html

Most of the thread is useless as the OP wouldn't supply critical data
and persisted in various rants, but on the 3rd page, he finally
provided the output of 'dmesg | grep iwl', which was

iwlagn: Intel(R) Wireless WiFi Link AGN driver for Linux, 1.3.27ks
iwlagn: Copyright(c) 2003-2008 Intel Corporation
iwlagn 0000:07:00.0: PCI INT A -> GSI 17 (level, low) -> IRQ 17
iwlagn 0000:07:00.0: setting latency timer to 64
iwlagn: Detected Intel Wireless WiFi Link 5300AGN REV=0x24
iwlagn: Unsuported EEPROM VER=0x114 < 0x11a CALIB=0x3 < 0x4
iwlagn 0000:07:00.0: PCI INT A disabled
iwlagn: probe of 0000:07:00.0 failed with error -22

The OP states that this device came from Best Buy. What is the current
scoop on this EEPROM version?

Thanks,

Larry


^ permalink raw reply

* [PATCH] ar9170: added phy register initialisation from eeprom values
From: Joerg Albert @ 2009-08-30 23:15 UTC (permalink / raw)
  To: Christian Lamparter, John W. Linville
  Cc: Johannes Berg, linux-wireless@vger.kernel.org

This patch adds the initialisation of some PHY registers
from the modal_header[] values in the EEPROM (see otus/hal/hpmain.c, line 333 ff.)

Signed-off-by: Joerg Albert <jal2@gmx.de>

---
 drivers/net/wireless/ath/ar9170/phy.c |  129 ++++++++++++++++++++++++++++++++-
 1 files changed, 128 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c
index cb8b5cd..47a5e5c 100644
--- a/drivers/net/wireless/ath/ar9170/phy.c
+++ b/drivers/net/wireless/ath/ar9170/phy.c
@@ -396,6 +396,131 @@ static struct ar9170_phy_init ar5416_phy_init[] = {
 	{ 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, }
 };
 
+/* look up a certain register in ar5416_phy_init[] and return the init. value
+   for the band and bandwidth given. Return 0 if register address not found. */
+u32 ar9170_get_default_phy_reg_val(int reg, bool is_2ghz, bool is_40mhz)
+{
+	struct ar9170_phy_init *p;
+	struct ar9170_phy_init *endp =
+		ar5416_phy_init+ARRAY_SIZE(ar5416_phy_init);
+
+	for (p = ar5416_phy_init; p < endp; p++)
+		if (p->reg == reg) {
+			if (is_2ghz)
+				return is_40mhz ? p->_2ghz_40 : p->_2ghz_20;
+			else
+				return is_40mhz ? p->_5ghz_40 : p->_5ghz_20;
+		}
+	return 0;
+}
+
+/* initialize some phy regs from eeprom values in modal_header[]
+   acc. to band and bandwith */
+static int ar9170_init_phy_from_eeprom(struct ar9170 *ar,
+				bool is_2ghz, bool is_40mhz)
+{
+	const u8 xpd2pd[16] = {
+		0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2,
+		0x2, 0x3, 0x7, 0x2, 0xB, 0x2, 0x2, 0x2
+	};
+	u32 defval, newval; /* two separate for debugging the changes */
+	/* pointer to the modal_header acc. to band */
+	struct ar9170_eeprom_modal *m = ar->eeprom.modal_header +
+		(is_2ghz ? 1 : 0);
+
+	ar9170_regwrite_begin(ar);
+
+	/* ant common control (index 0) */
+	defval = ar9170_get_default_phy_reg_val(0x1c5964, is_2ghz, is_40mhz);
+	newval = le32_to_cpu(m->antCtrlCommon);
+	ar9170_regwrite(0x1c5964, newval);
+
+	/* ant control chain 0 (index 1) */
+	defval = ar9170_get_default_phy_reg_val(0x1c5960, is_2ghz, is_40mhz);
+	newval = le32_to_cpu(m->antCtrlChain[0]);
+	ar9170_regwrite(0x1c5960, newval);
+
+	/* ant control chain 2 (index 2) */
+	defval = ar9170_get_default_phy_reg_val(0x1c7960, is_2ghz, is_40mhz);
+	newval = le32_to_cpu(m->antCtrlChain[1]);
+	ar9170_regwrite(0x1c7960, newval);
+
+	/* SwSettle (index 3) */
+	if (!is_40mhz) {
+		defval = ar9170_get_default_phy_reg_val(0x1c5844,
+							is_2ghz, is_40mhz);
+		newval = (defval & ~0x3f80) | ((m->switchSettling & 0x7f)<<7);
+		ar9170_regwrite(0x1c5844, newval);
+	}
+
+	/* adcDesired, pdaDesired (index 4) */
+	defval = ar9170_get_default_phy_reg_val(0x1c5850, is_2ghz, is_40mhz);
+	newval = (defval & ~0xffff) | ((u8)m->pgaDesiredSize << 8) |
+		((u8)m->adcDesiredSize);
+	ar9170_regwrite(0x1c5850, newval);
+
+	/* TxEndToXpaOff, TxFrameToXpaOn (index 5) */
+	defval = ar9170_get_default_phy_reg_val(0x1c5834, is_2ghz, is_40mhz);
+	newval = (m->txEndToXpaOff << 24) | (m->txEndToXpaOff << 16) |
+		(m->txFrameToXpaOn << 8) | m->txFrameToXpaOn;
+	ar9170_regwrite(0x1c5834, newval);
+
+	/* TxEndToRxOn (index 6) */
+	defval = ar9170_get_default_phy_reg_val(0x1c5828, is_2ghz, is_40mhz);
+	newval = (defval & ~0xff0000) | (m->txEndToRxOn << 16);
+	ar9170_regwrite(0x1c5828, newval);
+
+	/* thresh62 (index 7) */
+	defval = ar9170_get_default_phy_reg_val(0x1c8864, is_2ghz, is_40mhz);
+	newval = (defval & ~0x7f000) | (m->thresh62 << 12);
+	ar9170_regwrite(0x1c8864, newval);
+
+	/* tx/rx attenuation chain 0 (index 8) */
+	defval = ar9170_get_default_phy_reg_val(0x1c5848, is_2ghz, is_40mhz);
+	newval = (defval & ~0x3f000) | ((m->txRxAttenCh[0] & 0x3f) << 12);
+	ar9170_regwrite(0x1c5848, newval);
+
+	/* tx/rx attenuation chain 2 (index 9) */
+	defval = ar9170_get_default_phy_reg_val(0x1c7848, is_2ghz, is_40mhz);
+	newval = (defval & ~0x3f000) | ((m->txRxAttenCh[1] & 0x3f) << 12);
+	ar9170_regwrite(0x1c7848, newval);
+
+	/* tx/rx margin chain 0 (index 10) */
+	defval = ar9170_get_default_phy_reg_val(0x1c620c, is_2ghz, is_40mhz);
+	newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[0] & 0x3f) << 18);
+	/* bsw margin chain 0 for 5GHz only */
+	if (!is_2ghz)
+		newval = (newval & ~0x3c00) | ((m->bswMargin[0] & 0xf) << 10);
+	ar9170_regwrite(0x1c620c, newval);
+
+	/* tx/rx margin chain 2 (index 11) */
+	defval = ar9170_get_default_phy_reg_val(0x1c820c, is_2ghz, is_40mhz);
+	newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[1] & 0x3f) << 18);
+	ar9170_regwrite(0x1c820c, newval);
+
+	/* iqCall, iqCallq chain 0 (index 12) */
+	defval = ar9170_get_default_phy_reg_val(0x1c5920, is_2ghz, is_40mhz);
+	newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[0] & 0x3f) << 5) |
+		((u8)m->iqCalQCh[0] & 0x1f);
+	ar9170_regwrite(0x1c5920, newval);
+
+	/* iqCall, iqCallq chain 2 (index 13) */
+	defval = ar9170_get_default_phy_reg_val(0x1c7920, is_2ghz, is_40mhz);
+	newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[1] & 0x3f) << 5) |
+		((u8)m->iqCalQCh[1] & 0x1f);
+	ar9170_regwrite(0x1c7920, newval);
+
+	/* xpd gain mask (index 14) */
+	defval = ar9170_get_default_phy_reg_val(0x1c6258, is_2ghz, is_40mhz);
+	newval = (defval & ~0xf0000) | (xpd2pd[m->xpdGain & 0xf] << 16);
+	ar9170_regwrite(0x1c6258, newval);
+
+
+	ar9170_regwrite_finish();
+
+	return ar9170_regwrite_result();
+}
+
 int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
 {
 	int i, err;
@@ -426,7 +551,9 @@ int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
 	if (err)
 		return err;
 
-	/* XXX: use EEPROM data here! */
+	err = ar9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz);
+	if (err)
+		return err;
 
 	err = ar9170_init_power_cal(ar);
 	if (err)
-- 
1.6.0.4



^ permalink raw reply related

* Re: rtl8187b Problem with tx level
From: Larry Finger @ 2009-08-30 23:00 UTC (permalink / raw)
  To: Tobias Schlemmer; +Cc: linux-wireless
In-Reply-To: <h7eo7q$7ks$1@ger.gmane.org>

Tobias Schlemmer wrote:
> 
> Interestingly iwconfig always reports TX power of 20dBm, regardless of
> the actual tx power, but always a TX rate of 1M. Setting the latter to a
> higher value results in packet loss.

Where are you located? Your log says you are using the EU regulatory
domain; however, that is no longer valid. You should add a line like

options cfg80211 ieee80211_regdom=XX

to /etc/modprobe.conf.local. From your name, I would guess the XX
should be DE.

It is likely that the 20 dBm is set by mac80211 as the maximum allowed
by your local regulations. That value is in fact correct for most
locations in the EU.

My rtl8187b runs at a full 54 Mbs and operates at at least 15 m from
my AP. I don't run AP firmware that lets me see the signal strength
from the STA.

^ permalink raw reply

* Re: [PATCH -next] ipw2200: fix kconfig dependencies
From: John W. Linville @ 2009-08-30 22:35 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: linux-wireless, ipw2100-devel, akpm
In-Reply-To: <4A9ADFA1.5030706@oracle.com>

On Sun, Aug 30, 2009 at 01:22:57PM -0700, Randy Dunlap wrote:
> From: Randy Dunlap <randy.dunlap@oracle.com>
> 
> Fix kconfig dependencies for ipw2x00 drivers, fixes build errors:
> 
> ERROR: "wiphy_free" [drivers/net/wireless/ipw2x00/libipw.ko] undefined!
> ERROR: "wiphy_unregister" [drivers/net/wireless/ipw2x00/libipw.ko] undefined!
> ERROR: "wiphy_new" [drivers/net/wireless/ipw2x00/libipw.ko] undefined!
> ERROR: "cfg80211_wext_giwname" [drivers/net/wireless/ipw2x00/ipw2200.ko] undefined!
> ERROR: "wiphy_register" [drivers/net/wireless/ipw2x00/ipw2200.ko] undefined!
> 
> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>

Oops!  My bad...thanks, Randy!

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* rtl8187b Problem with tx level
From: Tobias Schlemmer @ 2009-08-30 20:44 UTC (permalink / raw)
  To: linux-wireless

[-- Attachment #1: Type: text/plain, Size: 1527 bytes --]

Hi,

I have some problem with my rtl8187b device. It is included in my laptop 
running Ubuntu linux 2.6.28. I've tested several compat-wireless 
releases including 2.6.30 and 2.6.31-rc7.

The problem is that the network adapter looses the connection to the 
access point at very low distances. It seems to be as if the driver is 
too optimistic about tx power. I monitored the singnal strength on the 
access point (Buffalo running DD-WRT). When I associate the laptop with 
it the recieved signal strength starts full and drops rapidly in the 
first seconds. At the end it is about 0 at a distance of 4m. At this 
moment no ping will arrive the destination. Tests with other access 
points show similar results.

After several attempts to get different drivers working I used an Ubuntu 
8.04 boot CD this morning which seems to work out of the box. It has 
kernel 2.6.24 using a module called r8187. I compared these two drivers 
and got much better signal strengths, at least more stable connections. 
Maybe it's interesting that the two drivers report different signal 
strength (compat-wireless reports about 10dBm higher values than the old 
driver) also in signal quality the compat wireless driver seems to be 
more optimistic.

Interestingly iwconfig always reports TX power of 20dBm, regardless of 
the actual tx power, but always a TX rate of 1M. Setting the latter to a 
higher value results in packet loss.

As I leave for holidays on Tuesday I can give further information only 
tomorrow and in two weeks.

Tobias

[-- Attachment #2: eventlog --]
[-- Type: text/plain, Size: 3844 bytes --]

Log of iw event -t 
Sun Aug 30 21:26:57 2009

iwdied with signal 2

Sun Aug 30 21:27:22 2009
----------------
1251660460.087134: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660481.753561: wlan0 (phy #0): disassoc 00:16:44:fb:52:6c -> 00:17:3f:7e:ab:08 reason 1: Unspecified
1251660486.831135: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660487.041865: wlan0 (phy #0): auth 00:17:3f:7e:ab:08 -> 00:16:44:fb:52:6c status: 0: Successful
1251660487.050600: wlan0 (phy #0): assoc 00:17:3f:7e:ab:08 -> 00:16:44:fb:52:6c status: 0: Successful
1251660588.213505: wlan0 (phy #0): deauth 00:16:44:fb:52:6c -> 00:17:3f:7e:ab:08 reason 3: Deauthenticated because sending station is leaving (or has left) the IBSS or ESS
1251660600.900453: wlan0 (phy #0): scan aborted: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660607.237699: wlan0 (phy #0): disassoc 00:16:44:fb:52:6c -> 00:17:3f:7e:ab:08 reason 1: Unspecified
1251660613.427166: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660614.348485: wlan0 (phy #0): auth: timed out
1251660620.263160: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660621.152487: wlan0 (phy #0): auth: timed out
1251660626.311193: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660627.200489: wlan0 (phy #0): auth: timed out
1251660632.359167: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660633.248491: wlan0 (phy #0): auth: timed out
1251660638.415165: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660639.304490: wlan0 (phy #0): auth: timed out
1251660644.467730: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660645.356493: wlan0 (phy #0): auth: timed out
1251660650.519172: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660651.419254: wlan0 (phy #0): auth: timed out
1251660656.587182: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660657.512517: wlan0 (phy #0): auth: timed out
1251660662.655181: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660663.532509: wlan0 (phy #0): auth: timed out
1251660668.711181: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660669.588513: wlan0 (phy #0): auth: timed out
1251660674.779164: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660675.656519: wlan0 (phy #0): auth: timed out
1251660680.943163: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660681.836528: wlan0 (phy #0): auth: timed out
1251660686.879163: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660687.768520: wlan0 (phy #0): auth: timed out
1251660692.927168: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660693.816525: wlan0 (phy #0): auth: timed out
1251660698.975165: wlan0 (phy #0): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472 2484, ""
1251660699.400865: wlan0 (phy #0): auth 00:17:3f:7e:ab:08 -> 00:16:44:fb:52:6c status: 0: Successful
1251660699.412964: wlan0 (phy #0): assoc 00:17:3f:7e:ab:08 -> 00:16:44:fb:52:6c status: 0: Successful


[-- Attachment #3: kernel-short.log --]
[-- Type: text/x-log, Size: 3813 bytes --]

[  346.940054] usb 1-1: new high speed USB device using ehci_hcd and address 4
[  347.086851] usb 1-1: configuration #1 chosen from 1 choice
[  347.418280] cfg80211: Calling CRDA for country: EU
[  348.348579] phy0: Selected rate control algorithm 'minstrel'
[  348.349108] phy0: hwaddr e3c7a080, RTL8187BvE V0 + rtl8225z2
[  348.349131] usbcore: registered new interface driver rtl8187
[  361.807409] phy0: device now idle
[  361.878423] ADDRCONF(NETDEV_UP): wlan0: link is not ready
[  361.893826] phy0: device no longer idle - scanning
[  364.225226] phy0: device now idle
[  364.806379] phy0: device no longer idle - scanning
[  366.893227] phy0: device now idle
[  390.835706] phy0: device no longer idle - scanning
[  392.917362] phy0: device now idle
[  412.002426] ADDRCONF(NETDEV_UP): wlan0: link is not ready
[  412.371061] phy0: device no longer idle - scanning
[  414.498373] wlan0: authenticate with AP e3c7b708
[  414.498397] wlan0: privacy configuration mismatch and mixed-cell disabled - disassociate
[  414.499742] phy0: device now idle
[  417.572157] phy0: device no longer idle - scanning
[  419.649259] phy0: device now idle
[  419.718250] phy0: device no longer idle - in use
[  419.785249] wlan0: authenticate with AP e3c7b708
[  419.786755] wlan0: authenticated
[  419.786756] wlan0: associate with AP e3c7b708
[  419.789134] wlan0: RX AssocResp from e3f8201a (capab=0x411 status=0 aid=3)
[  419.789138] wlan0: associated
[  419.789142] phy0: Allocated STA e3c00a08
[  419.789403] phy0: Inserted STA e3c00a08
[  419.790372] wlan0: switched to short barker preamble (BSSID=e3c7b708)
[  419.790374] wlan0: switched to short slot time (BSSID=e3c7b708)
[  419.795862] ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
[  420.664625] padlock: VIA PadLock not detected.
[  426.992527] wlan0: setting MTU 1492
[  429.796020] wlan0: no IPv6 routers present
[  465.032820] usb 2-2: USB disconnect, address 2
[  520.958259] wlan0: deauthenticating by local choice (reason=3)
[  520.959293] phy0: device now idle
[  521.037304] phy0: Removed STA e3c00a08
[  521.037411] phy0: Destroyed STA e3c00a08
[  524.902800] ADDRCONF(NETDEV_UP): wlan0: link is not ready
[  533.450798] ADDRCONF(NETDEV_UP): wlan0: link is not ready
[  533.452844] phy0: device no longer idle - scanning
[  533.645340] phy0: device now idle
[  537.890760] ADDRCONF(NETDEV_UP): wlan0: link is not ready
[  537.890876] phy0: device no longer idle - scanning
[  539.982438] wlan0: direct probe to AP e3c7b708 try 1
[  539.982476] wlan0: privacy configuration mismatch and mixed-cell disabled - disassociate
[  539.983926] phy0: device now idle
[  543.973724] phy0: device no longer idle - scanning
[  546.270791] phy0: device now idle
[  546.358314] phy0: device no longer idle - in use
[  546.425311] wlan0: direct probe to AP e3c7b708 try 1
[  546.624050] wlan0: direct probe to AP e3c7b708 try 2
[  546.824039] wlan0: direct probe to AP e3c7b708 try 3
[  547.024037] wlan0: direct probe to AP e3c7b708 timed out
[  547.024044] phy0: device now idle
[  551.030732] phy0: device no longer idle - scanning
[  553.093323] phy0: device now idle
[  553.162315] phy0: device no longer idle - in use
[  553.229316] wlan0: direct probe to AP e3c7b708 try 1
[  553.428042] wlan0: direct probe to AP e3c7b708 try 2
[  553.628037] wlan0: direct probe to AP e3c7b708 try 3
[  553.828036] wlan0: direct probe to AP e3c7b708 timed out
[  553.828043] phy0: device now idle
[  557.082433] phy0: device no longer idle - scanning
[  559.141327] phy0: device now idle
[  559.210312] phy0: device no longer idle - in use
[  559.277319] wlan0: direct probe to AP e3c7b708 try 1
[  559.476045] wlan0: direct probe to AP e3c7b708 try 2
[  559.676044] wlan0: direct probe to AP e3c7b708 try 3
[  559.876044] wlan0: direct probe to AP e3c7b708 timed out


[-- Attachment #4: lsusb --]
[-- Type: text/plain, Size: 5080 bytes --]

Bus 001 Device 004: ID 0bda:8189 Realtek Semiconductor Corp. RTL8187B Wireless 802.11g 54Mbps Network Adapter
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x0bda Realtek Semiconductor Corp.
  idProduct          0x8189 RTL8187B Wireless 802.11g 54Mbps Network Adapter
  bcdDevice            2.00
  iManufacturer           1 Manufacturer_Realtek
  iProduct                2 
  iSerial                 3 00e04c000001
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           81
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          4 Wireless Network Card
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           9
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              2 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x05  EP 5 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x06  EP 6 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x07  EP 7 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x89  EP 9 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x0a  EP 10 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x0b  EP 11 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x0c  EP 12 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  bNumConfigurations      1
Device Status:     0x0000
  (Bus Powered)


^ permalink raw reply

* [PATCH -next] ipw2200: fix kconfig dependencies
From: Randy Dunlap @ 2009-08-30 20:22 UTC (permalink / raw)
  To: linux-wireless; +Cc: ipw2100-devel, linville, akpm

From: Randy Dunlap <randy.dunlap@oracle.com>

Fix kconfig dependencies for ipw2x00 drivers, fixes build errors:

ERROR: "wiphy_free" [drivers/net/wireless/ipw2x00/libipw.ko] undefined!
ERROR: "wiphy_unregister" [drivers/net/wireless/ipw2x00/libipw.ko] undefined!
ERROR: "wiphy_new" [drivers/net/wireless/ipw2x00/libipw.ko] undefined!
ERROR: "cfg80211_wext_giwname" [drivers/net/wireless/ipw2x00/ipw2200.ko] undefined!
ERROR: "wiphy_register" [drivers/net/wireless/ipw2x00/ipw2200.ko] undefined!

Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
---
 drivers/net/wireless/ipw2x00/Kconfig |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

--- linux-next-20090828.orig/drivers/net/wireless/ipw2x00/Kconfig
+++ linux-next-20090828/drivers/net/wireless/ipw2x00/Kconfig
@@ -4,7 +4,7 @@
 
 config IPW2100
 	tristate "Intel PRO/Wireless 2100 Network Connection"
-	depends on PCI && WLAN_80211
+	depends on PCI && WLAN_80211 && CFG80211
 	select WIRELESS_EXT
 	select FW_LOADER
 	select LIB80211
@@ -63,7 +63,7 @@ config IPW2100_DEBUG
 
 config IPW2200
 	tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
-	depends on PCI && WLAN_80211
+	depends on PCI && WLAN_80211 && CFG80211
 	select WIRELESS_EXT
 	select FW_LOADER
 	select LIB80211
@@ -150,7 +150,7 @@ config IPW2200_DEBUG
 
 config LIBIPW
 	tristate
-	depends on PCI && WLAN_80211
+	depends on PCI && WLAN_80211 && CFG80211
 	select WIRELESS_EXT
 	select CRYPTO
 	select CRYPTO_ARC4

^ permalink raw reply

* Re: [rt2x00-users] [PATCH] rt2x00: Reorganize padding & L2 padding
From: Benoit PAPILLAULT @ 2009-08-30 19:47 UTC (permalink / raw)
  To: rt2x00 Users List; +Cc: linux-wireless
In-Reply-To: <200908301532.47769.IvDoorn@gmail.com>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Ivo van Doorn a écrit :
>>> +void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int
>>> header_length) +{ +    struct skb_frame_desc *skbdesc =
>>> get_skb_frame_desc(skb); +    unsigned int l2pad = 4 - (header_length
>>> & 3);
>> This formula is incorrect, it should be at least (4 -
>> (header_length%4)%4). I have a fix in my pending patches...
>> If header_length is 0 => l2pad should be 0 as well.
> 
> Header_length should never be 0 (that was fixed by this patch), so that should
> not be a problem. I'll review your patch so it can be send as update later. But I
> do think this patch can be merged into linux-wireless in regardless.
> 
> Ivo
> 
> P.S. Your mail client is really messing up the replies by removing end-of-line
> characters. :S

Sorry about my mail client (there was an HTML conversion). It should be
fixed now.

Regards,
Benoit
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkqa12MACgkQOR6EySwP7oIviQCdHXzTBbHuFuJE5BulKy1+a80z
rHMAnA4nL9XEz7sYAK5ifcQypJkNkcki
=Rg+z
-----END PGP SIGNATURE-----

^ permalink raw reply

* Re: ath9k DMA problems
From: Kunal Gangakhedkar @ 2009-08-30 18:00 UTC (permalink / raw)
  To: Howard Chu; +Cc: linux-wireless@vger.kernel.org, ath9k-devel@lists.ath9k.org
In-Reply-To: <4A987F0F.9040905@symas.com>

On Saturday 29 Aug 2009 6:36:23 am Howard Chu wrote:
> Am I the only one having these problems? ath9k hasn't worked well for me
> since 2.6.29.4; every snapshot since then has suffered from random drops.
> In 2.6.29.6 it at least would quickly reassociate. The current ones hang
> within 20-30 minutes of use and never come back. The compat-wireless
> snapshots have all been equally unusable.
>
> Howard Chu wrote:
> > Still seeing occasional hangs using the ath9k in 2.6.31-rc6, and even
> > worse using compat-wireless 2009-08-22. Today I got this which was even
> > more interesting:
> >
> > [369014.776586] wlan0: associate with AP 00:12:17:26:56:10 (try 1)
> > [369014.779197] wlan0: RX ReassocResp from 00:12:17:26:56:10 (capab=0x411
> > status=0 aid=2)
> > [369014.779197] wlan0: associated
> > [369472.707961] ath9k: DMA failed to stop in 10 ms AR_CR=0xdeadbeef
> > AR_DIAG_SW=0xdeadbeef
> >
> > This is on an HP dv5z laptop, it reports an AR9280 at boot.

Neither for me - I'm on an HP dv6 series laptop and have AR9285 chip.
I have also posted my logs to the ath9k-devel list, but yet to receive any 
further response.

The driver seems quite erratic - especially under heavy network load & also 
after pm-resume.

Admittedly, I haven't tried compat-wireless at all.

Kunal

^ permalink raw reply

* Re: [PATCH v2] b43: LP-PHY: Begin implementing calibration & software RFKILL support
From: Michael Buesch @ 2009-08-30 15:55 UTC (permalink / raw)
  To: Larry Finger
  Cc: Gábor Stefanik, John Linville, Mark Huijgen,
	Broadcom Wireless, linux-wireless
In-Reply-To: <4A9A965F.8020200@lwfinger.net>

On Sunday 30 August 2009 17:10:23 Larry Finger wrote:
> Michael Buesch wrote:
> > On Sunday 30 August 2009 02:15:55 Gábor Stefanik wrote:
> >>  static void lpphy_pr41573_workaround(struct b43_wldev *dev)
> >>  {
> >>  	struct b43_phy_lp *lpphy = dev->phy.lp;
> >> @@ -1357,28 +1488,440 @@ static void lpphy_pr41573_workaround(struct b43_wldev *dev)
> >>  		b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140),
> >>  				    saved_tab_size, saved_tab);
> >>  	}
> >> +	b43_put_phy_into_reset(dev);
> > 
> > Are you sure you really want this?
> > This function completely disables the PHY on the backplane and keeps the physical
> > PHY reset pin asserted (even after return from the function).
> > So the PHY will physically be powered down from this point on. The following
> > PHY accesses could even hang the machine, because the PHY won't respond to
> > register accesses anymore.
> > 
> > We currently only use this function on A/G Multi-PHY devices to permanently
> > hard-disable the PHY that's not used.
> 
> The PHY reset routine in
> http://bcm-v4.sipsolutions.net/802.11/PHY/Reset, which I just updated
> for the latest N PHY changes, appears to be a different routine than
> b43_put_phy_into_reset(). The names are confusing.

b43_put_phy_into_reset() is opencoded in the specifications in various init
routines. There's no separate specs page for that function.
But I think the code is straightforward and easy to understand.

-- 
Greetings, Michael.

^ permalink raw reply

* Re: [PATCH v2] b43: LP-PHY: Begin implementing calibration & software RFKILL support
From: Larry Finger @ 2009-08-30 15:10 UTC (permalink / raw)
  To: Michael Buesch
  Cc: Gábor Stefanik, John Linville, Mark Huijgen,
	Broadcom Wireless, linux-wireless
In-Reply-To: <200908301228.16845.mb@bu3sch.de>

Michael Buesch wrote:
> On Sunday 30 August 2009 02:15:55 Gábor Stefanik wrote:
>>  static void lpphy_pr41573_workaround(struct b43_wldev *dev)
>>  {
>>  	struct b43_phy_lp *lpphy = dev->phy.lp;
>> @@ -1357,28 +1488,440 @@ static void lpphy_pr41573_workaround(struct b43_wldev *dev)
>>  		b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140),
>>  				    saved_tab_size, saved_tab);
>>  	}
>> +	b43_put_phy_into_reset(dev);
> 
> Are you sure you really want this?
> This function completely disables the PHY on the backplane and keeps the physical
> PHY reset pin asserted (even after return from the function).
> So the PHY will physically be powered down from this point on. The following
> PHY accesses could even hang the machine, because the PHY won't respond to
> register accesses anymore.
> 
> We currently only use this function on A/G Multi-PHY devices to permanently
> hard-disable the PHY that's not used.

The PHY reset routine in
http://bcm-v4.sipsolutions.net/802.11/PHY/Reset, which I just updated
for the latest N PHY changes, appears to be a different routine than
b43_put_phy_into_reset(). The names are confusing.

Larry

^ permalink raw reply

* Re: [rt2x00-users] [PATCH] rt2x00: Reorganize padding & L2 padding
From: Ivo van Doorn @ 2009-08-30 13:32 UTC (permalink / raw)
  To: users; +Cc: Benoit PAPILLAULT, linux-wireless
In-Reply-To: <4A9990A8.1080002@free.fr>

> > +void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int
> > header_length) +{ +    struct skb_frame_desc *skbdesc =
> > get_skb_frame_desc(skb); +    unsigned int l2pad = 4 - (header_length
> > & 3);
> This formula is incorrect, it should be at least (4 -
> (header_length%4)%4). I have a fix in my pending patches...
> If header_length is 0 => l2pad should be 0 as well.

Header_length should never be 0 (that was fixed by this patch), so that should
not be a problem. I'll review your patch so it can be send as update later. But I
do think this patch can be merged into linux-wireless in regardless.

Ivo

P.S. Your mail client is really messing up the replies by removing end-of-line
characters. :S

^ permalink raw reply

* Re: [rt2x00-users] [PATCH] rt2x00: Fix TX status reporting
From: Ivo van Doorn @ 2009-08-30 13:30 UTC (permalink / raw)
  To: users; +Cc: Benoit PAPILLAULT, linux-wireless
In-Reply-To: <4A999024.6060800@free.fr>

On Saturday 29 August 2009, Benoit PAPILLAULT wrote:
> Ivo van Doorn a écrit :
> > Not all values of the TX status enumeration were covered during
> > updating of the TX statistics. This could lead to wrong bitrate
> > tuning but also wrong behavior in tools like hostapd.
> >
> > Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
> I have a pending patch about TX status that changed the meaning of
> TXDONE_FALLBACK just a bit... just to avoid this change in fact.
> I should be able to send those patches in few hours.
> 
> In my code, you success/failure of the packet is reported with
> TXDONE_SUCCESS / TXDONE_FAILURE. The TXDONE_FALLBACK is set
> independently to indicate that a fallback rate table has been used
> (and this could be the case for either success or failure).

Well that shouldn't block this patch at this time since it is a bugfix which
is quite important to get minstrel and hostapd working properly.

Once I have reviewed your patch it can be send upstream immediately or
in a single batch together with the rt2800pci driver. ;)

Ivo

^ permalink raw reply

* Re: ipw2200: firmware DMA loading rework
From: Bartlomiej Zolnierkiewicz @ 2009-08-30 12:37 UTC (permalink / raw)
  To: Zhu Yi
  Cc: Andrew Morton, Mel Gorman, Johannes Weiner, Pekka Enberg,
	Rafael J. Wysocki, Linux Kernel Mailing List, Kernel Testers List,
	Mel Gorman, netdev@vger.kernel.org, linux-mm@kvack.org,
	James Ketrenos, Chatre, Reinette, linux-wireless@vger.kernel.org,
	ipw2100-devel@lists.sourceforge.net
In-Reply-To: <1251430951.3704.181.camel@debian>

On Friday 28 August 2009 05:42:31 Zhu Yi wrote:
> Bartlomiej Zolnierkiewicz reported an atomic order-6 allocation failure
> for ipw2200 firmware loading in kernel 2.6.30. High order allocation is

s/2.6.30/2.6.31-rc6/

The issue has always been there but it was some recent change that
explicitly triggered the allocation failures (after 2.6.31-rc1).

> likely to fail and should always be avoided.
> 
> The patch fixes this problem by replacing the original order-6
> pci_alloc_consistent() with an array of order-1 pages from a pci pool.
> This utilized the ipw2200 DMA command blocks (up to 64 slots). The
> maximum firmware size support remains the same (64*8K).
> 
> This patch fixes bug http://bugzilla.kernel.org/show_bug.cgi?id=14016
> 
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Mel Gorman <mel@csn.ul.ie>
> Signed-off-by: Zhu Yi <yi.zhu@intel.com>

Thanks for the fix (also kudos to other people helping with the bugreport),
it works fine so far and looks OK to me:

Tested-and-reviewed-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>

^ permalink raw reply

* Re: [PATCH v2] b43: LP-PHY: Begin implementing calibration & software RFKILL support
From: Michael Buesch @ 2009-08-30 10:28 UTC (permalink / raw)
  To: Gábor Stefanik
  Cc: John Linville, Larry Finger, Mark Huijgen, Broadcom Wireless,
	linux-wireless
In-Reply-To: <4A99C4BB.7080806@gmail.com>

On Sunday 30 August 2009 02:15:55 Gábor Stefanik wrote:
>  static void lpphy_pr41573_workaround(struct b43_wldev *dev)
>  {
>  	struct b43_phy_lp *lpphy = dev->phy.lp;
> @@ -1357,28 +1488,440 @@ static void lpphy_pr41573_workaround(struct b43_wldev *dev)
>  		b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140),
>  				    saved_tab_size, saved_tab);
>  	}
> +	b43_put_phy_into_reset(dev);

Are you sure you really want this?
This function completely disables the PHY on the backplane and keeps the physical
PHY reset pin asserted (even after return from the function).
So the PHY will physically be powered down from this point on. The following
PHY accesses could even hang the machine, because the PHY won't respond to
register accesses anymore.

We currently only use this function on A/G Multi-PHY devices to permanently
hard-disable the PHY that's not used.

> +	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFF8);
> +	lpphy_table_init(dev); //FIXME is table init needed?
> +	lpphy_baseband_init(dev);
> +	b43_lpphy_op_software_rfkill(dev, false);
> +	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
> +	if (dev->phy.rev < 2) {
> +		b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0x140),
> +				     saved_tab_size, saved_tab);
> +	} else {
> +		b43_lptab_write_bulk(dev, B43_LPTAB32(7, 0x140),
> +				     saved_tab_size, saved_tab);
> +	}
> +	b43_write16(dev, B43_MMIO_CHANNEL, lpphy->channel);
> +	lpphy->tssi_npt = tssi_npt;
> +	lpphy->tssi_idx = tssi_idx;
> +	lpphy_set_analog_filter(dev, lpphy->channel);
> +	if (tx_pwr_idx_over != -1)
> +		lpphy_set_tx_power_by_index(dev, tx_pwr_idx_over);
> +	if (lpphy->rc_cap)
> +		lpphy_set_rc_cap(dev);
> +	b43_lpphy_op_set_rx_antenna(dev, lpphy->antenna);
> +	lpphy_set_tx_power_control(dev, txpctl_mode);
> +	kfree(saved_tab);
> +}

-- 
Greetings, Michael.

^ permalink raw reply

* [PATCH v2] b43: LP-PHY: Begin implementing calibration & software RFKILL support
From: Gábor Stefanik @ 2009-08-30  0:15 UTC (permalink / raw)
  To: John Linville, Michael Buesch, Larry Finger, Mark Huijgen
  Cc: Broadcom Wireless, linux-wireless

This implements the following calibration functions:
-Set TX IQCC
-Set TX Power by Index
-PR41573 workaround
-Calc RX IQ Comp
-PHY Cordic
-Run Samples
-Start/Stop TX Tone
-part of PAPD Cal TX Power
-RX I/Q Calibration
-The basic structure of the periodic calibration wrapper

Software RFKILL (required by calibration) is also implemented in
this round.

Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
V2: Fix a mistake I made in the PHY Cordic routine.

 drivers/net/wireless/b43/main.c   |    2 +-
 drivers/net/wireless/b43/main.h   |    2 +
 drivers/net/wireless/b43/phy_lp.c |  686 ++++++++++++++++++++++++++++++++-----
 drivers/net/wireless/b43/phy_lp.h |   11 +-
 4 files changed, 613 insertions(+), 88 deletions(-)

diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index f2c5b2d..59bee02 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3345,7 +3345,7 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
 	mutex_unlock(&wl->mutex);
 }
 
-static void b43_put_phy_into_reset(struct b43_wldev *dev)
+void b43_put_phy_into_reset(struct b43_wldev *dev)
 {
 	struct ssb_device *sdev = dev->dev;
 	u32 tmslow;
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index 0406e06..fdbea9a 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -129,6 +129,8 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
 
 void b43_controller_restart(struct b43_wldev *dev, const char *reason);
 
+void b43_put_phy_into_reset(struct b43_wldev *dev);
+
 #define B43_PS_ENABLED	(1 << 0)	/* Force enable hardware power saving */
 #define B43_PS_DISABLED	(1 << 1)	/* Force disable hardware power saving */
 #define B43_PS_AWAKE	(1 << 2)	/* Force device awake */
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 5fff30a..c13385b 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -67,6 +67,7 @@ static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev)
 	struct b43_phy_lp *lpphy = phy->lp;
 
 	memset(lpphy, 0, sizeof(*lpphy));
+	lpphy->antenna = B43_ANTENNA_DEFAULT;
 
 	//TODO
 }
@@ -751,11 +752,17 @@ static void lpphy_clear_deaf(struct b43_wldev *dev, bool user)
 	}
 }
 
+static void lpphy_set_trsw_over(struct b43_wldev *dev, bool tx, bool rx)
+{
+	u16 trsw = (tx << 1) | rx;
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, trsw);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+}
+
 static void lpphy_disable_crs(struct b43_wldev *dev, bool user)
 {
 	lpphy_set_deaf(dev, user);
-	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1);
-	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+	lpphy_set_trsw_over(dev, false, true);
 	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
 	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
 	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFF7);
@@ -790,6 +797,60 @@ static void lpphy_restore_crs(struct b43_wldev *dev, bool user)
 
 struct lpphy_tx_gains { u16 gm, pga, pad, dac; };
 
+static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
+{
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
+	if (dev->phy.rev >= 2) {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
+			b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7);
+		}
+	} else {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
+	}
+}
+
+static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
+{
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
+	if (dev->phy.rev >= 2) {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
+			b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8);
+		}
+	} else {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
+	}
+}
+
+static void lpphy_disable_tx_gain_override(struct b43_wldev *dev)
+{
+	if (dev->phy.rev < 2)
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
+	else {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F);
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF);
+	}
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF);
+}
+
+static void lpphy_enable_tx_gain_override(struct b43_wldev *dev)
+{
+	if (dev->phy.rev < 2)
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
+	else {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x80);
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x4000);
+	}
+	b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x40);
+}
+
 static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
 {
 	struct lpphy_tx_gains gains;
@@ -819,6 +880,17 @@ static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
 	b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
 }
 
+static u16 lpphy_get_pa_gain(struct b43_wldev *dev)
+{
+	return b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F;
+}
+
+static void lpphy_set_pa_gain(struct b43_wldev *dev, u16 gain)
+{
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xFB), 0xE03F, gain << 6);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xFD), 0x80FF, gain << 8);
+}
+
 static void lpphy_set_tx_gains(struct b43_wldev *dev,
 			       struct lpphy_tx_gains gains)
 {
@@ -829,8 +901,7 @@ static void lpphy_set_tx_gains(struct b43_wldev *dev,
 		b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
 				0xF800, rf_gain);
 	} else {
-		pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x1FC0;
-		pa_gain <<= 2;
+		pa_gain = lpphy_get_pa_gain(dev);
 		b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
 			      (gains.pga << 8) | gains.gm);
 		b43_phy_maskset(dev, B43_PHY_OFDM(0xFB),
@@ -841,13 +912,7 @@ static void lpphy_set_tx_gains(struct b43_wldev *dev,
 				0x8000, gains.pad | pa_gain);
 	}
 	lpphy_set_dac_gain(dev, gains.dac);
-	if (dev->phy.rev < 2) {
-		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8);
-	} else {
-		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7);
-		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14);
-	}
-	b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF, 1 << 6);
+	lpphy_enable_tx_gain_override(dev);
 }
 
 static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
@@ -887,38 +952,6 @@ static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
 	}
 }
 
-static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
-{
-	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
-	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
-	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
-	if (dev->phy.rev >= 2) {
-		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
-		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
-			b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7);
-		}
-	} else {
-		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
-	}
-}
-
-static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
-{
-	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
-	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
-	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
-	if (dev->phy.rev >= 2) {
-		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
-		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
-			b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8);
-		}
-	} else {
-		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
-	}
-}
-
 static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain)
 {
 	if (dev->phy.rev < 2)
@@ -1003,8 +1036,7 @@ static int lpphy_loopback(struct b43_wldev *dev)
 
 	memset(&iq_est, 0, sizeof(iq_est));
 
-	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3);
-	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+	lpphy_set_trsw_over(dev, true, true);
 	b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 1);
 	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
 	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
@@ -1126,7 +1158,7 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
 			b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM,
 					0x8FFF, ((u16)lpphy->tssi_npt << 16));
 			//TODO Set "TSSI Transmit Count" variable to total transmitted frame count
-			//TODO Disable TX gain override
+			lpphy_disable_tx_gain_override(dev);
 			lpphy->tx_pwr_idx_over = -1;
 		}
 	}
@@ -1312,15 +1344,73 @@ static void lpphy_calibrate_rc(struct b43_wldev *dev)
 	}
 }
 
+static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
+{
+	if (dev->phy.rev >= 2)
+		return; // rev2+ doesn't support antenna diversity
+
+	if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1))
+		return;
+
+	b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);
+
+	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2);
+	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1);
+
+	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);
+
+	dev->phy.lp->antenna = antenna;
+}
+
+static void lpphy_set_tx_iqcc(struct b43_wldev *dev, u16 a, u16 b)
+{
+	u16 tmp[2];
+
+	tmp[0] = a;
+	tmp[1] = b;
+	b43_lptab_write_bulk(dev, B43_LPTAB16(0, 80), 2, tmp);
+}
+
 static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index)
 {
 	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct lpphy_tx_gains gains;
+	u32 iq_comp, tx_gain, coeff, rf_power;
 
 	lpphy->tx_pwr_idx_over = index;
+	lpphy_read_tx_pctl_mode_from_hardware(dev);
 	if (lpphy->txpctl_mode != B43_LPPHY_TXPCTL_OFF)
 		lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_SW);
-
-	//TODO
+	if (dev->phy.rev >= 2) {
+		iq_comp = b43_lptab_read(dev, B43_LPTAB32(7, index + 320));
+		tx_gain = b43_lptab_read(dev, B43_LPTAB32(7, index + 192));
+		gains.pad = (tx_gain >> 16) & 0xFF;
+		gains.gm = tx_gain & 0xFF;
+		gains.pga = (tx_gain >> 8) & 0xFF;
+		gains.dac = (iq_comp >> 28) & 0xFF;
+		lpphy_set_tx_gains(dev, gains);
+	} else {
+		iq_comp = b43_lptab_read(dev, B43_LPTAB32(10, index + 320));
+		tx_gain = b43_lptab_read(dev, B43_LPTAB32(10, index + 192));
+		b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+				0xF800, (tx_gain >> 4) & 0x7FFF);
+		lpphy_set_dac_gain(dev, tx_gain & 0x7);
+		lpphy_set_pa_gain(dev, (tx_gain >> 24) & 0x7F);
+	}
+	lpphy_set_bb_mult(dev, (iq_comp >> 20) & 0xFF);
+	lpphy_set_tx_iqcc(dev, (iq_comp >> 10) & 0x3FF, iq_comp & 0x3FF);
+	if (dev->phy.rev >= 2) {
+		coeff = b43_lptab_read(dev, B43_LPTAB32(7, index + 448));
+	} else {
+		coeff = b43_lptab_read(dev, B43_LPTAB32(10, index + 448));
+	}
+	b43_lptab_write(dev, B43_LPTAB16(0, 85), coeff & 0xFFFF);
+	if (dev->phy.rev >= 2) {
+		rf_power = b43_lptab_read(dev, B43_LPTAB32(7, index + 576));
+		b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00,
+				rf_power & 0xFFFF);//SPEC FIXME mask & set != 0
+	}
+	lpphy_enable_tx_gain_override(dev);
 }
 
 static void lpphy_btcoex_override(struct b43_wldev *dev)
@@ -1329,6 +1419,47 @@ static void lpphy_btcoex_override(struct b43_wldev *dev)
 	b43_write16(dev, B43_MMIO_BTCOEX_TXCTL, 0xFF);
 }
 
+static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
+					 bool blocked)
+{
+	//TODO check MAC control register
+	if (blocked) {
+		if (dev->phy.rev >= 2) {
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x83FF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
+			b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0x80FF);
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xDFFF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0808);
+		} else {
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xE0FF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFCFF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0018);
+		}
+	} else {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xE0FF);
+		if (dev->phy.rev >= 2)
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xF7F7);
+		else
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFE7);
+	}
+}
+
+/* This was previously called lpphy_japan_filter */
+static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter!
+
+	if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific?
+		b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9);
+		if ((dev->phy.rev == 1) && (lpphy->rc_cap))
+			lpphy_set_rc_cap(dev);
+	} else {
+		b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F);
+	}
+}
+
 static void lpphy_pr41573_workaround(struct b43_wldev *dev)
 {
 	struct b43_phy_lp *lpphy = dev->phy.lp;
@@ -1357,28 +1488,440 @@ static void lpphy_pr41573_workaround(struct b43_wldev *dev)
 		b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140),
 				    saved_tab_size, saved_tab);
 	}
+	b43_put_phy_into_reset(dev);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFF8);
+	lpphy_table_init(dev); //FIXME is table init needed?
+	lpphy_baseband_init(dev);
+	b43_lpphy_op_software_rfkill(dev, false);
+	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
+	if (dev->phy.rev < 2) {
+		b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0x140),
+				     saved_tab_size, saved_tab);
+	} else {
+		b43_lptab_write_bulk(dev, B43_LPTAB32(7, 0x140),
+				     saved_tab_size, saved_tab);
+	}
+	b43_write16(dev, B43_MMIO_CHANNEL, lpphy->channel);
+	lpphy->tssi_npt = tssi_npt;
+	lpphy->tssi_idx = tssi_idx;
+	lpphy_set_analog_filter(dev, lpphy->channel);
+	if (tx_pwr_idx_over != -1)
+		lpphy_set_tx_power_by_index(dev, tx_pwr_idx_over);
+	if (lpphy->rc_cap)
+		lpphy_set_rc_cap(dev);
+	b43_lpphy_op_set_rx_antenna(dev, lpphy->antenna);
+	lpphy_set_tx_power_control(dev, txpctl_mode);
+	kfree(saved_tab);
+}
+
+struct lpphy_rx_iq_comp { u8 chan; s8 c1, c0; };
+
+static const struct lpphy_rx_iq_comp lpphy_5354_iq_table[] = {
+	{ .chan = 1, .c1 = -66, .c0 = 15, },
+	{ .chan = 2, .c1 = -66, .c0 = 15, },
+	{ .chan = 3, .c1 = -66, .c0 = 15, },
+	{ .chan = 4, .c1 = -66, .c0 = 15, },
+	{ .chan = 5, .c1 = -66, .c0 = 15, },
+	{ .chan = 6, .c1 = -66, .c0 = 15, },
+	{ .chan = 7, .c1 = -66, .c0 = 14, },
+	{ .chan = 8, .c1 = -66, .c0 = 14, },
+	{ .chan = 9, .c1 = -66, .c0 = 14, },
+	{ .chan = 10, .c1 = -66, .c0 = 14, },
+	{ .chan = 11, .c1 = -66, .c0 = 14, },
+	{ .chan = 12, .c1 = -66, .c0 = 13, },
+	{ .chan = 13, .c1 = -66, .c0 = 13, },
+	{ .chan = 14, .c1 = -66, .c0 = 13, },
+};
+
+static const struct lpphy_rx_iq_comp lpphy_rev0_1_iq_table[] = {
+	{ .chan = 1, .c1 = -64, .c0 = 13, },
+	{ .chan = 2, .c1 = -64, .c0 = 13, },
+	{ .chan = 3, .c1 = -64, .c0 = 13, },
+	{ .chan = 4, .c1 = -64, .c0 = 13, },
+	{ .chan = 5, .c1 = -64, .c0 = 12, },
+	{ .chan = 6, .c1 = -64, .c0 = 12, },
+	{ .chan = 7, .c1 = -64, .c0 = 12, },
+	{ .chan = 8, .c1 = -64, .c0 = 12, },
+	{ .chan = 9, .c1 = -64, .c0 = 12, },
+	{ .chan = 10, .c1 = -64, .c0 = 11, },
+	{ .chan = 11, .c1 = -64, .c0 = 11, },
+	{ .chan = 12, .c1 = -64, .c0 = 11, },
+	{ .chan = 13, .c1 = -64, .c0 = 11, },
+	{ .chan = 14, .c1 = -64, .c0 = 10, },
+	{ .chan = 34, .c1 = -62, .c0 = 24, },
+	{ .chan = 38, .c1 = -62, .c0 = 24, },
+	{ .chan = 42, .c1 = -62, .c0 = 24, },
+	{ .chan = 46, .c1 = -62, .c0 = 23, },
+	{ .chan = 36, .c1 = -62, .c0 = 24, },
+	{ .chan = 40, .c1 = -62, .c0 = 24, },
+	{ .chan = 44, .c1 = -62, .c0 = 23, },
+	{ .chan = 48, .c1 = -62, .c0 = 23, },
+	{ .chan = 52, .c1 = -62, .c0 = 23, },
+	{ .chan = 56, .c1 = -62, .c0 = 22, },
+	{ .chan = 60, .c1 = -62, .c0 = 22, },
+	{ .chan = 64, .c1 = -62, .c0 = 22, },
+	{ .chan = 100, .c1 = -62, .c0 = 16, },
+	{ .chan = 104, .c1 = -62, .c0 = 16, },
+	{ .chan = 108, .c1 = -62, .c0 = 15, },
+	{ .chan = 112, .c1 = -62, .c0 = 14, },
+	{ .chan = 116, .c1 = -62, .c0 = 14, },
+	{ .chan = 120, .c1 = -62, .c0 = 13, },
+	{ .chan = 124, .c1 = -62, .c0 = 12, },
+	{ .chan = 128, .c1 = -62, .c0 = 12, },
+	{ .chan = 132, .c1 = -62, .c0 = 12, },
+	{ .chan = 136, .c1 = -62, .c0 = 11, },
+	{ .chan = 140, .c1 = -62, .c0 = 10, },
+	{ .chan = 149, .c1 = -61, .c0 = 9, },
+	{ .chan = 153, .c1 = -61, .c0 = 9, },
+	{ .chan = 157, .c1 = -61, .c0 = 9, },
+	{ .chan = 161, .c1 = -61, .c0 = 8, },
+	{ .chan = 165, .c1 = -61, .c0 = 8, },
+	{ .chan = 184, .c1 = -62, .c0 = 25, },
+	{ .chan = 188, .c1 = -62, .c0 = 25, },
+	{ .chan = 192, .c1 = -62, .c0 = 25, },
+	{ .chan = 196, .c1 = -62, .c0 = 25, },
+	{ .chan = 200, .c1 = -62, .c0 = 25, },
+	{ .chan = 204, .c1 = -62, .c0 = 25, },
+	{ .chan = 208, .c1 = -62, .c0 = 25, },
+	{ .chan = 212, .c1 = -62, .c0 = 25, },
+	{ .chan = 216, .c1 = -62, .c0 = 26, },
+};
+
+static const struct lpphy_rx_iq_comp lpphy_rev2plus_iq_comp = {
+	.chan = 0,
+	.c1 = -64,
+	.c0 = 0,
+};
+
+static u8 lpphy_nbits(s32 val)
+{
+	u32 tmp = abs(val);
+	u8 nbits = 0;
+
+	while (tmp != 0) {
+		nbits++;
+		tmp >>= 1;
+	}
+
+	return nbits;
+}
+
+static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples)
+{
+	struct lpphy_iq_est iq_est;
+	u16 c0, c1;
+	int prod, ipwr, qpwr, prod_msb, q_msb, tmp1, tmp2, tmp3, tmp4, ret;
+
+	c1 = b43_phy_read(dev, B43_LPPHY_RX_COMP_COEFF_S);
+	c0 = c1 >> 8;
+	c1 |= 0xFF;
+
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, 0x00C0);
+	b43_phy_mask(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF);
+
+	ret = lpphy_rx_iq_est(dev, samples, 32, &iq_est);
+	if (!ret)
+		goto out;
+
+	prod = iq_est.iq_prod;
+	ipwr = iq_est.i_pwr;
+	qpwr = iq_est.q_pwr;
+
+	if (ipwr + qpwr < 2) {
+		ret = 0;
+		goto out;
+	}
+
+	prod_msb = lpphy_nbits(prod);
+	q_msb = lpphy_nbits(qpwr);
+	tmp1 = prod_msb - 20;
+
+	if (tmp1 >= 0) {
+		tmp3 = ((prod << (30 - prod_msb)) + (ipwr >> (1 + tmp1))) /
+			(ipwr >> tmp1);
+	} else {
+		tmp3 = ((prod << (30 - prod_msb)) + (ipwr << (-1 - tmp1))) /
+			(ipwr << -tmp1);
+	}
+
+	tmp2 = q_msb - 11;
+
+	if (tmp2 >= 0)
+		tmp4 = (qpwr << (31 - q_msb)) / (ipwr >> tmp2);
+	else
+		tmp4 = (qpwr << (31 - q_msb)) / (ipwr << -tmp2);
+
+	tmp4 -= tmp3 * tmp3;
+	tmp4 = -int_sqrt(tmp4);
+
+	c0 = tmp3 >> 3;
+	c1 = tmp4 >> 4;
+
+out:
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, c1);
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF, c0 << 8);
+	return ret;
+}
+
+/* Complex number using 2 32-bit signed integers */
+typedef struct {s32 i, q;} lpphy_c32;
+
+static lpphy_c32 lpphy_cordic(int theta)
+{
+	u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304,
+		      58666, 29335, 14668, 7334, 3667, 1833, 917, 458,
+		      229, 115, 57, 29, };
+	int i, tmp, signx = 1, angle = 0;
+	lpphy_c32 ret = { .i = 39797, .q = 0, };
+
+	theta = clamp_t(int, theta, -180, 180);
+
+	if (theta > 90) {
+		theta -= 180;
+		signx = -1;
+	} else if (theta < -90) {
+		theta += 180;
+		signx = -1;
+	}
+
+	for (i = 0; i <= 17; i++) {
+		if (theta > angle) {
+			tmp = ret.i - (ret.q >> i);
+			ret.q += ret.i >> i;
+			ret.i = tmp;
+			angle += arctg[i];
+		} else {
+			tmp = ret.i + (ret.q >> i);
+			ret.q -= ret.i >> i;
+			ret.i = tmp;
+			angle -= arctg[i];
+		}
+	}
+
+	ret.i *= signx;
+	ret.q *= signx;
+
+	return ret;
+}
+
+static void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops,
+			      u16 wait)
+{
+	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL,
+			0xFFC0, samples - 1);
+	if (loops != 0xFFFF)
+		loops--;
+	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000, loops);
+	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL, 0x3F, wait << 6);
+	b43_phy_set(dev, B43_LPPHY_A_PHY_CTL_ADDR, 0x1);
+}
+
+//SPEC FIXME what does a negative freq mean?
+static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u16 buf[64];
+	int i, samples, angle = 0, rotation = (9 * freq) / 500;
+	lpphy_c32 sample;
+
+	lpphy->tx_tone_freq = freq;
+
+	if (freq) {
+		/* Find i for which abs(freq) integrally divides 20000 * i */
+		for (i = 1; samples * abs(freq) != 20000 * i; i++) {
+			samples = (20000 * i) / abs(freq);
+			if(B43_WARN_ON(samples > 63))
+				return;
+		}
+	} else {
+		samples = 2;
+	}
+
+	for (i = 0; i < samples; i++) {
+		sample = lpphy_cordic(angle);
+		angle += rotation;
+		buf[i] = ((sample.i * max) & 0xFF) << 8;
+		buf[i] |= (sample.q * max) & 0xFF;
+	}
+
+	b43_lptab_write_bulk(dev, B43_LPTAB16(5, 0), samples, buf);
+
+	lpphy_run_samples(dev, samples, 0xFFFF, 0);
+}
+
+static void lpphy_stop_tx_tone(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	int i;
+
+	lpphy->tx_tone_freq = 0;
+
+	b43_phy_mask(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000);
+	for (i = 0; i < 31; i++) {
+		if (!(b43_phy_read(dev, B43_LPPHY_A_PHY_CTL_ADDR) & 0x1))
+			break;
+		udelay(100);
+	}
+}
+
+
+static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains,
+			   int mode, bool useindex, u8 index)
+{
 	//TODO
+}
 
-	kfree(saved_tab);
+static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct ssb_bus *bus = dev->dev->bus;
+	struct lpphy_tx_gains gains, oldgains;
+	int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
+
+	lpphy_read_tx_pctl_mode_from_hardware(dev);
+	old_txpctl = lpphy->txpctl_mode;
+	old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
+	if (old_afe_ovr)
+		oldgains = lpphy_get_tx_gains(dev);
+	old_rf = b43_phy_read(dev, B43_LPPHY_RF_PWR_OVERRIDE) & 0xFF;
+	old_bbmult = lpphy_get_bb_mult(dev);
+
+	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
+
+	if (bus->chip_id == 0x4325 && bus->chip_rev == 0)
+		lpphy_papd_cal(dev, gains, 0, 1, 30);
+	else
+		lpphy_papd_cal(dev, gains, 0, 1, 65);
+
+	if (old_afe_ovr)
+		lpphy_set_tx_gains(dev, oldgains);
+	lpphy_set_bb_mult(dev, old_bbmult);
+	lpphy_set_tx_power_control(dev, old_txpctl);
+	b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00, old_rf);
+}
+
+static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
+			    bool rx, bool pa, struct lpphy_tx_gains *gains)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct ssb_bus *bus = dev->dev->bus;
+	const struct lpphy_rx_iq_comp *iqcomp = NULL;
+	struct lpphy_tx_gains nogains, oldgains;
+	u16 tmp;
+	int i, ret;
+
+	memset(&nogains, 0, sizeof(nogains));
+	memset(&oldgains, 0, sizeof(oldgains));
+
+	if (bus->chip_id == 0x5354) {
+		for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) {
+			if (lpphy_5354_iq_table[i].chan == lpphy->channel) {
+				iqcomp = &lpphy_5354_iq_table[i];
+			}
+		}
+	} else if (dev->phy.rev >= 2) {
+		iqcomp = &lpphy_rev2plus_iq_comp;
+	} else {
+		for (i = 0; i < ARRAY_SIZE(lpphy_rev0_1_iq_table); i++) {
+			if (lpphy_rev0_1_iq_table[i].chan == lpphy->channel) {
+				iqcomp = &lpphy_rev0_1_iq_table[i];
+			}
+		}
+	}
+
+	if (B43_WARN_ON(!iqcomp))
+		return 0;
+
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, iqcomp->c1);
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S,
+			0x00FF, iqcomp->c0 << 8);
+
+	if (noise) {
+		tx = true;
+		rx = false;
+		pa = false;
+	}
+
+	lpphy_set_trsw_over(dev, tx, rx);
+
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
+				0xFFF7, pa << 3);
+	} else {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
+				0xFFDF, pa << 5);
+	}
+
+	tmp = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
+
+	if (noise)
+		lpphy_set_rx_gain(dev, 0x2D5D);
+	else {
+		if (tmp)
+			oldgains = lpphy_get_tx_gains(dev);
+		if (!gains)
+			gains = &nogains;
+		lpphy_set_tx_gains(dev, *gains);
+	}
+
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
+	lpphy_set_deaf(dev, false);
+	if (noise)
+		ret = lpphy_calc_rx_iq_comp(dev, 0xFFF0);
+	else {
+		lpphy_start_tx_tone(dev, 4000, 100);
+		ret = lpphy_calc_rx_iq_comp(dev, 0x4000);
+		lpphy_stop_tx_tone(dev);
+	}
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFC);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFDF);
+	if (!noise) {
+		if (tmp)
+			lpphy_set_tx_gains(dev, oldgains);
+		else
+			lpphy_disable_tx_gain_override(dev);
+	}
+	lpphy_disable_rx_gain_override(dev);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xF7FF);
+	return ret;
 }
 
 static void lpphy_calibration(struct b43_wldev *dev)
 {
 	struct b43_phy_lp *lpphy = dev->phy.lp;
 	enum b43_lpphy_txpctl_mode saved_pctl_mode;
+	bool full_cal = false;
+
+	if (lpphy->full_calib_chan != lpphy->channel) {
+		full_cal = true;
+		lpphy->full_calib_chan = lpphy->channel;
+	}
 
 	b43_mac_suspend(dev);
 
 	lpphy_btcoex_override(dev);
+	if (dev->phy.rev >= 2)
+		lpphy_save_dig_flt_state(dev);
 	lpphy_read_tx_pctl_mode_from_hardware(dev);
 	saved_pctl_mode = lpphy->txpctl_mode;
 	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
 	//TODO Perform transmit power table I/Q LO calibration
 	if ((dev->phy.rev == 0) && (saved_pctl_mode != B43_LPPHY_TXPCTL_OFF))
 		lpphy_pr41573_workaround(dev);
-	//TODO If a full calibration has not been performed on this channel yet, perform PAPD TX-power calibration
+	if ((dev->phy.rev >= 2) && full_cal) {
+		lpphy_papd_cal_txpwr(dev);
+	}
 	lpphy_set_tx_power_control(dev, saved_pctl_mode);
-	//TODO Perform I/Q calibration with a single control value set
+	if (dev->phy.rev >= 2)
+		lpphy_restore_dig_flt_state(dev);
+	lpphy_rx_iq_cal(dev, true, true, false, false, NULL);
 
 	b43_mac_enable(dev);
 }
@@ -1532,12 +2075,6 @@ static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
 	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
 }
 
-static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
-					 bool blocked)
-{
-	//TODO
-}
-
 struct b206x_channel {
 	u8 channel;
 	u16 freq;
@@ -2003,22 +2540,6 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
 	return err;
 }
 
-
-/* This was previously called lpphy_japan_filter */
-static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel)
-{
-	struct b43_phy_lp *lpphy = dev->phy.lp;
-	u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter!
-
-	if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific?
-		b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9);
-		if ((dev->phy.rev == 1) && (lpphy->rc_cap))
-			lpphy_set_rc_cap(dev);
-	} else {
-		b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F);
-	}
-}
-
 static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
 {
 	u16 tmp;
@@ -2203,18 +2724,6 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
 	return 0;
 }
 
-static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
-{
-	if (dev->phy.rev >= 2)
-		return; // rev2+ doesn't support antenna diversity
-
-	if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1))
-		return;
-
-	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2);
-	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1);
-}
-
 static void b43_lpphy_op_adjust_txpower(struct b43_wldev *dev)
 {
 	//TODO
@@ -2227,6 +2736,11 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
 	return B43_TXPWR_RES_DONE;
 }
 
+static void b43_lpphy_op_pwork_15sec(struct b43_wldev *dev)
+{
+	//TODO
+}
+
 const struct b43_phy_operations b43_phyops_lp = {
 	.allocate		= b43_lpphy_op_allocate,
 	.free			= b43_lpphy_op_free,
@@ -2244,4 +2758,6 @@ const struct b43_phy_operations b43_phyops_lp = {
 	.set_rx_antenna		= b43_lpphy_op_set_rx_antenna,
 	.recalc_txpower		= b43_lpphy_op_recalc_txpower,
 	.adjust_txpower		= b43_lpphy_op_adjust_txpower,
+	.pwork_15sec		= b43_lpphy_op_pwork_15sec,
+	.pwork_60sec		= lpphy_calibration,
 };
diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h
index c3232c1..62737f7 100644
--- a/drivers/net/wireless/b43/phy_lp.h
+++ b/drivers/net/wireless/b43/phy_lp.h
@@ -286,6 +286,7 @@
 #define B43_LPPHY_TR_LOOKUP_6			B43_PHY_OFDM(0xC8) /* TR Lookup 6 */
 #define B43_LPPHY_TR_LOOKUP_7			B43_PHY_OFDM(0xC9) /* TR Lookup 7 */
 #define B43_LPPHY_TR_LOOKUP_8			B43_PHY_OFDM(0xCA) /* TR Lookup 8 */
+#define B43_LPPHY_RF_PWR_OVERRIDE		B43_PHY_OFDM(0xD3) /* RF power override */
 
 
 
@@ -871,12 +872,12 @@ struct b43_phy_lp {
 	u8 rssi_gs;
 
 	/* RC cap */
-	u8 rc_cap; /* FIXME initial value? */
+	u8 rc_cap;
 	/* BX arch */
 	u8 bx_arch;
 
 	/* Full calibration channel */
-	u8 full_calib_chan; /* FIXME initial value? */
+	u8 full_calib_chan;
 
 	/* Transmit iqlocal best coeffs */
 	bool tx_iqloc_best_coeffs_valid;
@@ -891,6 +892,12 @@ struct b43_phy_lp {
 
 	/* The channel we are tuned to */
 	u8 channel;
+
+	/* The active antenna diversity mode */
+	int antenna;
+
+	/* Frequency of the active TX tone */
+	int tx_tone_freq;
 };
 
 enum tssi_mux_mode {
-- 
1.6.2.4




^ permalink raw reply related

* [PATCH] b43: LP-PHY: Begin implementing calibration & software RFKILL support
From: Gábor Stefanik @ 2009-08-29 23:20 UTC (permalink / raw)
  To: John Linville, Michael Buesch, Larry Finger, Mark Huijgen
  Cc: Broadcom Wireless, linux-wireless

This implements the following calibration functions:
-Set TX IQCC
-Set TX Power by Index
-PR41573 workaround
-Calc RX IQ Comp
-PHY Cordic
-Run Samples
-Start/Stop TX Tone
-part of PAPD Cal TX Power
-RX I/Q Calibration
-The basic structure of the periodic calibration wrapper

Software RFKILL (required by calibration) is also implemented in
this round.

Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
---
Larry, please check if I got the math in "PHY Cordic" right!

 drivers/net/wireless/b43/main.c   |    2 +-
 drivers/net/wireless/b43/main.h   |    2 +
 drivers/net/wireless/b43/phy_lp.c |  684 ++++++++++++++++++++++++++++++++-----
 drivers/net/wireless/b43/phy_lp.h |   11 +-
 4 files changed, 611 insertions(+), 88 deletions(-)

diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index f2c5b2d..59bee02 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3345,7 +3345,7 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
 	mutex_unlock(&wl->mutex);
 }
 
-static void b43_put_phy_into_reset(struct b43_wldev *dev)
+void b43_put_phy_into_reset(struct b43_wldev *dev)
 {
 	struct ssb_device *sdev = dev->dev;
 	u32 tmslow;
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index 0406e06..fdbea9a 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -129,6 +129,8 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
 
 void b43_controller_restart(struct b43_wldev *dev, const char *reason);
 
+void b43_put_phy_into_reset(struct b43_wldev *dev);
+
 #define B43_PS_ENABLED	(1 << 0)	/* Force enable hardware power saving */
 #define B43_PS_DISABLED	(1 << 1)	/* Force disable hardware power saving */
 #define B43_PS_AWAKE	(1 << 2)	/* Force device awake */
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 5fff30a..60e8f6f 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -67,6 +67,7 @@ static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev)
 	struct b43_phy_lp *lpphy = phy->lp;
 
 	memset(lpphy, 0, sizeof(*lpphy));
+	lpphy->antenna = B43_ANTENNA_DEFAULT;
 
 	//TODO
 }
@@ -751,11 +752,17 @@ static void lpphy_clear_deaf(struct b43_wldev *dev, bool user)
 	}
 }
 
+static void lpphy_set_trsw_over(struct b43_wldev *dev, bool tx, bool rx)
+{
+	u16 trsw = (tx << 1) | rx;
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, trsw);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+}
+
 static void lpphy_disable_crs(struct b43_wldev *dev, bool user)
 {
 	lpphy_set_deaf(dev, user);
-	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1);
-	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+	lpphy_set_trsw_over(dev, false, true);
 	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
 	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
 	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFF7);
@@ -790,6 +797,60 @@ static void lpphy_restore_crs(struct b43_wldev *dev, bool user)
 
 struct lpphy_tx_gains { u16 gm, pga, pad, dac; };
 
+static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
+{
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
+	if (dev->phy.rev >= 2) {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
+			b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7);
+		}
+	} else {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
+	}
+}
+
+static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
+{
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
+	if (dev->phy.rev >= 2) {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
+			b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8);
+		}
+	} else {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
+	}
+}
+
+static void lpphy_disable_tx_gain_override(struct b43_wldev *dev)
+{
+	if (dev->phy.rev < 2)
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
+	else {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F);
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF);
+	}
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF);
+}
+
+static void lpphy_enable_tx_gain_override(struct b43_wldev *dev)
+{
+	if (dev->phy.rev < 2)
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
+	else {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x80);
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x4000);
+	}
+	b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x40);
+}
+
 static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
 {
 	struct lpphy_tx_gains gains;
@@ -819,6 +880,17 @@ static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
 	b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
 }
 
+static u16 lpphy_get_pa_gain(struct b43_wldev *dev)
+{
+	return b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F;
+}
+
+static void lpphy_set_pa_gain(struct b43_wldev *dev, u16 gain)
+{
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xFB), 0xE03F, gain << 6);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xFD), 0x80FF, gain << 8);
+}
+
 static void lpphy_set_tx_gains(struct b43_wldev *dev,
 			       struct lpphy_tx_gains gains)
 {
@@ -829,8 +901,7 @@ static void lpphy_set_tx_gains(struct b43_wldev *dev,
 		b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
 				0xF800, rf_gain);
 	} else {
-		pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x1FC0;
-		pa_gain <<= 2;
+		pa_gain = lpphy_get_pa_gain(dev);
 		b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
 			      (gains.pga << 8) | gains.gm);
 		b43_phy_maskset(dev, B43_PHY_OFDM(0xFB),
@@ -841,13 +912,7 @@ static void lpphy_set_tx_gains(struct b43_wldev *dev,
 				0x8000, gains.pad | pa_gain);
 	}
 	lpphy_set_dac_gain(dev, gains.dac);
-	if (dev->phy.rev < 2) {
-		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8);
-	} else {
-		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7);
-		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14);
-	}
-	b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF, 1 << 6);
+	lpphy_enable_tx_gain_override(dev);
 }
 
 static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
@@ -887,38 +952,6 @@ static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
 	}
 }
 
-static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
-{
-	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
-	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
-	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
-	if (dev->phy.rev >= 2) {
-		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
-		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
-			b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7);
-		}
-	} else {
-		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
-	}
-}
-
-static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
-{
-	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
-	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
-	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
-	if (dev->phy.rev >= 2) {
-		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
-		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
-			b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8);
-		}
-	} else {
-		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
-	}
-}
-
 static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain)
 {
 	if (dev->phy.rev < 2)
@@ -1003,8 +1036,7 @@ static int lpphy_loopback(struct b43_wldev *dev)
 
 	memset(&iq_est, 0, sizeof(iq_est));
 
-	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3);
-	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+	lpphy_set_trsw_over(dev, true, true);
 	b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 1);
 	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
 	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
@@ -1126,7 +1158,7 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
 			b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM,
 					0x8FFF, ((u16)lpphy->tssi_npt << 16));
 			//TODO Set "TSSI Transmit Count" variable to total transmitted frame count
-			//TODO Disable TX gain override
+			lpphy_disable_tx_gain_override(dev);
 			lpphy->tx_pwr_idx_over = -1;
 		}
 	}
@@ -1312,15 +1344,73 @@ static void lpphy_calibrate_rc(struct b43_wldev *dev)
 	}
 }
 
+static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
+{
+	if (dev->phy.rev >= 2)
+		return; // rev2+ doesn't support antenna diversity
+
+	if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1))
+		return;
+
+	b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);
+
+	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2);
+	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1);
+
+	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);
+
+	dev->phy.lp->antenna = antenna;
+}
+
+static void lpphy_set_tx_iqcc(struct b43_wldev *dev, u16 a, u16 b)
+{
+	u16 tmp[2];
+
+	tmp[0] = a;
+	tmp[1] = b;
+	b43_lptab_write_bulk(dev, B43_LPTAB16(0, 80), 2, tmp);
+}
+
 static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index)
 {
 	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct lpphy_tx_gains gains;
+	u32 iq_comp, tx_gain, coeff, rf_power;
 
 	lpphy->tx_pwr_idx_over = index;
+	lpphy_read_tx_pctl_mode_from_hardware(dev);
 	if (lpphy->txpctl_mode != B43_LPPHY_TXPCTL_OFF)
 		lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_SW);
-
-	//TODO
+	if (dev->phy.rev >= 2) {
+		iq_comp = b43_lptab_read(dev, B43_LPTAB32(7, index + 320));
+		tx_gain = b43_lptab_read(dev, B43_LPTAB32(7, index + 192));
+		gains.pad = (tx_gain >> 16) & 0xFF;
+		gains.gm = tx_gain & 0xFF;
+		gains.pga = (tx_gain >> 8) & 0xFF;
+		gains.dac = (iq_comp >> 28) & 0xFF;
+		lpphy_set_tx_gains(dev, gains);
+	} else {
+		iq_comp = b43_lptab_read(dev, B43_LPTAB32(10, index + 320));
+		tx_gain = b43_lptab_read(dev, B43_LPTAB32(10, index + 192));
+		b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+				0xF800, (tx_gain >> 4) & 0x7FFF);
+		lpphy_set_dac_gain(dev, tx_gain & 0x7);
+		lpphy_set_pa_gain(dev, (tx_gain >> 24) & 0x7F);
+	}
+	lpphy_set_bb_mult(dev, (iq_comp >> 20) & 0xFF);
+	lpphy_set_tx_iqcc(dev, (iq_comp >> 10) & 0x3FF, iq_comp & 0x3FF);
+	if (dev->phy.rev >= 2) {
+		coeff = b43_lptab_read(dev, B43_LPTAB32(7, index + 448));
+	} else {
+		coeff = b43_lptab_read(dev, B43_LPTAB32(10, index + 448));
+	}
+	b43_lptab_write(dev, B43_LPTAB16(0, 85), coeff & 0xFFFF);
+	if (dev->phy.rev >= 2) {
+		rf_power = b43_lptab_read(dev, B43_LPTAB32(7, index + 576));
+		b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00,
+				rf_power & 0xFFFF);//SPEC FIXME mask & set != 0
+	}
+	lpphy_enable_tx_gain_override(dev);
 }
 
 static void lpphy_btcoex_override(struct b43_wldev *dev)
@@ -1329,6 +1419,47 @@ static void lpphy_btcoex_override(struct b43_wldev *dev)
 	b43_write16(dev, B43_MMIO_BTCOEX_TXCTL, 0xFF);
 }
 
+static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
+					 bool blocked)
+{
+	//TODO check MAC control register
+	if (blocked) {
+		if (dev->phy.rev >= 2) {
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x83FF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
+			b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0x80FF);
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xDFFF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0808);
+		} else {
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xE0FF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFCFF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0018);
+		}
+	} else {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xE0FF);
+		if (dev->phy.rev >= 2)
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xF7F7);
+		else
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFE7);
+	}
+}
+
+/* This was previously called lpphy_japan_filter */
+static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter!
+
+	if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific?
+		b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9);
+		if ((dev->phy.rev == 1) && (lpphy->rc_cap))
+			lpphy_set_rc_cap(dev);
+	} else {
+		b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F);
+	}
+}
+
 static void lpphy_pr41573_workaround(struct b43_wldev *dev)
 {
 	struct b43_phy_lp *lpphy = dev->phy.lp;
@@ -1357,28 +1488,438 @@ static void lpphy_pr41573_workaround(struct b43_wldev *dev)
 		b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140),
 				    saved_tab_size, saved_tab);
 	}
+	b43_put_phy_into_reset(dev);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFF8);
+	lpphy_table_init(dev); //FIXME is table init needed?
+	lpphy_baseband_init(dev);
+	b43_lpphy_op_software_rfkill(dev, false);
+	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
+	if (dev->phy.rev < 2) {
+		b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0x140),
+				     saved_tab_size, saved_tab);
+	} else {
+		b43_lptab_write_bulk(dev, B43_LPTAB32(7, 0x140),
+				     saved_tab_size, saved_tab);
+	}
+	b43_write16(dev, B43_MMIO_CHANNEL, lpphy->channel);
+	lpphy->tssi_npt = tssi_npt;
+	lpphy->tssi_idx = tssi_idx;
+	lpphy_set_analog_filter(dev, lpphy->channel);
+	if (tx_pwr_idx_over != -1)
+		lpphy_set_tx_power_by_index(dev, tx_pwr_idx_over);
+	if (lpphy->rc_cap)
+		lpphy_set_rc_cap(dev);
+	b43_lpphy_op_set_rx_antenna(dev, lpphy->antenna);
+	lpphy_set_tx_power_control(dev, txpctl_mode);
+	kfree(saved_tab);
+}
+
+struct lpphy_rx_iq_comp { u8 chan; s8 c1, c0; };
+
+static const struct lpphy_rx_iq_comp lpphy_5354_iq_table[] = {
+	{ .chan = 1, .c1 = -66, .c0 = 15, },
+	{ .chan = 2, .c1 = -66, .c0 = 15, },
+	{ .chan = 3, .c1 = -66, .c0 = 15, },
+	{ .chan = 4, .c1 = -66, .c0 = 15, },
+	{ .chan = 5, .c1 = -66, .c0 = 15, },
+	{ .chan = 6, .c1 = -66, .c0 = 15, },
+	{ .chan = 7, .c1 = -66, .c0 = 14, },
+	{ .chan = 8, .c1 = -66, .c0 = 14, },
+	{ .chan = 9, .c1 = -66, .c0 = 14, },
+	{ .chan = 10, .c1 = -66, .c0 = 14, },
+	{ .chan = 11, .c1 = -66, .c0 = 14, },
+	{ .chan = 12, .c1 = -66, .c0 = 13, },
+	{ .chan = 13, .c1 = -66, .c0 = 13, },
+	{ .chan = 14, .c1 = -66, .c0 = 13, },
+};
+
+static const struct lpphy_rx_iq_comp lpphy_rev0_1_iq_table[] = {
+	{ .chan = 1, .c1 = -64, .c0 = 13, },
+	{ .chan = 2, .c1 = -64, .c0 = 13, },
+	{ .chan = 3, .c1 = -64, .c0 = 13, },
+	{ .chan = 4, .c1 = -64, .c0 = 13, },
+	{ .chan = 5, .c1 = -64, .c0 = 12, },
+	{ .chan = 6, .c1 = -64, .c0 = 12, },
+	{ .chan = 7, .c1 = -64, .c0 = 12, },
+	{ .chan = 8, .c1 = -64, .c0 = 12, },
+	{ .chan = 9, .c1 = -64, .c0 = 12, },
+	{ .chan = 10, .c1 = -64, .c0 = 11, },
+	{ .chan = 11, .c1 = -64, .c0 = 11, },
+	{ .chan = 12, .c1 = -64, .c0 = 11, },
+	{ .chan = 13, .c1 = -64, .c0 = 11, },
+	{ .chan = 14, .c1 = -64, .c0 = 10, },
+	{ .chan = 34, .c1 = -62, .c0 = 24, },
+	{ .chan = 38, .c1 = -62, .c0 = 24, },
+	{ .chan = 42, .c1 = -62, .c0 = 24, },
+	{ .chan = 46, .c1 = -62, .c0 = 23, },
+	{ .chan = 36, .c1 = -62, .c0 = 24, },
+	{ .chan = 40, .c1 = -62, .c0 = 24, },
+	{ .chan = 44, .c1 = -62, .c0 = 23, },
+	{ .chan = 48, .c1 = -62, .c0 = 23, },
+	{ .chan = 52, .c1 = -62, .c0 = 23, },
+	{ .chan = 56, .c1 = -62, .c0 = 22, },
+	{ .chan = 60, .c1 = -62, .c0 = 22, },
+	{ .chan = 64, .c1 = -62, .c0 = 22, },
+	{ .chan = 100, .c1 = -62, .c0 = 16, },
+	{ .chan = 104, .c1 = -62, .c0 = 16, },
+	{ .chan = 108, .c1 = -62, .c0 = 15, },
+	{ .chan = 112, .c1 = -62, .c0 = 14, },
+	{ .chan = 116, .c1 = -62, .c0 = 14, },
+	{ .chan = 120, .c1 = -62, .c0 = 13, },
+	{ .chan = 124, .c1 = -62, .c0 = 12, },
+	{ .chan = 128, .c1 = -62, .c0 = 12, },
+	{ .chan = 132, .c1 = -62, .c0 = 12, },
+	{ .chan = 136, .c1 = -62, .c0 = 11, },
+	{ .chan = 140, .c1 = -62, .c0 = 10, },
+	{ .chan = 149, .c1 = -61, .c0 = 9, },
+	{ .chan = 153, .c1 = -61, .c0 = 9, },
+	{ .chan = 157, .c1 = -61, .c0 = 9, },
+	{ .chan = 161, .c1 = -61, .c0 = 8, },
+	{ .chan = 165, .c1 = -61, .c0 = 8, },
+	{ .chan = 184, .c1 = -62, .c0 = 25, },
+	{ .chan = 188, .c1 = -62, .c0 = 25, },
+	{ .chan = 192, .c1 = -62, .c0 = 25, },
+	{ .chan = 196, .c1 = -62, .c0 = 25, },
+	{ .chan = 200, .c1 = -62, .c0 = 25, },
+	{ .chan = 204, .c1 = -62, .c0 = 25, },
+	{ .chan = 208, .c1 = -62, .c0 = 25, },
+	{ .chan = 212, .c1 = -62, .c0 = 25, },
+	{ .chan = 216, .c1 = -62, .c0 = 26, },
+};
+
+static const struct lpphy_rx_iq_comp lpphy_rev2plus_iq_comp = {
+	.chan = 0,
+	.c1 = -64,
+	.c0 = 0,
+};
+
+static u8 lpphy_nbits(s32 val)
+{
+	u32 tmp = abs(val);
+	u8 nbits = 0;
+
+	while (tmp != 0) {
+		nbits++;
+		tmp >>= 1;
+	}
+
+	return nbits;
+}
+
+static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples)
+{
+	struct lpphy_iq_est iq_est;
+	u16 c0, c1;
+	int prod, ipwr, qpwr, prod_msb, q_msb, tmp1, tmp2, tmp3, tmp4, ret;
+
+	c1 = b43_phy_read(dev, B43_LPPHY_RX_COMP_COEFF_S);
+	c0 = c1 >> 8;
+	c1 |= 0xFF;
+
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, 0x00C0);
+	b43_phy_mask(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF);
+
+	ret = lpphy_rx_iq_est(dev, samples, 32, &iq_est);
+	if (!ret)
+		goto out;
+
+	prod = iq_est.iq_prod;
+	ipwr = iq_est.i_pwr;
+	qpwr = iq_est.q_pwr;
+
+	if (ipwr + qpwr < 2) {
+		ret = 0;
+		goto out;
+	}
+
+	prod_msb = lpphy_nbits(prod);
+	q_msb = lpphy_nbits(qpwr);
+	tmp1 = prod_msb - 20;
+
+	if (tmp1 >= 0) {
+		tmp3 = ((prod << (30 - prod_msb)) + (ipwr >> (1 + tmp1))) /
+			(ipwr >> tmp1);
+	} else {
+		tmp3 = ((prod << (30 - prod_msb)) + (ipwr << (-1 - tmp1))) /
+			(ipwr << -tmp1);
+	}
+
+	tmp2 = q_msb - 11;
+
+	if (tmp2 >= 0)
+		tmp4 = (qpwr << (31 - q_msb)) / (ipwr >> tmp2);
+	else
+		tmp4 = (qpwr << (31 - q_msb)) / (ipwr << -tmp2);
+
+	tmp4 -= tmp3 * tmp3;
+	tmp4 = -int_sqrt(tmp4);
+
+	c0 = tmp3 >> 3;
+	c1 = tmp4 >> 4;
+
+out:
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, c1);
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF, c0 << 8);
+	return ret;
+}
+
+/* Complex number using 2 32-bit signed integers */
+typedef struct {s32 i, q;} lpphy_c32;
+
+static lpphy_c32 lpphy_cordic(int theta)
+{
+	u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304,
+		      58666, 29335, 14668, 7334, 3667, 1833, 917, 458,
+		      229, 115, 57, 29, };
+	int i, tmp, signx = 1, angle = 0;
+	lpphy_c32 ret = { .i = 39797, .q = 0, };
+
+	theta = clamp_t(int, theta, -180, 180);
+
+	if (theta > 90) {
+		theta -= 180;
+		signx = -1;
+	} else if (theta < -90) {
+		theta += 180;
+		signx = -1;
+	}
+
+	for (i = 0; i <= 17; i++) {
+		if (theta > angle) {
+			tmp = ret.i - (ret.q >> i);
+			ret.q += ret.i >> i;
+			ret.i = tmp + arctg[i];
+		} else {
+			tmp = ret.i + (ret.q >> i);
+			ret.q -= ret.i >> i;
+			ret.i = tmp - arctg[i];
+		}
+	}
+
+	ret.i *= signx;
+	ret.q *= signx;
+
+	return ret;
+}
+
+static void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops,
+			      u16 wait)
+{
+	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL,
+			0xFFC0, samples - 1);
+	if (loops != 0xFFFF)
+		loops--;
+	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000, loops);
+	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL, 0x3F, wait << 6);
+	b43_phy_set(dev, B43_LPPHY_A_PHY_CTL_ADDR, 0x1);
+}
+
+//SPEC FIXME what does a negative freq mean?
+static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u16 buf[64];
+	int i, samples, angle = 0, rotation = (9 * freq) / 500;
+	lpphy_c32 sample;
+
+	lpphy->tx_tone_freq = freq;
+
+	if (freq) {
+		/* Find i for which abs(freq) integrally divides 20000 * i */
+		for (i = 1; samples * abs(freq) != 20000 * i; i++) {
+			samples = (20000 * i) / abs(freq);
+			if(B43_WARN_ON(samples > 63))
+				return;
+		}
+	} else {
+		samples = 2;
+	}
+
+	for (i = 0; i < samples; i++) {
+		sample = lpphy_cordic(angle);
+		angle += rotation;
+		buf[i] = ((sample.i * max) & 0xFF) << 8;
+		buf[i] |= (sample.q * max) & 0xFF;
+	}
+
+	b43_lptab_write_bulk(dev, B43_LPTAB16(5, 0), samples, buf);
+
+	lpphy_run_samples(dev, samples, 0xFFFF, 0);
+}
+
+static void lpphy_stop_tx_tone(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	int i;
+
+	lpphy->tx_tone_freq = 0;
+
+	b43_phy_mask(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000);
+	for (i = 0; i < 31; i++) {
+		if (!(b43_phy_read(dev, B43_LPPHY_A_PHY_CTL_ADDR) & 0x1))
+			break;
+		udelay(100);
+	}
+}
+
+
+static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains,
+			   int mode, bool useindex, u8 index)
+{
 	//TODO
+}
 
-	kfree(saved_tab);
+static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct ssb_bus *bus = dev->dev->bus;
+	struct lpphy_tx_gains gains, oldgains;
+	int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
+
+	lpphy_read_tx_pctl_mode_from_hardware(dev);
+	old_txpctl = lpphy->txpctl_mode;
+	old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
+	if (old_afe_ovr)
+		oldgains = lpphy_get_tx_gains(dev);
+	old_rf = b43_phy_read(dev, B43_LPPHY_RF_PWR_OVERRIDE) & 0xFF;
+	old_bbmult = lpphy_get_bb_mult(dev);
+
+	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
+
+	if (bus->chip_id == 0x4325 && bus->chip_rev == 0)
+		lpphy_papd_cal(dev, gains, 0, 1, 30);
+	else
+		lpphy_papd_cal(dev, gains, 0, 1, 65);
+
+	if (old_afe_ovr)
+		lpphy_set_tx_gains(dev, oldgains);
+	lpphy_set_bb_mult(dev, old_bbmult);
+	lpphy_set_tx_power_control(dev, old_txpctl);
+	b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00, old_rf);
+}
+
+static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
+			    bool rx, bool pa, struct lpphy_tx_gains *gains)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct ssb_bus *bus = dev->dev->bus;
+	const struct lpphy_rx_iq_comp *iqcomp = NULL;
+	struct lpphy_tx_gains nogains, oldgains;
+	u16 tmp;
+	int i, ret;
+
+	memset(&nogains, 0, sizeof(nogains));
+	memset(&oldgains, 0, sizeof(oldgains));
+
+	if (bus->chip_id == 0x5354) {
+		for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) {
+			if (lpphy_5354_iq_table[i].chan == lpphy->channel) {
+				iqcomp = &lpphy_5354_iq_table[i];
+			}
+		}
+	} else if (dev->phy.rev >= 2) {
+		iqcomp = &lpphy_rev2plus_iq_comp;
+	} else {
+		for (i = 0; i < ARRAY_SIZE(lpphy_rev0_1_iq_table); i++) {
+			if (lpphy_rev0_1_iq_table[i].chan == lpphy->channel) {
+				iqcomp = &lpphy_rev0_1_iq_table[i];
+			}
+		}
+	}
+
+	if (B43_WARN_ON(!iqcomp))
+		return 0;
+
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, iqcomp->c1);
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S,
+			0x00FF, iqcomp->c0 << 8);
+
+	if (noise) {
+		tx = true;
+		rx = false;
+		pa = false;
+	}
+
+	lpphy_set_trsw_over(dev, tx, rx);
+
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
+				0xFFF7, pa << 3);
+	} else {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
+				0xFFDF, pa << 5);
+	}
+
+	tmp = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
+
+	if (noise)
+		lpphy_set_rx_gain(dev, 0x2D5D);
+	else {
+		if (tmp)
+			oldgains = lpphy_get_tx_gains(dev);
+		if (!gains)
+			gains = &nogains;
+		lpphy_set_tx_gains(dev, *gains);
+	}
+
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
+	lpphy_set_deaf(dev, false);
+	if (noise)
+		ret = lpphy_calc_rx_iq_comp(dev, 0xFFF0);
+	else {
+		lpphy_start_tx_tone(dev, 4000, 100);
+		ret = lpphy_calc_rx_iq_comp(dev, 0x4000);
+		lpphy_stop_tx_tone(dev);
+	}
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFC);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFDF);
+	if (!noise) {
+		if (tmp)
+			lpphy_set_tx_gains(dev, oldgains);
+		else
+			lpphy_disable_tx_gain_override(dev);
+	}
+	lpphy_disable_rx_gain_override(dev);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xF7FF);
+	return ret;
 }
 
 static void lpphy_calibration(struct b43_wldev *dev)
 {
 	struct b43_phy_lp *lpphy = dev->phy.lp;
 	enum b43_lpphy_txpctl_mode saved_pctl_mode;
+	bool full_cal = false;
+
+	if (lpphy->full_calib_chan != lpphy->channel) {
+		full_cal = true;
+		lpphy->full_calib_chan = lpphy->channel;
+	}
 
 	b43_mac_suspend(dev);
 
 	lpphy_btcoex_override(dev);
+	if (dev->phy.rev >= 2)
+		lpphy_save_dig_flt_state(dev);
 	lpphy_read_tx_pctl_mode_from_hardware(dev);
 	saved_pctl_mode = lpphy->txpctl_mode;
 	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
 	//TODO Perform transmit power table I/Q LO calibration
 	if ((dev->phy.rev == 0) && (saved_pctl_mode != B43_LPPHY_TXPCTL_OFF))
 		lpphy_pr41573_workaround(dev);
-	//TODO If a full calibration has not been performed on this channel yet, perform PAPD TX-power calibration
+	if ((dev->phy.rev >= 2) && full_cal) {
+		lpphy_papd_cal_txpwr(dev);
+	}
 	lpphy_set_tx_power_control(dev, saved_pctl_mode);
-	//TODO Perform I/Q calibration with a single control value set
+	if (dev->phy.rev >= 2)
+		lpphy_restore_dig_flt_state(dev);
+	lpphy_rx_iq_cal(dev, true, true, false, false, NULL);
 
 	b43_mac_enable(dev);
 }
@@ -1532,12 +2073,6 @@ static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
 	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
 }
 
-static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
-					 bool blocked)
-{
-	//TODO
-}
-
 struct b206x_channel {
 	u8 channel;
 	u16 freq;
@@ -2003,22 +2538,6 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
 	return err;
 }
 
-
-/* This was previously called lpphy_japan_filter */
-static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel)
-{
-	struct b43_phy_lp *lpphy = dev->phy.lp;
-	u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter!
-
-	if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific?
-		b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9);
-		if ((dev->phy.rev == 1) && (lpphy->rc_cap))
-			lpphy_set_rc_cap(dev);
-	} else {
-		b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F);
-	}
-}
-
 static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
 {
 	u16 tmp;
@@ -2203,18 +2722,6 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
 	return 0;
 }
 
-static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
-{
-	if (dev->phy.rev >= 2)
-		return; // rev2+ doesn't support antenna diversity
-
-	if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1))
-		return;
-
-	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2);
-	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1);
-}
-
 static void b43_lpphy_op_adjust_txpower(struct b43_wldev *dev)
 {
 	//TODO
@@ -2227,6 +2734,11 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
 	return B43_TXPWR_RES_DONE;
 }
 
+static void b43_lpphy_op_pwork_15sec(struct b43_wldev *dev)
+{
+	//TODO
+}
+
 const struct b43_phy_operations b43_phyops_lp = {
 	.allocate		= b43_lpphy_op_allocate,
 	.free			= b43_lpphy_op_free,
@@ -2244,4 +2756,6 @@ const struct b43_phy_operations b43_phyops_lp = {
 	.set_rx_antenna		= b43_lpphy_op_set_rx_antenna,
 	.recalc_txpower		= b43_lpphy_op_recalc_txpower,
 	.adjust_txpower		= b43_lpphy_op_adjust_txpower,
+	.pwork_15sec		= b43_lpphy_op_pwork_15sec,
+	.pwork_60sec		= lpphy_calibration,
 };
diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h
index c3232c1..62737f7 100644
--- a/drivers/net/wireless/b43/phy_lp.h
+++ b/drivers/net/wireless/b43/phy_lp.h
@@ -286,6 +286,7 @@
 #define B43_LPPHY_TR_LOOKUP_6			B43_PHY_OFDM(0xC8) /* TR Lookup 6 */
 #define B43_LPPHY_TR_LOOKUP_7			B43_PHY_OFDM(0xC9) /* TR Lookup 7 */
 #define B43_LPPHY_TR_LOOKUP_8			B43_PHY_OFDM(0xCA) /* TR Lookup 8 */
+#define B43_LPPHY_RF_PWR_OVERRIDE		B43_PHY_OFDM(0xD3) /* RF power override */
 
 
 
@@ -871,12 +872,12 @@ struct b43_phy_lp {
 	u8 rssi_gs;
 
 	/* RC cap */
-	u8 rc_cap; /* FIXME initial value? */
+	u8 rc_cap;
 	/* BX arch */
 	u8 bx_arch;
 
 	/* Full calibration channel */
-	u8 full_calib_chan; /* FIXME initial value? */
+	u8 full_calib_chan;
 
 	/* Transmit iqlocal best coeffs */
 	bool tx_iqloc_best_coeffs_valid;
@@ -891,6 +892,12 @@ struct b43_phy_lp {
 
 	/* The channel we are tuned to */
 	u8 channel;
+
+	/* The active antenna diversity mode */
+	int antenna;
+
+	/* Frequency of the active TX tone */
+	int tx_tone_freq;
 };
 
 enum tssi_mux_mode {
-- 
1.6.2.4




^ permalink raw reply related

* Re: [rt2x00-users] [PATCH] rt2x00: Reorganize padding & L2 padding
From: Benoit PAPILLAULT @ 2009-08-29 20:33 UTC (permalink / raw)
  To: rt2x00 Users List; +Cc: John Linville, linux-wireless
In-Reply-To: <200908292030.45659.IvDoorn@gmail.com>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Ivo van Doorn a écrit :
> The old function rt2x00queue_payload_align() handled both adding
> and removing L2 padding and some basic frame alignment. The entire
> function was being abused because it had multiple functions and the
> header length argument was somtimes used to align the header
> instead of the payload.
>
> Additionally there was a bug when inserting L2 padding that only
> the payload was aligned but not the header. This happens when the
> header wasn't aligned properly by mac80211, but rt2x00lib only
> moves the payload.
>
> A secondary problem was that when removing L2 padding during TXdone
> or RX the skb wasn't resized to the proper size.
>
> Split the function into seperate functions each handling its task
> as it should.
>
> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> ---
> drivers/net/wireless/rt2x00/rt2x00crypto.c |    6 +-
> drivers/net/wireless/rt2x00/rt2x00dev.c    |   10 ++--
> drivers/net/wireless/rt2x00/rt2x00lib.h    |   45 +++++++++----
> drivers/net/wireless/rt2x00/rt2x00queue.c  |   99
> +++++++++++++++++++++------- 4 files changed, 116 insertions(+), 44
> deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c
> b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 30fbd3b..de36837
> 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++
> b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -154,7 +154,7 @@
> void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int
> header_length) skbdesc->flags &= ~SKBDESC_IV_STRIPPED; }
>
> -void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
> +void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int
> header_length, struct rxdone_entry_desc *rxdesc) { @@ -199,7 +199,7
> @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
> * move the header more then iv_len since we must * make room for
> the payload move as well. */ -    if (l2pad) { +    if (rxdesc->dev_flags
> & RXDONE_L2PAD) { skb_push(skb, iv_len - align); skb_put(skb,
> icv_len);
>
> @@ -230,7 +230,7 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff
> *skb, bool l2pad, * Move payload for alignment purposes. Note that
> * this is only needed when no l2 padding is present. */ -    if
> (!l2pad) { +    if (!(rxdesc->dev_flags & RXDONE_L2PAD)) {
> memmove(skb->data + transfer, skb->data + transfer + align,
> payload_len); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c
> b/drivers/net/wireless/rt2x00/rt2x00dev.c index 3f8c70e..5db613f
> 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++
> b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -216,7 +216,7 @@ void
> rt2x00lib_txdone(struct queue_entry *entry, * Remove L2 padding
> which was added during */ if (test_bit(DRIVER_REQUIRE_L2PAD,
> &rt2x00dev->flags)) -        rt2x00queue_payload_align(entry->skb, true,
> header_length); +        rt2x00queue_remove_l2pad(entry->skb,
> header_length);
>
> /* * If the IV/EIV data was stripped from the frame before it was
> @@ -360,7 +360,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev
> *rt2x00dev, struct sk_buff *skb; struct ieee80211_rx_status
> *rx_status = &rt2x00dev->rx_status; unsigned int header_length; -
> bool l2pad; int rate_idx; /* * Allocate a new sk_buffer. If no new
> buffer available, drop the @@ -389,7 +388,6 @@ void
> rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, * aligned on a 4
> byte boundary. */ header_length =
> ieee80211_get_hdrlen_from_skb(entry->skb); -    l2pad =
> !!(rxdesc.dev_flags & RXDONE_L2PAD);
>
> /* * Hardware might have stripped the IV/EIV/ICV data, @@ -399,10
> +397,12 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, */
> if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) && (rxdesc.flags &
> RX_FLAG_IV_STRIPPED)) -        rt2x00crypto_rx_insert_iv(entry->skb,
> l2pad, header_length, +        rt2x00crypto_rx_insert_iv(entry->skb,
> header_length, &rxdesc); +    else if (rxdesc.dev_flags &
> RXDONE_L2PAD) +        rt2x00queue_remove_l2pad(entry->skb,
> header_length); else -        rt2x00queue_payload_align(entry->skb,
> l2pad, header_length); +        rt2x00queue_align_payload(entry->skb,
> header_length);
>
> /* * Check if the frame was received using HT. In that case, diff
> --git a/drivers/net/wireless/rt2x00/rt2x00lib.h
> b/drivers/net/wireless/rt2x00/rt2x00lib.h index eeb2881..5462cb5
> 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++
> b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -120,21 +120,42 @@
> void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct
> sk_buff *skb); void rt2x00queue_free_skb(struct rt2x00_dev
> *rt2x00dev, struct sk_buff *skb);
>
> /** - * rt2x00queue_payload_align - Align 802.11 payload to 4-byte
> boundary + * rt2x00queue_align_frame - Align 802.11 frame to 4-byte
> boundary + * @skb: The skb to align + * + * Align the start of the
> 802.11 frame to a 4-byte boundary, this could + * mean the payload
> is not aligned properly though. + */ +void
> rt2x00queue_align_frame(struct sk_buff *skb); + +/** + *
> rt2x00queue_align_payload - Align 802.11 payload to 4-byte boundary
>  + * @skb: The skb to align + * @header_length: Length of 802.11
> header + * + * Align the 802.11 payload to a 4-byte boundary, this
> could + * mean the header is not aligned properly though. + */
> +void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int
> header_length); + +/** + * rt2x00queue_insert_l2pad - Align 802.11
> header & payload to 4-byte boundary + * @skb: The skb to align + *
> @header_length: Length of 802.11 header + * + * Apply L2 padding to
> align both header and payload to 4-byte boundary + */ +void
> rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int
> header_length); + +/** + * rt2x00queue_insert_l2pad - Remove L2
> padding from 802.11 frame * @skb: The skb to align - * @l2pad:
> Should L2 padding be used * @header_length: Length of 802.11 header
>  * - * This function prepares the @skb to be send to the device or
> mac80211. - * If @l2pad is set to true padding will occur between
> the 802.11 header - * and payload. Otherwise the padding will be
> done in front of the 802.11 - * header. - * When @l2pad is set the
> function will check for the &SKBDESC_L2_PADDED - * flag in
> &skb_frame_desc. If that flag is set, the padding is removed - *
> and the flag cleared. Otherwise the padding is added and the flag
> is set. + * Remove L2 padding used to align both header and payload
> to 4-byte boundary, + * by removing the L2 padding the header will
> no longer be 4-byte aligned. */ -void
> rt2x00queue_payload_align(struct sk_buff *skb, -                   bool
> l2pad, unsigned int header_length); +void
> rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int
> header_length);
>
> /** * rt2x00queue_write_tx_frame - Write TX frame to hardware @@
> -324,7 +345,7 @@ void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
> void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct
> txentry_desc *txdesc); void rt2x00crypto_tx_insert_iv(struct
> sk_buff *skb, unsigned int header_length); -void
> rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, +void
> rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int
> header_length, struct rxdone_entry_desc *rxdesc); #else diff --git
> a/drivers/net/wireless/rt2x00/rt2x00queue.c
> b/drivers/net/wireless/rt2x00/rt2x00queue.c index 06af823..577029e
> 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++
> b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -148,35 +148,89 @@
> void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct
> sk_buff *skb) dev_kfree_skb_any(skb); }
>
> -void rt2x00queue_payload_align(struct sk_buff *skb, -
> bool l2pad, unsigned int header_length) +void
> rt2x00queue_align_frame(struct sk_buff *skb) { -    struct
> skb_frame_desc *skbdesc = get_skb_frame_desc(skb); unsigned int
> frame_length = skb->len; -    unsigned int align = ALIGN_SIZE(skb,
> header_length); +    unsigned int align = ALIGN_SIZE(skb, 0);
>
> if (!align) return;
>
> -    if (l2pad) { -        if (skbdesc->flags & SKBDESC_L2_PADDED) {
-            /*
> Remove L2 padding */ -            memmove(skb->data + align, skb->data,
> header_length); -            skb_pull(skb, align); -           
skbdesc->flags &=
> ~SKBDESC_L2_PADDED; -        } else { -            /* Add L2 padding */ -
> skb_push(skb, align); -            memmove(skb->data, skb->data + align,
> header_length); -            skbdesc->flags |= SKBDESC_L2_PADDED;
-        } +
> skb_push(skb, align); +    memmove(skb->data, skb->data + align,
> frame_length); +    skb_trim(skb, frame_length); +} + +void
> rt2x00queue_align_payload(struct sk_buff *skb, unsigned int
> header_lengt) +{ +    unsigned int frame_length = skb->len; +    unsigned
> int align = ALIGN_SIZE(skb, header_lengt); + +    if (!align) +
> return; + +    skb_push(skb, align); +    memmove(skb->data, skb->data +
> align, frame_length); +    skb_trim(skb, frame_length); +} + +void
> rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int
> header_length) +{ +    struct skb_frame_desc *skbdesc =
> get_skb_frame_desc(skb); +    unsigned int frame_length = skb->len; +
> unsigned int header_align = ALIGN_SIZE(skb, 0); +    unsigned int
> payload_align = ALIGN_SIZE(skb, header_length); +    unsigned int
> l2pad = 4 - (payload_align - header_align); + +    if (header_align ==
> payload_align) { +        /* +         * Both header and payload must
be moved
> the same +         * amount of bytes to align them properly. This means +
> * we don't use the L2 padding but just move the entire +         * frame.
>  +         */ +        rt2x00queue_align_frame(skb); +    } else if
> (!payload_align) { +        /* +         * Simple L2 padding, only the
header
> needs to be moved, +         * the payload is already properly aligned. +
> */ +        skb_push(skb, header_align); +        memmove(skb->data,
skb->data
> + header_align, frame_length); +        skbdesc->flags |=
> SKBDESC_L2_PADDED; } else { -        /* Generic payload alignment to
> 4-byte boundary */ -        skb_push(skb, align); -       
memmove(skb->data,
> skb->data + align, frame_length); +        /* +         * +         *
Complicated L2
> padding, both header and payload need +         * to be moved. By default
> we only move to the start +         * of the buffer, so our header
> alignment needs to be +         * increased if there is not enough room
> for the header +         * to be moved. +         */ +        if
(payload_align >
> header_align) +            header_align += 4; + +        skb_push(skb,
> header_align); +        memmove(skb->data, skb->data + header_align,
> header_length); +        memmove(skb->data + header_length + l2pad, +
> skb->data + header_length + l2pad + header_align, +            frame_length
> - header_length); +        skbdesc->flags |= SKBDESC_L2_PADDED; } }
>
> +void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int
> header_length) +{ +    struct skb_frame_desc *skbdesc =
> get_skb_frame_desc(skb); +    unsigned int l2pad = 4 - (header_length
> & 3);
This formula is incorrect, it should be at least (4 -
(header_length%4)%4). I have a fix in my pending patches...
If header_length is 0 => l2pad should be 0 as well.

> + +    if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED)) +       
return;
> + +    memmove(skb->data + l2pad, skb->data, header_length); +
> skb_pull(skb, l2pad); +} + static void
> rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
> struct txentry_desc *txdesc) { @@ -456,18 +510,15 @@ int
> rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff
> *skb) /* * When DMA allocation is required we should guarentee to
> the * driver that the DMA is aligned to a 4-byte boundary. -     *
> Aligning the header to this boundary can be done by calling -     *
> rt2x00queue_payload_align with the header length of 0. * However
> some drivers require L2 padding to pad the payload * rather then
> the header. This could be a requirement for * PCI and USB devices,
> while header alignment only is valid * for PCI devices. */ if
> (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) -
> rt2x00queue_payload_align(entry->skb, true, -
> txdesc.header_length); +        rt2x00queue_insert_l2pad(entry->skb,
> txdesc.header_length); else if (test_bit(DRIVER_REQUIRE_DMA,
> &queue->rt2x00dev->flags)) -        rt2x00queue_payload_align(entry->skb,
> false, 0); +        rt2x00queue_align_frame(entry->skb);
>
> /* * It could be possible that the queue was corrupted and this
Regards,
Benoit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkqZkKUACgkQOR6EySwP7oJcQwCfUBeCwBVJHDWt0B1RINNZNt/G
pUQAoKTx2BizEOoUR7hB3sRvxbORJRMy
=LuW0
-----END PGP SIGNATURE-----


^ permalink raw reply

* Re: [rt2x00-users] [PATCH] rt2x00: Fix TX status reporting
From: Benoit PAPILLAULT @ 2009-08-29 20:31 UTC (permalink / raw)
  To: rt2x00 Users List; +Cc: John Linville, linux-wireless
In-Reply-To: <200908291910.14528.IvDoorn@gmail.com>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Ivo van Doorn a écrit :
> Not all values of the TX status enumeration were covered during
> updating of the TX statistics. This could lead to wrong bitrate
> tuning but also wrong behavior in tools like hostapd.
>
> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
I have a pending patch about TX status that changed the meaning of
TXDONE_FALLBACK just a bit... just to avoid this change in fact.
I should be able to send those patches in few hours.

In my code, you success/failure of the packet is reported with
TXDONE_SUCCESS / TXDONE_FAILURE. The TXDONE_FALLBACK is set
independently to indicate that a fallback rate table has been used
(and this could be the case for either success or failure).

Regards,
Benoit

> --- drivers/net/wireless/rt2x00/rt2x00dev.c |   28
> ++++++++++++++++------------ 1 files changed, 16 insertions(+), 12
> deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c
> b/drivers/net/wireless/rt2x00/rt2x00dev.c index 5db613f..71761b3
> 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++
> b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -206,6 +206,7 @@ void
> rt2x00lib_txdone(struct queue_entry *entry, unsigned int
> header_length = ieee80211_get_hdrlen_from_skb(entry->skb); u8
> rate_idx, rate_flags, retry_rates; unsigned int i; +    bool success;
>
> /* * Unmap the skb. @@ -234,13 +235,18 @@ void
> rt2x00lib_txdone(struct queue_entry *entry,
> rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb);
>
> /* -     * Update TX statistics. +     * Determine if the frame has been
> successfully transmitted. */ -    rt2x00dev->link.qual.tx_success += +
> success = test_bit(TXDONE_SUCCESS, &txdesc->flags) || -
> test_bit(TXDONE_UNKNOWN, &txdesc->flags); -
> rt2x00dev->link.qual.tx_failed += -        test_bit(TXDONE_FAILURE,
> &txdesc->flags); +        test_bit(TXDONE_UNKNOWN, &txdesc->flags) ||
> +        test_bit(TXDONE_FALLBACK, &txdesc->flags); + +    /* +     *
Update
> TX statistics. +     */ +    rt2x00dev->link.qual.tx_success += success;
> +    rt2x00dev->link.qual.tx_failed += !success;
>
> rate_idx = skbdesc->tx_rate_idx; rate_flags =
> skbdesc->tx_rate_flags; @@ -263,22 +269,20 @@ void
> rt2x00lib_txdone(struct queue_entry *entry,
> tx_info->status.rates[i].flags = rate_flags;
> tx_info->status.rates[i].count = 1; } -    if (i <
> (IEEE80211_TX_MAX_RATES -1)) +    if (i < (IEEE80211_TX_MAX_RATES -
> 1)) tx_info->status.rates[i].idx = -1; /* terminate */
>
> if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { -        if
> (test_bit(TXDONE_SUCCESS, &txdesc->flags) || -
> test_bit(TXDONE_UNKNOWN, &txdesc->flags)) +        if (success)
> tx_info->flags |= IEEE80211_TX_STAT_ACK; -        else if
> (test_bit(TXDONE_FAILURE, &txdesc->flags)) +        else
> rt2x00dev->low_level_stats.dot11ACKFailureCount++; }
>
> if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { -        if
> (test_bit(TXDONE_SUCCESS, &txdesc->flags) || -
> test_bit(TXDONE_UNKNOWN, &txdesc->flags)) +        if (success)
> rt2x00dev->low_level_stats.dot11RTSSuccessCount++; -        else if
> (test_bit(TXDONE_FAILURE, &txdesc->flags)) +        else
> rt2x00dev->low_level_stats.dot11RTSFailureCount++; }
>

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkqZkB8ACgkQOR6EySwP7oKnaQCglW+lu167n88CR3Chv1i4uF1P
I1kAoLrVvvXCbmzWN8M2/wHtyTSCnUZu
=IJEh
-----END PGP SIGNATURE-----


^ permalink raw reply

* Re: [ath5k-devel] Ath5k and proprietary extensions
From: Luis R. Rodriguez @ 2009-08-29 19:15 UTC (permalink / raw)
  To: Nick Kossifidis
  Cc: Benoit PAPILLAULT, ic.felix, ath5k-devel, linux-wireless,
	John W. Linville
In-Reply-To: <40f31dec0908290847g698a65e2t589a466a13b1b7f5@mail.gmail.com>

On Sat, Aug 29, 2009 at 8:47 AM, Nick Kossifidis<mickflemm@gmail.com> wrote:
> 2009/8/29 Benoit PAPILLAULT <benoit.papillault@free.fr>:
>>
>> I have been working on XR (in madwifi) for some time with no result. I
>> would appreciate to be able to test it in ath5k.
>
> All XR related stuff is missing from both Legacy and Sam's HAL + it's
> nasty IMHO.

Agreed.

  Luis

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox