* Re: [RFC] e1000 performance patch
From: Robin Humble @ 2006-04-27 20:49 UTC (permalink / raw)
To: Rick Jones; +Cc: netdev
In-Reply-To: <4450EC48.5060304@hp.com>
On Thu, Apr 27, 2006 at 09:07:36AM -0700, Rick Jones wrote:
>There should be three basic measures there - one is the single-instance
>request-response test. The idea is to see minimum latency. That test
>likes to see the interrupt throttle rate made very high, or disabled
>completely.
>
>The aggregate TCP_RR's and the TCP_STREAM tests are there to show what
>effect that has on the ability to do aggregate request/response and a
>bulk transfer.
I guess the whole point of my patch is to try to handle all these cases
efficiently without user intervention by making the driver self-tune
the InterruptThrottleRate depending on what traffic it's seeing.
I think it's doing the right things so far - at least it's a good
compromise - it probably won't ever be ideal in all workloads.
>>can netperf (or some other tool) mix up big and small message sizes
>>like 'the real world' perhaps does?
>>that might help me find a good frequency at which to try to adapt the
>>ITR... (eg. 1, 10, 100 or 1000 times a second)
>
>There is the "vst" (variable size test IIRC) in netperf4:
>
>http://www.netperf.org/svn/netperf4/branches/glib_migration
>
>The docs for netperf4 are presently pathetic. Feel free to email me for
>bootstrapping information. Basically, you'll need pkg-config, libxml2
>and glib-2.0 on the system.
thanks. I'll check it out.
actually, thinking about it more, the worst case for the patched driver
is a quiescent system (where ITR will be maximum) which then sees a
stream of large messages - say 500MB (~=5s at 1Gbit). so until the
watchdog kicks in (every 2s at the moment) and lowers the ITR then the
load on the cpu will be high.
The only solution for this is to run the ITR resetting watchdog as
often as possible. ie. times per second.
And then test it on real codes that do some sort of large message
bursty communication and see if they run faster or slower.
The patched driver will actually deal fairly well with a mixed size
workload as some of the workload will be large messages and that will
(on average) lower the ITR automatically.
cheers,
robin
^ permalink raw reply
* RE: [PATCH 1/3] Rough VJ Channel Implementation - vj_core.patch
From: Caitlin Bestler @ 2006-04-27 21:12 UTC (permalink / raw)
To: David S. Miller, johnpol; +Cc: kelly, rusty, netdev
netdev-owner@vger.kernel.org wrote:
> From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
> Date: Thu, 27 Apr 2006 15:51:26 +0400
>
>> There are some caveats here found while developing zero-copy sniffer
>> [1]. Project's goal was to remap skbs into userspace in real-time.
>> While absolute numbers (posted to netdev@) were really high, it is
>> only applicable to read-only application. As was shown in IOAT
>> thread, data must be warmed in caches, so reading from mapped area
>> will be as fast as memcpy() (read+write), and copy_to_user()
>> actually almost equal to memcpy() (benchmarks were posted to
>> netdev@). And we must add remapping overhead.
>
> Yes, all of these issues are related quite strongly. Thanks
> for making the connection explicit.
>
> But, the mapping overhead is zero for this net channel stuff,
> at least as it is implemented and designed by Kelly. Ring
> buffer is setup ahead of time into the user's address space,
> and a ring of buffers into that area are given to the networking card.
>
> We remember the translations here, so no get_user_pages() on
> each transfer and garbage like that. And yes this all harks
> back to the issues that are discussed in Chapter 5 of
> Networking Algorithmics.
> But the core thing to understand is that by defining a new
> API and setting up the buffer pool ahead of time, we avoid all of the
> get_user_pages() overhead while retaining full kernel/user protection.
>
> Evgeniy, the difference between this and your work is that
> you did not have an intelligent piece of hardware that could
> be told to recognize flows, and only put packets for a
> specific flow into that's flow's buffer pool.
>
>> If we want to dma data from nic into premapped userspace area, this
>> will strike with message sizes/misalignment/slow read and so on, so
>> preallocation has even more problems.
>
> I do not really think this is an issue, we put the full
> packet into user space and teach it where the offset is to
> the actual data.
> We'll do the same things we do today to try and get the data
> area aligned. User can do whatever is logical and relevant
> on his end to deal with strange cases.
>
> In fact we can specify that card has to take some care to get
> data area of packet aligned on say an 8 byte boundary or
> something like that. When we don't have hardware assist, we
> are going to be doing copies.
>
>> This change also requires significant changes in application, at
>> least until recv/send are changed, which is not the best thing to do.
>
> This is exactly the point, we can only do a good job and
> receive zero copy if we can change the interfaces, and that's
> exactly what we're doing here.
>
>> I do think that significant win in VJ's tests belongs not to
>> remapping and cache-oriented changes, but to move all protocol
>> processing into process' context.
>
> I partly disagree. The biggest win is eliminating all of the
> control overhead (all of "softint RX + protocol demux + IP
> route lookup + socket lookup" is turned into single flow
> demux), and the SMP safe data structure which makes it
> realistic enough to always move the bulk of the packet work
> to the socket's home cpu.
>
> I do not think userspace protocol implementation buys enough
> to justify it. We have to do the protection switch in and
> out of kernel space anyways, so why not still do the
> protected protocol processing work in the kernel? It is
> still being done on the user's behalf, contributes to his
> time slice, and avoids all of the terrible issues of
> userspace protocol implementations.
>
> So in my mind, the optimal situation from both a protection
> preservation and also a performance perspective is net
> channels to kernel socket protocol processing, buffers DMA'd
> directly into userspace if hardware assist is present.
>
Having a ring that is already flow qualified is indeed the
most important savings, and worth pursuing even if reaching
consensus on how to safely enable user-mode L4 processing.
The latter *can* be a big advantage when the L4 processing
can be done based on a user-mode call from an already
scheduled process. But the benefit is not there for a process
that needs to be woken up each time it receives a short request.
So the real issue is when there is an intelligent device that
uses hardware packet classification to place the packet in
the correct ring. We don't want to bypass packet filtering,
but it would be terribly wasteful to reclassify the packet.
Intelligent NICs will have packet classification capabilities
to support RDMA and iSCSI. Those capabilities should be available
to benefit SOCK_STREAM and SOCK_DGRAM users as well without it
being a choice of either turning all stack control over to
the NIC or ignorign all NIC capabilities beyound pretending
to be a dumb Ethernet NIC.
For example, counting packets within an approved connection
is a valid goal that the final solution should support. But
would a simple count be sufficient, or do we truly need the
full flexibility currently found in netfilter?
Obviously all of this does not need to be resolved in full
detail, but there should be some sense of the direction so
that data structures can be designed properly. My assumption
is that each input ring has a matching output ring, and that
the output ring cannot be used to send packets that would
not be matched by the reverse rule for the paired input ring.
So the information that supports enforcing that rule needs
to be stored somewhere other than the ring itself.
^ permalink raw reply
* Re: tune back idle cwnd closing?
From: Rick Jones @ 2006-04-27 21:12 UTC (permalink / raw)
To: David S. Miller; +Cc: jheffner, zach.brown, netdev
In-Reply-To: <20060427.131921.79333703.davem@davemloft.net>
having looked now at both 2861 and the 99 paper it references I see lots
of "may's" "mights" and "belief" but nothing "real world."
the CWV vs non CWV was done against a TCP that did indeed reset cwnd
after an RTT of idle, so it wasn't showing reset at idle versus no reset
at idle. just CWV's less draconian (?) reset than the non CWV stack.
the experimental validation in the 99 paper was still a simulation using
dummynet and a number of buffers rather smaller than what modem banks
were offering at the time, and it was for a modem, rather than any other
sort of link. and when they did use a real modem, the buffering in the
modem bank seems to have made the whole thing moot.
there was nothing about effect on intranets, or high-speed long hauls or
any of that.
what that means wrt having a sysctl to enable/disable functionality
still listed as experimental i'm not sure
rick jones
^ permalink raw reply
* Re: 2.6.16.11 BUG at tg3.c:2917
From: Ed L. Cashin @ 2006-04-27 21:04 UTC (permalink / raw)
To: Michael Chan; +Cc: netdev, David S. Miller
In-Reply-To: <1146152724.11406.3.camel@rh4>
On Thu, Apr 27, 2006 at 08:45:24AM -0700, Michael Chan wrote:
> On Thu, 2006-04-27 at 12:52 -0400, Ed L. Cashin wrote:
> > -- [please bite here ] ---------
> > Kernel BUG at drivers/net/tg3.c:2917
> > invalid opcode: 0000 [1] SMP
> > CPU 0
>
> Most likely caused by IO re-ordering. Try the test patch in this
> discussion:
>
> http://marc.theaimsgroup.com/?l=linux-netdev&m=113890239404768&w=2
I'm afraid I might be generating noise here. After my initial post I
found that I cannot trigger a panic without the latest changes to the
aoe driver in place. I haven't been able to trigger a panic using the
aoe driver inside 2.6.16.11.
I think we've identified the problem in the aoe driver, but if I'm
wrong, I will certainly try the TG3_FLAG_MBOX_WRITE_REORDER patch you
mention.
--
Ed L Cashin <ecashin@coraid.com>
^ permalink raw reply
* Re: Netpoll checksum issue
From: Herbert Xu @ 2006-04-27 21:29 UTC (permalink / raw)
To: Aubrey; +Cc: Stephen Hemminger, netdev
In-Reply-To: <6d6a94c50604270557w434945d2v4b934c328abaa92e@mail.gmail.com>
On Thu, Apr 27, 2006 at 08:57:33PM +0800, Aubrey wrote:
>
> Is there any update of this issue?
Assuming that the CHECKSUM_UNNECESSARY line wasn't there, then the
problem is simply that your packet has the wrong UDP checksum.
So I suggest that you print the packet out and compare it with
the original to see where the corruption is.
I don't see how the generic networking stack or netpoll could be
causing your problem.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH 1/32] rt2x00: code style fix
From: Ivo van Doorn @ 2006-04-27 22:02 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 330 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Coding style fix for all rt2x00 drivers.
This change was requested on the netdev list some time ago,
but the patch send then didn't contain all requested changes.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Available on server:
http://mendiosus.nl/rt2x00/rt2x00-01-code-style.diff
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 0/32] rt2x00
From: Ivo van Doorn @ 2006-04-27 22:02 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 4144 bytes --]
Hi,
Here follows quite a large series of patches
for rt2x00 for the wireless-dev tree.
This will bring rt2x00 in wireless-dev up to date with
our CVS tree except that rt61pci and rt73usb are not
yet send along. They will follow within a week.
Apologies for the long delay but due to time limitations
the highest priority was put on the CVS tree and not
on the regularly sending of patches. We will do our best
to send more frequent updates, so next time other developers
of rt2x00 will also be sending the patches.
A short summary of all patches the are following:
[PATCH 1/32] rt2x00: code style fix
[PATCH 2/32] rt2x00: use enumerations
[PATCH 3/32] rt2x00: use pci_*_consistent for DMA mapping
[PATCH 4/32] rt2x00: Add eeprom_multiread function
[PATCH 5/32] rt2x00: Optimize RATE flag handling
[PATCH 6/32] rt2x00: Use arraylike accessors for entries in DMA ring
[PATCH 7/32] rt2x00: make vals static
[PATCH 8/32] rt2x00: Invalid memory allocation check
[PATCH 9/32] rt2x00: Fix antenna configuration
[PATCH 10/32] rt2x00: Move TSF counting activation to correct funtion
[PATCH 11/32] rt2x00: Add more register defines
[PATCH 12/32] rt2x00: Add USB ID's
[PATCH 13/32] rt2x00: Tune link depending on link quality
[PATCH 14/32] rt2x00: Allocate eeprom memory
[PATCH 15/32] rt2x00: Move rx_params to correct location
[PATCH 16/32] rt2x00: Make sure TX rings are empty when scanning
[PATCH 17/32] rt2x00: Put net_device structure in data_ring
[PATCH 18/32] rt2x00: Make sure device has reached requested state while suspend/resume
[PATCH 19/32] rt2x00: Fix panics in interrupt handlers
[PATCH 20/32] rt2x00: byte ordering correctness
[PATCH 21/32] rt2x00: PRIO ring should be treated as regular TX ring
[PATCH 22/32] rt2x00: Allocate ring structures in single array
[PATCH 23/32] rt2x00: Make correct cast in USB interrupt
[PATCH 24/32] rt2x00: Use correct desc_addr and data_addr
[PATCH 25/32] rt2x00: Add flag handlers
[PATCH 26/32] rt2x00: Move all USB and PCI common data into seperate headers
[PATCH 27/32] rt2x00: Put Hardware button in generic header
[PATCH 28/32] rt2x00: Support TXRX led handling
[PATCH 29/32] rt2x00: dscape compatibilitiy
[PATCH 30/32] rt2x00: Correctly initialize TX power in registers
[PATCH 31/32] rt2x00: Correctly initialization and uninitialization of device
[PATCH 32/32] rt2x00: misc fixes
Some of the patches are quite big and placed on an external server,
the link for that patch will be placed in that particular mail.
All other patches are inlined but are also available on the same server:
http://mendiosus.nl/rt2x00/rt2x00-01-code-style.diff
http://mendiosus.nl/rt2x00/rt2x00-02-enum.diff
http://mendiosus.nl/rt2x00/rt2x00-03-dma-mapping.diff
http://mendiosus.nl/rt2x00/rt2x00-04-eeprom-multiread.diff
http://mendiosus.nl/rt2x00/rt2x00-05-txrate.diff
http://mendiosus.nl/rt2x00/rt2x00-06-array.diff
http://mendiosus.nl/rt2x00/rt2x00-07-static.diff
http://mendiosus.nl/rt2x00/rt2x00-08-rate-check.diff
http://mendiosus.nl/rt2x00/rt2x00-09-antenna.diff
http://mendiosus.nl/rt2x00/rt2x00-10-tsf-counting.diff
http://mendiosus.nl/rt2x00/rt2x00-11-register.diff
http://mendiosus.nl/rt2x00/rt2x00-12-usb-ids.diff
http://mendiosus.nl/rt2x00/rt2x00-13-link-tuner.diff
http://mendiosus.nl/rt2x00/rt2x00-14-eeprom.diff
http://mendiosus.nl/rt2x00/rt2x00-15-txrx-params.diff
http://mendiosus.nl/rt2x00/rt2x00-16-scan-params.diff
http://mendiosus.nl/rt2x00/rt2x00-17-ringdev.diff
http://mendiosus.nl/rt2x00/rt2x00-18-suspend.diff
http://mendiosus.nl/rt2x00/rt2x00-19-ring.diff
http://mendiosus.nl/rt2x00/rt2x00-20-endian.diff
http://mendiosus.nl/rt2x00/rt2x00-21-prio.diff
http://mendiosus.nl/rt2x00/rt2x00-22-rings.diff
http://mendiosus.nl/rt2x00/rt2x00-23-usbhandler.diff
http://mendiosus.nl/rt2x00/rt2x00-24-usbfixes.diff
http://mendiosus.nl/rt2x00/rt2x00-25-flags.diff
http://mendiosus.nl/rt2x00/rt2x00-26-dev.diff
http://mendiosus.nl/rt2x00/rt2x00-27-button.diff
http://mendiosus.nl/rt2x00/rt2x00-28-led.diff
http://mendiosus.nl/rt2x00/rt2x00-29-compat.diff
http://mendiosus.nl/rt2x00/rt2x00-30-config.diff
http://mendiosus.nl/rt2x00/rt2x00-31-init.diff
http://mendiosus.nl/rt2x00/rt2x00-32-misc.diff
IvD
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 2/32] rt2x00: use enumerations
From: Ivo van Doorn @ 2006-04-27 22:02 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 3381 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
The led_mode defines are equal in all drivers,
and should be placed in the common rt2x00.h header.
Make the led_mode, tx_status and dev_state defines
into enumerations.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 00:52:56.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:25:33.000000000 +0200
@@ -936,11 +936,6 @@ struct rt2x00_pci{
* Led status
*/
u8 led_mode;
-#define LED_MODE_DEFAULT 0
-#define LED_MODE_TXRX_ACTIVITY 1
-#define LED_MODE_SINGLE 2
-#define LED_MODE_ASUS 3
-#define LED_MODE_ALPHA 4
/*
* EEPROM BBP data.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 00:52:56.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 21:25:33.000000000 +0200
@@ -1192,11 +1192,6 @@ struct rt2x00_pci{
* Led status
*/
u8 led_mode;
-#define LED_MODE_DEFAULT 0
-#define LED_MODE_TXRX_ACTIVITY 1
-#define LED_MODE_SINGLE 2
-#define LED_MODE_ASUS 3
-#define LED_MODE_ALPHA 4
/*
* EEPROM BBP data.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 00:52:56.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:25:33.000000000 +0200
@@ -691,11 +691,6 @@ struct rt2x00_usb{
* Led status
*/
u8 led_mode;
-#define LED_MODE_DEFAULT 0
-#define LED_MODE_TXRX_ACTIVITY 1
-#define LED_MODE_SINGLE 2
-#define LED_MODE_ASUS 3
-#define LED_MODE_ALPHA 4
/*
* EEPROM BBP data.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:23:26.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:25:33.000000000 +0200
@@ -96,11 +96,34 @@ static int rt2x00_debug_level = 0;
/*
* TX result flags.
*/
-#define TX_SUCCESS 0
-#define TX_SUCCESS_RETRY 1
-#define TX_FAIL_RETRY 2
-#define TX_FAIL_INVALID 3
-#define TX_FAIL_OTHER 4
+enum TX_STATUS {
+ TX_SUCCESS = 0,
+ TX_SUCCESS_RETRY = 1,
+ TX_FAIL_RETRY = 2,
+ TX_FAIL_INVALID = 3,
+ TX_FAIL_OTHER = 4,
+};
+
+/*
+ * Led mode values.
+ */
+enum led_mode {
+ LED_MODE_DEFAULT = 0,
+ LED_MODE_TXRX_ACTIVITY = 1,
+ LED_MODE_SIGNAL_STRENGTH = 2,
+ LED_MODE_ASUS = 3,
+ LED_MODE_ALPHA = 4,
+};
+
+/*
+ * Device states
+ */
+enum dev_state {
+ STATE_DEEP_SLEEP = 0,
+ STATE_SLEEP = 1,
+ STATE_STANDBY = 2,
+ STATE_AWAKE = 3,
+};
/*
* Macros for determining which is the lowest or highest bit
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 3/32] rt2x00: use pci_*_consistent for DMA mapping
From: Ivo van Doorn @ 2006-04-27 22:02 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 2842 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Add linux/dma-mapping.h header to allow compilation
on some architectures. Instead of dma_*_coherent
use pci_*consistent functions.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:36:17.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:37:02.000000000 +0200
@@ -29,6 +29,7 @@
#include <linux/version.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -928,8 +929,8 @@ rt2400pci_alloc_ring(
/*
* Allocate DMA memory for descriptor and buffer.
*/
- ring->data_addr = dma_alloc_coherent(&rt2x00pci->pci_dev->dev,
- rt2x00_get_ring_size(ring), &ring->data_dma, GFP_KERNEL);
+ ring->data_addr = pci_alloc_consistent(rt2x00pci->pci_dev,
+ rt2x00_get_ring_size(ring), &ring->data_dma);
if (!ring->data_addr) {
kfree(ring->entry);
return -ENOMEM;
@@ -959,7 +960,7 @@ static void
rt2400pci_free_ring(struct rt2x00_pci *rt2x00pci, struct data_ring *ring)
{
if (ring->data_addr)
- dma_free_coherent(&rt2x00pci->pci_dev->dev,
+ pci_free_consistent(rt2x00pci->pci_dev,
rt2x00_get_ring_size(ring),
ring->data_addr, ring->data_dma);
ring->data_addr = NULL;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:36:17.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:37:02.000000000 +0200
@@ -29,6 +29,7 @@
#include <linux/version.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -964,8 +965,8 @@ rt2500pci_alloc_ring(
/*
* Allocate DMA memory for descriptor and buffer.
*/
- ring->data_addr = dma_alloc_coherent(&rt2x00pci->pci_dev->dev,
- rt2x00_get_ring_size(ring), &ring->data_dma, GFP_KERNEL);
+ ring->data_addr = pci_alloc_consistent(rt2x00pci->pci_dev,
+ rt2x00_get_ring_size(ring), &ring->data_dma);
if (!ring->data_addr) {
kfree(ring->entry);
return -ENOMEM;
@@ -995,7 +996,7 @@ static void
rt2500pci_free_ring(struct rt2x00_pci *rt2x00pci, struct data_ring *ring)
{
if (ring->data_addr)
- dma_free_coherent(&rt2x00pci->pci_dev->dev,
+ pci_free_consistent(rt2x00pci->pci_dev,
rt2x00_get_ring_size(ring),
ring->data_addr, ring->data_dma);
ring->data_addr = NULL;
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 4/32] rt2x00: Add eeprom_multiread function
From: Ivo van Doorn @ 2006-04-27 22:02 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 5022 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Add the eeprom_multiread function and clean up the code
a bit by using it as well. ;)
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:37:02.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:38:23.000000000 +0200
@@ -351,6 +351,17 @@ rt2x00_eeprom_read(
rt2x00_eeprom_pulse_low(rt2x00pci, &flags);
}
+static void
+rt2x00_eeprom_multiread(
+ const struct rt2x00_pci *rt2x00pci,
+ const u8 word, u16 *data, const u16 length)
+{
+ int counter;
+
+ for (counter = 0; counter < (length / sizeof(u16)); counter++)
+ rt2x00_eeprom_read(rt2x00pci, word + counter, data++);
+}
+
/*
* Configuration handlers.
*/
@@ -1824,9 +1835,8 @@ rt2400pci_init_eeprom(struct rt2x00_pci
/*
* 7 - Read BBP data from EEPROM and store in private structure.
*/
- for (counter = 0; counter < EEPROM_BBP_SIZE; counter++)
- rt2x00_eeprom_read(rt2x00pci, EEPROM_BBP_START + counter,
- &rt2x00pci->eeprom[counter]);
+ rt2x00_eeprom_multiread(rt2x00pci, EEPROM_BBP_START,
+ &rt2x00pci->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
return 0;
}
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:37:02.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:38:23.000000000 +0200
@@ -351,6 +351,17 @@ rt2x00_eeprom_read(
rt2x00_eeprom_pulse_low(rt2x00pci, &flags);
}
+static void
+rt2x00_eeprom_multiread(
+ const struct rt2x00_pci *rt2x00pci,
+ const u8 word, u16 *data, const u16 length)
+{
+ int counter;
+
+ for (counter = 0; counter < (length / sizeof(u16)); counter++)
+ rt2x00_eeprom_read(rt2x00pci, word + counter, data++);
+}
+
/*
* Configuration handlers.
*/
@@ -1886,9 +1897,8 @@ rt2500pci_init_eeprom(struct rt2x00_pci
/*
* 7 - Read BBP data from EEPROM and store in private structure.
*/
- for (counter = 0; counter < EEPROM_BBP_SIZE; counter++)
- rt2x00_eeprom_read(rt2x00pci, EEPROM_BBP_START + counter,
- &rt2x00pci->eeprom[counter]);
+ rt2x00_eeprom_multiread(rt2x00pci, EEPROM_BBP_START,
+ &rt2x00pci->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
return 0;
}
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:36:17.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:38:23.000000000 +0200
@@ -228,11 +228,21 @@ rf_write:
static inline void
rt2x00_eeprom_read(
const struct rt2x00_usb *rt2x00usb,
- const u16 offset, u16 *value, const u16 length)
+ const u16 word, u16 *data)
{
rt2x00_vendor_request(
rt2x00usb, USB_EEPROM_READ, USB_VENDOR_REQUEST_IN,
- offset, 0x00, value, length);
+ word, 0x00, data, 2);
+}
+
+static void
+rt2x00_eeprom_multiread(
+ const struct rt2x00_usb *rt2x00usb,
+ const u8 word, u16 *data, const u16 length)
+{
+ rt2x00_vendor_request(
+ rt2x00usb, USB_EEPROM_READ, USB_VENDOR_REQUEST_IN,
+ word, 0x00, data, length);
}
/*
@@ -1552,7 +1562,7 @@ rt2500usb_init_eeprom(struct rt2x00_usb
/*
* 1 - Read EEPROM word for configuration.
*/
- rt2x00_eeprom_read(rt2x00usb, EEPROM_ANTENNA, &eeprom, 2);
+ rt2x00_eeprom_read(rt2x00usb, EEPROM_ANTENNA, &eeprom);
/*
* 2 - Identify RF chipset.
@@ -1579,7 +1589,7 @@ rt2500usb_init_eeprom(struct rt2x00_usb
* 5 - Read BBP data from EEPROM and store in private structure.
*/
memset(&rt2x00usb->eeprom, 0x00, sizeof(rt2x00usb->eeprom));
- rt2x00_eeprom_read(rt2x00usb, EEPROM_BBP_START,
+ rt2x00_eeprom_multiread(rt2x00usb, EEPROM_BBP_START,
&rt2x00usb->eeprom[0], EEPROM_BBP_SIZE);
return 0;
@@ -1595,7 +1605,7 @@ rt2500usb_init_mac(struct rt2x00_usb *rt
/*
* Read MAC address from EEPROM.
*/
- rt2x00_eeprom_read(rt2x00usb, EEPROM_MAC_ADDR, ®[0], 6);
+ rt2x00_eeprom_multiread(rt2x00usb, EEPROM_MAC_ADDR, ®[0], 6);
net_dev->dev_addr[0] = rt2x00_get_field16(reg[0], MAC_CSR2_BYTE0);
net_dev->dev_addr[1] = rt2x00_get_field16(reg[0], MAC_CSR2_BYTE1);
@@ -1733,7 +1743,7 @@ rt2500usb_init_hw_channels(struct rt2x00
*/
for (counter = 0; counter < EEPROM_TXPOWER_SIZE; counter++) {
rt2x00_eeprom_read(rt2x00usb,
- EEPROM_TXPOWER_START + counter, &eeprom, 2);
+ EEPROM_TXPOWER_START + counter, &eeprom);
channels[(counter * 2)].power_level =
rt2x00_get_field16(eeprom, EEPROM_TXPOWER_1);
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 5/32] rt2x00: Optimize RATE flag handling
From: Ivo van Doorn @ 2006-04-27 22:02 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 8531 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Optimize RATE flags by using the FIELD32() macro's,
also make the unit in which the rate is handled the
same as is used in the dscape stack.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:38:23.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:39:24.000000000 +0200
@@ -550,7 +550,7 @@ rt2400pci_config_duration(struct rt2x00_
rt2x00_register_read(rt2x00pci, CSR19, ®);
value = SIFS + (2 * short_slot_time);
rt2x00_set_field32(®, CSR19_DIFS, value);
- value = SIFS + get_duration(IEEE80211_HEADER + ACK_SIZE, 2);
+ value = SIFS + get_duration(IEEE80211_HEADER + ACK_SIZE, 10);
rt2x00_set_field32(®, CSR19_EIFS, value);
rt2x00_register_write(rt2x00pci, CSR19, reg);
@@ -580,11 +580,11 @@ rt2400pci_config_rate(struct rt2x00_pci
value = SIFS + PLCP
+ (2 * (conf->short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME))
+ preamble
- + get_duration(ACK_SIZE, 2);
+ + get_duration(ACK_SIZE, 10);
rt2x00_set_field32(®[0], TXCSR1_ACK_TIMEOUT, value);
value = SIFS + PLCP
+ preamble
- + get_duration(ACK_SIZE, 2);
+ + get_duration(ACK_SIZE, 10);
rt2x00_set_field32(®[0], TXCSR1_ACK_CONSUME_TIME, value);
rt2x00_register_write(rt2x00pci, TXCSR1, reg[0]);
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:38:23.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:39:24.000000000 +0200
@@ -565,7 +565,7 @@ rt2500pci_config_duration(struct rt2x00_
rt2x00_register_read(rt2x00pci, CSR19, ®);
value = SIFS + (2 * short_slot_time);
rt2x00_set_field32(®, CSR19_DIFS, value);
- value = SIFS + get_duration(IEEE80211_HEADER + ACK_SIZE, 2);
+ value = SIFS + get_duration(IEEE80211_HEADER + ACK_SIZE, 10);
rt2x00_set_field32(®, CSR19_EIFS, value);
rt2x00_register_write(rt2x00pci, CSR19, reg);
@@ -595,11 +595,11 @@ rt2500pci_config_rate(struct rt2x00_pci
value = SIFS + PLCP
+ (2 * (conf->short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME))
+ preamble
- + get_duration(ACK_SIZE, 2);
+ + get_duration(ACK_SIZE, 10);
rt2x00_set_field32(®[0], TXCSR1_ACK_TIMEOUT, value);
value = SIFS + PLCP
+ preamble
- + get_duration(ACK_SIZE, 2);
+ + get_duration(ACK_SIZE, 10);
rt2x00_set_field32(®[0], TXCSR1_ACK_CONSUME_TIME, value);
rt2x00_register_write(rt2x00pci, TXCSR1, reg[0]);
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:38:23.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:39:24.000000000 +0200
@@ -467,7 +467,7 @@ rt2500usb_config_rate(struct rt2x00_usb
value = SIFS + PLCP
+ (2 * (conf->short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME))
+ preamble
- + get_duration(ACK_SIZE, 2);
+ + get_duration(ACK_SIZE, 10);
rt2x00_set_field16_nb(®, TXRX_CSR1_ACK_TIMEOUT, value);
rt2x00_register_write(rt2x00usb, TXRX_CSR1, reg);
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:36:19.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:39:24.000000000 +0200
@@ -609,71 +609,69 @@ struct scanning{
* passed to the ieee80211 kernel. We need to make it a consist of
* multiple fields because we want to store more then 1 device specific
* values inside the value.
- * 1 - rate, stored as 0.5Mbit/s.
- * 2 - MASK_RATE, which rates are enabled in this mode, this mask
+ * 1 - rate, stored as 100 kbit/s.
+ * 2 - preamble, short_preamble enabled flag.
+ * 3 - MASK_RATE, which rates are enabled in this mode, this mask
* corresponds with the TX register format for the current device.
- * 3 - plcp, 802.11b rates are device specific,
+ * 4 - plcp, 802.11b rates are device specific,
* 802.11g rates are set according to the ieee802.11a-1999 p.14.
- * 4 - preamble, short_preamble enabled flag.
* The bit to enable preamble is set in a seperate define.
*/
-#define OFFSET_RATE 0
-#define MASK_RATE 0x000000ff
-#define OFFSET_RATEMASK 8
-#define MASK_RATEMASK 0x00000fff
-#define OFFSET_PLCP 20
-#define MASK_PLCP 0x000000ff
-#define OFFSET_PREAMBLE 28
-#define MASK_PREAMBLE 0x000000ff
+#define DEV_RATE FIELD32(0x000007ff)
+#define DEV_PREAMBLE FIELD32(0x00000800)
+#define DEV_RATEMASK FIELD32(0x00fff000)
+#define DEV_PLCP FIELD32(0xff000000)
/*
- * Macro to set or get a field in the device
- * specific value.
+ * Macro's for creating the device specific rate value.
*/
#define DEVICE_RATE_VALUE(__rate, __mask, __plcp) \
- (int)( (__rate) << OFFSET_RATE \
- | (__mask) << OFFSET_RATEMASK \
- | (__plcp) << OFFSET_PLCP )
+ (int) ((((__rate) << DEV_RATE.bit_offset) & DEV_RATE.bit_mask) \
+ | (((__mask) << DEV_RATEMASK.bit_offset) & DEV_RATEMASK.bit_mask) \
+ | (((__plcp) << DEV_PLCP.bit_offset) & DEV_PLCP.bit_mask) )
#define DEVICE_RATE_PREAMBLE(__value) \
- (int)( (__value) | 1 << OFFSET_PREAMBLE )
+ (int)( (__value) | (1 << DEV_PREAMBLE.bit_offset) )
+/*
+ * Macro for reading the device specific rate value.
+ */
#define DEVICE_RATE_FIELD(__value, __mask) \
- (int)( ((__value) >> OFFSET_##__mask) & MASK_##__mask )
+ (int)( ((__value) & DEV_##__mask.bit_mask) >> DEV_##__mask.bit_offset)
-#define DEVICE_RATE_1MB DEVICE_RATE_VALUE(2, 0x001, 0x00)
-#define DEVICE_RATE_2MB DEVICE_RATE_VALUE(4, 0x003, 0x01)
+#define DEVICE_RATE_1MB DEVICE_RATE_VALUE(10, 0x001, 0x00)
+#define DEVICE_RATE_2MB DEVICE_RATE_VALUE(20, 0x003, 0x01)
#define DEVICE_RATE_2MB_PREAMBLE DEVICE_RATE_PREAMBLE(DEVICE_RATE_2MB)
-#define DEVICE_RATE_55MB DEVICE_RATE_VALUE(11, 0x007, 0x02)
+#define DEVICE_RATE_55MB DEVICE_RATE_VALUE(55, 0x007, 0x02)
#define DEVICE_RATE_55MB_PREAMBLE DEVICE_RATE_PREAMBLE(DEVICE_RATE_55MB)
-#define DEVICE_RATE_11MB DEVICE_RATE_VALUE(22, 0x00f, 0x03)
+#define DEVICE_RATE_11MB DEVICE_RATE_VALUE(110, 0x00f, 0x03)
#define DEVICE_RATE_11MB_PREAMBLE DEVICE_RATE_PREAMBLE(DEVICE_RATE_11MB)
-#define DEVICE_RATE_6MB DEVICE_RATE_VALUE(12, 0x01f, 0x0b)
-#define DEVICE_RATE_9MB DEVICE_RATE_VALUE(18, 0x03f, 0x0f)
-#define DEVICE_RATE_12MB DEVICE_RATE_VALUE(24, 0x07f, 0x0a)
-#define DEVICE_RATE_18MB DEVICE_RATE_VALUE(36, 0x0ff, 0x0e)
-#define DEVICE_RATE_24MB DEVICE_RATE_VALUE(48, 0x1ff, 0x09)
-#define DEVICE_RATE_36MB DEVICE_RATE_VALUE(72, 0x3ff, 0x0d)
-#define DEVICE_RATE_48MB DEVICE_RATE_VALUE(96, 0x7ff, 0x08)
-#define DEVICE_RATE_54MB DEVICE_RATE_VALUE(108, 0xfff, 0x0c)
+#define DEVICE_RATE_6MB DEVICE_RATE_VALUE(60, 0x01f, 0x0b)
+#define DEVICE_RATE_9MB DEVICE_RATE_VALUE(90, 0x03f, 0x0f)
+#define DEVICE_RATE_12MB DEVICE_RATE_VALUE(120, 0x07f, 0x0a)
+#define DEVICE_RATE_18MB DEVICE_RATE_VALUE(180, 0x0ff, 0x0e)
+#define DEVICE_RATE_24MB DEVICE_RATE_VALUE(240, 0x1ff, 0x09)
+#define DEVICE_RATE_36MB DEVICE_RATE_VALUE(360, 0x3ff, 0x0d)
+#define DEVICE_RATE_48MB DEVICE_RATE_VALUE(480, 0x7ff, 0x08)
+#define DEVICE_RATE_54MB DEVICE_RATE_VALUE(540, 0xfff, 0x0c)
/*
* Duration calculations
- * The rate variable passed is: 0.5MBs.
+ * The rate variable passed is: 100kbs.
* To convert from bytes to bits we multiply size with 8,
- * then the size is multiplied with 2 to make the
+ * then the size is multiplied with 10 to make the
* real rate -> rate argument correction.
*/
static inline u16
get_duration(const unsigned int size, const u8 rate)
{
- return ((size * 8 * 2) / rate);
+ return ((size * 8 * 10) / rate);
}
static inline u16
get_duration_res(const unsigned int size, const u8 rate)
{
- return ((size * 8 * 2) % rate);
+ return ((size * 8 * 10) % rate);
}
#define ACK_SIZE 14
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 6/32] rt2x00: Use arraylike accessors for entries in DMA ring
From: Ivo van Doorn @ 2006-04-27 22:02 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 6418 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Make the code a bit more readable by using
array like accessors for pointers in a loop.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:39:24.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:40:06.000000000 +0200
@@ -951,15 +951,15 @@ rt2400pci_alloc_ring(
* Initialize all ring entries to contain valid
* addresses.
*/
+ entry = (struct data_entry*)ring->entry;
for (counter = 0; counter < ring->stats.limit; counter++) {
- entry = ring->entry + (counter * ring->entry_size);
- entry->skb = NULL;
- entry->desc_addr = ring->data_addr
+ entry[counter].skb = NULL;
+ entry[counter].desc_addr = ring->data_addr
+ (counter * ring->desc_size);
- entry->data_addr = ring->data_addr
+ entry[counter].data_addr = ring->data_addr
+ (ring->stats.limit * ring->desc_size)
+ (counter * ring->data_size);
- entry->data_dma = ring->data_dma
+ entry[counter].data_dma = ring->data_dma
+ (ring->stats.limit * ring->desc_size)
+ (counter * ring->data_size);
}
@@ -989,14 +989,14 @@ rt2400pci_init_rxdesc(struct rt2x00_pci
memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
+ entry = (struct data_entry*)ring->entry;
for (counter = 0; counter < ring->stats.limit; counter++) {
- entry = ring->entry + (counter * ring->entry_size);
- rxd = entry->desc_addr;
+ rxd = entry[counter].desc_addr;
rt2x00_set_field32(&rxd->word2, RXD_W2_BUFFER_LENGTH,
ring->data_size);
rt2x00_set_field32(&rxd->word1, RXD_W1_BUFFER_ADDRESS,
- entry->data_dma);
+ entry[counter].data_dma);
rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
}
@@ -1012,14 +1012,14 @@ rt2400pci_init_txdesc(struct rt2x00_pci
memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
+ entry = (struct data_entry*)ring->entry;
for (counter = 0; counter < ring->stats.limit; counter++) {
- entry = ring->entry + (counter * ring->entry_size);
- txd = entry->desc_addr;
+ txd = entry[counter].desc_addr;
rt2x00_set_field32(&txd->word2, TXD_W2_BUFFER_LENGTH,
ring->data_size);
rt2x00_set_field32(&txd->word1, TXD_W1_BUFFER_ADDRESS,
- entry->data_dma);
+ entry[counter].data_dma);
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
rt2x00_set_field32(&txd->word0, TXD_W0_OWNER_NIC, 0);
}
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:39:24.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:40:06.000000000 +0200
@@ -987,15 +987,15 @@ rt2500pci_alloc_ring(
* Initialize all ring entries to contain valid
* addresses.
*/
+ entry = (struct data_entry*)ring->entry;
for (counter = 0; counter < ring->stats.limit; counter++) {
- entry = ring->entry + (counter * ring->entry_size);
- entry->skb = NULL;
- entry->desc_addr = ring->data_addr
+ entry[counter].skb = NULL;
+ entry[counter].desc_addr = ring->data_addr
+ (counter * ring->desc_size);
- entry->data_addr = ring->data_addr
+ entry[counter].data_addr = ring->data_addr
+ (ring->stats.limit * ring->desc_size)
+ (counter * ring->data_size);
- entry->data_dma = ring->data_dma
+ entry[counter].data_dma = ring->data_dma
+ (ring->stats.limit * ring->desc_size)
+ (counter * ring->data_size);
}
@@ -1025,12 +1025,12 @@ rt2500pci_init_rxdesc(struct rt2x00_pci
memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
+ entry = (struct data_entry*)ring->entry;
for (counter = 0; counter < ring->stats.limit; counter++) {
- entry = ring->entry + (counter * ring->entry_size);
- rxd = entry->desc_addr;
+ rxd = entry[counter].desc_addr;
rt2x00_set_field32(&rxd->word1, RXD_W1_BUFFER_ADDRESS,
- entry->data_dma);
+ entry[counter].data_dma);
rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
}
@@ -1046,12 +1046,12 @@ rt2500pci_init_txdesc(struct rt2x00_pci
memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
+ entry = (struct data_entry*)ring->entry;
for (counter = 0; counter < ring->stats.limit; counter++) {
- entry = ring->entry + (counter * ring->entry_size);
- txd = entry->desc_addr;
+ txd = entry[counter].desc_addr;
rt2x00_set_field32(&txd->word1, TXD_W1_BUFFER_ADDRESS,
- entry->data_dma);
+ entry[counter].data_dma);
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
rt2x00_set_field32(&txd->word0, TXD_W0_OWNER_NIC, 0);
}
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:39:24.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:40:06.000000000 +0200
@@ -803,22 +803,22 @@ rt2500usb_alloc_ring(
* addresses.
*/
status = 0;
+ entry = (struct data_entry*)ring->entry;
for (counter = 0; counter < ring->stats.limit; counter++) {
- entry = ring->entry + (counter * ring->entry_size);
- entry->ring = ring;
+ entry[counter].ring = ring;
if (!status)
- entry->urb = usb_alloc_urb(0, GFP_KERNEL);
+ entry[counter].urb = usb_alloc_urb(0, GFP_KERNEL);
else
- entry->urb = NULL;
- if (entry->urb == NULL)
+ entry[counter].urb = NULL;
+ if (entry[counter].urb == NULL)
status = -ENOMEM;
- entry->skb = NULL;
- entry->desc_addr = ring->data_addr
+ entry[counter].skb = NULL;
+ entry[counter].desc_addr = ring->data_addr
+ (counter * ring->desc_size);
- entry->data_addr = ring->data_addr
+ entry[counter].data_addr = ring->data_addr
+ (ring->stats.limit * ring->desc_size)
+ (counter * ring->data_size);
- entry->data_dma = ring->data_dma
+ entry[counter].data_dma = ring->data_dma
+ (ring->stats.limit * ring->desc_size)
+ (counter * ring->data_size);
}
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 7/32] rt2x00: make vals static
From: Ivo van Doorn @ 2006-04-27 22:02 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 6479 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
The vals[] arrays in *_init_hw_channels can be made
static to optimize memory and reduce stack size.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:40:06.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:40:43.000000000 +0200
@@ -1868,7 +1868,7 @@ rt2400pci_init_hw_channels(struct rt2x00
{
int counter;
u16 eeprom;
- u32 vals[] = {
+ static u32 vals[] = {
0x000c1fda, 0x000c1fee, 0x000c2002, 0x000c2016,
0x000c202a, 0x000c203e, 0x000c2052, 0x000c2066,
0x000c207a, 0x000c208e, 0x000c20a2, 0x000c20b6,
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:40:06.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:40:43.000000000 +0200
@@ -1929,9 +1929,9 @@ rt2500pci_init_hw_channels(struct rt2x00
struct ieee80211_channel *channels)
{
int counter;
- u16 eeprom;
u32 rf2_base;
- struct {
+ u16 eeprom;
+ static struct {
unsigned int chip;
u32 val[3];
} rf[] = {
@@ -1947,16 +1947,16 @@ rt2500pci_init_hw_channels(struct rt2x00
* Channel initialization.
* First we set the basic variables.
*/
- for (counter = 0; counter < 13; counter++) {
- channels[counter].chan = counter + 1;
+ for (counter = 0; counter < 13; counter++) {
+ channels[counter].chan = counter + 1;
channels[counter].freq = 2407 + ((counter + 1) * 5);
channels[counter].flag = IEEE80211_CHAN_W_IBSS
| IEEE80211_CHAN_W_ACTIVE_SCAN | IEEE80211_CHAN_W_SCAN;
channels[counter].antenna_max = 0xff;
- }
+ }
- channels[13].chan = 14;
- channels[13].freq = 2484;
+ channels[13].chan = 14;
+ channels[13].freq = 2484;
channels[13].flag = IEEE80211_CHAN_W_IBSS
| IEEE80211_CHAN_W_ACTIVE_SCAN | IEEE80211_CHAN_W_SCAN;
channels[13].antenna_max = 0xff;
@@ -1988,7 +1988,7 @@ rt2500pci_init_hw_channels(struct rt2x00
rf2_base = 0x00080000;
if (rt2x00_rf(&rt2x00pci->chip, RF2522)) {
- u32 vals[] = {
+ static u32 vals[] = {
0x000c1fda, 0x000c1fee, 0x000c2002, 0x000c2016,
0x000c202a, 0x000c203e, 0x000c2052, 0x000c2066,
0x000c207a, 0x000c208e, 0x000c20a2, 0x000c20b6,
@@ -2000,7 +2000,7 @@ rt2500pci_init_hw_channels(struct rt2x00
} else if (rt2x00_rf(&rt2x00pci->chip, RF2523)
|| rt2x00_rf(&rt2x00pci->chip, RF2524)
|| rt2x00_rf(&rt2x00pci->chip, RF2525)) {
- u32 vals[] = {
+ static u32 vals[] = {
0x00000c9e, 0x00000ca2, 0x00000ca6, 0x00000caa,
0x00000cae, 0x00000cb2, 0x00000cb6, 0x00000cba,
0x00000cbe, 0x00000d02, 0x00000d06, 0x00000d0a,
@@ -2012,7 +2012,7 @@ rt2500pci_init_hw_channels(struct rt2x00
cpu_to_le32(vals[counter] | rf2_base);
} else if (rt2x00_rf(&rt2x00pci->chip, RF2525E)
|| rt2x00_rf(&rt2x00pci->chip, RF5222)) {
- u32 vals[] = {
+ static u32 vals[] = {
0x00001136, 0x0000113a, 0x0000113e, 0x00001182,
0x00001186, 0x0000118a, 0x0000118e, 0x00001192,
0x00001196, 0x0000119a, 0x0000119e, 0x000011a2,
@@ -2024,7 +2024,7 @@ rt2500pci_init_hw_channels(struct rt2x00
cpu_to_le32(vals[counter] | rf2_base);
}
if (rt2x00_rf(&rt2x00pci->chip, RF5222)) {
- u32 vals[] = {
+ static u32 vals[] = {
0x00018896, 0x0001889a, 0x0001889e, 0x000188a2,
0x000188a6, 0x000188aa, 0x000188ae, 0x000188b2,
0x00008802, 0x00008806, 0x0000880a, 0x0000880e,
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:40:06.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:40:43.000000000 +0200
@@ -1629,9 +1629,9 @@ rt2500usb_init_hw_channels(struct rt2x00
struct ieee80211_channel *channels)
{
int counter;
- u16 eeprom;
u32 rf2_base;
- struct {
+ u16 eeprom;
+ static struct {
unsigned int chip;
u32 val[3];
} rf[] = {
@@ -1647,16 +1647,16 @@ rt2500usb_init_hw_channels(struct rt2x00
* Channel initialization.
* First we set the basic variables.
*/
- for (counter = 0; counter < 13; counter++) {
- channels[counter].chan = counter + 1;
+ for (counter = 0; counter < 13; counter++) {
+ channels[counter].chan = counter + 1;
channels[counter].freq = 2407 + ((counter + 1) * 5);
channels[counter].flag = IEEE80211_CHAN_W_IBSS
| IEEE80211_CHAN_W_ACTIVE_SCAN | IEEE80211_CHAN_W_SCAN;
channels[counter].antenna_max = 0xff;
- }
+ }
- channels[13].chan = 14;
- channels[13].freq = 2484;
+ channels[13].chan = 14;
+ channels[13].freq = 2484;
channels[13].flag = IEEE80211_CHAN_W_IBSS
| IEEE80211_CHAN_W_ACTIVE_SCAN | IEEE80211_CHAN_W_SCAN;
channels[13].antenna_max = 0xff;
@@ -1687,7 +1687,7 @@ rt2500usb_init_hw_channels(struct rt2x00
rf2_base = 0x00080000;
if (rt2x00_rf(&rt2x00usb->chip, RF2522)) {
- u32 vals[] = {
+ static u32 vals[] = {
0x000c1fda, 0x000c1fee, 0x000c2002, 0x000c2016,
0x000c202a, 0x000c203e, 0x000c2052, 0x000c2066,
0x000c207a, 0x000c208e, 0x000c20a2, 0x000c20b6,
@@ -1699,7 +1699,7 @@ rt2500usb_init_hw_channels(struct rt2x00
} else if (rt2x00_rf(&rt2x00usb->chip, RF2523)
|| rt2x00_rf(&rt2x00usb->chip, RF2524)
|| rt2x00_rf(&rt2x00usb->chip, RF2525)) {
- u32 vals[] = {
+ static u32 vals[] = {
0x00000c9e, 0x00000ca2, 0x00000ca6, 0x00000caa,
0x00000cae, 0x00000cb2, 0x00000cb6, 0x00000cba,
0x00000cbe, 0x00000d02, 0x00000d06, 0x00000d0a,
@@ -1720,7 +1720,7 @@ rt2500usb_init_hw_channels(struct rt2x00
for (counter = 0; counter < ARRAY_SIZE(vals); counter++)
channels[counter].val = cpu_to_le32(vals[counter]);
} else if (rt2x00_rf(&rt2x00usb->chip, RF5222)) {
- u32 vals[] = {
+ static u32 vals[] = {
0x00001136, 0x0000113a, 0x0000113e, 0x00001182,
0x00001186, 0x0000118a, 0x0000118e, 0x00001192,
0x00001196, 0x0000119a, 0x0000119e, 0x000011a2,
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 8/32] rt2x00: Invalid memory allocation check
From: Ivo van Doorn @ 2006-04-27 22:02 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 2687 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Fix invalid check when allocating the memory for
the rate structures. Instead of the channel pointer
the rates pointer should be verified.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:40:43.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:41:20.000000000 +0200
@@ -2036,7 +2036,7 @@ rt2400pci_init_hw(struct rt2x00_pci *rt2
hw->modes->num_rates = 4;
hw->modes->rates =
kzalloc(sizeof(struct ieee80211_rate) * 4, GFP_KERNEL);
- if (!hw->modes->channels)
+ if (!hw->modes->rates)
goto exit_free_channels;
/*
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:40:43.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:41:20.000000000 +0200
@@ -2236,7 +2236,7 @@ rt2500pci_init_hw(struct rt2x00_pci *rt2
hw->modes->rates =
kzalloc((sizeof(struct ieee80211_rate) * 12),
GFP_KERNEL);
- if (!hw->modes->channels)
+ if (!hw->modes->rates)
goto exit_free_channels;
} else {
hw->num_modes = 3;
@@ -2255,7 +2255,7 @@ rt2500pci_init_hw(struct rt2x00_pci *rt2
hw->modes->rates =
kzalloc((sizeof(struct ieee80211_rate) * 12),
GFP_KERNEL);
- if (!hw->modes->channels)
+ if (!hw->modes->rates)
goto exit_free_channels;
}
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:40:43.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:41:20.000000000 +0200
@@ -1931,7 +1931,7 @@ rt2500usb_init_hw(struct rt2x00_usb *rt2
hw->modes->rates =
kzalloc((sizeof(struct ieee80211_rate) * 12),
GFP_KERNEL);
- if (!hw->modes->channels)
+ if (!hw->modes->rates)
goto exit_free_channels;
} else {
hw->num_modes = 3;
@@ -1950,7 +1950,7 @@ rt2500usb_init_hw(struct rt2x00_usb *rt2
hw->modes->rates =
kzalloc((sizeof(struct ieee80211_rate) * 12),
GFP_KERNEL);
- if (!hw->modes->channels)
+ if (!hw->modes->rates)
goto exit_free_channels;
}
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 9/32] rt2x00: Fix antenna configuration
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 6449 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
The handling of the antenna configuration was not
completely correct. For all modules the double clearing
of some bits can be reduced, and for rt2500pci and rt2500usb
some registers were not corretly changed.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:41:20.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:41:52.000000000 +0200
@@ -485,6 +485,9 @@ rt2400pci_config_antenna(struct rt2x00_p
rt2x00_bbp_read(rt2x00pci, 4, ®_rx);
rt2x00_bbp_read(rt2x00pci, 1, ®_tx);
+ /*
+ * Clear current config antenna bits.
+ */
reg_rx &= ~0x06;
reg_tx &= ~0x03;
@@ -495,18 +498,18 @@ rt2400pci_config_antenna(struct rt2x00_p
*/
if (antenna == 0) {
/* Diversity. */
- reg_rx = (reg_rx & 0xf9) | 0x02;
- reg_tx = (reg_tx & 0xfc) | 0x01;
+ reg_rx |= 0x02;
+ reg_tx |= 0x01;
} else if (antenna == 1) {
/* RX: Antenna B */
- reg_rx = (reg_rx & 0xf9) | 0x04;
+ reg_rx |= 0x04;
/* TX: Antenna A */
- reg_tx = (reg_tx & 0xfc) | 0x00;
+ reg_tx |= 0x00;
} else if (antenna == 2) {
/* RX: Antenna A */
- reg_rx = (reg_rx & 0xf9) | 0x00;
+ reg_rx |= 0x00;
/* TX: Antenna B */
- reg_tx = (reg_tx & 0xfc) | 0x02;
+ reg_tx |= 0x02;
}
rt2x00_bbp_write(rt2x00pci, 4, reg_rx);
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:41:20.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:41:52.000000000 +0200
@@ -506,12 +506,17 @@ rt2500pci_config_channel(struct rt2x00_p
static void
rt2500pci_config_antenna(struct rt2x00_pci *rt2x00pci, int antenna)
{
+ u32 reg;
u8 reg_rx;
u8 reg_tx;
+ rt2x00_register_read(rt2x00pci, BBPCSR1, ®);
rt2x00_bbp_read(rt2x00pci, 14, ®_rx);
rt2x00_bbp_read(rt2x00pci, 2, ®_tx);
+ /*
+ * Clear current config antenna bits.
+ */
reg_rx &= ~0x06;
reg_tx &= ~0x03;
@@ -522,20 +527,46 @@ rt2500pci_config_antenna(struct rt2x00_p
*/
if (antenna == 0) {
/* Diversity. */
- reg_rx = (reg_rx & 0xf9) | 0x02;
- reg_tx = (reg_tx & 0xfc) | 0x01;
+ reg_rx |= 0x02;
+ reg_tx |= 0x01;
+ rt2x00_set_field32(®, BBPCSR1_CCK, 2);
+ rt2x00_set_field32(®, BBPCSR1_OFDM, 2);
} else if (antenna == 1) {
/* RX: Antenna B */
- reg_rx = (reg_rx & 0xf9) | 0x04;
+ reg_rx |= 0x04;
/* TX: Antenna A */
- reg_tx = (reg_tx & 0xfc) | 0x00;
+ reg_tx |= 0x00;
+ rt2x00_set_field32(®, BBPCSR1_CCK, 0);
+ rt2x00_set_field32(®, BBPCSR1_OFDM, 0);
} else if (antenna == 2) {
/* RX: Antenna A */
- reg_rx = (reg_rx & 0xf9) | 0x00;
+ reg_rx |= 0x00;
/* TX: Antenna B */
- reg_tx = (reg_tx & 0xfc) | 0x02;
+ reg_tx |= 0x02;
+ rt2x00_set_field32(®, BBPCSR1_CCK, 2);
+ rt2x00_set_field32(®, BBPCSR1_OFDM, 2);
+ }
+
+ /*
+ * RT2525E and RT5222 need to flip TX I/Q
+ */
+ if (rt2x00_rf(&rt2x00pci->chip, RF2525E)
+ || rt2x00_rf(&rt2x00pci->chip, RF5222)) {
+ reg_tx |= 0x04;
+ rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1);
+ rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1);
+
+ /*
+ * RT2525E does not need RX I/Q Flip.
+ */
+ if (rt2x00_rf(&rt2x00pci->chip, RF2525E))
+ reg_rx &= ~0x04;
+ } else {
+ rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0);
+ rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 0);
}
+ rt2x00_register_write(rt2x00pci, BBPCSR1, reg);
rt2x00_bbp_write(rt2x00pci, 14, reg_rx);
rt2x00_bbp_write(rt2x00pci, 2, reg_tx);
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:41:20.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:41:52.000000000 +0200
@@ -372,8 +372,9 @@ rt2500usb_config_antenna(struct rt2x00_u
rt2x00_register_read(rt2x00usb, PHY_CSR5, &csr5_reg);
rt2x00_register_read(rt2x00usb, PHY_CSR6, &csr6_reg);
- csr5_reg &= ~0x0003;
- csr6_reg &= ~0x0003;
+ /*
+ * Clear current config antenna bits.
+ */
reg_tx &= ~0x03;
reg_rx &= ~0x03;
@@ -386,40 +387,41 @@ rt2500usb_config_antenna(struct rt2x00_u
/* Diversity. */
reg_rx |= 0x01;
reg_tx |= 0x01;
- csr5_reg |= 0x0001;
- csr6_reg |= 0x0001;
+ rt2x00_set_field16_nb(&csr5_reg, PHY_CSR5_CCK, 1);
+ rt2x00_set_field16_nb(&csr6_reg, PHY_CSR6_OFDM, 1);
} else if (antenna == 1) {
/* RX: Antenna B */
reg_rx |= 0x02;
/* TX: Antenna A */
reg_tx |= 0x00;
- csr5_reg |= 0x0000;
- csr6_reg |= 0x0000;
+ rt2x00_set_field16_nb(&csr5_reg, PHY_CSR5_CCK, 0);
+ rt2x00_set_field16_nb(&csr6_reg, PHY_CSR6_OFDM, 0);
} else if (antenna == 2) {
/* RX: Antenna A */
reg_tx |= 0x02;
- csr5_reg |= 0x0002;
- csr6_reg |= 0x0002;
/* TX: Antenna B */
reg_rx |= 0x00;
+ rt2x00_set_field16_nb(&csr5_reg, PHY_CSR5_CCK, 2);
+ rt2x00_set_field16_nb(&csr6_reg, PHY_CSR6_OFDM, 2);
}
/*
- * RT2525E needs to flip TX I/Q but not RX I/Q.
+ * RT2525E and RT5222 need to flip TX I/Q
*/
- if (rt2x00_rf(&rt2x00usb->chip, RF2525E)) {
+ if (rt2x00_rf(&rt2x00usb->chip, RF2525E)
+ || rt2x00_rf(&rt2x00usb->chip, RF5222)) {
reg_tx |= 0x04;
- reg_rx &= ~0x04;
- csr5_reg |= 0x0004;
- csr6_reg |= 0x0004;
- }
- /*
- * RT5222 needs to flip TX I/Q.
- */
- if (rt2x00_rf(&rt2x00usb->chip, RF5222)) {
- reg_tx |= 0x04;
- csr5_reg |= 0x0004;
- csr6_reg |= 0x0004;
+ rt2x00_set_field16_nb(&csr5_reg, PHY_CSR5_CCK_FLIP, 1);
+ rt2x00_set_field16_nb(&csr6_reg, PHY_CSR6_OFDM_FLIP, 1);
+
+ /*
+ * RT2525E does not need RX I/Q Flip.
+ */
+ if (rt2x00_rf(&rt2x00usb->chip, RF2525E))
+ reg_rx &= ~0x04;
+ } else {
+ rt2x00_set_field16_nb(&csr5_reg, PHY_CSR5_CCK_FLIP, 0);
+ rt2x00_set_field16_nb(&csr6_reg, PHY_CSR6_OFDM_FLIP, 0);
}
rt2x00_bbp_write(rt2x00usb, 2, reg_tx);
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 10/32] rt2x00: Move TSF counting activation to correct funtion
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 6697 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Move the enabling of TSF counting into *_config_mode
where it actually belongs.
For rt2500usb this means that the rt2500usb_reset_tsf function
is now removed since it is still unknown in what registers the
TSF counters are stored in.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:41:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:42:29.000000000 +0200
@@ -385,6 +385,9 @@ rt2400pci_config_mode(struct rt2x00_pci
{
u32 reg;
+ /*
+ * Apply hardware packet filter.
+ */
rt2x00_register_read(rt2x00pci, RXCSR0, ®);
if (mode == IW_MODE_ADHOC
@@ -408,6 +411,19 @@ rt2400pci_config_mode(struct rt2x00_pci
}
rt2x00_register_write(rt2x00pci, RXCSR0, reg);
+
+ /*
+ * Enable TSF counter.
+ */
+ rt2x00_register_read(rt2x00pci, CSR14, ®);
+ rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
+ if (mode == IW_MODE_ADHOC)
+ rt2x00_set_field32(®, CSR14_TSF_SYNC, 2);
+ else if (mode == IW_MODE_INFRA)
+ rt2x00_set_field32(®, CSR14_TSF_SYNC, 1);
+ else
+ rt2x00_set_field32(®, CSR14_TSF_SYNC, 0);
+ rt2x00_register_write(rt2x00pci, CSR14, reg);
}
static void
@@ -1723,21 +1739,10 @@ static void
rt2400pci_reset_tsf(struct net_device *net_dev)
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
- struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
u32 reg = 0;
rt2x00_register_write(rt2x00pci, CSR16, reg);
rt2x00_register_write(rt2x00pci, CSR17, reg);
-
- rt2x00_register_read(rt2x00pci, CSR14, ®);
- rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
- if (conf->mode == IW_MODE_ADHOC)
- rt2x00_set_field32(®, CSR14_TSF_SYNC, 2);
- else if (conf->mode == IW_MODE_INFRA)
- rt2x00_set_field32(®, CSR14_TSF_SYNC, 1);
- else
- rt2x00_set_field32(®, CSR14_TSF_SYNC, 0);
- rt2x00_register_write(rt2x00pci, CSR14, reg);
}
static int
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:41:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:42:29.000000000 +0200
@@ -385,6 +385,9 @@ rt2500pci_config_mode(struct rt2x00_pci
{
u32 reg;
+ /*
+ * Apply hardware packet filter.
+ */
rt2x00_register_read(rt2x00pci, RXCSR0, ®);
if (mode == IW_MODE_ADHOC
@@ -411,6 +414,19 @@ rt2500pci_config_mode(struct rt2x00_pci
rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0);
rt2x00_register_write(rt2x00pci, RXCSR0, reg);
+
+ /*
+ * Enable TSF counter.
+ */
+ rt2x00_register_read(rt2x00pci, CSR14, ®);
+ rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
+ if (mode == IW_MODE_ADHOC)
+ rt2x00_set_field32(®, CSR14_TSF_SYNC, 2);
+ else if (mode == IW_MODE_INFRA)
+ rt2x00_set_field32(®, CSR14_TSF_SYNC, 1);
+ else
+ rt2x00_set_field32(®, CSR14_TSF_SYNC, 0);
+ rt2x00_register_write(rt2x00pci, CSR14, reg);
}
static void
@@ -1809,21 +1825,10 @@ static void
rt2500pci_reset_tsf(struct net_device *net_dev)
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
- struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
u32 reg = 0;
rt2x00_register_write(rt2x00pci, CSR16, reg);
rt2x00_register_write(rt2x00pci, CSR17, reg);
-
- rt2x00_register_read(rt2x00pci, CSR14, ®);
- rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
- if (conf->mode == IW_MODE_ADHOC)
- rt2x00_set_field32(®, CSR14_TSF_SYNC, 2);
- else if (conf->mode == IW_MODE_INFRA)
- rt2x00_set_field32(®, CSR14_TSF_SYNC, 1);
- else
- rt2x00_set_field32(®, CSR14_TSF_SYNC, 0);
- rt2x00_register_write(rt2x00pci, CSR14, reg);
}
static int
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:41:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:42:29.000000000 +0200
@@ -268,6 +268,9 @@ rt2500usb_config_mode(struct rt2x00_usb
{
u16 reg;
+ /*
+ * Apply hardware packet filter.
+ */
rt2x00_register_read(rt2x00usb, TXRX_CSR2, ®);
if (mode == IW_MODE_ADHOC
@@ -1509,24 +1512,6 @@ rt2500usb_get_tx_stats(struct net_device
return 0;
}
-static void
-rt2500usb_reset_tsf(struct net_device *net_dev)
-{
- struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
- struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
- u16 reg = 0;
-
- rt2x00_register_read(rt2x00usb, TXRX_CSR19, ®);
- rt2x00_set_field16_nb(®, TXRX_CSR19_TSF_COUNT, 1);
- if (conf->mode == IW_MODE_ADHOC)
- rt2x00_set_field16_nb(®, TXRX_CSR19_TSF_SYNC, 2);
- else if (conf->mode == IW_MODE_INFRA)
- rt2x00_set_field16_nb(®, TXRX_CSR19_TSF_SYNC, 1);
- else
- rt2x00_set_field16_nb(®, TXRX_CSR19_TSF_SYNC, 0);
- rt2x00_register_write(rt2x00usb, TXRX_CSR19, reg);
-}
-
static int
rt2500usb_beacon_update(struct net_device *net_dev,
struct sk_buff *skb, struct ieee80211_tx_control *control)
@@ -1880,7 +1865,6 @@ rt2500usb_init_hw(struct rt2x00_usb *rt2
hw->set_mac_address = rt2500usb_set_mac_address;
hw->conf_tx = rt2500usb_conf_tx;
hw->get_tx_stats = rt2500usb_get_tx_stats;
- hw->reset_tsf = rt2500usb_reset_tsf;
hw->beacon_update = rt2500usb_beacon_update;
/*
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:36:19.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:42:29.000000000 +0200
@@ -748,7 +748,6 @@ static int rt2500usb_conf_tx(struct net_
int queue, const struct ieee80211_tx_queue_params *params);
static int rt2500usb_get_tx_stats(struct net_device *net_dev,
struct ieee80211_tx_queue_stats *stats);
-static void rt2500usb_reset_tsf(struct net_device *net_dev);
static int rt2500usb_beacon_update(struct net_device *net_dev,
struct sk_buff *skb, struct ieee80211_tx_control *control);
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 11/32] rt2x00: Add more register defines
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 3868 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
During the work on rt2x00 several new registers could be defined.
This will add all those new registers, and will in the next
couple of patches be used.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 21:36:19.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 21:43:27.000000000 +0200
@@ -43,6 +43,13 @@
#define RF5222 0x0010
/*
+ * RT2560 version
+ */
+#define RT2560_VERSION_B 2
+#define RT2560_VERSION_C 3
+#define RT2560_VERSION_D 4
+
+/*
* Control/Status Registers(CSR).
* Some values are set in TU, whereas 1 TU == 1024 us.
*/
@@ -558,15 +565,23 @@
* Statistic Register.
* CNT1: PLCP error count.
* CNT2: Long error count.
- * CNT3: CCA false alarm count.
- * CNT4: Rx FIFO overflow count.
- * CNT5: Tx FIFO underrun count.
*/
#define TIMECSR2 0x00a8
#define CNT1 0x00ac
#define CNT2 0x00b0
#define TIMECSR3 0x00b4
+
+/*
+ * CNT3: CCA false alarm count.
+ */
#define CNT3 0x00b8
+#define CNT3_FALSE_CCA FIELD32(0x0000ffff)
+
+/*
+ * Statistic Register.
+ * CNT4: Rx FIFO overflow count.
+ * CNT5: Tx FIFO underrun count.
+ */
#define CNT4 0x00bc
#define CNT5 0x00c0
@@ -840,6 +855,10 @@
* BBPCSR1: BBP TX configuration.
*/
#define BBPCSR1 0x015c
+#define BBPCSR1_CCK FIELD32(0x00000003)
+#define BBPCSR1_CCK_FLIP FIELD32(0x00000004)
+#define BBPCSR1_OFDM FIELD32(0x00030000)
+#define BBPCSR1_OFDM_FLIP FIELD32(0x00040000)
/*
* Dual band configuration registers.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:42:29.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:43:27.000000000 +0200
@@ -160,10 +160,28 @@
#define MAC_CSR19 0x0426
/*
- * LED control registers.
+ * MAC_CSR20: LED control register.
+ * ACTIVITY: 0: idle, 1: active.
+ * LINK: 0: linkoff, 1: linkup.
+ * ACTIVITY_POLARITY: 0: active low, 1: active high.
*/
#define MAC_CSR20 0x0428
+#define MAC_CSR20_ACTIVITY FIELD16(0x0001)
+#define MAC_CSR20_LINK FIELD16(0x0002)
+#define MAC_CSR20_ACTIVITY_POLARITY FIELD16(0x0004)
+
+/*
+ * MAC_CSR21: LED control register.
+ * ON_PERIOD: On period, default 70ms.
+ * OFF_PERIOD: Off period, default 30ms.
+ */
#define MAC_CSR21 0x042a
+#define MAC_CSR21_ON_PERIOD FIELD16(0x00ff)
+#define MAC_CSR21_OFF_PERIOD FIELD16(0xff00)
+
+/*
+ * Collision window control register.
+ */
#define MAC_CSR22 0x042c
/*
@@ -373,10 +391,18 @@
/*
* BBP pre-TX registers.
* PHY_CSR5: BBP pre-TX CCK.
- * PHY_CSR6: BBP pre-TX OFDM.
*/
#define PHY_CSR5 0x04ca
+#define PHY_CSR5_CCK FIELD16(0x0003)
+#define PHY_CSR5_CCK_FLIP FIELD16(0x0004)
+
+/*
+ * BBP pre-TX registers.
+ * PHY_CSR6: BBP pre-TX OFDM.
+ */
#define PHY_CSR6 0x04cc
+#define PHY_CSR6_OFDM FIELD16(0x0003)
+#define PHY_CSR6_OFDM_FLIP FIELD16(0x0004)
/*
* PHY_CSR7: BBP access register 0.
@@ -459,6 +485,12 @@
* HW MAC address.
*/
#define EEPROM_MAC_ADDR 0x0004
+#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00)
/*
* EEPROM antenna.
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 12/32] rt2x00: Add USB ID's
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 1692 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Remove the rt73usb ID that accidently sneaked into
rt2500usb. And add new rt2500usb ID's.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:42:29.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:44:33.000000000 +0200
@@ -2192,6 +2192,7 @@ static struct usb_device_id rt2500usb_de
{ USB_DEVICE(0x0b05, 0x1707), .driver_info = RT2570},
/* Belkin */
{ USB_DEVICE(0x050d, 0x7050), .driver_info = RT2570},
+ { USB_DEVICE(0x050d, 0x7051), .driver_info = RT2570},
{ USB_DEVICE(0x050d, 0x705a), .driver_info = RT2570},
/* Cisco Systems */
{ USB_DEVICE(0x13b1, 0x000d), .driver_info = RT2570},
@@ -2201,7 +2202,6 @@ static struct usb_device_id rt2500usb_de
{ USB_DEVICE(0x14b2, 0x3c02), .driver_info = RT2570},
/* D-LINK */
{ USB_DEVICE(0x2001, 0x3c00), .driver_info = RT2570},
- { USB_DEVICE(0x07d1, 0x3c03), .driver_info = RT2570},
/* Gigabyte */
{ USB_DEVICE(0x1044, 0x8001), .driver_info = RT2570},
{ USB_DEVICE(0x1044, 0x8007), .driver_info = RT2570},
@@ -2224,6 +2224,10 @@ static struct usb_device_id rt2500usb_de
{ USB_DEVICE(0x0707, 0xee13), .driver_info = RT2570},
/* Spairon */
{ USB_DEVICE(0x114b, 0x0110), .driver_info = RT2570},
+ /* Trust */
+ { USB_DEVICE(0x0eb0, 0x9020), .driver_info = RT2570},
+ /* Zinwell */
+ { USB_DEVICE(0x5a57, 0x0260), .driver_info = RT2570},
{0,}
};
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 13/32] rt2x00: Tune link depending on link quality
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 7739 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Add link tuning capabilities, and call this function
every time the rxdone handler has finished.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:42:29.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:45:08.000000000 +0200
@@ -618,6 +618,41 @@ rt2400pci_config_rate(struct rt2x00_pci
}
/*
+ * Link tuning
+ */
+static void
+rt2400pci_link_tuner(struct rt2x00_pci *rt2x00pci)
+{
+ u8 reg;
+ char false_cca_delta;
+
+ /*
+ * Read false CCA counter.
+ */
+ rt2x00_bbp_read(rt2x00pci, 39, ®);
+
+ /*
+ * Determine difference with previous CCA counter.
+ */
+ false_cca_delta = reg - rt2x00pci->false_cca;
+ rt2x00pci->false_cca = reg;
+
+ /*
+ * Check if the difference is higher than the
+ * threshold and if so, tune the link.
+ */
+ if (false_cca_delta >= 8) {
+ /*
+ * Read and update RX AGC VGC.
+ */
+ rt2x00_bbp_read(rt2x00pci, 13, ®);
+ reg += 2;
+ if (reg < 0x20)
+ rt2x00_bbp_write(rt2x00pci, 13, reg);
+ }
+}
+
+/*
* TX descriptor initialization
*/
static void
@@ -779,6 +814,9 @@ rt2400pci_rxdone(void *data)
memcpy(skb_put(skb, size), entry->data_addr, size);
+ ring->params.rx.ssi =
+ rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
+
__ieee80211_rx(net_dev, skb, &ring->params.rx);
}
@@ -786,6 +824,11 @@ rt2400pci_rxdone(void *data)
rt2x00_ring_index_inc(&rt2x00pci->rx);
}
+
+ /*
+ * Tune link for optimal performance.
+ */
+ rt2400pci_link_tuner(rt2x00pci);
}
static void
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:36:19.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:45:08.000000000 +0200
@@ -926,6 +926,11 @@ struct rt2x00_pci{
struct workqueue_struct *workqueue;
/*
+ * False CCA count.
+ */
+ int false_cca;
+
+ /*
* EEPROM bus width.
*/
u8 eeprom_width;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:42:29.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:45:08.000000000 +0200
@@ -661,6 +661,51 @@ rt2500pci_config_rate(struct rt2x00_pci
}
/*
+ * Link tuning
+ */
+static void
+rt2500pci_link_tuner(struct rt2x00_pci *rt2x00pci, char rssi)
+{
+ u32 reg;
+ u8 reg_r17;
+
+ /*
+ * Don't perform any tuning during scan.
+ */
+ if (rt2x00pci->scan)
+ return;
+
+ rt2x00_register_read(rt2x00pci, CSR0, ®);
+ rt2x00_bbp_read(rt2x00pci, 17, ®_r17);
+
+ if (reg < RT2560_VERSION_D)
+ goto dynamic_cca_tune;
+
+ if (rssi < 40) {
+ if (reg_r17 >= 0x41)
+ rt2x00_bbp_write(rt2x00pci, 17, reg_r17);
+ return;
+ } else if (rssi >= 62) {
+ if (reg_r17 != 0x50)
+ rt2x00_bbp_write(rt2x00pci, 17, 0x50);
+ return;
+ } else if (reg_r17 >= 0x41) {
+ rt2x00_bbp_write(rt2x00pci, 17, reg_r17);
+ return;
+ }
+
+dynamic_cca_tune:
+ rt2x00_register_read(rt2x00pci, CNT3, ®);
+
+ reg = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
+
+ if (reg > 512 && reg_r17 < 0x40)
+ rt2x00_bbp_write(rt2x00pci, 17, ++reg_r17);
+ else if (reg < 100 && reg_r17 > 0x32)
+ rt2x00_bbp_write(rt2x00pci, 17, --reg_r17);
+}
+
+/*
* TX descriptor initialization
*/
static void
@@ -819,6 +864,14 @@ rt2500pci_rxdone(void *data)
struct sk_buff *skb;
struct rxd *rxd;
u16 size;
+ u8 rssi_count;
+ char total_rssi;
+
+ /*
+ * Initialize variable for average RSSI calculation.
+ */
+ rssi_count = 0;
+ total_rssi = 0;
while (1) {
entry = rt2x00_get_data_entry(ring);
@@ -843,12 +896,24 @@ rt2500pci_rxdone(void *data)
memcpy(skb_put(skb, size), entry->data_addr, size);
+ ring->params.rx.ssi =
+ rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
+
__ieee80211_rx(net_dev, skb, &ring->params.rx);
+
+ rssi_count++;
+ total_rssi += ring->params.rx.ssi;
}
rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
rt2x00_ring_index_inc(&rt2x00pci->rx);
}
+
+ /*
+ * Tune link for optimal performance.
+ */
+ if (total_rssi && rssi_count)
+ rt2500pci_link_tuner(rt2x00pci, total_rssi / rssi_count);
}
static void
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:44:33.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:45:08.000000000 +0200
@@ -485,6 +485,68 @@ rt2500usb_config_rate(struct rt2x00_usb
}
/*
+ * Link tuning
+ */
+static void
+rt2500usb_link_tuner(struct rt2x00_usb *rt2x00usb, char rssi)
+{
+ u16 reg;
+ u8 reg_r17;
+ u8 up_bound;
+ u8 low_bound;
+
+ /*
+ * Don't perform any tuning during scan.
+ */
+ if (rt2x00usb->scan)
+ return;
+
+ low_bound = 0x32;
+ if (rssi >= 43)
+ up_bound = 0x40;
+ else
+ up_bound = 0x40 - (43 - rssi);
+ if (up_bound < low_bound)
+ up_bound = low_bound;
+
+ if (rssi > 75) {
+ rt2x00_bbp_write(rt2x00usb, 24, 0x70);
+ rt2x00_bbp_write(rt2x00usb, 25, 0x40);
+ rt2x00_bbp_write(rt2x00usb, 61, 0x6d);
+ } else {
+ rt2x00_bbp_write(rt2x00usb, 24, 0x80);
+ rt2x00_bbp_write(rt2x00usb, 25, 0x50);
+ rt2x00_bbp_write(rt2x00usb, 61, 0x60);
+ }
+
+ rt2x00_bbp_read(rt2x00usb, 17, ®_r17);
+
+ if (rssi > 80) {
+ if (reg_r17 != 0x60)
+ rt2x00_bbp_write(rt2x00usb, 17, 0x60);
+ return;
+ } else if (rssi >= 62) {
+ if (reg_r17 != 0x48)
+ rt2x00_bbp_write(rt2x00usb, 17, 0x48);
+ return;
+ } else if (rssi >= 46) {
+ if (reg_r17 != 0x41)
+ rt2x00_bbp_write(rt2x00usb, 17, 0x41);
+ return;
+ } else if (reg_r17 > up_bound) {
+ rt2x00_bbp_write(rt2x00usb, 17, up_bound);
+ return;
+ }
+
+ rt2x00_register_read(rt2x00usb, STA_CSR3, ®);
+
+ if (reg > 512 && reg_r17 < up_bound)
+ rt2x00_bbp_write(rt2x00usb, 17, ++reg_r17);
+ else if (reg < 100 && reg_r17 > low_bound)
+ rt2x00_bbp_write(rt2x00usb, 17, --reg_r17);
+}
+
+/*
* TX descriptor initialization
*/
static void
@@ -636,6 +698,14 @@ rt2500usb_rxdone(void *data)
struct sk_buff *skb;
struct rxd *rxd;
u16 size;
+ u8 rssi_count;
+ char total_rssi;
+
+ /*
+ * Initialize variable for average RSSI calculation.
+ */
+ rssi_count = 0;
+ total_rssi = 0;
while (1) {
entry = rt2x00_get_data_entry(ring);
@@ -670,13 +740,25 @@ rt2500usb_rxdone(void *data)
memcpy(skb_put(skb, size), entry->data_addr, size);
+ ring->params.rx.ssi =
+ rt2x00_get_field32(rxd->word1, RXD_W1_RSSI);
+
__ieee80211_rx(net_dev, skb, &ring->params.rx);
+
+ rssi_count++;
+ total_rssi += ring->params.rx.ssi;
}
usb_submit_urb(entry->urb, GFP_ATOMIC);
rt2x00_ring_index_inc(ring);
}
+
+ /*
+ * Tune link for optimal performance.
+ */
+ if (total_rssi && rssi_count)
+ rt2500usb_link_tuner(rt2x00usb, total_rssi / rssi_count);
}
static void
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 14/32] rt2x00: Allocate eeprom memory
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 5873 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Make the EEPROM array in rt2x00_pci and rt2x00_usb a pointer,
and allocate the memory seperately. This is needed for make
the structures more generic for all rt2x00 pci or usb modules.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:45:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:47:22.000000000 +0200
@@ -1831,7 +1831,6 @@ rt2400pci_init_eeprom(struct rt2x00_pci
u32 reg;
u16 value;
u16 eeprom;
- int counter;
/*
* 1 - Detect EEPROM width.
@@ -1886,8 +1885,12 @@ rt2400pci_init_eeprom(struct rt2x00_pci
/*
* 7 - Read BBP data from EEPROM and store in private structure.
*/
+ rt2x00pci->eeprom = kzalloc(EEPROM_BBP_SIZE * sizeof(u16), GFP_KERNEL);
+ if (!rt2x00pci->eeprom)
+ return -ENOMEM;
+
rt2x00_eeprom_multiread(rt2x00pci, EEPROM_BBP_START,
- &rt2x00pci->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
+ rt2x00pci->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
return 0;
}
@@ -2197,6 +2200,8 @@ rt2400pci_uninitialize(struct net_device
del_timer_sync(&rt2x00pci->poll_timer);
#endif /* CONFIG_RT2400PCI_BUTTON */
+ kfree(rt2x00pci->eeprom);
+
if (likely(rt2x00pci->csr_addr)) {
iounmap(rt2x00pci->csr_addr);
rt2x00pci->csr_addr = NULL;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:45:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:47:22.000000000 +0200
@@ -945,7 +945,7 @@ struct rt2x00_pci{
/*
* EEPROM BBP data.
*/
- u16 eeprom[EEPROM_BBP_SIZE];
+ u16 *eeprom;
/*
* Low level statistics which will have
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:45:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:47:22.000000000 +0200
@@ -1939,7 +1939,6 @@ rt2500pci_init_eeprom(struct rt2x00_pci
u32 reg;
u16 value;
u16 eeprom;
- int counter;
/*
* 1 - Detect EEPROM width.
@@ -1998,8 +1997,12 @@ rt2500pci_init_eeprom(struct rt2x00_pci
/*
* 7 - Read BBP data from EEPROM and store in private structure.
*/
+ rt2x00pci->eeprom = kzalloc(EEPROM_BBP_SIZE * sizeof(u16), GFP_KERNEL);
+ if (!rt2x00pci->eeprom)
+ return -ENOMEM;
+
rt2x00_eeprom_multiread(rt2x00pci, EEPROM_BBP_START,
- &rt2x00pci->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
+ rt2x00pci->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
return 0;
}
@@ -2495,6 +2498,8 @@ rt2500pci_uninitialize(struct net_device
del_timer_sync(&rt2x00pci->poll_timer);
#endif /* CONFIG_RT2500PCI_BUTTON */
+ kfree(rt2x00pci->eeprom);
+
if (likely(rt2x00pci->csr_addr)) {
iounmap(rt2x00pci->csr_addr);
rt2x00pci->csr_addr = NULL;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 21:43:27.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 21:47:22.000000000 +0200
@@ -1215,7 +1215,7 @@ struct rt2x00_pci{
/*
* EEPROM BBP data.
*/
- u16 eeprom[EEPROM_BBP_SIZE];
+ u16 *eeprom;
/*
* Low level statistics which will have
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:45:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:47:22.000000000 +0200
@@ -1657,9 +1657,12 @@ rt2500usb_init_eeprom(struct rt2x00_usb
/*
* 5 - Read BBP data from EEPROM and store in private structure.
*/
- memset(&rt2x00usb->eeprom, 0x00, sizeof(rt2x00usb->eeprom));
+ rt2x00usb->eeprom = kzalloc(EEPROM_BBP_SIZE * sizeof(u16), GFP_KERNEL);
+ if (!rt2x00usb->eeprom)
+ return -ENOMEM;
+
rt2x00_eeprom_multiread(rt2x00usb, EEPROM_BBP_START,
- &rt2x00usb->eeprom[0], EEPROM_BBP_SIZE);
+ rt2x00usb->eeprom, EEPROM_BBP_SIZE * sizeof(u16));
return 0;
}
@@ -2116,6 +2119,8 @@ rt2500usb_uninitialize(struct net_device
{
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
+ kfree(rt2x00usb->eeprom);
+
if (rt2x00usb->scan) {
rt2x00usb->scan->cancelled = 1;
complete_all(&rt2x00usb->scan->completion);
@@ -2129,7 +2134,7 @@ rt2500usb_uninitialize(struct net_device
kfree(rt2x00usb->hw.modes);
rt2x00usb->hw.modes = NULL;
- }
+}
/*
* USB driver handlers.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:43:27.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:47:22.000000000 +0200
@@ -727,7 +727,7 @@ struct rt2x00_usb{
/*
* EEPROM BBP data.
*/
- u16 eeprom[EEPROM_BBP_SIZE];
+ u16 *eeprom;
/*
* Low level statistics which will have
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 15/32] rt2x00: Move rx_params to correct location
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 15891 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Store rx_params seperately outside the ring structure.
This is more safer and required because of some changes
in the way the rings are stored in the structure in the following
patches.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:47:52.000000000 +0200
@@ -475,8 +475,8 @@ rt2400pci_config_channel(struct rt2x00_p
/*
* Update active info for RX.
*/
- rt2x00pci->rx.params.rx.freq = freq;
- rt2x00pci->rx.params.rx.channel = channel;
+ rt2x00pci->rx_params.freq = freq;
+ rt2x00pci->rx_params.channel = channel;
/*
* Clear false CRC during channel switch.
@@ -534,7 +534,7 @@ rt2400pci_config_antenna(struct rt2x00_p
/*
* Update active info for RX.
*/
- rt2x00pci->rx.params.rx.antenna = antenna;
+ rt2x00pci->rx_params.antenna = antenna;
}
static void
@@ -814,10 +814,10 @@ rt2400pci_rxdone(void *data)
memcpy(skb_put(skb, size), entry->data_addr, size);
- ring->params.rx.ssi =
+ rt2x00pci->rx_params.ssi =
rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
- __ieee80211_rx(net_dev, skb, &ring->params.rx);
+ __ieee80211_rx(net_dev, skb, &rt2x00pci->rx_params);
}
rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
@@ -981,8 +981,8 @@ rt2400pci_alloc_ring(
/*
* Initialize ring parameters.
*/
- ring->params.tx.cw_min = 5; /* cw_min: 2^5 = 32. */
- ring->params.tx.cw_max = 10; /* cw_max: 2^10 = 1024. */
+ ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
+ ring->tx_params.cw_max = 10; /* cw_max: 2^10 = 1024. */
rt2x00_ring_index_clear(ring);
@@ -1374,7 +1374,7 @@ rt2400pci_tx(struct net_device *net_dev,
* queue. This is the alternative since we cannot
* set the CWmin and CWmax per descriptor.
*/
- rt2400pci_config_cw(rt2x00pci, &ring->params.tx);
+ rt2400pci_config_cw(rt2x00pci, &ring->tx_params);
rt2x00_register_write(rt2x00pci, TXCSR0, reg);
return 0;
@@ -1544,7 +1544,7 @@ rt2400pci_config_update(void *data)
/*
* Update active info for RX.
*/
- rt2x00pci->rx.params.rx.phymode = conf->phymode;
+ rt2x00pci->rx_params.phymode = conf->phymode;
}
static int
@@ -1599,7 +1599,7 @@ rt2400pci_scan(void *data)
* Switch channel and update active info for RX.
*/
if (rt2x00pci->scan->state == IEEE80211_SCAN_START) {
- rt2x00pci->rx.params.rx.phymode =
+ rt2x00pci->rx_params.phymode =
rt2x00pci->scan->conf.scan_phymode;
rt2400pci_config_channel(rt2x00pci,
@@ -1610,7 +1610,7 @@ rt2400pci_scan(void *data)
rt2400pci_config_txpower(rt2x00pci,
rt2x00pci->scan->conf.scan_power_level);
} else {
- rt2x00pci->rx.params.rx.phymode =
+ rt2x00pci->rx_params.phymode =
rt2x00pci->scan->conf.running_phymode;
rt2400pci_config_channel(rt2x00pci,
@@ -1726,7 +1726,7 @@ rt2400pci_conf_tx(struct net_device *net
else
return -EINVAL;
- memcpy(&ring->params, params, sizeof(*params));
+ memcpy(&ring->tx_params, params, sizeof(*params));
/*
* TODO: We can't use different cw_min and cw_max variables
@@ -1737,14 +1737,14 @@ rt2400pci_conf_tx(struct net_device *net
* RT2400 registers require to know the bit number 'n'.
*/
if (params->cw_min)
- ring->params.tx.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
+ ring->tx_params.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
else
- ring->params.tx.cw_min = 5; /* cw_min: 2^5 = 32. */
+ ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
if (params->cw_max)
- ring->params.tx.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
+ ring->tx_params.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
else
- ring->params.tx.cw_max = 10; /* cw_min: 2^10 = 1024. */
+ ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
return 0;
}
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 2006-04-27 21:47:52.000000000 +0200
@@ -926,6 +926,11 @@ struct rt2x00_pci{
struct workqueue_struct *workqueue;
/*
+ * RX ring parameters.
+ */
+ struct ieee80211_rx_status rx_params;
+
+ /*
* False CCA count.
*/
int false_cca;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:47:52.000000000 +0200
@@ -510,8 +510,8 @@ rt2500pci_config_channel(struct rt2x00_p
/*
* Update active info for RX.
*/
- rt2x00pci->rx.params.rx.freq = freq;
- rt2x00pci->rx.params.rx.channel = channel;
+ rt2x00pci->rx_params.freq = freq;
+ rt2x00pci->rx_params.channel = channel;
/*
* Clear false CRC during channel switch.
@@ -589,7 +589,7 @@ rt2500pci_config_antenna(struct rt2x00_p
/*
* Update active info for RX.
*/
- rt2x00pci->rx.params.rx.antenna = antenna;
+ rt2x00pci->rx_params.antenna = antenna;
}
static void
@@ -733,16 +733,16 @@ rt2500pci_write_tx_desc(
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
if (control->queue == IEEE80211_TX_QUEUE_DATA0) {
- params = &rt2x00pci->prio.params.tx;
+ params = &rt2x00pci->prio.tx_params;
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
} else if (control->queue == IEEE80211_TX_QUEUE_DATA1) {
- params = &rt2x00pci->tx.params.tx;
+ params = &rt2x00pci->tx.tx_params;
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
} else if (IEEE80211_TX_QUEUE_AFTER_BEACON) {
- params = &rt2x00pci->atim.params.tx;
+ params = &rt2x00pci->atim.tx_params;
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
} else if (IEEE80211_TX_QUEUE_BEACON) {
- params = &rt2x00pci->beacon.params.tx;
+ params = &rt2x00pci->beacon.tx_params;
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 1);
}
@@ -896,13 +896,13 @@ rt2500pci_rxdone(void *data)
memcpy(skb_put(skb, size), entry->data_addr, size);
- ring->params.rx.ssi =
+ rt2x00pci->rx_params.ssi =
rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
- __ieee80211_rx(net_dev, skb, &ring->params.rx);
+ __ieee80211_rx(net_dev, skb, &rt2x00pci->rx_params);
rssi_count++;
- total_rssi += ring->params.rx.ssi;
+ total_rssi += rt2x00pci->rx_params.ssi;
}
rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
@@ -1066,9 +1066,9 @@ rt2500pci_alloc_ring(
/*
* Initialize ring parameters.
*/
- ring->params.tx.aifs = 2;
- ring->params.tx.cw_min = 5; /* cw_min: 2^5 = 32. */
- ring->params.tx.cw_max = 10; /* cw_max: 2^10 = 1024. */
+ ring->tx_params.aifs = 2;
+ ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
+ ring->tx_params.cw_max = 10; /* cw_max: 2^10 = 1024. */
rt2x00_ring_index_clear(ring);
@@ -1657,7 +1657,7 @@ rt2500pci_config_update(void *data)
/*
* Update active info for RX.
*/
- rt2x00pci->rx.params.rx.phymode = conf->phymode;
+ rt2x00pci->rx_params.phymode = conf->phymode;
}
static int
@@ -1712,7 +1712,7 @@ rt2500pci_scan(void *data)
* Switch channel and update active info for RX.
*/
if (rt2x00pci->scan->state == IEEE80211_SCAN_START) {
- rt2x00pci->rx.params.rx.phymode =
+ rt2x00pci->rx_params.phymode =
rt2x00pci->scan->conf.scan_phymode;
rt2500pci_config_channel(rt2x00pci,
@@ -1721,7 +1721,7 @@ rt2500pci_scan(void *data)
rt2x00pci->scan->conf.scan_freq,
rt2x00pci->scan->conf.scan_power_level);
} else {
- rt2x00pci->rx.params.rx.phymode =
+ rt2x00pci->rx_params.phymode =
rt2x00pci->scan->conf.running_phymode;
rt2500pci_config_channel(rt2x00pci,
@@ -1835,24 +1835,24 @@ rt2500pci_conf_tx(struct net_device *net
else
return -EINVAL;
- memcpy(&ring->params, params, sizeof(*params));
+ memcpy(&ring->tx_params, params, sizeof(*params));
/*
* The passed variables are stored as real value ((2^n)-1).
* RT2400 registers require to know the bit number 'n'.
*/
if (params->cw_min)
- ring->params.tx.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
+ ring->tx_params.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
else
- ring->params.tx.cw_min = 5; /* cw_min: 2^5 = 32. */
+ ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
if (params->cw_max)
- ring->params.tx.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
+ ring->tx_params.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
else
- ring->params.tx.cw_max = 10; /* cw_min: 2^10 = 1024. */
+ ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
if (!params->aifs)
- ring->params.tx.aifs = 2;
+ ring->tx_params.aifs = 2;
return 0;
}
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.h 2006-04-27 21:47:52.000000000 +0200
@@ -1196,6 +1196,11 @@ struct rt2x00_pci{
struct workqueue_struct *workqueue;
/*
+ * RX ring parameters.
+ */
+ struct ieee80211_rx_status rx_params;
+
+ /*
* Alignment.
*/
u16 __pad;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:47:52.000000000 +0200
@@ -435,7 +435,7 @@ rt2500usb_config_antenna(struct rt2x00_u
/*
* Update active info for RX.
*/
- rt2x00usb->rx.params.rx.antenna = antenna;
+ rt2x00usb->rx_params.antenna = antenna;
}
static void
@@ -573,16 +573,16 @@ rt2500usb_write_tx_desc(
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
if (control->queue == IEEE80211_TX_QUEUE_DATA0) {
- params = &rt2x00usb->prio.params.tx;
+ params = &rt2x00usb->prio.tx_params;
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
} else if (control->queue == IEEE80211_TX_QUEUE_DATA1) {
- params = &rt2x00usb->tx.params.tx;
+ params = &rt2x00usb->tx.tx_params;
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
} else if (IEEE80211_TX_QUEUE_AFTER_BEACON) {
- params = &rt2x00usb->atim.params.tx;
+ params = &rt2x00usb->atim.tx_params;
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
} else if (IEEE80211_TX_QUEUE_BEACON) {
- params = &rt2x00usb->beacon.params.tx;
+ params = &rt2x00usb->beacon.tx_params;
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 1);
}
@@ -740,13 +740,13 @@ rt2500usb_rxdone(void *data)
memcpy(skb_put(skb, size), entry->data_addr, size);
- ring->params.rx.ssi =
+ rt2x00usb->rx_params.ssi =
rt2x00_get_field32(rxd->word1, RXD_W1_RSSI);
- __ieee80211_rx(net_dev, skb, &ring->params.rx);
+ __ieee80211_rx(net_dev, skb, &rt2x00usb->rx_params);
rssi_count++;
- total_rssi += ring->params.rx.ssi;
+ total_rssi += rt2x00usb->rx_params.ssi;
}
usb_submit_urb(entry->urb, GFP_ATOMIC);
@@ -855,9 +855,9 @@ rt2500usb_alloc_ring(
/*
* Initialize ring parameters.
*/
- ring->params.tx.aifs = 2;
- ring->params.tx.cw_min = 5; /* cw_min: 2^5 = 32. */
- ring->params.tx.cw_max = 10; /* cw_max: 2^10 = 1024. */
+ ring->tx_params.aifs = 2;
+ ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
+ ring->tx_params.cw_max = 10; /* cw_max: 2^10 = 1024. */
rt2x00_ring_index_clear(ring);
@@ -1394,7 +1394,7 @@ rt2500usb_config_update(void *data)
/*
* Update active info for RX.
*/
- rt2x00usb->rx.params.rx.phymode = conf->phymode;
+ rt2x00usb->rx_params.phymode = conf->phymode;
}
static int
@@ -1450,7 +1450,7 @@ rt2500usb_scan(void *data)
* Switch channel and update active info for RX.
*/
if (rt2x00usb->scan->state == IEEE80211_SCAN_START) {
- rt2x00usb->rx.params.rx.phymode =
+ rt2x00usb->rx_params.phymode =
rt2x00usb->scan->conf.scan_phymode;
rt2500usb_config_channel(rt2x00usb,
@@ -1459,7 +1459,7 @@ rt2500usb_scan(void *data)
rt2x00usb->scan->conf.scan_freq,
rt2x00usb->scan->conf.scan_power_level);
} else {
- rt2x00usb->rx.params.rx.phymode =
+ rt2x00usb->rx_params.phymode =
rt2x00usb->scan->conf.running_phymode;
rt2500usb_config_channel(rt2x00usb,
@@ -1558,24 +1558,24 @@ rt2500usb_conf_tx(struct net_device *net
else
return -EINVAL;
- memcpy(&ring->params, params, sizeof(*params));
+ memcpy(&ring->tx_params, params, sizeof(*params));
/*
* The passed variables are stored as real value ((2^n)-1).
* RT2400 registers require to know the bit number 'n'.
*/
if (params->cw_min)
- ring->params.tx.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
+ ring->tx_params.cw_min = HIGHEST_BIT16(params->cw_min) + 1;
else
- ring->params.tx.cw_min = 5; /* cw_min: 2^5 = 32. */
+ ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
if (params->cw_max)
- ring->params.tx.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
+ ring->tx_params.cw_max = HIGHEST_BIT16(params->cw_max) + 1;
else
- ring->params.tx.cw_max = 10; /* cw_min: 2^10 = 1024. */
+ ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
if (!params->aifs)
- ring->params.tx.aifs = 2;
+ ring->tx_params.aifs = 2;
return 0;
}
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:47:22.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.h 2006-04-27 21:47:52.000000000 +0200
@@ -714,6 +714,11 @@ struct rt2x00_usb{
struct workqueue_struct *workqueue;
/*
+ * RX ring parameters.
+ */
+ struct ieee80211_rx_status rx_params;
+
+ /*
* Alignment.
*/
u8 __pad1;
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:39:24.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:47:52.000000000 +0200
@@ -465,19 +465,9 @@ struct data_ring{
struct ieee80211_tx_queue_stats_data stats;
/*
- * Queue parameters.
- * We can safely put the following structures inside
- * the same union since a ring is either TX or RX
- * so they will never be used at the same time.
- * The ieee80211_rx_status structures is stored here, when
- * configuration changes have been passed to us, we can
- * change it to show the active configuration. And received
- * frames will always have the correct settings.
- */
- union {
- struct ieee80211_rx_status rx;
- struct ieee80211_tx_queue_params tx;
- } params;
+ * TX Queue parameters.
+ */
+ struct ieee80211_tx_queue_params tx_params;
/*
* Base address for data ring.
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 16/32] rt2x00: Make sure TX rings are empty when scanning
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 15118 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Improve the waiting when a skb buffer needs to be send
before the channel switch. This also makes sure no
pending packets are still on the TX ring while making the
channel switch.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:48:21.000000000 +0200
@@ -838,7 +838,6 @@ rt2400pci_txdone(void *data)
struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)ring->dev;
struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
struct data_entry *entry;
- struct skb_cb *cb;
struct txd *txd;
int tx_status;
int ack;
@@ -851,13 +850,6 @@ rt2400pci_txdone(void *data)
|| !rt2x00_get_field32(txd->word0, TXD_W0_VALID))
break;
- /*
- * Check if this frame was send for the scan routine.
- */
- cb = (struct skb_cb*)&entry->skb->cb;
- if (rt2x00pci->scan && cb->scan_complete)
- complete(&rt2x00pci->scan->completion);
-
ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
/*
@@ -896,6 +888,18 @@ rt2400pci_txdone(void *data)
rt2x00_ring_index_done_inc(ring);
} while (!rt2x00_ring_empty(ring));
+
+ /*
+ * Check if we are waiting on an empty queue
+ * to start scanning.
+ */
+ if (rt2x00pci->scan
+ && rt2x00_ring_empty(&rt2x00pci->tx)
+ && rt2x00_ring_empty(&rt2x00pci->atim)
+ && rt2x00_ring_empty(&rt2x00pci->prio)) {
+ rt2x00pci->scan->status = SCANNING_READY;
+ complete(&rt2x00pci->scan->completion);
+ }
}
static irqreturn_t
@@ -1517,6 +1521,14 @@ rt2400pci_stop(struct net_device *net_de
rt2x00_register_write(rt2x00pci, CSR8, reg);
/*
+ * Cancel scanning.
+ */
+ if (rt2x00pci->scan) {
+ rt2x00pci->scan->status = SCANNING_CANCELLED;
+ complete_all(&rt2x00pci->scan->completion);
+ }
+
+ /*
* Free DMA rings.
*/
rt2400pci_free_rings(rt2x00pci);
@@ -1564,35 +1576,23 @@ static void
rt2400pci_scan(void *data)
{
struct rt2x00_pci *rt2x00pci = data;
- struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
- struct skb_cb *cb;
if (unlikely(!rt2x00pci->scan))
return;
/*
- * Check if we have to send a packet before the
- * channel switch.
+ * Before we can start switch the channel for scanning
+ * we need to wait untill all TX rings are empty to
+ * guarentee that all frames are send on the correct channel.
*/
- if (rt2x00pci->scan->conf.skb) {
- cb = (struct skb_cb*)&rt2x00pci->scan->conf.skb->cb;
- cb->scan_complete = 1;
-
- if (rt2400pci_tx(net_dev, rt2x00pci->scan->conf.skb,
- rt2x00pci->scan->conf.tx_control))
- goto exit;
-
- /*
- * Wait for the frame to be correctly transmitted.
- */
+ if (rt2x00pci->scan->status != SCANNING_READY)
wait_for_completion(&rt2x00pci->scan->completion);
- }
/*
* Check if this scan has been cancelled while
* work was still scheduled.
*/
- if (rt2x00pci->scan->cancelled)
+ if (rt2x00pci->scan->status == SCANNING_CANCELLED)
goto exit;
/*
@@ -1633,9 +1633,24 @@ rt2400pci_passive_scan(struct net_device
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
+ if (rt2x00pci->scan)
+ return -EBUSY;
+
+ /*
+ * Allocate scanning structure to store scanning info.
+ */
rt2x00pci->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC);
if (!rt2x00pci->scan)
- return 0;
+ return -ENOMEM;
+
+ /*
+ * Check if we have to send a packet before the
+ * channel switch.
+ */
+ if (conf->skb) {
+ if (rt2400pci_tx(net_dev, conf->skb, conf->tx_control))
+ goto exit;
+ }
/*
* Initialize Scanning structure.
@@ -1646,14 +1661,21 @@ rt2400pci_passive_scan(struct net_device
rt2x00pci->scan->state = state;
- rt2x00pci->scan->cancelled = 0;
+ rt2x00pci->scan->status = 0;
/*
* Queue work.
*/
- queue_work(rt2x00pci->workqueue, &rt2x00pci->scan_work);
+ if (!queue_work(rt2x00pci->workqueue, &rt2x00pci->scan_work))
+ goto exit;
return 0;
+
+exit:
+ kfree(rt2x00pci->scan);
+ rt2x00pci->scan = NULL;
+
+ return -EIO;
}
static int
@@ -2207,11 +2229,6 @@ rt2400pci_uninitialize(struct net_device
rt2x00pci->csr_addr = NULL;
}
- if (rt2x00pci->scan) {
- rt2x00pci->scan->cancelled = 1;
- complete_all(&rt2x00pci->scan->completion);
- }
-
if (likely(rt2x00pci->workqueue)) {
flush_workqueue(rt2x00pci->workqueue);
destroy_workqueue(rt2x00pci->workqueue);
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:48:21.000000000 +0200
@@ -923,7 +923,6 @@ rt2500pci_txdone(void *data)
struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)ring->dev;
struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
struct data_entry *entry;
- struct skb_cb *cb;
struct txd *txd;
int tx_status;
int ack;
@@ -936,13 +935,6 @@ rt2500pci_txdone(void *data)
|| !rt2x00_get_field32(txd->word0, TXD_W0_VALID))
break;
- /*
- * Check if this frame was send for the scan routine.
- */
- cb = (struct skb_cb*)&entry->skb->cb;
- if (rt2x00pci->scan && cb->scan_complete)
- complete(&rt2x00pci->scan->completion);
-
ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
/*
@@ -981,6 +973,18 @@ rt2500pci_txdone(void *data)
rt2x00_ring_index_done_inc(ring);
} while (!rt2x00_ring_empty(ring));
+
+ /*
+ * Check if we are waiting on an empty queue
+ * to start scanning.
+ */
+ if (rt2x00pci->scan
+ && rt2x00_ring_empty(&rt2x00pci->tx)
+ && rt2x00_ring_empty(&rt2x00pci->atim)
+ && rt2x00_ring_empty(&rt2x00pci->prio)) {
+ rt2x00pci->scan->status = SCANNING_READY;
+ complete(&rt2x00pci->scan->completion);
+ }
}
static irqreturn_t
@@ -1630,6 +1634,14 @@ rt2500pci_stop(struct net_device *net_de
rt2x00_register_write(rt2x00pci, CSR8, reg);
/*
+ * Cancel scanning.
+ */
+ if (rt2x00pci->scan) {
+ rt2x00pci->scan->status = SCANNING_CANCELLED;
+ complete_all(&rt2x00pci->scan->completion);
+ }
+
+ /*
* Free DMA rings.
*/
rt2500pci_free_rings(rt2x00pci);
@@ -1677,35 +1689,23 @@ static void
rt2500pci_scan(void *data)
{
struct rt2x00_pci *rt2x00pci = data;
- struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
- struct skb_cb *cb;
if (unlikely(!rt2x00pci->scan))
return;
/*
- * Check if we have to send a packet before the
- * channel switch.
+ * Before we can start switch the channel for scanning
+ * we need to wait untill all TX rings are empty to
+ * guarentee that all frames are send on the correct channel.
*/
- if (rt2x00pci->scan->conf.skb) {
- cb = (struct skb_cb*)&rt2x00pci->scan->conf.skb->cb;
- cb->scan_complete = 1;
-
- if (rt2500pci_tx(net_dev, rt2x00pci->scan->conf.skb,
- rt2x00pci->scan->conf.tx_control))
- goto exit;
-
- /*
- * Wait for the frame to be correctly transmitted.
- */
+ if (rt2x00pci->scan->status != SCANNING_READY)
wait_for_completion(&rt2x00pci->scan->completion);
- }
/*
* Check if this scan has been cancelled while
* work was still scheduled.
*/
- if (rt2x00pci->scan->cancelled)
+ if (rt2x00pci->scan->status == SCANNING_CANCELLED)
goto exit;
/*
@@ -1742,9 +1742,24 @@ rt2500pci_passive_scan(struct net_device
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
+ if (rt2x00pci->scan)
+ return -EBUSY;
+
+ /*
+ * Allocate scanning structure to store scanning info.
+ */
rt2x00pci->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC);
if (!rt2x00pci->scan)
- return 0;
+ return -ENOMEM;
+
+ /*
+ * Check if we have to send a packet before the
+ * channel switch.
+ */
+ if (conf->skb) {
+ if (rt2500pci_tx(net_dev, conf->skb, conf->tx_control))
+ goto exit;
+ }
/*
* Initialize Scanning structure.
@@ -1755,14 +1770,21 @@ rt2500pci_passive_scan(struct net_device
rt2x00pci->scan->state = state;
- rt2x00pci->scan->cancelled = 0;
+ rt2x00pci->scan->status = 0;
/*
* Queue work.
*/
- queue_work(rt2x00pci->workqueue, &rt2x00pci->scan_work);
+ if (!queue_work(rt2x00pci->workqueue, &rt2x00pci->scan_work))
+ goto exit;
return 0;
+
+exit:
+ kfree(rt2x00pci->scan);
+ rt2x00pci->scan = NULL;
+
+ return -EIO;
}
static int
@@ -2505,20 +2527,15 @@ rt2500pci_uninitialize(struct net_device
rt2x00pci->csr_addr = NULL;
}
- if (rt2x00pci->scan) {
- rt2x00pci->scan->cancelled = 1;
- complete_all(&rt2x00pci->scan->completion);
- }
-
if (likely(rt2x00pci->workqueue)) {
flush_workqueue(rt2x00pci->workqueue);
destroy_workqueue(rt2x00pci->workqueue);
rt2x00pci->workqueue = NULL;
}
- kfree(rt2x00pci->hw.modes);
- rt2x00pci->hw.modes = NULL;
- }
+ kfree(rt2x00pci->hw.modes);
+ rt2x00pci->hw.modes = NULL;
+}
/*
* PCI driver handlers.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:48:21.000000000 +0200
@@ -769,7 +769,6 @@ rt2500usb_txdone(void *data)
struct net_device *net_dev = usb_get_intfdata(
rt2x00usb->usb_intf);
struct data_entry *entry;
- struct skb_cb *cb;
struct txd *txd;
int ack;
@@ -777,13 +776,6 @@ rt2500usb_txdone(void *data)
entry = rt2x00_get_data_entry_done(ring);
txd = entry->desc_addr;
- /*
- * Check if this frame was send for the scan routine.
- */
- cb = (struct skb_cb*)&entry->skb->cb;
- if (rt2x00usb->scan && cb->scan_complete)
- complete(&rt2x00usb->scan->completion);
-
ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
/*
@@ -815,6 +807,18 @@ rt2500usb_txdone(void *data)
rt2x00_ring_index_done_inc(entry->ring);
} while (!rt2x00_ring_empty(ring));
+
+ /*
+ * Check if we are waiting on an empty queue
+ * to start scanning.
+ */
+ if (rt2x00usb->scan
+ && rt2x00_ring_empty(&rt2x00usb->tx)
+ && rt2x00_ring_empty(&rt2x00usb->atim)
+ && rt2x00_ring_empty(&rt2x00usb->prio)) {
+ rt2x00usb->scan->status = SCANNING_READY;
+ complete(&rt2x00usb->scan->completion);
+ }
}
static void
@@ -1368,6 +1372,14 @@ rt2500usb_stop(struct net_device *net_de
rt2x00_register_write(rt2x00usb, MAC_CSR14, 0x2121);
/*
+ * Cancel scanning.
+ */
+ if (rt2x00usb->scan) {
+ rt2x00usb->scan->status = SCANNING_CANCELLED;
+ complete_all(&rt2x00usb->scan->completion);
+ }
+
+ /*
* Free DMA rings.
*/
rt2500usb_free_rings(rt2x00usb);
@@ -1414,36 +1426,23 @@ static void
rt2500usb_scan(void *data)
{
struct rt2x00_usb *rt2x00usb = data;
- struct net_device *net_dev =
- usb_get_intfdata(rt2x00usb->usb_intf);
- struct skb_cb *cb;
if (unlikely(!rt2x00usb->scan))
return;
/*
- * Check if we have to send a packet before the
- * channel switch.
+ * Before we can start switch the channel for scanning
+ * we need to wait untill all TX rings are empty to
+ * guarentee that all frames are send on the correct channel.
*/
- if (rt2x00usb->scan->conf.skb) {
- cb = (struct skb_cb*)&rt2x00usb->scan->conf.skb->cb;
- cb->scan_complete = 1;
-
- if (rt2500usb_tx(net_dev, rt2x00usb->scan->conf.skb,
- rt2x00usb->scan->conf.tx_control))
- goto exit;
-
- /*
- * Wait for the frame to be correctly transmitted.
- */
+ if (rt2x00usb->scan->status != SCANNING_READY)
wait_for_completion(&rt2x00usb->scan->completion);
- }
/*
* Check if this scan has been cancelled while
* work was still scheduled.
*/
- if (rt2x00usb->scan->cancelled)
+ if (rt2x00usb->scan->status == SCANNING_CANCELLED)
goto exit;
/*
@@ -1480,9 +1479,24 @@ rt2500usb_passive_scan(struct net_device
{
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
+ if (rt2x00usb->scan)
+ return -EBUSY;
+
+ /*
+ * Allocate scanning structure to store scanning info.
+ */
rt2x00usb->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC);
if (!rt2x00usb->scan)
- return 0;
+ return -ENOMEM;
+
+ /*
+ * Check if we have to send a packet before the
+ * channel switch.
+ */
+ if (conf->skb) {
+ if (rt2500usb_tx(net_dev, conf->skb, conf->tx_control))
+ goto exit;
+ }
/*
* Initialize Scanning structure.
@@ -1493,14 +1507,21 @@ rt2500usb_passive_scan(struct net_device
rt2x00usb->scan->state = state;
- rt2x00usb->scan->cancelled = 0;
+ rt2x00usb->scan->status = 0;
/*
* Queue work.
*/
- queue_work(rt2x00usb->workqueue, &rt2x00usb->scan_work);
+ if (!queue_work(rt2x00usb->workqueue, &rt2x00usb->scan_work))
+ goto exit;
return 0;
+
+exit:
+ kfree(rt2x00usb->scan);
+ rt2x00usb->scan = NULL;
+
+ return -EIO;
}
static int
@@ -2121,19 +2142,14 @@ rt2500usb_uninitialize(struct net_device
kfree(rt2x00usb->eeprom);
- if (rt2x00usb->scan) {
- rt2x00usb->scan->cancelled = 1;
- complete_all(&rt2x00usb->scan->completion);
- }
-
if (likely(rt2x00usb->workqueue)) {
flush_workqueue(rt2x00usb->workqueue);
destroy_workqueue(rt2x00usb->workqueue);
rt2x00usb->workqueue = NULL;
}
- kfree(rt2x00usb->hw.modes);
- rt2x00usb->hw.modes = NULL;
+ kfree(rt2x00usb->hw.modes);
+ rt2x00usb->hw.modes = NULL;
}
/*
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:48:21.000000000 +0200
@@ -428,15 +428,6 @@ rt2x00_rf(const struct _rt2x00_chip *chi
}
/*
- * Data to be placed in the skb->cb array.
- * therefor this structure may not exceed the 40 bytes.
- */
-struct skb_cb{
- int scan_complete;
-} __attribute__ ((packed));
-
-
-/*
* data_ring
* Data rings are used by the device to send and receive packets.
* The data_addr is the base address of the data memory.
@@ -589,7 +580,9 @@ struct scanning{
/*
* Flag to see if this scan has been cancelled.
*/
- short cancelled;
+ short status;
+#define SCANNING_READY 0x0001
+#define SCANNING_CANCELLED 0x0002
} __attribute__ ((packed));
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 17/32] rt2x00: Put net_device structure in data_ring
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 10234 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Change the structure stored in the data_ring structure
from the rt2x00_pci or rt2x00_usb to net_device.
This allows for better type checking, and the net_dev
is more often used in the interrupt handlers.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:48:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:49:08.000000000 +0200
@@ -760,10 +760,8 @@ rt2400pci_write_tx_desc(
static void
rt2400pci_beacondone(void *data)
{
- struct data_ring *ring = (struct data_ring*)data;
- struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)ring->dev;
- struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
- struct sk_buff *skb;
+ struct data_ring *ring = (struct data_ring*)data;
+ struct sk_buff *skb;
struct ieee80211_tx_control beacon;
memset(&beacon, 0x00, sizeof(beacon));
@@ -771,11 +769,11 @@ rt2400pci_beacondone(void *data)
/*
* TODO: What value should be passed as bss_idx?
*/
- skb = ieee80211_beacon_get(net_dev, 0, &beacon);
+ skb = ieee80211_beacon_get(ring->net_dev, 0, &beacon);
if (!skb)
return;
- rt2400pci_beacon_update(net_dev, skb, &beacon);
+ rt2400pci_beacon_update(ring->net_dev, skb, &beacon);
dev_kfree_skb_any(skb);
}
@@ -784,8 +782,8 @@ static void
rt2400pci_rxdone(void *data)
{
struct data_ring *ring = (struct data_ring*)data;
- struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)ring->dev;
- struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+ struct rt2x00_pci *rt2x00pci =
+ ieee80211_dev_hw_data(ring->net_dev);
struct data_entry *entry;
struct sk_buff *skb;
struct rxd *rxd;
@@ -817,7 +815,8 @@ rt2400pci_rxdone(void *data)
rt2x00pci->rx_params.ssi =
rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
- __ieee80211_rx(net_dev, skb, &rt2x00pci->rx_params);
+ __ieee80211_rx(ring->net_dev,
+ skb, &rt2x00pci->rx_params);
}
rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
@@ -835,8 +834,8 @@ static void
rt2400pci_txdone(void *data)
{
struct data_ring *ring = (struct data_ring*)data;
- struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)ring->dev;
- struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+ struct rt2x00_pci *rt2x00pci =
+ ieee80211_dev_hw_data(ring->net_dev);
struct data_entry *entry;
struct txd *txd;
int tx_status;
@@ -881,7 +880,8 @@ rt2400pci_txdone(void *data)
entry->tx_status.retry_count = rt2x00_get_field32(
txd->word0, TXD_W0_RETRY_COUNT);
- ieee80211_tx_status(net_dev, entry->skb, &entry->tx_status);
+ ieee80211_tx_status(ring->net_dev,
+ entry->skb, &entry->tx_status);
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
entry->skb = NULL;
@@ -975,7 +975,7 @@ rt2400pci_alloc_ring(
/*
*Set device structure.
*/
- ring->dev = rt2x00pci;
+ ring->net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
/*
* Initialize work structure for deferred work.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:48:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:49:08.000000000 +0200
@@ -834,10 +834,8 @@ rt2500pci_write_tx_desc(
static void
rt2500pci_beacondone(void *data)
{
- struct data_ring *ring = (struct data_ring*)data;
- struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)ring->dev;
- struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
- struct sk_buff *skb;
+ struct data_ring *ring = (struct data_ring*)data;
+ struct sk_buff *skb;
struct ieee80211_tx_control beacon;
memset(&beacon, 0x00, sizeof(beacon));
@@ -845,11 +843,11 @@ rt2500pci_beacondone(void *data)
/*
* TODO: What value should be passed as bss_idx?
*/
- skb = ieee80211_beacon_get(net_dev, 0, &beacon);
+ skb = ieee80211_beacon_get(ring->net_dev, 0, &beacon);
if (!skb)
return;
- rt2500pci_beacon_update(net_dev, skb, &beacon);
+ rt2500pci_beacon_update(ring->net_dev, skb, &beacon);
dev_kfree_skb_any(skb);
}
@@ -858,8 +856,8 @@ static void
rt2500pci_rxdone(void *data)
{
struct data_ring *ring = (struct data_ring*)data;
- struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)ring->dev;
- struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+ struct rt2x00_pci *rt2x00pci =
+ ieee80211_dev_hw_data(ring->net_dev);
struct data_entry *entry;
struct sk_buff *skb;
struct rxd *rxd;
@@ -899,7 +897,8 @@ rt2500pci_rxdone(void *data)
rt2x00pci->rx_params.ssi =
rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
- __ieee80211_rx(net_dev, skb, &rt2x00pci->rx_params);
+ __ieee80211_rx(ring->net_dev,
+ skb, &rt2x00pci->rx_params);
rssi_count++;
total_rssi += rt2x00pci->rx_params.ssi;
@@ -920,8 +919,8 @@ static void
rt2500pci_txdone(void *data)
{
struct data_ring *ring = (struct data_ring*)data;
- struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)ring->dev;
- struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+ struct rt2x00_pci *rt2x00pci =
+ ieee80211_dev_hw_data(ring->net_dev);
struct data_entry *entry;
struct txd *txd;
int tx_status;
@@ -966,7 +965,8 @@ rt2500pci_txdone(void *data)
entry->tx_status.retry_count = rt2x00_get_field32(
txd->word0, TXD_W0_RETRY_COUNT);
- ieee80211_tx_status(net_dev, entry->skb, &entry->tx_status);
+ ieee80211_tx_status(ring->net_dev,
+ entry->skb, &entry->tx_status);
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
entry->skb = NULL;
@@ -1060,7 +1060,7 @@ rt2500pci_alloc_ring(
/*
*Set device structure.
*/
- ring->dev = rt2x00pci;
+ ring->net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
/*
* Initialize work structure for deferred work.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:48:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:49:08.000000000 +0200
@@ -666,11 +666,8 @@ rt2500usb_write_tx_desc(
static void
rt2500usb_beacondone(void *data)
{
- struct data_ring *ring = (struct data_ring*)data;
- struct rt2x00_usb *rt2x00usb = (struct rt2x00_usb*)ring->dev;
- struct net_device *net_dev = usb_get_intfdata(
- rt2x00usb->usb_intf);
- struct sk_buff *skb;
+ struct data_ring *ring = (struct data_ring*)data;
+ struct sk_buff *skb;
struct ieee80211_tx_control beacon;
memset(&beacon, 0x00, sizeof(beacon));
@@ -678,11 +675,11 @@ rt2500usb_beacondone(void *data)
/*
* TODO: What value should be passed as bss_idx?
*/
- skb = ieee80211_beacon_get(net_dev, 0, &beacon);
+ skb = ieee80211_beacon_get(ring->net_dev, 0, &beacon);
if (!skb)
return;
- rt2500usb_beacon_update(net_dev, skb, &beacon);
+ rt2500usb_beacon_update(ring->net_dev, skb, &beacon);
dev_kfree_skb_any(skb);
}
@@ -691,9 +688,8 @@ static void
rt2500usb_rxdone(void *data)
{
struct data_ring *ring = (struct data_ring*)data;
- struct rt2x00_usb *rt2x00usb = (struct rt2x00_usb*)ring->dev;
- struct net_device *net_dev = usb_get_intfdata(
- rt2x00usb->usb_intf);
+ struct rt2x00_usb *rt2x00usb =
+ ieee80211_dev_hw_data(ring->net_dev);
struct data_entry *entry;
struct sk_buff *skb;
struct rxd *rxd;
@@ -743,7 +739,8 @@ rt2500usb_rxdone(void *data)
rt2x00usb->rx_params.ssi =
rt2x00_get_field32(rxd->word1, RXD_W1_RSSI);
- __ieee80211_rx(net_dev, skb, &rt2x00usb->rx_params);
+ __ieee80211_rx(ring->net_dev,
+ skb, &rt2x00usb->rx_params);
rssi_count++;
total_rssi += rt2x00usb->rx_params.ssi;
@@ -765,9 +762,8 @@ static void
rt2500usb_txdone(void *data)
{
struct data_ring *ring = (struct data_ring*)data;
- struct rt2x00_usb *rt2x00usb = (struct rt2x00_usb*)ring->dev;
- struct net_device *net_dev = usb_get_intfdata(
- rt2x00usb->usb_intf);
+ struct rt2x00_usb *rt2x00usb =
+ ieee80211_dev_hw_data(ring->net_dev);
struct data_entry *entry;
struct txd *txd;
int ack;
@@ -801,7 +797,8 @@ rt2500usb_txdone(void *data)
rt2x00_bbp_read(rt2x00usb, 0,
(u8*)&entry->tx_status.ack_signal);
- ieee80211_tx_status(net_dev, entry->skb, &entry->tx_status);
+ ieee80211_tx_status(ring->net_dev,
+ entry->skb, &entry->tx_status);
entry->skb = NULL;
@@ -825,7 +822,8 @@ static void
rt2500usb_interrupt(struct urb *urb, struct pt_regs *regs)
{
struct data_ring *ring = (struct data_ring*)urb->context;
- struct rt2x00_usb *rt2x00usb = (struct rt2x00_usb*)ring->dev;
+ struct rt2x00_usb *rt2x00usb =
+ ieee80211_dev_hw_data(ring->net_dev);
queue_work(rt2x00usb->workqueue, &ring->irq_work);
}
@@ -849,7 +847,7 @@ rt2500usb_alloc_ring(
/*
*Set device structure.
*/
- ring->dev = rt2x00usb;
+ ring->net_dev = usb_get_intfdata(rt2x00usb->usb_intf);
/*
* Initialize work structure for deferred work.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:48:21.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:49:08.000000000 +0200
@@ -436,9 +436,9 @@ rt2x00_rf(const struct _rt2x00_chip *chi
*/
struct data_ring{
/*
- * Pointer to device structure.
+ * net_device where this ring belongs to.
*/
- void *dev;
+ struct net_device *net_dev;
/*
* Work structure for bottom half interrupt handling.
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 18/32] rt2x00: Make sure device has reached requested state while suspend/resume
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 17190 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Add the *_set_state functions which makes sure
the device is switching state to awake or sleep.
Fix bad behaviour in the suspend routine,
and disable the radio before suspending.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:49:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:49:59.000000000 +0200
@@ -653,6 +653,44 @@ rt2400pci_link_tuner(struct rt2x00_pci *
}
/*
+ * Device state switch.
+ * This will put the device to sleep, or awake it.
+ */
+static int
+rt2400pci_set_state(struct rt2x00_pci *rt2x00pci, enum dev_state state)
+{
+ u32 reg;
+ int counter;
+ char put_to_sleep;
+
+ put_to_sleep = (state != STATE_AWAKE);
+
+ rt2x00_register_read(rt2x00pci, PWRCSR1, ®);
+ rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1);
+ rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state);
+ rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state);
+ rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
+ rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
+
+ /*
+ * Device is not guarenteed to be in the requested state yet.
+ * We must wait untill the register indicates that the
+ * device has entered the correct state.
+ */
+ for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
+ rt2x00_register_read(rt2x00pci, PWRCSR1, ®);
+ if ((rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE) == state)
+ && (rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE) == state))
+ return 0;
+ msleep(10);
+ }
+
+ NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+
+ return -EBUSY;
+}
+
+/*
* TX descriptor initialization
*/
static void
@@ -1190,6 +1228,9 @@ rt2400pci_init_registers(struct rt2x00_p
{
u32 reg;
+ if (rt2400pci_set_state(rt2x00pci, STATE_AWAKE))
+ return -EBUSY;
+
rt2x00_register_write(rt2x00pci, PWRCSR0, cpu_to_le32(0x3f3b3100));
rt2x00_register_write(rt2x00pci, PSCSR0, cpu_to_le32(0x00020002));
@@ -2342,57 +2383,42 @@ rt2400pci_remove(struct pci_dev *pci_dev
}
#ifdef CONFIG_PM
-static int rt2400pci_resume(struct pci_dev *pci_dev);
-
static int
rt2400pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
- int counter;
- u32 reg;
NOTICE("Going to sleep.\n");
- if (ieee80211_netif_oper(net_dev, NETIF_DETACH))
- return -EBUSY;
-
- rt2x00_register_read(rt2x00pci, PWRCSR1, ®);
- rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1);
- rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, 1);
- rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, 1);
- rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, 1);
- rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
-
/*
- * Device is not guarenteed to be asleep yet.
- * We must wait untill the register indicates
- * device has been correctly put to sleep.
+ * If radio was enabled, stop radio and
+ * set the resume flag to the radio will be enabled
+ * when resuming.
*/
- for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
- rt2x00_register_read(rt2x00pci, PWRCSR1, ®);
- if ((rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE) == 1)
- && (rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE) == 1))
- break;
- NOTICE("Waiting for device to sleep.\n");
- msleep(10);
+ if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+ if (net_dev->stop(net_dev))
+ return -EBUSY;
+ SET_FLAG(rt2x00pci, RADIO_RESUME);
}
- if (counter == REGISTER_BUSY_COUNT)
- goto exit;
-
- if (pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1)
- || pci_save_state(pci_dev)
- || pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)))
- goto exit;
-
- return 0;
+ /*
+ * Set device mode to sleep for power management.
+ */
+ if (rt2400pci_set_state(rt2x00pci, STATE_SLEEP))
+ return -EBUSY;
-exit:
- ERROR("Failed to suspend device.\n");
+ /*
+ * Uninitialize hardware.
+ */
+ rt2400pci_uninitialize(net_dev);
- rt2400pci_resume(pci_dev);
- return -EIO;
+ /*
+ * Disable PCI.
+ */
+ pci_save_state(pci_dev);
+ pci_disable_device(pci_dev);
+ return pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
}
static int
@@ -2400,25 +2426,44 @@ rt2400pci_resume(struct pci_dev *pci_dev
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
- u32 reg;
NOTICE("Waking up.\n");
+ /*
+ * Enable PCI.
+ */
if (pci_set_power_state(pci_dev, PCI_D0)
- || pci_restore_state(pci_dev)
- || pci_enable_wake(pci_dev, PCI_D0, 0)) {
+ || pci_enable_device(pci_dev)
+ || pci_restore_state(pci_dev)) {
ERROR("Failed to resume device.\n");
return -EIO;
}
- rt2x00_register_read(rt2x00pci, PWRCSR1, ®);
- rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1);
- rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, 3);
- rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, 3);
- rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, 0);
- rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
+ /*
+ * Initialize hardware.
+ */
+ if (rt2400pci_initialize(pci_dev, net_dev)) {
+ ERROR("Failed to initialize device.\n");
+ return -ENOMEM;
+ }
- return ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+ /*
+ * Set device mode to awake.
+ */
+ if (rt2400pci_set_state(rt2x00pci, STATE_AWAKE))
+ return -EBUSY;
+
+ /*
+ * Only enable radio when it was enabled
+ * when we suspended.
+ */
+ if (GET_FLAG(rt2x00pci, RADIO_RESUME)) {
+ if (net_dev->open(net_dev))
+ return -EBUSY;
+ CLEAR_FLAG(rt2x00pci, RADIO_RESUME);
+ }
+
+ return 0;
}
#endif /* CONFIG_PM */
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:49:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:49:59.000000000 +0200
@@ -706,6 +706,44 @@ dynamic_cca_tune:
}
/*
+ * Device state switch.
+ * This will put the device to sleep, or awake it.
+ */
+static int
+rt2500pci_set_state(struct rt2x00_pci *rt2x00pci, enum dev_state state)
+{
+ u32 reg;
+ int counter;
+ char put_to_sleep;
+
+ put_to_sleep = (state != STATE_AWAKE);
+
+ rt2x00_register_read(rt2x00pci, PWRCSR1, ®);
+ rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1);
+ rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state);
+ rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state);
+ rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
+ rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
+
+ /*
+ * Device is not guarenteed to be in the requested state yet.
+ * We must wait untill the register indicates that the
+ * device has entered the correct state.
+ */
+ for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
+ rt2x00_register_read(rt2x00pci, PWRCSR1, ®);
+ if ((rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE) == state)
+ && (rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE) == state))
+ return 0;
+ msleep(10);
+ }
+
+ NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+
+ return -EBUSY;
+}
+
+/*
* TX descriptor initialization
*/
static void
@@ -1272,6 +1310,9 @@ rt2500pci_init_registers(struct rt2x00_p
{
u32 reg;
+ if (rt2500pci_set_state(rt2x00pci, STATE_AWAKE))
+ return -EBUSY;
+
rt2x00_register_write(rt2x00pci, PWRCSR0, cpu_to_le32(0x3f3b3100));
rt2x00_register_write(rt2x00pci, PSCSR0, cpu_to_le32(0x00020002));
@@ -2636,57 +2677,42 @@ rt2500pci_remove(struct pci_dev *pci_dev
}
#ifdef CONFIG_PM
-static int rt2500pci_resume(struct pci_dev *pci_dev);
-
static int
rt2500pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
- int counter;
- u32 reg;
NOTICE("Going to sleep.\n");
- if (ieee80211_netif_oper(net_dev, NETIF_DETACH))
- return -EBUSY;
-
- rt2x00_register_read(rt2x00pci, PWRCSR1, ®);
- rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1);
- rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, 1);
- rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, 1);
- rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, 1);
- rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
-
/*
- * Device is not guarenteed to be asleep yet.
- * We must wait untill the register indicates
- * device has been correctly put to sleep.
+ * If radio was enabled, stop radio and
+ * set the resume flag to the radio will be enabled
+ * when resuming.
*/
- for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
- rt2x00_register_read(rt2x00pci, PWRCSR1, ®);
- if ((rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE) == 1)
- && (rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE) == 1))
- break;
- NOTICE("Waiting for device to sleep.\n");
- msleep(10);
+ if (GET_FLAG(rt2x00pci, RADIO_ENABLED)) {
+ if (net_dev->stop(net_dev))
+ return -EBUSY;
+ SET_FLAG(rt2x00pci, RADIO_RESUME);
}
- if (counter == REGISTER_BUSY_COUNT)
- goto exit;
-
- if (pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1)
- || pci_save_state(pci_dev)
- || pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)))
- goto exit;
-
- return 0;
+ /*
+ * Set device mode to sleep for power management.
+ */
+ if (rt2500pci_set_state(rt2x00pci, STATE_SLEEP))
+ return -EBUSY;
-exit:
- ERROR("Failed to suspend device.\n");
+ /*
+ * Uninitialize hardware.
+ */
+ rt2500pci_uninitialize(net_dev);
- rt2500pci_resume(pci_dev);
- return -EIO;
+ /*
+ * Disable PCI.
+ */
+ pci_save_state(pci_dev);
+ pci_disable_device(pci_dev);
+ return pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
}
static int
@@ -2694,25 +2720,44 @@ rt2500pci_resume(struct pci_dev *pci_dev
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
- u32 reg;
NOTICE("Waking up.\n");
+ /*
+ * Enable PCI.
+ */
if (pci_set_power_state(pci_dev, PCI_D0)
- || pci_restore_state(pci_dev)
- || pci_enable_wake(pci_dev, PCI_D0, 0)) {
+ || pci_enable_device(pci_dev)
+ || pci_restore_state(pci_dev)) {
ERROR("Failed to resume device.\n");
return -EIO;
}
- rt2x00_register_read(rt2x00pci, PWRCSR1, ®);
- rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1);
- rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, 3);
- rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, 3);
- rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, 0);
- rt2x00_register_write(rt2x00pci, PWRCSR1, reg);
+ /*
+ * Initialize hardware.
+ */
+ if (rt2500pci_initialize(pci_dev, net_dev)) {
+ ERROR("Failed to initialize device.\n");
+ return -ENOMEM;
+ }
- return ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+ /*
+ * Set device mode to awake.
+ */
+ if (rt2500pci_set_state(rt2x00pci, STATE_AWAKE))
+ return -EBUSY;
+
+ /*
+ * Only enable radio when it was enabled
+ * when we suspended.
+ */
+ if (GET_FLAG(rt2x00pci, RADIO_RESUME)) {
+ if (net_dev->open(net_dev))
+ return -EBUSY;
+ CLEAR_FLAG(rt2x00pci, RADIO_RESUME);
+ }
+
+ return 0;
}
#endif /* CONFIG_PM */
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:49:08.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:49:59.000000000 +0200
@@ -547,6 +547,46 @@ rt2500usb_link_tuner(struct rt2x00_usb *
}
/*
+ * Device state switch.
+ * This will put the device to sleep, or awake it.
+ */
+static int
+rt2500usb_set_state(struct rt2x00_usb *rt2x00usb, enum dev_state state)
+{
+ u16 reg;
+ int counter;
+ char put_to_sleep;
+
+ put_to_sleep = (state != STATE_AWAKE);
+
+ rt2x00_register_read(rt2x00usb, MAC_CSR17, ®);
+ rt2x00_set_field16_nb(®, MAC_CSR17_SET_STATE, 1);
+ rt2x00_set_field16_nb(®, MAC_CSR17_BBP_DESIRE_STATE, state);
+ rt2x00_set_field16_nb(®, MAC_CSR17_RF_DESIRE_STATE, state);
+ rt2x00_set_field16_nb(®, MAC_CSR17_PUT_TO_SLEEP, put_to_sleep);
+ rt2x00_register_write(rt2x00usb, MAC_CSR17, reg);
+
+ /*
+ * Device is not guarenteed to be in the requested state yet.
+ * We must wait untill the register indicates that the
+ * device has entered the correct state.
+ */
+ for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
+ rt2x00_register_read(rt2x00usb, MAC_CSR17, ®);
+ if ((rt2x00_get_field16_nb(
+ reg, MAC_CSR17_BBP_CURR_STATE) == state)
+ && (rt2x00_get_field16_nb(
+ reg, MAC_CSR17_RF_CURR_STATE) == state))
+ return 0;
+ msleep(10);
+ }
+
+ NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+
+ return -EBUSY;
+}
+
+/*
* TX descriptor initialization
*/
static void
@@ -1082,6 +1122,9 @@ rt2500usb_init_registers(struct rt2x00_u
{
u16 reg;
+ if (rt2500usb_set_state(rt2x00usb, STATE_AWAKE))
+ return -EBUSY;
+
rt2x00_vendor_request(rt2x00usb, USB_DEVICE_MODE,
USB_VENDOR_REQUEST_OUT, USB_MODE_TEST, 0x00, NULL, 0);
rt2x00_vendor_request(rt2x00usb, USB_SINGLE_WRITE,
@@ -2221,44 +2264,42 @@ rt2500usb_disconnect(struct usb_interfac
}
#ifdef CONFIG_PM
-static int rt2500usb_resume(struct usb_interface *usb_intf);
-
static int
rt2500usb_suspend(struct usb_interface *usb_intf, pm_message_t state)
{
struct net_device *net_dev = usb_get_intfdata(usb_intf);
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
- int counter;
- u16 reg;
NOTICE("Going to sleep.\n");
- if (ieee80211_netif_oper(net_dev, NETIF_DETACH))
+ /*
+ * If radio was enabled, stop radio and
+ * set the resume flag to the radio will be enabled
+ * when resuming.
+ */
+ if (GET_FLAG(rt2x00usb, RADIO_ENABLED)) {
+ if (net_dev->stop(net_dev))
+ return -EBUSY;
+ SET_FLAG(rt2x00usb, RADIO_RESUME);
+ }
+
+ /*
+ * Set device mode to sleep for power management.
+ */
+ if (rt2500usb_set_state(rt2x00usb, STATE_SLEEP))
return -EBUSY;
- rt2x00_register_read(rt2x00usb, MAC_CSR17, ®);
- rt2x00_set_field16_nb(®, MAC_CSR17_SET_STATE, 1);
- rt2x00_set_field16_nb(®, MAC_CSR17_BBP_DESIRE_STATE, 1);
- rt2x00_set_field16_nb(®, MAC_CSR17_RF_DESIRE_STATE, 1);
- rt2x00_set_field16_nb(®, MAC_CSR17_PUT_TO_SLEEP, 1);
- rt2x00_register_write(rt2x00usb, MAC_CSR17, reg);
+ /*
+ * Uninitialize hardware.
+ */
+ rt2500usb_uninitialize(net_dev);
/*
- * Device is not guarenteed to be asleep yet.
- * We must wait untill the register indicates
- * device has been correctly put to sleep.
+ * Decrease usbdev refcount.
*/
- for (counter = 0; counter < REGISTER_BUSY_COUNT; counter++) {
- rt2x00_register_read(rt2x00usb, MAC_CSR17, ®);
- if ((rt2x00_get_field16_nb(reg, MAC_CSR17_BBP_CURR_STATE) == 1)
- && (rt2x00_get_field16_nb(reg, MAC_CSR17_RF_CURR_STATE) == 1))
- return 0;
- NOTICE("Waiting for device to sleep.\n");
- msleep(10);
- }
+ usb_put_dev(interface_to_usbdev(usb_intf));
- rt2500usb_resume(usb_intf);
- return -EIO;
+ return 0;
}
static int
@@ -2266,18 +2307,39 @@ rt2500usb_resume(struct usb_interface *u
{
struct net_device *net_dev = usb_get_intfdata(usb_intf);
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
- u16 reg;
NOTICE("Waking up.\n");
- rt2x00_register_read(rt2x00usb, MAC_CSR17, ®);
- rt2x00_set_field16_nb(®, MAC_CSR17_SET_STATE, 1);
- rt2x00_set_field16_nb(®, MAC_CSR17_BBP_DESIRE_STATE, 3);
- rt2x00_set_field16_nb(®, MAC_CSR17_RF_DESIRE_STATE, 3);
- rt2x00_set_field16_nb(®, MAC_CSR17_PUT_TO_SLEEP, 0);
- rt2x00_register_write(rt2x00usb, MAC_CSR17, reg);
+ /*
+ * Increase usbdev refcount.
+ */
+ usb_get_dev(interface_to_usbdev(usb_intf));
- return ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+ /*
+ * Initialize hardware.
+ */
+ if (rt2500usb_initialize(usb_intf, net_dev)) {
+ ERROR("Failed to initialize device.\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * Set device mode to awake.
+ */
+ if (rt2500usb_set_state(rt2x00usb, STATE_AWAKE))
+ return -EBUSY;
+
+ /*
+ * Only enable radio when it was enabled
+ * when we suspended.
+ */
+ if (GET_FLAG(rt2x00usb, RADIO_RESUME)) {
+ if (net_dev->open(net_dev))
+ return -EBUSY;
+ CLEAR_FLAG(rt2x00usb, RADIO_RESUME);
+ }
+
+ return 0;
}
#endif /* CONFIG_PM */
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 19/32] rt2x00: Fix panics in interrupt handlers
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 3624 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
Fix panics when the interrupt handlers are being
run while the ring is empty.
During the interrupt handling break the loop
correctly when an error has been detected,
more work is being done after the loop.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:50:36.000000000 +0200
@@ -844,7 +844,7 @@ rt2400pci_rxdone(void *data)
&& !rt2x00_get_field32(rxd->word0, RXD_W0_PHYSICAL_ERROR)) {
skb = dev_alloc_skb(size + NET_IP_ALIGN);
if (!skb)
- return;
+ break;
skb_reserve(skb, NET_IP_ALIGN);
@@ -859,7 +859,7 @@ rt2400pci_rxdone(void *data)
rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
- rt2x00_ring_index_inc(&rt2x00pci->rx);
+ rt2x00_ring_index_inc(ring);
}
/*
@@ -879,7 +879,7 @@ rt2400pci_txdone(void *data)
int tx_status;
int ack;
- do {
+ while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
txd = entry->desc_addr;
@@ -925,7 +925,7 @@ rt2400pci_txdone(void *data)
entry->skb = NULL;
rt2x00_ring_index_done_inc(ring);
- } while (!rt2x00_ring_empty(ring));
+ }
/*
* Check if we are waiting on an empty queue
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:50:36.000000000 +0200
@@ -926,7 +926,7 @@ rt2500pci_rxdone(void *data)
&& !rt2x00_get_field32(rxd->word0, RXD_W0_PHYSICAL_ERROR)) {
skb = dev_alloc_skb(size + NET_IP_ALIGN);
if (!skb)
- return;
+ break;
skb_reserve(skb, NET_IP_ALIGN);
@@ -943,7 +943,7 @@ rt2500pci_rxdone(void *data)
}
rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
- rt2x00_ring_index_inc(&rt2x00pci->rx);
+ rt2x00_ring_index_inc(ring);
}
/*
@@ -964,7 +964,7 @@ rt2500pci_txdone(void *data)
int tx_status;
int ack;
- do {
+ while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
txd = entry->desc_addr;
@@ -1010,7 +1010,7 @@ rt2500pci_txdone(void *data)
entry->skb = NULL;
rt2x00_ring_index_done_inc(ring);
- } while (!rt2x00_ring_empty(ring));
+ }
/*
* Check if we are waiting on an empty queue
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:49:59.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:50:36.000000000 +0200
@@ -808,7 +808,7 @@ rt2500usb_txdone(void *data)
struct txd *txd;
int ack;
- do {
+ while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
txd = entry->desc_addr;
@@ -843,7 +843,7 @@ rt2500usb_txdone(void *data)
entry->skb = NULL;
rt2x00_ring_index_done_inc(entry->ring);
- } while (!rt2x00_ring_empty(ring));
+ }
/*
* Check if we are waiting on an empty queue
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox