Re: [PATCH 1/2] remove CONFIG_HAVE_ARCH_DEV_ALLOC_SKB

2006-07-26 Thread Christoph Hellwig
On Mon, Jul 24, 2006 at 03:44:15PM -0700, Roland Dreier wrote:
> > skbuff.h has an #ifndef CONFIG_HAVE_ARCH_DEV_ALLOC_SKB to allow
> > architectures to reimplement __dev_alloc_skb.  It's not set on any
> > architecture and now that we have an architecture-overrideable
> > NET_SKB_PAD there is not point at all to have one either.
> 
> I missed this when hch first posted it, sorry.
> 
> But my impression was that the intent of the config option was to let
> Xen hook __dev_alloc_skb() to allocate special receive skbs to handle
> their page-flipping virtual network device.  Which goes beyond
> NET_SKB_PAD.
> 
> So the real question is about Xen hooks I guess -- and given where the
> rest of Xen is, it probably does make sense to go ahead and strip this
> out.

If xen wants to use something else then dev_alloc_skb in their virtual
network driver that's totall fine.  No need to override the definiton of
dev_alloc_skb for that, though.  They can add their own xen_alloc_skb or
opencode the operation they want for it.

Note that overriding dev_alloc_skb is not just utterly pointless but would
even be harmfull in the case they'd finally add pci support for non-dom0
domains and used normaly NIC drivers in there.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Who maintains the website ?

2006-07-26 Thread Christophe Devriese
I would like to have a VLAN page on the main page, so that I can update it
a bit with relevant info, and then include the link to the external site
as it's basically a "here is a patch, here is a usage" page, while an
explanation of the different stuff would be nice (such as the forwarding
path, the vlan acceleration, where packets go ...).

On Wed, Jul 26, 2006 at 08:41:58AM +1200, Ian McDonald wrote:
> On 7/26/06, Christophe Devriese <[EMAIL PROTECTED]> wrote:
> >The http://linux-net.osdl.org/index.php/Main_Page website I mean.
> >
> It's a Wiki so anybody can alter content on the website. The exception
> to this is that particular page - the main page. If you want something
> altered on that particular page send email to one of the sysops.
> -- 
> Ian McDonald
> Web: http://wand.net.nz/~iam4
> Blog: http://imcdnzl.blogspot.com
> WAND Network Research Group
> Department of Computer Science
> University of Waikato
> New Zealand
> -
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to [EMAIL PROTECTED]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
---
Christophe Devriese   EURiD
Network Adminstrator / Developer
[EMAIL PROTECTED]
 http://www.eth1.org --

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Who maintains the website ?

2006-07-26 Thread Ian McDonald

On 7/26/06, Christophe Devriese <[EMAIL PROTECTED]> wrote:

I would like to have a VLAN page on the main page, so that I can update it
a bit with relevant info, and then include the link to the external site
as it's basically a "here is a patch, here is a usage" page, while an
explanation of the different stuff would be nice (such as the forwarding
path, the vlan acceleration, where packets go ...).


What is the external page? If it doesn't exist consider putting the
content on the wiki itself so others can improve it.

Prepare the Wiki page including linking in the existing VLAN link on
the front page and then we can see what can be done. You can create a
VLAN page without having to change the wiki front page initially...

If it looks good then Stephen, or myself or others can change the front page.
--
Ian McDonald
Web: http://wand.net.nz/~iam4
Blog: http://imcdnzl.blogspot.com
WAND Network Research Group
Department of Computer Science
University of Waikato
New Zealand
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[4/4] kevent: poll/select() notifications. Timer notifications.

2006-07-26 Thread Evgeniy Polyakov

This patch includes generic poll/select and timer notifications.

kevent_poll works simialr to epoll and has the same issues (callback
is invoked not from internal state machine of the caller, but through
process awake).

Timer notifications can be used for fine grained per-process time 
management, since iteractive timers are very inconveniently to use, 
and they are limited.

Signed-off-by: Evgeniy Polyakov <[EMAIL PROTECTED]>

diff --git a/kernel/kevent/kevent_poll.c b/kernel/kevent/kevent_poll.c
new file mode 100644
index 000..4950e7c
--- /dev/null
+++ b/kernel/kevent/kevent_poll.c
@@ -0,0 +1,223 @@
+/*
+ * kevent_poll.c
+ * 
+ * 2006 Copyright (c) Evgeniy Polyakov <[EMAIL PROTECTED]>
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static kmem_cache_t *kevent_poll_container_cache;
+static kmem_cache_t *kevent_poll_priv_cache;
+
+struct kevent_poll_ctl
+{
+   struct poll_table_structpt;
+   struct kevent   *k;
+};
+
+struct kevent_poll_wait_container
+{
+   struct list_headcontainer_entry;
+   wait_queue_head_t   *whead;
+   wait_queue_twait;
+   struct kevent   *k;
+};
+
+struct kevent_poll_private
+{
+   struct list_headcontainer_list;
+   spinlock_t  container_lock;
+};
+
+static int kevent_poll_enqueue(struct kevent *k);
+static int kevent_poll_dequeue(struct kevent *k);
+static int kevent_poll_callback(struct kevent *k);
+
+static int kevent_poll_wait_callback(wait_queue_t *wait, 
+   unsigned mode, int sync, void *key)
+{
+   struct kevent_poll_wait_container *cont = 
+   container_of(wait, struct kevent_poll_wait_container, wait);
+   struct kevent *k = cont->k;
+   struct file *file = k->st->origin;
+   unsigned long flags;
+   u32 revents, event;
+
+   revents = file->f_op->poll(file, NULL);
+   spin_lock_irqsave(&k->lock, flags);
+   event = k->event.event;
+   spin_unlock_irqrestore(&k->lock, flags);
+
+   kevent_storage_ready(k->st, NULL, revents);
+
+   return 0;
+}
+
+static void kevent_poll_qproc(struct file *file, wait_queue_head_t *whead, 
+   struct poll_table_struct *poll_table)
+{
+   struct kevent *k = 
+   container_of(poll_table, struct kevent_poll_ctl, pt)->k;
+   struct kevent_poll_private *priv = k->priv;
+   struct kevent_poll_wait_container *cont;
+   unsigned long flags;
+
+   cont = kmem_cache_alloc(kevent_poll_container_cache, SLAB_KERNEL);
+   if (!cont) {
+   kevent_break(k);
+   return;
+   }
+   
+   cont->k = k;
+   init_waitqueue_func_entry(&cont->wait, kevent_poll_wait_callback);
+   cont->whead = whead;
+
+   spin_lock_irqsave(&priv->container_lock, flags);
+   list_add_tail(&cont->container_entry, &priv->container_list);
+   spin_unlock_irqrestore(&priv->container_lock, flags);
+
+   add_wait_queue(whead, &cont->wait);
+}
+
+static int kevent_poll_enqueue(struct kevent *k)
+{
+   struct file *file;
+   int err, ready = 0;
+   unsigned int revents;
+   struct kevent_poll_ctl ctl;
+   struct kevent_poll_private *priv;
+
+   file = fget(k->event.id.raw[0]);
+   if (!file)
+   return -ENODEV;
+
+   err = -EINVAL;
+   if (!file->f_op || !file->f_op->poll)
+   goto err_out_fput;
+
+   err = -ENOMEM;
+   priv = kmem_cache_alloc(kevent_poll_priv_cache, SLAB_KERNEL);
+   if (!priv)
+   goto err_out_fput;
+
+   spin_lock_init(&priv->container_lock);
+   INIT_LIST_HEAD(&priv->container_list);
+
+   k->priv = priv;
+
+   ctl.k = k;
+   init_poll_funcptr(&ctl.pt, &kevent_poll_qproc);
+
+   err = kevent_storage_enqueue(&file->st, k);
+   if (err)
+   goto err_out_free;
+
+   revents = file->f_op->poll(file, &ctl.pt);
+   if (revents & k->event.event) {
+   ready = 1;
+   kevent_poll_dequeue(k);
+   }
+   
+   return ready;
+
+err_out_free:
+   kmem_cache_free(kevent_poll_priv_cache, priv);
+err_out_fput:
+   fput(file);
+   return err;
+}
+
+static int kevent_poll_dequeue(struct kevent *k)
+{
+   struct file *file = k->st->origin;
+   struct kevent_po

[3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Evgeniy Polyakov

This patch includes asynchronous propagation of file's data into VFS
cache and aio_sendfile() implementation.
Network aio_sendfile() works lazily - it asynchronously populates pages
into the VFS cache (which can be used for various tricks with adaptive
readahead) and then uses usual ->sendfile() callback.

Signed-off-by: Evgeniy Polyakov <[EMAIL PROTECTED]>

diff --git a/fs/bio.c b/fs/bio.c
index 6a0b9ad..a3ee530 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -119,7 +119,7 @@ void bio_free(struct bio *bio, struct bi
 /*
  * default destructor for a bio allocated with bio_alloc_bioset()
  */
-static void bio_fs_destructor(struct bio *bio)
+void bio_fs_destructor(struct bio *bio)
 {
bio_free(bio, fs_bio_set);
 }
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 04af9c4..295fce9 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -685,6 +685,7 @@ ext2_writepages(struct address_space *ma
 }
 
 struct address_space_operations ext2_aops = {
+   .get_block  = ext2_get_block,
.readpage   = ext2_readpage,
.readpages  = ext2_readpages,
.writepage  = ext2_writepage,
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 2edd7ee..e44f5ad 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1700,6 +1700,7 @@ static int ext3_journalled_set_page_dirt
 }
 
 static struct address_space_operations ext3_ordered_aops = {
+   .get_block  = ext3_get_block,
.readpage   = ext3_readpage,
.readpages  = ext3_readpages,
.writepage  = ext3_ordered_writepage,
diff --git a/fs/file_table.c b/fs/file_table.c
index bcea199..8759479 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -113,6 +113,9 @@ struct file *get_empty_filp(void)
if (security_file_alloc(f))
goto fail_sec;
 
+#ifdef CONFIG_KEVENT_POLL
+   kevent_storage_init(f, &f->st);
+#endif
tsk = current;
INIT_LIST_HEAD(&f->f_u.fu_list);
atomic_set(&f->f_count, 1);
@@ -160,6 +163,9 @@ void fastcall __fput(struct file *file)
might_sleep();
 
fsnotify_close(file);
+#ifdef CONFIG_KEVENT_POLL
+   kevent_storage_fini(&file->st);
+#endif
/*
 * The function eventpoll_release() should be the first called
 * in the file cleanup chain.
diff --git a/fs/inode.c b/fs/inode.c
index 3a2446a..0493935 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -22,6 +22,7 @@ #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
 /*
@@ -166,12 +167,18 @@ #endif
}
memset(&inode->u, 0, sizeof(inode->u));
inode->i_mapping = mapping;
+#if defined CONFIG_KEVENT
+   kevent_storage_init(inode, &inode->st);
+#endif
}
return inode;
 }
 
 void destroy_inode(struct inode *inode) 
 {
+#if defined CONFIG_KEVENT_INODE || defined CONFIG_KEVENT_SOCKET
+   kevent_storage_fini(&inode->st);
+#endif
BUG_ON(inode_has_buffers(inode));
security_inode_free(inode);
if (inode->i_sb->s_op->destroy_inode)
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 9857e50..578 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2997,6 +2997,7 @@ int reiserfs_setattr(struct dentry *dent
 }
 
 struct address_space_operations reiserfs_address_space_operations = {
+   .get_block = reiserfs_get_block,
.writepage = reiserfs_writepage,
.readpage = reiserfs_readpage,
.readpages = reiserfs_readpages,

diff --git a/include/linux/fs.h b/include/linux/fs.h
index ecc8c2c..248f6a1 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -236,6 +236,9 @@ #include 
 #include 
 #include 
 #include 
+#ifdef CONFIG_KEVENT
+#include 
+#endif
 
 struct hd_geometry;
 struct iovec;
@@ -348,6 +351,8 @@ struct address_space;
 struct writeback_control;
 
 struct address_space_operations {
+   int  (*get_block)(struct inode *inode, sector_t iblock,
+   struct buffer_head *bh_result, int create);
int (*writepage)(struct page *page, struct writeback_control *wbc);
int (*readpage)(struct file *, struct page *);
void (*sync_page)(struct page *);
@@ -526,6 +531,10 @@ #ifdef CONFIG_INOTIFY
struct mutexinotify_mutex;  /* protects the watches list */
 #endif
 
+#ifdef CONFIG_KEVENT_INODE
+   struct kevent_storage   st;
+#endif
+
unsigned long   i_state;
unsigned long   dirtied_when;   /* jiffies of first dirtying */
 
@@ -659,6 +668,9 @@ #ifdef CONFIG_EPOLL
struct list_headf_ep_links;
spinlock_t  f_ep_lock;
 #endif /* #ifdef CONFIG_EPOLL */
+#ifdef CONFIG_KEVENT_POLL
+   struct kevent_storage   st;
+#endif
struct address_space*f_mapping;
 };
 extern spinlock_t files_lock;
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index cc5dec7..0acc8db 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -15,6 +15,7 @@ 

[0/4] kevent: generic event processing subsystem.

2006-07-26 Thread Evgeniy Polyakov


Kevent subsystem incorporates several AIO/kqueue design notes and ideas.
Kevent can be used both for edge and level notifications. It supports
socket notifications (accept, send, recv), network AIO (aio_send(),
aio_recv() and aio_sendfile()), inode notifications (create/remove),
generic poll()/select() notifications and timer notifications.

There are several object in the kevent system:
storage - each source of events (socket, inode, timer, aio, anything) has
structure kevent_storage incorporated into it, which is basically a list
of registered interests for this source of events.
user - it is abstraction which holds all requested kevents. It is
similar to FreeBSD's kqueue.
kevent - set of interests for given source of events or storage.

When kevent is queued into storage, it will live there until removed by
kevent_dequeue(). When some activity is noticed in given storage, it
scans it's kevent_storage->list for kevents which match activity event.
If kevents are found and they are not already in the
kevent_user->ready_list, they will be added there at the end.

ioctl(WAIT) (or appropriate syscall) will wait until either requested
number of kevents are ready or timeout elapsed or at least one kevent is
ready, it's behaviour depends on parameters.

It is possible to have one-shot kevents, which are automatically removed
when are ready.

Any event can be added/removed/modified by ioctl or special controlling
syscall.

Network AIO is based on kevent and works as usual kevent storage on top
of inode.
When new socket is created it is associated with that inode and when
some activity is detected appropriate notifications are generated and
kevent_naio_callback() is called.
When new kevent is being registered, network AIO ->enqueue() callback
simply marks itself like usual socket event watcher. It also locks
physical userspace pages in memory and stores appropriate pointers in
private kevent structure. I have not created additional DMA memory
allocation methods, like Ulrich described in his article, so I handle it
inside NAIO which has some overhead (I posted get_user_pages()
sclability graph some time ago).
Network AIO callback gets pointers to userspace pages and tries to copy
data from receiving skb queue into them using protocol specific
callback. This callback is very similar to ->recvmsg(), so they could
share a lot in future (as far as I recall it worked only with hardware
capable to do checksumming, I'm a bit lazy).

Both network and aio implementation work on top of hooks inside
appropriate state machines, but not as repeated call design (curect AIO) 
or special thread (SGI AIO). AIO work was stopped, since I was unable to 
achieve the same speed as synchronous read 
(maximum speeds were 2Gb/sec vs. 2.1 GB/sec for aio and sync IO accordingly
when reading data from the cache).
Network aio_sendfile() works lazily - it asynchronously populates pages
into the VFS cache (which can be used for various tricks with adaptive
readahead) and then uses usual ->sendfile() callback.

I have not created an interface for userspace events (like Solaris), 
since right now I do not see it's usefullness, but if there is
requirements for that it is quite easy with kevents.

Patches currently include ifdefs and kevent can be disabled in config,
when things are settled that can be removed.

1. kevent homepage.
http://tservice.net.ru/~s0mbre/old/?section=projects&item=kevent

2. network aio homepage.
http://tservice.net.ru/~s0mbre/old/?section=projects&item=naio

3. LWN.net published a very good article about kevent.
http://lwn.net/Articles/172844/

Thank you.

Signed-off-by: Evgeniy Polyakov <[EMAIL PROTECTED]>

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[2/4] kevent: network AIO, socket notifications.

2006-07-26 Thread Evgeniy Polyakov

This patchset includes socket notifications and network asynchronous IO.
Network AIO is based on kevent and works as usual kevent storage on top
of inode.

When new socket is created it is associated with inode (to save some space,
since inode already has kevent_storage embedded) and when some activity is 
detected appropriate notifications are generated and kevent_naio_callback() 
is called.

When new kevent is being registered, network AIO ->enqueue() callback
simply marks itself like usual socket event watcher. It also locks
physical userspace pages in memory and stores appropriate pointers in
private kevent structure. I have not created additional DMA memory
allocation methods, like Ulrich described in his article, so I handle it
inside NAIO which has some overhead (I posted get_user_pages()
sclability graph some time ago). New set of syscalls to allocate DMAable
memory is in TODO.

Network AIO callback gets pointers to userspace pages and tries to copy
data from receiving skb queue into them using protocol specific
callback. This callback is very similar to ->recvmsg(), so they could
share a lot in future (as far as I recall it worked only with hardware
capable to do checksumming, I'm a bit lazy, it is in TODO)

Signed-off-by: Evgeniy Polyakov <[EMAIL PROTECTED]>


diff --git a/kernel/kevent/kevent_socket.c b/kernel/kevent/kevent_socket.c
new file mode 100644
index 000..c230aaa
--- /dev/null
+++ b/kernel/kevent/kevent_socket.c
@@ -0,0 +1,125 @@
+/*
+ * kevent_socket.c
+ * 
+ * 2006 Copyright (c) Evgeniy Polyakov <[EMAIL PROTECTED]>
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+static int kevent_socket_callback(struct kevent *k)
+{
+   struct inode *inode = k->st->origin;
+   struct sock *sk = SOCKET_I(inode)->sk;
+   int rmem;
+   
+   if (k->event.event & KEVENT_SOCKET_RECV) {
+   int ret = 0;
+   
+   if ((rmem = atomic_read(&sk->sk_rmem_alloc)) > 0 || 
+   !skb_queue_empty(&sk->sk_receive_queue))
+   ret = 1;
+   if (sk->sk_shutdown & RCV_SHUTDOWN)
+   ret = 1;
+   if (ret)
+   return ret;
+   }
+   if ((k->event.event & KEVENT_SOCKET_ACCEPT) && 
+   (!reqsk_queue_empty(&inet_csk(sk)->icsk_accept_queue) || 
+   
reqsk_queue_len_young(&inet_csk(sk)->icsk_accept_queue))) {
+   k->event.ret_data[1] = 
reqsk_queue_len(&inet_csk(sk)->icsk_accept_queue);
+   return 1;
+   }
+
+   return 0;
+}
+
+int kevent_socket_enqueue(struct kevent *k)
+{
+   struct file *file;
+   struct inode *inode;
+   int err, fput_needed;
+
+   file = fget_light(k->event.id.raw[0], &fput_needed);
+   if (!file)
+   return -ENODEV;
+
+   err = -EINVAL;
+   if (!file->f_dentry || !file->f_dentry->d_inode)
+   goto err_out_fput;
+
+   inode = igrab(file->f_dentry->d_inode);
+   if (!inode)
+   goto err_out_fput;
+
+   err = kevent_storage_enqueue(&inode->st, k);
+   if (err)
+   goto err_out_iput;
+
+   err = k->callback(k);
+   if (err)
+   goto err_out_dequeue;
+
+   fput_light(file, fput_needed);
+   return err;
+
+err_out_dequeue:
+   kevent_storage_dequeue(k->st, k);
+err_out_iput:
+   iput(inode);
+err_out_fput:
+   fput_light(file, fput_needed);
+   return err;
+}
+
+int kevent_socket_dequeue(struct kevent *k)
+{
+   struct inode *inode = k->st->origin;
+
+   kevent_storage_dequeue(k->st, k);
+   iput(inode);
+
+   return 0;
+}
+
+int kevent_init_socket(struct kevent *k)
+{
+   k->enqueue = &kevent_socket_enqueue;
+   k->dequeue = &kevent_socket_dequeue;
+   k->callback = &kevent_socket_callback;
+   return 0;
+}
+
+void kevent_socket_notify(struct sock *sk, u32 event)
+{
+   if (sk->sk_socket && !test_and_set_bit(SOCK_ASYNC_INUSE, 
&sk->sk_flags)) {
+   kevent_storage_ready(&SOCK_INODE(sk->sk_socket)->st, NULL, 
event);
+   sock_reset_flag(sk, SOCK_A

Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Christoph Hellwig
On Wed, Jul 26, 2006 at 01:18:15PM +0400, Evgeniy Polyakov wrote:
> 
> This patch includes asynchronous propagation of file's data into VFS
> cache and aio_sendfile() implementation.
> Network aio_sendfile() works lazily - it asynchronously populates pages
> into the VFS cache (which can be used for various tricks with adaptive
> readahead) and then uses usual ->sendfile() callback.
> 
> Signed-off-by: Evgeniy Polyakov <[EMAIL PROTECTED]>
> 
> diff --git a/fs/bio.c b/fs/bio.c
> index 6a0b9ad..a3ee530 100644
> --- a/fs/bio.c
> +++ b/fs/bio.c
> @@ -119,7 +119,7 @@ void bio_free(struct bio *bio, struct bi
>  /*
>   * default destructor for a bio allocated with bio_alloc_bioset()
>   */
> -static void bio_fs_destructor(struct bio *bio)
> +void bio_fs_destructor(struct bio *bio)
>  {
>   bio_free(bio, fs_bio_set);
>  }
> diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
> index 04af9c4..295fce9 100644
> --- a/fs/ext2/inode.c
> +++ b/fs/ext2/inode.c
> @@ -685,6 +685,7 @@ ext2_writepages(struct address_space *ma
>  }
>  
>  struct address_space_operations ext2_aops = {
> + .get_block  = ext2_get_block,

No way in hell.  For whatever you do please provide a interface at
the readpage/writepage/sendfile/etc abstraction layer.  get_block is
nothing that can be exposed to the common code.

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Christoph Hellwig
On Wed, Jul 26, 2006 at 01:18:15PM +0400, Evgeniy Polyakov wrote:
> 
> This patch includes asynchronous propagation of file's data into VFS
> cache and aio_sendfile() implementation.
> Network aio_sendfile() works lazily - it asynchronously populates pages
> into the VFS cache (which can be used for various tricks with adaptive
> readahead) and then uses usual ->sendfile() callback.

And please don't base this on sendfile.  Please make the splice infrastructure
aynschronous without duplicating all the code but rather make the existing
code aynch and the existing synchronous call wait on them to finish, similar
to how we handle async/sync direct I/O.  And to be honest, I don't think
adding all this code is acceptable if it can't replace the existing aio
code while keeping the interface.  So while you interface looks pretty
sane the implementation needs a lot of work still :)

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Who maintains the website ?

2006-07-26 Thread Christophe Devriese
I have created the http://linux-net.osdl.org/index.php/VLAN page. What do
you think ?

Regards,

Christophe

On Wed, Jul 26, 2006 at 08:52:52PM +1200, Ian McDonald wrote:
> On 7/26/06, Christophe Devriese <[EMAIL PROTECTED]> wrote:
> >I would like to have a VLAN page on the main page, so that I can update it
> >a bit with relevant info, and then include the link to the external site
> >as it's basically a "here is a patch, here is a usage" page, while an
> >explanation of the different stuff would be nice (such as the forwarding
> >path, the vlan acceleration, where packets go ...).
> >
> What is the external page? If it doesn't exist consider putting the
> content on the wiki itself so others can improve it.
> 
> Prepare the Wiki page including linking in the existing VLAN link on
> the front page and then we can see what can be done. You can create a
> VLAN page without having to change the wiki front page initially...
> 
> If it looks good then Stephen, or myself or others can change the front 
> page.
> -- 
> Ian McDonald
> Web: http://wand.net.nz/~iam4
> Blog: http://imcdnzl.blogspot.com
> WAND Network Research Group
> Department of Computer Science
> University of Waikato
> New Zealand
> -
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to [EMAIL PROTECTED]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
---
Christophe Devriese   EURiD
Network Adminstrator / Developer
[EMAIL PROTECTED]
 http://www.eth1.org --

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Evgeniy Polyakov
On Wed, Jul 26, 2006 at 11:00:13AM +0100, Christoph Hellwig ([EMAIL PROTECTED]) 
wrote:
> >  struct address_space_operations ext2_aops = {
> > +   .get_block  = ext2_get_block,
> 
> No way in hell.  For whatever you do please provide a interface at
> the readpage/writepage/sendfile/etc abstraction layer.  get_block is
> nothing that can be exposed to the common code.

Compare this with sync read methods - all they do is exactly the same
operations with low-level blocks, which are combined into nice exported
function, so there is _no_ readpage layer - it calls only one function
which works with blocks.

I would create the same, i.e. async_readpage(), which called kevent's
functions and processed low-level blocks, just like sync code does, but
that requires kevent to be deep part of the FS tree.

So I prefer to have
kevent/some_function_which_works_with_blocks_and_kevents() 

instead of
fs/some_function_which_works_with_block_and_kevents()
kevent/call_that_function_like_all_readpage_callbacks_do().

So it is not a technical problem, but political one.
-- 
Evgeniy Polyakov
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread David Miller
From: Christoph Hellwig <[EMAIL PROTECTED]>
Date: Wed, 26 Jul 2006 11:04:31 +0100

> And to be honest, I don't think adding all this code is acceptable
> if it can't replace the existing aio code while keeping the
> interface.  So while you interface looks pretty sane the
> implementation needs a lot of work still :)

Networking and disk AIO have significantly different needs.

Therefore, I really don't see it as reasonable to expect
a merge of these two things.  It doesn't make any sense.

I do agree that this stuff needs to be cleaned up, all the get_block
etc. hacks have to be pulled out and abstracted properly.  That part
of the kevent changes are indeed still crap :)
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Christoph Hellwig
On Wed, Jul 26, 2006 at 03:12:47AM -0700, David Miller wrote:
> From: Christoph Hellwig <[EMAIL PROTECTED]>
> Date: Wed, 26 Jul 2006 11:04:31 +0100
> 
> > And to be honest, I don't think adding all this code is acceptable
> > if it can't replace the existing aio code while keeping the
> > interface.  So while you interface looks pretty sane the
> > implementation needs a lot of work still :)
> 
> Networking and disk AIO have significantly different needs.
> 
> Therefore, I really don't see it as reasonable to expect
> a merge of these two things.  It doesn't make any sense.

I'm not sure about that.  The current aio interface isn't exactly nice
for disk I/O either.  I'm more than happy to have a discussion about
that aspect.

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Christoph Hellwig
On Wed, Jul 26, 2006 at 02:08:49PM +0400, Evgeniy Polyakov wrote:
> On Wed, Jul 26, 2006 at 11:00:13AM +0100, Christoph Hellwig ([EMAIL 
> PROTECTED]) wrote:
> > >  struct address_space_operations ext2_aops = {
> > > + .get_block  = ext2_get_block,
> > 
> > No way in hell.  For whatever you do please provide a interface at
> > the readpage/writepage/sendfile/etc abstraction layer.  get_block is
> > nothing that can be exposed to the common code.
> 
> Compare this with sync read methods - all they do is exactly the same
> operations with low-level blocks, which are combined into nice exported
> function, so there is _no_ readpage layer - it calls only one function
> which works with blocks.

No.  The abtraction layer there is ->readpage(s).  _A_ common implementation
works with a get_block callback from the filesystem, but there are various
others.  We've been there before, up to mid-2.3.x we had a get_block inode
operation and we got rid of it because it is the wrong abstraction.

> So it is not a technical problem, but political one.

It's a technical problem, and it's called get you abstractions right.  And
ontop of that a political one and that's called get your abstraction coherent.
If you managed to argue all of us into accept that get_block is the right
abstraction (and as I mentioned above that's technically not true) you'd
still have the burden to update everything to use the same abstraction.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Evgeniy Polyakov
On Wed, Jul 26, 2006 at 11:04:31AM +0100, Christoph Hellwig ([EMAIL PROTECTED]) 
wrote:
> On Wed, Jul 26, 2006 at 01:18:15PM +0400, Evgeniy Polyakov wrote:
> > 
> > This patch includes asynchronous propagation of file's data into VFS
> > cache and aio_sendfile() implementation.
> > Network aio_sendfile() works lazily - it asynchronously populates pages
> > into the VFS cache (which can be used for various tricks with adaptive
> > readahead) and then uses usual ->sendfile() callback.
> 
> And please don't base this on sendfile.  Please make the splice infrastructure
> aynschronous without duplicating all the code but rather make the existing
> code aynch and the existing synchronous call wait on them to finish, similar
> to how we handle async/sync direct I/O.  And to be honest, I don't think
> adding all this code is acceptable if it can't replace the existing aio
> code while keeping the interface.  So while you interface looks pretty
> sane the implementation needs a lot of work still :)

Kevent was created quite before splice and friends, so I used what there
were :)

I stopped to work on AIO, since neither existing, nor mine
implementation were able to outperform sync speeds (one of the major problems
in my implementation is get_user_pages() overhead, which can be
completely eliminated with physical memory allocation being done in
advance in userspace, like Ulrich described).
My personal opinion on existing AIO is that it is not the right design.
Benjamin LaHaise agree with me (if I understood him right), but he
failed to move AIO outside repeated-call model (2.4 had state machine
based one, and out-of-the tree 2.6 patches have that design too).
In theory existing AIO (with all posix userspace API) can be replaced
with kevent (it will even take less space), but I would present it as a
TODO item, since kevent itself has nothing to do with AIO.

Kevent is a generic event processing mechanism, AIO, network AIO and all
others are just kernel users of it's functionality.

