Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: 802.11: Throughput optimization beyond rate selection
From: John W. Linville @ 2009-10-12 13:59 UTC (permalink / raw)
  To: Joerg Pommnitz; +Cc: linux-wireless
In-Reply-To: <487238.22616.qm@web51405.mail.re2.yahoo.com>

On Mon, Oct 12, 2009 at 02:28:07AM -0700, Joerg Pommnitz wrote:
> Hello all,
> the throughput achieved over a wireless 802.11 network depends on more than the 
> rate selection. Other parameters are fragmentation threshold, RTS threshold 
> and the retry limits. Are you aware of a "unified throughput optimization" algorithm 
> that tries to optimize the whole parameter set instead of just the data rate? 

No, do tell...post code as well... :-)

-- 
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

* Re: [PATCH] b43: fix ieee80211_rx() context
From: John W. Linville @ 2009-10-12 13:38 UTC (permalink / raw)
  To: David Miller; +Cc: kalle.valo, johannes, hidave.darkstar, linux-wireless
In-Reply-To: <20091011.200857.141215452.davem@davemloft.net>

On Sun, Oct 11, 2009 at 08:08:57PM -0700, David Miller wrote:
> From: Kalle Valo <kalle.valo@iki.fi>
> Date: Sun, 11 Oct 2009 19:08:58 +0300
> 
> > Johannes Berg <johannes@sipsolutions.net> writes:
> > 
> >>> > +	local_bh_disable();
> >>> >  	ieee80211_rx(dev->wl->hw, skb);
> >>> > +	local_bh_enable();
> >>> 
> >>> This is a bit awkward from drivers' point of view, we have to add the
> >>> same code to all mac80211 drivers using either SPI or SDIO buses.
> >>> 
> >>> What about adding a new inline function ieee80211_rx_ni() which would
> >>> disable bottom halves like above and call ieee80211_rx()? IMHO that's
> >>> easier for the driver developers to understand and also easier to
> >>> document ("use this function when calling from process context"). If
> >>> this is acceptable, I can create a patch.
> >>
> >> I really don't see the point, since it's just three lines of code, but I
> >> wouldn't mind all that much either.
> > 
> > My worry are the developers who even don't know what is a bottom half
> > and might get it all wrong. (Yes, there really are such people.)
> 
> And the difference between this and knowing you need to call the
> ieee80211_rx_ni() thing is?
> 
> You have to know what the heck a bottom half is to even know that you
> would need to call the ieee80211_rx_ni() thing.
> 
> And that's the same amount of knowledge necessary to simply wrap the
> thing in a BH disable/enable sequence.

I'm not sure I see the difference between this and the rationale for
having netif_rx_ni vs. an open-coded version of it?  ieee80211_rx_ni
seems like a small amount of code (could even be inline) that
potentially avoids some stupid bugs...?

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

* Re: RaLink 148f:3070 not working since upgrade from 2.6.30 to 2.6.31
From: John W. Linville @ 2009-10-12 13:43 UTC (permalink / raw)
  To: Bráulio B O Bhavamitra; +Cc: linux-wireless
In-Reply-To: <1df1788c0910110518l1d120983id2bf997d2446b4a7@mail.gmail.com>

On Sun, Oct 11, 2009 at 09:18:24AM -0300, Bráulio B O Bhavamitra wrote:
> Also in Ubuntu Karmic Beta (where the firmware is present) it doesn't
> work (radio not working, can't find any access point)
> 
> 2009/10/11 Bráulio B O Bhavamitra <brauliobo@gmail.com>:
> > Since the upgrade from kernel 2.6.30 to 2.6.31 on archlinux the usb
> > wireless from Ralink doesn't work anymore.
> > Please ask for more info if necessary.

This commit is post-2.6.30 (and pre-2.6.31):

commit d53d9e67b55f6a9fc3f836c5c392eb41ce5676f4
Author: Ivo van Doorn <IvDoorn@gmail.com>
Date:   Sun Apr 26 15:47:48 2009 +0200

    rt2x00: Implement support for rt2800usb
    
    Add support for the rt2800usb chipset.
    
    Current problems:
     * Cannot scan 11n AP's
     * No TX during first minute after association
     * Broken Hardware encryption
    
    Includes various patches from Mattias, Felix, Xose and Axel.
    
    Signed-off-by: Mattias Nissler <mattias.nissler@gmx.de>
    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
    Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com>
    Signed-off-by: Axel Kollhofer <rain_maker@root-forum.org>
    Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
    Signed-off-by: John W. Linville <linville@tuxdriver.com>

That is the first time 148f:3070 is supported by the rt2x00 drivers.
I have no idea what you were using up to 2.6.30...

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

* Re: [RFC] p54pci: skb_over_panic, soft lockup, stall under flood
From: Quintin Pitts @ 2009-10-12 13:34 UTC (permalink / raw)
  To: Christian Lamparter; +Cc: Larry Finger, linux-wireless
In-Reply-To: <200910121057.10381.chunkeey@googlemail.com>

On Mon Oct 12 2009 03:57:10 GMT-0500 (CDT), Christian Lamparter wrote:
> On Monday 12 October 2009 02:09:22 Quintin Pitts wrote:
>> On Sun Oct 11 2009 10:31:42 GMT-0500 (CDT), Larry Finger wrote:
>>> On 10/11/2009 09:28 AM, Quintin Pitts wrote:
>>> As I understand it, this patch is to fix the driver to work around
>>> firmware errors. If that is correct, please state that clearly. If
>>> only partially correct, then indicate which parts are to fix firmware
>>> errors, and which are to fix driver errors. Has your analysis included
>>> thinking about where the driver might delay to avoid firmware problems.
>> I think Christian has hit the nail on the head.
>> Mostly flaky hardware or implementation (it8152 pci bridge) when pushed.
> 
> hmm, flaky hardware or simply incomplete linux support.
> you've said that it works with win ce,
> so I suppose the code is missing some important bits.
> 
> e.g.:
> 
> 00:06.0 Network controller: Intersil Corporation ISL3886 [Prism Javelin/Prism Xbow] (rev 01)
> Subsystem: Intersil Corporation Device 0000
> Flags: bus master, medium devsel, latency 56, IRQ 217
> 
> by the looks of it, something could wrong with the latency timer value.
> (what's lspci -vvnnxxx output for the card?)

00:06.0 Network controller [0280]: Intersil Corporation ISL3886 [Prism Javelin/Prism Xbow] [1260:3886] (rev 01)
	Subsystem: Intersil Corporation Device [1260:0000]
	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 56 (2500ns min, 7000ns max), Cache Line Size: 32 bytes
	Interrupt: pin A routed to IRQ 217
	Region 0: Memory at 11000000 (32-bit, non-prefetchable) [size=8K]
	Capabilities: [dc] Power Management version 1
		Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
		Status: D0 PME-Enable- DSel=0 DScale=0 PME-
	Kernel modules: prism54, p54pci
00: 60 12 86 38 06 01 90 02 01 00 80 02 08 38 00 00
10: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
20: 00 00 00 00 00 00 00 00 01 08 00 00 60 12 00 00
30: 00 00 00 00 dc 00 00 00 00 00 00 00 d9 01 0a 1c
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
d0: 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 fe
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

After the driver is up with the p54-latency patch:

00:06.0 Network controller [0280]: Intersil Corporation ISL3886 [Prism Javelin/Prism Xbow] [1260:3886] (rev 01)
	Subsystem: Intersil Corporation Device [1260:0000]
	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV+ VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx+
	Latency: 80 (2500ns min, 7000ns max), Cache Line Size: 32 bytes
	Interrupt: pin A routed to IRQ 217
	Region 0: Memory at 11000000 (32-bit, non-prefetchable) [size=8K]
	Capabilities: [dc] Power Management version 1
		Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
		Status: D0 PME-Enable- DSel=0 DScale=0 PME-
	Kernel driver in use: p54pci
	Kernel modules: prism54, p54pci
00: 60 12 86 38 16 01 98 02 01 00 80 02 08 50 00 00
10: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
20: 00 00 00 00 00 00 00 00 01 08 00 00 60 12 00 00
30: 00 00 00 00 dc 00 00 00 00 00 00 00 d9 01 0a 1c
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
d0: 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 fe
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

> 
> I've attached a minimal patch which c&p some latency-timer related logic
> from the original prism54 driver code to p54pci.
> Can you please give this a try?

Still same weird results with p54-latency patch.  Triggering my condition
statements. under a 3 minute iperf test.

p54p_check_rx_ring: rx_ring len/flags has address - skipping!                   
p54p_check_rx_ring: rx_ring len/flags has address - skipping!                   
p54p_check_rx_ring: rx_ring len/flags has address - skipping!                   
p54p_check_rx_ring: rx_ring len/flags has address - skipping!                   
p54p_check_rx_ring: rx_ring len/flags has address - skipping!                   
p54p_check_rx_ring: rx_ring len/flags has address - skipping!                   
p54p_check_rx_ring: index > ring_index diff *index=176894 devidx=176640 hostidx=
176901 ring_limit=8 Returning call!                                             
p54p_check_rx_ring: rx_ring len/flags has address - skipping!                   
p54p_check_rx_ring: rx_ring len/flags has address - skipping!                   
p54p_check_rx_ring: rx_ring len/flags has address - skipping!                   
p54p_check_rx_ring: rx_ring len/flags has address - skipping!                   
p54p_check_rx_ring: rx_ring len/flags has address - skipping!     

> I don't have a p54pci available for testing right now.
> 
> Regards,
> 	Chr

Thanks,

Quintin.

^ permalink raw reply

* Re: [PATCH 1/3] iwmc3200top: Add Intel Wireless MultiCom 3200 top driver.
From: John W. Linville @ 2009-10-12 13:17 UTC (permalink / raw)
  To: David Miller
  Cc: tomasw, netdev, linux-wireless, linux-mmc, yi.zhu,
	inaky.perez-gonzalez, cindy.h.kao, guy.cohen, ron.rindjunsky
In-Reply-To: <20091011.033647.66923614.davem@davemloft.net>

On Sun, Oct 11, 2009 at 03:36:47AM -0700, David Miller wrote:
> From: Tomas Winkler <tomasw@gmail.com>
> Date: Sun, 11 Oct 2009 10:05:20 +0200
> 
> > Just close my eyes and there is new game to play. :)
> > It's not in the patchwork, so is there any reason you are not planning
> > to add it.   The patch intention was for net-next, it looks like
> > I didn't mark it as such, my fault.
> 
> Because there still seems to be some confusion between which of these
> bits go through John Linville as a wireless driver and which bits
> go directly through me.
> 
> By default I assume John picks up "wireless" drivers and send them
> to me in his wireless merges to me.
> 
> If that's not the case, explicitly do a fresh submission of this patch
> and explicitly ask me to merge it.

I was afraid this might get lost in the confusion.  I had other things
to worry about and since it crossed so many lines and was sent to
netdev, I figured I'd worry about it later if it got lost... :-(

FWIW, I think the wimax/bluetooth/wifi connection makes net-next-2.6
the right tree for this.

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

* Re: WARNING: slow-path
From: David Woodhouse @ 2009-10-12 13:08 UTC (permalink / raw)
  To: Holger Schurig; +Cc: linux-wireless
In-Reply-To: <200910121335.21807.hs4233@mail.mn-solutions.de>

On Mon, 2009-10-12 at 13:35 +0200, Holger Schurig wrote:
> [   33.369923] WARNING: at net/wireless/mlme.c:135 __cfg80211_send_deauth+0x3f/0x1e1 [cfg80211]()

You're triggering the warning at line 135 of net/wireless/mlme.c, which
is 'ASSERT_WDEV_LOCK(wdev)' -- it's complaining that the lock isn't
held.
 
> static int lbs_cfg_ret_deauth(struct lbs_private *priv, unsigned long dummy,
>                            struct cmd_header *resp)
>         cfg80211_send_deauth(priv->dev, (u8 *)&mgmt, sizeof(mgmt),
>                              (void *)dummy); 

What happens if you make that last argument NULL instead of passing
'dummy' back to it? That makes cfg80211_send_deauth() magically do
different things w.r.t. locking. Johannes, this is _evil_:

void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
                          void *cookie)
{
        struct wireless_dev *wdev = dev->ieee80211_ptr;

        BUG_ON(cookie && wdev != cookie);

        if (cookie) {
                /* called within callback */
                __cfg80211_send_deauth(dev, buf, len);
        } else {
                wdev_lock(wdev);
                __cfg80211_send_deauth(dev, buf, len);
                wdev_unlock(wdev);
        }
}


-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation


^ permalink raw reply

* Re: [PATCH] b43: fix ieee80211_rx() context
From: Luciano Coelho @ 2009-10-12 12:29 UTC (permalink / raw)
  To: ext Kalle Valo
  Cc: David Miller, johannes@sipsolutions.net, linville@tuxdriver.com,
	hidave.darkstar@gmail.com, linux-wireless@vger.kernel.org
In-Reply-To: <87tyy5njbf.fsf@purkki.valot.fi>

ext Kalle Valo wrote:
> David Miller <davem@davemloft.net> writes:
> 
>>>> I really don't see the point, since it's just three lines of code, but I
>>>> wouldn't mind all that much either.
>>> My worry are the developers who even don't know what is a bottom half
>>> and might get it all wrong. (Yes, there really are such people.)
>> And the difference between this and knowing you need to call the
>> ieee80211_rx_ni() thing is?
>>
>> You have to know what the heck a bottom half is to even know that you
>> would need to call the ieee80211_rx_ni() thing.
>>
>> And that's the same amount of knowledge necessary to simply wrap the
>> thing in a BH disable/enable sequence.
> 
> I was thinking that it's possible to document it something like this:
> 
> o in irq context use ieee80211_rx_irqsafe()
> o in a tasklet use ieee80211_rx()
> o in process context use ieee80211_rx_ni()
> 
> Also in the future it might be easier to optimise something based on
> these functions. Maybe.
> 
> But as Johannes didn't like the idea, and neither do you, I'm going to
> drop the idea. I'll add the BH disable/enable to wl1251 instead and
> hopefully Luciano does the same to wl1271.

Yeps, I can do the same for wl1271.

-- 
Cheers,
Luca.

^ permalink raw reply

* 2.6.32-rc4-git1 -- INFO: possible circular locking dependency detected
From: Miles Lane @ 2009-10-12 12:28 UTC (permalink / raw)
  To: LKML, Johannes Berg, linux-wireless

[  823.466853] [ INFO: possible circular locking dependency detected ]
[  823.466866] 2.6.32-rc4-git1 #2
[  823.466873] -------------------------------------------------------
[  823.466884] swapper/0 is trying to acquire lock:
[  823.466893]  (&sta->lock){+.-...}, at: [<f857bda4>]
sta_addba_resp_timer_expired+0x1b/0x50 [mac80211]
[  823.466940]
[  823.466943] but task is already holding lock:
[  823.466953]
(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer){+.-...}, at:
[<c1032f22>] run_timer_softirq+0x125/0x1e5
[  823.466984]
[  823.466987] which lock already depends on the new lock.
[  823.466991]
[  823.467000]
[  823.467002] the existing dependency chain (in reverse order) is:
[  823.467013]
[  823.467015] -> #1 (&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer){+.-...}:
[  823.467037]        [<c104ac2c>] __lock_acquire+0x9fb/0xb6d
[  823.467056]        [<c104adfa>] lock_acquire+0x5c/0x73
[  823.467072]        [<c10336b8>] del_timer_sync+0x29/0x6c
[  823.467089]        [<f857bceb>]
ieee80211_process_addba_resp+0x49/0xa0 [mac80211]
[  823.467121]        [<f8584585>] ieee80211_rx_h_action+0xeb/0x335 [mac80211]
[  823.467157]        [<f8585654>]
ieee80211_invoke_rx_handlers+0xe50/0x10d8 [mac80211]
[  823.467193]        [<f8585d46>]
__ieee80211_rx_handle_packet+0x46a/0x497 [mac80211]
[  823.467229]        [<f8586475>] ieee80211_rx+0x4d1/0x530 [mac80211]
[  823.467263]        [<f89936e3>] ath_rx_send_to_mac80211+0xa0/0xa8 [ath9k]
[  823.467302]        [<f899439e>] ath_rx_tasklet+0x7b6/0x7f5 [ath9k]
[  823.467338]        [<f8992115>] ath9k_tasklet+0x47/0xc7 [ath9k]
[  823.467373]        [<c102f4a1>] tasklet_action+0x8e/0xe1
[  823.467391]        [<c102f95b>] __do_softirq+0x8d/0x117
[  823.467409]
[  823.467412] -> #0 (&sta->lock){+.-...}:
[  823.467430]        [<c104ab2e>] __lock_acquire+0x8fd/0xb6d
[  823.467447]        [<c104adfa>] lock_acquire+0x5c/0x73
[  823.467464]        [<c132526f>] _spin_lock_bh+0x2a/0x39
[  823.467481]        [<f857bda4>]
sta_addba_resp_timer_expired+0x1b/0x50 [mac80211]
[  823.467514]        [<c1032f6d>] run_timer_softirq+0x170/0x1e5
[  823.467531]        [<c102f95b>] __do_softirq+0x8d/0x117
[  823.467548]
[  823.467551] other info that might help us debug this:
[  823.467555]
[  823.467566] 1 lock held by swapper/0:
[  823.467574]  #0:
(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer){+.-...}, at:
[<c1032f22>] run_timer_softirq+0x125/0x1e5
[  823.467604]
[  823.467607] stack backtrace:
[  823.467619] Pid: 0, comm: swapper Not tainted 2.6.32-rc4-git1 #2
[  823.467628] Call Trace:
[  823.467643]  [<c13233c8>] ? printk+0xf/0x11
[  823.467659]  [<c1049ef5>] print_circular_bug+0x8a/0x96
[  823.467675]  [<c104ab2e>] __lock_acquire+0x8fd/0xb6d
[  823.467694]  [<c104adfa>] lock_acquire+0x5c/0x73
[  823.467725]  [<f857bda4>] ? sta_addba_resp_timer_expired+0x1b/0x50 [mac80211]
[  823.467742]  [<c132526f>] _spin_lock_bh+0x2a/0x39
[  823.467772]  [<f857bda4>] ? sta_addba_resp_timer_expired+0x1b/0x50 [mac80211]
[  823.467803]  [<f857bda4>] sta_addba_resp_timer_expired+0x1b/0x50 [mac80211]
[  823.467820]  [<c1032f6d>] run_timer_softirq+0x170/0x1e5
[  823.467836]  [<c1032f22>] ? run_timer_softirq+0x125/0x1e5
[  823.467866]  [<f857bd89>] ? sta_addba_resp_timer_expired+0x0/0x50 [mac80211]
[  823.467885]  [<c102f95b>] __do_softirq+0x8d/0x117
[  823.467901]  [<c102f8ce>] ? __do_softirq+0x0/0x117
[  823.467911]  <IRQ>  [<c102faf5>] ? irq_exit+0x38/0x75
[  823.467939]  [<c10045b1>] ? do_IRQ+0x88/0x9c
[  823.467954]  [<c1003175>] ? common_interrupt+0x35/0x3c
[  823.467971]  [<c104007b>] ? sched_clock_tick+0x31/0x77
[  823.467989]  [<c11b84ff>] ? acpi_idle_enter_bm+0x233/0x25e
[  823.468008]  [<c125c232>] ? cpuidle_idle_call+0x65/0x9b
[  823.468023]  [<c1001cd1>] ? cpu_idle+0xb9/0xe8
[  823.468041]  [<c131708b>] ? rest_init+0x67/0x69
[  823.468058]  [<c14e28e8>] ? start_kernel+0x3a3/0x3aa
[  823.468076]  [<c14e2098>] ? i386_start_kernel+0x98/0x9f

^ permalink raw reply

* Re: 2.6.32-rc4: Reported regressions 2.6.30 -> 2.6.31
From: Frederik Deweerdt @ 2009-10-12 12:22 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Andrew Morton, Linus Torvalds,
	Natalie Protasevich, Kernel Testers List, Network Development,
	Linux ACPI, Linux PM List, Linux SCSI List, Linux Wireless List,
	DRI
In-Reply-To: <56acieJJ2fF.A.nEB.Hzl0KB@chimera>

Hi Rafael,

On Mon, Oct 12, 2009 at 12:41:30AM +0200, Rafael J. Wysocki wrote:
> Bug-Entry	: http://bugzilla.kernel.org/show_bug.cgi?id=14185
> Subject		: Oops in driversbasefirmware_class
> Submitter	:  <lars_ericsson@telia.com>
> Date		: 2009-09-17 05:09 (25 days old)
> First-Bad-Commit: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6e03a201bbe8137487f340d26aa662110e324b20
> 
> 
> Bug-Entry	: http://bugzilla.kernel.org/show_bug.cgi?id=14253
> Subject		: Oops in driversbasefirmware_class
> Submitter	: Lars Ericsson <Lars_Ericsson@telia.com>
> Date		: 2009-09-16 20:44 (26 days old)
> References	: http://lkml.org/lkml/2009/9/16/461
> Handled-By	: Frederik Deweerdt <frederik.deweerdt@xprog.eu>
> Patch		: http://patchwork.kernel.org/patch/49914/
> 
Those two are refering to the same bug.

Regards,
Frederik

^ permalink raw reply

* [PATCH 11/16] wl1271: Enable smart reflex
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Enable and configure smart reflex. This should have a reducing impact on
power consumption.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_acx.c  |   72 +++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/wl1271_acx.h  |   23 +++++++++
 drivers/net/wireless/wl12xx/wl1271_init.c |    5 ++
 3 files changed, 100 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index d5dac57..6c29890 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -998,3 +998,75 @@ out:
 	kfree(rx_conf);
 	return ret;
 }
+
+int wl1271_acx_smart_reflex(struct wl1271 *wl)
+{
+	struct acx_smart_reflex_state *sr_state = NULL;
+	struct acx_smart_reflex_config_params *sr_param = NULL;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx smart reflex");
+
+	sr_param = kzalloc(sizeof(*sr_param), GFP_KERNEL);
+	if (!sr_param) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* set cryptic smart reflex parameters - source TI reference code */
+	sr_param->error_table[0].len = 0x07;
+	sr_param->error_table[0].upper_limit = 0x03;
+	sr_param->error_table[0].values[0] = 0x18;
+	sr_param->error_table[0].values[1] = 0x10;
+	sr_param->error_table[0].values[2] = 0x05;
+	sr_param->error_table[0].values[3] = 0xfb;
+	sr_param->error_table[0].values[4] = 0xf0;
+	sr_param->error_table[0].values[5] = 0xe8;
+
+	sr_param->error_table[1].len = 0x07;
+	sr_param->error_table[1].upper_limit = 0x03;
+	sr_param->error_table[1].values[0] = 0x18;
+	sr_param->error_table[1].values[1] = 0x10;
+	sr_param->error_table[1].values[2] = 0x05;
+	sr_param->error_table[1].values[3] = 0xf6;
+	sr_param->error_table[1].values[4] = 0xf0;
+	sr_param->error_table[1].values[5] = 0xe8;
+
+	sr_param->error_table[2].len = 0x07;
+	sr_param->error_table[2].upper_limit = 0x03;
+	sr_param->error_table[2].values[0] = 0x18;
+	sr_param->error_table[2].values[1] = 0x10;
+	sr_param->error_table[2].values[2] = 0x05;
+	sr_param->error_table[2].values[3] = 0xfb;
+	sr_param->error_table[2].values[4] = 0xf0;
+	sr_param->error_table[2].values[5] = 0xe8;
+
+	ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS,
+				   sr_param, sizeof(*sr_param));
+	if (ret < 0) {
+		wl1271_warning("failed to set smart reflex params: %d", ret);
+		goto out;
+	}
+
+	sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL);
+	if (!sr_state) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* enable smart reflex */
+	sr_state->enable = 1;
+
+	ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE,
+				   sr_state, sizeof(*sr_state));
+	if (ret < 0) {
+		wl1271_warning("failed to set smart reflex params: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(sr_state);
+	kfree(sr_param);
+	return ret;
+
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 07256d2..0c704af 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -445,6 +445,25 @@ struct acx_bt_wlan_coex {
 	u8 pad[3];
 } __attribute__ ((packed));
 
+struct acx_smart_reflex_state {
+	struct acx_header header;
+
+	u8 enable;
+	u8 padding[3];
+};
+
+struct smart_reflex_err_table {
+	u8 len;
+	s8 upper_limit;
+	s8 values[14];
+};
+
+struct acx_smart_reflex_config_params {
+	struct acx_header header;
+
+	struct smart_reflex_err_table error_table[3];
+};
+
 #define PTA_ANTENNA_TYPE_DEF		  (0)
 #define PTA_BT_HP_MAXTIME_DEF		  (2000)
 #define PTA_WLAN_HP_MAX_TIME_DEF	  (5000)
@@ -1184,6 +1203,9 @@ enum {
 	ACX_PEER_HT_CAP             = 0x0057,
 	ACX_HT_BSS_OPERATION        = 0x0058,
 	ACX_COEX_ACTIVITY           = 0x0059,
+	ACX_SET_SMART_REFLEX_DEBUG  = 0x005A,
+	ACX_SET_SMART_REFLEX_STATE  = 0x005B,
+	ACX_SET_SMART_REFLEX_PARAMS = 0x005F,
 	DOT11_RX_MSDU_LIFE_TIME     = 0x1004,
 	DOT11_CUR_TX_PWR            = 0x100D,
 	DOT11_RX_DOT11_MODE         = 0x1012,
@@ -1233,5 +1255,6 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl);
 int wl1271_acx_mem_cfg(struct wl1271 *wl);
 int wl1271_acx_init_mem_config(struct wl1271 *wl);
 int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
+int wl1271_acx_smart_reflex(struct wl1271 *wl);
 
 #endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index bf4d0e1..f9315f6 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -394,6 +394,11 @@ int wl1271_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		goto out_free_memmap;
 
+	/* Configure smart reflex */
+	ret = wl1271_acx_smart_reflex(wl);
+	if (ret < 0)
+		goto out_free_memmap;
+
 	return 0;
 
  out_free_memmap:
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 09/16] wl1271: Update interrupt handling by removing an extra SPI read
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Remove separate interrupt register reading from the interrupt handling
routine. This will slightly improve interrupt performance.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_main.c |   74 ++++++++++++-----------------
 drivers/net/wireless/wl12xx/wl1271_reg.h  |    2 +-
 2 files changed, 31 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 22d44ba..8ac9bc1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -76,20 +76,14 @@ static void wl1271_power_on(struct wl1271 *wl)
 	wl->set_power(true);
 }
 
-static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status)
+static void wl1271_fw_status(struct wl1271 *wl,
+			     struct wl1271_fw_status *status)
 {
 	u32 total = 0;
 	int i;
 
-	/*
-	 * FIXME: Reading the FW status directly from the registers seems to
-	 * be the right thing to do, but it doesn't work.  And in the
-	 * reference driver, there is a workaround called
-	 * USE_SDIO_24M_WORKAROUND, which reads the status from memory
-	 * instead, so we do the same here.
-	 */
-
-	wl1271_spi_mem_read(wl, STATUS_MEM_ADDRESS, status, sizeof(*status));
+	wl1271_spi_reg_read(wl, FW_STATUS_ADDR, status,
+			    sizeof(*status), false);
 
 	wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
 		     "drv_rx_counter = %d, tx_results_counter = %d)",
@@ -114,11 +108,10 @@ static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status)
 	wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
 }
 
-#define WL1271_IRQ_MAX_LOOPS 10
 static void wl1271_irq_work(struct work_struct *work)
 {
-	u32 intr, ctr = WL1271_IRQ_MAX_LOOPS;
 	int ret;
+	u32 intr;
 	struct wl1271 *wl =
 		container_of(work, struct wl1271, irq_work);
 
@@ -135,7 +128,8 @@ static void wl1271_irq_work(struct work_struct *work)
 
 	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
 
-	intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
+	wl1271_fw_status(wl, wl->fw_status);
+	intr = wl->fw_status->intr;
 	if (!intr) {
 		wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
 		goto out_sleep;
@@ -143,43 +137,35 @@ static void wl1271_irq_work(struct work_struct *work)
 
 	intr &= WL1271_INTR_MASK;
 
-	do {
-		wl1271_fw_status(wl, wl->fw_status);
-
-
-		if (intr & (WL1271_ACX_INTR_EVENT_A |
-			    WL1271_ACX_INTR_EVENT_B)) {
-			wl1271_debug(DEBUG_IRQ,
-				     "WL1271_ACX_INTR_EVENT (0x%x)", intr);
-			if (intr & WL1271_ACX_INTR_EVENT_A)
-				wl1271_event_handle(wl, 0);
-			else
-				wl1271_event_handle(wl, 1);
-		}
+	if (intr & (WL1271_ACX_INTR_EVENT_A |
+		    WL1271_ACX_INTR_EVENT_B)) {
+		wl1271_debug(DEBUG_IRQ,
+			     "WL1271_ACX_INTR_EVENT (0x%x)", intr);
+		if (intr & WL1271_ACX_INTR_EVENT_A)
+			wl1271_event_handle(wl, 0);
+		else
+			wl1271_event_handle(wl, 1);
+	}
 
-		if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
-			wl1271_debug(DEBUG_IRQ,
-				     "WL1271_ACX_INTR_INIT_COMPLETE");
+	if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
+		wl1271_debug(DEBUG_IRQ,
+			     "WL1271_ACX_INTR_INIT_COMPLETE");
 
-		if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
-			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
+	if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
+		wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
 
-		if (intr & WL1271_ACX_INTR_DATA) {
-			u8 tx_res_cnt = wl->fw_status->tx_results_counter -
-				wl->tx_results_count;
+	if (intr & WL1271_ACX_INTR_DATA) {
+		u8 tx_res_cnt = wl->fw_status->tx_results_counter -
+			wl->tx_results_count;
 
-			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
+		wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
 
-			/* check for tx results */
-			if (tx_res_cnt)
-				wl1271_tx_complete(wl, tx_res_cnt);
+		/* check for tx results */
+		if (tx_res_cnt)
+			wl1271_tx_complete(wl, tx_res_cnt);
 
-			wl1271_rx(wl, wl->fw_status);
-		}
-
-		intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
-		intr &= WL1271_INTR_MASK;
-	} while (intr && --ctr);
+		wl1271_rx(wl, wl->fw_status);
+	}
 
 out_sleep:
 	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
diff --git a/drivers/net/wireless/wl12xx/wl1271_reg.h b/drivers/net/wireless/wl12xx/wl1271_reg.h
index bd12615..6af87b5 100644
--- a/drivers/net/wireless/wl12xx/wl1271_reg.h
+++ b/drivers/net/wireless/wl12xx/wl1271_reg.h
@@ -34,7 +34,7 @@
 #define REGISTERS_WORK_SIZE 0x0000b000
 
 #define HW_ACCESS_ELP_CTRL_REG_ADDR         0x1FFFC
-#define STATUS_MEM_ADDRESS                  0x40400
+#define FW_STATUS_ADDR                      (0x14FC0 + 0xA000)
 
 /* ELP register commands */
 #define ELPCTRL_WAKE_UP             0x1
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 10/16] wl1271: Enable ELP
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

The new firmware has fixed a firmware crash problem related to ELP entry.
Enable ELP to conserve power.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_ps.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index 5580e53..fb821c9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -39,12 +39,7 @@ void wl1271_elp_work(struct work_struct *work)
 
 	mutex_lock(&wl->mutex);
 
-	/*
-	 * FIXME: below, by means of the "true", ELP has been disabled for now
-	 * to work around a firmware bug. To be enabled upon receiving a new
-	 * firmware version.
-	 */
-	if (true || wl->elp || !wl->psm)
+	if (wl->elp || !wl->psm)
 		goto out;
 
 	wl1271_debug(DEBUG_PSM, "chip to elp");
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 02/16] wl1271: workaround to send a disconnect before rejoining
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

We don't get any indication from the stack when we have disassociated.  In
wl1271, it is important to send a CMD_DISCONNECT before joining again,
because the firmware cleans some things up.  So we check if we're already
joined and disconnect if that's the case.

Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h      |    3 +++
 drivers/net/wireless/wl12xx/wl1271_cmd.c  |   15 +++++++++++++++
 drivers/net/wireless/wl12xx/wl1271_main.c |    3 +++
 3 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 96a5813..858bf6b 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -422,6 +422,9 @@ struct wl1271 {
 	struct wl1271_tx_hw_res_if *tx_res_if;
 
 	struct ieee80211_vif *vif;
+
+	/* Used for a workaround to send disconnect before rejoining */
+	bool joined;
 };
 
 int wl1271_plt_start(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index d09ad12..ef92834 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -191,6 +191,19 @@ int wl1271_cmd_join(struct wl1271 *wl)
 			do_cal = false;
 	}
 
+	/* FIXME: This is a workaround, because with the current stack, we
+	 * cannot know when we have disassociated.  So, if we have already
+	 * joined, we disconnect before joining again. */
+	if (wl->joined) {
+		ret = wl1271_cmd_disconnect(wl);
+		if (ret < 0) {
+			wl1271_error("failed to disconnect before rejoining");
+			goto out;
+		}
+
+		wl->joined = false;
+	}
+
 	join = kzalloc(sizeof(*join), GFP_KERNEL);
 	if (!join) {
 		ret = -ENOMEM;
@@ -245,6 +258,8 @@ int wl1271_cmd_join(struct wl1271 *wl)
 		goto out_free;
 	}
 
+	wl->joined = true;
+
 	/*
 	 * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
 	 * simplify locking we just sleep instead, for now
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 3662715..b9f2091 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -648,6 +648,8 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
 	wl->tx_security_seq_32 = 0;
 	wl->time_offset = 0;
 	wl->session_counter = 0;
+	wl->joined = false;
+
 	for (i = 0; i < NUM_TX_QUEUES; i++)
 		wl->tx_blocks_freed[i] = 0;
 
@@ -1395,6 +1397,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 	wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
 	wl->band = IEEE80211_BAND_2GHZ;
 	wl->vif = NULL;
+	wl->joined = false;
 
 	for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
 		wl->tx_frames[i] = NULL;
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 14/16] wl1271: Update boot time configuration for the new firmware
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Update the magic values of the wl1271 boot time config according to the new
reference driver.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_init.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index f9315f6..e45af07 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -202,7 +202,7 @@ static int wl1271_init_general_parms(struct wl1271 *wl)
 	gen_parms->clk_valid_on_wakeup = 0;
 	gen_parms->dc2dcmode = 0;
 	gen_parms->single_dual_band = 0;
-	gen_parms->tx_bip_fem_autodetect = 1;
+	gen_parms->tx_bip_fem_autodetect = 0;
 	gen_parms->tx_bip_fem_manufacturer = 1;
 	gen_parms->settings = 1;
 
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 13/16] wl1271: Remove outdated SPI functions
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

With the change to the new firmware, there was a change to firmware memory
partitioning. Along with that change, the translation of all partitions was
unified, and separate functions for reg and mem access became unnecessary.

Cleanup the unnecessary functions.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_boot.c  |   63 +++++++++++----------
 drivers/net/wireless/wl12xx/wl1271_cmd.c   |   19 +++---
 drivers/net/wireless/wl12xx/wl1271_event.c |    8 +-
 drivers/net/wireless/wl12xx/wl1271_main.c  |   12 ++--
 drivers/net/wireless/wl12xx/wl1271_ps.c    |    4 +-
 drivers/net/wireless/wl12xx/wl1271_rx.c    |   10 ++--
 drivers/net/wireless/wl12xx/wl1271_spi.c   |   85 +++++++++-------------------
 drivers/net/wireless/wl12xx/wl1271_spi.h   |   36 +++++-------
 drivers/net/wireless/wl12xx/wl1271_tx.c    |   10 ++--
 9 files changed, 107 insertions(+), 140 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index b586577..a27601d 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -93,19 +93,19 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
 	u32 cpu_ctrl;
 
 	/* 10.5.0 run the firmware (I) */
-	cpu_ctrl = wl1271_reg_read32(wl, ACX_REG_ECPU_CONTROL);
+	cpu_ctrl = wl1271_spi_read32(wl, ACX_REG_ECPU_CONTROL);
 
 	/* 10.5.1 run the firmware (II) */
 	cpu_ctrl |= flag;
-	wl1271_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
+	wl1271_spi_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
 }
 
 static void wl1271_boot_fw_version(struct wl1271 *wl)
 {
 	struct wl1271_static_data static_data;
 
-	wl1271_spi_mem_read(wl, wl->cmd_box_addr,
-			    &static_data, sizeof(static_data));
+	wl1271_spi_read(wl, wl->cmd_box_addr,
+			&static_data, sizeof(static_data), false);
 
 	strncpy(wl->chip.fw_ver, static_data.fw_version,
 		sizeof(wl->chip.fw_ver));
@@ -164,7 +164,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
 		memcpy(chunk, p, CHUNK_SIZE);
 		wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
 			     p, addr);
-		wl1271_spi_mem_write(wl, addr, chunk, CHUNK_SIZE);
+		wl1271_spi_write(wl, addr, chunk, CHUNK_SIZE, false);
 
 		chunk_num++;
 	}
@@ -175,7 +175,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
 	memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
 	wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
 		     fw_data_len % CHUNK_SIZE, p, addr);
-	wl1271_spi_mem_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE);
+	wl1271_spi_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
 
 	kfree(chunk);
 	return 0;
@@ -262,7 +262,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
 			wl1271_debug(DEBUG_BOOT,
 				     "nvs burst write 0x%x: 0x%x",
 				     dest_addr, val);
-			wl1271_reg_write32(wl, dest_addr, val);
+			wl1271_spi_write32(wl, dest_addr, val);
 
 			nvs_ptr += 4;
 			dest_addr += 4;
@@ -289,7 +289,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
 	/* FIXME: In wl1271, we upload everything at once.
 	   No endianness handling needed here?! The ref driver doesn't do
 	   anything about it at this point */
-	wl1271_spi_mem_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len);
+	wl1271_spi_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
 
 	kfree(nvs_aligned);
 	return 0;
@@ -298,9 +298,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
 static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
 {
 	enable_irq(wl->irq);
-	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
+	wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
 			   WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
-	wl1271_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
+	wl1271_spi_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
 }
 
 static int wl1271_boot_soft_reset(struct wl1271 *wl)
@@ -309,12 +309,13 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
 	u32 boot_data;
 
 	/* perform soft reset */
-	wl1271_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
+	wl1271_spi_write32(wl, ACX_REG_SLV_SOFT_RESET,
+			   ACX_SLV_SOFT_RESET_BIT);
 
 	/* SOFT_RESET is self clearing */
 	timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
 	while (1) {
-		boot_data = wl1271_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
+		boot_data = wl1271_spi_read32(wl, ACX_REG_SLV_SOFT_RESET);
 		wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
 		if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
 			break;
@@ -330,10 +331,10 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
 	}
 
 	/* disable Rx/Tx */
-	wl1271_reg_write32(wl, ENABLE, 0x0);
+	wl1271_spi_write32(wl, ENABLE, 0x0);
 
 	/* disable auto calibration on start*/
-	wl1271_reg_write32(wl, SPARE_A2, 0xffff);
+	wl1271_spi_write32(wl, SPARE_A2, 0xffff);
 
 	return 0;
 }
@@ -345,7 +346,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
 
 	wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
 
-	chip_id = wl1271_reg_read32(wl, CHIP_ID_B);
+	chip_id = wl1271_spi_read32(wl, CHIP_ID_B);
 
 	wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
 
@@ -358,7 +359,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
 	loop = 0;
 	while (loop++ < INIT_LOOP) {
 		udelay(INIT_LOOP_DELAY);
-		interrupt = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+		interrupt = wl1271_spi_read32(wl,
+					      ACX_REG_INTERRUPT_NO_CLEAR);
 
 		if (interrupt == 0xffffffff) {
 			wl1271_error("error reading hardware complete "
@@ -367,7 +369,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
 		}
 		/* check that ACX_INTR_INIT_COMPLETE is enabled */
 		else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) {
-			wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
+			wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK,
 					   WL1271_ACX_INTR_INIT_COMPLETE);
 			break;
 		}
@@ -380,10 +382,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
 	}
 
 	/* get hardware config command mail box */
-	wl->cmd_box_addr = wl1271_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);
+	wl->cmd_box_addr = wl1271_spi_read32(wl, REG_COMMAND_MAILBOX_PTR);
 
 	/* get hardware config event mail box */
-	wl->event_box_addr = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
+	wl->event_box_addr = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR);
 
 	/* set the working partition to its "running" mode offset */
 	wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -458,9 +460,9 @@ int wl1271_boot(struct wl1271 *wl)
 		wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
 	}
 
-	wl1271_reg_write32(wl, PLL_PARAMETERS, clk);
+	wl1271_spi_write32(wl, PLL_PARAMETERS, clk);
 
-	pause = wl1271_reg_read32(wl, PLL_PARAMETERS);
+	pause = wl1271_spi_read32(wl, PLL_PARAMETERS);
 
 	wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
 
@@ -469,10 +471,10 @@ int wl1271_boot(struct wl1271 *wl)
 					   * 0x3ff (magic number ).  How does
 					   * this work?! */
 	pause |= WU_COUNTER_PAUSE_VAL;
-	wl1271_reg_write32(wl, WU_COUNTER_PAUSE, pause);
+	wl1271_spi_write32(wl, WU_COUNTER_PAUSE, pause);
 
 	/* Continue the ELP wake up sequence */
-	wl1271_reg_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
+	wl1271_spi_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
 	udelay(500);
 
 	wl1271_set_partition(wl, &part_table[PART_DRPW]);
@@ -482,18 +484,18 @@ int wl1271_boot(struct wl1271 *wl)
 	   before taking DRPw out of reset */
 
 	wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START);
-	clk = wl1271_reg_read32(wl, DRPW_SCRATCH_START);
+	clk = wl1271_spi_read32(wl, DRPW_SCRATCH_START);
 
 	wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
 
 	/* 2 */
 	clk |= (REF_CLOCK << 1) << 4;
-	wl1271_reg_write32(wl, DRPW_SCRATCH_START, clk);
+	wl1271_spi_write32(wl, DRPW_SCRATCH_START, clk);
 
 	wl1271_set_partition(wl, &part_table[PART_WORK]);
 
 	/* Disable interrupts */
-	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+	wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
 
 	ret = wl1271_boot_soft_reset(wl);
 	if (ret < 0)
@@ -508,21 +510,22 @@ int wl1271_boot(struct wl1271 *wl)
 	 * ACX_EEPROMLESS_IND_REG */
 	wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
 
-	wl1271_reg_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG);
+	wl1271_spi_write32(wl, ACX_EEPROMLESS_IND_REG,
+			   ACX_EEPROMLESS_IND_REG);
 
-	tmp = wl1271_reg_read32(wl, CHIP_ID_B);
+	tmp = wl1271_spi_read32(wl, CHIP_ID_B);
 
 	wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
 
 	/* 6. read the EEPROM parameters */
-	tmp = wl1271_reg_read32(wl, SCR_PAD2);
+	tmp = wl1271_spi_read32(wl, SCR_PAD2);
 
 	ret = wl1271_boot_write_irq_polarity(wl);
 	if (ret < 0)
 		goto out;
 
 	/* FIXME: Need to check whether this is really what we want */
-	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
+	wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
 			   WL1271_ACX_ALL_EVENTS_VECTOR);
 
 	/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index ef92834..f727744 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -55,13 +55,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len)
 
 	WARN_ON(len % 4 != 0);
 
-	wl1271_spi_mem_write(wl, wl->cmd_box_addr, buf, len);
+	wl1271_spi_write(wl, wl->cmd_box_addr, buf, len, false);
 
-	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
+	wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
 
 	timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);
 
-	intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+	intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
 	while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
 		if (time_after(jiffies, timeout)) {
 			wl1271_error("command complete timeout");
@@ -71,10 +71,10 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len)
 
 		msleep(1);
 
-		intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+		intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
 	}
 
-	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
+	wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK,
 			   WL1271_ACX_INTR_CMD_COMPLETE);
 
 out:
@@ -302,7 +302,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer)
 		 * The answer would be a wl1271_command, where the
 		 * parameter array contains the actual answer.
 		 */
-		wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len);
+		wl1271_spi_read(wl, wl->cmd_box_addr, buf, buf_len, false);
 
 		cmd_answer = buf;
 
@@ -341,7 +341,7 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len)
 	}
 
 	/* the interrogate command got in, we can read the answer */
-	wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, len);
+	wl1271_spi_read(wl, wl->cmd_box_addr, buf, len, false);
 
 	acx = buf;
 	if (acx->cmd.status != CMD_STATUS_SUCCESS)
@@ -496,7 +496,7 @@ int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
 	}
 
 	/* the read command got in, we can now read the answer */
-	wl1271_spi_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
+	wl1271_spi_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd), false);
 
 	if (cmd->header.status != CMD_STATUS_SUCCESS)
 		wl1271_error("error in read command result: %d",
@@ -591,7 +591,8 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
 		goto out;
 	}
 
-	wl1271_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
+	wl1271_spi_read(wl, wl->cmd_box_addr, params, sizeof(*params),
+			false);
 
 	if (params->header.status != CMD_STATUS_SUCCESS) {
 		wl1271_error("Scan command error: %d",
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index f329276..4189e97 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -98,7 +98,7 @@ int wl1271_event_unmask(struct wl1271 *wl)
 
 void wl1271_event_mbox_config(struct wl1271 *wl)
 {
-	wl->mbox_ptr[0] = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
+	wl->mbox_ptr[0] = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR);
 	wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
 
 	wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
@@ -116,8 +116,8 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
 		return -EINVAL;
 
 	/* first we read the mbox descriptor */
-	wl1271_spi_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
-			    sizeof(struct event_mailbox));
+	wl1271_spi_read(wl, wl->mbox_ptr[mbox_num], &mbox,
+			sizeof(struct event_mailbox), false);
 
 	/* process the descriptor */
 	ret = wl1271_event_process(wl, &mbox);
@@ -125,7 +125,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
 		return ret;
 
 	/* then we let the firmware know it can go on...*/
-	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
+	wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 8ac9bc1..5ef0bd5 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -82,8 +82,8 @@ static void wl1271_fw_status(struct wl1271 *wl,
 	u32 total = 0;
 	int i;
 
-	wl1271_spi_reg_read(wl, FW_STATUS_ADDR, status,
-			    sizeof(*status), false);
+	wl1271_spi_read(wl, FW_STATUS_ADDR, status,
+			sizeof(*status), false);
 
 	wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
 		     "drv_rx_counter = %d, tx_results_counter = %d)",
@@ -126,7 +126,7 @@ static void wl1271_irq_work(struct work_struct *work)
 	if (ret < 0)
 		goto out;
 
-	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+	wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
 
 	wl1271_fw_status(wl, wl->fw_status);
 	intr = wl->fw_status->intr;
@@ -168,7 +168,7 @@ static void wl1271_irq_work(struct work_struct *work)
 	}
 
 out_sleep:
-	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
+	wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
 			   WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
 	wl1271_ps_elp_sleep(wl);
 
@@ -279,7 +279,7 @@ static void wl1271_fw_wakeup(struct wl1271 *wl)
 	u32 elp_reg;
 
 	elp_reg = ELPCTRL_WAKE_UP;
-	wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
+	wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
 }
 
 static int wl1271_setup(struct wl1271 *wl)
@@ -322,7 +322,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
 	/* whal_FwCtrl_BootSm() */
 
 	/* 0. read chip id from CHIP_ID */
-	wl->chip.id = wl1271_reg_read32(wl, CHIP_ID_B);
+	wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B);
 
 	/* 1. check if chip id is valid */
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index fb821c9..bb8745d 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -43,7 +43,7 @@ void wl1271_elp_work(struct work_struct *work)
 		goto out;
 
 	wl1271_debug(DEBUG_PSM, "chip to elp");
-	wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
+	wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
 	wl->elp = true;
 
 out:
@@ -86,7 +86,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
 		wl->elp_compl = &compl;
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
-	wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
+	wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
 
 	if (!pending) {
 		ret = wait_for_completion_timeout(
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index 1d98653..7979b69 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -132,7 +132,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
 	}
 
 	buf = skb_put(skb, length);
-	wl1271_spi_reg_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
+	wl1271_spi_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
 
 	/* the data read starts with the descriptor */
 	desc = (struct wl1271_rx_descriptor *) buf;
@@ -176,9 +176,9 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
 			wl->rx_mem_pool_addr.addr + 4;
 
 		/* Choose the block we want to read */
-		wl1271_spi_reg_write(wl, WL1271_SLV_REG_DATA,
-				     &wl->rx_mem_pool_addr,
-				     sizeof(wl->rx_mem_pool_addr), false);
+		wl1271_spi_write(wl, WL1271_SLV_REG_DATA,
+				 &wl->rx_mem_pool_addr,
+				 sizeof(wl->rx_mem_pool_addr), false);
 
 		wl1271_rx_handle_data(wl, buf_size);
 
@@ -186,5 +186,5 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
 		drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
 	}
 
-	wl1271_reg_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
+	wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
 }
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index 7a7890b..4800fdf 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -183,13 +183,13 @@ int wl1271_set_partition(struct wl1271 *wl,
 		     p->mem3.start, p->mem3.size);
 
 	/* write partition info to the chipset */
-	wl1271_write32(wl, HW_PART0_START_ADDR, p->mem.start);
-	wl1271_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
-	wl1271_write32(wl, HW_PART1_START_ADDR, p->reg.start);
-	wl1271_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
-	wl1271_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
-	wl1271_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
-	wl1271_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
+	wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
+	wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
+	wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
+	wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
+	wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
+	wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
+	wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
 
 	return 0;
 }
@@ -257,8 +257,8 @@ void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len)
 	wl1271_error("SPI read busy-word timeout!\n");
 }
 
-void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf,
-		     size_t len, bool fixed)
+void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
+			 size_t len, bool fixed)
 {
 	struct spi_transfer t[3];
 	struct spi_message m;
@@ -302,8 +302,8 @@ void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf,
 	wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
 }
 
-void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf,
-		      size_t len, bool fixed)
+void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
+			  size_t len, bool fixed)
 {
 	struct spi_transfer t[2];
 	struct spi_message m;
@@ -336,77 +336,47 @@ void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf,
 	wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
 }
 
-void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf,
-			 size_t len)
+void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len,
+		     bool fixed)
 {
 	int physical;
 
 	physical = wl1271_translate_addr(wl, addr);
 
-	wl1271_spi_read(wl, physical, buf, len, false);
+	wl1271_spi_raw_read(wl, physical, buf, len, fixed);
 }
 
-void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf,
-			  size_t len)
+void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len,
+		      bool fixed)
 {
 	int physical;
 
 	physical = wl1271_translate_addr(wl, addr);
 
-	wl1271_spi_write(wl, physical, buf, len, false);
+	wl1271_spi_raw_write(wl, physical, buf, len, fixed);
 }
 
-void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len,
-			 bool fixed)
+u32 wl1271_spi_read32(struct wl1271 *wl, int addr)
 {
-	int physical;
-
-	physical = wl1271_translate_addr(wl, addr);
-
-	wl1271_spi_read(wl, physical, buf, len, fixed);
-}
-
-void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len,
-			  bool fixed)
-{
-	int physical;
-
-	physical = wl1271_translate_addr(wl, addr);
-
-	wl1271_spi_write(wl, physical, buf, len, fixed);
+	return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
 }
 
-u32 wl1271_mem_read32(struct wl1271 *wl, int addr)
+void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val)
 {
-	return wl1271_read32(wl, wl1271_translate_addr(wl, addr));
-}
-
-void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val)
-{
-	wl1271_write32(wl, wl1271_translate_addr(wl, addr), val);
-}
-
-u32 wl1271_reg_read32(struct wl1271 *wl, int addr)
-{
-	return wl1271_read32(wl, wl1271_translate_addr(wl, addr));
-}
-
-void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val)
-{
-	wl1271_write32(wl, wl1271_translate_addr(wl, addr), val);
+	wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
 }
 
 void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
 {
 	/* write address >> 1 + 0x30000 to OCP_POR_CTR */
 	addr = (addr >> 1) + 0x30000;
-	wl1271_reg_write32(wl, OCP_POR_CTR, addr);
+	wl1271_spi_write32(wl, OCP_POR_CTR, addr);
 
 	/* write value to OCP_POR_WDATA */
-	wl1271_reg_write32(wl, OCP_DATA_WRITE, val);
+	wl1271_spi_write32(wl, OCP_DATA_WRITE, val);
 
 	/* write 1 to OCP_CMD */
-	wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_WRITE);
+	wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE);
 }
 
 u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
@@ -416,14 +386,14 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
 
 	/* write address >> 1 + 0x30000 to OCP_POR_CTR */
 	addr = (addr >> 1) + 0x30000;
-	wl1271_reg_write32(wl, OCP_POR_CTR, addr);
+	wl1271_spi_write32(wl, OCP_POR_CTR, addr);
 
 	/* write 2 to OCP_CMD */
-	wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_READ);
+	wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ);
 
 	/* poll for data ready */
 	do {
-		val = wl1271_reg_read32(wl, OCP_DATA_READ);
+		val = wl1271_spi_read32(wl, OCP_DATA_READ);
 		timeout--;
 	} while (!(val & OCP_READY_MASK) && timeout);
 
@@ -440,4 +410,3 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
 		return 0xffff;
 	}
 }
-
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h
index 4f1608e..cb7df1c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.h
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.h
@@ -85,24 +85,18 @@
 #define OCP_STATUS_RESP_ERROR 0x30000
 
 /* Raw target IO, address is not translated */
-void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf,
+void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
 		      size_t len, bool fixed);
-void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf,
+void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
 		     size_t len, bool fixed);
 
-/* Memory target IO, address is tranlated to partition 0 */
-void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf, size_t len);
-void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf, size_t len);
-u32 wl1271_mem_read32(struct wl1271 *wl, int addr);
-void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val);
-
-/* Registers IO */
-void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len,
-			 bool fixed);
-void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len,
-			  bool fixed);
-u32 wl1271_reg_read32(struct wl1271 *wl, int addr);
-void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val);
+/* Translated target IO */
+void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len,
+		     bool fixed);
+void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len,
+		      bool fixed);
+u32 wl1271_spi_read32(struct wl1271 *wl, int addr);
+void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val);
 
 /* Top Register IO */
 void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
@@ -114,19 +108,19 @@ void wl1271_spi_init(struct wl1271 *wl);
 int wl1271_set_partition(struct wl1271 *wl,
 			 struct wl1271_partition_set *p);
 
-static inline u32 wl1271_read32(struct wl1271 *wl, int addr)
+static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
 {
-	wl1271_spi_read(wl, addr, &wl->buffer_32,
-			sizeof(wl->buffer_32), false);
+	wl1271_spi_raw_read(wl, addr, &wl->buffer_32,
+			    sizeof(wl->buffer_32), false);
 
 	return wl->buffer_32;
 }
 
-static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
+static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
 {
 	wl->buffer_32 = val;
-	wl1271_spi_write(wl, addr, &wl->buffer_32,
-			 sizeof(wl->buffer_32), false);
+	wl1271_spi_raw_write(wl, addr, &wl->buffer_32,
+			     sizeof(wl->buffer_32), false);
 }
 
 #endif /* __WL1271_SPI_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index 56a7f36..4560458 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -154,11 +154,11 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb,
 	len = WL1271_TX_ALIGN(skb->len);
 
 	/* perform a fixed address block write with the packet */
-	wl1271_spi_reg_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
+	wl1271_spi_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
 
 	/* write packet new counter into the write access register */
 	wl->tx_packets_count++;
-	wl1271_reg_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
+	wl1271_spi_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
 
 	desc = (struct wl1271_tx_hw_descr *) skb->data;
 	wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)",
@@ -331,8 +331,8 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count)
 	wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
 
 	/* read the tx results from the chipset */
-	wl1271_spi_mem_read(wl, memmap->tx_result,
-			    wl->tx_res_if, sizeof(*wl->tx_res_if));
+	wl1271_spi_read(wl, memmap->tx_result,
+			wl->tx_res_if, sizeof(*wl->tx_res_if), false);
 
 	/* verify that the result buffer is not getting overrun */
 	if (count > TX_HW_RESULT_QUEUE_LEN) {
@@ -353,7 +353,7 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count)
 	}
 
 	/* write host counter to chipset (to ack) */
-	wl1271_mem_write32(wl, memmap->tx_result +
+	wl1271_spi_write32(wl, memmap->tx_result +
 			   offsetof(struct wl1271_tx_hw_res_if,
 				    tx_result_host_counter),
 			   wl->tx_res_if->tx_result_fw_counter);
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 16/16] wl1271: remove unnecessary joins and join only when the bssid changes
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

We were using the join command to change some settings when the stack asked
us to do it.  In many cases they were not needed (and could cause potential
problems), so they were removed.  In other cases there are ACX commands that
can be used instead of using join to reconfigure.

Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h      |    4 --
 drivers/net/wireless/wl12xx/wl1271_cmd.c  |    4 +-
 drivers/net/wireless/wl12xx/wl1271_main.c |   61 ++++++++++------------------
 3 files changed, 24 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index b2bc7b5..aa9bb2e 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -378,10 +378,6 @@ struct wl1271 {
 	/* Our association ID */
 	u16 aid;
 
-	/* Beacon parameters */
-	u16 beacon_int;
-	u8 dtim_period;
-
 	/* currently configured rate set */
 	u32 basic_rate_set;
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index f727744..eaa1de9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -232,8 +232,8 @@ int wl1271_cmd_join(struct wl1271 *wl)
 	join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
 		RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
 
-	join->beacon_interval = wl->beacon_int;
-	join->dtim_interval = wl->dtim_period;
+	join->beacon_interval = WL1271_DEFAULT_BEACON_INT;
+	join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD;
 	join->bss_type = wl->bss_type;
 	join->channel = wl->channel;
 	join->ssid_len = wl->ssid_len;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index fc0d03f..821a775 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -710,7 +710,15 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw,
 	if (ret < 0)
 		goto out;
 
-	memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+	if (memcmp(wl->bssid, conf->bssid, ETH_ALEN)) {
+		wl1271_debug(DEBUG_MAC80211, "bssid changed");
+
+		memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+
+		ret = wl1271_cmd_join(wl);
+		if (ret < 0)
+			goto out_sleep;
+	}
 
 	ret = wl1271_cmd_build_null_data(wl);
 	if (ret < 0)
@@ -720,12 +728,6 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw,
 	if (wl->ssid_len)
 		memcpy(wl->ssid, conf->ssid, wl->ssid_len);
 
-	if (wl->bss_type != BSS_TYPE_IBSS) {
-		ret = wl1271_cmd_join(wl);
-		if (ret < 0)
-			goto out_sleep;
-	}
-
 	if (conf->changed & IEEE80211_IFCC_BEACON) {
 		beacon = ieee80211_beacon_get(hw, vif);
 		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
@@ -743,11 +745,6 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw,
 
 		if (ret < 0)
 			goto out_sleep;
-
-		ret = wl1271_cmd_join(wl);
-
-		if (ret < 0)
-			goto out_sleep;
 	}
 
 out_sleep:
@@ -782,14 +779,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
 		goto out;
 
 	if (channel != wl->channel) {
-		u8 old_channel = wl->channel;
+		/*
+		 * We assume that the stack will configure the right channel
+		 * before associating, so we don't need to send a join
+		 * command here.  We will join the right channel when the
+		 * BSSID changes
+		 */
 		wl->channel = channel;
-
-		ret = wl1271_cmd_join(wl);
-		if (ret < 0) {
-			wl->channel = old_channel;
-			goto out_sleep;
-		}
 	}
 
 	ret = wl1271_cmd_build_null_data(wl);
@@ -1102,17 +1098,14 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 
 	if (changed & BSS_CHANGED_ASSOC) {
 		if (bss_conf->assoc) {
-			wl->beacon_int = bss_conf->beacon_int;
-			wl->dtim_period = bss_conf->dtim_period;
 			wl->aid = bss_conf->aid;
 
-			ret = wl1271_cmd_join(wl);
-			if (ret < 0) {
-				wl1271_warning("Association configuration "
-					       "failed %d", ret);
-				goto out_sleep;
-			}
-
+			/*
+			 * with wl1271, we don't need to update the
+			 * beacon_int and dtim_period, because the firmware
+			 * updates it by itself when the first beacon is
+			 * received after a join.
+			 */
 			ret = wl1271_cmd_build_ps_poll(wl, wl->aid);
 			if (ret < 0)
 				goto out_sleep;
@@ -1130,8 +1123,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 			}
 		} else {
 			/* use defaults when not associated */
-			wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
-			wl->dtim_period = WL1271_DEFAULT_DTIM_PERIOD;
 			wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
 			wl->aid = 0;
 		}
@@ -1170,18 +1161,12 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 	if (changed & BSS_CHANGED_BASIC_RATES) {
 		wl->basic_rate_set = wl1271_enabled_rates_get(
 			wl, bss_conf->basic_rates);
-		ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set);
 
+		ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set);
 		if (ret < 0) {
 			wl1271_warning("Set rate policies failed %d", ret);
 			goto out_sleep;
 		}
