Re: Hello, We have IP100A Linux driver need to submit to 2.6.x kernel
On Thu, 27 Jul 2006 14:41:29 +0800 "Jesse Huang" <[EMAIL PROTECTED]> wrote: > Dear All: > > I am IC Plus software engineer. We have IP100A 10/100 fast network adapter > driver need to submit to Linux 2.6.x kernel. Thanks! > Please tell me who should I submit to. > Please send it to the four addresses to which you sent this email. Documentation/SubmittingDrivers, Documentation/SubmittingPatches and Documentation/SubmitChecklist contain helpful info. - 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.
On Wed, 2006-07-26 at 09:22 -0700, Badari Pulavarty wrote: > 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 Badari, Thanks for refreshing those patches, they have been sitting here for quite some time now and collected dust. I also think Suparna's patchset for doing buffered AIO would be a real plus here. > > 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. Ulrich, I you want to have a look at how those patches are put to use in libposix-aio, have a look at http://sourceforge.net/projects/paiol. It could be a starting point for glibc. Thanks, Sébastien. -- - Sébastien DuguéBULL/FREC:B1-247 phone: (+33) 476 29 77 70 Bullcom: 229-7770 mailto:[EMAIL PROTECTED] Linux POSIX AIO: http://www.bullopensource.org/posix http://sourceforge.net/projects/paiol - - 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: async network I/O, event channels, etc
From: Evgeniy Polyakov <[EMAIL PROTECTED]> Date: Wed, 26 Jul 2006 10:28:17 +0400 > 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). I've been thinking about this aspect, and I think it's very interesting. Let's be clear what the ramifications of this are first. Using the terminology of Network Algorithmics, this is an instance of Principle 2, "Shift computation in time". Instead of using get_user_pages() at AIO setup, we instead map the thing to userspace later when the user wants it. Pinning pages is a pain because both user and kernel refer to the buffer at the same time. We get more flexibility when the user has to map the thing explicitly. I want us to think about how a user might want to use this. What I anticipate is that users will want to organize a pool of AIO buffers for themselves using this DMA interface. So the events they are truly interested in are of a finer granularity than you might expect. They want to know when pieces of a buffer are available for reuse. And here is the core dilemma. If you make the event granularity too coarse, a larger AIO buffer pool is necessary. If you make the event granuliary too fine, event processing begins to dominate, and costs too much. This is true even for something as light weight as kevent. - 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 3/5] [NET]: Protocol Independant Policy Routing Rules Framework
From: James Morris <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 01:58:58 -0400 (EDT) > On Thu, 27 Jul 2006, Thomas Graf wrote: > > > + rule = kmalloc(ops->rule_size, GFP_KERNEL); > > + if (rule == NULL) { > > + err = -ENOMEM; > > + goto errout; > > + } > > + memset(rule, 0, ops->rule_size); > > + > > kzalloc() ? :-) Good catch :) He did use kzalloc() in a few other places, to his credit. - 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: Netchannles: first stage has been completed. Further ideas.
From: Rusty Russell <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 15:46:12 +1000 > Yes, my first thought back in January was how netfilter would interact > with this in a sane way. One answer is "don't": once someone registers > on any hook we go into slow path. Another is to run the hooks in socket > context, which is better, but precludes having the consumer in > userspace, which still appeals to me 8) Small steps, small steps. I have not ruled out userspace TCP just yet, but we are not prepared to go there right now anyways. It is just the same kind of jump to go to kernel level netchannels as it is to go from kernel level netchannels to userspace netchannel based TCP. > What would the tuple look like? Off the top of my head: > SRCIP/DSTIP/PROTO/SPT/DPT/IN/OUT (where IN and OUT are boolean values > indicating whether the src/dest is local). > > Of course, it means rewriting all the userspace tools, documentation, > and creating a complete new infrastructure for connection tracking and > NAT, but if that's what's required, then so be it. I think we are able to finally talk seriously about revamping netfilter on this level because we finally have a good incentive to do so and some kind of model exists to work against. Robert's trie might be able to handle your tuple very well, fwiw, perhaps even with prefixing. But something occurs to me. Socket has ID when it is created and goes to established state. This means we have this tuple, and thus we can prelookup the netfilter rule and attach this cached lookup state on the socket. Your tuple in this case is defined to be: SRCIP/DSTIP/"TCP"/SPT/DPT/0/1 I do not know how practical this is, it is just some suggestion. Would there be prefixing in these tuples? That's where the trouble starts. If you add prefixing, troubles and limitations of lookup of today reappear. If you disallow prefixing, tables get very large but lookup becomes simpler and practical. - 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 3/5] [NET]: Protocol Independant Policy Routing Rules Framework
On Thu, 27 Jul 2006, Thomas Graf wrote: > + rule = kmalloc(ops->rule_size, GFP_KERNEL); > + if (rule == NULL) { > + err = -ENOMEM; > + goto errout; > + } > + memset(rule, 0, ops->rule_size); > + kzalloc() ? :-) - James -- James Morris <[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
Re: Netchannles: first stage has been completed. Further ideas.
On Wed, 2006-07-26 at 22:17 -0700, David Miller wrote: > I read this as "we will be able to get around the problems" but > no specific answer as to "how". I am an optimist too but I want > to start seeing concrete discussion about the way in which the > problems will be dealt with. > > Alexey has some ideas, such as running the netfilter path from the > netchannel consumer socket context. That is the kind of thing > we need to be talking about. Yes, my first thought back in January was how netfilter would interact with this in a sane way. One answer is "don't": once someone registers on any hook we go into slow path. Another is to run the hooks in socket context, which is better, but precludes having the consumer in userspace, which still appeals to me 8) So I don't like either. The mistake (?) with netfilter was that we are completely general: you will see all packets, do what you want. If, instead, we had forced all rules to be of form "show me all packets matching this tuple" we would be in a combine it in a single lookup with routing etc. What would the tuple look like? Off the top of my head: SRCIP/DSTIP/PROTO/SPT/DPT/IN/OUT (where IN and OUT are boolean values indicating whether the src/dest is local). Of course, it means rewriting all the userspace tools, documentation, and creating a complete new infrastructure for connection tracking and NAT, but if that's what's required, then so be it. Rusty. -- Help! Save Australia from the worst of the DMCA: http://linux.org.au/law - 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: Netchannles: first stage has been completed. Further ideas.
From: Rusty Russell <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 12:17:51 +1000 > On Wed, 2006-07-19 at 03:01 +0400, Alexey Kuznetsov wrote: > > About locks: > > > > > is completely lockless (there is one irq lock when skb > > > is queued/dequeued into netchannels queue in hard/soft irq, > > > > Equivalent of socket spinlock. > > I don't think they are equivalent. In channels, this can be split into > two locks, queue lock and an dequeue lock, which operate independently. > The socket spinlock cannot. Moreover, in the case where there is a > guarantee about IRQs being bound to a single CPU (as Dave's ideas on > MSI), the queue lock is no longer required. In the case where there is > a single reader of the socket (or, as VJ did, the other end is in > userspace), no dequeue lock is required. Cost is a very interesting question here. I guess your main point is that eventually this lock can be made to go away, whereas Alexey speaks about the state of Evgivny's specific implementation. > My feeling is that modern cards will do partial demux for us; whether we > use netchannels or not, we should use that to accelerate lookup. Making > card aim MSI at same CPU for same flow is a start (and as Dave said, > much less code). As the next step, having the card give us a cookie > too, would allow us to explicitly skip first level of lookup. This > should allow us to identify which flows are simple enough to be directly > accelerated (whether by channels or something else): no bonding, raw > sockets, non-trivial netfilter rules, connection tracking changes, etc. I read this as "we will be able to get around the problems" but no specific answer as to "how". I am an optimist too but I want to start seeing concrete discussion about the way in which the problems will be dealt with. Alexey has some ideas, such as running the netfilter path from the netchannel consumer socket context. That is the kind of thing we need to be talking about. Robert Olsson is also doing some work involving full flow classifications using special trie structures in the routing cache that might be extendable to netchannels. His trick is to watch for the FIN shutdown sequence and GC route cache entries for a flow when this is seen. This is in order to keep the trie shallow and thus have a better bound on memory accesses for routing lookups. We are not a group of mathematicians discussing the tractability of some problem. Our interest is practice not theory. :) - 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: Is the qla3xxx driver in the mainline?
Michael Tokarev wrote: > 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. I've borrowed an ISP4022 based adapter, the qla3xxx should be supported. > > 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). > Thanks for the info. With qla3xxx, we can actually use the Ethernet interface of the qla4022 instead of the bcm57xx tg3. So, we could compare the performance of the on-board TOE/iscsi with open-iscsi better. -- albert - 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: Netchannles: first stage has been completed. Further ideas.
On Wed, 2006-07-19 at 03:01 +0400, Alexey Kuznetsov wrote: > Hello! > > Can I ask couple of questions? Just as a person who looked at VJ's > slides once and was confused. And startled, when found that it is not > considered as another joke of genuis. :-) Hi Alexey! > About locks: > > > is completely lockless (there is one irq lock when skb > > is queued/dequeued into netchannels queue in hard/soft irq, > > Equivalent of socket spinlock. I don't think they are equivalent. In channels, this can be split into two locks, queue lock and an dequeue lock, which operate independently. The socket spinlock cannot. Moreover, in the case where there is a guarantee about IRQs being bound to a single CPU (as Dave's ideas on MSI), the queue lock is no longer required. In the case where there is a single reader of the socket (or, as VJ did, the other end is in userspace), no dequeue lock is required. > VJ slides describe a totally different scheme, where softirq part is omitted > completely, protocol processing is moved to user space as whole. > It is an amazing toy. But I see nothing, which could promote its status > to practical. Exokernels used to do this thing for ages, and all the > performance gains are compensated by overcomplicated classification > engine, which has to remain in kernel and essentially to do the same > work which routing/firewalling/socket hash tables do. My feeling is that modern cards will do partial demux for us; whether we use netchannels or not, we should use that to accelerate lookup. Making card aim MSI at same CPU for same flow is a start (and as Dave said, much less code). As the next step, having the card give us a cookie too, would allow us to explicitly skip first level of lookup. This should allow us to identify which flows are simple enough to be directly accelerated (whether by channels or something else): no bonding, raw sockets, non-trivial netfilter rules, connection tracking changes, etc. Thoughts? Rusty. -- Help! Save Australia from the worst of the DMCA: http://linux.org.au/law - 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: Netchannel: default, find, add to socket
From: Kelly Daly <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 10:50:00 +1000 > Implement finding of correct netchannel for buffer, default netchannel and > attach a netchannel to a socket > > Signed-off-by: Kelly Daly <[EMAIL PROTECTED]> Patch is still corrupted. My tolerance on this matter is growing extremely thin. Send these patches to yourself and try to apply them, it will save me a lot of time. > @@ -65,6 +71,10 @@ static inline struct netchannel_buftrail > return __netchannel_dequeue(np); > } > > +extern struct netchannel *find_netchannel(const struct netchannel_buftrailer > *bp); > +extern int sock_add_netchannel(struct sock *sk); > extern struct sk_buff *skb_netchan_graft(struct netchannel_buftrailer *, > gfp_t); > > #endif /* _LINUX_NETCHANNEL_H */ > diff -urp davem/include/net/inet_hashtables.h > kelly_new/include/net/inet_hashtables.h This patch hunk states there are 10 lines in the new section of the file, yet the hunk is truncated at 8 lines. - 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
Netchannel: default, find, add to socket
Implement finding of correct netchannel for buffer, default netchannel and attach a netchannel to a socket Signed-off-by: Kelly Daly <[EMAIL PROTECTED]> --- diff -urp davem/include/linux/netchannel.h kelly_new/include/linux/netchannel.h --- davem/include/linux/netchannel.h2006-06-16 15:14:15.0 +1000 +++ kelly_new/include/linux/netchannel.h2006-07-10 14:04:54.0 +1000 @@ -19,6 +19,7 @@ struct netchannel { void(*netchan_callb)(struct netchannel *); void*netchan_callb_data; unsigned long netchan_head; + wait_queue_head_t wq; }; extern void netchannel_init(struct netchannel *, @@ -56,6 +57,11 @@ static inline unsigned char *netchan_buf return netchan_buf_base(bp) + bp->netchan_buf_offset; } +static inline int netchan_data_len(const struct netchannel_buftrailer *bp) +{ + return bp->netchan_buf_len - bp->netchan_buf_offset; +} + extern int netchannel_enqueue(struct netchannel *, struct netchannel_buftrailer *); extern struct netchannel_buftrailer *__netchannel_dequeue(struct netchannel *); static inline struct netchannel_buftrailer *netchannel_dequeue(struct netchannel *np) @@ -65,6 +71,10 @@ static inline struct netchannel_buftrail return __netchannel_dequeue(np); } +extern struct netchannel *find_netchannel(const struct netchannel_buftrailer *bp); +extern int sock_add_netchannel(struct sock *sk); extern struct sk_buff *skb_netchan_graft(struct netchannel_buftrailer *, gfp_t); #endif /* _LINUX_NETCHANNEL_H */ diff -urp davem/include/net/inet_hashtables.h kelly_new/include/net/inet_hashtables.h --- davem/include/net/inet_hashtables.h 2006-06-16 14:34:20.0 +1000 +++ kelly_new/include/net/inet_hashtables.h 2006-06-19 10:42:45.0 +1000 @@ -418,4 +418,7 @@ static inline struct sock *inet_lookup(s extern int inet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk); +extern void inet_hash_register(u8 proto, struct inet_hashinfo *hashinfo); +extern struct sock *inet_lookup_proto(u8 protocol, u32 saddr, u16 sport, u32 daddr, u16 dport, int ifindex); + #endif /* _INET_HASHTABLES_H */ diff -urp davem/include/net/sock.h kelly_new/include/net/sock.h --- davem/include/net/sock.h2006-06-16 15:14:16.0 +1000 +++ kelly_new/include/net/sock.h2006-06-19 10:42:45.0 +1000 @@ -196,6 +196,7 @@ struct sock { unsigned short sk_type; int sk_rcvbuf; socket_lock_t sk_lock; + struct netchannel *sk_channel; wait_queue_head_t *sk_sleep; struct dst_entry*sk_dst_cache; struct xfrm_policy *sk_policy[2]; diff -urp davem/net/core/dev.c kelly_new/net/core/dev.c --- davem/net/core/dev.c2006-06-16 15:14:16.0 +1000 +++ kelly_new/net/core/dev.c2006-07-10 14:11:22.0 +1000 @@ -113,9 +113,12 @@ #include #include #include +#include +#include #include #include #include +#include /* * The list of packet types we will receive (as opposed to discard) @@ -190,6 +193,8 @@ static inline struct hlist_head *dev_ind return &dev_index_head[ifindex & ((1wq); + np->netchan_callb = callb; np->netchan_callb_data = callb_data; } @@ -1912,6 +1924,122 @@ struct netchannel_buftrailer *__netchann } EXPORT_SYMBOL_GPL(__netchannel_dequeue); +/* Find the channel for a packet, or return default channel. */ +struct netchannel *find_netchannel(const struct netchannel_buftrailer *bp) +{ + struct sock *sk = NULL; + int datalen = netchan_data_len(bp); + + switch (bp->netchan_buf_proto) { + case __constant_htons(ETH_P_IP): { + struct iphdr *ip = (void *)bp - datalen; + int iphl = ip->ihl * 4; + + /* FIXME: Do sanity checks, parse packet. */ + + if (datalen >= (iphl + 4) && iphl == sizeof(struct iphdr)) { + u16 *ports = (u16 *)ip + 1; + sk = inet_lookup_proto(ip->protocol, +ip->saddr, ports[0], +ip->daddr, ports[1], +bp->netchan_buf_dev->ifindex); + } + break; + } + } + + if (sk && sk->sk_channel) + return sk->sk_channel; + return &default_netchannel; +} +EXPORT_SYMBOL_GPL(find_netchannel); + +/* add the netchannel to the socket */ +int sock_add_netchannel(struct sock *sk) +{ + struct netchannel *np; + + np = kmalloc(sizeof(struct netchannel), GFP_KERNEL); + if (!np) + return -ENOMEM;
Re: [PATCH 5/5] [IPV4]: Use Protocol Independant Policy Routing Rules Framework
From: Thomas Graf <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 00:00:05 +0200 > Index: net-2.6.git/net/ipv4/fib_rules.c > === > --- net-2.6.git.orig/net/ipv4/fib_rules.c > +++ net-2.6.git/net/ipv4/fib_rules.c ... > - new_r = kmalloc(sizeof(*new_r), GFP_KERNEL); > - if (!new_r) > - return -ENOMEM; > - memset(new_r, 0, sizeof(*new_r)); When you respin these patches, please regenerate them against the current tree which now uses kzalloc() here. Thanks. - 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 4/5] [IPV6]: Policy Routing Rules
From: David Miller <[EMAIL PROTECTED]> Date: Wed, 26 Jul 2006 16:33:43 -0700 (PDT) > Therfore, the better fix seems to be, to change the Makefile > rule to be: > > ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o > > Ok? And once this is fixed, new problems crop up :-) WARNING: net/ipv6/ipv6.o - Section mismatch: reference to .exit.text:fib6_rules_cleanup from .text between 'ip6_route_cleanup' (at offset 0xbfd4) and 'rt6_mtu_change_route' WARNING: "fib_rules_dump" [net/ipv6/ipv6.ko] undefined! WARNING: "fib_rules_register" [net/ipv6/ipv6.ko] undefined! WARNING: "fib_rules_lookup" [net/ipv6/ipv6.ko] undefined! WARNING: "fib_rules_unregister" [net/ipv6/ipv6.ko] undefined! The fib_rules_* cases are easy to fix, simply export those symbols using EXPORT_SYMBOL_GPL() in net/core/fib_rules.c The other problem is a bit more onerous. ip6_route_cleanup is not marked __exit, since it is called from initialization as well as exit contexts. Therefore fib6_rules_cleanup() has to have it's __exit marker deleted too. IPv6 seems to build modular now with all of these issues taken care of. Thomas, please integrate these fixes into your patch. Thanks. - 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 1/5] [IPV6]: Remove ndiscs rt6_lock dependency
From: Tushar Gohad <[EMAIL PROTECTED]> Date: Wed, 26 Jul 2006 16:34:03 -0700 > Are these changes scheduled to go into 2.6.18-rcX or 2.6.19? Since the feature freeze is frozen, net-2.6.19 is where it will likely go. - 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 4/5] [IPV6]: Policy Routing Rules
From: Thomas Graf <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 00:00:04 +0200 > Index: net-2.6.git/include/net/ip6_route.h > === > --- net-2.6.git.orig/include/net/ip6_route.h > +++ net-2.6.git/include/net/ip6_route.h > @@ -41,6 +41,11 @@ struct pol_chain { > > extern struct rt6_info ip6_null_entry; > > +#ifdef CONFIG_IPV6_MULTIPLE_TABLES > +extern struct rt6_info ip6_prohibit_entry; > +extern struct rt6_info ip6_blk_hole_entry; > +#endif > + > extern int ip6_rt_gc_interval; > > extern void ip6_route_input(struct sk_buff *skb); Because of my other suggestion, changing IPV6_MULTIPLE_TABLES to tristate, the build will fail unless we add a second condition to this ifdef, namely "CONFIG_IPV6_MULTIPLE_TABLES_MODULE". In fact, all this doesn't look so nice. All we want to do is make fib6_rules.o get built into ipv6-objs if it is enabled. Therfore, the better fix seems to be, to change the Makefile rule to be: ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o Ok? - 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 1/5] [IPV6]: Remove ndiscs rt6_lock dependency
Are these changes scheduled to go into 2.6.18-rcX or 2.6.19? Thanks. - Tushar David Miller wrote: From: Thomas Graf <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 00:00:01 +0200 (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]> This one looks great. Signed-off-by: David S. Miller <[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 - 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 4/5] [IPV6]: Policy Routing Rules
From: Thomas Graf <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 00:00:04 +0200 > Index: net-2.6.git/net/ipv6/Makefile > === > --- net-2.6.git.orig/net/ipv6/Makefile > +++ net-2.6.git/net/ipv6/Makefile > @@ -29,3 +29,5 @@ obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel. > obj-y += exthdrs_core.o > > obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o > + > +obj-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o This will cause a build failure if IPV6 is built modular. The fix is simple, make CONFIG_IPV6_MULTIPLE_TABLES a tristate instead of a bool. - 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/5] [IPV6]: Multiple Routing Tables
From: Thomas Graf <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 00:48:48 +0200 > Fortunately it's only used read-only when notifying to figure > out the destination pid but that code seems bogus as well and > we can probably remove the netlink cb passing hell throughout > all the code there. Yes, that pid handling looks very strange. But I would search the history of this code that passes the netlink skb parms around before making any changes to things like inet6_rt_notify :) It appears to have been added in 2.4.32, the original patch passes the raw pid around as the argument but that got changed to the current form which passes the netlink_skb_parms. - 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
From: Stephen Smalley <[EMAIL PROTECTED]> Date: Wed, 26 Jul 2006 16:50:40 -0400 > > 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? This is my feeling too. - 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/5] [IPV6]: Multiple Routing Tables
* David Miller <[EMAIL PROTECTED]> 2006-07-26 15:39 > Wow, were we corrupting the IP6CB() of input packets on every > route lookup that hit this path? I found that via compile error as passing on skb to this context didn't make sense when I rewrote the code around it :-) Fortunately it's only used read-only when notifying to figure out the destination pid but that code seems bogus as well and we can probably remove the netlink cb passing hell throughout all the code 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: [PATCH 4/5] [IPV6]: Policy Routing Rules
From: Thomas Graf <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 00:00:04 +0200 > Adds support for policy routing rules including a new > local table for routes with a local destination. > > Signed-off-by: Thomas Graf <[EMAIL PROTECTED]> With the generic fib_rules this is straightforward, looks good. Signed-off-by: David S. Miller <[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
Re: [PATCH 5/5] [IPV4]: Use Protocol Independant Policy Routing Rules Framework
From: Thomas Graf <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 00:00:05 +0200 > Signed-off-by: Thomas Graf <[EMAIL PROTECTED]> Like the ipv6 counterpart, this looks fine too. Signed-off-by: David S. Miller <[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
Re: [PATCH 3/5] [NET]: Protocol Independant Policy Routing Rules Framework
From: Thomas Graf <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 00:00:03 +0200 > Derived from net/ipv6/fib_rules.c > > Signed-off-by: Thomas Graf <[EMAIL PROTECTED]> A very nice abstraction, looks great. Signed-off-by: David S. Miller <[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
Re: [PATCH 2/5] [IPV6]: Multiple Routing Tables
From: Thomas Graf <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 00:00:02 +0200 > 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]> This looks good, and it seems we even fixed a bug: > @@ -586,7 +612,7 @@ restart: > > dst_hold(&rt->u.dst); > if (nrt) { > - err = ip6_ins_rt(nrt, NULL, NULL, &NETLINK_CB(skb)); > + err = ip6_ins_rt(nrt, NULL, NULL, NULL); > if (!err) > goto out2; > } Wow, were we corrupting the IP6CB() of input packets on every route lookup that hit this path? I'm probably the one who put that erroneous &NETLINK_CB(skb) there. Sorry :) Signed-off-by: David S. Miller <[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
Re: [PATCH 1/5] [IPV6]: Remove ndiscs rt6_lock dependency
From: Thomas Graf <[EMAIL PROTECTED]> Date: Thu, 27 Jul 2006 00:00:01 +0200 > (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]> This one looks great. Signed-off-by: David S. Miller <[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
Re: [PATCH 1/3] add netdev_alloc_skb
From: Christoph Hellwig <[EMAIL PROTECTED]> Date: Wed, 26 Jul 2006 13:31:36 +0200 > + * %NULL is returned in there is no free memory. Although this function > + * allocates memory it can be called from an interrupt. ... > + * %NULL is returned in there is no free memory. Looks like a typo in both cases, I think you mean "NULL is returned _if_ there" not "in there" I think I can queue this up for 2.6.19 if you fix this typo, but I'm not going to slap the deprecated marker on dev_alloc_skb() until all of the in-tree cases are being taken care of. It will just be a bunch of pointless noise, and at worse it will push the remaining conversions on some poor soul such as Andrew :) - 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 5/5] [IPV4]: Use Protocol Independant Policy Routing Rules Framework
Signed-off-by: Thomas Graf <[EMAIL PROTECTED]> Index: net-2.6.git/include/net/ip_fib.h === --- net-2.6.git.orig/include/net/ip_fib.h +++ net-2.6.git/include/net/ip_fib.h @@ -18,6 +18,7 @@ #include #include +#include /* WARNING: The ordering of these elements must match ordering * of RTA_* rtnetlink attribute numbers. @@ -203,9 +204,8 @@ static inline void fib_select_default(co #define ip_fib_main_table (fib_tables[RT_TABLE_MAIN]) extern struct fib_table * fib_tables[RT_TABLE_MAX+1]; -extern int fib_lookup(const struct flowi *flp, struct fib_result *res); +extern int fib_lookup(struct flowi *flp, struct fib_result *res); extern struct fib_table *__fib_new_table(int id); -extern void fib_rule_put(struct fib_rule *r); static inline struct fib_table *fib_get_table(int id) { @@ -251,15 +251,15 @@ extern u32 __fib_res_prefsrc(struct fib extern struct fib_table *fib_hash_init(int id); #ifdef CONFIG_IP_MULTIPLE_TABLES -/* Exported by fib_rules.c */ +extern int fib4_rules_dump(struct sk_buff *skb, struct netlink_callback *cb); + +extern void __init fib4_rules_init(void); +extern void __exit fib4_rules_cleanup(void); -extern int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); -extern int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); -extern int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb); #ifdef CONFIG_NET_CLS_ROUTE extern u32 fib_rules_tclass(struct fib_result *res); #endif -extern void fib_rules_init(void); + #endif static inline void fib_combine_itag(u32 *itag, struct fib_result *res) Index: net-2.6.git/net/ipv4/Kconfig === --- net-2.6.git.orig/net/ipv4/Kconfig +++ net-2.6.git/net/ipv4/Kconfig @@ -88,6 +88,7 @@ config IP_FIB_HASH config IP_MULTIPLE_TABLES bool "IP: policy routing" depends on IP_ADVANCED_ROUTER + select FIB_RULES ---help--- Normally, a router decides what to do with a received packet based solely on the packet's final destination address. If you say Y here, Index: net-2.6.git/net/ipv4/devinet.c === --- net-2.6.git.orig/net/ipv4/devinet.c +++ net-2.6.git/net/ipv4/devinet.c @@ -1153,9 +1153,7 @@ static struct rtnetlink_link inet_rtnetl [RTM_GETROUTE - RTM_BASE] = { .doit = inet_rtm_getroute, .dumpit = inet_dump_fib,}, #ifdef CONFIG_IP_MULTIPLE_TABLES - [RTM_NEWRULE - RTM_BASE] = { .doit = inet_rtm_newrule, }, - [RTM_DELRULE - RTM_BASE] = { .doit = inet_rtm_delrule, }, - [RTM_GETRULE - RTM_BASE] = { .dumpit = inet_dump_rules, }, + [RTM_GETRULE - RTM_BASE] = { .dumpit = fib4_rules_dump, }, #endif }; Index: net-2.6.git/net/ipv4/fib_rules.c === --- net-2.6.git.orig/net/ipv4/fib_rules.c +++ net-2.6.git/net/ipv4/fib_rules.c @@ -5,9 +5,8 @@ * * IPv4 Forwarding Information Base: policy rules. * - * Version:$Id: fib_rules.c,v 1.17 2001/10/31 21:55:54 davem Exp $ - * * Authors:Alexey Kuznetsov, <[EMAIL PROTECTED]> + * Thomas Graf <[EMAIL PROTECTED]> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,129 +18,154 @@ * Marc Boucher: routing by fwmark */ -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include +#include #include #include #include - #include -#include #include #include -#include #include +#include -#define FRprintk(a...) +static struct fib_rules_ops fib4_rules_ops; -struct fib_rule +struct fib4_rule { - struct hlist_node hlist; - atomic_tr_clntref; - u32 r_preference; - unsigned char r_table; - unsigned char r_action; - unsigned char r_dst_len; - unsigned char r_src_len; - u32 r_src; - u32 r_srcmask; - u32 r_dst; - u32 r_dstmask; - u32 r_srcmap; - u8 r_flags; - u8 r_tos; + struct fib_rule common; + u8 dst_len; + u8 src_len; + u8 tos; + u32 src; + u32 srcmask; + u32 dst; + u32 dstmask; #ifdef CONFIG_IP_ROUTE_FWMARK - u32 r_fwmark; + u32 fwmark; #endif - int
[PATCH 3/5] [NET]: Protocol Independant Policy Routing Rules Framework
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
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
(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
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: +
[PATCH 2/5] [IPV6]: Multiple Routing Tables
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
Re: [XFRM]: Fix protocol field value for outgoing IPv6 GSO packets
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
Update of the r8169 branch
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: H/W requirements for NETIF_F_HW_CSUM
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
Re: [PATCH Round 4 2/3] Core network changes to support network event notification.
From: Steve Wise <[EMAIL PROTECTED]> Date: Wed, 26 Jul 2006 11:15:43 -0500 > Dave, what do you think about removing the user-space stuff for the > first round of integration? IE: Just add netevents and kernel hooks to > generate them. Sure. - 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
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: [3/4] kevent: AIO, aio_sendfile() implementation.
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
RFC: kernel memory leak fix for af_unix datagram getpeersec
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: [PATCH]NET: Add ECN support for TSO
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
RE: H/W requirements for NETIF_F_HW_CSUM
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: 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. 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
[PATCH] via-rhine: NAPI poll enable
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: [PATCH 24/24] RT2x00: Misc. fixes
>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
>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
Re: [PATCH 20/24] RT2x00: Use SET_NETDEV_DEV
>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
>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 22/24] RT2x00: Optimize config handlers
>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
>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
>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 21/24] RT2x00: Correctly initialize tx_status->control field before packet transmission
>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 15/24] RT2x00: Merge PCI and USB version of data_entry structure
>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 7/24] RT2x00: Add RTS frame creation
>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
>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
>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 12/24] RT2x00: Add new rt73usb devices
>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
>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 11/24] RT2x00: Move scan_work to scanning structure
>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
>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 8/24] RT2x00: Fix *_set_state() functions
>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 6/24] RT2x00: Add TXPOWER_FROM_DEV and TXPOWER_TO_DEV macros
>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 5/24] RT2x00: Clean up device specific rate value initialization
>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 4/24] RT2x00: Add ethtool support
>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 2/24] RT2x00: Add interface structure
>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
[RESEND PATCH 0/24] RT2x00
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 10/24] RT2x00: Add software and hardware sequence counting
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
Re: [PATCH 10/24] RT2x00: Add software and hardware sequence counting
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
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
H/W requirements for NETIF_F_HW_CSUM
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
[PATCH 12/24] RT2x00: Add new rt73usb devices
>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
>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
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
[PATCH 14/24] RT2x00: Check if read eeprom words are valid
>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
>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
>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 15/24] RT2x00: Merge PCI and USB version of data_entry structure
>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
>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 2/24] RT2x00: Add interface structure
>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
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
>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 13/24] RT2x00: Allow link tuning while scanning
>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
>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 10/24] RT2x00: Add software and hardware sequence counting
>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
>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 22/24] RT2x00: Optimize config handlers
>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
>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 4/24] RT2x00: Add ethtool support
>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
>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
>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 21/24] RT2x00: Correctly initialize tx_status->control field before packet transmission
>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
>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
>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 23/24] RT2x00: Fix register initialization
>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 9/24] RT2x00: Don't use driver_data and driver_info fields
>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 6/24] RT2x00: Add TXPOWER_FROM_DEV and TXPOWER_TO_DEV macros
>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
Re: [PATCH dscape] d80211: Switch d80211.h to IEEE80211_ style names
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 ?
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
Re: [PATCH dscape] d80211: Switch d80211.h to IEEE80211_ style names
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
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