-- 
Evgeniy Polyakov
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Evgeniy Polyakov
On Wed, Jul 26, 2006 at 11:13:56AM +0100, Christoph Hellwig ([EMAIL PROTECTED]) 
wrote:
> On Wed, Jul 26, 2006 at 02:08:49PM +0400, Evgeniy Polyakov wrote:
> > On Wed, Jul 26, 2006 at 11:00:13AM +0100, Christoph Hellwig ([EMAIL 
> > PROTECTED]) wrote:
> > > >  struct address_space_operations ext2_aops = {
> > > > +   .get_block  = ext2_get_block,
> > > 
> > > No way in hell.  For whatever you do please provide a interface at
> > > the readpage/writepage/sendfile/etc abstraction layer.  get_block is
> > > nothing that can be exposed to the common code.
> > 
> > Compare this with sync read methods - all they do is exactly the same
> > operations with low-level blocks, which are combined into nice exported
> > function, so there is _no_ readpage layer - it calls only one function
> > which works with blocks.
> 
> No.  The abtraction layer there is ->readpage(s).  _A_ common implementation
> works with a get_block callback from the filesystem, but there are various
> others.  We've been there before, up to mid-2.3.x we had a get_block inode
> operation and we got rid of it because it is the wrong abstraction.

Well, kevent can work not from it's own, but with common implementation,
which works with get_block(). No problem here.

> > So it is not a technical problem, but political one.
> 
> It's a technical problem, and it's called get you abstractions right.  And
> ontop of that a political one and that's called get your abstraction coherent.
> If you managed to argue all of us into accept that get_block is the right
> abstraction (and as I mentioned above that's technically not true) you'd
> still have the burden to update everything to use the same abstraction.

Christoph, I completely understand your point of view.
There is absolutely no technical problem to create common async implementation,
and place it where existing sync lives and call from readpage() level.

It just requires to allow to change BIO callbacks instead of default
one, and (probably) event sync readpage can be used.

-- 
Evgeniy Polyakov
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Christoph Hellwig
On Wed, Jul 26, 2006 at 02:19:21PM +0400, Evgeniy Polyakov wrote:
> I stopped to work on AIO, since neither existing, nor mine
> implementation were able to outperform sync speeds (one of the major problems
> in my implementation is get_user_pages() overhead, which can be
> completely eliminated with physical memory allocation being done in
> advance in userspace, like Ulrich described).
> My personal opinion on existing AIO is that it is not the right design.
> Benjamin LaHaise agree with me (if I understood him right),

I completely agree with that aswell.

> but he
> failed to move AIO outside repeated-call model (2.4 had state machine
> based one, and out-of-the tree 2.6 patches have that design too).
> In theory existing AIO (with all posix userspace API) can be replaced
> with kevent (it will even take less space), but I would present it as a
> TODO item, since kevent itself has nothing to do with AIO.

And replacing the existing aio code is exactly we I want you to do.  We
can't keep adding more and more code without getting rid of old mess forever.

And yes, the asynchronous pagecache population bit in your patchkit has a lot
to do with aio.  It's same variant of aio done right (or at least less bad).

I suspect the right way to go ahead is to drop that bit for now (it's the
by far worst code in the patchkit anyway) and then we can redo it later to
not get abstractions wrong and duplicate lots of code but also replace the
aio code.  I don't expect you to do that alone, you'll probably need quite
a bit help from us FS and VM people.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [1/4] kevent: core files.

2006-07-26 Thread Andrew Morton
On Wed, 26 Jul 2006 13:18:15 +0400
Evgeniy Polyakov <[EMAIL PROTECTED]> wrote:

> +static int kevent_ctl_process(struct file *file, 
> + struct kevent_user_control *ctl, void __user *arg)
> +{
> + int err;
> + struct kevent_user *u = file->private_data;
> +
> + if (!u)
> + return -EINVAL;
> +
> + switch (ctl->cmd) {
> + case KEVENT_CTL_ADD:
> + err = kevent_user_ctl_add(u, ctl, 
> + arg+sizeof(struct kevent_user_control));
> + break;
> + case KEVENT_CTL_REMOVE:
> + err = kevent_user_ctl_remove(u, ctl, 
> + arg+sizeof(struct kevent_user_control));
> + break;
> + case KEVENT_CTL_MODIFY:
> + err = kevent_user_ctl_modify(u, ctl, 
> + arg+sizeof(struct kevent_user_control));
> + break;
> + case KEVENT_CTL_WAIT:
> + err = kevent_user_wait(file, u, ctl, arg);
> + break;
> + case KEVENT_CTL_INIT:
> + err = kevent_ctl_init();
> + default:
> + err = -EINVAL;
> + break;
> + }
> +
> + return err;
> +}

Please indent the body of the switch one tabstop to the left.

> +asmlinkage long sys_kevent_ctl(int fd, void __user *arg)
> +{
> + int err, fput_needed;
> + struct kevent_user_control ctl;
> + struct file *file;
> +
> + if (copy_from_user(&ctl, arg, sizeof(struct kevent_user_control)))
> + return -EINVAL;
> +
> + if (ctl.cmd == KEVENT_CTL_INIT)
> + return kevent_ctl_init();
> +
> + file = fget_light(fd, &fput_needed);
> + if (!file)
> + return -ENODEV;
> +
> + err = kevent_ctl_process(file, &ctl, arg);
> +
> + fput_light(file, fput_needed);
> + return err;
> +}

If the user passes this an fd which was obtained via means other than
kevent_ctl_init(), the kernel will explode.  Do

if (file->f_fop != &kevent_user_fops)
return -EINVAL;

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [1/4] kevent: core files.

2006-07-26 Thread Evgeniy Polyakov
On Wed, Jul 26, 2006 at 03:31:05AM -0700, Andrew Morton ([EMAIL PROTECTED]) 
wrote:
> Please indent the body of the switch one tabstop to the left.
..
> If the user passes this an fd which was obtained via means other than
> kevent_ctl_init(), the kernel will explode.  Do
> 
>   if (file->f_fop != &kevent_user_fops)
>   return -EINVAL;

Thanks, I will implement both.

-- 
Evgeniy Polyakov
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [1/4] kevent: core files.

2006-07-26 Thread Evgeniy Polyakov
On Wed, Jul 26, 2006 at 01:18:15PM +0400, Evgeniy Polyakov ([EMAIL PROTECTED]) 
wrote:
> +struct kevent *kevent_alloc(gfp_t mask)
> +{
> + struct kevent *k;
> + 
> + if (kevent_cache)
> + k = kmem_cache_alloc(kevent_cache, mask);
> + else
> + k = kzalloc(sizeof(struct kevent), mask);
> +
> + return k;
> +}
> +

Sorry for that.
It is fixed already to always use cache, but I forget to commit that
change before I created pachset.

-- 
Evgeniy Polyakov
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/3] add netdev_alloc_skb

2006-07-26 Thread Christoph Hellwig
Add a dev_alloc_skb variant that takes a struct net_device * paramater.
For now that paramater is unused, but I'll use it to allocate the skb
from node-local memory in a follow-up patch.  Also there have been some
other plans mentioned on the list that can use it.


Signed-off-by: Christoph Hellwig <[EMAIL PROTECTED]>

Index: linux-2.6/include/linux/skbuff.h
===
--- linux-2.6.orig/include/linux/skbuff.h   2006-07-26 10:58:43.0 
+0200
+++ linux-2.6/include/linux/skbuff.h2006-07-26 11:10:23.0 +0200
@@ -1104,6 +1104,28 @@
return __dev_alloc_skb(length, GFP_ATOMIC);
 }
 
+extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
+   unsigned int length, gfp_t gfp_mask);
+
+/**
+ * netdev_alloc_skb - allocate an skbuff for rx on a specific device
+ * @dev: network device to receive on
+ * @length: length to allocate
+ *
+ * Allocate a new &sk_buff and assign it a usage count of one. The
+ * buffer has unspecified headroom built in. Users should allocate
+ * the headroom they think they need without accounting for the
+ * built in space. The built in space is used for optimisations.
+ *
+ * %NULL is returned in there is no free memory. Although this function
+ * allocates memory it can be called from an interrupt.
+ */
+static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
+   unsigned int length)
+{
+   return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
+}
+
 /**
  * skb_cow - copy header of skb when it is required
  * @skb: buffer to cow
Index: linux-2.6/net/core/skbuff.c
===
--- linux-2.6.orig/net/core/skbuff.c2006-07-26 10:58:43.0 +0200
+++ linux-2.6/net/core/skbuff.c 2006-07-26 11:10:40.0 +0200
@@ -256,6 +256,29 @@
goto out;
 }
 
+/**
+ * __netdev_alloc_skb - allocate an skbuff for rx on a specific device
+ * @dev: network device to receive on
+ * @length: length to allocate
+ * @gfp_mask: get_free_pages mask, passed to alloc_skb
+ *
+ * Allocate a new &sk_buff and assign it a usage count of one. The
+ * buffer has unspecified headroom built in. Users should allocate
+ * the headroom they think they need without accounting for the
+ * built in space. The built in space is used for optimisations.
+ *
+ * %NULL is returned in there is no free memory.
+ */
+struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
+   unsigned int length, gfp_t gfp_mask)
+{
+   struct sk_buff *skb;
+
+   skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
+   if (likely(skb))
+   skb_reserve(skb, NET_SKB_PAD);
+   return skb;
+}
 
 static void skb_drop_list(struct sk_buff **listp)
 {
@@ -2042,6 +2065,7 @@
 EXPORT_SYMBOL(kfree_skb);
 EXPORT_SYMBOL(__pskb_pull_tail);
 EXPORT_SYMBOL(__alloc_skb);
+EXPORT_SYMBOL(__netdev_alloc_skb);
 EXPORT_SYMBOL(pskb_copy);
 EXPORT_SYMBOL(pskb_expand_head);
 EXPORT_SYMBOL(skb_checksum);
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/3] deprecate dev_alloc_skb

2006-07-26 Thread Christoph Hellwig

Signed-off-by: Christoph Hellwig <[EMAIL PROTECTED]>

Index: linux-2.6/include/linux/skbuff.h
===
--- linux-2.6.orig/include/linux/skbuff.h   2006-07-26 12:06:12.0 
+0200
+++ linux-2.6/include/linux/skbuff.h2006-07-26 12:08:49.0 +0200
@@ -1077,9 +1077,13 @@
  * built in space. The built in space is used for optimisations.
  *
  * %NULL is returned in there is no free memory.
+ *
+ * NOTE: Do not use this function.  Network driver want to use
+ * netdev_alloc_skb for the receive path, everyone else wants plain
+ * alloc_skb.
  */
-static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
- gfp_t gfp_mask)
+static inline struct sk_buff * __deprecated
+__dev_alloc_skb(unsigned int length, gfp_t gfp_mask)
 {
struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
if (likely(skb))
@@ -1098,8 +1102,13 @@
  *
  * %NULL is returned in there is no free memory. Although this function
  * allocates memory it can be called from an interrupt.
+ *
+ * NOTE: Do not use this function.  Network driver want to use
+ * netdev_alloc_skb for the receive path, everyone else wants plain
+ * alloc_skb.
  */
-static inline struct sk_buff *dev_alloc_skb(unsigned int length)
+static inline struct sk_buff * __deprecated
+dev_alloc_skb(unsigned int length)
 {
return __dev_alloc_skb(length, GFP_ATOMIC);
 }
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[IPROUTE2]: documentation bug fix on mirred

2006-07-26 Thread Jamal Hadi Salim

Stephen,

Heres another on top of the others i sent. If you get the time, can
update your git tree with these patches?
If you are planning to make a release soon, please ping me - I have at
least one more patch that i need to work on.

cheers,
jamal

Update mirred usage to fix a bug noticed by
Andy Furniss <[EMAIL PROTECTED]>
Also make it a little more readable.

---
commit e2e0fac73a39bc6878f93cd7698f4c823ef85546
tree cfdad9a98fa1925237128b307d8ddd77b86a09a7
parent a067bda2c7c9972ad77ac174830a245896d18897
author Jamal Hadi Salim <[EMAIL PROTECTED]> Wed, 26 Jul 2006 07:45:25 -0400
committer Jamal Hadi Salim <[EMAIL PROTECTED](none)> Wed, 26 Jul 2006 07:45:25 
-0400

 doc/actions/mirred-usage |   59 ++
 1 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/doc/actions/mirred-usage b/doc/actions/mirred-usage
index 03ea9d0..2622c43 100644
--- a/doc/actions/mirred-usage
+++ b/doc/actions/mirred-usage
@@ -1,7 +1,11 @@
 
 Very funky action. I do plan to add to a few more things to it
 This is the basic stuff. Idea borrowed from the way ethernet switches
-mirror and redirect packets.
+mirror and redirect packets. The main difference with say a vannila
+ethernet switch is that you can use u32 classifier to select a
+flow to be mirrored. High end switches typically can select based
+on more than just a port (eg a 5 tuple classifier). They may also be
+capable of redirecting.
 
 Usage: 
 
@@ -12,11 +16,15 @@ ACTION := 
 INDEX is the specific policy instance id
 DEVICENAME is the devicename
 
-Direction Ingress is not supported at the moment. It will be in the
-future as well as mirror/redirecting to a socket.
+Direction:
+- Ingress is not supported at the moment. It will be in the
+future as well as mirror/redirecting to a socket. 
 
-Mirroring essentially takes a copy of the packet whereas redirecting
-steals the packet and redirects to specified destination.
+Action:
+- Mirror takes a copy of the packet and sends it to specified
+dev ("port" in ethernet switch/bridging terminology)
+- redirect
+steals the packet and redirects to specified destination dev.
 
 What NOT to do if you dont want your machine to crash:
 --
@@ -34,7 +42,7 @@ In the future if there are easy ways to 
 without affecting other packets not interested in this feature
 I will add them. At the moment that is not clear.
 
-Some examples of bad things to do:
+Some examples of bad things NOT to do:
 1) redirecting eth0 to eth0
 2) eth0->eth1-> eth0
 3) eth0->lo-> eth1-> eth0
@@ -43,7 +51,7 @@ B) Do not redirect from one IFB device t
 Remember that IFB is a very specialized case of packet redirecting
 device. Instead of redirecting it puts packets at the exact spot
 on the stack it found them from.
-This bad policy will actually not crash your machine but your 
+Redirecting from ifbX->ifbY will actually not crash your machine but your 
 packets will all be dropped (this is much simpler to detect
 and resolve and is only affecting users of ifb as opposed to the
 whole stack).
@@ -52,24 +60,28 @@ In the case of A) the problem has to do 
 for the devices queue lock and in the second case for the transmit lock.
 
 Some examples:
-
+-
 
 1) Mirror all packets arriving on eth0 to be sent out on eth1.
 You may have a sniffer or some accounting box hooked up on eth1.
  
-tc qdisc add dev lo eth0
+---
+tc qdisc add dev eth0 ingress
 tc filter add dev eth0 parent : protocol ip prio 10 u32 \
 match u32 0 0 flowid 1:2 action mirred egress mirror dev eth1
+---
 
 If you replace "mirror" with "redirect" then not a copy but rather
 the original packet is sent to eth1.
 
 2) Host A is hooked  up to us on eth0
 
-tc qdisc add dev lo ingress
 # redirect all packets arriving on ingress of lo to eth0
+---
+tc qdisc add dev lo ingress
 tc filter add dev lo parent : protocol ip prio 10 u32 \
 match u32 0 0 flowid 1:2 action mirred egress redirect dev eth0
+---
 
 On host A start a tcpdump on interface connecting to us.
 
@@ -88,27 +100,28 @@ stack (i.e ping would work).
 3) Even more funky example:
 
 #
-#allow 1 out 10 packets to randomly make it to the 
+#allow 1 out 10 packets on ingress of lo to randomly make it to the 
 # host A (Randomness uses the netrand generator)
 #
+---
 tc filter add dev lo parent : protocol ip prio 10 u32 \
 match u32 0 0 flowid 1:2 \
 action drop random determ ok 10\
 action mirred egress mirror dev eth0
+---
 
 4)
-# for packets coming from 10.0.0.9:
-#Redirect packets on egress, if exceeding a 100Kbps rate,
-# to eth1 
+# for packets from 10.0.0.9 going out on eth0 (could be local 
+# IP or something # we are forwarding) - 
+# if exceeding a 100Kbps rate, then redirect to eth1 
 #
 
+---
 tc qdisc add dev eth0 handle 1:0 root prio
-
 tc filter add dev eth0 parent 1:0 protocol ip prio 6 u32 \
 match ip src 10.0.0.9/32 flowid 1:16 \
 action police rate 100kbit burst 90k ok \
 action mirred egress mir

Re: Is the qla3xxx driver in the mainline?

2006-07-26 Thread Michael Tokarev
Albert Lee wrote:
[]
> (I am curious to have some performance comparison of
> qla3xxx + open iscsi v.s. qla4xxx + on board TOE/iscsi.)

On wich card?  I've been told that IPS4010 for example
isn't supported by qla3xxx.

BTW, I found qla4xxx (on IPS4010) performs noticeable
worse than open-iscsi stack on top of tigon (non-jumbo-
frames-capable) GigE NIC (on an eserver xSeries 346
machine).

/mjt
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] ip multicast route bug fix

2006-07-26 Thread Alexey Kuznetsov
HellO!

> I like this.  However, since the cloned skb is either discarded in case
> of error, or queued in which case the caller discards its reference right
> away, wouldn't it be simpler to just do this?

Well, if we wanted just to cheat those checking tools, it is nice.
But if we want clarity, it does not look so sweet.

I _loved_ the tricks with skb refcnt a lot (look into netlink.c :-))
until the day, when pskb_expand_head() and Co appeared. It is so much
more handy and so hates refcnt.

I would seriously review all the uses of refcnt and leave it internal
to skbuff.c and use it externally only in a few places,
where it is obviously safe (MSG_PEEK, mostly) 

Alexey
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Bonding active-backup issue.

2006-07-26 Thread Christophe Devriese
If I implement a patch taking an unused flag and implementing IFF_SILENT,
in order to fix incorrect bonding active-backup behavior, will it get
accepted ?

If not, what can I do ?

-- 
---
Christophe Devriese   EURiD
Network Adminstrator / Developer
[EMAIL PROTECTED]
 http://www.eth1.org --

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Avi Kivity

David Miller wrote:


From: Christoph Hellwig <[EMAIL PROTECTED]>
Date: Wed, 26 Jul 2006 11:04:31 +0100

> And to be honest, I don't think adding all this code is acceptable
> if it can't replace the existing aio code while keeping the
> interface.  So while you interface looks pretty sane the
> implementation needs a lot of work still :)

Networking and disk AIO have significantly different needs.

Surely, there needs to be a unified polling interface to support single 
threaded designs.


--
error compiling committee.c: too many arguments to function

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Ulrich Drepper
Christoph Hellwig wrote:
>> My personal opinion on existing AIO is that it is not the right design.
>> Benjamin LaHaise agree with me (if I understood him right),
> 
> I completely agree with that aswell.

I agree, too, but the current code is not the last of the line.  Suparna
has a st of patches which make the current kernel aio code work much
better and especially make it really usable to implement POSIX AIO.

In Ottawa we were talking about submitting it and Suparna will.  We just
thought about a little longer timeframe.  I guess it could be
accelerated since he mostly has the patch done.  But I don't know her
schedule.

Important here is, don't base any decision on the current aio
implementation.

-- 
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖



signature.asc
Description: OpenPGP digital signature


Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Badari Pulavarty

Ulrich Drepper wrote:

Christoph Hellwig wrote:
  

My personal opinion on existing AIO is that it is not the right design.
Benjamin LaHaise agree with me (if I understood him right),
  

I completely agree with that aswell.



I agree, too, but the current code is not the last of the line.  Suparna
has a st of patches which make the current kernel aio code work much
better and especially make it really usable to implement POSIX AIO.

In Ottawa we were talking about submitting it and Suparna will.  We just
thought about a little longer timeframe.  I guess it could be
accelerated since he mostly has the patch done.  But I don't know her
schedule.

Important here is, don't base any decision on the current aio
implementation.
  

Ulrich,

Suparna mentioned your interest in making POSIX glibc aio work with 
kernel-aio at OLS.
We thought taking a re-look at the (kernel side) work BULL did, would be 
a nice starting
point. I re-based those patches to 2.6.18-rc2 and sent it to Zach Brown 
for review before

sending them out to list.

These patches does NOT make AIO any cleaner. All they do is add 
functionality to support

POSIX AIO easier. These are

[ PATCH 1/3 ]  Adding signal notification for event completion

[ PATCH 2/3 ]  lio (listio) completion semantics

[ PATCH 3/3 ] cancel_fd support

Suparna explained these in the following article:

http://lwn.net/Articles/148755/

If you think, this is a reasonable direction/approach for the kernel and 
you would take care
of glibc side of things - I can spend time on these patches, getting 
them to reasonable shape

and push for inclusion.

Please let us know.

Thanks,
Badari


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH dscape] d80211: Switch d80211.h to IEEE80211_ style names

2006-07-26 Thread Jiri Benc
On Mon, 24 Jul 2006 23:02:50 -0700, Michael Wu wrote:
> These two attached patches also roll in a switch to MAC_FMT and MAC_ARG, and 
> use IEEE80211_DATA_LEN when possible. Otherwise, it's the same as before 
> except split into two patches.

Nice, thanks a lot.

One more thing (hopefully the last one), could you try to keep lines
under 80 characters? I understand that with such long identifiers it is
not always possible (it dramatically reduces readability of the code if
you try to force the limit in every case) but there are some places
where it is feasible.

Also, when changing a line that is indented with spaces instead of tab
characters, it's nice to convert that spaces to tabs. That's not a
requirement, though; I will modify the patch if you won't do it.

Thanks,

 Jiri

-- 
Jiri Benc
SUSE Labs
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH dscape] d80211: Switch d80211.h to IEEE80211_ style names

2006-07-26 Thread Michael Wu
On Wednesday 26 July 2006 09:32, Jiri Benc wrote:
> One more thing (hopefully the last one), could you try to keep lines
> under 80 characters? I understand that with such long identifiers it is
> not always possible (it dramatically reduces readability of the code if
> you try to force the limit in every case) but there are some places
> where it is feasible.
>
Ah, yeah, that was a problem..

> Also, when changing a line that is indented with spaces instead of tab
> characters, it's nice to convert that spaces to tabs. That's not a
> requirement, though; I will modify the patch if you won't do it.
>
I still want to convert d80211_mgmt.h. Once that's done, I'll look through for 
those tabs/spaces & long lines formatting issues. I won't mind if you start 
fixing some of those issues now, however. :)

-Michael Wu


pgpGADwr1ceTl.pgp
Description: PGP signature


Re: [PATCH dscape] d80211: Switch d80211.h to IEEE80211_ style names

2006-07-26 Thread Jiri Benc
On Wed, 26 Jul 2006 09:43:55 -0700, Michael Wu wrote:
> I still want to convert d80211_mgmt.h. Once that's done, I'll look through 
> for 
> those tabs/spaces & long lines formatting issues. I won't mind if you start 
> fixing some of those issues now, however. :)

I just meant running some s/ {8}/\t/ on your patch :-)

Also, I don't want to fix all of tab issues in d80211 by one big patch.
I always have several patches pending (and other people probably too)
and it leads to unnecessary rejects when applying them. Instead, I
gradually correct them when changing corresponding lines.

Thanks,

 Jiri

-- 
Jiri Benc
SUSE Labs
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Who maintains the website ?

2006-07-26 Thread Stephen Hemminger
On Wed, 26 Jul 2006 12:14:01 +0200
Christophe Devriese <[EMAIL PROTECTED]> wrote:

> I have created the http://linux-net.osdl.org/index.php/VLAN page.
> What do you think ?

I changed the mainpage VLAN to point to that. You might want to move
the generic (non-linux stuff) to wikipedia.
http://en.wikipedia.org/wiki/VLAN
and put a link to that. It is standard to put the external links
at the bottom of the article.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/24] RT2x00: Add TXPOWER_FROM_DEV and TXPOWER_TO_DEV macros

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Add TXPOWER_FROM_DEV and TXPOWER_TO_DEV macro's
to convert the txpower values read from the eeprom
to the value dscape expects, and vice versa.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-23 17:01:06.0 +0200
+++ wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 17:24:56.0 +0200
@@ -582,8 +582,7 @@
 
 static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, u8 
txpower)
 {
-   txpower = (txpower < 39) ? 39 : txpower;
-   txpower = (txpower > 62) ? 62 : txpower;
+   txpower = TXPOWER_TO_DEV(txpower);
rt2x00_bbp_write(rt2x00dev, 3, txpower);
 }
 
@@ -2343,15 +2342,11 @@
rt2x00_eeprom_read(rt2x00dev,
EEPROM_TXPOWER_START + i, &eeprom);
 
-   channels[(i * 2)].power_level =
-   rt2x00_get_field16(eeprom, EEPROM_TXPOWER_1);
-   if (channels[(i * 2)].power_level > 0x7f)
-   channels[(i * 2)].power_level = 0x27;
-
-   channels[(i * 2) + 1].power_level =
-   rt2x00_get_field16(eeprom, EEPROM_TXPOWER_2);
-   if (channels[(i * 2) + 1].power_level > 0x7f)
-   channels[(i * 2) + 1].power_level = 0x27;
+   channels[(i * 2)].power_level = TXPOWER_FROM_DEV(
+   rt2x00_get_field16(eeprom, EEPROM_TXPOWER_1));
+
+   channels[(i * 2) + 1].power_level = TXPOWER_FROM_DEV(
+   rt2x00_get_field16(eeprom, EEPROM_TXPOWER_2));
}
 
/*
diff -rU3 wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 
wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.h   
2006-07-23 16:34:46.0 +0200
+++ wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 
2006-07-23 17:15:44.0 +0200
@@ -845,6 +845,34 @@
 };
 
 /*
+ * Macro's for converting txpower from EEPROM to dscape value
+ * and from dscape value to register value.
+ * NOTE: Logics in rt2400pci for txpower are reversed
+ * compared to the other rt2x00 drivers. A higher txpower
+ * value means that the txpower must be lowered. This is
+ * important when converting the value coming from the
+ * dscape stack to the rt2400 acceptable value.
+ */
+#define MIN_TXPOWER31
+#define MAX_TXPOWER62
+#define DEFAULT_TXPOWER39
+
+#define TXPOWER_FROM_DEV(__txpower) \
+   ({ \
+   ((__txpower) > MAX_TXPOWER) ? DEFAULT_TXPOWER - MIN_TXPOWER : \
+   ((__txpower) < MIN_TXPOWER) ? DEFAULT_TXPOWER - MIN_TXPOWER : \
+   (((__txpower) - MAX_TXPOWER) + MIN_TXPOWER); \
+   })
+
+#define TXPOWER_TO_DEV(__txpower) \
+   ({ \
+   (__txpower) += MIN_TXPOWER; \
+   ((__txpower) < MIN_TXPOWER) ? MAX_TXPOWER : \
+   (((__txpower) > MAX_TXPOWER) ? MIN_TXPOWER : \
+   (MAX_TXPOWER - ((__txpower) - MIN_TXPOWER))); \
+   })
+
+/*
  * IEEE stack callback functions declarations.
  */
 static int rt2400pci_tx(struct net_device *net_dev,
diff -rU3 wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-23 17:01:39.0 +0200
+++ wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 17:31:27.0 +0200
@@ -533,8 +533,9 @@
u32 rf3 = rt2x00dev->rf3;
u32 rf4 = rt2x00dev->rf4;
 
-   txpower = (txpower < 19) ? 19 : txpower;
-   txpower = (txpower > 31) ? 31 : txpower;
+   if (txpower == 0xff)
+   txpower = rt2x00dev->tx_power;
+   txpower = TXPOWER_TO_DEV(txpower);
 
if (rt2x00_rf(&rt2x00dev->chip, RF2525E) && channel == 14)
rf4 |= cpu_to_le32(0x0010);
@@ -615,6 +616,14 @@
rt2x00_register_read(rt2x00dev, CNT0, &rf1);
 }
 
+static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev, int 
txpower)
+{
+   txpower = TXPOWER_TO_DEV(txpower);
+
+   rt2x00_set_field32(&rt2x00dev->rf3, RF3_TXPOWER, txpower);
+   rt2x00_rf_write(rt2x00dev, rt2x00dev->rf3);
+}
+
 static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, int 
antenna)
 {
u32 reg;
@@ -2003,6 +2012,7 @@
rt2500pci_config_channel(rt2x00dev,
conf->channel_val, conf->channel, conf->freq,
conf->power_level);
+   rt2500pci_config_txpower(rt2x00dev, conf->power_level);
rt2500pci_config_antenna(rt2x00dev, conf->antenna_sel);
rt2500pci_config_duration(rt2x00dev, conf->short_slot_time);
rt2500p

[PATCH 9/24] RT2x00: Don't use driver_data and driver_info fields

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

driver_info and driver_data are not required for rt2x00,
neither is there any need to check that field when the probe()
function is called. The PCI and USB layers already correctly
make the checks.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-23 18:34:06.0 +0200
+++ wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 
19:36:40.0 +0200
@@ -2670,11 +2670,6 @@
struct net_device *net_dev;
int status;
 
-   if (unlikely(id->driver_data != RT2460)) {
-   ERROR("Detected device not supported.\n");
-   return -ENODEV;
-   }
-
if (pci_enable_device(pci_dev)) {
ERROR("Enable device failed.\n");
return -EIO;
@@ -2839,7 +2834,7 @@
DRV_NAME " - " DRV_VERSION " (" DRV_RELDATE ") by " DRV_PROJECT;
 
 static struct pci_device_id rt2400pci_device_table[] = {
-   { PCI_DEVICE(0x1814, 0x0101), .driver_data = RT2460},
+   { PCI_DEVICE(0x1814, 0x0101) },
{ 0, }
 };
 
diff -rU3 wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-23 18:34:14.0 +0200
+++ wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 
19:33:46.0 +0200
@@ -2936,11 +2936,6 @@
struct net_device *net_dev;
int status;
 
-   if (unlikely(id->driver_data != RT2560)) {
-   ERROR("Detected device not supported.\n");
-   return -ENODEV;
-   }
-
if (pci_enable_device(pci_dev)) {
ERROR("Enable device failed.\n");
return -EIO;
@@ -3105,7 +3100,7 @@
DRV_NAME " - " DRV_VERSION " (" DRV_RELDATE ") by " DRV_PROJECT;
 
 static struct pci_device_id rt2500pci_device_table[] = {
-   { PCI_DEVICE(0x1814, 0x0201), .driver_data = RT2560},
+   { PCI_DEVICE(0x1814, 0x0201) },
{ 0, }
 };
 
diff -rU3 wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-23 18:36:12.0 +0200
+++ wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
2006-07-23 
19:36:18.0 +0200
@@ -2545,11 +2545,6 @@
struct net_device *net_dev;
int status;
 
-   if (unlikely(id->driver_info != RT2570)) {
-   ERROR("Detected device not supported.\n");
-   return -ENODEV;
-   }
-
usb_dev = usb_get_dev(usb_dev);
 
net_dev = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), NULL);
@@ -2682,46 +2677,46 @@
 
 static struct usb_device_id rt2500usb_device_table[] = {
/* ASUS */
-   { USB_DEVICE(0x0b05, 0x1706), .driver_info = RT2570},
-   { USB_DEVICE(0x0b05, 0x1707), .driver_info = RT2570},
+   { USB_DEVICE(0x0b05, 0x1706) },
+   { USB_DEVICE(0x0b05, 0x1707) },
/* Belkin */
-   { USB_DEVICE(0x050d, 0x7050), .driver_info = RT2570},
-   { USB_DEVICE(0x050d, 0x7051), .driver_info = RT2570},
-   { USB_DEVICE(0x050d, 0x705a), .driver_info = RT2570},
+   { USB_DEVICE(0x050d, 0x7050) },
+   { USB_DEVICE(0x050d, 0x7051) },
+   { USB_DEVICE(0x050d, 0x705a) },
/* Cisco Systems */
-   { USB_DEVICE(0x13b1, 0x000d), .driver_info = RT2570},
-   { USB_DEVICE(0x13b1, 0x0011), .driver_info = RT2570},
-   { USB_DEVICE(0x13b1, 0x001a), .driver_info = RT2570},
+   { USB_DEVICE(0x13b1, 0x000d) },
+   { USB_DEVICE(0x13b1, 0x0011) },
+   { USB_DEVICE(0x13b1, 0x001a) },
/* Conceptronic */
-   { USB_DEVICE(0x14b2, 0x3c02), .driver_info = RT2570},
+   { USB_DEVICE(0x14b2, 0x3c02) },
/* D-LINK */
-   { USB_DEVICE(0x2001, 0x3c00), .driver_info = RT2570},
+   { USB_DEVICE(0x2001, 0x3c00) },
/* Gigabyte */
-   { USB_DEVICE(0x1044, 0x8001), .driver_info = RT2570},
-   { USB_DEVICE(0x1044, 0x8007), .driver_info = RT2570},
+   { USB_DEVICE(0x1044, 0x8001) },
+   { USB_DEVICE(0x1044, 0x8007) },
/* Hercules */
-   { USB_DEVICE(0x06f8, 0xe000), .driver_info = RT2570},
+   { USB_DEVICE(0x06f8, 0xe000) },
/* Melco */
-   { USB_DEVICE(0x0411, 0x0066), .driver_info = RT2570},
-   { USB_DEVICE(0x0411, 0x0067), .driver_info = RT2570},
-   { USB_DEVICE(0x0411, 0x008b), .driver_info = RT2570},
+   { USB_DEVICE(0x0411, 0x0066) },
+   { USB_DEVICE(0x0411, 0x0067) },
+   { USB_DEVICE(0x0411, 0x008b) },
/* MSI */
-   { USB_DEVICE(0x0db0, 0x6861), .driver_info = RT2570},
-   { USB_DEVICE(0x0db0, 0

[PATCH 23/24] RT2x00: Fix register initialization

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Thanks to ethtool a lot of problems with initialization
of the registers has been discovered.
This will correctly initialize all registers.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2400pci.c  
2006-07-26 12:49:38.0 +0200
+++ wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-26 14:04:13.0 +0200
@@ -482,6 +482,8 @@
GET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR)))
return;
 
+   rt2x00_register_write(rt2x00dev, CSR14, 0);
+
/*
 * Apply hardware packet filter.
 */
@@ -513,16 +515,40 @@
rt2400pci_config_promisc(rt2x00dev, 1);
 
/*
+* Enable beacon config
+*/
+   rt2x00_register_read(rt2x00dev, BCNCSR1, ®);
+   rt2x00_set_field32(®, BCNCSR1_PRELOAD,
+   PREAMBLE + get_duration(IEEE80211_HEADER, 2));
+   rt2x00_register_write(rt2x00dev, BCNCSR1, reg);
+
+   /*
 * Enable synchronisation.
 */
+   rt2x00_register_read(rt2x00dev, CSR12, ®);
+   rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, 100 * 16);
+   rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, 100 * 16);
+   rt2x00_register_write(rt2x00dev, CSR12, reg);
+
rt2x00_register_read(rt2x00dev, CSR14, ®);
-   rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
-   if (type == IEEE80211_IF_TYPE_IBSS)
+   if (type != IEEE80211_IF_TYPE_MNTR) {
+   rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
+   rt2x00_set_field32(®, CSR14_TBCN, 1);
+   }
+
+   if (type == IEEE80211_IF_TYPE_IBSS) {
rt2x00_set_field32(®, CSR14_TSF_SYNC, 2);
-   else if (type == IEEE80211_IF_TYPE_STA)
+   rt2x00_set_field32(®, CSR14_BEACON_GEN, 1);
+   } else if (type == IEEE80211_IF_TYPE_STA) {
rt2x00_set_field32(®, CSR14_TSF_SYNC, 1);
-   else
+   rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
+   } else if (type == IEEE80211_IF_TYPE_AP) {
rt2x00_set_field32(®, CSR14_TSF_SYNC, 0);
+   rt2x00_set_field32(®, CSR14_BEACON_GEN, 1);
+   } else if (type == IEEE80211_IF_TYPE_MNTR) {
+   rt2x00_set_field32(®, CSR14_TSF_SYNC, 0);
+   rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
+   }
rt2x00_register_write(rt2x00dev, CSR14, reg);
 
/*
@@ -726,7 +752,7 @@
 
reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
 
-   rt2x00_register_write(rt2x00dev, ARCSR1, reg[0]);
+   rt2x00_register_write(rt2x00dev, ARCSR1, cpu_to_le32(reg[0]));
 
rt2x00_register_read(rt2x00dev, TXCSR1, ®[0]);
value = SIFS + PLCP
@@ -830,8 +856,8 @@
 
rt2x00_register_read(rt2x00dev, LEDCSR, ®);
 
-   rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 30);
-   rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 70);
+   rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70);
+   rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30);
 
if (rt2x00dev->led_mode == LED_MODE_TXRX_ACTIVITY) {
rt2x00_set_field32(®, LEDCSR_LINK, 1);
diff -rU3 wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2500pci.c  
2006-07-26 12:50:25.0 +0200
+++ wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-26 14:04:55.0 +0200
@@ -482,6 +482,8 @@
GET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR)))
return;
 
+   rt2x00_register_write(rt2x00dev, CSR14, 0);
+
/*
 * Apply hardware packet filter.
 */