-		ret = wl1271_cmd_join(wl);
-		if (ret < 0) {
-			wl1271_warning("Join with new basic rate "
-				       "set failed %d", ret);
-			goto out_sleep;
-		}
 	}
 
 out_sleep:
@@ -1380,8 +1365,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 	wl->psm_requested = false;
 	wl->tx_queue_stopped = false;
 	wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
-	wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
-	wl->dtim_period = WL1271_DEFAULT_DTIM_PERIOD;
 	wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
 	wl->band = IEEE80211_BAND_2GHZ;
 	wl->vif = NULL;
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 03/16] wl1271: add workaround to avoid distortion due to excessive tx power
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

We still don't have proper calibration for our devices, so we are using way
too much power for TX, which causes a lot of distortion.  This hack hardcodes
the txpower to 7dBm.

Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_acx.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index b9dfa09..d5dac57 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -137,7 +137,12 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
 		goto out;
 	}
 
-	acx->current_tx_power = power * 10;
+	/*
+	 * FIXME: This is a workaround needed while we don't the correct
+	 * calibration, to avoid distortions
+	 */
+	/* acx->current_tx_power = power * 10; */
+	acx->current_tx_power = 70;
 
 	ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
 	if (ret < 0) {
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 01/16] wl1271: implement cmd_disconnect
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

This patch implements the CMD_DISCONNECT command, which should be sent to the
firmware when we are disassociated.

Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_cmd.c |   32 +++++++++++++++++++++++++++++-
 drivers/net/wireless/wl12xx/wl1271_cmd.h |   27 +++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index ac93efd..d09ad12 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -191,7 +191,6 @@ int wl1271_cmd_join(struct wl1271 *wl)
 			do_cal = false;
 	}
 
-
 	join = kzalloc(sizeof(*join), GFP_KERNEL);
 	if (!join) {
 		ret = -ENOMEM;
@@ -825,3 +824,34 @@ out:
 
 	return ret;
 }
+
+int wl1271_cmd_disconnect(struct wl1271 *wl)
+{
+	struct wl1271_cmd_disconnect *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd disconnect");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->rx_config_options = wl->rx_config;
+	cmd->rx_filter_options = wl->rx_filter;
+	/* disconnect reason is not used in immediate disconnections */
+	cmd->type = DISCONNECT_IMMEDIATE;
+
+	ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd));
+	if (ret < 0) {
+		wl1271_error("failed to send disconnect command");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 63bc441..0219664 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -50,6 +50,7 @@ int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
 int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 		       u8 key_size, const u8 *key, const u8 *addr,
 		       u32 tx_seq_32, u16 tx_seq_16);
+int wl1271_cmd_disconnect(struct wl1271 *wl);
 
 enum wl1271_commands {
 	CMD_INTERROGATE     = 1,    /*use this to read information elements*/
@@ -461,4 +462,30 @@ struct wl1271_cmd_cal_p2g {
 	u8  padding2;
 } __attribute__ ((packed));
 
+
+/*
+ * There are three types of disconnections:
+ *
+ * DISCONNECT_IMMEDIATE: the fw doesn't send any frames
+ * DISCONNECT_DEAUTH:    the fw generates a DEAUTH request with the reason
+ *                       we have passed
+ * DISCONNECT_DISASSOC:  the fw generates a DESASSOC request with the reason
+ *                       we have passed
+ */
+enum wl1271_disconnect_type {
+	DISCONNECT_IMMEDIATE,
+	DISCONNECT_DEAUTH,
+	DISCONNECT_DISASSOC
+};
+
+struct wl1271_cmd_disconnect {
+	u32 rx_config_options;
+	u32 rx_filter_options;
+
+	u16 reason;
+	u8  type;
+
+	u8  padding;
+} __attribute__ ((packed));
+
 #endif /* __WL1271_CMD_H__ */
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 07/16] wl1271: Add top-register access functions
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Add top register access function.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_boot.c |   27 ++---------------
 drivers/net/wireless/wl12xx/wl1271_boot.h |   15 +---------
 drivers/net/wireless/wl12xx/wl1271_spi.c  |   46 +++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/wl1271_spi.h  |   16 ++++++++++
 4 files changed, 66 insertions(+), 38 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index 2eb7836..1a3084c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -419,34 +419,13 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
 
 static int wl1271_boot_write_irq_polarity(struct wl1271 *wl)
 {
-	u32 polarity, status, i;
+	u32 polarity;
 
-	wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY);
-	wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_READ);
-
-	/* Wait until the command is complete (ie. bit 18 is set) */
-	for (i = 0; i < OCP_CMD_LOOP; i++) {
-		polarity = wl1271_reg_read32(wl, OCP_DATA_READ);
-		if (polarity & OCP_READY_MASK)
-			break;
-	}
-	if (i == OCP_CMD_LOOP) {
-		wl1271_error("OCP command timeout!");
-		return -EIO;
-	}
-
-	status = polarity & OCP_STATUS_MASK;
-	if (status != OCP_STATUS_OK) {
-		wl1271_error("OCP command failed (%d)", status);
-		return -EIO;
-	}
+	polarity = wl1271_top_reg_read(wl, OCP_REG_POLARITY);
 
 	/* We use HIGH polarity, so unset the LOW bit */
 	polarity &= ~POLARITY_LOW;
-
-	wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY);
-	wl1271_reg_write32(wl, OCP_DATA_WRITE, polarity);
-	wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_WRITE);
+	wl1271_top_reg_write(wl, OCP_REG_POLARITY, polarity);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h
index b0d8fb4..4501653 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.h
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.h
@@ -50,20 +50,7 @@ struct wl1271_static_data {
 #define WU_COUNTER_PAUSE_VAL 0x3FF
 #define WELP_ARM_COMMAND_VAL 0x4
 
-#define OCP_CMD_LOOP  32
-
-#define OCP_CMD_WRITE 0x1
-#define OCP_CMD_READ  0x2
-
-#define OCP_READY_MASK  BIT(18)
-#define OCP_STATUS_MASK (BIT(16) | BIT(17))
-
-#define OCP_STATUS_NO_RESP    0x00000
-#define OCP_STATUS_OK         0x10000
-#define OCP_STATUS_REQ_FAILED 0x20000
-#define OCP_STATUS_RESP_ERROR 0x30000
-
-#define OCP_REG_POLARITY 0x30032
+#define OCP_REG_POLARITY 0x0064
 
 #define CMD_MBOX_ADDRESS 0x407B4
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index 367f2d3..7a7890b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -395,3 +395,49 @@ void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val)
 {
 	wl1271_write32(wl, wl1271_translate_addr(wl, addr), val);
 }
+
+void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
+{
+	/* write address >> 1 + 0x30000 to OCP_POR_CTR */
+	addr = (addr >> 1) + 0x30000;
+	wl1271_reg_write32(wl, OCP_POR_CTR, addr);
+
+	/* write value to OCP_POR_WDATA */
+	wl1271_reg_write32(wl, OCP_DATA_WRITE, val);
+
+	/* write 1 to OCP_CMD */
+	wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_WRITE);
+}
+
+u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
+{
+	u32 val;
+	int timeout = OCP_CMD_LOOP;
+
+	/* write address >> 1 + 0x30000 to OCP_POR_CTR */
+	addr = (addr >> 1) + 0x30000;
+	wl1271_reg_write32(wl, OCP_POR_CTR, addr);
+
+	/* write 2 to OCP_CMD */
+	wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_READ);
+
+	/* poll for data ready */
+	do {
+		val = wl1271_reg_read32(wl, OCP_DATA_READ);
+		timeout--;
+	} while (!(val & OCP_READY_MASK) && timeout);
+
+	if (!timeout) {
+		wl1271_warning("Top register access timed out.");
+		return 0xffff;
+	}
+
+	/* check data status and return if OK */
+	if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
+		return val & 0xffff;
+	else {
+		wl1271_warning("Top register access returned error.");
+		return 0xffff;
+	}
+}
+
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h
index c58e027..4f1608e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.h
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.h
@@ -71,6 +71,18 @@
 		((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32))
 #define HW_ACCESS_WSPI_INIT_CMD_MASK  0
 