@@ -516,16 +518,44 @@
rt2500pci_config_promisc(rt2x00dev, 1);
 
/*
+* Enable beacon config
+*/
+   if (ring) {
+   rt2x00_register_read(rt2x00dev, BCNCSR1, ®);
+   rt2x00_set_field32(®, BCNCSR1_PRELOAD,
+   PREAMBLE + get_duration(IEEE80211_HEADER, 2));
+   rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN,
+   rt2x00dev->ring[RING_BEACON].tx_params.cw_min);
+   rt2x00_register_write(rt2x00dev, BCNCSR1, reg);
+   }
+
+   /*
 * Enable synchronisation.
 */
+   rt2x00_register_read(rt2x00dev, CSR12, ®);
+   rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, 100 * 16);
+   rt2x00_set_field32(®, CSR12_CFPMAX_DURATION, 100 * 16);
+   rt2x00_register_write(rt2x00dev, CSR12, reg);
+
rt2x00_register_read(rt2x00dev, CSR14, ®);
-   rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
-   if (type == IEEE80211_IF_TYPE_IBSS)
+   if (type != IEEE80211_IF_TYPE_MNTR) {
+   rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
+

[PATCH 21/24] RT2x00: Correctly initialize tx_status->control field before packet transmission

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

The control field inside the tx_status field of each entry
should be correctly initialized when a packet is queued.
We can use the same field to pass it to dscape when updating the beacon.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-26 10:46:52.0 +0200
+++ wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-26 10:55:31.0 +0200
@@ -1587,17 +1587,16 @@
 {
struct data_ring *ring = data;
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(ring->net_dev);
+   struct data_entry *entry = rt2x00_get_data_entry(
+   &rt2x00dev->ring[RING_BEACON]);
struct sk_buff *skb;
-   struct ieee80211_tx_control beacon;
-
-   memset(&beacon, 0x00, sizeof(beacon));
 
skb = ieee80211_beacon_get(ring->net_dev,
-   rt2x00dev->interface.id, &beacon);
+   rt2x00dev->interface.id, &entry->tx_status.control);
if (!skb)
return;
 
-   rt2400pci_beacon_update(ring->net_dev, skb, &beacon);
+   rt2400pci_beacon_update(ring->net_dev, skb, &entry->tx_status.control);
 
dev_kfree_skb_any(skb);
 }
@@ -1881,6 +1880,7 @@
 
memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
rt2400pci_write_tx_desc(rt2x00dev, txd, skb, control);
+   memcpy(&entry->tx_status.control, control, sizeof(*control));
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
SET_FLAG(entry, ENTRY_RTS_FRAME);
entry->skb = skb;
diff -rU3 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-26 10:46:48.0 +0200
+++ wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-26 10:56:10.0 +0200
@@ -1712,17 +1712,16 @@
 {
struct data_ring *ring = data;
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(ring->net_dev);
+   struct data_entry *entry = rt2x00_get_data_entry(
+   &rt2x00dev->ring[RING_BEACON]);
struct sk_buff *skb;
-   struct ieee80211_tx_control beacon;
-
-   memset(&beacon, 0x00, sizeof(beacon));
 
skb = ieee80211_beacon_get(ring->net_dev,
-   rt2x00dev->interface.id, &beacon);
+   rt2x00dev->interface.id, &entry->tx_status.control);
if (!skb)
return;
 
-   rt2500pci_beacon_update(ring->net_dev, skb, &beacon);
+   rt2500pci_beacon_update(ring->net_dev, skb, &entry->tx_status.control);
 
dev_kfree_skb_any(skb);
 }
@@ -2016,6 +2015,7 @@
 
memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
rt2500pci_write_tx_desc(rt2x00dev, txd, skb, control);
+   memcpy(&entry->tx_status.control, control, sizeof(*control));
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
SET_FLAG(entry, ENTRY_RTS_FRAME);
entry->skb = skb;
diff -rU3 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-26 10:46:32.0 +0200
+++ wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
2006-07-26 10:56:11.0 +0200
@@ -1447,17 +1447,16 @@
 {
struct data_ring *ring = data;
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(ring->net_dev);
+   struct data_entry *entry = rt2x00_get_data_entry(
+   &rt2x00dev->ring[RING_BEACON]);
struct sk_buff *skb;
-   struct ieee80211_tx_control beacon;
-
-   memset(&beacon, 0x00, sizeof(beacon));
 
skb = ieee80211_beacon_get(ring->net_dev,
-   rt2x00dev->interface.id, &beacon);
+   rt2x00dev->interface.id, &entry->tx_status.control);
if (!skb)
return;
 
-   rt2500usb_beacon_update(ring->net_dev, skb, &beacon);
+   rt2500usb_beacon_update(ring->net_dev, skb, &entry->tx_status.control);
 
dev_kfree_skb_any(skb);
 }
@@ -1715,6 +1714,7 @@
 
memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
rt2500usb_write_tx_desc(rt2x00dev, txd, skb, control);
+   memcpy(&entry->tx_status.control, control, sizeof(*control));
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
SET_FLAG(entry, ENTRY_RTS_FRAME);
entry->skb = skb;
diff -rU3 wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-setnetdev/drivers/net/wirele

[PATCH 19/24] RT2x00: Simplify *_reset() functions

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

The reset function can be greatly simplified.
when a reset is required the best thing to do,
is to switch the radio off and on again.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-25 23:27:17.0 +0200
+++ wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-26 10:41:21.0 +0200
@@ -1905,42 +1905,9 @@
 static int rt2400pci_reset(struct net_device *net_dev)
 {
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
-   u32 reg;
-
-   /*
-* Cancel RX and TX.
-*/
-   rt2x00_register_read(rt2x00dev, TXCSR0, ®);
-   rt2x00_set_field32(®, TXCSR0_ABORT, 1);
-   rt2x00_register_write(rt2x00dev, TXCSR0, reg);
-
-   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
-   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1);
-   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
-
-   /*
-* Clear interrupts.
-*/
-   rt2x00_register_read(rt2x00dev, CSR7, ®);
-   rt2x00_register_write(rt2x00dev, CSR7, reg);
 
-   /*
-* Clear all rings, and reinitialize.
-*/
-   rt2400pci_init_rxdesc(rt2x00dev, &rt2x00dev->ring[RING_RX]);
-   rt2400pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_TX]);
-   rt2400pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_ATIM]);
-   rt2400pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_PRIO]);
-   rt2400pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_BEACON]);
-
-   /*
-* Enable RX again.
-*/
-   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
-   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0);
-   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
-
-   return 0;
+   rt2400pci_disable_radio(rt2x00dev);
+   return rt2400pci_enable_radio(rt2x00dev);
 }
 
 static int rt2400pci_add_interface(struct net_device *net_dev,
diff -rU3 wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-25 23:27:54.0 +0200
+++ wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-26 10:41:32.0 +0200
@@ -2040,42 +2040,9 @@
 static int rt2500pci_reset(struct net_device *net_dev)
 {
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
-   u32 reg;
-
-   /*
-* Cancel RX and TX.
-*/
-   rt2x00_register_read(rt2x00dev, TXCSR0, ®);
-   rt2x00_set_field32(®, TXCSR0_ABORT, 1);
-   rt2x00_register_write(rt2x00dev, TXCSR0, reg);
-
-   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
-   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1);
-   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
-
-   /*
-* Clear interrupts.
-*/
-   rt2x00_register_read(rt2x00dev, CSR7, ®);
-   rt2x00_register_write(rt2x00dev, CSR7, reg);
 
-   /*
-* Clear all rings, and reinitialize.
-*/
-   rt2500pci_init_rxdesc(rt2x00dev, &rt2x00dev->ring[RING_RX]);
-   rt2500pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_TX]);
-   rt2500pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_ATIM]);
-   rt2500pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_PRIO]);
-   rt2500pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_BEACON]);
-
-   /*
-* Enable RX again.
-*/
-   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
-   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0);
-   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
-
-   return 0;
+   rt2500pci_disable_radio(rt2x00dev);
+   return rt2500pci_enable_radio(rt2x00dev);
 }
 
 static int rt2500pci_add_interface(struct net_device *net_dev,
diff -rU3 wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
2006-07-25 23:28:54.0 +0200
+++ wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-26 10:42:02.0 +0200
@@ -1738,28 +1738,12 @@
return NETDEV_TX_OK;
 }
 
-static inline void rt2500usb_reset_ring(struct data_ring *ring)
-{
-   unsigned int i;
-
-   for (i = 0; i < ring->stats.limit; i++)
-   usb_kill_urb(ring->entry[i].urb);
-}
-
 static int rt2500usb_reset(struct net_device *net_dev)
 {
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
-   rt2500usb_reset_ring(&rt2x00dev->ring[RING_RX]);
-   rt2500usb_reset_ring(&rt2x00dev->ring[RING_TX]);
-   rt2500usb_reset_ring(&rt2x00dev->ring[RING_ATIM]);
-   rt2500usb_reset_ring(&rt2x00dev->ring[RING_PRIO]);
-   rt2500usb_reset_

[PATCH 17/24] RT2x00: reorganize allocation/initialization of ieee80211_hw and rt2x00

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Fix initialization of driver/hardware.
Make a clear seperation between allocation and initialization.
Remove the open() and stop() functions since they have been deprecated
by dscape some time ago.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

http://www.mendiosus.nl/rt2x00/17_rt2x00_init.diff
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/24] RT2x00: Add ethtool support

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Add ethtool support.
At the moment we support the following features:
* read driver info
* read registers
* read eeprom
* enable and disable debug output

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 
wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c  
2006-07-23 15:53:06.0 +0200
+++ wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 16:30:58.0 +0200
@@ -33,7 +33,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 
 #include 
 #include 
@@ -362,6 +364,79 @@
 #endif /* CONFIG_RT2400PCI_BUTTON */
 
 /*
+ * Ethtool handlers.
+ */
+static void rt2400pci_get_drvinfo(struct net_device *net_dev,
+   struct ethtool_drvinfo *drvinfo)
+{
+   struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+
+   strcpy(drvinfo->driver, DRV_NAME);
+   strcpy(drvinfo->version, DRV_VERSION);
+   strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
+   drvinfo->eedump_len = EEPROM_SIZE;
+   drvinfo->regdump_len = CSR_REG_SIZE;
+}
+
+static int rt2400pci_get_regs_len(struct net_device *net_dev)
+{
+   return CSR_REG_SIZE;
+}
+
+static void rt2400pci_get_regs(struct net_device *net_dev,
+   struct ethtool_regs *regs, void *data)
+{
+   struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+
+   rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
+   regs->version = *((u32*)data);
+   regs->len = CSR_REG_SIZE;
+}
+
+#ifdef CONFIG_RT2400PCI_DEBUG
+static u32 rt2400pci_get_msglevel(struct net_device *net_dev)
+{
+   return rt2x00_debug_level;
+}
+
+static void rt2400pci_set_msglevel(struct net_device *net_dev, u32 msg)
+{
+   rt2x00_debug_level = !!msg;
+}
+#endif /* CONFIG_RT2400PCI_DEBUG */
+
+static int rt2400pci_get_eeprom_len(struct net_device *net_dev)
+{
+   return EEPROM_SIZE;
+}
+
+static int rt2400pci_get_eeprom(struct net_device *net_dev,
+   struct ethtool_eeprom *eeprom, u8 *data)
+{
+   struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+
+   eeprom->magic = 0xbad;
+
+   rt2x00_eeprom_multiread(rt2x00dev,
+   eeprom->offset / sizeof(u16), (void*)data, eeprom->len);
+
+   return 0;
+}
+
+static struct ethtool_ops rt2400pci_ethtool_ops = {
+   .get_drvinfo= rt2400pci_get_drvinfo,
+   .get_regs_len   = rt2400pci_get_regs_len,
+   .get_regs   = rt2400pci_get_regs,
+#ifdef CONFIG_RT2400PCI_DEBUG
+   .get_msglevel   = rt2400pci_get_msglevel,
+   .set_msglevel   = rt2400pci_set_msglevel,
+#endif /* CONFIG_RT2400PCI_DEBUG */
+   .get_link   = ethtool_op_get_link,
+   .get_eeprom_len = rt2400pci_get_eeprom_len,
+   .get_eeprom = rt2400pci_get_eeprom,
+};
+
+/*
  * Configuration handlers.
  */
 static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
@@ -2582,6 +2657,8 @@
goto exit_release_regions;
}
 
+   SET_ETHTOOL_OPS(net_dev, &rt2400pci_ethtool_ops);
+
pci_set_drvdata(pci_dev, net_dev);
 
status = rt2400pci_initialize(pci_dev, net_dev);
diff -rU3 
wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 
wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.h  
2006-07-22 23:05:16.0 +0200
+++ wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 
2006-07-23 16:34:46.0 +0200
@@ -39,6 +39,14 @@
 #define RF2421 0x0001
 
 /*
+ * Register layout information.
+ */
+#define CSR_REG_BASE   0x
+#define CSR_REG_SIZE   0x014c
+#define EEPROM_BASE0x
+#define EEPROM_SIZE0x00ff
+
+/*
  * Control/Status Registers(CSR).
  * Some values are set in TU, whereas 1 TU == 1024 us.
  */
diff -rU3 
wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c  
2006-07-23 15:53:09.0 +0200
+++ wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 16:31:10.0 +0200
@@ -33,7 +33,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 
 #include 
 #include 
@@ -362,6 +364,79 @@
 #endif /* CONFIG_RT2500PCI_BUTTON */
 
 /*
+ * Ethtool handlers.
+ */
+static void rt2500pci_get_drvinfo(struct net_device *net_dev,
+   struct ethtool_drvinfo *drvinfo)
+{
+   struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+
+   strcpy(drvinfo->driver, DRV_NAME);
+   strcpy(drvinfo->version, DRV_VERSION);
+   strcpy(drvinfo->bus_info, pci_name(rt2x0

[PATCH 5/24] RT2x00: Clean up device specific rate value initialization

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

ieee80211_rate structure should be initialized by device_rate_entry
And the creation of the device specific rate value can be optimized
and made more clearer.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 16:30:58.0 +0200
+++ wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-23 17:01:06.0 +0200
@@ -680,10 +680,10 @@
u32 value;
u32 preamble;
 
-   preamble = DEVICE_RATE_FIELD(rate, PREAMBLE)
+   preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
? SHORT_PREAMBLE : PREAMBLE;
 
-   reg[0] = DEVICE_RATE_FIELD(rate, RATEMASK);
+   reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
 
rt2x00_register_write(rt2x00dev, ARCSR1, reg[0]);
 
@@ -699,7 +699,7 @@
rt2x00_set_field32(®[0], TXCSR1_ACK_CONSUME_TIME, value);
rt2x00_register_write(rt2x00dev, TXCSR1, reg[0]);
 
-   value = DEVICE_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
+   value = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
 
reg[0] = cpu_to_le32(0x00700400 | value);   /* ARCSR2 */
reg[1] = cpu_to_le32(0x00380401 | value);   /* ARCSR3 */
@@ -919,9 +919,9 @@
 * Convert length to microseconds.
 */
residual = get_duration_res(length,
-   DEVICE_RATE_FIELD(control->tx_rate, RATE));
+   DEVICE_GET_RATE_FIELD(control->tx_rate, RATE));
length = get_duration(length,
-   DEVICE_RATE_FIELD(control->tx_rate, RATE));
+   DEVICE_GET_RATE_FIELD(control->tx_rate, RATE));
 
if (residual)
length++;
@@ -939,8 +939,8 @@
length_high = 0x8000 | 0x0700 | (length >> 8);
length_low = 0x8000 | 0x0800 | (length & 0xff);
 
-   signal = 0x8500 | DEVICE_RATE_FIELD(control->tx_rate, PLCP);
-   if (DEVICE_RATE_FIELD(control->tx_rate, PREAMBLE))
+   signal = 0x8500 | DEVICE_GET_RATE_FIELD(control->tx_rate, PLCP);
+   if (DEVICE_GET_RATE_FIELD(control->tx_rate, PREAMBLE))
signal |= 0x0008;
 
service = 0x0600 | 0x0004;
@@ -2370,33 +2370,10 @@
/*
 * Rates initialization.
 */
-   rates[0].rate = 10;
-   rates[0].val = DEVICE_RATE_1MB;
-   rates[0].flags = IEEE80211_RATE_CCK;
-   rates[0].val2 = DEVICE_RATE_1MB;
-   rates[0].min_rssi_ack = 0;
-   rates[0].min_rssi_ack_delta = 0;
-
-   rates[1].rate = 20;
-   rates[1].val = DEVICE_RATE_2MB;
-   rates[1].flags = IEEE80211_RATE_CCK_2;
-   rates[1].val2 = DEVICE_RATE_2MB_PREAMBLE;
-   rates[1].min_rssi_ack = 0;
-   rates[1].min_rssi_ack_delta = 0;
-
-   rates[2].rate = 55;
-   rates[2].val = DEVICE_RATE_55MB;
-   rates[2].flags = IEEE80211_RATE_CCK_2;
-   rates[2].val2 = DEVICE_RATE_55MB_PREAMBLE;
-   rates[2].min_rssi_ack = 0;
-   rates[2].min_rssi_ack_delta = 0;
-
-   rates[3].rate = 110;
-   rates[3].val = DEVICE_RATE_11MB;
-   rates[3].flags = IEEE80211_RATE_CCK_2;
-   rates[3].val2 = DEVICE_RATE_11MB_PREAMBLE;
-   rates[3].min_rssi_ack = 0;
-   rates[3].min_rssi_ack_delta = 0;
+   device_rate_entry(&rates[0], 10, 0x001, 0x00, IEEE80211_RATE_CCK);
+   device_rate_entry(&rates[1], 20, 0x003, 0x01, IEEE80211_RATE_CCK_2);
+   device_rate_entry(&rates[2], 55, 0x007, 0x02, IEEE80211_RATE_CCK_2);
+   device_rate_entry(&rates[3], 110, 0x00f, 0x03, IEEE80211_RATE_CCK_2);
 }
 
 static int rt2400pci_init_hw(struct rt2x00_dev *rt2x00dev)
diff -rU3 wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 16:31:10.0 +0200
+++ wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-23 17:01:39.0 +0200
@@ -725,10 +725,10 @@
u32 value;
u32 preamble;
 
-   preamble = DEVICE_RATE_FIELD(rate, PREAMBLE)
+   preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
? SHORT_PREAMBLE : PREAMBLE;
 
-   reg[0] = DEVICE_RATE_FIELD(rate, RATEMASK);
+   reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
 
rt2x00_register_write(rt2x00dev, ARCSR1, reg[0]);
 
@@ -744,7 +744,7 @@
rt2x00_set_field32(®[0], TXCSR1_ACK_CONSUME_TIME, value);
rt2x00_register_write(rt2x00dev, TXCSR1, reg[0]);
 
-   value = DEVICE_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
+   value = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
 
reg[0] = cpu_to_le32(0x00700400 | value);   /* ARCSR2 */
reg[1] = cpu_to_le32(0x00380401 | value);   /* ARCSR3 */
@@ -993,7 +993,7 @@
 * this can be done by checking if bit 4 or higher

[PATCH 18/24] RT2x00: Make suspend and resume handlers work correctly

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Fix suspend and resume handlers,
they should no longer use net_dev->open()
and net_dev->stop() since that delivers the wrong behaviour.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-25 20:21:44.0 +0200
+++ wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-25 23:27:17.0 +0200
@@ -2885,15 +2885,9 @@
NOTICE("Going to sleep.\n");
 
/*
-* If radio was enabled, stop radio and
-* set the resume flag to the radio will be enabled
-* when resuming.
-*/
-   if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) {
-   if (net_dev->stop(net_dev))
-   return -EBUSY;
-   SET_FLAG(rt2x00dev, RADIO_RESUME);
-   }
+* Disable the radio.
+*/
+   rt2400pci_disable_radio(rt2x00dev);
 
/*
 * Set device mode to sleep for power management.
@@ -2902,11 +2896,16 @@
return -EBUSY;
 
/*
-* Uninitialize hardware.
+* Uninitialize device.
 */
rt2400pci_uninitialize(rt2x00dev);
 
/*
+* Uninitialize hardware.
+*/
+   rt2400pci_free_dev(net_dev);
+
+   /*
 * Disable PCI.
 */
pci_save_state(pci_dev);
@@ -2934,28 +2933,15 @@
/*
 * Initialize hardware.
 */
-   if (rt2400pci_initialize(rt2x00dev)) {
-   ERROR("Failed to initialize device.\n");
+   if (rt2400pci_alloc_dev(pci_dev, net_dev)) {
+   ERROR("Failed to allocate device.\n");
return -ENOMEM;
}
 
/*
-* Set device mode to awake.
+* Set device mode to awake for power management.
 */
-   if (rt2400pci_set_state(rt2x00dev, STATE_AWAKE))
-   return -EBUSY;
-
-   /*
-* Only enable radio when it was enabled
-* when we suspended.
-*/
-   if (GET_FLAG(rt2x00dev, RADIO_RESUME)) {
-   if (net_dev->open(net_dev))
-   return -EBUSY;
-   CLEAR_FLAG(rt2x00dev, RADIO_RESUME);
-   }
-
-   return 0;
+   return rt2400pci_set_state(rt2x00dev, STATE_AWAKE);
 }
 #endif /* CONFIG_PM */
 
diff -rU3 wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-25 20:21:45.0 +0200
+++ wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-25 23:27:54.0 +0200
@@ -3156,15 +3156,9 @@
NOTICE("Going to sleep.\n");
 
/*
-* If radio was enabled, stop radio and
-* set the resume flag to the radio will be enabled
-* when resuming.
-*/
-   if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) {
-   if (net_dev->stop(net_dev))
-   return -EBUSY;
-   SET_FLAG(rt2x00dev, RADIO_RESUME);
-   }
+* Disable the radio.
+*/
+   rt2500pci_disable_radio(rt2x00dev);
 
/*
 * Set device mode to sleep for power management.
@@ -3173,11 +3167,16 @@
return -EBUSY;
 
/*
-* Uninitialize hardware.
+* Uninitialize device.
 */
rt2500pci_uninitialize(rt2x00dev);
 
/*
+* Uninitialize hardware.
+*/
+   rt2500pci_free_dev(net_dev);
+
+   /*
 * Disable PCI.
 */
pci_save_state(pci_dev);
@@ -3205,28 +3204,15 @@
/*
 * Initialize hardware.
 */
-   if (rt2500pci_initialize(rt2x00dev)) {
-   ERROR("Failed to initialize device.\n");
+   if (rt2500pci_alloc_dev(pci_dev, net_dev)) {
+   ERROR("Failed to allocate device.\n");
return -ENOMEM;
}
 
/*
-* Set device mode to awake.
+* Set device mode to awake for power management.
 */
-   if (rt2500pci_set_state(rt2x00dev, STATE_AWAKE))
-   return -EBUSY;
-
-   /*
-* Only enable radio when it was enabled
-* when we suspended.
-*/
-   if (GET_FLAG(rt2x00dev, RADIO_RESUME)) {
-   if (net_dev->open(net_dev))
-   return -EBUSY;
-   CLEAR_FLAG(rt2x00dev, RADIO_RESUME);
-   }
-
-   return 0;
+   return rt2500pci_set_state(rt2x00dev, STATE_AWAKE);
 }
 #endif /* CONFIG_PM */
 
diff -rU3 wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-25 20:21:43.0 +0200
+++

[PATCH 22/24] RT2x00: Optimize config handlers

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Optimize the configuration handlers to only run
when the current configuration has been changed.
This means we need to store the current setting
of most configuration options in rt2x00_dev.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-26 10:55:31.0 +0200
+++ wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2400pci.c  
2006-07-26 12:49:38.0 +0200
@@ -475,6 +475,14 @@
u32 reg;
 
/*
+* Only continue when there is something to be done.
+*/
+   if (type == rt2x00dev->interface.type ||
+   (rt2x00dev->interface.monitor_count ^
+   GET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR)))
+   return;
+
+   /*
 * Apply hardware packet filter.
 */
rt2x00_register_read(rt2x00dev, RXCSR0, ®);
@@ -520,7 +528,13 @@
/*
 * Update working mode.
 */
-   rt2x00dev->interface.type = type;
+   if (type != IEEE80211_IF_TYPE_MNTR)
+   rt2x00dev->interface.type = type;
+
+   if (rt2x00dev->interface.monitor_count)
+   SET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR);
+   else
+   CLEAR_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR);
 }
 
 static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
@@ -529,6 +543,12 @@
u32 rf1 = rt2x00dev->rf1;
u32 rf3 = rt2x00dev->rf3;
 
+   /*
+* Only continue when there is something to be done.
+*/
+   if (channel == rt2x00dev->rx_params.channel)
+   return;
+
INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x.\n",
rf1, rf2, rf3);
 
@@ -575,15 +595,31 @@
rt2x00dev->rx_params.channel = channel;
 
/*
+* Update rf fields
+*/
+   rt2x00dev->rf1 = rf1;
+   rt2x00dev->rf2 = rf2;
+   rt2x00dev->rf3 = rf3;
+
+   /*
 * Clear false CRC during channel switch.
 */
rt2x00_register_read(rt2x00dev, CNT0, &rf1);
 }
 
-static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, u8 
txpower)
+static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int 
txpower)
 {
txpower = TXPOWER_TO_DEV(txpower);
+
+   /*
+* Only continue when there is something to be done.
+*/
+   if (txpower == rt2x00dev->tx_power)
+   return;
+
rt2x00_bbp_write(rt2x00dev, 3, txpower);
+
+   rt2x00dev->tx_power = txpower;
 }
 
 static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev, int 
antenna)
@@ -591,6 +627,12 @@
u8 reg_rx;
u8 reg_tx;
 
+   /*
+* Only continue when there is something to be done.
+*/
+   if (rt2x00dev->rx_params.antenna == antenna)
+   return;
+
rt2x00_bbp_read(rt2x00dev, 4, ®_rx);
rt2x00_bbp_read(rt2x00dev, 1, ®_tx);
 
@@ -713,6 +755,12 @@
 {
struct ieee80211_rate *rate;
 
+   /*
+* Only continue when there is something to be done.
+*/
+   if (rt2x00dev->rx_params.phymode == phymode)
+   return;
+
rate = &rt2x00dev->hw.modes[0].rates[
rt2x00dev->hw.modes[0].num_rates - 1];
 
@@ -1760,6 +1808,9 @@
if (!reg)
return IRQ_NONE;
 
+   if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
+   return IRQ_HANDLED;
+
/*
 * Handle interrupts, walk through all bits
 * and run the tasks, the bits are checked in order of
@@ -1982,12 +2033,17 @@
u32 reg;
 
/*
-* Some configuration changes require the RX to be disabled.
+* Check if we need to disable the radio,
+* if this is not the case, at least the RX must be disabled.
 */
if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) {
-   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
-   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1);
-   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
+   if (!conf->radio_enabled)
+   rt2400pci_disable_radio(rt2x00dev);
+   else {
+   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
+   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1);
+   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
+   }
}
 
rt2400pci_config_channel(rt2x00dev,
@@ -2000,24 +2056,13 @@
/*
 * Reenable RX only if the radio should be on.
 */
-   if (conf->radio_enabled) {
-   if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) {
-   if (rt2400pci_open(net_dev)) {
-   ERROR("Failed to enabled radio.\n");
- 

[PATCH 16/24] RT2x00: Fix rt61pci interrupt handling

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

rt61pci irq is a bit different compared to the others,
when the irq is raised, we should read from the register which
ring and which entry has been send. And this entry should
be processed. Using a for loop to go through all entries
is no longer working since we require certain statistics
from the registers.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-rt61irq/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
2006-07-25 14:55:25.0 +0200
+++ wireless-dev-rt61irq/drivers/net/wireless/d80211/rt2x00/rt61pci.c   
2006-07-25 16:13:19.0 +0200
@@ -1473,72 +1473,119 @@
rt61pci_activity_led(rt2x00dev, total_rssi);
 }
 
-static void rt61pci_txdone(void *data)
+static void rt61pci_txdone_entry(struct data_entry *entry, u32 sta_csr4)
 {
-   struct data_ring *ring = data;
-   struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(ring->net_dev);
-   struct data_entry *entry;
+   struct rt2x00_dev *rt2x00dev =
+   ieee80211_dev_hw_data(entry->ring->net_dev);
struct txd *txd;
int tx_status;
int ack;
-   int reg;
int ring_full;
 
+   txd = rt2x00pci_desc_addr(entry);
+
+   if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
+   !rt2x00_get_field32(txd->word0, TXD_W0_VALID))
+   return;
+
+   ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
+
/*
-* Store the current status of the ring.
+* TODO: How can te below field be set correctly?
 */
-   ring_full = rt2x00_ring_full(ring);
+   entry->tx_status.tx_filtered = 0;
 
-   while (!rt2x00_ring_empty(ring)) {
-   entry = rt2x00_get_data_entry_done(ring);
-   txd = rt2x00pci_desc_addr(entry);
+   entry->tx_status.queue_length = entry->ring->stats.limit;
 
-   rt2x00_register_read(rt2x00dev, STA_CSR4, ®);
+   /*
+* The TXD_W0_RESULT field will only be set when
+* we had requested an ACK. So we have received an
+* ACK response when ACK was requested and status
+* was succesfull.
+*/
+   tx_status = rt2x00_get_field32(sta_csr4, STA_CSR4_TX_RESULT);
+   entry->tx_status.ack = 0;
+   if (ack && (tx_status == TX_SUCCESS ||
+   tx_status == TX_SUCCESS_RETRY))
+   entry->tx_status.ack = 1;
+   else if (ack && tx_status == TX_FAIL_RETRY) {
+   rt2x00dev->low_level_stats.dot11ACKFailureCount++;
+   entry->tx_status.excessive_retries++;
+   }
 
-   if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
-   !rt2x00_get_field32(txd->word0, TXD_W0_VALID) ||
-   !rt2x00_get_field32(reg, STA_CSR4_VALID))
-   break;
+   rt2x00_bbp_read(rt2x00dev, 32,
+   (u8*)&entry->tx_status.ack_signal);
 
-   ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
+   entry->tx_status.retry_count = rt2x00_get_field32(
+   sta_csr4, STA_CSR4_RETRY_COUNT);
 
-   /*
-* TODO: How can te below field be set correctly?
-*/
-   entry->tx_status.tx_filtered = 0;
+   if (!GET_FLAG(entry, ENTRY_RTS_FRAME))
+   ieee80211_tx_status(entry->ring->net_dev,
+   entry->skb, &entry->tx_status);
 
-   entry->tx_status.queue_length = ring->stats.limit;
+   rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+   entry->skb = NULL;
 
-   /*
-* The TXD_W0_RESULT field will only be set when
-* we had requested an ACK. So we have received an
-* ACK response when ACK was requested and status
-* was succesfull.
-*/
-   tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
-   entry->tx_status.ack = 0;
-   if (ack && (tx_status == TX_SUCCESS ||
-   tx_status == TX_SUCCESS_RETRY))
-   entry->tx_status.ack = 1;
-   else if (ack && tx_status == TX_FAIL_RETRY) {
-   rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-   entry->tx_status.excessive_retries++;
-   }
+   /*
+* Store the current status of the ring.
+*/
+   ring_full = rt2x00_ring_full(entry->ring);
 
-   rt2x00_bbp_read(rt2x00dev, 32,
-   (u8*)&entry->tx_status.ack_signal);
+   rt2x00_ring_index_done_inc(entry->ring);
 
-   entry->tx_status.retry_count = rt2x00_get_field32(
-   reg, STA_CSR4_RETRY_COUNT);
+   /*
+* If the data ring was full before the txdone handler
+* we must make sure the packet queue in the d80211 

[PATCH 10/24] RT2x00: Add software and hardware sequence counting

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Add software sequence number counting to rt2400pci and rt2500pci,
enable hardware sequence number counting for rt2500usb, rt61pci and rt73usb.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 
19:36:40.0 +0200
+++ wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-23 19:52:17.0 +0200
@@ -1682,6 +1682,11 @@
return NETDEV_TX_BUSY;
}
 
+   /*
+* Set the software sequence number.
+*/
+   rt2x00_set_sequence(skb, &rt2x00dev->interface.sequence);
+
memcpy(entry->data_addr, skb->data, skb->len);
rt2400pci_write_tx_desc(rt2x00dev, txd, skb, control);
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
@@ -2275,6 +2280,11 @@
 */
control->queue = IEEE80211_TX_QUEUE_BEACON;
 
+   /*
+* Set the software sequence number.
+*/
+   rt2x00_set_sequence(skb, &rt2x00dev->interface.sequence);
+
memcpy(entry->data_addr, skb->data, skb->len);
rt2400pci_write_tx_desc(rt2x00dev, entry->desc_addr, skb, control);
 
diff -rU3 wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 
19:33:46.0 +0200
+++ wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-23 19:52:28.0 +0200
@@ -1817,6 +1817,11 @@
return NETDEV_TX_BUSY;
}
 
+   /*
+* Set the software sequence number.
+*/
+   rt2x00_set_sequence(skb, &rt2x00dev->interface.sequence);
+
memcpy(entry->data_addr, skb->data, skb->len);
rt2500pci_write_tx_desc(rt2x00dev, txd, skb, control);
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
@@ -2401,6 +2406,11 @@
 */
control->queue = IEEE80211_TX_QUEUE_BEACON;
 
+   /*
+* Set the software sequence number.
+*/
+   rt2x00_set_sequence(skb, &rt2x00dev->interface.sequence);
+
memcpy(entry->data_addr, skb->data, skb->len);
rt2500pci_write_tx_desc(rt2x00dev, entry->desc_addr, skb, control);
 
diff -rU3 wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
2006-07-23 
19:36:18.0 +0200
+++ wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-23 19:54:54.0 +0200
@@ -1385,7 +1385,7 @@
rt2x00_register_write(rt2x00dev, MAC_CSR18, reg);
 
rt2x00_register_read(rt2x00dev, TXRX_CSR1, ®);
-   rt2x00_set_field16_nb(®, TXRX_CSR1_AUTO_SEQUENCE, 0x00);
+   rt2x00_set_field16_nb(®, TXRX_CSR1_AUTO_SEQUENCE, 1);
rt2x00_register_write(rt2x00dev, TXRX_CSR1, reg);
 
rt2x00_register_read(rt2x00dev, PHY_CSR4, ®);
diff -rU3 wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2x00.h 
wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2x00.h
2006-07-23 
18:09:00.0 +0200
+++ wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2x00.h   
2006-07-23 19:49:00.0 +0200
@@ -911,6 +911,50 @@
 }
 
 /*
+ * Sequence number handlers.
+ */
+static inline int rt2x00_require_sequence(struct ieee80211_hdr *ieee80211hdr)
+{
+   /*
+* Check if the packet has a header
+* that contains a seq_ctrl field.
+*/
+   if (ieee80211_get_hdrlen(
+   le16_to_cpu(ieee80211hdr->frame_control)) >= IEEE80211_HEADER)
+   return 1;
+   return 0;
+}
+
+static inline void rt2x00_set_sequence(struct sk_buff *skb, u16 *seq)
+{
+   struct ieee80211_hdr *ieee80211hdr =
+   (struct ieee80211_hdr*)skb->data;
+
+   /*
+* Only attach the sequence number, when
+* the buffer requires it.
+*/
+   if (!rt2x00_require_sequence(ieee80211hdr))
+   return;
+
+   /*
+* Set the sequence number for this frame,
+* but do not change the fragment number.
+*/
+   ieee80211hdr->seq_ctrl |= cpu_to_le16((*seq << 4) & 0xfff0);
+
+   /*
+* Since the dscape stack sends all packets and
+* fragments individually, we need to check if there
+* will be new fragments following.
+* If this is the last or only fragment, the sequence
+* counter should be increased.
+*/
+   if (!ieee80211_get_morefrag(ieee80211hdr))
+   *seq = (*seq + 1) & 0x0fff;
+}
+
+/*
  * Duration calculations
  * The rate variab

[PATCH 8/24] RT2x00: Fix *_set_state() functions

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Fix problems with waking up the device at initialization time.
The debug message should be more descriptive of the problem,
when the device fails to wake up.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 
18:16:35.0 +0200
+++ wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-23 18:34:06.0 +0200
@@ -857,7 +857,9 @@
msleep(10);
}
 
-   NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+   NOTICE("Device failed to enter state %d, "
+   "current device state: bbp %d and rf %d.\n",
+   state, bbp_state, rf_state);
 
return -EBUSY;
 }
diff -rU3 wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 
18:16:41.0 +0200
+++ wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-23 18:34:14.0 +0200
@@ -930,7 +930,9 @@
msleep(10);
}
 
-   NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+   NOTICE("Device failed to enter state %d, "
+   "current device state: bbp %d and rf %d.\n",
+   state, bbp_state, rf_state);
 
return -EBUSY;
 }
diff -rU3 wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
2006-07-23 
18:15:52.0 +0200
+++ wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-23 18:36:12.0 +0200
@@ -731,6 +731,7 @@
enum dev_state state)
 {
u16 reg;
+   u16 reg2;
unsigned int i;
char put_to_sleep;
char bbp_state;
@@ -739,11 +740,12 @@
put_to_sleep = (state != STATE_AWAKE);
 
rt2x00_register_read(rt2x00dev, 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(rt2x00dev, MAC_CSR17, reg);
+   rt2x00_set_field16_nb(®, MAC_CSR17_SET_STATE, 1);
+   rt2x00_register_write(rt2x00dev, MAC_CSR17, reg);
 
/*
 * Device is not guarenteed to be in the requested state yet.
@@ -751,16 +753,20 @@
 * device has entered the correct state.
 */
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-   rt2x00_register_read(rt2x00dev, MAC_CSR17, ®);
-   bbp_state = rt2x00_get_field16_nb(
-   reg, MAC_CSR17_BBP_CURR_STATE);
-   rf_state = rt2x00_get_field16_nb(reg, MAC_CSR17_RF_CURR_STATE);
+   rt2x00_register_read(rt2x00dev, MAC_CSR17, ®2);
+   bbp_state = rt2x00_get_field16_nb(reg2,
+   MAC_CSR17_BBP_CURR_STATE);
+   rf_state = rt2x00_get_field16_nb(reg2,
+   MAC_CSR17_RF_CURR_STATE);
if (bbp_state == state && rf_state == state)
return 0;
+   rt2x00_register_write(rt2x00dev, MAC_CSR17, reg);
msleep(10);
}
 
-   NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+   NOTICE("Device failed to enter state %d, "
+   "current device state: bbp %d and rf %d.\n",
+   state, bbp_state, rf_state);
 
return -EBUSY;
 }
diff -rU3 wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt61pci.c   
2006-07-23 
18:16:51.0 +0200
+++ wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
2006-07-23 
19:22:41.0 +0200
@@ -1169,19 +1169,33 @@
u32 reg;
unsigned int i;
char put_to_sleep;
+   char current_state;
 
put_to_sleep = (state != STATE_AWAKE);
 
-   if (!put_to_sleep)
-   rt2x00_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0x00, 0x00);
-
rt2x00_register_read(rt2x00dev, MAC_CSR12, ®);
rt2x00_set_field32(®, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
rt2x00_register_write(rt2x00dev, MAC_CSR12, reg);
 
-   if (put_to_sleep)
+   if (put_to_sleep) {
+   rt2x00_register_write(rt2x00dev,
+   SOFT_RESET_CSR, cpu_to_le32(0x0005));
+   r

[PATCH 13/24] RT2x00: Allow link tuning while scanning

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

rt2x00 does not know when we are scanning,
unless passive_scan() is being used.
For consistent behaviour we should not block
tuning while scanning.
We should however not tune the connection when
it has been disabled in the hardware.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c  
2006-07-23 22:41:58.0 +0200
+++ wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt2500pci.c  
2006-07-23 22:59:00.0 +0200
@@ -811,9 +811,10 @@
u8 reg_r17;
 
/*
-* Don't perform any tuning during scan.
+* Don't perform any tuning when it is disabled
+* in the EEPROM.
 */
-   if (rt2x00dev->scan)
+   if (GET_FLAG(rt2x00dev, CONFIG_DISABLE_BBP_TUNING))
return;
 
rt2x00_register_read(rt2x00dev, CSR0, ®);
@@ -2488,7 +2489,16 @@
SET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON);
 
/*
-* 7 - Read BBP data from EEPROM and store in private structure.
+* 7 - Check if the BBP tuning should be enabled.
+*/
+   rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+   if (eeprom == 0x)
+   eeprom = 0;
+   if (rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
+   SET_FLAG(rt2x00dev, CONFIG_DISABLE_BBP_TUNING);
+
+   /*
+* 8 - Read BBP data from EEPROM and store in private structure.
 */
rt2x00dev->eeprom = kzalloc(EEPROM_BBP_SIZE * sizeof(u16), GFP_KERNEL);
if (!rt2x00dev->eeprom)
diff -rU3 wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c  
2006-07-23 22:42:03.0 +0200
+++ wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt2500usb.c  
2006-07-23 23:00:43.0 +0200
@@ -617,15 +617,16 @@
  */
 static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev, char rssi)
 {
-   u16  reg;
+   u16 reg;
u8 reg_r17;
u8 up_bound;
u8 low_bound;
 
/*
-* Don't perform any tuning during scan.
+* Don't perform any tuning when it is disabled
+* in the EEPROM.
 */
-   if (rt2x00dev->scan)
+   if (GET_FLAG(rt2x00dev, CONFIG_DISABLE_BBP_TUNING))
return;
 
low_bound = 0x32;
@@ -2105,7 +2106,16 @@
EEPROM_ANTENNA_LED_MODE);
 
/*
-* 5 - Read BBP data from EEPROM and store in private structure.
+* 5 - Check if the BBP tuning should be disabled.
+*/
+   rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+   if (eeprom == 0x)
+   eeprom = 0;
+   if (rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
+   SET_FLAG(rt2x00dev, CONFIG_DISABLE_BBP_TUNING);
+
+   /*
+* 6 - Read BBP data from EEPROM and store in private structure.
 */
rt2x00dev->eeprom = kzalloc(EEPROM_BBP_SIZE * sizeof(u16), GFP_KERNEL);
if (!rt2x00dev->eeprom)
diff -rU3 wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-23 22:42:09.0 +0200
+++ wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-23 23:04:25.0 +0200
@@ -1043,12 +1043,6 @@
u8 up_bound;
u8 low_bound;
 
-   /*
-* Don't perform any tuning during scan.
-*/
-   if (rt2x00dev->scan)
-   return;
-
if (rt2x00dev->rx_params.phymode == MODE_IEEE80211A) {
up_bound = 0x48;
low_bound = 0x28;
diff -rU3 wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c
2006-07-23 22:47:41.0 +0200
+++ wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt73usb.c
2006-07-23 23:04:31.0 +0200
@@ -757,12 +757,6 @@
u8 up_bound;
u8 low_bound;
 
-   /*
-* Don't perform any tuning during scan.
-*/
-   if (rt2x00dev->scan)
-   return;
-
if (rt2x00dev->rx_params.phymode == MODE_IEEE80211A) {
up_bound = 0x48;
low_bound = 0x28;
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/24] RT2x00: Add RTS frame creation

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Support RTS.
When rts is required, create the frame and send it out
before the rest of the frames.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 17:24:56.0 +0200
+++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 
18:16:35.0 +0200
@@ -863,6 +863,36 @@
 }
 
 /*
+ * RTS frame creation.
+ */
+static struct sk_buff* rt2400pci_create_rts(struct rt2x00_dev *rt2x00dev,
+   struct ieee80211_hdr *hdr, unsigned short duration)
+{
+   struct ieee80211_hdr *ieee80211hdr;
+   struct sk_buff *skb;
+   u16 temp;
+
+   skb = dev_alloc_skb(IEEE80211_HEADER);
+   if (!skb)
+   return NULL;
+
+   /*
+* Copy the entire header over to RTS frame.
+*/
+   memcpy(skb_put(skb, IEEE80211_HEADER), hdr, IEEE80211_HEADER);
+   ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+
+   temp = (WLAN_FC_TYPE_CTRL  << 2) | (WLAN_FC_STYPE_RTS << 4);
+   ieee80211hdr->frame_control = cpu_to_le16(temp);
+
+   ieee80211hdr->duration_id += cpu_to_le16(duration);
+
+   ieee80211hdr->seq_ctrl = 0;
+
+   return skb;
+}
+
+/*
  * TX descriptor initialization
  */
 static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
@@ -876,15 +906,32 @@
u16 length_low;
u16 signal;
u16 service;
+   u16 frame_control;
+   u8 bitrate;
+   int tx_rate;
+
+   /*
+* Check which rate should be used for this frame.
+*/
+   frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+   if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS &&
+   control->rts_cts_rate)
+   tx_rate = control->rts_cts_rate;
+   else
+   tx_rate = control->tx_rate;
 
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 1);
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
 
/*
-* TODO: IFS can be various values, where can we find
-* which one we want to use?
+* Set IFS to IFS_SIFS when the this is not the first fragment,
+* or this fragment came after RTS/CTS.
 */
-   rt2x00_set_field32(&txd->word0, TXD_W0_IFS, 0);
+   if ((WLAN_GET_SEQ_FRAG(le16_to_cpu(ieee80211hdr->seq_ctrl)) > 0) ||
+   control->use_rts_cts)
+   rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_SIFS);
+   else
+   rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_BACKOFF);
 
if (control->queue == IEEE80211_TX_QUEUE_BEACON)
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 1);
@@ -896,16 +943,15 @@
 */
rt2x00_set_field32(&txd->word0, TXD_W0_RETRY_MODE, 0);
 
-   if (ieee80211hdr->frame_control & WLAN_FC_MOREFRAG)
+   if (frame_control & WLAN_FC_MOREFRAG)
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 0);
 
-   /*
-* TODO: Does this field mean device will send RTS, or that this
-* frame is an RTS frame?
-*/
-   rt2x00_set_field32(&txd->word0, TXD_W0_RTS, control->use_rts_cts);
+   if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
+   rt2x00_set_field32(&txd->word10, TXD_W10_RTS, 1);
+   else
+   rt2x00_set_field32(&txd->word10, TXD_W10_RTS, 0);
 
rt2x00_set_field32(&txd->word2, TXD_W2_DATABYTE_COUNT, skb->len);
 
@@ -918,9 +964,9 @@
 * Convert length to microseconds.
 */
residual = get_duration_res(length,
-   DEVICE_GET_RATE_FIELD(control->tx_rate, RATE));
+   DEVICE_GET_RATE_FIELD(tx_rate, RATE));
length = get_duration(length,
-   DEVICE_GET_RATE_FIELD(control->tx_rate, RATE));
+   DEVICE_GET_RATE_FIELD(tx_rate, RATE));
 
if (residual)
length++;
@@ -938,8 +984,8 @@
length_high = 0x8000 | 0x0700 | (length >> 8);
length_low = 0x8000 | 0x0800 | (length & 0xff);
 
-   signal = 0x8500 | DEVICE_GET_RATE_FIELD(control->tx_rate, PLCP);
-   if (DEVICE_GET_RATE_FIELD(control->tx_rate, PREAMBLE))
+   signal = 0x8500 | DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
+   if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
signal |= 0x0008;
 
service = 0x0600 | 0x0004;
@@ -1089,8 +1135,9 @@
entry->tx_status.retry_count = rt2x00_get_field32(
txd->word0, TXD_W0_RETRY_COUNT);
 
-   ieee80211_tx_status(ring->net_dev,
-   entry->skb, &entry->tx_status);
+   if (!GET_FLAG(entry, ENTRY_RTS_FRAME))
+   ieee80211_tx_status(ring->net_dev,
+

[PATCH 2/24] RT2x00: Add interface structure

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Move all settings depending on the current association into
a seperate interface structure.
Altough we only support 1 association type at a time,
we do support multiple monitor devices, keep track of the
number using the monitor_count field.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-22 23:17:54.0 +0200
+++ wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-23 14:54:53.0 +0200
@@ -411,7 +411,7 @@
rt2x00_set_field32(®, RXCSR0_DROP_TODS, 0);
 
rt2x00_set_field32(®, RXCSR0_DROP_CRC, 1);
-   if (type == IEEE80211_IF_TYPE_MNTR) {
+   if (rt2x00pci->interface.monitor_count) {
rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 0);
rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 0);
rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 0);
@@ -426,7 +426,7 @@
/*
 * Enable promisc mode when in monitor mode.
 */
-   if (type == IEEE80211_IF_TYPE_MNTR)
+   if (rt2x00pci->interface.monitor_count)
rt2400pci_config_promisc(rt2x00pci, 1);
 
/*
@@ -445,7 +445,7 @@
/*
 * Update working mode.
 */
-   rt2x00pci->type = type;
+   rt2x00pci->interface.type = type;
 }
 
 static void rt2400pci_config_channel(struct rt2x00_pci *rt2x00pci,
@@ -897,7 +897,7 @@
memset(&beacon, 0x00, sizeof(beacon));
 
skb = ieee80211_beacon_get(ring->net_dev,
-   rt2x00pci->interface_id, &beacon);
+   rt2x00pci->interface.id, &beacon);
if (!skb)
return;
 
@@ -1725,16 +1725,36 @@
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
/*
-* We only support 1 single working mode.
+* We only support 1 non-monitor interface.
 */
-   if (GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
+   if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+   GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
return -ENOBUFS;
 
-   rt2x00pci->interface_id = conf->if_id;
+   SET_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+
+   rt2x00_add_interface(&rt2x00pci->interface, conf);
 
+   /*
+* Enable configuration.
+*/
+   rt2400pci_config_type(rt2x00pci, conf->type);
rt2400pci_config_mac_address(rt2x00pci, conf->mac_addr);
 
-   SET_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+   /*
+* In case of master mode, set the BSSID to our MAC.
+*/
+   if (conf->type == IEEE80211_IF_TYPE_AP) {
+   memcpy(&rt2x00pci->interface.bssid, conf->mac_addr, ETH_ALEN);
+   rt2400pci_config_bssid(rt2x00pci, conf->mac_addr);
+   }
+
+   /*
+* Enable radio when this is the first
+* interface that is brought up.
+*/
+   if (!GET_FLAG(rt2x00pci, DEVICE_ENABLED_RADIO))
+   return rt2400pci_enable_radio(rt2x00pci);
 
return 0;
 }
@@ -1745,14 +1765,22 @@
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
/*
-* We only support 1 single working mode.
+* We only support 1 non-monitor interface.
 */
-   if (!GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
+   if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+   !GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
return;
 
-   rt2x00pci->interface_id = 0;
+   rt2x00_remove_interface(&rt2x00pci->interface, conf);
 
CLEAR_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+
+   /*
+* Disable radio if this was the last interface
+* that was working with this device.
+*/
+   if (!rt2x00pci->interface.monitor_count)
+   rt2400pci_disable_radio(rt2x00pci);
 }
 
 static void rt2400pci_config_update(void *data)
@@ -1818,15 +1846,20 @@
 {
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
-   rt2400pci_config_type(rt2x00pci, conf->type);
-
/*
 * When configuring monitor mode, we are done now.
+* but if we are configuring another mode it must be
+* equal to the interface that has been added.
 */
-   if (rt2x00pci->type == IEEE80211_IF_TYPE_MNTR)
+   if (conf->type == IEEE80211_IF_TYPE_MNTR)
return 0;
+   else if (conf->type != rt2x00pci->interface.type)
+   return -EINVAL;
 
-   rt2400pci_config_bssid(rt2x00pci, conf->bssid);
+   if (conf->bssid) {
+   memcpy(&rt2x00pci->interface.bssid, conf->bssid, ETH_ALEN);
+   rt2400pci_config_bssid(rt2x00pci, conf->bssid);
+   }
 
return 0;
 }
@@ -1835,21 +1868,27 @@
unsigned short flags, int mc_count)
 {
str

[PATCH 0/24] RT2x00

2006-07-26 Thread Ivo van Doorn
Hi,

Here is a new series of patches to bring rt2x00 in wireless-dev
up to date again.

I am holding back 2 patches, which will be send later this week,
but they are changes not only to rt2x00, so there is a chance those
patches will be rejected at first.

Anyway, here are the patches for rt2x00 only. ;)

Some of the patches are quite large, and have been placed
on an external server. Links can be found in the patch mail.

Some of the main changes:
- Code style fix
- suspend/resume fix (Yes, this time it is actually working)
- Device initialization cleanup
- Ethtool support
- register initialization fixes
- Reduce code duplication

After these patches the status of rt2x00 is as follows:

Master mode works, a connection can be established that lasts for a few hours.
Data transfer speed match 1Mbit/s, so there is something not right yet.

Monitor mode seems to work as expected, except for USB devices, which seem
to have problems with RX.

Managed mode seems to be able to start associations, but the connection is not 
lasting and the longest association time seems to be 20 minutes.

Ivo
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 24/24] RT2x00: Misc. fixes

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Misc. fixes
* Compile fixes
* Code style fixes previously overlooked
* Better check of return values of functions

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-misc/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-26 15:39:52.0 +0200
+++ wireless-dev-misc/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-26 15:56:37.0 +0200
@@ -360,7 +360,7 @@
rt2x00dev, rt2x00_get_field32(reg, GPIOCSR_BIT0));
 }
 #else /* CONFIG_RT2400PCI_BUTTON */
-static void rt2400pci_button_poll(struct rt2x00_dev *rt2x00dev){}
+static void rt2400pci_button_poll(unsigned long data){}
 #endif /* CONFIG_RT2400PCI_BUTTON */
 
 /*
@@ -1520,7 +1520,7 @@
 {
struct ieee80211_hdr *ieee80211hdr;
struct sk_buff *skb;
-   u16 temp;
+   u16 frame_control;
 
skb = dev_alloc_skb(IEEE80211_HEADER);
if (!skb)
@@ -1532,8 +1532,8 @@
memcpy(skb_put(skb, IEEE80211_HEADER), hdr, IEEE80211_HEADER);
ieee80211hdr = (struct ieee80211_hdr*)skb->data;
 
-   temp = (WLAN_FC_TYPE_CTRL  << 2) | (WLAN_FC_STYPE_RTS << 4);
-   ieee80211hdr->frame_control = cpu_to_le16(temp);
+   frame_control = (WLAN_FC_TYPE_CTRL  << 2) | (WLAN_FC_STYPE_RTS << 4);
+   ieee80211hdr->frame_control = cpu_to_le16(frame_control);
 
ieee80211hdr->duration_id += cpu_to_le16(duration);
 
@@ -1559,7 +1559,7 @@
u16 frame_control;
u8 bitrate;
int tx_rate;
- 
+
/*
 * Check which rate should be used for this frame.
 */
@@ -1593,16 +1593,16 @@
 */
rt2x00_set_field32(&txd->word0, TXD_W0_RETRY_MODE, 0);
 
-   if (frame_control & WLAN_FC_MOREFRAG)
+   if (ieee80211_get_morefrag(ieee80211hdr))
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 0);
- 
+
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
rt2x00_set_field32(&txd->word0, TXD_W0_RTS, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_RTS, 0);
- 
+
rt2x00_set_field32(&txd->word2, TXD_W2_DATABYTE_COUNT, skb->len);
 
/*
@@ -1613,10 +1613,9 @@
/*
 * Convert length to microseconds.
 */
-   residual = get_duration_res(length,
-   DEVICE_GET_RATE_FIELD(tx_rate, RATE));
-   length = get_duration(length,
-   DEVICE_GET_RATE_FIELD(tx_rate, RATE));
+   bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
+   residual = get_duration_res(length, bitrate);
+   length = get_duration(length, bitrate);
 
if (residual)
length++;
@@ -2627,16 +2626,16 @@
for (i = 0; i < 13; i++) {
channels[i].chan = i + 1;
channels[i].freq = 2407 + ((i + 1) * 5);
-   channels[i].flag = IEEE80211_CHAN_W_IBSS
-   | IEEE80211_CHAN_W_ACTIVE_SCAN | IEEE80211_CHAN_W_SCAN;
+   channels[i].flag = IEEE80211_CHAN_W_IBSS |
+   IEEE80211_CHAN_W_ACTIVE_SCAN | IEEE80211_CHAN_W_SCAN;
channels[i].val = cpu_to_le32(vals[i]);
channels[i].antenna_max = 0xff;
}
 
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].flag = IEEE80211_CHAN_W_IBSS |
+   IEEE80211_CHAN_W_ACTIVE_SCAN | IEEE80211_CHAN_W_SCAN;
channels[13].val = cpu_to_le32(vals[13]);
channels[13].antenna_max = 0xff;
 
@@ -2852,9 +2851,10 @@
struct net_device *net_dev;
int status;
 
-   if (pci_enable_device(pci_dev)) {
+   status = pci_enable_device(pci_dev);
+   if (status) {
ERROR("Enable device failed.\n");
-   return -EIO;
+   return status;
}
 
pci_set_master(pci_dev);
@@ -2869,9 +2869,9 @@
goto exit_disable_device;
}
 
-   if (pci_request_regions(pci_dev, pci_name(pci_dev))) {
+   status = pci_request_regions(pci_dev, pci_name(pci_dev));
+   if (status) {
ERROR("PCI request regions failed.\n");
-   status = -EBUSY;
goto exit_disable_device;
}
 
diff -rU3 wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-misc/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-26 15:39:52.0 +0200
+++ wireless-dev-misc/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-26 15:56:37.0 +0200
@@ -360,7 +360,7 @@
rt2x00dev, rt2x00_get_field32(reg, GPIOCSR_BIT0));

[PATCH 15/24] RT2x00: Merge PCI and USB version of data_entry structure

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Merge the data_entry structure for USB and PCI into
a single structure. This means that all access to the data_addr
and desc_addr should now be performed through the functions:
rt2x00pci_desc_addr()
rt2x00pci_data_addr()
And for usb:
rt2x00usb_urb()
rt2x00usb_rxdata_addr()
rt2x00usb_rxdesc_addr()
rt2x00usb_txdata_addr()
rt2x00usb_txdesc_addr()

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-eeprom/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-eeprom/drivers/net/wireless/d80211/rt2x00/rt2400pci.c  
2006-07-23 22:41:51.0 +0200
+++ wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-25 10:44:12.0 +0200
@@ -1039,7 +1039,7 @@
 
while (1) {
entry = rt2x00_get_data_entry(ring);
-   rxd = entry->desc_addr;
+   rxd = rt2x00pci_desc_addr(entry);
 
if (rt2x00_get_field32(rxd->word0, RXD_W0_OWNER_NIC))
break;
@@ -1058,7 +1058,8 @@
 
skb_reserve(skb, NET_IP_ALIGN);
 
-   memcpy(skb_put(skb, size), entry->data_addr, size);
+   memcpy(skb_put(skb, size), rt2x00pci_data_addr(entry),
+   size);
 
rt2x00dev->rx_params.ssi =
rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
@@ -1100,7 +1101,7 @@
 
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
-   txd = entry->desc_addr;
+   txd = rt2x00pci_desc_addr(entry);
 
if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
!rt2x00_get_field32(txd->word0, TXD_W0_VALID))
@@ -1237,10 +1238,10 @@
  * DMA ring functions.
  */
 static int rt2400pci_alloc_ring(struct rt2x00_dev *rt2x00dev,
-   struct data_ring *ring, void (*handler)(void *),
+   unsigned short type, void (*handler)(void *),
const u16 max_entries, const u16 data_size, const u16 desc_size)
 {
-   struct data_entry *entry;
+   struct data_ring *ring = &rt2x00dev->ring[type];
unsigned int i;
 
/*
@@ -1261,15 +1262,15 @@
 
rt2x00_ring_index_clear(ring);
 
+   ring->type = type;
ring->stats.limit = max_entries;
-   ring->entry_size = sizeof(struct data_entry);
ring->data_size = data_size;
ring->desc_size = desc_size;
 
/*
 * Allocate all ring entries.
 */
-   ring->entry = kmalloc(ring->stats.limit * ring->entry_size,
+   ring->entry = kmalloc(ring->stats.limit * sizeof(struct data_entry),
GFP_KERNEL);
if (!ring->entry)
return -ENOMEM;
@@ -1288,15 +1289,14 @@
 * Initialize all ring entries to contain valid
 * addresses.
 */
-   entry = ring->entry;
for (i = 0; i < ring->stats.limit; i++) {
-   entry[i].skb = NULL;
-   entry[i].desc_addr = ring->data_addr
+   ring->entry[i].skb = NULL;
+   ring->entry[i].priv = ring->data_addr
+ (i * ring->desc_size);
-   entry[i].data_addr = ring->data_addr
+   ring->entry[i].data_addr = ring->data_addr
+ (ring->stats.limit * ring->desc_size)
+ (i * ring->data_size);
-   entry[i].data_dma = ring->data_dma
+   ring->entry[i].data_dma = ring->data_dma
+ (ring->stats.limit * ring->desc_size)
+ (i * ring->data_size);
}
@@ -1329,19 +1329,19 @@
SET_FLAG(rt2x00dev, DEVICE_SUPPORT_ATIM);
 
if (rt2400pci_alloc_ring(
-   rt2x00dev, &rt2x00dev->ring[RING_RX], rt2400pci_rxdone,
+   rt2x00dev, RING_RX, rt2400pci_rxdone,
RX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct rxd)) ||
rt2400pci_alloc_ring(
-   rt2x00dev, &rt2x00dev->ring[RING_TX], rt2400pci_txdone,
+   rt2x00dev, RING_TX, rt2400pci_txdone,
 TX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd)) ||
rt2400pci_alloc_ring(
-   rt2x00dev, &rt2x00dev->ring[RING_ATIM], rt2400pci_txdone,
+   rt2x00dev, RING_ATIM, rt2400pci_txdone,
ATIM_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd)) ||
rt2400pci_alloc_ring(
-   rt2x00dev, &rt2x00dev->ring[RING_PRIO], rt2400pci_txdone,
+   rt2x00dev, RING_PRIO, rt2400pci_txdone,
TX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd)) ||
rt2400pci_alloc_ring(
-   rt2x00dev, &rt2x00dev->ring[RING_BEACON], rt2400pci_beacondone,
+   rt2x00dev, RING_BEACON, rt2400pci_beacondone,
BEACON_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))) {
 

[PATCH 3/24] RT2x00: Merge rt2x00_pci and rt2x00_usb

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

rt2x00_pci and rt2x00_usb are for 99% equal,
the only difference they have are not worth the duplicate code.
Merge the structures into rt2x00_dev.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

http://www.mendiosus.nl/rt2x00/03_rt2x00_pciusb_dev.diff
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 14/24] RT2x00: Check if read eeprom words are valid

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Make checks if the EEPROM data read is valid,
if it is not, use the default values.
Also fix the endian issue when reading the PCI_CONFIG_HEADER.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-eeprom/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-23 23:04:25.0 +0200
+++ wireless-dev-eeprom/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-23 23:19:17.0 +0200
@@ -2914,6 +2914,7 @@
u32 reg;
u16 value;
u16 eeprom;
+   u16 device;
 
/*
 * 1 - Detect EEPROM width.
@@ -2934,12 +2935,11 @@
 * To determine the RT chip we have to read the
 * PCI header of the device.
 */
-   pci_read_config_dword(rt2x00dev_pci(rt2x00dev),
-   PCI_CONFIG_HEADER, ®);
-   reg = rt2x00_get_field32(reg, PCI_CONFIG_HEADER_DEVICE);
+   pci_read_config_word(
+   rt2x00dev_pci(rt2x00dev), PCI_CONFIG_HEADER_DEVICE, &device);
 
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-   rt2x00_set_chip(&rt2x00dev->chip, (u16)reg, value);
+   rt2x00_set_chip(&rt2x00dev->chip, device, value);
 
if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
!rt2x00_rf(&rt2x00dev->chip, RF5325) &&
@@ -2985,6 +2985,8 @@
 * 8 - Read external LNA informations.
 */
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+   if (eeprom == 0x)
+   eeprom = 0;
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
SET_FLAG(rt2x00dev, CONFIG_EXTERNAL_LNA_A);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
@@ -2994,58 +2996,35 @@
 * 9 - Store led settings, for correct led behaviour.
 */
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
-   if (eeprom == 0x) {
-   rt2x00dev->led_mode = LED_MODE_DEFAULT;
 
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_LED_MODE, LED_MODE_DEFAULT);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_0, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_1, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_2, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_3, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_4, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_ACT, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_READY_BG, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_READY_A, 1);
-   } else {
+   /*
+* If the eeprom value is invalid,
+* switch to default led mode.
+*/
+   if (eeprom == 0x)
+   rt2x00dev->led_mode = LED_MODE_DEFAULT;
+   else
rt2x00dev->led_mode = rt2x00_get_field16(eeprom,
EEPROM_LED_LED_MODE);
 
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_LED_MODE, rt2x00dev->led_mode);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_0, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_GPIO_0));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_1, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_GPIO_1));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_2, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_GPIO_2));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_3, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_GPIO_3));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_4, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_GPIO_4));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_ACT, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_ACT));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_READY_BG, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_RDY_G));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_READY_A, rt2x00_get_field16(eeprom,
-   

[PATCH 11/24] RT2x00: Move scan_work to scanning structure

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Remove scan_work from rt2x00_dev and place it in the scanning structure.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-23 19:52:17.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-23 22:41:51.0 +0200
@@ -2139,7 +2139,8 @@
/*
 * Queue work.
 */
-   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan_work))
+   INIT_WORK(&rt2x00dev->scan->work, rt2400pci_scan, rt2x00dev);
+   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
goto exit;
 
return 0;
@@ -2599,7 +2600,6 @@
/*
 * Intialize scanning attributes.
 */
-   INIT_WORK(&rt2x00dev->scan_work, rt2400pci_scan, rt2x00dev);
rt2x00dev->scan = NULL;
 
if (rt2400pci_init_eeprom(rt2x00dev) ||
diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-23 19:52:28.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-23 22:41:58.0 +0200
@@ -2271,7 +2271,8 @@
/*
 * Queue work.
 */
-   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan_work))
+   INIT_WORK(&rt2x00dev->scan->work, rt2500pci_scan, rt2x00dev);
+   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
goto exit;
 
return 0;
@@ -2865,7 +2866,6 @@
/*
 * Intialize scanning attributes.
 */
-   INIT_WORK(&rt2x00dev->scan_work, rt2500pci_scan, rt2x00dev);
rt2x00dev->scan = NULL;
 