+#define OCP_CMD_LOOP  32
+
+#define OCP_CMD_WRITE 0x1
+#define OCP_CMD_READ  0x2
+
+#define OCP_READY_MASK  BIT(18)
+#define OCP_STATUS_MASK (BIT(16) | BIT(17))
+
+#define OCP_STATUS_NO_RESP    0x00000
+#define OCP_STATUS_OK         0x10000
+#define OCP_STATUS_REQ_FAILED 0x20000
+#define OCP_STATUS_RESP_ERROR 0x30000
 
 /* Raw target IO, address is not translated */
 void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf,
@@ -92,6 +104,10 @@ void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len,
 u32 wl1271_reg_read32(struct wl1271 *wl, int addr);
 void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val);
 
+/* Top Register IO */
+void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
+u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
+
 /* INIT and RESET words */
 void wl1271_spi_reset(struct wl1271 *wl);
 void wl1271_spi_init(struct wl1271 *wl);
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 04/16] wl1271: enable HW_AVAILABLE interrupt to fix ELP
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

We need to listen to HW_AVAILABLE interrupts when using ELP with firmware
revision 6.1.0.0.241.  Add WL1271_ACX_INTR_HW_AVAILABLE to the interrupts that
are enabled by default.

Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_acx.h |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 0c2a107..07256d2 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -61,8 +61,9 @@
 					    WL1271_ACX_INTR_HW_AVAILABLE  | \
 					    WL1271_ACX_INTR_DATA)
 
-#define WL1271_INTR_MASK                   (WL1271_ACX_INTR_EVENT_A |	\
-					    WL1271_ACX_INTR_EVENT_B | \
+#define WL1271_INTR_MASK                   (WL1271_ACX_INTR_EVENT_A      | \
+					    WL1271_ACX_INTR_EVENT_B      | \
+					    WL1271_ACX_INTR_HW_AVAILABLE | \
 					    WL1271_ACX_INTR_DATA)
 
 /* Target's information element */
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 00/16] Second batch of patches for wl1271
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Hi,

Here is the second batch of patches to be included in wireless-testing.  I got
a few comments from Johannes about the first batch and those issues will be
fixed after I send the 3rd and final batch.

Cheers,
Luca.

Juuso Oikarinen (10):
  wl1271: Update memory mapping for firmware revision 6.1.0.0.241
  wl1271: Remove RX workaround
  wl1271: Add top-register access functions
  wl1271: RefClk configuration
  wl1271: Update interrupt handling by removing an extra SPI read
  wl1271: Enable ELP
  wl1271: Enable smart reflex
  wl1271: Update TX path block calucation algo
  wl1271: Remove outdated SPI functions
  wl1271: Update boot time configuration for the new firmware

Luciano Coelho (6):
  wl1271: implement cmd_disconnect
  wl1271: workaround to send a disconnect before rejoining
  wl1271: add workaround to avoid distortion due to excessive tx power
  wl1271: enable HW_AVAILABLE interrupt to fix ELP
  wl1271: use acx_rx_config instead of join when updating filters
  wl1271: remove unnecessary joins and join only when the bssid changes

 drivers/net/wireless/wl12xx/wl1271.h       |   14 +-
 drivers/net/wireless/wl12xx/wl1271_acx.c   |   79 +++++++++-
 drivers/net/wireless/wl12xx/wl1271_acx.h   |   28 +++-
 drivers/net/wireless/wl12xx/wl1271_boot.c  |  177 ++++++++++----------
 drivers/net/wireless/wl12xx/wl1271_boot.h  |   22 +--
 drivers/net/wireless/wl12xx/wl1271_cmd.c   |   68 +++++++--
 drivers/net/wireless/wl12xx/wl1271_cmd.h   |   27 +++
 drivers/net/wireless/wl12xx/wl1271_event.c |    8 +-
 drivers/net/wireless/wl12xx/wl1271_init.c  |    7 +-
 drivers/net/wireless/wl12xx/wl1271_main.c  |  160 ++++++++----------
 drivers/net/wireless/wl12xx/wl1271_ps.c    |   11 +-
 drivers/net/wireless/wl12xx/wl1271_reg.h   |    3 +-
 drivers/net/wireless/wl12xx/wl1271_rx.c    |   14 +-
 drivers/net/wireless/wl12xx/wl1271_spi.c   |  251 ++++++++++++----------------
 drivers/net/wireless/wl12xx/wl1271_spi.h   |   65 +++++---
 drivers/net/wireless/wl12xx/wl1271_tx.c    |   14 +-
 16 files changed, 531 insertions(+), 417 deletions(-)


^ permalink raw reply

* [PATCH 15/16] wl1271: use acx_rx_config instead of join when updating filters
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

We shouldn't use a join command to change the filter settings while
associated.  The right way to do it is to use ACX_RX_CFG.

Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_main.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 5ef0bd5..fc0d03f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -422,7 +422,7 @@ static void wl1271_filter_work(struct work_struct *work)
 		goto out;
 
 	/* apply configured filters */
-	ret = wl1271_cmd_join(wl);
+	ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
 	if (ret < 0)
 		goto out_sleep;
 
@@ -869,6 +869,8 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
 			wl1271_warning("Unknown mc address length.");
 	}
 
+	/* FIXME: We still need to set our filters properly */
+
 	spin_lock_irqsave(&wl->wl_lock, flags);
 	kfree(wl->filter_params);
 	wl->filter_params = fp;
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 12/16] wl1271: Update TX path block calucation algo
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Update the TX path block calculation algorithm based on TI reference.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_tx.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index 5d3aa4b..56a7f36 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -57,8 +57,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
 	/* approximate the number of blocks required for this packet
 	   in the firmware */
 	/* FIXME: try to figure out what is done here and make it cleaner */
-	total_blocks = (total_len) >> TX_HW_BLOCK_SHIFT_DIV;
-	excluded = (total_blocks << 2) + (skb->len & 0xff) + 34;
+	total_blocks = (total_len + 20) >> TX_HW_BLOCK_SHIFT_DIV;
+	excluded = (total_blocks << 2) + ((total_len + 20) & 0xff) + 34;
 	total_blocks += (excluded > 252) ? 2 : 1;
 	total_blocks += TX_HW_BLOCK_SPARE;
 
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 06/16] wl1271: Remove RX workaround
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Remove RX workaround which is not needed with newer firmware revisions. This
will reduce one SPI register transaction per RX packet.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_reg.h |    1 -
 drivers/net/wireless/wl12xx/wl1271_rx.c  |    4 ----
 2 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_reg.h b/drivers/net/wireless/wl12xx/wl1271_reg.h
index f8ed4a4..bd12615 100644
--- a/drivers/net/wireless/wl12xx/wl1271_reg.h
+++ b/drivers/net/wireless/wl12xx/wl1271_reg.h
@@ -213,7 +213,6 @@
 ==============================================*/
 #define ACX_REG_INTERRUPT_ACK          (REGISTERS_BASE + 0x04F0)
 
-#define RX_DRIVER_DUMMY_WRITE_ADDRESS  (REGISTERS_BASE + 0x0534)
 #define RX_DRIVER_COUNTER_ADDRESS      (REGISTERS_BASE + 0x0538)
 
 /* Device Configuration registers*/
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index 5d8d401..1d98653 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -187,8 +187,4 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
 	}
 
 	wl1271_reg_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
-
-	/* This is a workaround for some problems in the chip */
-	wl1271_reg_write32(wl, RX_DRIVER_DUMMY_WRITE_ADDRESS, 0x1);
-
 }
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 08/16] wl1271: RefClk configuration
From: Luciano Coelho @ 2009-10-12 12:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255349337-9776-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Updated RefClk configuration based on reference sources. Apparently this
change will improve RF performance.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_boot.c |   20 ++++++++++++++++++--
 drivers/net/wireless/wl12xx/wl1271_boot.h |    9 ++++++++-
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index 1a3084c..b586577 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -435,13 +435,29 @@ int wl1271_boot(struct wl1271 *wl)
 	int ret = 0;
 	u32 tmp, clk, pause;
 
-	if (REF_CLOCK == 0 || REF_CLOCK == 2)
-		/* ref clk: 19.2/38.4 */
+	if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4)
+		/* ref clk: 19.2/38.4/38.4-XTAL */
 		clk = 0x3;
 	else if (REF_CLOCK == 1 || REF_CLOCK == 3)
 		/* ref clk: 26/52 */
 		clk = 0x5;
 
+	if (REF_CLOCK != 0) {
+		u16 val;
+		/* Set clock type */
+		val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE);
+		val &= FREF_CLK_TYPE_BITS;
+		val |= CLK_REQ_PRCM;
+		wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
+	} else {
+		u16 val;
+		/* Set clock polarity */
+		val = wl1271_top_reg_read(wl, OCP_REG_CLK_POLARITY);
+		val &= FREF_CLK_POLARITY_BITS;
+		val |= CLK_REQ_OUTN_SEL;
+		wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
+	}
+
 	wl1271_reg_write32(wl, PLL_PARAMETERS, clk);
 
 	pause = wl1271_reg_read32(wl, PLL_PARAMETERS);
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h
index 4501653..412443e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.h
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.h
@@ -50,10 +50,17 @@ struct wl1271_static_data {
 #define WU_COUNTER_PAUSE_VAL 0x3FF
 #define WELP_ARM_COMMAND_VAL 0x4
 
-#define OCP_REG_POLARITY 0x0064
+#define OCP_REG_POLARITY     0x0064
+#define OCP_REG_CLK_TYPE     0x0448
+#define OCP_REG_CLK_POLARITY 0x0cb2
 
 #define CMD_MBOX_ADDRESS 0x407B4
 
 #define POLARITY_LOW BIT(1)
 
+#define FREF_CLK_TYPE_BITS     0xfffffe7f
+#define CLK_REQ_PRCM           0x100
+#define FREF_CLK_POLARITY_BITS 0xfffff8ff
+#define CLK_REQ_OUTN_SEL       0x700
+
 #endif
-- 
1.5.6.5


^ permalink raw reply related


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