if (rt2500pci_init_eeprom(rt2x00dev) ||
diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-23 19:54:54.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-23 22:42:03.0 +0200
@@ -1942,7 +1942,8 @@
/*
 * Queue work.
 */
-   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan_work))
+   INIT_WORK(&rt2x00dev->scan->work, rt2500usb_scan, rt2x00dev);
+   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
goto exit;
 
return 0;
@@ -2481,7 +2482,6 @@
/*
 * Intialize scanning attributes.
 */
-   INIT_WORK(&rt2x00dev->scan_work, rt2500usb_scan, rt2x00dev);
rt2x00dev->scan = NULL;
 
if (rt2500usb_init_eeprom(rt2x00dev) ||
diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2x00.h 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2x00.h   
2006-07-23 19:49:00.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2x00.h   
2006-07-23 
22:32:51.0 +0200
@@ -676,6 +676,11 @@
short status;
 #define SCANNING_READY 0x0001
 #define SCANNING_CANCELLED 0x0002
+
+   /*
+* Work structure for scheduling the scanning work.
+*/
+   struct work_struct work;
 };
 
 /*
diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt61pci.c  
2006-07-23 19:53:45.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt61pci.c  
2006-07-23 
22:42:09.0 +0200
@@ -2764,7 +2764,8 @@
/*
 * Queue work.
 */
-   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan_work))
+   INIT_WORK(&rt2x00dev->scan->work, rt61pci_scan, rt2x00dev);
+   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
goto exit;
 
return 0;
@@ -3438,7 +3439,6 @@
/*
 * Initialize scanning attributes.
 */
-   INIT_WORK(&rt2x00dev->scan_work, rt61pci_scan, rt2x00dev);
rt2x00dev->scan = NULL;
 
if (rt61pci_init_eeprom(rt2x00dev) ||
diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt73usb.c  
2006-07-23 19:54:16.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt73usb.c  
2006-07-23 
22:35:17.0 +0200
@@ -2266,7 +2266,8 @@
/*
 * Queue work.
 */
-   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan_work))

[PATCH 20/24] RT2x00: Use SET_NETDEV_DEV

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Use SET_NETDEV_DEV to help userspace detect the wireless interfaces.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-26 10:41:21.0 +0200
+++ wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-26 10:46:52.0 +0200
@@ -2795,6 +2795,7 @@
}
 
SET_ETHTOOL_OPS(net_dev, &rt2400pci_ethtool_ops);
+   SET_NETDEV_DEV(net_dev, &pci_dev->dev);
 
pci_set_drvdata(pci_dev, net_dev);
 
diff -rU3 wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-26 10:41:32.0 +0200
+++ wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-26 10:46:48.0 +0200
@@ -3066,6 +3066,7 @@
}
 
SET_ETHTOOL_OPS(net_dev, &rt2500pci_ethtool_ops);
+   SET_NETDEV_DEV(net_dev, &pci_dev->dev);
 
pci_set_drvdata(pci_dev, net_dev);
 
diff -rU3 wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-26 10:42:02.0 +0200
+++ wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-26 10:46:32.0 +0200
@@ -2686,6 +2686,7 @@
}
 
SET_ETHTOOL_OPS(net_dev, &rt2500usb_ethtool_ops);
+   SET_NETDEV_DEV(net_dev, &usb_intf->dev);
 
usb_set_intfdata(usb_intf, net_dev);
 
diff -rU3 wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
2006-07-26 
10:41:48.0 +0200
+++ wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
2006-07-26 10:46:44.0 +0200
@@ -3634,6 +3634,7 @@
}
 
SET_ETHTOOL_OPS(net_dev, &rt61pci_ethtool_ops);
+   SET_NETDEV_DEV(net_dev, &pci_dev->dev);
 
pci_set_drvdata(pci_dev, net_dev);
 
diff -rU3 wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
2006-07-26 
10:42:19.0 +0200
+++ wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
2006-07-26 10:46:22.0 +0200
@@ -3081,6 +3081,7 @@
}
 
SET_ETHTOOL_OPS(net_dev, &rt73usb_ethtool_ops);
+   SET_NETDEV_DEV(net_dev, &usb_intf->dev);
 
usb_set_intfdata(usb_intf, net_dev);
 
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 12/24] RT2x00: Add new rt73usb devices

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Add new rt73usb devices.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

diff -rU3 wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt73usb.c  
2006-07-23 
22:35:17.0 +0200
+++ wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c
2006-07-23 22:47:41.0 +0200
@@ -3119,6 +3119,8 @@
{ USB_DEVICE(0x07d1, 0x3c04) },
/* Gigabyte */
{ USB_DEVICE(0x1044, 0x8008) },
+   /* Linksys */
+   { USB_DEVICE(0x13b1, 0x0020) },
/* MSI */
{ USB_DEVICE(0x0db0, 0x6877) },
{ USB_DEVICE(0x0db0, 0xa874) },
@@ -3127,6 +3129,8 @@
{ USB_DEVICE(0x148f, 0x2671) },
/* Qcom */
{ USB_DEVICE(0x18e8, 0x6196) },
+   /* Sitecom */
+   { USB_DEVICE(0x0df6, 0x9712) },
{ 0, }
 };
 
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/24] RT2x00: Style fix

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Coding style fix.
* Reduce the amount of tabs in the code
* Put Place function return type and function name on a single line
* Replace 'u8 char counter' with 'unsigned int i'
* Place '&&', '||' and '|' on the end of a line, instead of at the start.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

---

http://www.mendiosus.nl/rt2x00/01_rt2x00_style.diff
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH dscape] d80211: Switch d80211.h to IEEE80211_ style names

2006-07-26 Thread Michael Wu
On Wednesday 26 July 2006 09:53, Jiri Benc wrote:
> I just meant running some s/ {8}/\t/ on your patch :-)
>
> Also, I don't want to fix all of tab issues in d80211 by one big patch.
> I always have several patches pending (and other people probably too)
> and it leads to unnecessary rejects when applying them. Instead, I
> gradually correct them when changing corresponding lines.
>
Ah. Well, if you don't mind doing the space->tabs fix, please do. I don't know 
if I can get to that soon enough.

Thanks,
-Michael Wu


pgpzFYRu2QHPn.pgp
Description: PGP signature


H/W requirements for NETIF_F_HW_CSUM

2006-07-26 Thread Ravinandan Arakali
Hello,
Our current NIC does not provide the actual checksum value on receive path.
Hence we only claim NETIF_F_IP_CSUM instead of the more general
NETIF_F_HW_CSUM.

To support this in a future adapter, we would like to know what exactly are
the requirements (on both Rx and Tx )to claim NETIF_F_HW_CSUM ?

Following are some specific questions:
1. On Tx, our adapter supports checksumming of TCP/UDP over IPv4 and IPv6.
This computation is TCP/UDP specific. Does the checksum calculation need to
be more generic ? Also, skbuff.h says that the checksum needs to be placed
at a specific location(skb->h.raw+skb->csum). I guess this means the adapter
needs to pass back the checksum to host driver after transmission. What
happens in case of TSO ?
2. On Rx, is it suffficient if we place the L4 checksum in skb->csum ? What
about L3 checksum ?

Thanks,
Ravi

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 10/24] RT2x00: Add software and hardware sequence counting

2006-07-26 Thread Jiri Benc
On Wed, 26 Jul 2006 19:05:08 +0200, Ivo van Doorn wrote:
> Add software sequence number counting to rt2400pci and rt2500pci,

Ah, we don't support sequence numbering in d80211? Why didn't you yell
at me?

 Jiri

-- 
Jiri Benc
SUSE Labs
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 10/24] RT2x00: Add software and hardware sequence counting

2006-07-26 Thread Ivo van Doorn
Hi,

> > Add software sequence number counting to rt2400pci and rt2500pci,
>
> Ah, we don't support sequence numbering in d80211? Why didn't you yell
> at me?

To be the honest the same reason as why I didn't yell about RTS,
I had placed it on my todo list for d80211. ;)
But due to limited time I have never started on it, and I still had to look to 
see if it belongs in d80211 or in the driver. Very often the device itself is 
handling the sequence counting. rt2400pci and rt2500pci just seem to be the
exception.

Ivo
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 10/24] RT2x00: Add software and hardware sequence counting

2006-07-26 Thread Jiri Benc
On Wed, 26 Jul 2006 19:48:35 +0200, Ivo van Doorn wrote:
> To be the honest the same reason as why I didn't yell about RTS,

Yes, another thing that should be in the stack.

> I had placed it on my todo list for d80211. ;)

Please, if you encounter such thing, speak loudly so everybody
interested has an idea what's missing.

Could you send me your d80211 todo list?

> But due to limited time I have never started on it, and I still had to look 
> to 
> see if it belongs in d80211 or in the driver. Very often the device itself is 
> handling the sequence counting. rt2400pci and rt2500pci just seem to be the
> exception.

It belongs to the stack. Both from theoretical (it is a part of 802.11
spec) and practical (at least two drivers need that) point of view.

Thanks,

 Jiri

-- 
Jiri Benc
SUSE Labs
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RESEND PATCH 0/24] RT2x00

2006-07-26 Thread Ivo van Doorn
Hi,

> Here is a new series of patches to bring rt2x00 in wireless-dev
> up to date again.
> 
> I am holding back 2 patches, which will be send later this week,
> but they are changes not only to rt2x00, so there is a chance those
> patches will be rejected at first.
> 
> Anyway, here are the patches for rt2x00 only. ;)

[..snip..]

My apologies, I had not configured my mail client correctly,
This means that all patches have been word wrapped. :(

Here is the correct series for wireless-dev

Ivo
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/24] RT2x00: Add interface structure

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Move all settings depending on the current association into
a seperate interface structure.
Altough we only support 1 association type at a time,
we do support multiple monitor devices, keep track of the
number using the monitor_count field.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-22 23:17:54.0 +0200
+++ wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-23 14:54:53.0 +0200
@@ -411,7 +411,7 @@
rt2x00_set_field32(®, RXCSR0_DROP_TODS, 0);
 
rt2x00_set_field32(®, RXCSR0_DROP_CRC, 1);
-   if (type == IEEE80211_IF_TYPE_MNTR) {
+   if (rt2x00pci->interface.monitor_count) {
rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 0);
rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 0);
rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 0);
@@ -426,7 +426,7 @@
/*
 * Enable promisc mode when in monitor mode.
 */
-   if (type == IEEE80211_IF_TYPE_MNTR)
+   if (rt2x00pci->interface.monitor_count)
rt2400pci_config_promisc(rt2x00pci, 1);
 
/*
@@ -445,7 +445,7 @@
/*
 * Update working mode.
 */
-   rt2x00pci->type = type;
+   rt2x00pci->interface.type = type;
 }
 
 static void rt2400pci_config_channel(struct rt2x00_pci *rt2x00pci,
@@ -897,7 +897,7 @@
memset(&beacon, 0x00, sizeof(beacon));
 
skb = ieee80211_beacon_get(ring->net_dev,
-   rt2x00pci->interface_id, &beacon);
+   rt2x00pci->interface.id, &beacon);
if (!skb)
return;
 
@@ -1725,16 +1725,36 @@
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
/*
-* We only support 1 single working mode.
+* We only support 1 non-monitor interface.
 */
-   if (GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
+   if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+   GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
return -ENOBUFS;
 
-   rt2x00pci->interface_id = conf->if_id;
+   SET_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+
+   rt2x00_add_interface(&rt2x00pci->interface, conf);
 
+   /*
+* Enable configuration.
+*/
+   rt2400pci_config_type(rt2x00pci, conf->type);
rt2400pci_config_mac_address(rt2x00pci, conf->mac_addr);
 
-   SET_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+   /*
+* In case of master mode, set the BSSID to our MAC.
+*/
+   if (conf->type == IEEE80211_IF_TYPE_AP) {
+   memcpy(&rt2x00pci->interface.bssid, conf->mac_addr, ETH_ALEN);
+   rt2400pci_config_bssid(rt2x00pci, conf->mac_addr);
+   }
+
+   /*
+* Enable radio when this is the first
+* interface that is brought up.
+*/
+   if (!GET_FLAG(rt2x00pci, DEVICE_ENABLED_RADIO))
+   return rt2400pci_enable_radio(rt2x00pci);
 
return 0;
 }
@@ -1745,14 +1765,22 @@
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
/*
-* We only support 1 single working mode.
+* We only support 1 non-monitor interface.
 */
-   if (!GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
+   if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+   !GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
return;
 
-   rt2x00pci->interface_id = 0;
+   rt2x00_remove_interface(&rt2x00pci->interface, conf);
 
CLEAR_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+
+   /*
+* Disable radio if this was the last interface
+* that was working with this device.
+*/
+   if (!rt2x00pci->interface.monitor_count)
+   rt2400pci_disable_radio(rt2x00pci);
 }
 
 static void rt2400pci_config_update(void *data)
@@ -1818,15 +1846,20 @@
 {
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
 
-   rt2400pci_config_type(rt2x00pci, conf->type);
-
/*
 * When configuring monitor mode, we are done now.
+* but if we are configuring another mode it must be
+* equal to the interface that has been added.
 */
-   if (rt2x00pci->type == IEEE80211_IF_TYPE_MNTR)
+   if (conf->type == IEEE80211_IF_TYPE_MNTR)
return 0;
+   else if (conf->type != rt2x00pci->interface.type)
+   return -EINVAL;
 
-   rt2400pci_config_bssid(rt2x00pci, conf->bssid);
+   if (conf->bssid) {
+   memcpy(&rt2x00pci->interface.bssid, conf->bssid, ETH_ALEN);
+   rt2400pci_config_bssid(rt2x00pci, conf->bssid);
+   }
 
return 0;
 }
@@ -1835,21 +1868,27 @@
unsigned short flags, int mc_count)
 {
struct r

Re: [PATCH 4/24] RT2x00: Add ethtool support

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Add ethtool support.
At the moment we support the following features:
* read driver info
* read registers
* read eeprom
* enable and disable debug output

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 
wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c  
2006-07-23 15:53:06.0 +0200
+++ wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 16:30:58.0 +0200
@@ -33,7 +33,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 
 #include 
 #include 
@@ -362,6 +364,79 @@
 #endif /* CONFIG_RT2400PCI_BUTTON */
 
 /*
+ * Ethtool handlers.
+ */
+static void rt2400pci_get_drvinfo(struct net_device *net_dev,
+   struct ethtool_drvinfo *drvinfo)
+{
+   struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+
+   strcpy(drvinfo->driver, DRV_NAME);
+   strcpy(drvinfo->version, DRV_VERSION);
+   strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
+   drvinfo->eedump_len = EEPROM_SIZE;
+   drvinfo->regdump_len = CSR_REG_SIZE;
+}
+
+static int rt2400pci_get_regs_len(struct net_device *net_dev)
+{
+   return CSR_REG_SIZE;
+}
+
+static void rt2400pci_get_regs(struct net_device *net_dev,
+   struct ethtool_regs *regs, void *data)
+{
+   struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+
+   rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
+   regs->version = *((u32*)data);
+   regs->len = CSR_REG_SIZE;
+}
+
+#ifdef CONFIG_RT2400PCI_DEBUG
+static u32 rt2400pci_get_msglevel(struct net_device *net_dev)
+{
+   return rt2x00_debug_level;
+}
+
+static void rt2400pci_set_msglevel(struct net_device *net_dev, u32 msg)
+{
+   rt2x00_debug_level = !!msg;
+}
+#endif /* CONFIG_RT2400PCI_DEBUG */
+
+static int rt2400pci_get_eeprom_len(struct net_device *net_dev)
+{
+   return EEPROM_SIZE;
+}
+
+static int rt2400pci_get_eeprom(struct net_device *net_dev,
+   struct ethtool_eeprom *eeprom, u8 *data)
+{
+   struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+
+   eeprom->magic = 0xbad;
+
+   rt2x00_eeprom_multiread(rt2x00dev,
+   eeprom->offset / sizeof(u16), (void*)data, eeprom->len);
+
+   return 0;
+}
+
+static struct ethtool_ops rt2400pci_ethtool_ops = {
+   .get_drvinfo= rt2400pci_get_drvinfo,
+   .get_regs_len   = rt2400pci_get_regs_len,
+   .get_regs   = rt2400pci_get_regs,
+#ifdef CONFIG_RT2400PCI_DEBUG
+   .get_msglevel   = rt2400pci_get_msglevel,
+   .set_msglevel   = rt2400pci_set_msglevel,
+#endif /* CONFIG_RT2400PCI_DEBUG */
+   .get_link   = ethtool_op_get_link,
+   .get_eeprom_len = rt2400pci_get_eeprom_len,
+   .get_eeprom = rt2400pci_get_eeprom,
+};
+
+/*
  * Configuration handlers.
  */
 static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
@@ -2582,6 +2657,8 @@
goto exit_release_regions;
}
 
+   SET_ETHTOOL_OPS(net_dev, &rt2400pci_ethtool_ops);
+
pci_set_drvdata(pci_dev, net_dev);
 
status = rt2400pci_initialize(pci_dev, net_dev);
diff -rU3 
wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 
wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.h  
2006-07-22 23:05:16.0 +0200
+++ wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 
2006-07-23 16:34:46.0 +0200
@@ -39,6 +39,14 @@
 #define RF2421 0x0001
 
 /*
+ * Register layout information.
+ */
+#define CSR_REG_BASE   0x
+#define CSR_REG_SIZE   0x014c
+#define EEPROM_BASE0x
+#define EEPROM_SIZE0x00ff
+
+/*
  * Control/Status Registers(CSR).
  * Some values are set in TU, whereas 1 TU == 1024 us.
  */
diff -rU3 
wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-pciusb_dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c  
2006-07-23 15:53:09.0 +0200
+++ wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 16:31:10.0 +0200
@@ -33,7 +33,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 
 #include 
 #include 
@@ -362,6 +364,79 @@
 #endif /* CONFIG_RT2500PCI_BUTTON */
 
 /*
+ * Ethtool handlers.
+ */
+static void rt2500pci_get_drvinfo(struct net_device *net_dev,
+   struct ethtool_drvinfo *drvinfo)
+{
+   struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+
+   strcpy(drvinfo->driver, DRV_NAME);
+   strcpy(drvinfo->version, DRV_VERSION);
+   strcpy(drvinfo->bus_info, pci_name(rt2x00dev_

Re: [PATCH 5/24] RT2x00: Clean up device specific rate value initialization

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

ieee80211_rate structure should be initialized by device_rate_entry
And the creation of the device specific rate value can be optimized
and made more clearer.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 16:30:58.0 +0200
+++ wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-23 17:01:06.0 +0200
@@ -680,10 +680,10 @@
u32 value;
u32 preamble;
 
-   preamble = DEVICE_RATE_FIELD(rate, PREAMBLE)
+   preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
? SHORT_PREAMBLE : PREAMBLE;
 
-   reg[0] = DEVICE_RATE_FIELD(rate, RATEMASK);
+   reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
 
rt2x00_register_write(rt2x00dev, ARCSR1, reg[0]);
 
@@ -699,7 +699,7 @@
rt2x00_set_field32(®[0], TXCSR1_ACK_CONSUME_TIME, value);
rt2x00_register_write(rt2x00dev, TXCSR1, reg[0]);
 
-   value = DEVICE_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
+   value = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
 
reg[0] = cpu_to_le32(0x00700400 | value);   /* ARCSR2 */
reg[1] = cpu_to_le32(0x00380401 | value);   /* ARCSR3 */
@@ -919,9 +919,9 @@
 * Convert length to microseconds.
 */
residual = get_duration_res(length,
-   DEVICE_RATE_FIELD(control->tx_rate, RATE));
+   DEVICE_GET_RATE_FIELD(control->tx_rate, RATE));
length = get_duration(length,
-   DEVICE_RATE_FIELD(control->tx_rate, RATE));
+   DEVICE_GET_RATE_FIELD(control->tx_rate, RATE));
 
if (residual)
length++;
@@ -939,8 +939,8 @@
length_high = 0x8000 | 0x0700 | (length >> 8);
length_low = 0x8000 | 0x0800 | (length & 0xff);
 
-   signal = 0x8500 | DEVICE_RATE_FIELD(control->tx_rate, PLCP);
-   if (DEVICE_RATE_FIELD(control->tx_rate, PREAMBLE))
+   signal = 0x8500 | DEVICE_GET_RATE_FIELD(control->tx_rate, PLCP);
+   if (DEVICE_GET_RATE_FIELD(control->tx_rate, PREAMBLE))
signal |= 0x0008;
 
service = 0x0600 | 0x0004;
@@ -2370,33 +2370,10 @@
/*
 * Rates initialization.
 */
-   rates[0].rate = 10;
-   rates[0].val = DEVICE_RATE_1MB;
-   rates[0].flags = IEEE80211_RATE_CCK;
-   rates[0].val2 = DEVICE_RATE_1MB;
-   rates[0].min_rssi_ack = 0;
-   rates[0].min_rssi_ack_delta = 0;
-
-   rates[1].rate = 20;
-   rates[1].val = DEVICE_RATE_2MB;
-   rates[1].flags = IEEE80211_RATE_CCK_2;
-   rates[1].val2 = DEVICE_RATE_2MB_PREAMBLE;
-   rates[1].min_rssi_ack = 0;
-   rates[1].min_rssi_ack_delta = 0;
-
-   rates[2].rate = 55;
-   rates[2].val = DEVICE_RATE_55MB;
-   rates[2].flags = IEEE80211_RATE_CCK_2;
-   rates[2].val2 = DEVICE_RATE_55MB_PREAMBLE;
-   rates[2].min_rssi_ack = 0;
-   rates[2].min_rssi_ack_delta = 0;
-
-   rates[3].rate = 110;
-   rates[3].val = DEVICE_RATE_11MB;
-   rates[3].flags = IEEE80211_RATE_CCK_2;
-   rates[3].val2 = DEVICE_RATE_11MB_PREAMBLE;
-   rates[3].min_rssi_ack = 0;
-   rates[3].min_rssi_ack_delta = 0;
+   device_rate_entry(&rates[0], 10, 0x001, 0x00, IEEE80211_RATE_CCK);
+   device_rate_entry(&rates[1], 20, 0x003, 0x01, IEEE80211_RATE_CCK_2);
+   device_rate_entry(&rates[2], 55, 0x007, 0x02, IEEE80211_RATE_CCK_2);
+   device_rate_entry(&rates[3], 110, 0x00f, 0x03, IEEE80211_RATE_CCK_2);
 }
 
 static int rt2400pci_init_hw(struct rt2x00_dev *rt2x00dev)
diff -rU3 wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-ethtool/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 16:31:10.0 +0200
+++ wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-23 17:01:39.0 +0200
@@ -725,10 +725,10 @@
u32 value;
u32 preamble;
 
-   preamble = DEVICE_RATE_FIELD(rate, PREAMBLE)
+   preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
? SHORT_PREAMBLE : PREAMBLE;
 
-   reg[0] = DEVICE_RATE_FIELD(rate, RATEMASK);
+   reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
 
rt2x00_register_write(rt2x00dev, ARCSR1, reg[0]);
 
@@ -744,7 +744,7 @@
rt2x00_set_field32(®[0], TXCSR1_ACK_CONSUME_TIME, value);
rt2x00_register_write(rt2x00dev, TXCSR1, reg[0]);
 
-   value = DEVICE_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
+   value = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
 
reg[0] = cpu_to_le32(0x00700400 | value);   /* ARCSR2 */
reg[1] = cpu_to_le32(0x00380401 | value);   /* ARCSR3 */
@@ -993,7 +993,7 @@
 * this can be done by checking if bit 4 or higher

Re: [PATCH 6/24] RT2x00: Add TXPOWER_FROM_DEV and TXPOWER_TO_DEV macros

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Add TXPOWER_FROM_DEV and TXPOWER_TO_DEV macro's
to convert the txpower values read from the eeprom
to the value dscape expects, and vice versa.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-23 17:01:06.0 +0200
+++ wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 17:24:56.0 +0200
@@ -582,8 +582,7 @@
 
 static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, u8 txpower)
 {
-   txpower = (txpower < 39) ? 39 : txpower;
-   txpower = (txpower > 62) ? 62 : txpower;
+   txpower = TXPOWER_TO_DEV(txpower);
rt2x00_bbp_write(rt2x00dev, 3, txpower);
 }
 
@@ -2343,15 +2342,11 @@
rt2x00_eeprom_read(rt2x00dev,
EEPROM_TXPOWER_START + i, &eeprom);
 
-   channels[(i * 2)].power_level =
-   rt2x00_get_field16(eeprom, EEPROM_TXPOWER_1);
-   if (channels[(i * 2)].power_level > 0x7f)
-   channels[(i * 2)].power_level = 0x27;
-
-   channels[(i * 2) + 1].power_level =
-   rt2x00_get_field16(eeprom, EEPROM_TXPOWER_2);
-   if (channels[(i * 2) + 1].power_level > 0x7f)
-   channels[(i * 2) + 1].power_level = 0x27;
+   channels[(i * 2)].power_level = TXPOWER_FROM_DEV(
+   rt2x00_get_field16(eeprom, EEPROM_TXPOWER_1));
+
+   channels[(i * 2) + 1].power_level = TXPOWER_FROM_DEV(
+   rt2x00_get_field16(eeprom, EEPROM_TXPOWER_2));
}
 
/*
diff -rU3 wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 
wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
--- wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2400pci.h   
2006-07-23 16:34:46.0 +0200
+++ wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.h 
2006-07-23 17:15:44.0 +0200
@@ -845,6 +845,34 @@
 };
 
 /*
+ * Macro's for converting txpower from EEPROM to dscape value
+ * and from dscape value to register value.
+ * NOTE: Logics in rt2400pci for txpower are reversed
+ * compared to the other rt2x00 drivers. A higher txpower
+ * value means that the txpower must be lowered. This is
+ * important when converting the value coming from the
+ * dscape stack to the rt2400 acceptable value.
+ */
+#define MIN_TXPOWER31
+#define MAX_TXPOWER62
+#define DEFAULT_TXPOWER39
+
+#define TXPOWER_FROM_DEV(__txpower) \
+   ({ \
+   ((__txpower) > MAX_TXPOWER) ? DEFAULT_TXPOWER - MIN_TXPOWER : \
+   ((__txpower) < MIN_TXPOWER) ? DEFAULT_TXPOWER - MIN_TXPOWER : \
+   (((__txpower) - MAX_TXPOWER) + MIN_TXPOWER); \
+   })
+
+#define TXPOWER_TO_DEV(__txpower) \
+   ({ \
+   (__txpower) += MIN_TXPOWER; \
+   ((__txpower) < MIN_TXPOWER) ? MAX_TXPOWER : \
+   (((__txpower) > MAX_TXPOWER) ? MIN_TXPOWER : \
+   (MAX_TXPOWER - ((__txpower) - MIN_TXPOWER))); \
+   })
+
+/*
  * IEEE stack callback functions declarations.
  */
 static int rt2400pci_tx(struct net_device *net_dev,
diff -rU3 wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rates/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-23 17:01:39.0 +0200
+++ wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 17:31:27.0 +0200
@@ -533,8 +533,9 @@
u32 rf3 = rt2x00dev->rf3;
u32 rf4 = rt2x00dev->rf4;
 
-   txpower = (txpower < 19) ? 19 : txpower;
-   txpower = (txpower > 31) ? 31 : txpower;
+   if (txpower == 0xff)
+   txpower = rt2x00dev->tx_power;
+   txpower = TXPOWER_TO_DEV(txpower);
 
if (rt2x00_rf(&rt2x00dev->chip, RF2525E) && channel == 14)
rf4 |= cpu_to_le32(0x0010);
@@ -615,6 +616,14 @@
rt2x00_register_read(rt2x00dev, CNT0, &rf1);
 }
 
+static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
+{
+   txpower = TXPOWER_TO_DEV(txpower);
+
+   rt2x00_set_field32(&rt2x00dev->rf3, RF3_TXPOWER, txpower);
+   rt2x00_rf_write(rt2x00dev, rt2x00dev->rf3);
+}
+
 static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, int antenna)
 {
u32 reg;
@@ -2003,6 +2012,7 @@
rt2500pci_config_channel(rt2x00dev,
conf->channel_val, conf->channel, conf->freq,
conf->power_level);
+   rt2500pci_config_txpower(rt2x00dev, conf->power_level);
rt2500pci_config_antenna(rt2x00dev, conf->antenna_sel);
rt2500pci_config_duration(rt2x00dev, conf->short_slot_time);
rt2500pci_confi

Re: [PATCH 8/24] RT2x00: Fix *_set_state() functions

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Fix problems with waking up the device at initialization time.
The debug message should be more descriptive of the problem,
when the device fails to wake up.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 18:16:35.0 +0200
+++ wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-23 18:34:06.0 +0200
@@ -857,7 +857,9 @@
msleep(10);
}
 
-   NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+   NOTICE("Device failed to enter state %d, "
+   "current device state: bbp %d and rf %d.\n",
+   state, bbp_state, rf_state);
 
return -EBUSY;
 }
diff -rU3 wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 18:16:41.0 +0200
+++ wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-23 18:34:14.0 +0200
@@ -930,7 +930,9 @@
msleep(10);
}
 
-   NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+   NOTICE("Device failed to enter state %d, "
+   "current device state: bbp %d and rf %d.\n",
+   state, bbp_state, rf_state);
 
return -EBUSY;
 }
diff -rU3 wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
2006-07-23 18:15:52.0 +0200
+++ wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-23 18:36:12.0 +0200
@@ -731,6 +731,7 @@
enum dev_state state)
 {
u16 reg;
+   u16 reg2;
unsigned int i;
char put_to_sleep;
char bbp_state;
@@ -739,11 +740,12 @@
put_to_sleep = (state != STATE_AWAKE);
 
rt2x00_register_read(rt2x00dev, 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(rt2x00dev, MAC_CSR17, reg);
+   rt2x00_set_field16_nb(®, MAC_CSR17_SET_STATE, 1);
+   rt2x00_register_write(rt2x00dev, MAC_CSR17, reg);
 
/*
 * Device is not guarenteed to be in the requested state yet.
@@ -751,16 +753,20 @@
 * device has entered the correct state.
 */
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-   rt2x00_register_read(rt2x00dev, MAC_CSR17, ®);
-   bbp_state = rt2x00_get_field16_nb(
-   reg, MAC_CSR17_BBP_CURR_STATE);
-   rf_state = rt2x00_get_field16_nb(reg, MAC_CSR17_RF_CURR_STATE);
+   rt2x00_register_read(rt2x00dev, MAC_CSR17, ®2);
+   bbp_state = rt2x00_get_field16_nb(reg2,
+   MAC_CSR17_BBP_CURR_STATE);
+   rf_state = rt2x00_get_field16_nb(reg2,
+   MAC_CSR17_RF_CURR_STATE);
if (bbp_state == state && rf_state == state)
return 0;
+   rt2x00_register_write(rt2x00dev, MAC_CSR17, reg);
msleep(10);
}
 
-   NOTICE("Device failed to %s.\n" , put_to_sleep ? "suspend" : "resume");
+   NOTICE("Device failed to enter state %d, "
+   "current device state: bbp %d and rf %d.\n",
+   state, bbp_state, rf_state);
 
return -EBUSY;
 }
diff -rU3 wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt61pci.c   
2006-07-23 18:16:51.0 +0200
+++ wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
2006-07-23 19:22:41.0 +0200
@@ -1169,19 +1169,33 @@
u32 reg;
unsigned int i;
char put_to_sleep;
+   char current_state;
 
put_to_sleep = (state != STATE_AWAKE);
 
-   if (!put_to_sleep)
-   rt2x00_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0x00, 0x00);
-
rt2x00_register_read(rt2x00dev, MAC_CSR12, ®);
rt2x00_set_field32(®, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
rt2x00_register_write(rt2x00dev, MAC_CSR12, reg);
 
-   if (put_to_sleep)
+   if (put_to_sleep) {
+   rt2x00_register_write(rt2x00dev,
+   SOFT_RESET_CSR, cpu_to_le32(0x0005));
+   rt2x00_regi

Re: [PATCH 11/24] RT2x00: Move scan_work to scanning structure

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Remove scan_work from rt2x00_dev and place it in the scanning structure.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-23 19:52:17.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-23 22:41:51.0 +0200
@@ -2139,7 +2139,8 @@
/*
 * Queue work.
 */
-   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan_work))
+   INIT_WORK(&rt2x00dev->scan->work, rt2400pci_scan, rt2x00dev);
+   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
goto exit;
 
return 0;
@@ -2599,7 +2600,6 @@
/*
 * Intialize scanning attributes.
 */
-   INIT_WORK(&rt2x00dev->scan_work, rt2400pci_scan, rt2x00dev);
rt2x00dev->scan = NULL;
 
if (rt2400pci_init_eeprom(rt2x00dev) ||
diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-23 19:52:28.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-23 22:41:58.0 +0200
@@ -2271,7 +2271,8 @@
/*
 * Queue work.
 */
-   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan_work))
+   INIT_WORK(&rt2x00dev->scan->work, rt2500pci_scan, rt2x00dev);
+   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
goto exit;
 
return 0;
@@ -2865,7 +2866,6 @@
/*
 * Intialize scanning attributes.
 */
-   INIT_WORK(&rt2x00dev->scan_work, rt2500pci_scan, rt2x00dev);
rt2x00dev->scan = NULL;
 
if (rt2500pci_init_eeprom(rt2x00dev) ||
diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-23 19:54:54.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-23 22:42:03.0 +0200
@@ -1942,7 +1942,8 @@
/*
 * Queue work.
 */
-   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan_work))
+   INIT_WORK(&rt2x00dev->scan->work, rt2500usb_scan, rt2x00dev);
+   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
goto exit;
 
return 0;
@@ -2481,7 +2482,6 @@
/*
 * Intialize scanning attributes.
 */
-   INIT_WORK(&rt2x00dev->scan_work, rt2500usb_scan, rt2x00dev);
rt2x00dev->scan = NULL;
 
if (rt2500usb_init_eeprom(rt2x00dev) ||
diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2x00.h 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2x00.h   
2006-07-23 19:49:00.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt2x00.h   
2006-07-23 22:32:51.0 +0200
@@ -676,6 +676,11 @@
short status;
 #define SCANNING_READY 0x0001
 #define SCANNING_CANCELLED 0x0002
+
+   /*
+* Work structure for scheduling the scanning work.
+*/
+   struct work_struct work;
 };
 
 /*
diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt61pci.c  
2006-07-23 19:53:45.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt61pci.c  
2006-07-23 22:42:09.0 +0200
@@ -2764,7 +2764,8 @@
/*
 * Queue work.
 */
-   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan_work))
+   INIT_WORK(&rt2x00dev->scan->work, rt61pci_scan, rt2x00dev);
+   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan->work))
goto exit;
 
return 0;
@@ -3438,7 +3439,6 @@
/*
 * Initialize scanning attributes.
 */
-   INIT_WORK(&rt2x00dev->scan_work, rt61pci_scan, rt2x00dev);
rt2x00dev->scan = NULL;
 
if (rt61pci_init_eeprom(rt2x00dev) ||
diff -rU3 wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt73usb.c  
2006-07-23 19:54:16.0 +0200
+++ wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt73usb.c  
2006-07-23 22:35:17.0 +0200
@@ -2266,7 +2266,8 @@
/*
 * Queue work.
 */
-   if (!queue_work(rt2x00dev->workqueue, &rt2x00dev->scan_work))
+   

Re: [PATCH 10/24] RT2x00: Add software and hardware sequence counting

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Add software sequence number counting to rt2400pci and rt2500pci,
enable hardware sequence number counting for rt2500usb, rt61pci and rt73usb.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 19:36:40.0 +0200
+++ wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-23 19:52:17.0 +0200
@@ -1682,6 +1682,11 @@
return NETDEV_TX_BUSY;
}
 
+   /*
+* Set the software sequence number.
+*/
+   rt2x00_set_sequence(skb, &rt2x00dev->interface.sequence);
+
memcpy(entry->data_addr, skb->data, skb->len);
rt2400pci_write_tx_desc(rt2x00dev, txd, skb, control);
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
@@ -2275,6 +2280,11 @@
 */
control->queue = IEEE80211_TX_QUEUE_BEACON;
 
+   /*
+* Set the software sequence number.
+*/
+   rt2x00_set_sequence(skb, &rt2x00dev->interface.sequence);
+
memcpy(entry->data_addr, skb->data, skb->len);
rt2400pci_write_tx_desc(rt2x00dev, entry->desc_addr, skb, control);
 
diff -rU3 wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 19:33:46.0 +0200
+++ wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-23 19:52:28.0 +0200
@@ -1817,6 +1817,11 @@
return NETDEV_TX_BUSY;
}
 
+   /*
+* Set the software sequence number.
+*/
+   rt2x00_set_sequence(skb, &rt2x00dev->interface.sequence);
+
memcpy(entry->data_addr, skb->data, skb->len);
rt2500pci_write_tx_desc(rt2x00dev, txd, skb, control);
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
@@ -2401,6 +2406,11 @@
 */
control->queue = IEEE80211_TX_QUEUE_BEACON;
 
+   /*
+* Set the software sequence number.
+*/
+   rt2x00_set_sequence(skb, &rt2x00dev->interface.sequence);
+
memcpy(entry->data_addr, skb->data, skb->len);
rt2500pci_write_tx_desc(rt2x00dev, entry->desc_addr, skb, control);
 
diff -rU3 wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
2006-07-23 19:36:18.0 +0200
+++ wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-23 19:54:54.0 +0200
@@ -1385,7 +1385,7 @@
rt2x00_register_write(rt2x00dev, MAC_CSR18, reg);
 
rt2x00_register_read(rt2x00dev, TXRX_CSR1, ®);
-   rt2x00_set_field16_nb(®, TXRX_CSR1_AUTO_SEQUENCE, 0x00);
+   rt2x00_set_field16_nb(®, TXRX_CSR1_AUTO_SEQUENCE, 1);
rt2x00_register_write(rt2x00dev, TXRX_CSR1, reg);
 
rt2x00_register_read(rt2x00dev, PHY_CSR4, ®);
diff -rU3 wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2x00.h 
wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2x00.h
2006-07-23 18:09:00.0 +0200
+++ wireless-dev-sequence/drivers/net/wireless/d80211/rt2x00/rt2x00.h   
2006-07-23 19:49:00.0 +0200
@@ -911,6 +911,50 @@
 }
 
 /*
+ * Sequence number handlers.
+ */
+static inline int rt2x00_require_sequence(struct ieee80211_hdr *ieee80211hdr)
+{
+   /*
+* Check if the packet has a header
+* that contains a seq_ctrl field.
+*/
+   if (ieee80211_get_hdrlen(
+   le16_to_cpu(ieee80211hdr->frame_control)) >= IEEE80211_HEADER)
+   return 1;
+   return 0;
+}
+
+static inline void rt2x00_set_sequence(struct sk_buff *skb, u16 *seq)
+{
+   struct ieee80211_hdr *ieee80211hdr =
+   (struct ieee80211_hdr*)skb->data;
+
+   /*
+* Only attach the sequence number, when
+* the buffer requires it.
+*/
+   if (!rt2x00_require_sequence(ieee80211hdr))
+   return;
+
+   /*
+* Set the sequence number for this frame,
+* but do not change the fragment number.
+*/
+   ieee80211hdr->seq_ctrl |= cpu_to_le16((*seq << 4) & 0xfff0);
+
+   /*
+* Since the dscape stack sends all packets and
+* fragments individually, we need to check if there
+* will be new fragments following.
+* If this is the last or only fragment, the sequence
+* counter should be increased.
+*/
+   if (!ieee80211_get_morefrag(ieee80211hdr))
+   *seq = (*seq + 1) & 0x0fff;
+}
+
+/*
  * Duration calculations
  * The rate variable passed

Re: [PATCH 12/24] RT2x00: Add new rt73usb devices

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Add new rt73usb devices.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-scan/drivers/net/wireless/d80211/rt2x00/rt73usb.c  
2006-07-23 22:35:17.0 +0200
+++ wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c
2006-07-23 22:47:41.0 +0200
@@ -3119,6 +3119,8 @@
{ USB_DEVICE(0x07d1, 0x3c04) },
/* Gigabyte */
{ USB_DEVICE(0x1044, 0x8008) },
+   /* Linksys */
+   { USB_DEVICE(0x13b1, 0x0020) },
/* MSI */
{ USB_DEVICE(0x0db0, 0x6877) },
{ USB_DEVICE(0x0db0, 0xa874) },
@@ -3127,6 +3129,8 @@
{ USB_DEVICE(0x148f, 0x2671) },
/* Qcom */
{ USB_DEVICE(0x18e8, 0x6196) },
+   /* Sitecom */
+   { USB_DEVICE(0x0df6, 0x9712) },
{ 0, }
 };
 
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 14/24] RT2x00: Check if read eeprom words are valid

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Make checks if the EEPROM data read is valid,
if it is not, use the default values.
Also fix the endian issue when reading the PCI_CONFIG_HEADER.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-eeprom/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-23 23:04:25.0 +0200
+++ wireless-dev-eeprom/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-23 23:19:17.0 +0200
@@ -2914,6 +2914,7 @@
u32 reg;
u16 value;
u16 eeprom;
+   u16 device;
 
/*
 * 1 - Detect EEPROM width.
@@ -2934,12 +2935,11 @@
 * To determine the RT chip we have to read the
 * PCI header of the device.
 */
-   pci_read_config_dword(rt2x00dev_pci(rt2x00dev),
-   PCI_CONFIG_HEADER, ®);
-   reg = rt2x00_get_field32(reg, PCI_CONFIG_HEADER_DEVICE);
+   pci_read_config_word(
+   rt2x00dev_pci(rt2x00dev), PCI_CONFIG_HEADER_DEVICE, &device);
 
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-   rt2x00_set_chip(&rt2x00dev->chip, (u16)reg, value);
+   rt2x00_set_chip(&rt2x00dev->chip, device, value);
 
if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
!rt2x00_rf(&rt2x00dev->chip, RF5325) &&
@@ -2985,6 +2985,8 @@
 * 8 - Read external LNA informations.
 */
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+   if (eeprom == 0x)
+   eeprom = 0;
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
SET_FLAG(rt2x00dev, CONFIG_EXTERNAL_LNA_A);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
@@ -2994,58 +2996,35 @@
 * 9 - Store led settings, for correct led behaviour.
 */
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
-   if (eeprom == 0x) {
-   rt2x00dev->led_mode = LED_MODE_DEFAULT;
 
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_LED_MODE, LED_MODE_DEFAULT);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_0, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_1, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_2, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_3, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_4, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_ACT, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_READY_BG, 1);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_READY_A, 1);
-   } else {
+   /*
+* If the eeprom value is invalid,
+* switch to default led mode.
+*/
+   if (eeprom == 0x)
+   rt2x00dev->led_mode = LED_MODE_DEFAULT;
+   else
rt2x00dev->led_mode = rt2x00_get_field16(eeprom,
EEPROM_LED_LED_MODE);
 
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_LED_MODE, rt2x00dev->led_mode);
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_0, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_GPIO_0));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_1, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_GPIO_1));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_2, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_GPIO_2));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_3, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_GPIO_3));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_GPIO_4, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_GPIO_4));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_ACT, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_ACT));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_READY_BG, rt2x00_get_field16(eeprom,
-   EEPROM_LED_POLARITY_RDY_G));
-   rt2x00_set_field16(&rt2x00dev->led_reg,
-   MCU_LEDCS_POLARITY_READY_A, rt2x00_get_field16(eeprom,
-

Re: [PATCH 7/24] RT2x00: Add RTS frame creation

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Support RTS.
When rts is required, create the frame and send it out
before the rest of the frames.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 17:24:56.0 +0200
+++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 18:16:35.0 +0200
@@ -863,6 +863,36 @@
 }
 
 /*
+ * RTS frame creation.
+ */
+static struct sk_buff* rt2400pci_create_rts(struct rt2x00_dev *rt2x00dev,
+   struct ieee80211_hdr *hdr, unsigned short duration)
+{
+   struct ieee80211_hdr *ieee80211hdr;
+   struct sk_buff *skb;
+   u16 temp;
+
+   skb = dev_alloc_skb(IEEE80211_HEADER);
+   if (!skb)
+   return NULL;
+
+   /*
+* Copy the entire header over to RTS frame.
+*/
+   memcpy(skb_put(skb, IEEE80211_HEADER), hdr, IEEE80211_HEADER);
+   ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+
+   temp = (WLAN_FC_TYPE_CTRL  << 2) | (WLAN_FC_STYPE_RTS << 4);
+   ieee80211hdr->frame_control = cpu_to_le16(temp);
+
+   ieee80211hdr->duration_id += cpu_to_le16(duration);
+
+   ieee80211hdr->seq_ctrl = 0;
+
+   return skb;
+}
+
+/*
  * TX descriptor initialization
  */
 static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
@@ -876,15 +906,32 @@
u16 length_low;
u16 signal;
u16 service;
+   u16 frame_control;
+   u8 bitrate;
+   int tx_rate;
+
+   /*
+* Check which rate should be used for this frame.
+*/
+   frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+   if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS &&
+   control->rts_cts_rate)
+   tx_rate = control->rts_cts_rate;
+   else
+   tx_rate = control->tx_rate;
 
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 1);
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
 
/*
-* TODO: IFS can be various values, where can we find
-* which one we want to use?
+* Set IFS to IFS_SIFS when the this is not the first fragment,
+* or this fragment came after RTS/CTS.
 */
-   rt2x00_set_field32(&txd->word0, TXD_W0_IFS, 0);
+   if ((WLAN_GET_SEQ_FRAG(le16_to_cpu(ieee80211hdr->seq_ctrl)) > 0) ||
+   control->use_rts_cts)
+   rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_SIFS);
+   else
+   rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_BACKOFF);
 
if (control->queue == IEEE80211_TX_QUEUE_BEACON)
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 1);
@@ -896,16 +943,15 @@
 */
rt2x00_set_field32(&txd->word0, TXD_W0_RETRY_MODE, 0);
 
-   if (ieee80211hdr->frame_control & WLAN_FC_MOREFRAG)
+   if (frame_control & WLAN_FC_MOREFRAG)
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 0);
 
-   /*
-* TODO: Does this field mean device will send RTS, or that this
-* frame is an RTS frame?
-*/
-   rt2x00_set_field32(&txd->word0, TXD_W0_RTS, control->use_rts_cts);
+   if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
+   rt2x00_set_field32(&txd->word10, TXD_W10_RTS, 1);
+   else
+   rt2x00_set_field32(&txd->word10, TXD_W10_RTS, 0);
 
rt2x00_set_field32(&txd->word2, TXD_W2_DATABYTE_COUNT, skb->len);
 
@@ -918,9 +964,9 @@
 * Convert length to microseconds.
 */
residual = get_duration_res(length,
-   DEVICE_GET_RATE_FIELD(control->tx_rate, RATE));
+   DEVICE_GET_RATE_FIELD(tx_rate, RATE));
length = get_duration(length,
-   DEVICE_GET_RATE_FIELD(control->tx_rate, RATE));
+   DEVICE_GET_RATE_FIELD(tx_rate, RATE));
 
if (residual)
length++;
@@ -938,8 +984,8 @@
length_high = 0x8000 | 0x0700 | (length >> 8);
length_low = 0x8000 | 0x0800 | (length & 0xff);
 
-   signal = 0x8500 | DEVICE_GET_RATE_FIELD(control->tx_rate, PLCP);
-   if (DEVICE_GET_RATE_FIELD(control->tx_rate, PREAMBLE))
+   signal = 0x8500 | DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
+   if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
signal |= 0x0008;
 
service = 0x0600 | 0x0004;
@@ -1089,8 +1135,9 @@
entry->tx_status.retry_count = rt2x00_get_field32(
txd->word0, TXD_W0_RETRY_COUNT);
 
-   ieee80211_tx_status(ring->net_dev,
-   entry->skb, &entry->tx_status);
+   if (!GET_FLAG(entry, ENTRY_RTS_FRAME))
+   ieee80211_tx_status(ring->net_dev,
+  

Re: [PATCH 9/24] RT2x00: Don't use driver_data and driver_info fields

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

driver_info and driver_data are not required for rt2x00,
neither is there any need to check that field when the probe()
function is called. The PCI and USB layers already correctly
make the checks.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-23 18:34:06.0 +0200
+++ wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-23 19:36:40.0 +0200
@@ -2670,11 +2670,6 @@
struct net_device *net_dev;
int status;
 
-   if (unlikely(id->driver_data != RT2460)) {
-   ERROR("Detected device not supported.\n");
-   return -ENODEV;
-   }
-
if (pci_enable_device(pci_dev)) {
ERROR("Enable device failed.\n");
return -EIO;
@@ -2839,7 +2834,7 @@
DRV_NAME " - " DRV_VERSION " (" DRV_RELDATE ") by " DRV_PROJECT;
 
 static struct pci_device_id rt2400pci_device_table[] = {
-   { PCI_DEVICE(0x1814, 0x0101), .driver_data = RT2460},
+   { PCI_DEVICE(0x1814, 0x0101) },
{ 0, }
 };
 
diff -rU3 wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-23 18:34:14.0 +0200
+++ wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-23 19:33:46.0 +0200
@@ -2936,11 +2936,6 @@
struct net_device *net_dev;
int status;
 
-   if (unlikely(id->driver_data != RT2560)) {
-   ERROR("Detected device not supported.\n");
-   return -ENODEV;
-   }
-
if (pci_enable_device(pci_dev)) {
ERROR("Enable device failed.\n");
return -EIO;
@@ -3105,7 +3100,7 @@
DRV_NAME " - " DRV_VERSION " (" DRV_RELDATE ") by " DRV_PROJECT;
 
 static struct pci_device_id rt2500pci_device_table[] = {
-   { PCI_DEVICE(0x1814, 0x0201), .driver_data = RT2560},
+   { PCI_DEVICE(0x1814, 0x0201) },
{ 0, }
 };
 
diff -rU3 wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-state/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-23 18:36:12.0 +0200
+++ wireless-dev-dev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
2006-07-23 19:36:18.0 +0200
@@ -2545,11 +2545,6 @@
struct net_device *net_dev;
int status;
 
-   if (unlikely(id->driver_info != RT2570)) {
-   ERROR("Detected device not supported.\n");
-   return -ENODEV;
-   }
-
usb_dev = usb_get_dev(usb_dev);
 
net_dev = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), NULL);
@@ -2682,46 +2677,46 @@
 
 static struct usb_device_id rt2500usb_device_table[] = {
/* ASUS */
-   { USB_DEVICE(0x0b05, 0x1706), .driver_info = RT2570},
-   { USB_DEVICE(0x0b05, 0x1707), .driver_info = RT2570},
+   { USB_DEVICE(0x0b05, 0x1706) },
+   { USB_DEVICE(0x0b05, 0x1707) },
/* Belkin */
-   { USB_DEVICE(0x050d, 0x7050), .driver_info = RT2570},
-   { USB_DEVICE(0x050d, 0x7051), .driver_info = RT2570},
-   { USB_DEVICE(0x050d, 0x705a), .driver_info = RT2570},
+   { USB_DEVICE(0x050d, 0x7050) },
+   { USB_DEVICE(0x050d, 0x7051) },
+   { USB_DEVICE(0x050d, 0x705a) },
/* Cisco Systems */
-   { USB_DEVICE(0x13b1, 0x000d), .driver_info = RT2570},
-   { USB_DEVICE(0x13b1, 0x0011), .driver_info = RT2570},
-   { USB_DEVICE(0x13b1, 0x001a), .driver_info = RT2570},
+   { USB_DEVICE(0x13b1, 0x000d) },
+   { USB_DEVICE(0x13b1, 0x0011) },
+   { USB_DEVICE(0x13b1, 0x001a) },
/* Conceptronic */
-   { USB_DEVICE(0x14b2, 0x3c02), .driver_info = RT2570},
+   { USB_DEVICE(0x14b2, 0x3c02) },
/* D-LINK */
-   { USB_DEVICE(0x2001, 0x3c00), .driver_info = RT2570},
+   { USB_DEVICE(0x2001, 0x3c00) },
/* Gigabyte */
-   { USB_DEVICE(0x1044, 0x8001), .driver_info = RT2570},
-   { USB_DEVICE(0x1044, 0x8007), .driver_info = RT2570},
+   { USB_DEVICE(0x1044, 0x8001) },
+   { USB_DEVICE(0x1044, 0x8007) },
/* Hercules */
-   { USB_DEVICE(0x06f8, 0xe000), .driver_info = RT2570},
+   { USB_DEVICE(0x06f8, 0xe000) },
/* Melco */
-   { USB_DEVICE(0x0411, 0x0066), .driver_info = RT2570},
-   { USB_DEVICE(0x0411, 0x0067), .driver_info = RT2570},
-   { USB_DEVICE(0x0411, 0x008b), .driver_info = RT2570},
+   { USB_DEVICE(0x0411, 0x0066) },
+   { USB_DEVICE(0x0411, 0x0067) },
+   { USB_DEVICE(0x0411, 0x008b) },
/* MSI */
-   { USB_DEVICE(0x0db0, 0x6861), .driver_info = RT2570},
-   { USB_DEVICE(0x0db0, 0x6865), 

Re: [PATCH 13/24] RT2x00: Allow link tuning while scanning

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

rt2x00 does not know when we are scanning,
unless passive_scan() is being used.
For consistent behaviour we should not block
tuning while scanning.
We should however not tune the connection when
it has been disabled in the hardware.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c  
2006-07-23 22:41:58.0 +0200
+++ wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt2500pci.c  
2006-07-23 22:59:00.0 +0200
@@ -811,9 +811,10 @@
u8 reg_r17;
 
/*
-* Don't perform any tuning during scan.
+* Don't perform any tuning when it is disabled
+* in the EEPROM.
 */
-   if (rt2x00dev->scan)
+   if (GET_FLAG(rt2x00dev, CONFIG_DISABLE_BBP_TUNING))
return;
 
rt2x00_register_read(rt2x00dev, CSR0, ®);
@@ -2488,7 +2489,16 @@
SET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON);
 
/*
-* 7 - Read BBP data from EEPROM and store in private structure.
+* 7 - Check if the BBP tuning should be enabled.
+*/
+   rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+   if (eeprom == 0x)
+   eeprom = 0;
+   if (rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
+   SET_FLAG(rt2x00dev, CONFIG_DISABLE_BBP_TUNING);
+
+   /*
+* 8 - Read BBP data from EEPROM and store in private structure.
 */
rt2x00dev->eeprom = kzalloc(EEPROM_BBP_SIZE * sizeof(u16), GFP_KERNEL);
if (!rt2x00dev->eeprom)
diff -rU3 wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c  
2006-07-23 22:42:03.0 +0200
+++ wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt2500usb.c  
2006-07-23 23:00:43.0 +0200
@@ -617,15 +617,16 @@
  */
 static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev, char rssi)
 {
-   u16  reg;
+   u16 reg;
u8 reg_r17;
u8 up_bound;
u8 low_bound;
 
/*
-* Don't perform any tuning during scan.
+* Don't perform any tuning when it is disabled
+* in the EEPROM.
 */
-   if (rt2x00dev->scan)
+   if (GET_FLAG(rt2x00dev, CONFIG_DISABLE_BBP_TUNING))
return;
 
low_bound = 0x32;
@@ -2105,7 +2106,16 @@
EEPROM_ANTENNA_LED_MODE);
 
/*
-* 5 - Read BBP data from EEPROM and store in private structure.
+* 5 - Check if the BBP tuning should be disabled.
+*/
+   rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+   if (eeprom == 0x)
+   eeprom = 0;
+   if (rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
+   SET_FLAG(rt2x00dev, CONFIG_DISABLE_BBP_TUNING);
+
+   /*
+* 6 - Read BBP data from EEPROM and store in private structure.
 */
rt2x00dev->eeprom = kzalloc(EEPROM_BBP_SIZE * sizeof(u16), GFP_KERNEL);
if (!rt2x00dev->eeprom)
diff -rU3 wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-23 22:42:09.0 +0200
+++ wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-23 23:04:25.0 +0200
@@ -1043,12 +1043,6 @@
u8 up_bound;
u8 low_bound;
 
-   /*
-* Don't perform any tuning during scan.
-*/
-   if (rt2x00dev->scan)
-   return;
-
if (rt2x00dev->rx_params.phymode == MODE_IEEE80211A) {
up_bound = 0x48;
low_bound = 0x28;
diff -rU3 wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-newdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c
2006-07-23 22:47:41.0 +0200
+++ wireless-dev-tuning/drivers/net/wireless/d80211/rt2x00/rt73usb.c
2006-07-23 23:04:31.0 +0200
@@ -757,12 +757,6 @@
u8 up_bound;
u8 low_bound;
 
-   /*
-* Don't perform any tuning during scan.
-*/
-   if (rt2x00dev->scan)
-   return;
-
if (rt2x00dev->rx_params.phymode == MODE_IEEE80211A) {
up_bound = 0x48;
low_bound = 0x28;
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 15/24] RT2x00: Merge PCI and USB version of data_entry structure

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Merge the data_entry structure for USB and PCI into
a single structure. This means that all access to the data_addr
and desc_addr should now be performed through the functions:
rt2x00pci_desc_addr()
rt2x00pci_data_addr()
And for usb:
rt2x00usb_urb()
rt2x00usb_rxdata_addr()
rt2x00usb_rxdesc_addr()
rt2x00usb_txdata_addr()
rt2x00usb_txdesc_addr()

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-eeprom/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-eeprom/drivers/net/wireless/d80211/rt2x00/rt2400pci.c  
2006-07-23 22:41:51.0 +0200
+++ wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-25 10:44:12.0 +0200
@@ -1039,7 +1039,7 @@
 
while (1) {
entry = rt2x00_get_data_entry(ring);
-   rxd = entry->desc_addr;
+   rxd = rt2x00pci_desc_addr(entry);
 
if (rt2x00_get_field32(rxd->word0, RXD_W0_OWNER_NIC))
break;
@@ -1058,7 +1058,8 @@
 
skb_reserve(skb, NET_IP_ALIGN);
 
-   memcpy(skb_put(skb, size), entry->data_addr, size);
+   memcpy(skb_put(skb, size), rt2x00pci_data_addr(entry),
+   size);
 
rt2x00dev->rx_params.ssi =
rt2x00_get_field32(rxd->word2, RXD_W2_RSSI);
@@ -1100,7 +1101,7 @@
 
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
-   txd = entry->desc_addr;
+   txd = rt2x00pci_desc_addr(entry);
 
if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
!rt2x00_get_field32(txd->word0, TXD_W0_VALID))
@@ -1237,10 +1238,10 @@
  * DMA ring functions.
  */
 static int rt2400pci_alloc_ring(struct rt2x00_dev *rt2x00dev,
-   struct data_ring *ring, void (*handler)(void *),
+   unsigned short type, void (*handler)(void *),
const u16 max_entries, const u16 data_size, const u16 desc_size)
 {
-   struct data_entry *entry;
+   struct data_ring *ring = &rt2x00dev->ring[type];
unsigned int i;
 
/*
@@ -1261,15 +1262,15 @@
 
rt2x00_ring_index_clear(ring);
 
+   ring->type = type;
ring->stats.limit = max_entries;
-   ring->entry_size = sizeof(struct data_entry);
ring->data_size = data_size;
ring->desc_size = desc_size;
 
/*
 * Allocate all ring entries.
 */
-   ring->entry = kmalloc(ring->stats.limit * ring->entry_size,
+   ring->entry = kmalloc(ring->stats.limit * sizeof(struct data_entry),
GFP_KERNEL);
if (!ring->entry)
return -ENOMEM;
@@ -1288,15 +1289,14 @@
 * Initialize all ring entries to contain valid
 * addresses.
 */
-   entry = ring->entry;
for (i = 0; i < ring->stats.limit; i++) {
-   entry[i].skb = NULL;
-   entry[i].desc_addr = ring->data_addr
+   ring->entry[i].skb = NULL;
+   ring->entry[i].priv = ring->data_addr
+ (i * ring->desc_size);
-   entry[i].data_addr = ring->data_addr
+   ring->entry[i].data_addr = ring->data_addr
+ (ring->stats.limit * ring->desc_size)
+ (i * ring->data_size);
-   entry[i].data_dma = ring->data_dma
+   ring->entry[i].data_dma = ring->data_dma
+ (ring->stats.limit * ring->desc_size)
+ (i * ring->data_size);
}
@@ -1329,19 +1329,19 @@
SET_FLAG(rt2x00dev, DEVICE_SUPPORT_ATIM);
 
if (rt2400pci_alloc_ring(
-   rt2x00dev, &rt2x00dev->ring[RING_RX], rt2400pci_rxdone,
+   rt2x00dev, RING_RX, rt2400pci_rxdone,
RX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct rxd)) ||
rt2400pci_alloc_ring(
-   rt2x00dev, &rt2x00dev->ring[RING_TX], rt2400pci_txdone,
+   rt2x00dev, RING_TX, rt2400pci_txdone,
 TX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd)) ||
rt2400pci_alloc_ring(
-   rt2x00dev, &rt2x00dev->ring[RING_ATIM], rt2400pci_txdone,
+   rt2x00dev, RING_ATIM, rt2400pci_txdone,
ATIM_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd)) ||
rt2400pci_alloc_ring(
-   rt2x00dev, &rt2x00dev->ring[RING_PRIO], rt2400pci_txdone,
+   rt2x00dev, RING_PRIO, rt2400pci_txdone,
TX_ENTRIES, DATA_FRAME_SIZE, sizeof(struct txd)) ||
rt2400pci_alloc_ring(
-   rt2x00dev, &rt2x00dev->ring[RING_BEACON], rt2400pci_beacondone,
+   rt2x00dev, RING_BEACON, rt2400pci_beacondone,
BEACON_ENTRIES, MGMT_FRAME_SIZE, sizeof(struct txd))) {
  

Re: [PATCH 21/24] RT2x00: Correctly initialize tx_status->control field before packet transmission

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

The control field inside the tx_status field of each entry
should be correctly initialized when a packet is queued.
We can use the same field to pass it to dscape when updating the beacon.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-26 10:46:52.0 +0200
+++ wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-26 10:55:31.0 +0200
@@ -1587,17 +1587,16 @@
 {
struct data_ring *ring = data;
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(ring->net_dev);
+   struct data_entry *entry = rt2x00_get_data_entry(
+   &rt2x00dev->ring[RING_BEACON]);
struct sk_buff *skb;
-   struct ieee80211_tx_control beacon;
-
-   memset(&beacon, 0x00, sizeof(beacon));
 
skb = ieee80211_beacon_get(ring->net_dev,
-   rt2x00dev->interface.id, &beacon);
+   rt2x00dev->interface.id, &entry->tx_status.control);
if (!skb)
return;
 
-   rt2400pci_beacon_update(ring->net_dev, skb, &beacon);
+   rt2400pci_beacon_update(ring->net_dev, skb, &entry->tx_status.control);
 
dev_kfree_skb_any(skb);
 }
@@ -1881,6 +1880,7 @@
 
memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
rt2400pci_write_tx_desc(rt2x00dev, txd, skb, control);
+   memcpy(&entry->tx_status.control, control, sizeof(*control));
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
SET_FLAG(entry, ENTRY_RTS_FRAME);
entry->skb = skb;
diff -rU3 wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-26 10:46:48.0 +0200
+++ wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-26 10:56:10.0 +0200
@@ -1712,17 +1712,16 @@
 {
struct data_ring *ring = data;
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(ring->net_dev);
+   struct data_entry *entry = rt2x00_get_data_entry(
+   &rt2x00dev->ring[RING_BEACON]);
struct sk_buff *skb;
-   struct ieee80211_tx_control beacon;
-
-   memset(&beacon, 0x00, sizeof(beacon));
 
skb = ieee80211_beacon_get(ring->net_dev,
-   rt2x00dev->interface.id, &beacon);
+   rt2x00dev->interface.id, &entry->tx_status.control);
if (!skb)
return;
 
-   rt2500pci_beacon_update(ring->net_dev, skb, &beacon);
+   rt2500pci_beacon_update(ring->net_dev, skb, &entry->tx_status.control);
 
dev_kfree_skb_any(skb);
 }
@@ -2016,6 +2015,7 @@
 
memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
rt2500pci_write_tx_desc(rt2x00dev, txd, skb, control);
+   memcpy(&entry->tx_status.control, control, sizeof(*control));
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
SET_FLAG(entry, ENTRY_RTS_FRAME);
entry->skb = skb;
diff -rU3 wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-26 10:46:32.0 +0200
+++ wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
2006-07-26 10:56:11.0 +0200
@@ -1447,17 +1447,16 @@
 {
struct data_ring *ring = data;
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(ring->net_dev);
+   struct data_entry *entry = rt2x00_get_data_entry(
+   &rt2x00dev->ring[RING_BEACON]);
struct sk_buff *skb;
-   struct ieee80211_tx_control beacon;
-
-   memset(&beacon, 0x00, sizeof(beacon));
 
skb = ieee80211_beacon_get(ring->net_dev,
-   rt2x00dev->interface.id, &beacon);
+   rt2x00dev->interface.id, &entry->tx_status.control);
if (!skb)
return;
 
-   rt2500usb_beacon_update(ring->net_dev, skb, &beacon);
+   rt2500usb_beacon_update(ring->net_dev, skb, &entry->tx_status.control);
 
dev_kfree_skb_any(skb);
 }
@@ -1715,6 +1714,7 @@
 
memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
rt2500usb_write_tx_desc(rt2x00dev, txd, skb, control);
+   memcpy(&entry->tx_status.control, control, sizeof(*control));
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
SET_FLAG(entry, ENTRY_RTS_FRAME);
entry->skb = skb;
diff -rU3 wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-setnetdev/drivers/net/wireless/d8021

Re: [PATCH 22/24] RT2x00: Optimize config handlers

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Optimize the configuration handlers to only run
when the current configuration has been changed.
This means we need to store the current setting
of most configuration options in rt2x00_dev.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-control/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-26 10:55:31.0 +0200
+++ wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2400pci.c  
2006-07-26 12:49:38.0 +0200
@@ -475,6 +475,14 @@
u32 reg;
 
/*
+* Only continue when there is something to be done.
+*/
+   if (type == rt2x00dev->interface.type ||
+   (rt2x00dev->interface.monitor_count ^
+   GET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR)))
+   return;
+
+   /*
 * Apply hardware packet filter.
 */
rt2x00_register_read(rt2x00dev, RXCSR0, ®);
@@ -520,7 +528,13 @@
/*
 * Update working mode.
 */
-   rt2x00dev->interface.type = type;
+   if (type != IEEE80211_IF_TYPE_MNTR)
+   rt2x00dev->interface.type = type;
+
+   if (rt2x00dev->interface.monitor_count)
+   SET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR);
+   else
+   CLEAR_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR);
 }
 
 static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
@@ -529,6 +543,12 @@
u32 rf1 = rt2x00dev->rf1;
u32 rf3 = rt2x00dev->rf3;
 
+   /*
+* Only continue when there is something to be done.
+*/
+   if (channel == rt2x00dev->rx_params.channel)
+   return;
+
INFO("Switching channel. RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x.\n",
rf1, rf2, rf3);
 
@@ -575,15 +595,31 @@
rt2x00dev->rx_params.channel = channel;
 
/*
+* Update rf fields
+*/
+   rt2x00dev->rf1 = rf1;
+   rt2x00dev->rf2 = rf2;
+   rt2x00dev->rf3 = rf3;
+
+   /*
 * Clear false CRC during channel switch.
 */
rt2x00_register_read(rt2x00dev, CNT0, &rf1);
 }
 
-static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, u8 txpower)
+static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
 {
txpower = TXPOWER_TO_DEV(txpower);
+
+   /*
+* Only continue when there is something to be done.
+*/
+   if (txpower == rt2x00dev->tx_power)
+   return;
+
rt2x00_bbp_write(rt2x00dev, 3, txpower);
+
+   rt2x00dev->tx_power = txpower;
 }
 
 static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev, int antenna)
@@ -591,6 +627,12 @@
u8 reg_rx;
u8 reg_tx;
 
+   /*
+* Only continue when there is something to be done.
+*/
+   if (rt2x00dev->rx_params.antenna == antenna)
+   return;
+
rt2x00_bbp_read(rt2x00dev, 4, ®_rx);
rt2x00_bbp_read(rt2x00dev, 1, ®_tx);
 
@@ -713,6 +755,12 @@
 {
struct ieee80211_rate *rate;
 
+   /*
+* Only continue when there is something to be done.
+*/
+   if (rt2x00dev->rx_params.phymode == phymode)
+   return;
+
rate = &rt2x00dev->hw.modes[0].rates[
rt2x00dev->hw.modes[0].num_rates - 1];
 
@@ -1760,6 +1808,9 @@
if (!reg)
return IRQ_NONE;
 
+   if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
+   return IRQ_HANDLED;
+
/*
 * Handle interrupts, walk through all bits
 * and run the tasks, the bits are checked in order of
@@ -1982,12 +2033,17 @@
u32 reg;
 
/*
-* Some configuration changes require the RX to be disabled.
+* Check if we need to disable the radio,
+* if this is not the case, at least the RX must be disabled.
 */
if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) {
-   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
-   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1);
-   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
+   if (!conf->radio_enabled)
+   rt2400pci_disable_radio(rt2x00dev);
+   else {
+   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
+   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1);
+   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
+   }
}
 
rt2400pci_config_channel(rt2x00dev,
@@ -2000,24 +2056,13 @@
/*
 * Reenable RX only if the radio should be on.
 */
-   if (conf->radio_enabled) {
-   if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) {
-   if (rt2400pci_open(net_dev)) {
-   ERROR("Failed to enabled radio.\n");
- 

Re: [PATCH 16/24] RT2x00: Fix rt61pci interrupt handling

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

rt61pci irq is a bit different compared to the others,
when the irq is raised, we should read from the register which
ring and which entry has been send. And this entry should
be processed. Using a for loop to go through all entries
is no longer working since we require certain statistics
from the registers.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-rt61irq/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-ringentry/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
2006-07-25 14:55:25.0 +0200
+++ wireless-dev-rt61irq/drivers/net/wireless/d80211/rt2x00/rt61pci.c   
2006-07-25 16:13:19.0 +0200
@@ -1473,72 +1473,119 @@
rt61pci_activity_led(rt2x00dev, total_rssi);
 }
 
-static void rt61pci_txdone(void *data)
+static void rt61pci_txdone_entry(struct data_entry *entry, u32 sta_csr4)
 {
-   struct data_ring *ring = data;
-   struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(ring->net_dev);
-   struct data_entry *entry;
+   struct rt2x00_dev *rt2x00dev =
+   ieee80211_dev_hw_data(entry->ring->net_dev);
struct txd *txd;
int tx_status;
int ack;
-   int reg;
int ring_full;
 
+   txd = rt2x00pci_desc_addr(entry);
+
+   if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
+   !rt2x00_get_field32(txd->word0, TXD_W0_VALID))
+   return;
+
+   ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
+
/*
-* Store the current status of the ring.
+* TODO: How can te below field be set correctly?
 */
-   ring_full = rt2x00_ring_full(ring);
+   entry->tx_status.tx_filtered = 0;
 
-   while (!rt2x00_ring_empty(ring)) {
-   entry = rt2x00_get_data_entry_done(ring);
-   txd = rt2x00pci_desc_addr(entry);
+   entry->tx_status.queue_length = entry->ring->stats.limit;
 
-   rt2x00_register_read(rt2x00dev, STA_CSR4, ®);
+   /*
+* The TXD_W0_RESULT field will only be set when
+* we had requested an ACK. So we have received an
+* ACK response when ACK was requested and status
+* was succesfull.
+*/
+   tx_status = rt2x00_get_field32(sta_csr4, STA_CSR4_TX_RESULT);
+   entry->tx_status.ack = 0;
+   if (ack && (tx_status == TX_SUCCESS ||
+   tx_status == TX_SUCCESS_RETRY))
+   entry->tx_status.ack = 1;
+   else if (ack && tx_status == TX_FAIL_RETRY) {
+   rt2x00dev->low_level_stats.dot11ACKFailureCount++;
+   entry->tx_status.excessive_retries++;
+   }
 
-   if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
-   !rt2x00_get_field32(txd->word0, TXD_W0_VALID) ||
-   !rt2x00_get_field32(reg, STA_CSR4_VALID))
-   break;
+   rt2x00_bbp_read(rt2x00dev, 32,
+   (u8*)&entry->tx_status.ack_signal);
 
-   ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
+   entry->tx_status.retry_count = rt2x00_get_field32(
+   sta_csr4, STA_CSR4_RETRY_COUNT);
 
-   /*
-* TODO: How can te below field be set correctly?
-*/
-   entry->tx_status.tx_filtered = 0;
+   if (!GET_FLAG(entry, ENTRY_RTS_FRAME))
+   ieee80211_tx_status(entry->ring->net_dev,
+   entry->skb, &entry->tx_status);
 
-   entry->tx_status.queue_length = ring->stats.limit;
+   rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+   entry->skb = NULL;
 
-   /*
-* The TXD_W0_RESULT field will only be set when
-* we had requested an ACK. So we have received an
-* ACK response when ACK was requested and status
-* was succesfull.
-*/
-   tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
-   entry->tx_status.ack = 0;
-   if (ack && (tx_status == TX_SUCCESS ||
-   tx_status == TX_SUCCESS_RETRY))
-   entry->tx_status.ack = 1;
-   else if (ack && tx_status == TX_FAIL_RETRY) {
-   rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-   entry->tx_status.excessive_retries++;
-   }
+   /*
+* Store the current status of the ring.
+*/
+   ring_full = rt2x00_ring_full(entry->ring);
 
-   rt2x00_bbp_read(rt2x00dev, 32,
-   (u8*)&entry->tx_status.ack_signal);
+   rt2x00_ring_index_done_inc(entry->ring);
 
-   entry->tx_status.retry_count = rt2x00_get_field32(
-   reg, STA_CSR4_RETRY_COUNT);
+   /*
+* If the data ring was full before the txdone handler
+* we must make sure the packet queue in the d80211 stack

Re: [PATCH 23/24] RT2x00: Fix register initialization

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Thanks to ethtool a lot of problems with initialization
of the registers has been discovered.
This will correctly initialize all registers.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2400pci.c  
2006-07-26 12:49:38.0 +0200
+++ wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-26 14:04:13.0 +0200
@@ -482,6 +482,8 @@
GET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR)))
return;
 
+   rt2x00_register_write(rt2x00dev, CSR14, 0);
+
/*
 * Apply hardware packet filter.
 */
@@ -513,16 +515,40 @@
rt2400pci_config_promisc(rt2x00dev, 1);
 
/*
+* Enable beacon config
+*/
+   rt2x00_register_read(rt2x00dev, BCNCSR1, ®);
+   rt2x00_set_field32(®, BCNCSR1_PRELOAD,
+   PREAMBLE + get_duration(IEEE80211_HEADER, 2));
+   rt2x00_register_write(rt2x00dev, BCNCSR1, reg);
+
+   /*
 * Enable synchronisation.
 */
+   rt2x00_register_read(rt2x00dev, CSR12, ®);
+   rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, 100 * 16);
+   rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, 100 * 16);
+   rt2x00_register_write(rt2x00dev, CSR12, reg);
+
rt2x00_register_read(rt2x00dev, CSR14, ®);
-   rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
-   if (type == IEEE80211_IF_TYPE_IBSS)
+   if (type != IEEE80211_IF_TYPE_MNTR) {
+   rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
+   rt2x00_set_field32(®, CSR14_TBCN, 1);
+   }
+
+   if (type == IEEE80211_IF_TYPE_IBSS) {
rt2x00_set_field32(®, CSR14_TSF_SYNC, 2);
-   else if (type == IEEE80211_IF_TYPE_STA)
+   rt2x00_set_field32(®, CSR14_BEACON_GEN, 1);
+   } else if (type == IEEE80211_IF_TYPE_STA) {
rt2x00_set_field32(®, CSR14_TSF_SYNC, 1);
-   else
+   rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
+   } else if (type == IEEE80211_IF_TYPE_AP) {
rt2x00_set_field32(®, CSR14_TSF_SYNC, 0);
+   rt2x00_set_field32(®, CSR14_BEACON_GEN, 1);
+   } else if (type == IEEE80211_IF_TYPE_MNTR) {
+   rt2x00_set_field32(®, CSR14_TSF_SYNC, 0);
+   rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
+   }
rt2x00_register_write(rt2x00dev, CSR14, reg);
 
/*
@@ -726,7 +752,7 @@
 
reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
 
-   rt2x00_register_write(rt2x00dev, ARCSR1, reg[0]);
+   rt2x00_register_write(rt2x00dev, ARCSR1, cpu_to_le32(reg[0]));
 
rt2x00_register_read(rt2x00dev, TXCSR1, ®[0]);
value = SIFS + PLCP
@@ -830,8 +856,8 @@
 
rt2x00_register_read(rt2x00dev, LEDCSR, ®);
 
-   rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 30);
-   rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 70);
+   rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70);
+   rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30);
 
if (rt2x00dev->led_mode == LED_MODE_TXRX_ACTIVITY) {
rt2x00_set_field32(®, LEDCSR_LINK, 1);
diff -rU3 wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-config/drivers/net/wireless/d80211/rt2x00/rt2500pci.c  
2006-07-26 12:50:25.0 +0200
+++ wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-26 14:04:55.0 +0200
@@ -482,6 +482,8 @@
GET_FLAG(rt2x00dev, INTERFACE_ENABLED_MONITOR)))
return;
 
+   rt2x00_register_write(rt2x00dev, CSR14, 0);
+
/*
 * Apply hardware packet filter.
 */
@@ -516,16 +518,44 @@
rt2500pci_config_promisc(rt2x00dev, 1);
 
/*
+* Enable beacon config
+*/
+   if (ring) {
+   rt2x00_register_read(rt2x00dev, BCNCSR1, ®);
+   rt2x00_set_field32(®, BCNCSR1_PRELOAD,
+   PREAMBLE + get_duration(IEEE80211_HEADER, 2));
+   rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN,
+   rt2x00dev->ring[RING_BEACON].tx_params.cw_min);
+   rt2x00_register_write(rt2x00dev, BCNCSR1, reg);
+   }
+
+   /*
 * Enable synchronisation.
 */
+   rt2x00_register_read(rt2x00dev, CSR12, ®);
+   rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, 100 * 16);
+   rt2x00_set_field32(®, CSR12_CFPMAX_DURATION, 100 * 16);
+   rt2x00_register_write(rt2x00dev, CSR12, reg);
+
rt2x00_register_read(rt2x00dev, CSR14, ®);
-   rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
-   if (type == IEEE80211_IF_TYPE_IBSS)
+   if (type != IEEE80211_IF_TYPE_MNTR) {
+   rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
+ 

Re: [PATCH 20/24] RT2x00: Use SET_NETDEV_DEV

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Use SET_NETDEV_DEV to help userspace detect the wireless interfaces.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-26 10:41:21.0 +0200
+++ wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-26 10:46:52.0 +0200
@@ -2795,6 +2795,7 @@
}
 
SET_ETHTOOL_OPS(net_dev, &rt2400pci_ethtool_ops);
+   SET_NETDEV_DEV(net_dev, &pci_dev->dev);
 
pci_set_drvdata(pci_dev, net_dev);
 
diff -rU3 wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-26 10:41:32.0 +0200
+++ wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-26 10:46:48.0 +0200
@@ -3066,6 +3066,7 @@
}
 
SET_ETHTOOL_OPS(net_dev, &rt2500pci_ethtool_ops);
+   SET_NETDEV_DEV(net_dev, &pci_dev->dev);
 
pci_set_drvdata(pci_dev, net_dev);
 
diff -rU3 wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-26 10:42:02.0 +0200
+++ wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-26 10:46:32.0 +0200
@@ -2686,6 +2686,7 @@
}
 
SET_ETHTOOL_OPS(net_dev, &rt2500usb_ethtool_ops);
+   SET_NETDEV_DEV(net_dev, &usb_intf->dev);
 
usb_set_intfdata(usb_intf, net_dev);
 
diff -rU3 wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
2006-07-26 10:41:48.0 +0200
+++ wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt61pci.c 
2006-07-26 10:46:44.0 +0200
@@ -3634,6 +3634,7 @@
}
 
SET_ETHTOOL_OPS(net_dev, &rt61pci_ethtool_ops);
+   SET_NETDEV_DEV(net_dev, &pci_dev->dev);
 
pci_set_drvdata(pci_dev, net_dev);
 
diff -rU3 wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
2006-07-26 10:42:19.0 +0200
+++ wireless-dev-setnetdev/drivers/net/wireless/d80211/rt2x00/rt73usb.c 
2006-07-26 10:46:22.0 +0200
@@ -3081,6 +3081,7 @@
}
 
SET_ETHTOOL_OPS(net_dev, &rt73usb_ethtool_ops);
+   SET_NETDEV_DEV(net_dev, &usb_intf->dev);
 
usb_set_intfdata(usb_intf, net_dev);
 
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 19/24] RT2x00: Simplify *_reset() functions

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

The reset function can be greatly simplified.
when a reset is required the best thing to do,
is to switch the radio off and on again.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-25 23:27:17.0 +0200
+++ wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2400pci.c   
2006-07-26 10:41:21.0 +0200
@@ -1905,42 +1905,9 @@
 static int rt2400pci_reset(struct net_device *net_dev)
 {
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
-   u32 reg;
-
-   /*
-* Cancel RX and TX.
-*/
-   rt2x00_register_read(rt2x00dev, TXCSR0, ®);
-   rt2x00_set_field32(®, TXCSR0_ABORT, 1);
-   rt2x00_register_write(rt2x00dev, TXCSR0, reg);
-
-   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
-   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1);
-   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
-
-   /*
-* Clear interrupts.
-*/
-   rt2x00_register_read(rt2x00dev, CSR7, ®);
-   rt2x00_register_write(rt2x00dev, CSR7, reg);
 
-   /*
-* Clear all rings, and reinitialize.
-*/
-   rt2400pci_init_rxdesc(rt2x00dev, &rt2x00dev->ring[RING_RX]);
-   rt2400pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_TX]);
-   rt2400pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_ATIM]);
-   rt2400pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_PRIO]);
-   rt2400pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_BEACON]);
-
-   /*
-* Enable RX again.
-*/
-   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
-   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0);
-   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
-
-   return 0;
+   rt2400pci_disable_radio(rt2x00dev);
+   return rt2400pci_enable_radio(rt2x00dev);
 }
 
 static int rt2400pci_add_interface(struct net_device *net_dev,
diff -rU3 wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-25 23:27:54.0 +0200
+++ wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500pci.c   
2006-07-26 10:41:32.0 +0200
@@ -2040,42 +2040,9 @@
 static int rt2500pci_reset(struct net_device *net_dev)
 {
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
-   u32 reg;
-
-   /*
-* Cancel RX and TX.
-*/
-   rt2x00_register_read(rt2x00dev, TXCSR0, ®);
-   rt2x00_set_field32(®, TXCSR0_ABORT, 1);
-   rt2x00_register_write(rt2x00dev, TXCSR0, reg);
-
-   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
-   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1);
-   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
-
-   /*
-* Clear interrupts.
-*/
-   rt2x00_register_read(rt2x00dev, CSR7, ®);
-   rt2x00_register_write(rt2x00dev, CSR7, reg);
 
-   /*
-* Clear all rings, and reinitialize.
-*/
-   rt2500pci_init_rxdesc(rt2x00dev, &rt2x00dev->ring[RING_RX]);
-   rt2500pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_TX]);
-   rt2500pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_ATIM]);
-   rt2500pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_PRIO]);
-   rt2500pci_init_txdesc(rt2x00dev, &rt2x00dev->ring[RING_BEACON]);
-
-   /*
-* Enable RX again.
-*/
-   rt2x00_register_read(rt2x00dev, RXCSR0, ®);
-   rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0);
-   rt2x00_register_write(rt2x00dev, RXCSR0, reg);
-
-   return 0;
+   rt2500pci_disable_radio(rt2x00dev);
+   return rt2500pci_enable_radio(rt2x00dev);
 }
 
 static int rt2500pci_add_interface(struct net_device *net_dev,
diff -rU3 wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
2006-07-25 23:28:54.0 +0200
+++ wireless-dev-reset/drivers/net/wireless/d80211/rt2x00/rt2500usb.c   
2006-07-26 10:42:02.0 +0200
@@ -1738,28 +1738,12 @@
return NETDEV_TX_OK;
 }
 
-static inline void rt2500usb_reset_ring(struct data_ring *ring)
-{
-   unsigned int i;
-
-   for (i = 0; i < ring->stats.limit; i++)
-   usb_kill_urb(ring->entry[i].urb);
-}
-
 static int rt2500usb_reset(struct net_device *net_dev)
 {
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
-   rt2500usb_reset_ring(&rt2x00dev->ring[RING_RX]);
-   rt2500usb_reset_ring(&rt2x00dev->ring[RING_TX]);
-   rt2500usb_reset_ring(&rt2x00dev->ring[RING_ATIM]);
-   rt2500usb_reset_ring(&rt2x00dev->ring[RING_PRIO]);
-   rt2500usb_reset_ring(

Re: [PATCH 24/24] RT2x00: Misc. fixes

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Misc. fixes
* Compile fixes
* Code style fixes previously overlooked
* Better check of return values of functions

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-misc/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-26 15:39:52.0 +0200
+++ wireless-dev-misc/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-26 15:56:37.0 +0200
@@ -360,7 +360,7 @@
rt2x00dev, rt2x00_get_field32(reg, GPIOCSR_BIT0));
 }
 #else /* CONFIG_RT2400PCI_BUTTON */
-static void rt2400pci_button_poll(struct rt2x00_dev *rt2x00dev){}
+static void rt2400pci_button_poll(unsigned long data){}
 #endif /* CONFIG_RT2400PCI_BUTTON */
 
 /*
@@ -1520,7 +1520,7 @@
 {
struct ieee80211_hdr *ieee80211hdr;
struct sk_buff *skb;
-   u16 temp;
+   u16 frame_control;
 
skb = dev_alloc_skb(IEEE80211_HEADER);
if (!skb)
@@ -1532,8 +1532,8 @@
memcpy(skb_put(skb, IEEE80211_HEADER), hdr, IEEE80211_HEADER);
ieee80211hdr = (struct ieee80211_hdr*)skb->data;
 
-   temp = (WLAN_FC_TYPE_CTRL  << 2) | (WLAN_FC_STYPE_RTS << 4);
-   ieee80211hdr->frame_control = cpu_to_le16(temp);
+   frame_control = (WLAN_FC_TYPE_CTRL  << 2) | (WLAN_FC_STYPE_RTS << 4);
+   ieee80211hdr->frame_control = cpu_to_le16(frame_control);
 
ieee80211hdr->duration_id += cpu_to_le16(duration);
 
@@ -1559,7 +1559,7 @@
u16 frame_control;
u8 bitrate;
int tx_rate;
- 
+
/*
 * Check which rate should be used for this frame.
 */
@@ -1593,16 +1593,16 @@
 */
rt2x00_set_field32(&txd->word0, TXD_W0_RETRY_MODE, 0);
 
-   if (frame_control & WLAN_FC_MOREFRAG)
+   if (ieee80211_get_morefrag(ieee80211hdr))
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 0);
- 
+
if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
rt2x00_set_field32(&txd->word0, TXD_W0_RTS, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_RTS, 0);
- 
+
rt2x00_set_field32(&txd->word2, TXD_W2_DATABYTE_COUNT, skb->len);
 
/*
@@ -1613,10 +1613,9 @@
/*
 * Convert length to microseconds.
 */
-   residual = get_duration_res(length,
-   DEVICE_GET_RATE_FIELD(tx_rate, RATE));
-   length = get_duration(length,
-   DEVICE_GET_RATE_FIELD(tx_rate, RATE));
+   bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
+   residual = get_duration_res(length, bitrate);
+   length = get_duration(length, bitrate);
 
if (residual)
length++;
@@ -2627,16 +2626,16 @@
for (i = 0; i < 13; i++) {
channels[i].chan = i + 1;
channels[i].freq = 2407 + ((i + 1) * 5);
-   channels[i].flag = IEEE80211_CHAN_W_IBSS
-   | IEEE80211_CHAN_W_ACTIVE_SCAN | IEEE80211_CHAN_W_SCAN;
+   channels[i].flag = IEEE80211_CHAN_W_IBSS |
+   IEEE80211_CHAN_W_ACTIVE_SCAN | IEEE80211_CHAN_W_SCAN;
channels[i].val = cpu_to_le32(vals[i]);
channels[i].antenna_max = 0xff;
}
 
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].flag = IEEE80211_CHAN_W_IBSS |
+   IEEE80211_CHAN_W_ACTIVE_SCAN | IEEE80211_CHAN_W_SCAN;
channels[13].val = cpu_to_le32(vals[13]);
channels[13].antenna_max = 0xff;
 
@@ -2852,9 +2851,10 @@
struct net_device *net_dev;
int status;
 
-   if (pci_enable_device(pci_dev)) {
+   status = pci_enable_device(pci_dev);
+   if (status) {
ERROR("Enable device failed.\n");
-   return -EIO;
+   return status;
}
 
pci_set_master(pci_dev);
@@ -2869,9 +2869,9 @@
goto exit_disable_device;
}
 
-   if (pci_request_regions(pci_dev, pci_name(pci_dev))) {
+   status = pci_request_regions(pci_dev, pci_name(pci_dev));
+   if (status) {
ERROR("PCI request regions failed.\n");
-   status = -EBUSY;
goto exit_disable_device;
}
 
diff -rU3 wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-misc/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-reginit/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-26 15:39:52.0 +0200
+++ wireless-dev-misc/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-26 15:56:37.0 +0200
@@ -360,7 +360,7 @@
rt2x00dev, rt2x00_get_field32(reg, GPIOCSR_BIT0));
 }
 

Re: [PATCH 18/24] RT2x00: Make suspend and resume handlers work correctly

2006-07-26 Thread Ivo van Doorn
>From Ivo van Doorn <[EMAIL PROTECTED]>

Fix suspend and resume handlers,
they should no longer use net_dev->open()
and net_dev->stop() since that delivers the wrong behaviour.

Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>

diff -rU3 wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-25 20:21:44.0 +0200
+++ wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 
2006-07-25 23:27:17.0 +0200
@@ -2885,15 +2885,9 @@
NOTICE("Going to sleep.\n");
 
/*
-* If radio was enabled, stop radio and
-* set the resume flag to the radio will be enabled
-* when resuming.
-*/
-   if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) {
-   if (net_dev->stop(net_dev))
-   return -EBUSY;
-   SET_FLAG(rt2x00dev, RADIO_RESUME);
-   }
+* Disable the radio.
+*/
+   rt2400pci_disable_radio(rt2x00dev);
 
/*
 * Set device mode to sleep for power management.
@@ -2902,11 +2896,16 @@
return -EBUSY;
 
/*
-* Uninitialize hardware.
+* Uninitialize device.
 */
rt2400pci_uninitialize(rt2x00dev);
 
/*
+* Uninitialize hardware.
+*/
+   rt2400pci_free_dev(net_dev);
+
+   /*
 * Disable PCI.
 */
pci_save_state(pci_dev);
@@ -2934,28 +2933,15 @@
/*
 * Initialize hardware.
 */
-   if (rt2400pci_initialize(rt2x00dev)) {
-   ERROR("Failed to initialize device.\n");
+   if (rt2400pci_alloc_dev(pci_dev, net_dev)) {
+   ERROR("Failed to allocate device.\n");
return -ENOMEM;
}
 
/*
-* Set device mode to awake.
+* Set device mode to awake for power management.
 */
-   if (rt2400pci_set_state(rt2x00dev, STATE_AWAKE))
-   return -EBUSY;
-
-   /*
-* Only enable radio when it was enabled
-* when we suspended.
-*/
-   if (GET_FLAG(rt2x00dev, RADIO_RESUME)) {
-   if (net_dev->open(net_dev))
-   return -EBUSY;
-   CLEAR_FLAG(rt2x00dev, RADIO_RESUME);
-   }
-
-   return 0;
+   return rt2400pci_set_state(rt2x00dev, STATE_AWAKE);
 }
 #endif /* CONFIG_PM */
 
diff -rU3 wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-25 20:21:45.0 +0200
+++ wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 
2006-07-25 23:27:54.0 +0200
@@ -3156,15 +3156,9 @@
NOTICE("Going to sleep.\n");
 
/*
-* If radio was enabled, stop radio and
-* set the resume flag to the radio will be enabled
-* when resuming.
-*/
-   if (GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO)) {
-   if (net_dev->stop(net_dev))
-   return -EBUSY;
-   SET_FLAG(rt2x00dev, RADIO_RESUME);
-   }
+* Disable the radio.
+*/
+   rt2500pci_disable_radio(rt2x00dev);
 
/*
 * Set device mode to sleep for power management.
@@ -3173,11 +3167,16 @@
return -EBUSY;
 
/*
-* Uninitialize hardware.
+* Uninitialize device.
 */
rt2500pci_uninitialize(rt2x00dev);
 
/*
+* Uninitialize hardware.
+*/
+   rt2500pci_free_dev(net_dev);
+
+   /*
 * Disable PCI.
 */
pci_save_state(pci_dev);
@@ -3205,28 +3204,15 @@
/*
 * Initialize hardware.
 */
-   if (rt2500pci_initialize(rt2x00dev)) {
-   ERROR("Failed to initialize device.\n");
+   if (rt2500pci_alloc_dev(pci_dev, net_dev)) {
+   ERROR("Failed to allocate device.\n");
return -ENOMEM;
}
 
/*
-* Set device mode to awake.
+* Set device mode to awake for power management.
 */
-   if (rt2500pci_set_state(rt2x00dev, STATE_AWAKE))
-   return -EBUSY;
-
-   /*
-* Only enable radio when it was enabled
-* when we suspended.
-*/
-   if (GET_FLAG(rt2x00dev, RADIO_RESUME)) {
-   if (net_dev->open(net_dev))
-   return -EBUSY;
-   CLEAR_FLAG(rt2x00dev, RADIO_RESUME);
-   }
-
-   return 0;
+   return rt2500pci_set_state(rt2x00dev, STATE_AWAKE);
 }
 #endif /* CONFIG_PM */
 
diff -rU3 wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 
wireless-dev-suspend/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-init/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-25 20:21:43.0 +0200
+++ wire

[PATCH] via-rhine: NAPI poll enable

2006-07-26 Thread Stephen Hemminger

The poll_enable should be in init_registers before enabling interrupts,
not in tx_timeout. Thanks for spotting it Roger.

Signed-off-by: Stephen Hemminger <[EMAIL PROTECTED]>

--- sky2.orig/drivers/net/via-rhine.c   2006-07-25 13:43:19.0 -0700
+++ sky2/drivers/net/via-rhine.c2006-07-25 13:43:10.0 -0700
@@ -1048,6 +1048,8 @@
 
rhine_set_rx_mode(dev);
 
+   netif_poll_enable(dev);
+
/* Enable interrupts by setting the interrupt mask. */
iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
   IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
@@ -1199,7 +1201,6 @@
dev->trans_start = jiffies;
rp->stats.tx_errors++;
netif_wake_queue(dev);
-   netif_poll_enable(dev);
 }
 
 static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: H/W requirements for NETIF_F_HW_CSUM

2006-07-26 Thread Stephen Hemminger
On Wed, 26 Jul 2006 10:28:00 -0700
"Ravinandan Arakali" <[EMAIL PROTECTED]> wrote:

> Hello,
> Our current NIC does not provide the actual checksum value on receive path.
> Hence we only claim NETIF_F_IP_CSUM instead of the more general
> NETIF_F_HW_CSUM.
> 
> To support this in a future adapter, we would like to know what exactly are
> the requirements (on both Rx and Tx )to claim NETIF_F_HW_CSUM ?

If you set NETIF_F_HW_CSUM, on transmit the adapter if ip_summed is set
will be handed an unchecksummed frame with the offset to stuff the checksum at.
Only difference between NETIF_F_HW_CSUM and NETIF_F_IP_CSUM is that IP_CSUM
means the device can handle IPV4 only.

NETIF_F_HW_CSUM has no impact on receive. The form of receive checksumming 
format
is up to the device. It can either put one's complement in skb->csum and
set ip_summed to CHECKSUM_HW or if device only reports checksum good then
set CHECKSUM_UNNECESSARY.

Several are a couple of subtleties to the receive processing:
* Meaning of ip_summed changes from tx to rx path and that has to be handled
  in code that does forwarding like bridges.
* If device only reports checksum okay vs bad. The packets marked bad might
  be another protocol, so should be passed up with CHECKSUM_NONE and let any
  checksum errors get detected in software.
* Checksum HW on receive should work better since then IPV6 and nested 
protocols like
  VLAN's can be handled.

> Following are some specific questions:
> 1. On Tx, our adapter supports checksumming of TCP/UDP over IPv4 and IPv6.
> This computation is TCP/UDP specific. Does the checksum calculation need to
> be more generic ? Also, skbuff.h says that the checksum needs to be placed
> at a specific location(skb->h.raw+skb->csum). I guess this means the adapter
> needs to pass back the checksum to host driver after transmission. What
> happens in case of TSO ?
> 2. On Rx, is it suffficient if we place the L4 checksum in skb->csum ? What
> about L3 checksum ?
> 

The L3 checksum (IP) is always computed. Since the header is in CPU cache anyway
it is faster that way.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: H/W requirements for NETIF_F_HW_CSUM

2006-07-26 Thread Ravinandan Arakali
Steve,
Thanks for the response.
Pls see my comments below.

> -Original Message-
> From: Stephen Hemminger [mailto:[EMAIL PROTECTED]
> Sent: Wednesday, July 26, 2006 12:16 PM
> To: [EMAIL PROTECTED]
> Cc: netdev@vger.kernel.org; [EMAIL PROTECTED];
> [EMAIL PROTECTED]; [EMAIL PROTECTED];
> [EMAIL PROTECTED]; [EMAIL PROTECTED]; Leonid. Grossman
> (E-mail)
> Subject: Re: H/W requirements for NETIF_F_HW_CSUM
> 
> 
> On Wed, 26 Jul 2006 10:28:00 -0700
> "Ravinandan Arakali" <[EMAIL PROTECTED]> wrote:
> 
> > Hello,
> > Our current NIC does not provide the actual checksum value 
> on receive path.
> > Hence we only claim NETIF_F_IP_CSUM instead of the more general
> > NETIF_F_HW_CSUM.
> > 
> > To support this in a future adapter, we would like to know 
> what exactly are
> > the requirements (on both Rx and Tx )to claim NETIF_F_HW_CSUM ?
> 
> If you set NETIF_F_HW_CSUM, on transmit the adapter if 
> ip_summed is set
> will be handed an unchecksummed frame with the offset to 
> stuff the checksum at.
> Only difference between NETIF_F_HW_CSUM and NETIF_F_IP_CSUM 
> is that IP_CSUM
> means the device can handle IPV4 only.

Since our adapter does IPv4 and IPv6 checksum, do we then satisfy
the requirements to claim NETIF_F_HW_CSUM on Tx side ?
Also, for non-TSO, we can stuff the checksum at specified offset
in skb. What about TSO frames ?

> 
> NETIF_F_HW_CSUM has no impact on receive. The form of receive 
> checksumming format
> is up to the device. It can either put one's complement in 
> skb->csum and
> set ip_summed to CHECKSUM_HW or if device only reports 
> checksum good then
> set CHECKSUM_UNNECESSARY.

The reason for thinking that NETIF_F_HW_CSUM and CHECKSUM_UNNECESSARY
don't go together was a comment from Jeff way back in '04 when our 
driver was initially submitted. Quoting from that mail:

"You CANNOT use NETIF_F_HW_CSUM, when your hardware does not provide the 
checksum value.  You must use NETIF_F_IP_CSUM.  Your use of 
NETIF_F_HW_CSUM + CHECKSUM_UNNECESSARY is flat out incorrect."

> 
> Several are a couple of subtleties to the receive processing:
> * Meaning of ip_summed changes from tx to rx path and that 
> has to be handled
>   in code that does forwarding like bridges.
> * If device only reports checksum okay vs bad. The packets 
> marked bad might
>   be another protocol, so should be passed up with 
> CHECKSUM_NONE and let any
>   checksum errors get detected in software.
> * Checksum HW on receive should work better since then IPV6 
> and nested protocols like
>   VLAN's can be handled.
> 
> > Following are some specific questions:
> > 1. On Tx, our adapter supports checksumming of TCP/UDP over 
> IPv4 and IPv6.
> > This computation is TCP/UDP specific. Does the checksum 
> calculation need to
> > be more generic ? Also, skbuff.h says that the checksum 
> needs to be placed
> > at a specific location(skb->h.raw+skb->csum). I guess this 
> means the adapter
> > needs to pass back the checksum to host driver after 
> transmission. What
> > happens in case of TSO ?
> > 2. On Rx, is it suffficient if we place the L4 checksum in 
> skb->csum ? What
> > about L3 checksum ?
> > 
> 
> The L3 checksum (IP) is always computed. Since the header is 
> in CPU cache anyway
> it is faster that way.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH]NET: Add ECN support for TSO

2006-07-26 Thread Michael Chan
On Fri, 2006-07-14 at 12:12 -0400, Dan Reader wrote:

> If we implement the approach you suggest and all data sent uses TSO, the
> receiver can easily determine the expected codepoint of almost any
> isolated CE packet.  It simply has to look at the segment before and the
> segment after (which it can wait for, thanks to delayed ACKs).  If they
> have the same ECT value, use that one.  If they're different, then it
> just has to perform a check for non-MSS (i.e. the boundary between TSOs
> if send ops do not yield a multiple of MSS) and it might know.

I don't think it's that easy to guess.  The TSO sizes are almost always
multiples of MSS because they get trimmed or they are limited by the
congestion window.  The receiver will eventually make a mistake using
your scheme above that the sender can reliably detect.

I agree that replicating the ECT bits makes it less random, but it seems
to be the simplest and best approach.  In real life, there will be some
TSO and some non-TSO packets making it even more difficult to guess.
Randomizing the ECT bits in hardware makes verification of the nonce-sum
very complicated and unreliable.


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RFC: kernel memory leak fix for af_unix datagram getpeersec

2006-07-26 Thread Catherine Zhang
Hi, all,

Enclosed please find the new fix for the memory leak problem, incorporating
suggestions from Stephen and James.

thanks all for your help!
Catherine

--


From: [EMAIL PROTECTED]

This patch implements a cleaner fix for the memory leak problem of the original 
unix datagram getpeersec patch.  Instead of creating a security context each
time a unix datagram is sent, we only create the security context when the
receiver requests it.

This new design requires modification of the current unix_getsecpeer_dgram
LSM hook and addition of two new hooks, namely, sid_to_secctx and
release_secctx.  The former retrieves the security context and the latter
releases it.  A hook is required for releasing the security context because
it is up to the security module to decide how that's done.  In the case of
Selinux, it's a simple kfree operation.


---

 include/linux/security.h |   41 +++--
 include/net/af_unix.h|6 ++
 include/net/scm.h|   29 +
 net/ipv4/ip_sockglue.c   |9 +++--
 net/unix/af_unix.c   |   33 ++---
 security/dummy.c |   14 --
 security/selinux/hooks.c |   34 ++
 7 files changed, 109 insertions(+), 57 deletions(-)

diff -puN include/net/scm.h~af_unix-datagram-getpeersec-ml-fix include/net/scm.h
--- linux-2.6.18-rc2/include/net/scm.h~af_unix-datagram-getpeersec-ml-fix   
2006-07-22 21:28:21.0 -0400
+++ linux-2.6.18-rc2-cxzhang/include/net/scm.h  2006-07-24 11:19:54.0 
-0400
@@ -3,6 +3,7 @@
 
 #include 
 #include 
+#include 
 
 /* Well, we should have at least one descriptor open
  * to accept passed FDs 8)
@@ -20,8 +21,7 @@ struct scm_cookie
struct ucredcreds;  /* Skb credentials  */
struct scm_fp_list  *fp;/* Passed files */
 #ifdef CONFIG_SECURITY_NETWORK
-   char*secdata;   /* Security context */
-   u32 seclen; /* Security length  */
+   u32 sid;/* Passed security ID   */
 #endif
unsigned long   seq;/* Connection seqno */
 };
@@ -32,6 +32,16 @@ extern int __scm_send(struct socket *soc
 extern void __scm_destroy(struct scm_cookie *scm);
 extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
 
+#ifdef CONFIG_SECURITY_NETWORK
+static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct 
scm_cookie *scm)
+{
+   security_socket_getpeersec_dgram(sock, NULL, &scm->sid);
+}
+#else
+static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct 
scm_cookie *scm)
+{ }
+#endif /* CONFIG_SECURITY_NETWORK */
+
 static __inline__ void scm_destroy(struct scm_cookie *scm)
 {
if (scm && scm->fp)
@@ -47,6 +57,7 @@ static __inline__ int scm_send(struct so
scm->creds.pid = p->tgid;
scm->fp = NULL;
scm->seq = 0;
+   unix_get_peersec_dgram(sock, scm);
if (msg->msg_controllen <= 0)
return 0;
return __scm_send(sock, msg, scm);
@@ -55,8 +66,18 @@ static __inline__ int scm_send(struct so
 #ifdef CONFIG_SECURITY_NETWORK
 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct 
scm_cookie *scm)
 {
-   if (test_bit(SOCK_PASSSEC, &sock->flags) && scm->secdata != NULL)
-   put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, scm->seclen, 
scm->secdata);
+   char *secdata;
+   u32 seclen;
+   int err;
+
+   if (test_bit(SOCK_PASSSEC, &sock->flags)) {
+   err = security_sid_to_secctx(scm->sid, &secdata, &seclen);
+
+   if (!err) {
+   put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, 
secdata);
+   security_release_secctx(secdata, seclen);
+   }
+   }
 }
 #else
 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct 
scm_cookie *scm)
diff -puN net/unix/af_unix.c~af_unix-datagram-getpeersec-ml-fix 
net/unix/af_unix.c
--- linux-2.6.18-rc2/net/unix/af_unix.c~af_unix-datagram-getpeersec-ml-fix  
2006-07-22 23:01:26.0 -0400
+++ linux-2.6.18-rc2-cxzhang/net/unix/af_unix.c 2006-07-22 23:14:15.0 
-0400
@@ -127,30 +127,6 @@ static atomic_t unix_nr_socks = ATOMIC_I
 
 #define UNIX_ABSTRACT(sk)  (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE)
 
-#ifdef CONFIG_SECURITY_NETWORK
-static void unix_get_peersec_dgram(struct sk_buff *skb)
-{
-   int err;
-
-   err = security_socket_getpeersec_dgram(skb, UNIXSECDATA(skb),
-  UNIXSECLEN(skb));
-   if (err)
-   *(UNIXSECDATA(skb)) = NULL;
-}
-
-static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff 
*skb)
-{
-   scm->secdata = *UNIXSECDATA(skb);
-   scm->seclen = *UNIXSECLEN(skb);
-}
-#else
-static inline void unix_get_peersec_dgram(struct sk_buff *sk

Re: [3/4] kevent: AIO, aio_sendfile() implementation.

2006-07-26 Thread Phillip Susi

Christoph Hellwig wrote:

Networking and disk AIO have significantly different needs.

Therefore, I really don't see it as reasonable to expect
a merge of these two things.  It doesn't make any sense.


I'm not sure about that.  The current aio interface isn't exactly nice
for disk I/O either.  I'm more than happy to have a discussion about
that aspect.




I agree that it makes perfect sense for a merger because aio and 
networking have very similar needs.  In both cases, the caller hands the 
kernel a buffer and wants the kernel to either fill it or consume it, 
and to be able to do so asynchronously.  You also want to maximize 
performance in both cases by taking advantage of zero copy IO.


I wonder though, why do you say the current aio interface isn't nice for 
disk IO?  It seems to work rather nicely to me, and is much better than 
the posix aio interface.


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: RFC: kernel memory leak fix for af_unix datagram getpeersec

2006-07-26 Thread Stephen Smalley
On Wed, 2006-07-26 at 16:19 -0400, Catherine Zhang wrote:
> diff -puN include/net/scm.h~af_unix-datagram-getpeersec-ml-fix 
> include/net/scm.h
> --- linux-2.6.18-rc2/include/net/scm.h~af_unix-datagram-getpeersec-ml-fix 
> 2006-07-22 21:28:21.0 -0400
> +++ linux-2.6.18-rc2-cxzhang/include/net/scm.h2006-07-24 
> 11:19:54.0 -0400
> @@ -3,6 +3,7 @@
>  
>  #include 
>  #include 
> +#include 
>  
>  /* Well, we should have at least one descriptor open
>   * to accept passed FDs 8)
> @@ -20,8 +21,7 @@ struct scm_cookie
>   struct ucredcreds;  /* Skb credentials  */
>   struct scm_fp_list  *fp;/* Passed files */
>  #ifdef CONFIG_SECURITY_NETWORK
> - char*secdata;   /* Security context */
> - u32 seclen; /* Security length  */
> + u32 sid;/* Passed security ID   */

I think that "secid" is what has been chosen for security identifiers
outside of the core SELinux code to to avoid confusion with session
identifiers.  Lingering references to sid or ctxid are going to be
converted to secid.

> diff -puN net/unix/af_unix.c~af_unix-datagram-getpeersec-ml-fix 
> net/unix/af_unix.c
> --- linux-2.6.18-rc2/net/unix/af_unix.c~af_unix-datagram-getpeersec-ml-fix
> 2006-07-22 23:01:26.0 -0400
> +++ linux-2.6.18-rc2-cxzhang/net/unix/af_unix.c   2006-07-22 
> 23:14:15.0 -0400
> @@ -1323,8 +1299,9 @@ static int unix_dgram_sendmsg(struct kio
>   memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
>   if (siocb->scm->fp)
>   unix_attach_fds(siocb->scm, skb);
> -
> - unix_get_peersec_dgram(skb);
> +#ifdef CONFIG_SECURITY_NETWORK
> + memcpy(UNIXSID(skb), &siocb->scm->sid, sizeof(u32));
> +#endif /* CONFIG_SECURITY_NETWORK */

You want to retain the static inlines, and just update their contents,
not replace them with embedded #ifdefs.  And this could be a direct
assignment, right?

-- 
Stephen Smalley
National Security Agency

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: H/W requirements for NETIF_F_HW_CSUM

2006-07-26 Thread David Miller
From: "Ravinandan Arakali" <[EMAIL PROTECTED]>
Date: Wed, 26 Jul 2006 12:34:28 -0700

> "You CANNOT use NETIF_F_HW_CSUM, when your hardware does not provide the 
> checksum value.  You must use NETIF_F_IP_CSUM.  Your use of 
> NETIF_F_HW_CSUM + CHECKSUM_UNNECESSARY is flat out incorrect."

NETIF_F_HW_CSUM means, on transmit, that you can handle being given a
skb with ip_summed set to CHECKSUM_HW.

When you see CHECKSUM_HW on transmit, this means that skb->csum holds
the offset into the packet where you should place the computed
checksum.  Actually you are given two packet offsets, defined as
follows:

csum_start_off = (u32) (skb->h.raw - skb->data);
csum_stuff_off = (u32) ((skb->h.raw + skb->csum) - skb->data);

The first value is where you should start calculating the two's
complement checksum, and the second value is the offset into the
packet where you should place the 16-bit checksum after you have
folded it.

The thing I think you are misunderstanding is that in order to support
NETIF_F_HW_CSUM you must be able to compute the two's complement over
_ARBITRARY_ portions of the packet and be able to place the 16-bit
checkum you compute at _ARBITRARY_ locations in the packet.

Therefore, saying things like "our card can only handle IPV4 and IPV6"
have no sense when discussing CHECKSUM_HW.  The algorithm of
CHECKSUM_HW on transmit is generic, the protocol in use doesn't
matter, it does a generic two's complement checksum over some section
of the packet data.  This allows to handle arbitrary protocols that
make use of two's complement checksums, not just "ipv4 and ipv6".

On receive, if you want to set CHECKSUM_HW, the card must compute the
two's complement checksum over the entire packet data and place it
in skb->csum.

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Update of the r8169 branch

2006-07-26 Thread Francois Romieu
The r8169 branch at git://electric-eye.fr.zoreil.com/home/romieu/linux-2.6.git
has been replaced by an updated version which should correctly support
the 8168 chipset given Boris and David's feedback.

The previous version of the r8169 branch has been archived as r8169-20060612.

The changes may support some different flavors of the chipset (pci-e 8136
and 8167) but I have not received confirmation nor support request for
those.

The changes are available as a serie of patches too at:
http://www.fr.zoreil.com/linux/kernel/2.6.x/2.6.18-rc2/r8169

The r8169 branch do not conflict with Jeff's upstream branch (ok, it's
currently merged...).

The changes below are included (against mainline):

commit bcf0bf90cd9e9242b66e0563b6a8c8db2e4c262c

r8169: sync with vendor's driver

- add several PCI ID for the PCI-E adapters ;
- new identification strings ;
- the RTL_GIGA_MAC_VER_ defines have been renamed to closely match the
  out-of-tree driver. It makes the comparison less hairy ;
- various magic ;
- the PCI region for the device with PCI ID 0x8136 is guessed.
  Explanation: the in-kernel Linux driver is written to allow MM register
  accesses and avoid the IO tax. The relevant BAR register was found at
  base address 1 for the plain-old PCI 8169. User reported lspci show that
  it is found at base address 2 for the new Gigabit PCI-E 816{8/9}.
  Typically:
  01:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd.: Unknown 
device 8168 (rev 01)
  Subsystem: Unknown device 1631:e015
  Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- 
ParErr- Stepping- SERR- FastB2B-
  Status: Cap+ 66Mhz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- 
SERR- 

commit 4ff96fa67379c31ced69f193c7ffba17051f38e8

r8169: remove rtl8169_init_board

Rationale:
- its signature is not exactly pretty;
- it has no knowledge of pci_device_id;
- kiss 23 lines good bye.

Signed-off-by: Francois Romieu <[EMAIL PROTECTED]>

commit 623a1593c84afb86b2f496a56fb4ec37f82b5c78

r8169: hardware flow control

The datasheet suggests that the device handles the hardware flow
control almost automagically. User report a different story, so
let's try to twiddle the mii registers.

Signed-off-by: Francois Romieu <[EMAIL PROTECTED]>

commit 9dccf61112e6755f4e6f154c1794bab3c509bc71

r8169: RX fifo overflow recovery

Signed-off-by: Francois Romieu <[EMAIL PROTECTED]>

commit a2b98a697fa4e7564f78905b83db122824916cf9

r8169: mac address change support

Fix for http://bugzilla.kernel.org/show_bug.cgi?id=6032.

Cc: Tim Mattox <[EMAIL PROTECTED]>
Signed-off-by: Francois Romieu <[EMAIL PROTECTED]>

-- 
Ueimor
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [XFRM]: Fix protocol field value for outgoing IPv6 GSO packets

2006-07-26 Thread David Miller
From: Herbert Xu <[EMAIL PROTECTED]>
Date: Tue, 25 Jul 2006 10:13:26 +1000

> On Tue, Jul 25, 2006 at 02:09:26AM +0200, Patrick McHardy wrote:
> > This appears to be a mistake, but I didn't follow the GSO stuff
> > very closely, so there could be some non-obvious reason.
> 
> Yes it definitely was a mistake! Thanks for picking this up Patrick.
> 
> > [XFRM]: Fix protocol field value for outgoing IPv6 GSO packets
> > 
> > Signed-off-by: Patrick McHardy <[EMAIL PROTECTED]>
> 
> Acked-by: Herbert Xu <[EMAIL PROTECTED]>

Applied, thanks guys.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/5] [IPV6]: Multiple Routing Tables

2006-07-26 Thread Thomas Graf
Adds the framework to support multiple IPv6 routing tables.
Currently all automatically generated routes are put into the
same table. This could be changed at a later point after
considering the produced locking overhead.

When locating routes for redirects only the main table is
searched for now. Since policy rules will not be reversible
it is unclear whether it makes sense to change this.

Signed-off-by: Thomas Graf <[EMAIL PROTECTED]>

Index: net-2.6.git/include/net/ip6_fib.h
===
--- net-2.6.git.orig/include/net/ip6_fib.h
+++ net-2.6.git/include/net/ip6_fib.h
@@ -51,6 +51,8 @@ struct rt6key
int plen;
 };
 
+struct fib6_table;
+
 struct rt6_info
 {
union {
@@ -71,6 +73,7 @@ struct rt6_info
u32 rt6i_flags;
u32 rt6i_metric;
atomic_trt6i_ref;
+   struct fib6_table   *rt6i_table;
 
struct rt6key   rt6i_dst;
struct rt6key   rt6i_src;
@@ -143,12 +146,41 @@ struct rt6_statistics {
 
 typedef void   (*f_pnode)(struct fib6_node *fn, void *);
 
-extern struct fib6_nodeip6_routing_table;
+struct fib6_table {
+   struct hlist_node   tb6_hlist;
+   u32 tb6_id;
+   rwlock_ttb6_lock;
+   struct fib6_nodetb6_root;
+};
+
+#define RT6_TABLE_UNSPEC   RT_TABLE_UNSPEC
+#define RT6_TABLE_MAIN RT_TABLE_MAIN
+#define RT6_TABLE_LOCALRT6_TABLE_MAIN
+#define RT6_TABLE_DFLT RT6_TABLE_MAIN
+#define RT6_TABLE_INFO RT6_TABLE_MAIN
+
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+#define FIB6_TABLE_MIN 1
+#define FIB6_TABLE_MAX RT_TABLE_MAX
+#else
+#define FIB6_TABLE_MIN RT_TABLE_MAIN
+#define FIB6_TABLE_MAX FIB6_TABLE_MIN
+#endif
+
+#define RT6_F_STRICT   1
+
+typedef struct rt6_info *(*pol_lookup_t)(struct fib6_table *,
+struct flowi *, int);
 
 /*
  * exported functions
  */
 
+extern struct fib6_table * fib6_get_table(u32 id);
+extern struct fib6_table * fib6_new_table(u32 id);
+extern struct dst_entry *  fib6_rule_lookup(struct flowi *fl, int flags,
+pol_lookup_t lookup);
+
 extern struct fib6_node*fib6_lookup(struct fib6_node *root,
 struct in6_addr *daddr,
 struct in6_addr *saddr);
@@ -161,6 +193,9 @@ extern void fib6_clean_tree(struct fib
int (*func)(struct rt6_info *, 
void *arg),
int prune, void *arg);
 
+extern voidfib6_clean_all(int (*func)(struct rt6_info *, 
void *arg),
+  int prune, void *arg);
+
 extern int fib6_walk(struct fib6_walker_t *w);
 extern int fib6_walk_continue(struct fib6_walker_t *w);
 
Index: net-2.6.git/net/ipv6/ip6_fib.c
===
--- net-2.6.git.orig/net/ipv6/ip6_fib.c
+++ net-2.6.git/net/ipv6/ip6_fib.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_PROC_FS
 #include 
@@ -147,6 +148,126 @@ static __inline__ void rt6_release(struc
dst_free(&rt->u.dst);
 }
 
+static struct fib6_table fib6_main_tbl = {
+   .tb6_id = RT6_TABLE_MAIN,
+   .tb6_lock   = RW_LOCK_UNLOCKED,
+   .tb6_root   = {
+   .leaf   = &ip6_null_entry,
+   .fn_flags   = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
+   },
+};
+
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+
+#define FIB_TABLE_HASHSZ 256
+static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
+
+static struct fib6_table *fib6_alloc_table(u32 id)
+{
+   struct fib6_table *table;
+
+   table = kzalloc(sizeof(*table), GFP_ATOMIC);
+   if (table != NULL) {
+   table->tb6_id = id;
+   table->tb6_lock = RW_LOCK_UNLOCKED;
+   table->tb6_root.leaf = &ip6_null_entry;
+   table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
+   }
+
+   return table;
+}
+
+static void fib6_link_table(struct fib6_table *tb)
+{
+   unsigned int h;
+
+   h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1);
+
+   /*
+* No protection necessary, this is the only list mutatation
+* operation, tables never disappear once they exist.
+*/
+   hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]);
+}
+
+struct fib6_table *fib6_new_table(u32 id)
+{
+   struct fib6_table *tb;
+
+   if (id == 0)
+   id = RT6_TABLE_MAIN;
+   tb = fib6_get_table(id);
+   if (tb)
+   retur

[PATCH 3/5] [NET]: Protocol Independant Policy Routing Rules Framework

2006-07-26 Thread Thomas Graf
Derived from net/ipv6/fib_rules.c

Signed-off-by: Thomas Graf <[EMAIL PROTECTED]>

Index: net-2.6.git/include/linux/fib_rules.h
===
--- /dev/null
+++ net-2.6.git/include/linux/fib_rules.h
@@ -0,0 +1,60 @@
+#ifndef __LINUX_FIB_RULES_H
+#define __LINUX_FIB_RULES_H
+
+#include 
+#include 
+
+/* rule is permanent, and cannot be deleted */
+#define FIB_RULE_PERMANENT 1
+
+struct fib_rule_hdr
+{
+   __u8family;
+   __u8dst_len;
+   __u8src_len;
+   __u8tos;
+
+   __u8table;
+   __u8res1;   /* reserved */
+   __u8res2;   /* reserved */
+   __u8action;
+
+   __u32   flags;
+};
+
+enum
+{
+   FRA_UNSPEC,
+   FRA_DST,/* destination address */
+   FRA_SRC,/* source address */
+   FRA_IFNAME, /* interface name */
+   FRA_UNUSED1,
+   FRA_UNUSED2,
+   FRA_PRIORITY,   /* priority/preference */
+   FRA_UNUSED3,
+   FRA_UNUSED4,
+   FRA_UNUSED5,
+   FRA_FWMARK, /* netfilter mark (IPv4) */
+   FRA_FLOW,   /* flow/class id */
+   __FRA_MAX
+};
+
+#define FRA_MAX (__FRA_MAX - 1)
+
+enum
+{
+   FR_ACT_UNSPEC,
+   FR_ACT_TO_TBL,  /* Pass to fixed table */
+   FR_ACT_RES1,
+   FR_ACT_RES2,
+   FR_ACT_RES3,
+   FR_ACT_RES4,
+   FR_ACT_BLACKHOLE,   /* Drop without notification */
+   FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */
+   FR_ACT_PROHIBIT,/* Drop with EACCES */
+   __FR_ACT_MAX,
+};
+
+#define FR_ACT_MAX (__FR_ACT_MAX - 1)
+
+#endif
Index: net-2.6.git/include/net/fib_rules.h
===
--- /dev/null
+++ net-2.6.git/include/net/fib_rules.h
@@ -0,0 +1,89 @@
+#ifndef __NET_FIB_RULES_H
+#define __NET_FIB_RULES_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct fib_rule
+{
+   struct list_headlist;
+   atomic_trefcnt;
+   int ifindex;
+   charifname[IFNAMSIZ];
+   u32 pref;
+   u32 flags;
+   u32 table;
+   u8  action;
+   struct rcu_head rcu;
+};
+
+struct fib_lookup_arg
+{
+   void*lookup_ptr;
+   void*result;
+   struct fib_rule *rule;
+};
+
+struct fib_rules_ops
+{
+   int family;
+   struct list_headlist;
+   int rule_size;
+
+   int (*action)(struct fib_rule *,
+ struct flowi *, int,
+ struct fib_lookup_arg *);
+   int (*match)(struct fib_rule *,
+struct flowi *, int);
+   int (*configure)(struct fib_rule *,
+struct sk_buff *,
+struct nlmsghdr *,
+struct fib_rule_hdr *,
+struct nlattr **);
+   int (*compare)(struct fib_rule *,
+  struct fib_rule_hdr *,
+  struct nlattr **);
+   int (*fill)(struct fib_rule *, struct sk_buff *,
+   struct nlmsghdr *,
+   struct fib_rule_hdr *);
+   u32 (*default_pref)(void);
+
+   struct nla_policy   *policy;
+   struct list_head*rules_list;
+   struct module   *owner;
+};
+
+static inline void fib_rule_get(struct fib_rule *rule)
+{
+   atomic_inc(&rule->refcnt);
+}
+
+static inline void fib_rule_put_rcu(struct rcu_head *head)
+{
+   struct fib_rule *rule = container_of(head, struct fib_rule, rcu);
+   kfree(rule);
+}
+
+static inline void fib_rule_put(struct fib_rule *rule)
+{
+   if (atomic_dec_and_test(&rule->refcnt))
+   call_rcu(&rule->rcu, fib_rule_put_rcu);
+}
+
+extern int fib_rules_register(struct fib_rules_ops *);
+extern int fib_rules_unregister(struct fib_rules_ops *);
+
+extern int fib_rules_lookup(struct fib_rules_ops *,
+struct flowi *, int flags,
+struct fib_lookup_arg *);
+
+extern int fib_nl_newrule(struct sk_buff *,
+  struct nlmsghdr *, void *);
+extern int fib_nl_delrule(struct sk_buff *,
+  struct nlmsghdr *, void *);
+extern

[RFC] Multiple IPV6 Routing Tables & Policy Routing

2006-07-26 Thread Thomas Graf
Hello,

Thought it might be time to go through a round of comments
on this work. Even though I've almost rewritten all the code
the patches are based on the work found on www.mobile-ipv6.org.
I have no idea which code was written by whom so just email me
to get the credits right.

Main differences to the version found on mobile-ipv6.org is
that I removed table refcnt and defined that tables cannot
disappear once created to simplify things and avoid too many
atomic operations when looking up routes. I've replaced the
table array with a hash table to prepare it for > 255 tables
and made things aware of the new default router selection
code and experimental route info stuff added recently.

It's not final but somewhat working, I'm eager to see comments
or patches. I apologize if I've tramped onto anybody's foot
by taking this up and submitting it, this isn't meant as an
attempt to steal credits but rather to pick up good code and
finally get it upstream after a very long while.

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] [IPV6]: Remove ndiscs rt6_lock dependency

2006-07-26 Thread Thomas Graf
(Ab)using rt6_lock wouldn't work anymore if rt6_lock is
converted into a per table lock.

Signed-off-by: Thomas Graf <[EMAIL PROTECTED]>

Index: net-2.6.git/net/ipv6/route.c
===
--- net-2.6.git.orig/net/ipv6/route.c
+++ net-2.6.git/net/ipv6/route.c
@@ -745,8 +745,6 @@ static void ip6_rt_update_pmtu(struct ds
}
 }
 
-/* Protected by rt6_lock.  */
-static struct dst_entry *ndisc_dst_gc_list;
 static int ipv6_get_mtu(struct net_device *dev);
 
 static inline unsigned int ipv6_advmss(unsigned int mtu)
@@ -767,6 +765,9 @@ static inline unsigned int ipv6_advmss(u
return mtu;
 }
 
+static struct dst_entry *ndisc_dst_gc_list;
+DEFINE_SPINLOCK(ndisc_lock);
+
 struct dst_entry *ndisc_dst_alloc(struct net_device *dev, 
  struct neighbour *neigh,
  struct in6_addr *addr,
@@ -807,10 +808,10 @@ struct dst_entry *ndisc_dst_alloc(struct
rt->rt6i_dst.plen = 128;
 #endif
 
-   write_lock_bh(&rt6_lock);
+   spin_lock_bh(&ndisc_lock);
rt->u.dst.next = ndisc_dst_gc_list;
ndisc_dst_gc_list = &rt->u.dst;
-   write_unlock_bh(&rt6_lock);
+   spin_unlock_bh(&ndisc_lock);
 
fib6_force_start_gc();
 
@@ -824,8 +825,11 @@ int ndisc_dst_gc(int *more)
int freed;
 
next = NULL;
+   freed = 0;
+
+   spin_lock_bh(&ndisc_lock);
pprev = &ndisc_dst_gc_list;
-   freed = 0;
+
while ((dst = *pprev) != NULL) {
if (!atomic_read(&dst->__refcnt)) {
*pprev = dst->next;
@@ -837,6 +841,8 @@ int ndisc_dst_gc(int *more)
}
}
 
+   spin_unlock_bh(&ndisc_lock);
+
return freed;
 }
 

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/5] [IPV6]: Policy Routing Rules

2006-07-26 Thread Thomas Graf
Adds support for policy routing rules including a new
local table for routes with a local destination.

Signed-off-by: Thomas Graf <[EMAIL PROTECTED]>

Index: net-2.6.git/net/ipv6/fib6_rules.c
===
--- /dev/null
+++ net-2.6.git/net/ipv6/fib6_rules.c
@@ -0,0 +1,256 @@
+/*
+ * net/ipv6/fib6_rules.c   IPv6 Routing Policy Rules
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ * Authors
+ * Ville Nuorvala  <[EMAIL PROTECTED]>
+ * Thomas Graf <[EMAIL PROTECTED]>
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+struct fib6_rule
+{
+   struct fib_rule common;
+   struct rt6key   src;
+   struct rt6key   dst;
+   u8  tclass;
+};
+
+static struct fib_rules_ops fib6_rules_ops;
+
+static struct fib6_rule main_rule = {
+   .common = {
+   .refcnt =   ATOMIC_INIT(2),
+   .pref = 0x7FFE,
+   .action =   FR_ACT_TO_TBL,
+   .table =RT6_TABLE_MAIN,
+   },
+};
+
+static struct fib6_rule local_rule = {
+   .common = {
+   .refcnt =   ATOMIC_INIT(2),
+   .pref = 0,
+   .action =   FR_ACT_TO_TBL,
+   .table =RT6_TABLE_LOCAL,
+   .flags =FIB_RULE_PERMANENT,
+   },
+};
+
+static LIST_HEAD(fib6_rules);
+
+struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
+  pol_lookup_t lookup)
+{
+   struct fib_lookup_arg arg = {
+   .lookup_ptr = lookup,
+   };
+
+   fib_rules_lookup(&fib6_rules_ops, fl, flags, &arg);
+   fib_rule_put(arg.rule);
+
+   return (struct dst_entry *) arg.result;
+}
+
+int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
+int flags, struct fib_lookup_arg *arg)
+{
+   struct rt6_info *rt = NULL;
+   struct fib6_table *table;
+   pol_lookup_t lookup = arg->lookup_ptr;
+
+   switch (rule->action) {
+   case FR_ACT_TO_TBL:
+   break;
+   case FR_ACT_UNREACHABLE:
+   goto no_rt;
+   default:
+   case FR_ACT_BLACKHOLE:
+   rt = &ip6_blk_hole_entry;
+   goto discard_pkt;
+   case FR_ACT_PROHIBIT:
+   rt = &ip6_prohibit_entry;
+   goto discard_pkt;
+   }
+
+   table = fib6_get_table(rule->table);
+   if (table)
+   rt = lookup(table, flp, flags);
+
+   if (rt == &ip6_null_entry)
+   dst_release(&rt->u.dst);
+   else
+   goto out;
+no_rt:
+   rt = &ip6_null_entry;
+discard_pkt:
+   dst_hold(&rt->u.dst);
+out:
+
+   arg->result = rt;
+   return 0;
+}
+
+
+static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
+{
+   struct fib6_rule *r = (struct fib6_rule *) rule;
+
+   if (!ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
+   return 0;
+
+#ifdef CONFIG_IPV6_SUBTREES
+   if ((flags & RT6_F_HAS_SADDR) &&
+   !ipv6_prefix_equal(&fl->fl6_src, &r->r_src.addr, r->r_src.plen))
+   return 0;
+#endif
+
+   return 1;
+}
+
+static struct nla_policy fib6_rule_policy[RTA_MAX+1] __read_mostly = {
+   [FRA_IFNAME]= { .type = NLA_STRING },
+   [FRA_PRIORITY]  = { .type = NLA_U32 },
+   [FRA_SRC]   = { .minlen = sizeof(struct in6_addr) },
+   [FRA_DST]   = { .minlen = sizeof(struct in6_addr) },
+};
+
+static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
+  struct nlmsghdr *nlh, struct fib_rule_hdr *frh,
+  struct nlattr **tb)
+{
+   int err = -EINVAL;
+   struct fib6_rule *rule6 = (struct fib6_rule *) rule;
+
+   if (frh->src_len > 128 || frh->dst_len > 128 ||
+   (frh->tos & ~IPV6_FLOWINFO_MASK))
+   goto errout;
+
+#ifndef CONFIG_IPV6_SUBTREES
+   if (frh->src_len > 0)
+   goto errout;
+#endif
+
+   if (rule->action == FR_ACT_TO_TBL) {
+   if (rule->table == RT6_TABLE_UNSPEC)
+   goto errout;
+
+   if (fib6_new_table(rule->table) == NULL) {
+   err = -ENOBUFS;
+   goto errout;
+   }
+   }
+
+   if (tb[FRA_SRC])
+   nla_memcpy(&rule6->src.addr, tb[FRA_SRC],
+  sizeof(struct in6_addr));
+
+   if (tb[FRA_DST])
+   nla_memcpy(&rule6->dst.addr, tb[FRA_DST],
+  sizeof(struct in6_addr));
+
+   rule6->src.plen = frh->src_len;
+   rule6->dst.plen = frh->dst_len;
+   rule6->tclass = frh->tos;
+
+   err = 0;
+errout:
+ 

  1   2   >