Netdev List
 help / color / mirror / Atom feed
* [PATCH 0/8] Intel I/O Acceleration Technology (I/OAT)
From: Chris Leech @ 2006-03-03 21:40 UTC (permalink / raw)
  To: linux-kernel, netdev

This patch series is the first full release of the Intel(R) I/O
Acceleration Technology (I/OAT) for Linux.  It includes an in kernel API
for offloading memory copies to hardware, a driver for the I/OAT DMA memcpy
engine, and changes to the TCP stack to offload copies of received
networking data to application space.

These changes apply to DaveM's net-2.6.17 tree as of commit
2bd84a93d8bb7192ad8c23ef41008502be1cb603 ([IRDA]: TOIM3232 dongle support)

They are available to pull from
	git://198.78.49.142/~cleech/linux-2.6 ioat-2.6.17

There are 8 patches in the series:
	1) The memcpy offload APIs and class code
	2) The Intel I/OAT DMA driver (ioatdma)
	3) Core networking code to setup networking as a DMA memcpy client
	4) Utility functions for sk_buff to iovec offloaded copy
	5) Structure changes needed for TCP receive offload
	6) Rename cleanup_rbuf to tcp_cleanup_rbuf
	7) Add a sysctl to tune the minimum offloaded I/O size for TCP
	8) The main TCP receive offload changes

--
Chris Leech <christopher.leech@intel.com>
I/O Acceleration Technology Software Development
LAN Access Division / Digital Enterprise Group 

^ permalink raw reply

* [PATCH 3/5] export of ip_dev_find as part of Infiniband connection abstraction
From: Sean Hefty @ 2006-03-03 21:14 UTC (permalink / raw)
  To: Hefty, Sean, netdev, linux-kernel; +Cc: openib-general
In-Reply-To: <ORSMSX401X3cf3ednHM0000009a@orsmsx401.amr.corp.intel.com>

I wanted to make doubly sure that this didn't get lost in the patch series, but
ip_dev_find() is re-exported.  The use is shown below.

- Sean

>+int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
>+{
>+	struct net_device *dev;
>+	u32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
>+	int ret;
>+
>+	dev = ip_dev_find(ip);
>+	if (!dev)
>+		return -EADDRNOTAVAIL;
>+
>+	ret = copy_addr(dev_addr, dev, NULL);
>+	dev_put(dev);
>+	return ret;
>+}

{snip}

>+static int addr_resolve_local(struct sockaddr_in *src_in,
>+			      struct sockaddr_in *dst_in,
>+			      struct rdma_dev_addr *addr)
>+{
>+	struct net_device *dev;
>+	u32 src_ip = src_in->sin_addr.s_addr;
>+	u32 dst_ip = dst_in->sin_addr.s_addr;
>+	int ret;
>+
>+	dev = ip_dev_find(dst_ip);
>+	if (!dev)
>+		return -EADDRNOTAVAIL;
>+
>+	if (!src_ip) {
>+		src_in->sin_family = dst_in->sin_family;
>+		src_in->sin_addr.s_addr = dst_ip;
>+		ret = copy_addr(addr, dev, dev->dev_addr);
>+	} else {
>+		ret = rdma_translate_ip((struct sockaddr *)src_in, addr);
>+		if (!ret)
>+			memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
>+	}
>+
>+	dev_put(dev);
>+	return ret;
>+}

{snip}

>diff -uprN -X linux-2.6.git/Documentation/dontdiff
>linux-2.6.git/net/ipv4/fib_frontend.c
>linux-2.6.ib/net/ipv4/fib_frontend.c
>--- linux-2.6.git/net/ipv4/fib_frontend.c	2006-01-16 10:28:29.000000000
-0800
>+++ linux-2.6.ib/net/ipv4/fib_frontend.c	2006-01-16 16:14:24.000000000
-0800
>@@ -666,4 +666,5 @@ void __init ip_fib_init(void)
> }
>
> EXPORT_SYMBOL(inet_addr_type);
>+EXPORT_SYMBOL(ip_dev_find);
> EXPORT_SYMBOL(ip_rt_ioctl);

^ permalink raw reply

* [PATCH 0/5] Infiniband: connection abstraction
From: Sean Hefty @ 2006-03-03 21:13 UTC (permalink / raw)
  To: Hefty, Sean, netdev, linux-kernel; +Cc: openib-general
In-Reply-To: <ORSMSX401KZmcK8r6be00000097@orsmsx401.amr.corp.intel.com>

>Here's an updated version of these patches based on feedback.   (The license
>did not change and continues to match that of the other Infiniband code.)
>Please consider for inclusion in 2.6.17.

This is just a ping for anymore feedback to this patch series, so that I can
respond to any requests before 2.6.17 opens up.

I can resubmit the patches if necessary.

Thanks,
Sean

^ permalink raw reply

* Re: [Announce] Intel PRO/Wireless 3945ABG Network Connection
From: Jeff Garzik @ 2006-03-03 20:31 UTC (permalink / raw)
  To: Kasper Sandberg
  Cc: Christoph Hellwig, Alan Cox, James Ketrenos, NetDev, linux-kernel,
	okir
In-Reply-To: <1141416267.17837.1.camel@localhost>

Kasper Sandberg wrote:
> the binary userspace daemon protects against nothing.

In the technical realm, true.  In the legal realm, potentially false.

	Jeff

^ permalink raw reply

* Re: [Announce] Intel PRO/Wireless 3945ABG Network Connection
From: Kasper Sandberg @ 2006-03-03 20:04 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Alan Cox, James Ketrenos, NetDev, linux-kernel, okir
In-Reply-To: <20060227171029.GA763@infradead.org>

On Mon, 2006-02-27 at 17:10 +0000, Christoph Hellwig wrote:
> On Sun, Feb 26, 2006 at 12:58:02AM +0000, Alan Cox wrote:
> > On Sad, 2006-02-25 at 08:41 +0000, Christoph Hellwig wrote:
> > > the regualatory problems are not true.  
> > 
> > They are although the binary interpretation isn't AFAIK from law but
> > from lawyers. The same is actually true in much of the EU. The actual
> > requirement is that the transmitting device must be reasonably
> > tamperproof. Some of the lawyers have decided that for a software radio
> > tamperproof means "binary".
> 
> Exactly.  There's no strong requirement, it's just over-zealous corporate
> lawyers.  That's why we need to push Intel strongly here.
i completely agree, besides, if this userspace binary blob just does
something to /sys what is to prevent a user from doing that himself?
what is to prevent someone to modify the driver slightly to smash a log
entry every time the daemon does something?

the binary userspace daemon protects against nothing.
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

^ permalink raw reply

* Re: [RFC] [PATCH 1/2] Driver to remember ethernet MAC values: maclist
From: Atsushi Nemoto @ 2006-03-03 16:17 UTC (permalink / raw)
  To: tbm; +Cc: linux-kernel, netdev, jbowler
In-Reply-To: <20060220010113.GA19309@deprecation.cyrius.com>

>>>>> On Mon, 20 Feb 2006 01:01:13 +0000, Martin Michlmayr <tbm@cyrius.com> said:

tbm> Some Ethernet hardware implementations have no built-in storage
tbm> for allocated MAC values - an example is the Intel IXP420 chip
tbm> which has support for Ethernet but no defined way of storing
tbm> allocated MAC values.  With such hardware different board level
tbm> implementations store the allocated MAC (or MACs) in different
tbm> ways.  Rather than put board level code into a specific Ethernet
tbm> driver this driver provides a generally accessible repository for
tbm> the MACs which can be written by board level code and read by the
tbm> driver.

Slow response:

It can be done with register_netdevice_notifier().  You can catch
NETDEV_REGISTER event, check the device is what you expected by
looking dev->irq or something, and initialize dev->dev_addr.  Whole
these can be implemented in your board level code.

---
Atsushi Nemoto

^ permalink raw reply

* 2.6.16-rc5-mm2: IPW_QOS: two remarks
From: Adrian Bunk @ 2006-03-03 15:26 UTC (permalink / raw)
  To: Andrew Morton, Andreas Happe; +Cc: linux-kernel, linville, jgarzik, netdev
In-Reply-To: <20060303045651.1f3b55ec.akpm@osdl.org>

On Fri, Mar 03, 2006 at 04:56:51AM -0800, Andrew Morton wrote:
>...
> Changes since 2.6.16-rc5-mm1:
>...
>  git-netdev-all.patch
>...
>  git trees
>...

Two remarks regarding the new IPW_QOS option:
- it should be named IPW2200_QOS (similar to the other IPW2200_* 
  options)
- please add a help text

cu
Adrian

-- 

       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed

^ permalink raw reply

* [PATCH 1/4] [REQSK] Dont reset rskq_defer_accept in reqsk_queue_alloc
From: Chris Wright @ 2006-03-03  7:55 UTC (permalink / raw)
  To: linux-kernel, stable, David S. Miller
  Cc: Justin Forbes, Zwane Mwaikambo, Theodore Ts'o, Randy Dunlap,
	Dave Jones, Chuck Wolber, torvalds, akpm, alan,
	Arnaldo Carvalho de Melo, netdev, Alexandra N. Kossovsky,
	Arnaldo Carvalho de Melo
In-Reply-To: <20060303075542.659414000@sorel.sous-sol.org>

[-- Attachment #1: don-t-reset-rskq_defer_accept-in-reqsk_queue_alloc.patch --]
[-- Type: text/plain, Size: 1113 bytes --]

-stable review patch.  If anyone has any objections, please let us know.
------------------

In 295f7324ff8d9ea58b4d3ec93b1aaa1d80e048a9 I moved defer_accept from
tcp_sock to request_queue and mistakingly reset it at reqsl_queue_alloc, causing
calls to setsockopt(TCP_DEFER_ACCEPT ) to be lost after bind, the fix is to
remove the zeroing of rskq_defer_accept from reqsl_queue_alloc.

Thanks to Alexandra N. Kossovsky <Alexandra.Kossovsky@oktetlabs.ru> for
reporting and testing the suggested fix.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
---

 net/core/request_sock.c |    1 -
 1 files changed, 1 deletion(-)

--- linux-2.6.15.5.orig/net/core/request_sock.c
+++ linux-2.6.15.5/net/core/request_sock.c
@@ -52,7 +52,6 @@ int reqsk_queue_alloc(struct request_soc
 	get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd));
 	rwlock_init(&queue->syn_wait_lock);
 	queue->rskq_accept_head = queue->rskq_accept_head = NULL;
-	queue->rskq_defer_accept = 0;
 	lopt->nr_table_entries = nr_table_entries;
 
 	write_lock_bh(&queue->syn_wait_lock);

--

^ permalink raw reply

* Re: [PATCH] powerpc: ibmveth: Harden driver initilisation for kexec
From: Randy.Dunlap @ 2006-03-03  4:12 UTC (permalink / raw)
  To: michael; +Cc: linuxppc64-dev, jgarzik, anton, netdev
In-Reply-To: <200603031210.53220.michael@ellerman.id.au>

On Fri, 3 Mar 2006 12:10:47 +1100 Michael Ellerman wrote:

> On Fri, 3 Mar 2006 11:34, Randy.Dunlap wrote:
> > On Fri, 3 Mar 2006 11:22:45 +1100 Michael Ellerman wrote:
> > > Hi Jeff,
> > >
> > > I realise it's late, but it'd be really good if you could send this up
> > > for 2.6.16, we're hosed without it.
> >
> > I'm wondering if this means that for every virtual/hypervisor
> > situation, we have to modify any $interested_drivers.
> > Why wouldn't we come up with a cleaner solution (in the long term)?
> >
> > E.g., could the hypervisor know when one of it's virtual OSes
> > dies or reboots and release its resources then?
> 
> It does exactly that for a regular reboot, but when we kexec we _don't_ die or 
> reboot, as far as the Hypervisor is concerned it's all systems go.
> 
> It's something of a double-edged sword, we're totally in control which gives 
> us lots of flexibility, and _fast_ reboot times, but we also have to do a bit 
> of extra stuff (ie. this patch) to keep things sane.

s/this patch/some patch/

Yes, you have certainly thought about this more/longer than I have,
so why is something more generic like this bad instead of good:

Somewhere early in start_kernel() (e.g.), do an hv call that says
"free all assigned resources".

Maybe hv doesn't know "all assigned resources."
Maybe it's just that this patch is simpler than an hv change,
although this (current) patch could leave some other drivers that
need to be "fixed," while an hv change wouldn't do that.

So I'm not opposed to this current patch as a short-term solution,
but I don't think it's the right long-term solution.

---
~Randy

^ permalink raw reply

* Re: [PATCH] powerpc: ibmveth: Harden driver initilisation for kexec
From: Michael Ellerman @ 2006-03-03  2:11 UTC (permalink / raw)
  To: linuxppc64-dev; +Cc: Paul Mackerras, netdev, Jeff Garzik, anton
In-Reply-To: <44079627.6070100@pobox.com>


[-- Attachment #1.1: Type: text/plain, Size: 1464 bytes --]

On Fri, 3 Mar 2006 12:04, Jeff Garzik wrote:
> Santiago Leon wrote:
> > From: Michael Ellerman <michael@ellerman.id.au>
> >
> > After a kexec the veth driver will fail when trying to register with the
> > Hypervisor because the previous kernel has not unregistered.
> >
> > So if the registration fails, we unregister and then try again.
> >
> > Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> > Acked-by: Anton Blanchard <anton@samba.org>
> > Signed-off-by: Santiago Leon <santil@us.ibm.com>
> > ---
> >
> >  drivers/net/ibmveth.c |   32 ++++++++++++++++++++++++++------
> >  1 files changed, 26 insertions(+), 6 deletions(-)
> >
> > Looks good to me, and has been around for a couple of months.
>
> This seems completely bonkers to me:
>
> 	are resources available?
> 	if no
> 		free resources
> 		try again

I'm not sure I follow, are you suggesting we do the h_free_logical_lan() 
unconditionally, followed by h_register_logical_lan() ??

If that's what you mean, I didn't do it that way because it would effect the 
normal code path. This patch only modifies the behaviour if we fail to 
register the adapter. I'm much more comfortable changing the failure case 
than the default.

cheers

-- 
Michael Ellerman
IBM OzLabs

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

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

_______________________________________________
Linuxppc64-dev mailing list
Linuxppc64-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc64-dev

^ permalink raw reply

* Re: [PATCH] powerpc: ibmveth: Harden driver initilisation for kexec
From: Michael Ellerman @ 2006-03-03  1:10 UTC (permalink / raw)
  To: linuxppc64-dev; +Cc: netdev, Randy.Dunlap, jgarzik, anton
In-Reply-To: <20060302163423.f758c5bc.rdunlap@xenotime.net>


[-- Attachment #1.1: Type: text/plain, Size: 1159 bytes --]

On Fri, 3 Mar 2006 11:34, Randy.Dunlap wrote:
> On Fri, 3 Mar 2006 11:22:45 +1100 Michael Ellerman wrote:
> > Hi Jeff,
> >
> > I realise it's late, but it'd be really good if you could send this up
> > for 2.6.16, we're hosed without it.
>
> I'm wondering if this means that for every virtual/hypervisor
> situation, we have to modify any $interested_drivers.
> Why wouldn't we come up with a cleaner solution (in the long term)?
>
> E.g., could the hypervisor know when one of it's virtual OSes
> dies or reboots and release its resources then?

It does exactly that for a regular reboot, but when we kexec we _don't_ die or 
reboot, as far as the Hypervisor is concerned it's all systems go.

It's something of a double-edged sword, we're totally in control which gives 
us lots of flexibility, and _fast_ reboot times, but we also have to do a bit 
of extra stuff (ie. this patch) to keep things sane.

cheers

-- 
Michael Ellerman
IBM OzLabs

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

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

_______________________________________________
Linuxppc64-dev mailing list
Linuxppc64-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc64-dev

^ permalink raw reply

* Re: [PATCH] powerpc: ibmveth: Harden driver initilisation for kexec
From: Jeff Garzik @ 2006-03-03  1:04 UTC (permalink / raw)
  To: Santiago Leon; +Cc: michael, linuxppc64-dev, Paul Mackerras, anton, netdev
In-Reply-To: <44074A22.8060705@us.ibm.com>

Santiago Leon wrote:
> From: Michael Ellerman <michael@ellerman.id.au>
> 
> After a kexec the veth driver will fail when trying to register with the
> Hypervisor because the previous kernel has not unregistered.
> 
> So if the registration fails, we unregister and then try again.
> 
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> Acked-by: Anton Blanchard <anton@samba.org>
> Signed-off-by: Santiago Leon <santil@us.ibm.com>
> ---
> 
>  drivers/net/ibmveth.c |   32 ++++++++++++++++++++++++++------
>  1 files changed, 26 insertions(+), 6 deletions(-)
> 
> Looks good to me, and has been around for a couple of months.

This seems completely bonkers to me:

	are resources available?
	if no
		free resources
		try again

It makes resource checking pointless.

	Jeff

^ permalink raw reply

* Re: [PATCH] powerpc: ibmveth: Harden driver initilisation for kexec
From: Paul Mackerras @ 2006-03-03  1:00 UTC (permalink / raw)
  To: Randy.Dunlap; +Cc: michael, linuxppc64-dev, jgarzik, anton, netdev
In-Reply-To: <20060302163423.f758c5bc.rdunlap@xenotime.net>

Randy.Dunlap writes:

> E.g., could the hypervisor know when one of it's virtual OSes
> dies or reboots and release its resources then?

I think the point is that with kexec, the same virtual machine keeps
running, so the hypervisor doesn't see the OS dying or rebooting.

Paul.

^ permalink raw reply

* Re: [PATCH] powerpc: ibmveth: Harden driver initilisation for kexec
From: Randy.Dunlap @ 2006-03-03  0:34 UTC (permalink / raw)
  To: michael; +Cc: linuxppc64-dev, netdev, jgarzik, anton
In-Reply-To: <200603031122.51174.michael@ellerman.id.au>

On Fri, 3 Mar 2006 11:22:45 +1100 Michael Ellerman wrote:

> Hi Jeff,
> 
> I realise it's late, but it'd be really good if you could send this up for 
> 2.6.16, we're hosed without it.

I'm wondering if this means that for every virtual/hypervisor
situation, we have to modify any $interested_drivers.
Why wouldn't we come up with a cleaner solution (in the long term)?

E.g., could the hypervisor know when one of it's virtual OSes
dies or reboots and release its resources then?

This patch just looks like a short-term solution to me.


> cheers
> 
> On Fri, 3 Mar 2006 06:40, Santiago Leon wrote:
> > From: Michael Ellerman <michael@ellerman.id.au>
> >
> > After a kexec the veth driver will fail when trying to register with the
> > Hypervisor because the previous kernel has not unregistered.
> >
> > So if the registration fails, we unregister and then try again.
> >
> > Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> > Acked-by: Anton Blanchard <anton@samba.org>
> > Signed-off-by: Santiago Leon <santil@us.ibm.com>
> > ---
> >
> >   drivers/net/ibmveth.c |   32 ++++++++++++++++++++++++++------
> >   1 files changed, 26 insertions(+), 6 deletions(-)
> >
> > Looks good to me, and has been around for a couple of months.
> >
> > Index: kexec/drivers/net/ibmveth.c
> > ===================================================================
> > --- kexec.orig/drivers/net/ibmveth.c
> > +++ kexec/drivers/net/ibmveth.c
> > @@ -436,6 +436,31 @@ static void ibmveth_cleanup(struct ibmve
> >   		ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[i]);
> >   }
> >
> > +static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter,
> > +		union ibmveth_buf_desc rxq_desc, u64 mac_address)
> > +{
> > +	int rc, try_again = 1;
> > +
> > +	/* After a kexec the adapter will still be open, so our attempt to
> > +	 * open it will fail. So if we get a failure we free the adapter and
> > +	 * try again, but only once. */
> > +retry:
> > +	rc = h_register_logical_lan(adapter->vdev->unit_address,
> > +			adapter->buffer_list_dma, rxq_desc.desc,
> > +			adapter->filter_list_dma, mac_address);
> > +
> > +	if (rc != H_Success && try_again) {
> > +		do {
> > +			rc = h_free_logical_lan(adapter->vdev->unit_address);
> > +		} while (H_isLongBusy(rc) || (rc == H_Busy));
> > +
> > +		try_again = 0;
> > +		goto retry;
> > +	}
> > +
> > +	return rc;
> > +}
> > +
> >   static int ibmveth_open(struct net_device *netdev)
> >   {
> >   	struct ibmveth_adapter *adapter = netdev->priv;
> > @@ -504,12 +529,7 @@ static int ibmveth_open(struct net_devic
> >   	ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr);
> >   	ibmveth_debug_printk("receive q   @ 0x%p\n",
> > adapter->rx_queue.queue_addr);
> >
> > -
> > -	lpar_rc = h_register_logical_lan(adapter->vdev->unit_address,
> > -					 adapter->buffer_list_dma,
> > -					 rxq_desc.desc,
> > -					 adapter->filter_list_dma,
> > -					 mac_address);
> > +	lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address);
> >
> >   	if(lpar_rc != H_Success) {
> >   		ibmveth_error_printk("h_register_logical_lan failed with %ld\n",
> > lpar_rc);
> >
> >
> >
> > _______________________________________________
> > Linuxppc64-dev mailing list
> > Linuxppc64-dev@ozlabs.org
> > https://ozlabs.org/mailman/listinfo/linuxppc64-dev
> 
> -- 
> Michael Ellerman
> IBM OzLabs

---
~Randy

^ permalink raw reply

* Re: [PATCH] powerpc: ibmveth: Harden driver initilisation for kexec
From: Michael Ellerman @ 2006-03-03  0:22 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc64-dev, netdev, anton
In-Reply-To: <44074A22.8060705@us.ibm.com>


[-- Attachment #1.1: Type: text/plain, Size: 3053 bytes --]

Hi Jeff,

I realise it's late, but it'd be really good if you could send this up for 
2.6.16, we're hosed without it.

cheers

On Fri, 3 Mar 2006 06:40, Santiago Leon wrote:
> From: Michael Ellerman <michael@ellerman.id.au>
>
> After a kexec the veth driver will fail when trying to register with the
> Hypervisor because the previous kernel has not unregistered.
>
> So if the registration fails, we unregister and then try again.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> Acked-by: Anton Blanchard <anton@samba.org>
> Signed-off-by: Santiago Leon <santil@us.ibm.com>
> ---
>
>   drivers/net/ibmveth.c |   32 ++++++++++++++++++++++++++------
>   1 files changed, 26 insertions(+), 6 deletions(-)
>
> Looks good to me, and has been around for a couple of months.
>
> Index: kexec/drivers/net/ibmveth.c
> ===================================================================
> --- kexec.orig/drivers/net/ibmveth.c
> +++ kexec/drivers/net/ibmveth.c
> @@ -436,6 +436,31 @@ static void ibmveth_cleanup(struct ibmve
>   		ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[i]);
>   }
>
> +static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter,
> +		union ibmveth_buf_desc rxq_desc, u64 mac_address)
> +{
> +	int rc, try_again = 1;
> +
> +	/* After a kexec the adapter will still be open, so our attempt to
> +	 * open it will fail. So if we get a failure we free the adapter and
> +	 * try again, but only once. */
> +retry:
> +	rc = h_register_logical_lan(adapter->vdev->unit_address,
> +			adapter->buffer_list_dma, rxq_desc.desc,
> +			adapter->filter_list_dma, mac_address);
> +
> +	if (rc != H_Success && try_again) {
> +		do {
> +			rc = h_free_logical_lan(adapter->vdev->unit_address);
> +		} while (H_isLongBusy(rc) || (rc == H_Busy));
> +
> +		try_again = 0;
> +		goto retry;
> +	}
> +
> +	return rc;
> +}
> +
>   static int ibmveth_open(struct net_device *netdev)
>   {
>   	struct ibmveth_adapter *adapter = netdev->priv;
> @@ -504,12 +529,7 @@ static int ibmveth_open(struct net_devic
>   	ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr);
>   	ibmveth_debug_printk("receive q   @ 0x%p\n",
> adapter->rx_queue.queue_addr);
>
> -
> -	lpar_rc = h_register_logical_lan(adapter->vdev->unit_address,
> -					 adapter->buffer_list_dma,
> -					 rxq_desc.desc,
> -					 adapter->filter_list_dma,
> -					 mac_address);
> +	lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address);
>
>   	if(lpar_rc != H_Success) {
>   		ibmveth_error_printk("h_register_logical_lan failed with %ld\n",
> lpar_rc);
>
>
>
> _______________________________________________
> Linuxppc64-dev mailing list
> Linuxppc64-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc64-dev

-- 
Michael Ellerman
IBM OzLabs

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]

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

_______________________________________________
Linuxppc64-dev mailing list
Linuxppc64-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc64-dev

^ permalink raw reply

* [PATCH] powerpc: ibmveth: Harden driver initilisation for kexec
From: Santiago Leon @ 2006-03-02 19:40 UTC (permalink / raw)
  To: anton, linuxppc64-dev, michael, jgarzik, netdev
In-Reply-To: <20060131042903.GF28896@krispykreme>

From: Michael Ellerman <michael@ellerman.id.au>

After a kexec the veth driver will fail when trying to register with the
Hypervisor because the previous kernel has not unregistered.

So if the registration fails, we unregister and then try again.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Santiago Leon <santil@us.ibm.com>
---

  drivers/net/ibmveth.c |   32 ++++++++++++++++++++++++++------
  1 files changed, 26 insertions(+), 6 deletions(-)

Looks good to me, and has been around for a couple of months.

Index: kexec/drivers/net/ibmveth.c
===================================================================
--- kexec.orig/drivers/net/ibmveth.c
+++ kexec/drivers/net/ibmveth.c
@@ -436,6 +436,31 @@ static void ibmveth_cleanup(struct ibmve
  		ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[i]);
  }

+static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter,
+		union ibmveth_buf_desc rxq_desc, u64 mac_address)
+{
+	int rc, try_again = 1;
+
+	/* After a kexec the adapter will still be open, so our attempt to
+	 * open it will fail. So if we get a failure we free the adapter and
+	 * try again, but only once. */
+retry:
+	rc = h_register_logical_lan(adapter->vdev->unit_address,
+			adapter->buffer_list_dma, rxq_desc.desc,
+			adapter->filter_list_dma, mac_address);
+
+	if (rc != H_Success && try_again) {
+		do {
+			rc = h_free_logical_lan(adapter->vdev->unit_address);
+		} while (H_isLongBusy(rc) || (rc == H_Busy));
+
+		try_again = 0;
+		goto retry;
+	}
+
+	return rc;
+}
+
  static int ibmveth_open(struct net_device *netdev)
  {
  	struct ibmveth_adapter *adapter = netdev->priv;
@@ -504,12 +529,7 @@ static int ibmveth_open(struct net_devic
  	ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr);
  	ibmveth_debug_printk("receive q   @ 0x%p\n", 
adapter->rx_queue.queue_addr);

-
-	lpar_rc = h_register_logical_lan(adapter->vdev->unit_address,
-					 adapter->buffer_list_dma,
-					 rxq_desc.desc,
-					 adapter->filter_list_dma,
-					 mac_address);
+	lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address);

  	if(lpar_rc != H_Success) {
  		ibmveth_error_printk("h_register_logical_lan failed with %ld\n", 
lpar_rc);

^ permalink raw reply

* Re: [PATCH] IrDA: TOIM3232 dongle support
From: David S. Miller @ 2006-03-02  0:04 UTC (permalink / raw)
  To: samuel.ortiz-xNZwKgViW5gAvxtiuMwx3w
  Cc: irda-users-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	netdev-u79uwXL29TY76Z2rM5mHXA, jt-sDzT885Ts8HQT0dZR+AlfA
In-Reply-To: <20060301223623.GA17813@irie>

From: Samuel Ortiz <samuel.ortiz-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
Date: Thu, 2 Mar 2006 00:36:23 +0200

> Here goes a patch for supporting TOIM3232 based serial IrDA dongles.
> The code is based on the tekram dongle code.
> 
> It's been tested with a TOIM3232 based IRWave 320S dongle. It may work
> for TOIM4232 dongles, although it's not been tested.
> 
> Signed-off-by: David Basden <davidb-irda-Q/PxBS77Xz0@public.gmane.org>
> Signed-off-by: Samuel Ortiz <samuel.ortiz-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>

Applied, thanks a lot.


-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642

^ permalink raw reply

* Re: [PATCH] pcmcia: avoid binding hostap_cs to Orinoco cards
From: Jeff Garzik @ 2006-03-01 23:37 UTC (permalink / raw)
  To: Linux Kernel Mailing List, linux, Netdev List
In-Reply-To: <200603012259.k21MxEN3013604@hera.kernel.org>

Linux Kernel Mailing List wrote:
> commit 40e3cad61197fce63853e778db020f7637d988f2
> tree 6e086c930e1aef0bb24eb61af42d1f3c1fb7d38c
> parent f0892b89e3c19c7d805825ca12511d26dcdf6415
> author Pavel Roskin <proski@gnu.org> Tue, 28 Feb 2006 11:18:31 -0500
> committer Dominik Brodowski <linux@dominikbrodowski.net> Wed, 01 Mar 2006 11:12:00 +0100
> 
> [PATCH] pcmcia: avoid binding hostap_cs to Orinoco cards
> 
> Don't just use cards with PCMCIA ID 0x0156, 0x0002.  Make sure that the
> vendor string is "Intersil" or "INTERSIL"
> 
> Signed-off-by: Pavel Roskin <proski@gnu.org>
> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
> 
>  drivers/net/wireless/hostap/hostap_cs.c |    5 ++++-
>  1 files changed, 4 insertions(+), 1 deletion(-)

Why was this not CC'd to the wireless maintainer and netdev list?

	Jeff

^ permalink raw reply

* [git patch] e1000 fix
From: Jeff Garzik @ 2006-03-01 22:42 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: netdev, linux-kernel


Please pull from 'upstream-fixes' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git

to receive the following updates:

 drivers/net/e1000/e1000.h      |    3 -
 drivers/net/e1000/e1000_main.c |  117 +++++++++++++++--------------------------
 2 files changed, 45 insertions(+), 75 deletions(-)

Jeff Kirsher:
      e1000: revert to single descriptor for legacy receive path

diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 27c7730..99baf0e 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -225,9 +225,6 @@ struct e1000_rx_ring {
 	struct e1000_ps_page *ps_page;
 	struct e1000_ps_page_dma *ps_page_dma;
 
-	struct sk_buff *rx_skb_top;
-	struct sk_buff *rx_skb_prev;
-
 	/* cpu for rx queue */
 	int cpu;
 
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 31e3329..5b7d0f4 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -103,7 +103,7 @@ static char e1000_driver_string[] = "Int
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION "6.3.9-k2"DRIVERNAPI
+#define DRV_VERSION "6.3.9-k4"DRIVERNAPI
 char e1000_driver_version[] = DRV_VERSION;
 static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
 
@@ -1635,8 +1635,6 @@ setup_rx_desc_die:
 
 	rxdr->next_to_clean = 0;
 	rxdr->next_to_use = 0;
-	rxdr->rx_skb_top = NULL;
-	rxdr->rx_skb_prev = NULL;
 
 	return 0;
 }
@@ -1713,8 +1711,23 @@ e1000_setup_rctl(struct e1000_adapter *a
 		rctl |= adapter->rx_buffer_len << 0x11;
 	} else {
 		rctl &= ~E1000_RCTL_SZ_4096;
-		rctl &= ~E1000_RCTL_BSEX;
-		rctl |= E1000_RCTL_SZ_2048;
+		rctl |= E1000_RCTL_BSEX; 
+		switch (adapter->rx_buffer_len) {
+		case E1000_RXBUFFER_2048:
+		default:
+			rctl |= E1000_RCTL_SZ_2048;
+			rctl &= ~E1000_RCTL_BSEX;
+			break;
+		case E1000_RXBUFFER_4096:
+			rctl |= E1000_RCTL_SZ_4096;
+			break;
+		case E1000_RXBUFFER_8192:
+			rctl |= E1000_RCTL_SZ_8192;
+			break;
+		case E1000_RXBUFFER_16384:
+			rctl |= E1000_RCTL_SZ_16384;
+			break;
+		}
 	}
 
 #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
@@ -2107,16 +2120,6 @@ e1000_clean_rx_ring(struct e1000_adapter
 		}
 	}
 
-	/* there also may be some cached data in our adapter */
-	if (rx_ring->rx_skb_top) {
-		dev_kfree_skb(rx_ring->rx_skb_top);
-
-		/* rx_skb_prev will be wiped out by rx_skb_top */
-		rx_ring->rx_skb_top = NULL;
-		rx_ring->rx_skb_prev = NULL;
-	}
-
-
 	size = sizeof(struct e1000_buffer) * rx_ring->count;
 	memset(rx_ring->buffer_info, 0, size);
 	size = sizeof(struct e1000_ps_page) * rx_ring->count;
@@ -3106,24 +3109,27 @@ e1000_change_mtu(struct net_device *netd
 		break;
 	}
 
-	/* since the driver code now supports splitting a packet across
-	 * multiple descriptors, most of the fifo related limitations on
-	 * jumbo frame traffic have gone away.
-	 * simply use 2k descriptors for everything.
-	 *
-	 * NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
-	 * means we reserve 2 more, this pushes us to allocate from the next
-	 * larger slab size
-	 * i.e. RXBUFFER_2048 --> size-4096 slab */
 
-	/* recent hardware supports 1KB granularity */
 	if (adapter->hw.mac_type > e1000_82547_rev_2) {
-		adapter->rx_buffer_len =
-		    ((max_frame < E1000_RXBUFFER_2048) ?
-		        max_frame : E1000_RXBUFFER_2048);
+		adapter->rx_buffer_len = max_frame;
 		E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
-	} else
-		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+	} else {
+		if(unlikely((adapter->hw.mac_type < e1000_82543) &&
+		   (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
+			DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
+					    "on 82542\n");
+			return -EINVAL;
+		} else {
+			if(max_frame <= E1000_RXBUFFER_2048)
+				adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+			else if(max_frame <= E1000_RXBUFFER_4096)
+				adapter->rx_buffer_len = E1000_RXBUFFER_4096;
+			else if(max_frame <= E1000_RXBUFFER_8192)
+				adapter->rx_buffer_len = E1000_RXBUFFER_8192;
+			else if(max_frame <= E1000_RXBUFFER_16384)
+				adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+		}
+	}
 
 	netdev->mtu = new_mtu;
 
@@ -3620,7 +3626,7 @@ e1000_clean_rx_irq(struct e1000_adapter 
 	uint8_t last_byte;
 	unsigned int i;
 	int cleaned_count = 0;
-	boolean_t cleaned = FALSE, multi_descriptor = FALSE;
+	boolean_t cleaned = FALSE;
 
 	i = rx_ring->next_to_clean;
 	rx_desc = E1000_RX_DESC(*rx_ring, i);
@@ -3652,43 +3658,12 @@ e1000_clean_rx_irq(struct e1000_adapter 
 
 		length = le16_to_cpu(rx_desc->length);
 
-		skb_put(skb, length);
-
-		if (!(status & E1000_RXD_STAT_EOP)) {
-			if (!rx_ring->rx_skb_top) {
-				rx_ring->rx_skb_top = skb;
-				rx_ring->rx_skb_top->len = length;
-				rx_ring->rx_skb_prev = skb;
-			} else {
-				if (skb_shinfo(rx_ring->rx_skb_top)->frag_list) {
-					rx_ring->rx_skb_prev->next = skb;
-					skb->prev = rx_ring->rx_skb_prev;
-				} else {
-					skb_shinfo(rx_ring->rx_skb_top)->frag_list = skb;
-				}
-				rx_ring->rx_skb_prev = skb;
-				rx_ring->rx_skb_top->data_len += length;
-			}
+		if (unlikely(!(status & E1000_RXD_STAT_EOP))) {
+			/* All receives must fit into a single buffer */
+			E1000_DBG("%s: Receive packet consumed multiple"
+				  " buffers\n", netdev->name);
+			dev_kfree_skb_irq(skb);
 			goto next_desc;
-		} else {
-			if (rx_ring->rx_skb_top) {
-				if (skb_shinfo(rx_ring->rx_skb_top)
-							->frag_list) {
-					rx_ring->rx_skb_prev->next = skb;
-					skb->prev = rx_ring->rx_skb_prev;
-				} else
-					skb_shinfo(rx_ring->rx_skb_top)
-							->frag_list = skb;
-
-				rx_ring->rx_skb_top->data_len += length;
-				rx_ring->rx_skb_top->len +=
-					rx_ring->rx_skb_top->data_len;
-
-				skb = rx_ring->rx_skb_top;
-				multi_descriptor = TRUE;
-				rx_ring->rx_skb_top = NULL;
-				rx_ring->rx_skb_prev = NULL;
-			}
 		}
 
 		if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
@@ -3712,10 +3687,7 @@ e1000_clean_rx_irq(struct e1000_adapter 
 		 * performance for small packets with large amounts
 		 * of reassembly being done in the stack */
 #define E1000_CB_LENGTH 256
-		if ((length < E1000_CB_LENGTH) &&
-		   !rx_ring->rx_skb_top &&
-		   /* or maybe (status & E1000_RXD_STAT_EOP) && */
-		   !multi_descriptor) {
+		if (length < E1000_CB_LENGTH) {
 			struct sk_buff *new_skb =
 			    dev_alloc_skb(length + NET_IP_ALIGN);
 			if (new_skb) {
@@ -3729,7 +3701,8 @@ e1000_clean_rx_irq(struct e1000_adapter 
 				skb = new_skb;
 				skb_put(skb, length);
 			}
-		}
+		} else
+			skb_put(skb, length);
 
 		/* end copybreak code */
 

^ permalink raw reply related

* [PATCH] IrDA: TOIM3232 dongle support
From: Samuel Ortiz @ 2006-03-01 22:36 UTC (permalink / raw)
  To: ext David S. Miller
  Cc: IrDA users, netdev-u79uwXL29TY76Z2rM5mHXA, Jean Tourrilhes

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=unknown-8bit, Size: 16265 bytes --]

Hi David,

Here goes a patch for supporting TOIM3232 based serial IrDA dongles.
The code is based on the tekram dongle code.

It's been tested with a TOIM3232 based IRWave 320S dongle. It may work
for TOIM4232 dongles, although it's not been tested.

Cheers,
Samuel.

Signed-off-by: David Basden <davidb-irda-Q/PxBS77Xz0@public.gmane.org>
Signed-off-by: Samuel Ortiz <samuel.ortiz-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>

diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 7a08134..1b0f0d0 100644
--- a/drivers/net/irda/Kconfig
+++ a/drivers/net/irda/Kconfig
@@ -62,10 +62,18 @@ config TEKRAM_DONGLE
 	  attaches to the normal 9-pin serial port connector, and can
 	  currently only be used by IrTTY.  To activate support for Tekram
 	  dongles you will have to start irattach like this:
 	  "irattach -d tekram".
 
+config TOIM3232_DONGLE
+	tristate "TOIM3232 IrDa dongle"
+	depends on DONGLE && IRDA
+	help
+	  Say Y here if you want to build support for the Vishay/Temic
+	  TOIM3232 and TOIM4232 based dongles.
+	  To compile it as a module, choose M here.
+
 config LITELINK_DONGLE
 	tristate "Parallax LiteLink dongle"
 	depends on DONGLE && IRDA
 	help
 	  Say Y here if you want to build support for the Parallax Litelink

diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 72cbfdc..27ab75f 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -41,8 +41,9 @@ obj-$(CONFIG_LITELINK_DONGLE)	+= litelin
 obj-$(CONFIG_GIRBIL_DONGLE)	+= girbil-sir.o
 obj-$(CONFIG_OLD_BELKIN_DONGLE)	+= old_belkin-sir.o
 obj-$(CONFIG_MCP2120_DONGLE)	+= mcp2120-sir.o
 obj-$(CONFIG_ACT200L_DONGLE)	+= act200l-sir.o
 obj-$(CONFIG_MA600_DONGLE)	+= ma600-sir.o
+obj-$(CONFIG_TOIM3232_DONGLE)	+= toim3232-sir.o
 
 # The SIR helper module
 sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o

diff --git a/drivers/net/irda/toim3232-sir.c b/drivers/net/irda/toim3232-sir.c
new file mode 100644
index 0000000..b8e275c
--- a/drivers/net/irda/toim3232-sir.c
+++ b/drivers/net/irda/toim3232-sir.c
@@ -0,0 +1,375 @@
+/*********************************************************************
+ *                
+ * Filename:      toim3232-sir.c
+ * Version:       1.0
+ * Description:   Implementation of dongles based on the Vishay/Temic
+ * 		  TOIM3232 SIR Endec chipset. Currently only the
+ * 		  IRWave IR320ST-2 is tested, although it should work
+ * 		  with any TOIM3232 or TOIM4232 chipset based RS232
+ * 		  dongle with minimal modification.
+ * 		  Based heavily on the Tekram driver (tekram.c), 
+ * 		  with thanks to Dag Brattli and Martin Diehl.
+ * Status:        Experimental.
+ * Author:        David Basden <davidb-irda-Q/PxBS77Xz0@public.gmane.org>
+ * Created at:    Thu Feb 09 23:47:32 2006
+ * 
+ *     Copyright (c) 2006 David Basden.
+ *     Copyright (c) 1998-1999 Dag Brattli,
+ *     Copyright (c) 2002 Martin Diehl,
+ *     All Rights Reserved.
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+/*
+ * This driver has currently only been tested on the IRWave IR320ST-2
+ * 
+ * PROTOCOL:
+ *
+ * The protocol for talking to the TOIM3232 is quite easy, and is
+ * designed to interface with RS232 with only level convertors. The
+ * BR/~D line on the chip is brought high to signal 'command mode',
+ * where a command byte is sent to select the baudrate of the RS232
+ * interface and the pulse length of the IRDA output. When BR/~D
+ * is brought low, the dongle then changes to the selected baudrate,
+ * and the RS232 interface is used for data until BR/~D is brought
+ * high again. The initial speed for the TOIMx323 after RESET is 
+ * 9600 baud.  The baudrate for command-mode is the last selected
+ * baud-rate, or 9600 after a RESET.
+ *
+ * The  dongle I have (below) adds some extra hardware on the front end,
+ * but this is mostly directed towards pariasitic power from the RS232
+ * line rather than changing very much about how to communicate with
+ * the TOIM3232.
+ *
+ * The protocol to talk to the TOIM4232 chipset seems to be almost
+ * identical to the TOIM3232 (and the 4232 datasheet is more detailed)
+ * so this code will probably work on that as well, although I haven't
+ * tested it on that hardware.
+ *
+ * Target dongle variations that might be common:
+ *
+ * DTR and RTS function: 
+ *   The data sheet for the 4232 has a sample implementation that hooks the
+ *   DTR and RTS lines to the RESET and BaudRate/~Data lines of the
+ *   chip (through line-converters). Given both DTR and RTS would have to
+ *   be held low in normal operation, and the TOIMx232 requires +5V to
+ *   signal ground, most dongle designers would almost certainly choose
+ *   an implementation that kept at least one of DTR or RTS high in 
+ *   normal operation to provide power to the dongle, but will likely
+ *   vary between designs.
+ *
+ * User specified command bits:
+ *  There are two user-controllable output lines from the TOIMx232 that
+ *  can be set low or high by setting the appropriate bits in the
+ *  high-nibble of the command byte (when setting speed and pulse length).
+ *  These might be used to switch on and off added hardware or extra
+ *  dongle features.
+ *
+ *
+ * Target hardware: IRWave IR320ST-2
+ *
+ * 	The IRWave IR320ST-2 is a simple dongle based on the Vishay/Temic
+ * 	TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transciever.
+ * 	It uses a hex inverter and some discrete components to buffer and
+ * 	line convert the RS232 down to 5V.
+ *
+ * 	The dongle is powered through a voltage regulator, fed by a large
+ * 	capacitor. To switch the dongle on, DTR is brought high to charge 
+ * 	the capacitor and drive the voltage regulator. DTR isn't associated
+ * 	with any control lines on the TOIM3232. Parisitic power is also taken
+ * 	from the RTS, TD and RD lines when brought high, but through resistors. 
+ * 	When DTR is low, the circuit might lose power even with RTS high.
+ *
+ * 	RTS is inverted and attached to the BR/~D input pin. When RTS
+ * 	is high, BR/~D is low, and the TOIM3232 is in the normal 'data' mode.
+ * 	RTS is brought low, BR/~D is high, and the TOIM3232 is in 'command 
+ * 	mode'.
+ *
+ * 	For some unknown reason, the RESET line isn't actually connected
+ * 	to anything. This means to reset the dongle to get it to a known
+ * 	state (9600 baud) you must drop DTR and RTS low, wait for the power
+ * 	capacitor to discharge, and then bring DTR (and RTS for data mode)
+ * 	high again, and wait for the capacitor to charge, the power supply
+ * 	to stabilise, and the oscillator clock to stabilise. 
+ *
+ * 	Fortunately, if the current baudrate is known, the chipset can
+ * 	easily change speed by entering command mode without having to
+ * 	reset the dongle first.
+ *
+ * 	Major Components:
+ *
+ * 	- Vishay/Temic TOIM3232 SIR Endec to change RS232 pulse timings 
+ * 	  to IRDA pulse timings
+ * 	- 3.6864MHz crystal to drive TOIM3232 clock oscillator
+ * 	- DM74lS04M Inverting Hex line buffer for RS232 input buffering
+ * 	  and level conversion
+ * 	- PJ2951AC 150mA voltage regulator
+ * 	- Vishay/Temic TFDS4500	SIR IRDA front-end transceiver
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h> 
+
+#include <net/irda/irda.h>
+
+#include "sir-dev.h"
+
+MODULE_PARM(toim3232delay, "i");
+MODULE_PARM_DESC(toim3232delay, "toim3232 dongle write complete delay");
+static int toim3232delay = 150;	/* default is 150 ms */
+
+#if 0
+MODULE_PARM(toim3232flipdtr, "i");
+MODULE_PARM_DESC(toim3232flipdtr, "toim3232 dongle invert DTR (Reset)");
+static int toim3232flipdtr = 0;	/* default is DTR high to reset */
+
+MODULE_PARM(toim3232fliptrs, "i");
+MODULE_PARM_DESC(toim3232fliprts, "toim3232 dongle invert RTS (BR/D)");
+static int toim3232fliprts = 0;	/* default is RTS high for baud change */
+#endif
+
+static int toim3232_open(struct sir_dev *);
+static int toim3232_close(struct sir_dev *);
+static int toim3232_change_speed(struct sir_dev *, unsigned);
+static int toim3232_reset(struct sir_dev *);
+
+#define TOIM3232_115200 0x00
+#define TOIM3232_57600  0x01
+#define TOIM3232_38400  0x02
+#define TOIM3232_19200  0x03
+#define TOIM3232_9600   0x06
+#define TOIM3232_2400   0x0A
+
+#define TOIM3232_PW     0x10 /* Pulse select bit */
+
+static struct dongle_driver toim3232 = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "Vishay TOIM3232",
+	.type		= IRDA_TOIM3232_DONGLE,
+	.open		= toim3232_open,
+	.close		= toim3232_close,
+	.reset		= toim3232_reset,
+	.set_speed	= toim3232_change_speed,
+};
+
+static int __init toim3232_sir_init(void)
+{
+	if (toim3232delay < 1  ||  toim3232delay > 500)
+		toim3232delay = 200;
+	IRDA_DEBUG(1, "%s - using %d ms delay\n",
+		toim3232.driver_name, toim3232delay);
+	return irda_register_dongle(&toim3232);
+}
+
+static void __exit toim3232_sir_cleanup(void)
+{
+	irda_unregister_dongle(&toim3232);
+}
+
+static int toim3232_open(struct sir_dev *dev)
+{
+	struct qos_info *qos = &dev->qos;
+
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
+
+	/* Pull the lines high to start with. 
+	 *
+	 * For the IR320ST-2, we need to charge the main supply capacitor to
+	 * switch the device on. We keep DTR high throughout to do this.
+	 * When RTS, TD and RD are high, they will also trickle-charge the
+	 * cap. RTS is high for data transmission, and low for baud rate select.
+	 * 	-- DGB
+	 */
+	sirdev_set_dtr_rts(dev, TRUE, TRUE);
+
+	/* The TOI3232 supports many speeds between 1200bps and 115000bps.
+	 * We really only care about those supported by the IRDA spec, but
+	 * 38400 seems to be implemented in many places */
+	qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+
+	/* From the tekram driver. Not sure what a reasonable value is -- DGB */
+	qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
+	irda_qos_bits_to_value(qos);
+
+	/* irda thread waits 50 msec for power settling */
+
+	return 0;
+}
+
+static int toim3232_close(struct sir_dev *dev)
+{
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
+
+	/* Power off dongle */
+	sirdev_set_dtr_rts(dev, FALSE, FALSE);
+
+	return 0;
+}
+
+/*
+ * Function toim3232change_speed (dev, state, speed)
+ *
+ *    Set the speed for the TOIM3232 based dongle. Warning, this 
+ *    function must be called with a process context!
+ *
+ *    Algorithm
+ *    1. keep DTR high but clear RTS to bring into baud programming mode
+ *    2. wait at least 7us to enter programming mode 
+ *    3. send control word to set baud rate and timing
+ *    4. wait at least 1us
+ *    5. bring RTS high to enter DATA mode (RS232 is passed through to transceiver)
+ *    6. should take effect immediately (although probably worth waiting)
+ */
+
+#define TOIM3232_STATE_WAIT_SPEED	(SIRDEV_STATE_DONGLE_SPEED + 1)
+
+static int toim3232_change_speed(struct sir_dev *dev, unsigned speed)
+{
+	unsigned state = dev->fsm.substate;
+	unsigned delay = 0;
+	u8 byte;
+	static int ret = 0;
+	
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
+
+	switch(state) {
+	case SIRDEV_STATE_DONGLE_SPEED:
+
+		/* Figure out what we are going to send as a control byte */
+		switch (speed) {
+		case 2400:
+			byte = TOIM3232_PW|TOIM3232_2400;
+			break;
+		default:
+			speed = 9600;
+			ret = -EINVAL;
+			/* fall thru */
+		case 9600:
+			byte = TOIM3232_PW|TOIM3232_9600;
+			break;
+		case 19200:
+			byte = TOIM3232_PW|TOIM3232_19200;
+			break;
+		case 38400:
+			byte = TOIM3232_PW|TOIM3232_38400;
+			break;
+		case 57600:
+			byte = TOIM3232_PW|TOIM3232_57600;
+			break;
+		case 115200:
+			byte = TOIM3232_115200;
+			break;
+		}
+
+		/* Set DTR, Clear RTS: Go into baud programming mode */
+		sirdev_set_dtr_rts(dev, TRUE, FALSE);
+	
+		/* Wait at least 7us */
+		udelay(14);
+
+		/* Write control byte */
+		sirdev_raw_write(dev, &byte, 1);
+		
+		dev->speed = speed;
+
+		state = TOIM3232_STATE_WAIT_SPEED;
+		delay = toim3232delay;
+		break;
+
+	case TOIM3232_STATE_WAIT_SPEED:
+		/* Have transmitted control byte * Wait for 'at least 1us' */
+		udelay(14);
+
+		/* Set DTR, Set RTS: Go into normal data mode */
+		sirdev_set_dtr_rts(dev, TRUE, TRUE);
+
+		/* Wait (TODO: check this is needed) */
+		udelay(50);
+		break;
+
+	default:
+		printk(KERN_ERR "%s - undefined state %d\n", __FUNCTION__, state);
+		ret = -EINVAL;
+		break;
+	}
+
+	dev->fsm.substate = state;
+	return (delay > 0) ? delay : ret;
+}
+
+/*
+ * Function toim3232reset (driver)
+ *
+ *      This function resets the toim3232 dongle. Warning, this function 
+ *      must be called with a process context!! 
+ *
+ * What we should do is:
+ * 	0. Pull RESET high 
+ * 	1. Wait for at least 7us
+ * 	2. Pull RESET low
+ * 	3. Wait for at least 7us
+ * 	4. Pull BR/~D high
+ * 	5. Wait for at least 7us
+ * 	6. Send control byte to set baud rate
+ * 	7. Wait at least 1us after stop bit
+ * 	8. Pull BR/~D low
+ * 	9. Should then be in data mode
+ *
+ * Because the IR320ST-2 doesn't have the RESET line connected for some reason,
+ * we'll have to do something else.
+ *
+ * The default speed after a RESET is 9600, so lets try just bringing it up in 
+ * data mode after switching it off, waiting for the supply capacitor to
+ * discharge, and then switch it back on. This isn't actually pulling RESET
+ * high, but it seems to have the same effect.
+ *
+ * This behaviour will probably work on dongles that have the RESET line connected,
+ * but if not, add a flag for the IR320ST-2, and implment the above-listed proper
+ * behaviour.
+ *
+ * RTS is inverted and then fed to BR/~D, so to put it in programming mode, we
+ * need to have pull RTS low
+ */
+
+static int toim3232_reset(struct sir_dev *dev)
+{
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
+
+	/* Switch off both DTR and RTS to switch off dongle */
+	sirdev_set_dtr_rts(dev, FALSE, FALSE); 
+
+	/* Should sleep a while. This might be evil doing it this way.*/
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(msecs_to_jiffies(50));
+
+	/* Set DTR, Set RTS (data mode) */
+	sirdev_set_dtr_rts(dev, TRUE, TRUE);
+	
+	/* Wait at least 10 ms for power to stabilize again */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(msecs_to_jiffies(10));
+
+	/* Speed should now be 9600 */
+	dev->speed = 9600;
+
+	return 0;
+}
+
+MODULE_AUTHOR("David Basden <davidb-linux-Q/PxBS77Xz0@public.gmane.org>");
+MODULE_DESCRIPTION("Vishay/Temic TOIM3232 based dongle driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("irda-dongle-12"); /* IRDA_TOIM3232_DONGLE */
+		
+module_init(toim3232_sir_init);
+module_exit(toim3232_sir_cleanup);

diff --git a/include/linux/irda.h b/include/linux/irda.h
index 95dee17..09d8f10 100644
--- a/include/linux/irda.h
+++ b/include/linux/irda.h
@@ -74,10 +74,11 @@ typedef enum {
 	IRDA_OLD_BELKIN_DONGLE   = 7,
 	IRDA_EP7211_IR           = 8,
 	IRDA_MCP2120_DONGLE      = 9,
 	IRDA_ACT200L_DONGLE      = 10,
 	IRDA_MA600_DONGLE        = 11,
+	IRDA_TOIM3232_DONGLE     = 12,
 } IRDA_DONGLE;
 
 /* Protocol types to be used for SOCK_DGRAM */
 enum {
 	IRDAPROTO_UNITDATA = 0,


-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid\x110944&bid$1720&dat\x121642

^ permalink raw reply related

* [PATCH] wireless.git: update acxsm to 0.4.7
From: Denis Vlasenko @ 2006-03-01 13:58 UTC (permalink / raw)
  To: acx100-devel
  Cc: John W. Linville, Carlos Martín, netdev, Christoph Hellwig
In-Reply-To: <20060228013415.GD26559@tuxdriver.com>

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

On Tuesday 28 February 2006 03:34, John W. Linville wrote:
> On Mon, Feb 27, 2006 at 11:44:38AM +0100, Carlos Martín wrote:
> > On Monday 27 February 2006 11:20, Denis Vlasenko wrote:
> > > > Comments are welcome and I'll split the patch if needed.
> 
> Denis are you applying this patch to your tree?  If so, I'll rely on
> you to push it to me when you are ready.
> 
> If not, then I will need Carlos to generate the diffs so that they
> can be applied to the top of the tree with -p1.
> 
> 	http://linux.yyz.us/patch-format.html

Changelog:

[20060301] 0.4.7
* Carlos Martin <carlos@cmartin.tk>
  - splitted monolithic module into acx-common + acx-pci + acx-usb
    modules

[20060212] 0.4.6
* Carlos Martin <carlos@cmartin.tk>
  - Fix breakage of "Get rid of circular list of adev's"
  - Remove .owner = THIS_MODULE

[20060209] 0.4.5
* Get rid of circular list of adev's

[20060208]
* Change the acx_ioctl_{get,set}_encode functions to use
  the 80211 stack in the kernel, so they become mere wrappers.

[20060206]
* Register driver device ids to usb device table

[20060205] 0.4.4
* Andreas Mohr <andi@rhlx01.fht-esslingen.de>
  - implement much more flexible firmware statistics parsing
    (for /proc/driver/acx_wlanX_diag)
    This has the nice effect that we now get output for both the older
    TNETW1100 USB and TNETW1450.
    Since firmware statistics information has non-stable layout depending on
    firmware version, please report if you suspect any parsing mismatch!
    This improved version now uses 2kB more driver space, unfortunately.
  - use "% 8" modulo instead of more complicated "% 5" calculation

Signed-off-by: Denis Vlasenko <vda@ilport.com.ua>
--
vda

[-- Attachment #2: acx_cmn.patch --]
[-- Type: text/x-diff, Size: 71712 bytes --]

diff -urpN wireless-2.6.git/drivers/net/wireless/Makefile wireless-2.6.git.acx/drivers/net/wireless/Makefile
--- wireless-2.6.git/drivers/net/wireless/Makefile	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/Makefile	Wed Mar  1 12:01:19 2006
@@ -37,7 +37,8 @@ obj-$(CONFIG_PRISM54_USB)	+= prism54usb/
 
 obj-$(CONFIG_HOSTAP)		+= hostap/
 obj-$(CONFIG_BCM43XX)		+= bcm43xx/
-obj-$(CONFIG_ACX)		+= tiacx/
+obj-$(CONFIG_ACX_PCI)		+= tiacx/
+obj-$(CONFIG_ACX_USB)		+= tiacx/
 
 # 16-bit wireless PCMCIA client drivers
 obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/Changelog wireless-2.6.git.acx/drivers/net/wireless/tiacx/Changelog
--- wireless-2.6.git/drivers/net/wireless/tiacx/Changelog	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/Changelog	Wed Mar  1 15:43:45 2006
@@ -70,6 +70,37 @@ TODO: from Efthym <efthym@gmx.net>:
 13:13:32 wlan0: tx error 0x20, buf 05!
 13:13:32 wlan0: tx error 0x20, buf 06!
 
+[20060301] 0.4.7
+* Carlos Martin <carlos@cmartin.tk>
+  - splitted monolithic module into acx-common + acx-pci + acx-usb
+    modules
+
+[20060212] 0.4.6
+* Carlos Martin <carlos@cmartin.tk>
+  - Fix breakage of "Get rid of circular list of adev's"
+  - Remove .owner = THIS_MODULE
+
+[20060209] 0.4.5
+* Get rid of circular list of adev's
+
+[20060208]
+* Change the acx_ioctl_{get,set}_encode functions to use
+  the 80211 stack in the kernel, so they become mere wrappers.
+
+[20060206]
+* Register driver device ids to usb device table
+
+[20060205] 0.4.4
+* Andreas Mohr <andi@rhlx01.fht-esslingen.de>
+  - implement much more flexible firmware statistics parsing
+    (for /proc/driver/acx_wlanX_diag)
+    This has the nice effect that we now get output for both the older
+    TNETW1100 USB and TNETW1450.
+    Since firmware statistics information has non-stable layout depending on
+    firmware version, please report if you suspect any parsing mismatch!
+    This improved version now uses 2kB more driver space, unfortunately.
+  - use "% 8" modulo instead of more complicated "% 5" calculation
+
 [20060203] 0.4.3
 * merge from acx 0.3.32
 
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/Kconfig wireless-2.6.git.acx/drivers/net/wireless/tiacx/Kconfig
--- wireless-2.6.git/drivers/net/wireless/tiacx/Kconfig	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/Kconfig	Wed Mar  1 12:05:04 2006
@@ -1,20 +1,14 @@
-config ACX
-	tristate
+config ACX_PCI
+	tristate "TI acx100/acx111 802.11b/g PCI"
+	depends on NET_RADIO && EXPERIMENTAL && PCI
 	select FW_LOADER
 	select IEEE80211
 	select IEEE80211_SOFTMAC
-
-config ACX_PCI
-	tristate "TI acx100/acx111 802.11b/g wireless PCI chipsets"
-	depends on NET_RADIO && EXPERIMENTAL && PCI && (USB || ACX_USB=n)
-	select ACX
-	select ACX_PCI_BOOL
 	---help---
-	Include support for PCI and CardBus 802.11b/g wireless cards
-	based on Texas Instruments acx100 and acx111 chipsets.
+	A driver for 802.11b/g wireless cards based on
+	Texas Instruments acx100 and acx111 chipsets.
 
-	This driver supports Host AP mode that allows
-	your computer to act as an IEEE 802.11 access point.
+	This is the PCI code.
 
 	acx chipsets need their firmware loaded at startup.
 	You will need to provide a firmware image via hotplug.
@@ -39,20 +33,20 @@ config ACX_PCI
 	Firmware files are not covered by GPL and are not distributed
 	with this driver for legal reasons.
 
-config ACX_PCI_BOOL
-	bool
+	Texas Instruments did not take part in development of this driver
+	in any way, shape or form.
 
 config ACX_USB
-	tristate "TI acx100/acx111 802.11b/g USB wireless chipsets"
+	tristate "TI acx100/acx111 802.11b/g USB"
 	depends on NET_RADIO && EXPERIMENTAL && USB
-	select ACX
-	select ACX_USB_BOOL
+	select FW_LOADER
+	select IEEE80211
+	select IEEE80211_SOFTMAC
 	---help---
-	Include support for USB 802.11b/g wireless cards
-	based on Texas Instruments acx100 and acx111 chipsets.
+	A driver for 802.11b/g wireless cards based on
+	Texas Instruments acx100 and acx111 chipsets.
 
-	This driver supports Host AP mode that allows
-	your computer to act as an IEEE 802.11 access point.
+	This is the USB code.
 
 	There is only one currently known device in this category,
 	D-Link DWL-120+, but newer devices seem to be on the horizon.
@@ -66,5 +60,6 @@ config ACX_USB
 	Firmware files are not covered by GPL and are not distributed
 	with this driver for legal reasons.
 
-config ACX_USB_BOOL
-	bool
+	Texas Instruments did not take part in development of this driver
+	in any way, shape or form.
+
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/Makefile wireless-2.6.git.acx/drivers/net/wireless/tiacx/Makefile
--- wireless-2.6.git/drivers/net/wireless/tiacx/Makefile	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/Makefile	Wed Mar  1 12:05:04 2006
@@ -1,6 +1,6 @@
-obj-$(CONFIG_ACX) += acx.o
+acx-common-y := wlan.o ioctl.o common.o
+acx-usb-y := usb.o
+acx-pci-y := pci.o
 
-acx-obj-$(CONFIG_ACX_PCI_BOOL) += pci.o
-acx-obj-$(CONFIG_ACX_USB_BOOL) += usb.o
-
-acx-objs := wlan.o ioctl.o common.o $(acx-obj-y)
+obj-$(CONFIG_ACX_PCI) += acx-common.o acx-pci.o
+obj-$(CONFIG_ACX_USB) += acx-common.o acx-usb.o
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/README wireless-2.6.git.acx/drivers/net/wireless/tiacx/README
--- wireless-2.6.git/drivers/net/wireless/tiacx/README	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/README	Wed Mar  1 12:27:48 2006
@@ -1,21 +1,16 @@
-*** Not run tested. Almost certainly won't work. Lots of things are TODO. ***
+*** Barely works. Lots of things are TODO. ***
 
 This tarball contains a port of acx driver to ieee80211softmac
 stack. Broadcom 43xx driver was used as an example.
 See http://bcm43xx.berlios.de/,
 ftp://ftp.berlios.de/pub/bcm43xx/snapshots/
 
-Latest softmac source is in softmac-snapshot/ and net/
-is a symlink to softmac-snapshot/include/net/.
-softmac-snapshot/ is to be replaced regularly with newer
-snapshots from http://softmac.sipsolutions.net/SoftMAC.
-
 grep for '//SM' to see the code added to standalone acx driver code.
 
 Contact:
 netdev@vger.kernel.org
 acx100-devel@lists.sourceforge.net
-softmac-dev@sipsolutions.net 
+softmac-dev@sipsolutions.net
 
 Bug reports:
 
@@ -45,4 +40,22 @@ radio module). For example, my firmware 
 Alternatively, I may remove it and use pair of files 'tiacx111' and
 'tiacx111r16' instead.
 USB driver:
-image is named 'tiacx100usb'
+image is named 'tiacxNNNusbcMM'
+
+Build instructions:
+
+You need to have git and cogito installed.
+
+# Get initial wireless-2.6.git tree (large download - >300MB)
+cg-clone rsync://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git wireless-2.6.git
+cd wireless-2.6.git
+# Get a branch
+cg-branch-add r-softmac 'rsync://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git#softmac'
+cg-fetch r-softmac
+# Switch to it (make it current)
+git-checkout r-softmac
+# Pull updates from remote master tree
+cg-update r-softmac
+
+You will have a complete Linux kernel in wireless-2.6.git/.
+Replace drivers/net/wireless/tiacx/* by files from this tarball.
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/acx_config.h wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_config.h
--- wireless-2.6.git/drivers/net/wireless/tiacx/acx_config.h	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_config.h	Wed Mar  1 15:43:59 2006
@@ -1,4 +1,4 @@
-#define ACX_RELEASE "v0.4.3"
+#define ACX_RELEASE "v0.4.7"
 
 /* set to 0 if you don't want any debugging code to be compiled in */
 /* set to 1 if you want some debugging */
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/acx_func.h wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_func.h
--- wireless-2.6.git/drivers/net/wireless/tiacx/acx_func.h	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_func.h	Wed Mar  1 12:31:08 2006
@@ -66,27 +66,27 @@
 */
 #if ACX_DEBUG > 1
 
-void log_fn_enter(const char *funcname);
-void log_fn_exit(const char *funcname);
-void log_fn_exit_v(const char *funcname, int v);
+void acx_log_fn_enter(const char *funcname);
+void acx_log_fn_exit(const char *funcname);
+void acx_log_fn_exit_v(const char *funcname, int v);
 
 #define FN_ENTER \
 	do { \
 		if (unlikely(acx_debug & L_FUNC)) { \
-			log_fn_enter(__func__); \
+			acx_log_fn_enter(__func__); \
 		} \
 	} while (0)
 
 #define FN_EXIT1(v) \
 	do { \
 		if (unlikely(acx_debug & L_FUNC)) { \
-			log_fn_exit_v(__func__, v); \
+			acx_log_fn_exit_v(__func__, v); \
 		} \
 	} while (0)
 #define FN_EXIT0 \
 	do { \
 		if (unlikely(acx_debug & L_FUNC)) { \
-			log_fn_exit(__func__); \
+			acx_log_fn_exit(__func__); \
 		} \
 	} while (0)
 
@@ -257,7 +257,7 @@ has_only_one_bit(u16 v)
 **		but may be run under lock
 **
 ** A small number of local helpers do not have acx_[eisl]_ prefix.
-** They are always close to caller and are to be revieved locally.
+** They are always close to caller and are to be reviewed locally.
 **
 ** Theory of operation:
 **
@@ -417,44 +417,29 @@ void acx_set_status(acx_device_t *adev, 
 #if ACX_DEBUG
 
 /* We want to log cmd names */
-int acxpci_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
-int acxusb_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
-static inline int
-acx_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr)
-{
-	if (IS_PCI(adev))
-		return acxpci_s_issue_cmd_timeo_debug(adev, cmd, param, len, timeout, cmdstr);
-	return acxusb_s_issue_cmd_timeo_debug(adev, cmd, param, len, timeout, cmdstr);
-}
-#define acx_s_issue_cmd(adev,cmd,param,len) \
-	acx_s_issue_cmd_timeo_debug(adev,cmd,param,len,ACX_CMD_TIMEOUT_DEFAULT,#cmd)
-#define acx_s_issue_cmd_timeo(adev,cmd,param,len,timeo) \
-	acx_s_issue_cmd_timeo_debug(adev,cmd,param,len,timeo,#cmd)
+
+#define acx_s_issue_cmd(adev, cmd, param, len) \
+	(adev)->ops.issue_cmd(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT, #cmd)
+
+#define acx_s_issue_cmd_timeo(adev,cmd,param,len, timeout)			\
+	(adev)->ops.issue_cmd(adev, cmd, param, len, timeout, #cmd)
+
 int acx_s_configure_debug(acx_device_t *adev, void *pdr, int type, const char* str);
 #define acx_s_configure(adev,pdr,type) \
 	acx_s_configure_debug(adev,pdr,type,#type)
+
 int acx_s_interrogate_debug(acx_device_t *adev, void *pdr, int type, const char* str);
 #define acx_s_interrogate(adev,pdr,type) \
 	acx_s_interrogate_debug(adev,pdr,type,#type)
 
 #else
 
-int acxpci_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout);
-int acxusb_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout);
-static inline int
-acx_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd,	void *param, unsigned len, unsigned timeout)
-{
-	if (IS_PCI(adev))
-		return acxpci_s_issue_cmd_timeo(adev, cmd, param, len, timeout);
-	return acxusb_s_issue_cmd_timeo(adev, cmd, param, len, timeout);
-}
-static inline int
-acx_s_issue_cmd(acx_device_t *adev, unsigned cmd, void *param, unsigned len)
-{
-	if (IS_PCI(adev))
-		return acxpci_s_issue_cmd_timeo(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
-	return acxusb_s_issue_cmd_timeo(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT);
-}
+#define acx_s_issue_cmd(adev, cmd, param, len) \
+	(adev)->ops.issue_cmd(adev, cmd, param, len, ACX_CMD_TIMEOUT_DEFAULT)
+
+#define acx_s_issue_cmd_timeo(adev, cmd, param, len, timeout)			\
+	(adev)->ops.issue_cmd(adev, cmd, param, len, timeout)
+
 int acx_s_configure(acx_device_t *adev, void *pdr, int type);
 int acx_s_interrogate(acx_device_t *adev, void *pdr, int type);
 
@@ -503,64 +488,23 @@ int acxpci_s_upload_radio(acx_device_t *
 /***********************************************************************
 ** Unsorted yet :)
 */
-int acxpci_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf);
-int acxusb_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf);
-static inline int
-acx_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
-{
-	if (IS_PCI(adev))
-		return acxpci_s_read_phy_reg(adev, reg, charbuf);
-	return acxusb_s_read_phy_reg(adev, reg, charbuf);
-}
+#define acx_s_read_phy_reg(adev, reg, charbuf) \
+	(adev)->ops.read_phy_reg(adev, reg, charbuf)
 
-int acxpci_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value);
-int acxusb_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value);
-static inline int
-acx_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
-{
-	if (IS_PCI(adev))
-		return acxpci_s_write_phy_reg(adev, reg, value);
-	return acxusb_s_write_phy_reg(adev, reg, value);
-}
+#define acx_s_write_phy_reg(adev, reg, value) \
+	(adev)->ops.write_phy_reg(adev, reg, value)
 
-tx_t* acxpci_l_alloc_tx(acx_device_t *adev);
-tx_t* acxusb_l_alloc_tx(acx_device_t *adev);
-static inline tx_t*
-acx_l_alloc_tx(acx_device_t *adev)
-{
-	if (IS_PCI(adev))
-		return acxpci_l_alloc_tx(adev);
-	return acxusb_l_alloc_tx(adev);
-}
+#define acx_l_alloc_tx(adev) \
+	(adev)->ops.alloc_tx(adev)
 
-void acxusb_l_dealloc_tx(tx_t *tx_opaque);
-static inline void
-acx_l_dealloc_tx(acx_device_t *adev, tx_t *tx_opaque)
-{
-	if (IS_USB(adev))
-		acxusb_l_dealloc_tx(tx_opaque);
-}
+#define acx_l_dealloc_tx(adev, tx_opaque) \
+	(adev)->ops.dealloc_tx(tx_opaque)
 
-void* acxpci_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque);
-void* acxusb_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque);
-static inline void*
-acx_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque)
-{
-	if (IS_PCI(adev))
-		return acxpci_l_get_txbuf(adev, tx_opaque);
-	return acxusb_l_get_txbuf(adev, tx_opaque);
-}
+#define acx_l_get_txbuf(adev, tx_opaque) \
+	(adev)->ops.get_txbuf(adev, tx_opaque)
 
-void acxpci_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len);
-void acxusb_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len);
-static inline void
-acx_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len)
-{
-	if (IS_PCI(adev))
-		acxpci_l_tx_data(adev, tx_opaque, len);
-	else
-		acxusb_l_tx_data(adev, tx_opaque, len);
-}
+#define acx_l_tx_data(adev, tx_opaque, len) \
+	(adev)->ops.tx_data(adev, tx_opaque, len)
 
 static inline wlan_hdr_t*
 acx_get_wlan_hdr(acx_device_t *adev, const rxbuffer_t *rxbuf)
@@ -637,6 +581,9 @@ void acx_display_hardware_details(acx_de
 int acx_e_change_mtu(struct net_device *ndev, int mtu);
 struct net_device_stats* acx_e_get_stats(struct net_device *ndev);
 struct iw_statistics* acx_e_get_wireless_stats(struct net_device *ndev);
+
+int acx100_s_create_dma_regions(acx_device_t *);
+int acx111_s_create_dma_regions(acx_device_t *);
 
 int __init acxpci_e_init_module(void);
 int __init acxusb_e_init_module(void);
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/acx_struct.h wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_struct.h
--- wireless-2.6.git/drivers/net/wireless/tiacx/acx_struct.h	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_struct.h	Wed Mar  1 12:05:04 2006
@@ -87,6 +87,31 @@ enum { acx_debug = 0 };
 #define SCHEDULE_WORK schedule_work
 #define FLUSH_SCHEDULED_WORK flush_scheduled_work
 
+/***********************************************************************
+** Chip-specific functions get set here.
+*/
+
+struct acx_ops {
+	int (*create_dma_regions)(acx_device_t *);
+	void (*delete_dma_regions)(acx_device_t *);
+
+#if ACX_DEBUG
+	int (*issue_cmd)(acx_device_t *adev, unsigned cmd, void *param,
+			 unsigned len, unsigned cmd_timeout, const char *cmdstr);
+#else
+	int (*issue_cmd)(acx_device_t *adev, unsigned cmd, void *param,
+			 unsigned len, unsigned cmd_timeout);
+#endif /* ACX_DEBUG */
+	tx_t* (*alloc_tx)(acx_device_t *adev);
+	void (*dealloc_tx)(tx_t *tx_opaque);
+
+	void* (*get_txbuf)(acx_device_t *adev, tx_t *tx_opaque);
+	void (*tx_data)(acx_device_t *adev, tx_t *tx_opaque, int len);
+
+	int (*write_phy_reg)(acx_device_t *adev, u32 reg, u8 value);
+	int (*read_phy_reg)(acx_device_t *adev, u32 reg, u8 *charbuf);
+};
+
 
 /***********************************************************************
 ** Constants
@@ -105,8 +130,8 @@ enum { acx_debug = 0 };
 #define DEVTYPE_PCI		0
 #define DEVTYPE_USB		1
 
-#if defined(CONFIG_ACX_PCI_BOOL)
- #if !defined(CONFIG_ACX_USB_BOOL)
+#if defined(CONFIG_ACX_PCI)
+ #if !defined(CONFIG_ACX_USB)
   #define IS_PCI(adev)	1
  #else
   #define IS_PCI(adev)	((adev)->dev_type == DEVTYPE_PCI)
@@ -115,8 +140,8 @@ enum { acx_debug = 0 };
  #define IS_PCI(adev)	0
 #endif
 
-#if defined(CONFIG_ACX_USB_BOOL)
- #if !defined(CONFIG_ACX_PCI_BOOL)
+#if defined(CONFIG_ACX_USB)
+ #if !defined(CONFIG_ACX_PCI)
   #define IS_USB(adev)	1
  #else
   #define IS_USB(adev)	((adev)->dev_type == DEVTYPE_USB)
@@ -578,21 +603,34 @@ typedef struct rxbuffer {
 
 
 /*--- Firmware statistics ----------------------------------------------------*/
-typedef struct fw_stats {
-	u32	val0x0 ACX_PACKED;		/* hdr; */
+
+/* define a random 100 bytes more to catch firmware versions which
+ * provide a bigger struct */
+#define FW_STATS_FUTURE_EXTENSION	100
+
+typedef struct fw_stats_tx {
 	u32	tx_desc_of ACX_PACKED;
+} fw_stats_tx_t;
+
+typedef struct fw_stats_rx {
 	u32	rx_oom ACX_PACKED;
 	u32	rx_hdr_of ACX_PACKED;
-	u32	rx_hdr_use_next ACX_PACKED;
+	u32	rx_hw_stuck ACX_PACKED; /* old: u32	rx_hdr_use_next */
 	u32	rx_dropped_frame ACX_PACKED;
 	u32	rx_frame_ptr_err ACX_PACKED;
 	u32	rx_xfr_hint_trig ACX_PACKED;
+	u32	rx_aci_events ACX_PACKED; /* later versions only */
+	u32	rx_aci_resets ACX_PACKED; /* later versions only */
+} fw_stats_rx_t;
 
+typedef struct fw_stats_dma {
 	u32	rx_dma_req ACX_PACKED;
 	u32	rx_dma_err ACX_PACKED;
 	u32	tx_dma_req ACX_PACKED;
 	u32	tx_dma_err ACX_PACKED;
+} fw_stats_dma_t;
 
+typedef struct fw_stats_irq {
 	u32	cmd_cplt ACX_PACKED;
 	u32	fiq ACX_PACKED;
 	u32	rx_hdrs ACX_PACKED;
@@ -600,23 +638,79 @@ typedef struct fw_stats {
 	u32	rx_mem_of ACX_PACKED;
 	u32	rx_rdys ACX_PACKED;
 	u32	irqs ACX_PACKED;
-	u32	acx_trans_procs ACX_PACKED;
+	u32	tx_procs ACX_PACKED;
 	u32	decrypt_done ACX_PACKED;
 	u32	dma_0_done ACX_PACKED;
 	u32	dma_1_done ACX_PACKED;
 	u32	tx_exch_complet ACX_PACKED;
 	u32	commands ACX_PACKED;
-	u32	acx_rx_procs ACX_PACKED;
+	u32	rx_procs ACX_PACKED;
 	u32	hw_pm_mode_changes ACX_PACKED;
 	u32	host_acks ACX_PACKED;
 	u32	pci_pm ACX_PACKED;
 	u32	acm_wakeups ACX_PACKED;
+} fw_stats_irq_t;
 
+typedef struct fw_stats_wep {
 	u32	wep_key_count ACX_PACKED;
 	u32	wep_default_key_count ACX_PACKED;
 	u32	dot11_def_key_mib ACX_PACKED;
 	u32	wep_key_not_found ACX_PACKED;
 	u32	wep_decrypt_fail ACX_PACKED;
+	u32	wep_pkt_decrypt ACX_PACKED;
+	u32	wep_decrypt_irqs ACX_PACKED;
+} fw_stats_wep_t;
+
+typedef struct fw_stats_pwr {
+	u32	tx_start_ctr ACX_PACKED;
+	u32	no_ps_tx_too_short ACX_PACKED;
+	u32	rx_start_ctr ACX_PACKED;
+	u32	no_ps_rx_too_short ACX_PACKED;
+	u32	lppd_started ACX_PACKED;
+	u32	no_lppd_too_noisy ACX_PACKED;
+	u32	no_lppd_too_short ACX_PACKED;
+	u32	no_lppd_matching_frame ACX_PACKED;
+} fw_stats_pwr_t;
+
+typedef struct fw_stats_mic {
+	u32 mic_rx_pkts ACX_PACKED;
+	u32 mic_calc_fail ACX_PACKED;
+} fw_stats_mic_t;
+
+typedef struct fw_stats_aes {
+	u32 aes_enc_fail ACX_PACKED;
+	u32 aes_dec_fail ACX_PACKED;
+	u32 aes_enc_pkts ACX_PACKED;
+	u32 aes_dec_pkts ACX_PACKED;
+	u32 aes_enc_irq ACX_PACKED;
+	u32 aes_dec_irq ACX_PACKED;
+} fw_stats_aes_t;
+
+typedef struct fw_stats_event {
+	u32 heartbeat ACX_PACKED;
+	u32 calibration ACX_PACKED;
+	u32 rx_mismatch ACX_PACKED;
+	u32 rx_mem_empty ACX_PACKED;
+	u32 rx_pool ACX_PACKED;
+	u32 oom_late ACX_PACKED;
+	u32 phy_tx_err ACX_PACKED;
+	u32 tx_stuck ACX_PACKED;
+} fw_stats_event_t;
+
+/* mainly for size calculation only */
+typedef struct fw_stats {
+	u16			type;
+	u16			len;
+	fw_stats_tx_t		tx;
+	fw_stats_rx_t		rx;
+	fw_stats_dma_t		dma;
+	fw_stats_irq_t		irq;
+	fw_stats_wep_t		wep;
+	fw_stats_pwr_t		pwr;
+	fw_stats_mic_t		mic;
+	fw_stats_aes_t		aes;
+	fw_stats_event_t	evt;
+	u8			_padding[FW_STATS_FUTURE_EXTENSION];
 } fw_stats_t;
 
 /* Firmware version struct */
@@ -1122,14 +1216,12 @@ struct acx_device {
 	unsigned long		lock_time;
 #endif
 
-	/*** Device chain ***/
-	struct acx_device	*next;		/* link for list of devices */
-
 	/*** Linux network device ***/
 	struct net_device	*ndev;		/* pointer to linux netdevice */
-	struct net_device	*prev_nd;	/* FIXME: We should not chain via our
-						 * private struct acx_device _and_
-						 * the struct net_device */
+
+	/* Chip-specific functions */
+	struct acx_ops		ops;
+
 	/*** Device statistics ***/
 	struct net_device_stats	stats;		/* net device statistics */
 #ifdef WIRELESS_EXT
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/common.c wireless-2.6.git.acx/drivers/net/wireless/tiacx/common.c
--- wireless-2.6.git/drivers/net/wireless/tiacx/common.c	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/common.c	Wed Mar  1 12:31:34 2006
@@ -84,6 +84,7 @@ static int acx_l_transmit_assoc_req(acx_
 */
 #if ACX_DEBUG
 unsigned int acx_debug /* will add __read_mostly later */ = ACX_DEFAULT_MSG;
+EXPORT_SYMBOL_GPL(acx_debug);
 /* parameter is 'debug', corresponding var is acx_debug */
 module_param_named(debug, acx_debug, uint, 0);
 MODULE_PARM_DESC(debug, "Debug level mask (see L_xxx constants)");
@@ -94,7 +95,7 @@ MODULE_LICENSE("Dual MPL/GPL");
 #endif
 /* USB had this: MODULE_AUTHOR("Martin Wawro <martin.wawro AT uni-dortmund.de>"); */
 MODULE_AUTHOR("ACX100 Open Source Driver development team");
-MODULE_DESCRIPTION("Driver for TI ACX1xx based wireless cards (CardBus/PCI/USB)");
+MODULE_DESCRIPTION("Driver for TI ACX1xx based wireless cards (common)");
 
 
 /***********************************************************************
@@ -265,7 +266,7 @@ static const char
 spaces[] = "          " "          "; /* Nx10 spaces */
 
 void
-log_fn_enter(const char *funcname)
+acx_log_fn_enter(const char *funcname)
 {
 	int indent;
 	TIMESTAMP(d);
@@ -282,8 +283,11 @@ log_fn_enter(const char *funcname)
 
 	acx_debug_func_indent += FUNC_INDENT_INCREMENT;
 }
+
+EXPORT_SYMBOL_GPL(acx_log_fn_enter);
+
 void
-log_fn_exit(const char *funcname)
+acx_log_fn_exit(const char *funcname)
 {
 	int indent;
 	TIMESTAMP(d);
@@ -300,8 +304,11 @@ log_fn_exit(const char *funcname)
 		funcname
 	);
 }
+
+EXPORT_SYMBOL_GPL(acx_log_fn_exit);
+
 void
-log_fn_exit_v(const char *funcname, int v)
+acx_log_fn_exit_v(const char *funcname, int v)
 {
 	int indent;
 	TIMESTAMP(d);
@@ -319,6 +326,9 @@ log_fn_exit_v(const char *funcname, int 
 		v
 	);
 }
+
+EXPORT_SYMBOL_GPL(acx_log_fn_exit_v);
+
 #endif /* ACX_DEBUG > 1 */
 
 
@@ -333,6 +343,7 @@ acx_s_msleep(int ms)
 	FN_EXIT0;
 }
 
+EXPORT_SYMBOL_GPL(acx_s_msleep);
 
 /***********************************************************************
 ** Not inlined: it's larger than it seems
@@ -413,6 +424,8 @@ acx_get_packet_type_string(u16 fc)
 	}
 	return str;
 }
+
+EXPORT_SYMBOL_GPL(acx_get_packet_type_string);
 #endif
 
 
@@ -482,6 +495,8 @@ acx_cmd_status_str(unsigned int state)
 			cmd_error_strings[state] : "?";
 }
 
+EXPORT_SYMBOL_GPL(acx_cmd_status_str);
+
 
 /***********************************************************************
 ** get_status_string
@@ -573,6 +588,8 @@ acx_dump_bytes(const void *data, int num
 		printk("%02X\n", *ptr);
 	}
 }
+
+EXPORT_SYMBOL_GPL(acx_dump_bytes);
 #endif
 
 
@@ -660,6 +677,7 @@ acx_s_get_firmware_version(acx_device_t 
 	FN_EXIT0;
 }
 
+EXPORT_SYMBOL_GPL(acx_s_get_firmware_version);
 
 /***********************************************************************
 ** acx_display_hardware_details
@@ -730,6 +748,7 @@ acx_display_hardware_details(acx_device_
 	FN_EXIT0;
 }
 
+EXPORT_SYMBOL_GPL(acx_display_hardware_details);
 
 /***********************************************************************
 */
@@ -748,6 +767,7 @@ acx_e_change_mtu(struct net_device *ndev
 	return 0;
 }
 
+EXPORT_SYMBOL_GPL(acx_e_change_mtu);
 
 /***********************************************************************
 ** acx_e_get_stats, acx_e_get_wireless_stats
@@ -759,6 +779,8 @@ acx_e_get_stats(struct net_device *ndev)
 	return &adev->stats;
 }
 
+EXPORT_SYMBOL_GPL(acx_e_get_stats);
+
 struct iw_statistics*
 acx_e_get_wireless_stats(struct net_device *ndev)
 {
@@ -824,6 +846,7 @@ acx_signal_determine_quality(u8 signal, 
 	return qual;
 }
 
+EXPORT_SYMBOL_GPL(acx_signal_determine_quality);
 
 /***********************************************************************
 ** Interrogate/configure commands
@@ -853,7 +876,7 @@ acx100_ie_len[] = {
 	ACX1xx_IE_RXCONFIG_LEN,
 	0,
 	0,
-	ACX1xx_IE_FIRMWARE_STATISTICS_LEN,
+	sizeof(fw_stats_t)-4,
 	0,
 	ACX1xx_IE_FEATURE_CONFIG_LEN,
 	ACX111_IE_KEY_CHOOSE_LEN,
@@ -930,7 +953,7 @@ acx111_ie_len[] = {
 	ACX1xx_IE_RXCONFIG_LEN,
 	0,
 	0,
-	ACX1xx_IE_FIRMWARE_STATISTICS_LEN,
+	sizeof(fw_stats_t)-4,
 	0,
 	ACX1xx_IE_FEATURE_CONFIG_LEN,
 	ACX111_IE_KEY_CHOOSE_LEN,
@@ -992,12 +1015,11 @@ acx111_ie_len_dot11[] = {
 #if !ACX_DEBUG
 int
 acx_s_configure(acx_device_t *adev, void *pdr, int type)
-{
 #else
 int
 acx_s_configure_debug(acx_device_t *adev, void *pdr, int type, const char* typestr)
-{
 #endif
+{
 	u16 len;
 	int res;
 
@@ -1030,13 +1052,12 @@ acx_s_configure_debug(acx_device_t *adev
 #if !ACX_DEBUG
 int
 acx_s_interrogate(acx_device_t *adev, void *pdr, int type)
-{
 #else
 int
 acx_s_interrogate_debug(acx_device_t *adev, void *pdr, int type,
 		const char* typestr)
-{
 #endif
+{
 	u16 len;
 	int res;
 
@@ -1063,6 +1084,12 @@ acx_s_interrogate_debug(acx_device_t *ad
 	return res;
 }
 
+#if ACX_DEBUG
+EXPORT_SYMBOL_GPL(acx_s_interrogate_debug);
+#else
+EXPORT_SYMBOL_GPL(acx_s_interrogate);
+#endif /* ACX_DEBUG */
+
 #if CMD_DISCOVERY
 void
 great_inquisitor(acx_device_t *adev)
@@ -1150,20 +1177,27 @@ static int
 acx_s_proc_diag_output(char *buf, acx_device_t *adev)
 {
 	char *p = buf;
-	fw_stats_t *fw_stats;
 	unsigned long flags;
+	unsigned int len = 0, partlen;
+	u32 temp1, temp2;
+	u8 *st, *st_end;
+#ifdef __BIG_ENDIAN
+	u8 *st2;
+#endif
+	fw_stats_t *fw_stats;
+	char *part_str = NULL;
+	fw_stats_tx_t *tx = NULL;
+	fw_stats_rx_t *rx = NULL;
+	fw_stats_dma_t *dma = NULL;
+	fw_stats_irq_t *irq = NULL;
+	fw_stats_wep_t *wep = NULL;
+	fw_stats_pwr_t *pwr = NULL;
+	fw_stats_mic_t *mic = NULL;
+	fw_stats_aes_t *aes = NULL;
+	fw_stats_event_t *evt = NULL;
 
 	FN_ENTER;
 
-	/* TODO: may replace kmalloc/memset with kzalloc once
-	 * Linux 2.6.14 is widespread */
-	fw_stats = kmalloc(sizeof(*fw_stats), GFP_KERNEL);
-	if (!fw_stats) {
-		FN_EXIT1(0);
-		return 0;
-	}
-	memset(fw_stats, 0, sizeof(*fw_stats));
-
 	acx_lock(adev, flags);
 
 	if (IS_PCI(adev))
@@ -1207,63 +1241,322 @@ acx_s_proc_diag_output(char *buf, acx_de
 
 	acx_unlock(adev, flags);
 
-	if (OK != acx_s_interrogate(adev, fw_stats, ACX1xx_IE_FIRMWARE_STATISTICS))
-		p += sprintf(p,
-			"\n"
-			"** Firmware **\n"
-			"QUERY FAILED!!\n");
-	else {
-		p += sprintf(p,
-			"\n"
-			"** Firmware **\n"
-			"version \"%s\"\n"
-			"tx_desc_overfl %u, rx_OutOfMem %u, rx_hdr_overfl %u, rx_hdr_use_next %u\n"
-			"rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u, rx_dma_req %u\n"
-			"rx_dma_err %u, tx_dma_req %u, tx_dma_err %u, cmd_cplt %u, fiq %u\n"
-			"rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u, irqs %u\n"
-			"acx_trans_procs %u, decrypt_done %u, dma_0_done %u, dma_1_done %u\n",
-			adev->firmware_version,
-			le32_to_cpu(fw_stats->tx_desc_of),
-			le32_to_cpu(fw_stats->rx_oom),
-			le32_to_cpu(fw_stats->rx_hdr_of),
-			le32_to_cpu(fw_stats->rx_hdr_use_next),
-			le32_to_cpu(fw_stats->rx_dropped_frame),
-			le32_to_cpu(fw_stats->rx_frame_ptr_err),
-			le32_to_cpu(fw_stats->rx_xfr_hint_trig),
-			le32_to_cpu(fw_stats->rx_dma_req),
-			le32_to_cpu(fw_stats->rx_dma_err),
-			le32_to_cpu(fw_stats->tx_dma_req),
-			le32_to_cpu(fw_stats->tx_dma_err),
-			le32_to_cpu(fw_stats->cmd_cplt),
-			le32_to_cpu(fw_stats->fiq),
-			le32_to_cpu(fw_stats->rx_hdrs),
-			le32_to_cpu(fw_stats->rx_cmplt),
-			le32_to_cpu(fw_stats->rx_mem_of),
-			le32_to_cpu(fw_stats->rx_rdys),
-			le32_to_cpu(fw_stats->irqs),
-			le32_to_cpu(fw_stats->acx_trans_procs),
-			le32_to_cpu(fw_stats->decrypt_done),
-			le32_to_cpu(fw_stats->dma_0_done),
-			le32_to_cpu(fw_stats->dma_1_done));
+	p += sprintf(p,
+		"\n"
+		"** Firmware **\n"
+		"NOTE: version dependent statistics layout, "
+		"please report if you suspect wrong parsing!\n"
+		"\n"
+		"version \"%s\"\n", adev->firmware_version);
+
+	/* TODO: may replace kmalloc/memset with kzalloc once
+	 * Linux 2.6.14 is widespread */
+	fw_stats = kmalloc(sizeof(*fw_stats), GFP_KERNEL);
+	if (!fw_stats) {
+		FN_EXIT1(0);
+		return 0;
+	}
+	memset(fw_stats, 0, sizeof(*fw_stats));
+
+	st = (u8 *)fw_stats;
+
+	part_str = "statistics query command";
+
+	if (OK != acx_s_interrogate(adev, st, ACX1xx_IE_FIRMWARE_STATISTICS))
+		goto fw_stats_end;
+
+	st += sizeof(u16);
+	len = *(u16 *)st;
+
+	if (len > sizeof(*fw_stats)) {
 		p += sprintf(p,
-			"tx_exch_complet %u, commands %u, acx_rx_procs %u\n"
-			"hw_pm_mode_changes %u, host_acks %u, pci_pm %u, acm_wakeups %u\n"
-			"wep_key_count %u, wep_default_key_count %u, dot11_def_key_mib %u\n"
-			"wep_key_not_found %u, wep_decrypt_fail %u\n",
-			le32_to_cpu(fw_stats->tx_exch_complet),
-			le32_to_cpu(fw_stats->commands),
-			le32_to_cpu(fw_stats->acx_rx_procs),
-			le32_to_cpu(fw_stats->hw_pm_mode_changes),
-			le32_to_cpu(fw_stats->host_acks),
-			le32_to_cpu(fw_stats->pci_pm),
-			le32_to_cpu(fw_stats->acm_wakeups),
-			le32_to_cpu(fw_stats->wep_key_count),
-			le32_to_cpu(fw_stats->wep_default_key_count),
-			le32_to_cpu(fw_stats->dot11_def_key_mib),
-			le32_to_cpu(fw_stats->wep_key_not_found),
-			le32_to_cpu(fw_stats->wep_decrypt_fail));
+			"firmware version with bigger fw_stats struct detected\n"
+			"(%u vs. %u), please report\n", len, sizeof(fw_stats_t));
+		if (len > sizeof(*fw_stats)) {
+			p += sprintf(p, "struct size exceeded allocation!\n");
+			len = sizeof(*fw_stats);
+		}
+	}
+	st += sizeof(u16);
+	st_end = st - 2*sizeof(u16) + len;
+
+#ifdef __BIG_ENDIAN
+	/* let's make one bold assumption here:
+	 * (hopefully!) *all* statistics fields are u32 only,
+	 * thus if we need to make endianness corrections
+	 * we can simply do them in one go, in advance */
+	st2 = (u8 *)fw_stats;
+	for (temp1 = 0; temp1 < len; temp1 += 4, st2 += 4)
+		*(u32 *)st2 = le32_to_cpu(*(u32 *)st2);
+#endif
+
+	part_str = "Rx/Tx";
+
+	/* directly at end of a struct part? --> no error! */
+	if (st == st_end)
+		goto fw_stats_end;
+
+	tx = (fw_stats_tx_t *)st;
+	st += sizeof(fw_stats_tx_t);
+	rx = (fw_stats_rx_t *)st;
+	st += sizeof(fw_stats_rx_t);
+	partlen = sizeof(fw_stats_tx_t) + sizeof(fw_stats_rx_t);
+
+	if (IS_ACX100(adev)) {
+		/* at least ACX100 PCI F/W 1.9.8.b
+		 * and ACX100 USB F/W 1.0.7-USB
+		 * don't have those two fields... */
+		st -= 2*sizeof(u32);
+
+		/* our parsing doesn't quite match this firmware yet,
+		 * log failure */
+		if (st > st_end)
+			goto fw_stats_fail;
+		temp1 = temp2 = 999999999;
+	} else {
+		if (st > st_end)
+			goto fw_stats_fail;
+		temp1 = rx->rx_aci_events;
+		temp2 = rx->rx_aci_resets;
 	}
 
+	p += sprintf(p,
+		"%s:\n"
+		"  tx_desc_overfl %u\n"
+		"  rx_OutOfMem %u, rx_hdr_overfl %u, rx_hw_stuck %u\n"
+		"  rx_dropped_frame %u, rx_frame_ptr_err %u, rx_xfr_hint_trig %u\n"
+		"  rx_aci_events %u, rx_aci_resets %u\n",
+		part_str,
+		tx->tx_desc_of,
+		rx->rx_oom,
+		rx->rx_hdr_of,
+		rx->rx_hw_stuck,
+		rx->rx_dropped_frame,
+		rx->rx_frame_ptr_err,
+		rx->rx_xfr_hint_trig,
+		temp1,
+		temp2);
+
+	part_str = "DMA";
+
+	if (st == st_end)
+		goto fw_stats_end;
+
+	dma = (fw_stats_dma_t *)st;
+	partlen = sizeof(fw_stats_dma_t);
+	st += partlen;
+
+	if (st > st_end)
+		goto fw_stats_fail;
+
+	p += sprintf(p,
+		"%s:\n"
+		"  rx_dma_req %u, rx_dma_err %u, tx_dma_req %u, tx_dma_err %u\n",
+		part_str,
+		dma->rx_dma_req,
+		dma->rx_dma_err,
+		dma->tx_dma_req,
+		dma->tx_dma_err);
+
+	part_str = "IRQ";
+
+	if (st == st_end)
+		goto fw_stats_end;
+
+	irq = (fw_stats_irq_t *)st;
+	partlen = sizeof(fw_stats_irq_t);
+	st += partlen;
+
+	if (st > st_end)
+		goto fw_stats_fail;
+
+	p += sprintf(p,
+		"%s:\n"
+		"  cmd_cplt %u, fiq %u\n"
+		"  rx_hdrs %u, rx_cmplt %u, rx_mem_overfl %u, rx_rdys %u\n"
+		"  irqs %u, tx_procs %u, decrypt_done %u\n"
+		"  dma_0_done %u, dma_1_done %u, tx_exch_complet %u\n"
+		"  commands %u, rx_procs %u, hw_pm_mode_changes %u\n"
+		"  host_acks %u, pci_pm %u, acm_wakeups %u\n",
+		part_str,
+		irq->cmd_cplt,
+		irq->fiq,
+		irq->rx_hdrs,
+		irq->rx_cmplt,
+		irq->rx_mem_of,
+		irq->rx_rdys,
+		irq->irqs,
+		irq->tx_procs,
+		irq->decrypt_done,
+		irq->dma_0_done,
+		irq->dma_1_done,
+		irq->tx_exch_complet,
+		irq->commands,
+		irq->rx_procs,
+		irq->hw_pm_mode_changes,
+		irq->host_acks,
+		irq->pci_pm,
+		irq->acm_wakeups);
+
+	part_str = "WEP";
+
+	if (st == st_end)
+		goto fw_stats_end;
+
+	wep = (fw_stats_wep_t *)st;
+	partlen = sizeof(fw_stats_wep_t);
+	st += partlen;
+
+	if (
+	    (IS_PCI(adev) && IS_ACX100(adev))
+	||  (IS_USB(adev) && IS_ACX100(adev))
+	) {
+		/* at least ACX100 PCI F/W 1.9.8.b
+		 * and ACX100 USB F/W 1.0.7-USB
+		 * don't have those two fields... */
+		st -= 2*sizeof(u32);
+		if (st > st_end)
+			goto fw_stats_fail;
+		temp1 = temp2 = 999999999;
+	} else {
+		if (st > st_end)
+			goto fw_stats_fail;
+		temp1 = wep->wep_pkt_decrypt;
+		temp2 = wep->wep_decrypt_irqs;
+	}
+
+	p += sprintf(p,
+		"%s:\n"
+		"  wep_key_count %u, wep_default_key_count %u, dot11_def_key_mib %u\n"
+		"  wep_key_not_found %u, wep_decrypt_fail %u\n"
+		"  wep_pkt_decrypt %u, wep_decrypt_irqs %u\n",
+		part_str,
+		wep->wep_key_count,
+		wep->wep_default_key_count,
+		wep->dot11_def_key_mib,
+		wep->wep_key_not_found,
+		wep->wep_decrypt_fail,
+		temp1,
+		temp2);
+
+	part_str = "power";
+
+	if (st == st_end)
+		goto fw_stats_end;
+
+	pwr = (fw_stats_pwr_t *)st;
+	partlen = sizeof(fw_stats_pwr_t);
+	st += partlen;
+
+	if (st > st_end)
+		goto fw_stats_fail;
+
+	p += sprintf(p,
+		"%s:\n"
+		"  tx_start_ctr %u, no_ps_tx_too_short %u\n"
+		"  rx_start_ctr %u, no_ps_rx_too_short %u\n"
+		"  lppd_started %u\n"
+		"  no_lppd_too_noisy %u, no_lppd_too_short %u, no_lppd_matching_frame %u\n",
+		part_str,
+		pwr->tx_start_ctr,
+		pwr->no_ps_tx_too_short,
+		pwr->rx_start_ctr,
+		pwr->no_ps_rx_too_short,
+		pwr->lppd_started,
+		pwr->no_lppd_too_noisy,
+		pwr->no_lppd_too_short,
+		pwr->no_lppd_matching_frame);
+
+	part_str = "MIC";
+
+	if (st == st_end)
+		goto fw_stats_end;
+
+	mic = (fw_stats_mic_t *)st;
+	partlen = sizeof(fw_stats_mic_t);
+	st += partlen;
+
+	if (st > st_end)
+		goto fw_stats_fail;
+
+	p += sprintf(p,
+		"%s:\n"
+		"  mic_rx_pkts %u, mic_calc_fail %u\n",
+		part_str,
+		mic->mic_rx_pkts,
+		mic->mic_calc_fail);
+
+	part_str = "AES";
+
+	if (st == st_end)
+		goto fw_stats_end;
+
+	aes = (fw_stats_aes_t *)st;
+	partlen = sizeof(fw_stats_aes_t);
+	st += partlen;
+
+	if (st > st_end)
+		goto fw_stats_fail;
+
+	p += sprintf(p,
+		"%s:\n"
+		"  aes_enc_fail %u, aes_dec_fail %u\n"
+		"  aes_enc_pkts %u, aes_dec_pkts %u\n"
+		"  aes_enc_irq %u, aes_dec_irq %u\n",
+		part_str,
+		aes->aes_enc_fail,
+		aes->aes_dec_fail,
+		aes->aes_enc_pkts,
+		aes->aes_dec_pkts,
+		aes->aes_enc_irq,
+		aes->aes_dec_irq);
+
+	part_str = "event";
+
+	if (st == st_end)
+		goto fw_stats_end;
+
+	evt = (fw_stats_event_t *)st;
+	partlen = sizeof(fw_stats_event_t);
+	st += partlen;
+
+	if (st > st_end)
+		goto fw_stats_fail;
+
+	p += sprintf(p,
+		"%s:\n"
+		"  heartbeat %u, calibration %u\n"
+		"  rx_mismatch %u, rx_mem_empty %u, rx_pool %u\n"
+		"  oom_late %u\n"
+		"  phy_tx_err %u, tx_stuck %u\n",
+		part_str,
+		evt->heartbeat,
+		evt->calibration,
+		evt->rx_mismatch,
+		evt->rx_mem_empty,
+		evt->rx_pool,
+		evt->oom_late,
+		evt->phy_tx_err,
+		evt->tx_stuck);
+
+	if (st < st_end)
+		goto fw_stats_bigger;
+
+	goto fw_stats_end;
+
+fw_stats_fail:
+	st -= partlen;
+	p += sprintf(p,
+		"failed at %s part (size %u), offset %u (struct size %u), "
+		"please report\n", part_str, partlen,
+		(int)st - (int)fw_stats, len);
+
+fw_stats_bigger:
+	for (; st < st_end; st += 4)
+		p += sprintf(p,
+			"UNKN%3d: %u\n", (int)st - (int)fw_stats, *(u32 *)st);
+
+fw_stats_end:
 	kfree(fw_stats);
 
 	FN_EXIT1(p - buf);
@@ -1472,11 +1765,15 @@ acx_proc_register_entries(const struct n
 	return manage_proc_entries(ndev, 0);
 }
 
+EXPORT_SYMBOL_GPL(acx_proc_register_entries);
+
 int
 acx_proc_unregister_entries(const struct net_device *ndev)
 {
 	return manage_proc_entries(ndev, 1);
 }
+
+EXPORT_SYMBOL_GPL(acx_proc_unregister_entries);
 #endif /* CONFIG_PROC_FS */
 
 
@@ -1852,7 +2149,7 @@ bad:
 ** Note that this fn messes up heavily with hardware, but we cannot
 ** lock it (we need to sleep). Not a problem since IRQs can't happen
 */
-static int
+int
 acx100_s_create_dma_regions(acx_device_t *adev)
 {
 	acx100_ie_queueconfig_t queueconf;
@@ -1936,6 +2233,7 @@ end:
 	return res;
 }
 
+EXPORT_SYMBOL_GPL(acx100_s_create_dma_regions);
 
 /***********************************************************************
 ** acx111_s_create_dma_regions
@@ -1945,7 +2243,7 @@ end:
 */
 #define ACX111_PERCENT(percent) ((percent)/5)
 
-static int
+int
 acx111_s_create_dma_regions(acx_device_t *adev)
 {
 	struct acx111_ie_memoryconfig memconf;
@@ -2033,6 +2331,7 @@ fail:
 	return NOT_OK;
 }
 
+EXPORT_SYMBOL_GPL(acx111_s_create_dma_regions);
 
 /***********************************************************************
 */
@@ -2298,6 +2597,7 @@ acx_s_set_defaults(acx_device_t *adev)
 	FN_EXIT0;
 }
 
+EXPORT_SYMBOL_GPL(acx_s_set_defaults);
 
 /***********************************************************************
 ** FIXME: this should be solved in a general way for all radio types
@@ -2723,76 +3023,78 @@ acx_l_process_rxbuf(acx_device_t *adev, 
 
 
 //SM: have no dev specific code, should be moved to sm layer
+/* Filter out unrelated packets, call ieee80211_rx[_mgt] */
 static int
-_TODO_wlan_rx(struct ieee80211_device *ieee,
-		struct sk_buff *skb,
-		struct ieee80211_rx_stats *stats)
+_TODO_ieee80211_rx_any(struct ieee80211_device *ieee,
+		     struct sk_buff *skb, struct ieee80211_rx_stats *stats)
 {
 	struct ieee80211_hdr_4addr *hdr;
-	int is_packet_for_us = 0;
+	int is_packet_for_us;
 	u16 fc;
 
 	if (ieee->iw_mode == IW_MODE_MONITOR)
 		return ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL;
 
 	hdr = (struct ieee80211_hdr_4addr *)skb->data;
+	fc = le16_to_cpu(hdr->frame_ctl);
 
-	switch (ieee->iw_mode) {
-	case IW_MODE_ADHOC:
-		if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0 ||
-		    memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0 ||
-		    is_broadcast_ether_addr(hdr->addr1) ||
-		    is_multicast_ether_addr(hdr->addr1) ||
-		    ieee->dev->flags & IFF_PROMISC)
-			is_packet_for_us = 1;
+	if ((fc & IEEE80211_FCTL_VERS) != 0)
+		return -EINVAL;
+
+	switch (fc & IEEE80211_FCTL_FTYPE) {
+	case IEEE80211_FTYPE_MGMT:
+		ieee80211_rx_mgt(ieee, hdr, stats);
+		return 0;
+	case IEEE80211_FTYPE_DATA:
 		break;
-	case IW_MODE_INFRA:
+	case IEEE80211_FTYPE_CTL:
+		return 0;
 	default:
-		/* When receiving multicast or broadcast packets, filter out
-		   the packets we send ourself; we shouldn't see those */
-		if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0 ||
-		    memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0 ||
-		    (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN) &&
-		     (is_broadcast_ether_addr(hdr->addr1) ||
-		      is_multicast_ether_addr(hdr->addr1) ||
-		      ieee->dev->flags & IFF_PROMISC)))
-			is_packet_for_us = 1;
-		break;
+		return -EINVAL;
 	}
 
-	fc = hdr->frame_ctl;
-
-	if ((fc & WF_FC_ISWEPi) && !ieee->host_decrypt) {
-		fc &= ~WF_FC_ISWEPi;
-		hdr->frame_ctl = fc;		
-		/* trim IV and ICV */
-		/* FIXME: this must be done only for WEP encrypted packets */
-		if (skb->len < 32) {
-			printk("acx: RX packet dropped: PROTECTED flag "
-				"set and length < 32 (%d)\n", skb->len);
-			return -EINVAL;
-		} else {		
-			memmove(skb->data + 4, skb->data, 24);
-			skb_pull(skb, 4);
-			skb_trim(skb, skb->len - 4);
+	is_packet_for_us = 0;
+	switch (ieee->iw_mode) {
+	case IW_MODE_ADHOC:
+		/* our BSS and not from/to DS */
+		if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0)
+		if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) {
+			/* promisc: get all */
+			if (ieee->dev->flags & IFF_PROMISC)
+				is_packet_for_us = 1;
+			/* to us */
+			else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
+				is_packet_for_us = 1;
+			/* mcast */
+			else if (is_multicast_ether_addr(hdr->addr1))
+				is_packet_for_us = 1;
 		}
-		hdr = (struct ieee80211_hdr_4addr *)skb->data;
-	}
-
-	switch (fc & WF_FC_FTYPEi) {
-	case WF_FTYPE_MGMTi:
-		ieee80211_rx_mgt(ieee, hdr, stats);
 		break;
-	case WF_FTYPE_DATAi:
-		if (is_packet_for_us)
-			return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL);
-		break;
-	case WF_FTYPE_CTLi:
+	case IW_MODE_INFRA:
+		/* our BSS (== from our AP) and from DS */
+		if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0)
+		if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) {
+			/* promisc: get all */
+			if (ieee->dev->flags & IFF_PROMISC)
+				is_packet_for_us = 1;
+			/* to us */
+			else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
+				is_packet_for_us = 1;
+			/* mcast */
+			else if (is_multicast_ether_addr(hdr->addr1)) {
+				/* not our own packet bcasted from AP */
+				if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN))
+					is_packet_for_us = 1;
+			}
+		}
 		break;
 	default:
-		return -EINVAL;
+		/* ? */
+		break;
 	}
 
+	if (is_packet_for_us)
+		return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL);
 	return 0;
 }
 
@@ -2862,12 +3164,12 @@ acx_l_softmac_process_rxbuf(acx_device_t
 
 	memset(&stats, 0, sizeof(stats));
 	stats.mac_time = le16_to_cpu(rxbuf->time);
-	//stats.rssi = 
+	//stats.rssi =
 	stats.signal = rxbuf->phy_snr;
 	stats.noise = rxbuf->phy_level;
 	stats.rate = rxbuf->phy_plcp_signal / 5;
 	stats.received_channel = adev->channel;
-	//stats.control = 
+	//stats.control =
 	stats.mask = 0
 		| IEEE80211_STATMASK_SIGNAL
 		| IEEE80211_STATMASK_NOISE
@@ -2877,12 +3179,12 @@ acx_l_softmac_process_rxbuf(acx_device_t
 	stats.freq = IEEE80211_24GHZ_BAND;
 	stats.len = skb->len;
 
-	_TODO_wlan_rx(adev->ieee, skb, &stats);
+	_TODO_ieee80211_rx_any(adev->ieee, skb, &stats);
 end:
 	FN_EXIT0;
 }
 
-
+EXPORT_SYMBOL_GPL(acx_l_softmac_process_rxbuf);
 
 
 
@@ -3035,6 +3337,7 @@ acx_l_handle_txrate_auto(acx_device_t *a
 	}
 }
 
+EXPORT_SYMBOL_GPL(acx_l_handle_txrate_auto);
 
 /***********************************************************************
 ** acx_i_start_xmit
@@ -3147,7 +3450,7 @@ acx_i_ieee80211_start_xmit(struct ieee80
 
 	acx_lock(adev, flags);
 
-        for (i = 0; i < txb->nr_frags; i++) {
+	for (i = 0; i < txb->nr_frags; i++) {
 		tx_t *tx;
 		void *txbuf;
 		struct sk_buff *skb = txb->fragments[i];
@@ -3170,7 +3473,7 @@ acx_i_ieee80211_start_xmit(struct ieee80
 		//ndev->trans_start = jiffies;
 		//adev->stats.tx_packets++;
 		//adev->stats.tx_bytes += skb->len;
-        }
+	}
 	rc = 0;
 
 end:
@@ -3184,6 +3487,7 @@ end_no_unlock:
 	return rc;
 }
 
+EXPORT_SYMBOL_GPL(acx_i_ieee80211_start_xmit);
 
 /***********************************************************************
 ** acx_l_update_ratevector
@@ -3481,6 +3785,7 @@ acx_set_status(acx_device_t *adev, u16 n
 	FN_EXIT0;
 }
 
+EXPORT_SYMBOL_GPL(acx_set_status);
 
 /***********************************************************************
 ** acx_i_timer
@@ -3560,6 +3865,7 @@ acx_i_timer(unsigned long address)
 	FN_EXIT0;
 }
 
+EXPORT_SYMBOL_GPL(acx_i_timer);
 
 /***********************************************************************
 ** acx_set_timer
@@ -5484,6 +5790,7 @@ release_ret:
 	return res;
 }
 
+EXPORT_SYMBOL_GPL(acx_s_read_fw);
 
 /***********************************************************************
 ** acx_s_set_wepkey
@@ -6072,6 +6379,7 @@ fail:
 	return result;
 }
 
+EXPORT_SYMBOL_GPL(acx_s_init_mac);
 
 void
 acx_s_set_sane_reg_domain(acx_device_t *adev, int do_set)
@@ -6704,6 +7012,7 @@ acx_s_update_card_settings(acx_device_t 
 	FN_EXIT0;
 }
 
+EXPORT_SYMBOL_GPL(acx_s_update_card_settings);
 
 /***********************************************************************
 ** acx_e_after_interrupt_task
@@ -6910,6 +7219,7 @@ acx_schedule_task(acx_device_t *adev, un
 	SCHEDULE_WORK(&adev->after_interrupt_task);
 }
 
+EXPORT_SYMBOL_GPL(acx_schedule_task);
 
 /***********************************************************************
 */
@@ -6921,6 +7231,7 @@ acx_init_task_scheduler(acx_device_t *ad
 			adev->ndev);
 }
 
+EXPORT_SYMBOL_GPL(acx_init_task_scheduler);
 
 /***********************************************************************
 ** acx_s_start
@@ -6947,6 +7258,7 @@ acx_s_start(acx_device_t *adev)
 	FN_EXIT0;
 }
 
+EXPORT_SYMBOL_GPL(acx_s_start);
 
 /***********************************************************************
 ** acx_update_capabilities
@@ -7138,59 +7450,7 @@ acx_s_parse_configoption(acx_device_t *a
 */
 }
 
-
-/***********************************************************************
-*/
-static int __init
-acx_e_init_module(void)
-{
-	int r1,r2;
-
-	acx_struct_size_check();
-
-	printk("acx: this driver is still EXPERIMENTAL\n"
-		"acx: reading README file and/or Craig's HOWTO is "
-		"recommended, visit http://acx100.sf.net in case "
-		"of further questions/discussion\n");
-
-#if defined(CONFIG_ACX_PCI_BOOL)
-	r1 = acxpci_e_init_module();
-#else
-	r1 = -EINVAL;
-#endif
-#if defined(CONFIG_ACX_USB_BOOL)
-	r2 = acxusb_e_init_module();
-#else
-	r2 = -EINVAL;
-#endif
-	if (r2 && r1) /* both failed! */
-		return r2 ? r2 : r1;
-	/* return success if at least one succeeded */
-	return 0;
-}
-
-static void __exit
-acx_e_cleanup_module(void)
-{
-#if defined(CONFIG_ACX_PCI_BOOL)
-	acxpci_e_cleanup_module();
-#endif
-#if defined(CONFIG_ACX_USB_BOOL)
-	acxusb_e_cleanup_module();
-#endif
-}
-
-module_init(acx_e_init_module)
-module_exit(acx_e_cleanup_module)
-
-
-
-
-
-
-
-
-
+EXPORT_SYMBOL_GPL(acx_s_parse_configoption);
 
 //SM
 void
@@ -7230,7 +7490,7 @@ acx_e_ieee80211_set_security(struct net_
 			adev->ieee->sec.flags |= SEC_ACTIVE_KEY;
 		} else
 			adev->ieee->sec.flags &= ~SEC_ACTIVE_KEY;
-		
+
 	} else
 		adev->ieee->sec.flags &= ~SEC_ACTIVE_KEY;
 
@@ -7257,13 +7517,14 @@ acx_e_ieee80211_set_security(struct net_
 		adev->ieee->sec.flags |= SEC_LEVEL;
 		SET_BIT(adev->set_mask, GETSET_WEP);
 	}
-	
+
 	acx_unlock(adev, flags);
 	acx_sem_unlock(adev);
 
 	acx_s_update_card_settings(adev);
 }
 
+EXPORT_SYMBOL_GPL(acx_e_ieee80211_set_security);
 
 void
 acx_e_ieee80211_set_chan(struct net_device *ndev, u8 channel)
@@ -7277,3 +7538,5 @@ acx_e_ieee80211_set_chan(struct net_devi
 
 	acx_sem_unlock(adev);
 }
+
+EXPORT_SYMBOL_GPL(acx_e_ieee80211_set_chan);
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/ioctl.c wireless-2.6.git.acx/drivers/net/wireless/tiacx/ioctl.c
--- wireless-2.6.git/drivers/net/wireless/tiacx/ioctl.c	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/ioctl.c	Wed Mar  1 12:05:04 2006
@@ -1007,87 +1007,9 @@ acx_ioctl_set_encode(
 	union iwreq_data *wrqu,
 	char *extra)
 {
-	struct iw_point *dwrq = &wrqu->encoding;
-	acx_device_t *adev = ndev2adev(ndev);
-	int index;
 	int result;
-
 	FN_ENTER;
-
-	log(L_IOCTL, "set encoding flags=0x%04X, size=%d, key: %s\n",
-			dwrq->flags, dwrq->length, extra ? "set" : "No key");
-
-	acx_sem_lock(adev);
-
-	index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-
-	if (dwrq->length > 0) {
-		/* if index is 0 or invalid, use default key */
-		if ((index < 0) || (index > 3))
-			index = (int)adev->ieee->sec.active_key;
-
-		if (0 == (dwrq->flags & IW_ENCODE_NOKEY)) {
-			if (dwrq->length > 29)
-				dwrq->length = 29; /* restrict it */
-
-			if (dwrq->length > 13) {
-				/* 29*8 == 232, WEP256 */
-				adev->ieee->sec.key_sizes[index] = 29;
-			} else if (dwrq->length > 5) {
-				/* 13*8 == 104bit, WEP128 */
-				adev->ieee->sec.key_sizes[index] = 13;
-			} else if (dwrq->length > 0) {
-				/* 5*8 == 40bit, WEP64 */
-				adev->ieee->sec.key_sizes[index] = 5;
-			} else {
-				/* disable key */
-				adev->ieee->sec.key_sizes[index] = 0;
-			}
-
-			memset(adev->ieee->sec.keys[index], 0,
-				sizeof(adev->ieee->sec.keys[index]));
-			memcpy(adev->ieee->sec.keys[index], extra, dwrq->length);
-		}
-	} else {
-		/* set transmit key */
-		if ((index >= 0) && (index <= 3))
-			adev->ieee->sec.active_key = index;
-		else if (0 == (dwrq->flags & IW_ENCODE_MODE)) {
-			/* complain if we were not just setting
-			 * the key mode */
-			result = -EINVAL;
-			goto end_unlock;
-		}
-	}
-
-	adev->ieee->sec.enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
-
-	if (dwrq->flags & IW_ENCODE_OPEN) {
-		adev->ieee->sec.auth_mode = WLAN_AUTH_OPEN;
-
-	} else if (dwrq->flags & IW_ENCODE_RESTRICTED) {
-	  adev->ieee->sec.auth_mode = WLAN_AUTH_SHARED_KEY;
-	}
-
-	/* set flag to make sure the card WEP settings get updated */
-	SET_BIT(adev->set_mask, GETSET_WEP);
-
-	log(L_IOCTL, "len=%d, key at 0x%p, flags=0x%X\n",
-		dwrq->length, extra, dwrq->flags);
-
-	for (index = 0; index <= 3; index++) {
-		if (adev->ieee->sec.key_sizes[index]) {
-			log(L_IOCTL,	"index=%d, size=%d, key at 0x%p\n",
-				adev->ieee->sec.active_key,
-				(int) adev->ieee->sec.key_sizes[index],
-				adev->ieee->sec.keys[index]);
-		}
-	}
-	result = -EINPROGRESS;
-
-end_unlock:
-	acx_sem_unlock(adev);
-
+	result = ieee80211_wx_set_encode(netdev_priv(ndev), info, wrqu, extra);
 	FN_EXIT1(result);
 	return result;
 }
@@ -1103,38 +1025,45 @@ acx_ioctl_get_encode(
 	union iwreq_data *wrqu,
 	char *extra)
 {
-	struct iw_point *dwrq = &wrqu->encoding;
-	acx_device_t *adev = ndev2adev(ndev);
-	int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-
+	int result;
 	FN_ENTER;
-
-	if (adev->ieee->sec.enabled == 0) {
-		dwrq->flags = IW_ENCODE_DISABLED;
-	} else {
-		if ((index < 0) || (index > 3))
-			index = (int)adev->ieee->sec.active_key;
-
-		dwrq->flags = (adev->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY) ?
-				IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
-		dwrq->length = adev->ieee->sec.key_sizes[index];
-
-		memcpy(extra, adev->ieee->sec.keys[index],
-			      adev->ieee->sec.key_sizes[index]);
-	}
-
-	/* set the current index */
-	SET_BIT(dwrq->flags, index + 1);
-
-	log(L_IOCTL, "len=%d, key=%p, flags=0x%X\n",
-	       dwrq->length, dwrq->pointer,
-	       dwrq->flags);
-
-	FN_EXIT1(OK);
-	return OK;
+	result = ieee80211_wx_get_encode(netdev_priv(ndev), info, wrqu, extra);
+	FN_EXIT1(result);
+	return result;
 }
 
-
+/***********************************************************************
+** acx_ioctl_set_encodeext
+*/
+static int
+acx_ioctl_set_encodeext(
+	struct net_device *ndev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int result;
+	FN_ENTER;
+	result = ieee80211_wx_set_encodeext(netdev_priv(ndev), info, wrqu, extra);
+	FN_EXIT1(result);
+	return result;
+}
+/***********************************************************************
+** acx_ioctl_get_encodeext
+*/
+static int
+acx_ioctl_get_encodeext(
+	struct net_device *ndev,
+	struct iw_request_info *info,
+	union iwreq_data *wrqu,
+	char *extra)
+{
+	int result;
+	FN_ENTER;
+	result = ieee80211_wx_get_encodeext(netdev_priv(ndev), info, wrqu, extra);
+	FN_EXIT1(result);
+	return result;
+}
 /***********************************************************************
 */
 static int
@@ -2608,6 +2537,8 @@ static const iw_handler acx_ioctl_handle
 	/* Encoding */
 	WX(SIOCSIWENCODE)	= acx_ioctl_set_encode,
 	WX(SIOCGIWENCODE)	= acx_ioctl_get_encode,
+	WX(SIOCSIWENCODEEXT)    = acx_ioctl_set_encodeext,
+	WX(SIOCGIWENCODEEXT)    = acx_ioctl_get_encodeext,
 	/* Power saving */
 	WX(SIOCSIWPOWER)	= acx_ioctl_set_power,
 	WX(SIOCGIWPOWER)	= acx_ioctl_get_power,
@@ -2803,3 +2734,5 @@ const struct iw_handler_def acx_ioctl_ha
 	.get_wireless_stats = acx_e_get_wireless_stats
 #endif /* IW > 5 */
 };
+
+EXPORT_SYMBOL_GPL(acx_ioctl_handler_def);
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/pci.c wireless-2.6.git.acx/drivers/net/wireless/tiacx/pci.c
--- wireless-2.6.git/drivers/net/wireless/tiacx/pci.c	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/pci.c	Wed Mar  1 12:05:04 2006
@@ -105,6 +105,25 @@ static int acxpci_e_close(struct net_dev
 static void acxpci_s_up(struct net_device *ndev);
 static void acxpci_s_down(struct net_device *ndev);
 
+#if ACX_DEBUG
+static int acxpci_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
+#else
+static int acxpci_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout);
+#endif
+static int acxpci_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf);
+static int acxpci_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value);
+static tx_t* acxpci_l_alloc_tx(acx_device_t *adev);
+static void acxpci_l_dealloc_tx(tx_t *tx_opaque);
+static void* acxpci_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque);
+static void acxpci_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len);
+
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("Dual MPL/GPL");
+#endif
+/* USB had this: MODULE_AUTHOR("Martin Wawro <martin.wawro AT uni-dortmund.de>"); */
+MODULE_AUTHOR("ACX100 Open Source Driver development team");
+MODULE_DESCRIPTION("Driver for TI ACX1xx based wireless cards (CardBus/PCI)");
+
 
 /***********************************************************************
 ** Register access
@@ -174,11 +193,13 @@ write_flush(acx_device_t *adev)
 	readb(adev->iobase);
 }
 
-
-/***********************************************************************
-*/
-static struct net_device *root_adev_newest = NULL;
-DECLARE_MUTEX(root_adev_sem);
+INLINE_IO int
+adev_present(acx_device_t *adev)
+{
+	/* fast version (accesses the first register, IO_ACX_SOFT_RESET,
+	 * which should be safe): */
+	return readl(adev->iobase) != 0xffffffff;
+}
 
 
 /***********************************************************************
@@ -406,7 +427,7 @@ end:
 ** Messing with rx/tx disabling and enabling here
 ** (write_reg32(adev, IO_ACX_ENABLE, 0b000000xx)) kills traffic
 */
-int
+static int
 acxpci_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
 {
 	int result = NOT_OK;
@@ -447,7 +468,7 @@ fail:
 
 /***********************************************************************
 */
-int
+static int
 acxpci_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
 {
 	FN_ENTER;
@@ -1001,8 +1022,8 @@ end:
 #undef FUNC
 #define FUNC "issue_cmd"
 
+static int
 #if !ACX_DEBUG
-int
 acxpci_s_issue_cmd_timeo(
 	acx_device_t *adev,
 	unsigned int cmd,
@@ -1011,7 +1032,6 @@ acxpci_s_issue_cmd_timeo(
 	unsigned cmd_timeout)
 {
 #else
-int
 acxpci_s_issue_cmd_timeo_debug(
 	acx_device_t *adev,
 	unsigned cmd,
@@ -1058,13 +1078,13 @@ acxpci_s_issue_cmd_timeo_debug(
 		/* Test for IDLE state */
 		if (!cmd_status)
 			break;
-		if (counter % 5 == 0) {
+		if (counter % 8 == 0) {
 			if (time_after(jiffies, timeout)) {
 				counter = 0;
 				break;
 			}
-			/* we waited 5 iterations, no luck. Sleep 5 ms */
-			acx_s_msleep(5);
+			/* we waited 8 iterations, no luck. Sleep 8 ms */
+			acx_s_msleep(8);
 		}
 	} while (likely(--counter));
 
@@ -1124,13 +1144,13 @@ acxpci_s_issue_cmd_timeo_debug(
 				break;
 		}
 
-		if (counter % 5 == 0) {
+		if (counter % 8 == 0) {
 			if (time_after(jiffies, timeout)) {
 				counter = 0;
 				break;
 			}
-			/* we waited 5 iterations, no luck. Sleep 5 ms */
-			acx_s_msleep(5);
+			/* we waited 8 iterations, no luck. Sleep 8 ms */
+			acx_s_msleep(8);
 		}
 	} while (likely(--counter));
 
@@ -1273,62 +1293,6 @@ acx_show_card_eeprom_id(acx_device_t *ad
 
 
 /***********************************************************************
-*/
-static void
-acxpci_s_device_chain_add(struct net_device *ndev)
-{
-	acx_device_t *adev = ndev2adev(ndev);
-
-	down(&root_adev_sem);
-	adev->prev_nd = root_adev_newest;
-	root_adev_newest = ndev;
-	adev->ndev = ndev;
-	up(&root_adev_sem);
-}
-
-static void
-acxpci_s_device_chain_remove(struct net_device *ndev)
-{
-	struct net_device *querydev;
-	struct net_device *olderdev;
-	struct net_device *newerdev;
-
-	down(&root_adev_sem);
-	querydev = root_adev_newest;
-	newerdev = NULL;
-	while (querydev) {
-		olderdev = ndev2adev(querydev)->prev_nd;
-		if (0 == strcmp(querydev->name, ndev->name)) {
-			if (!newerdev) {
-				/* if we were at the beginning of the
-				 * list, then it's the list head that
-				 * we need to update to point at the
-				 * next older device */
-				root_adev_newest = olderdev;
-			} else {
-				/* it's the device that is newer than us
-				 * that we need to update to point at
-				 * the device older than us */
-				ndev2adev(newerdev)->prev_nd = olderdev;
-			}
-			break;
-		}
-		/* "newerdev" is actually the device of the old iteration,
-		 * but since the list starts (root_adev_newest)
-		 * with the newest devices,
-		 * it's newer than the ones following.
-		 * Oh the joys of iterating from newest to oldest :-\ */
-		newerdev = querydev;
-
-		/* keep checking old devices for matches until we hit the end
-		 * of the list */
-		querydev = olderdev;
-	}
-	up(&root_adev_sem);
-}
-
-
-/***********************************************************************
 ** acxpci_free_desc_queues
 **
 ** Releases the queues that have been allocated, the
@@ -1617,6 +1581,7 @@ acxpci_e_probe(struct pci_dev *pdev, con
 	** just _presume_ that we're under sem (instead of actually taking it): */
 	/* acx_sem_lock(adev); */
 	adev->pdev = pdev;
+	adev->ndev = ndev;
 	adev->dev_type = DEVTYPE_PCI;
 	adev->chip_type = chip_type;
 	adev->chip_name = chip_name;
@@ -1645,6 +1610,24 @@ acxpci_e_probe(struct pci_dev *pdev, con
 	adev->ieee->sec.enabled = 0;
 	adev->ieee->sec.auth_mode = WLAN_AUTH_OPEN;
 
+	if (IS_ACX100(adev)) {
+		adev->ops.create_dma_regions = acx100_s_create_dma_regions;
+	} else {
+		adev->ops.create_dma_regions = acx111_s_create_dma_regions;
+	}
+	adev->ops.delete_dma_regions = acxpci_s_delete_dma_regions;
+#if ACX_DEBUG
+	adev->ops.issue_cmd = acxpci_s_issue_cmd_timeo_debug;
+#else
+	adev->ops.issue_cmd  = acxpci_s_issue_cmd_timeo;
+#endif /* ACX_DEBUG */
+	adev->ops.alloc_tx = acxpci_l_alloc_tx;
+	adev->ops.dealloc_tx = acxpci_l_dealloc_tx;
+	adev->ops.get_txbuf = acxpci_l_get_txbuf;
+	adev->ops.tx_data = acxpci_l_tx_data;
+	adev->ops.write_phy_reg = acxpci_s_write_phy_reg;
+	adev->ops.read_phy_reg = acxpci_s_read_phy_reg;
+
 #ifdef NONESSENTIAL_FEATURES
 	acx_show_card_eeprom_id(adev);
 #endif /* NONESSENTIAL_FEATURES */
@@ -1654,9 +1637,6 @@ acxpci_e_probe(struct pci_dev *pdev, con
 #endif
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
-	/* register new dev in linked list */
-	acxpci_s_device_chain_add(ndev);
-
 	log(L_IRQ|L_INIT, "using IRQ %d\n", pdev->irq);
 
 	/* need to be able to restore PCI state after a suspend */
@@ -1731,7 +1711,6 @@ fail_register_netdev:
 fail_init_mac:
 fail_reset:
 
-	acxpci_s_device_chain_remove(ndev);
 	free_netdev(ndev);
 fail_alloc_netdev:
 fail_irq:
@@ -1765,11 +1744,8 @@ done:
 /***********************************************************************
 ** acxpci_e_remove
 **
-** Deallocate PCI resources for the acx chip.
-**
-** This should NOT execute any other hardware operations on the card,
-** since the card might already be ejected. Instead, that should be done
-** in cleanup_module, since the card is most likely still available there.
+** Shut device down (if not hot unplugged)
+** and deallocate PCI resources for the acx chip.
 **
 ** pdev - ptr to PCI device structure containing info about pci configuration
 */
@@ -1779,6 +1755,7 @@ acxpci_e_remove(struct pci_dev *pdev)
 	struct net_device *ndev;
 	acx_device_t *adev;
 	unsigned long mem_region1, mem_region2;
+	unsigned long flags;
 
 	FN_ENTER;
 
@@ -1791,6 +1768,43 @@ acxpci_e_remove(struct pci_dev *pdev)
 
 	adev = ndev2adev(ndev);
 
+	/* If device wasn't hot unplugged... */
+	if (adev_present(adev)) {
+
+		acx_sem_lock(adev);
+
+		/* disable both Tx and Rx to shut radio down properly */
+		acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
+		acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
+
+#ifdef REDUNDANT
+		/* put the eCPU to sleep to save power
+		 * Halting is not possible currently,
+		 * since not supported by all firmware versions */
+		acx_s_issue_cmd(adev, ACX100_CMD_SLEEP, NULL, 0);
+#endif
+		acx_lock(adev, flags);
+		/* disable power LED to save power :-) */
+		log(L_INIT, "switching off power LED to save power\n");
+		acxpci_l_power_led(adev, 0);
+		/* stop our eCPU */
+		if (IS_ACX111(adev)) {
+			/* FIXME: does this actually keep halting the eCPU?
+			 * I don't think so...
+			 */
+			acxpci_l_reset_mac(adev);
+		} else {
+			u16 temp;
+			/* halt eCPU */
+			temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1;
+			write_reg16(adev, IO_ACX_ECPU_CTRL, temp);
+			write_flush(adev);
+		}
+		acx_unlock(adev, flags);
+
+		acx_sem_unlock(adev);
+	}
+
 	/* unregister the device to not let the kernel
 	 * (e.g. ioctls) access a half-deconfigured device
 	 * NB: this will cause acxpci_e_close() to be called,
@@ -1802,6 +1816,13 @@ acxpci_e_remove(struct pci_dev *pdev)
 	 * For paranoid reasons we continue to follow the rules */
 	acx_sem_lock(adev);
 
+	if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
+		acxpci_s_down(ndev);
+		CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
+	}
+
+	acx_proc_unregister_entries(ndev);
+
 	if (IS_ACX100(adev)) {
 		mem_region1 = PCI_ACX100_REGION1;
 		mem_region2 = PCI_ACX100_REGION2;
@@ -1810,33 +1831,21 @@ acxpci_e_remove(struct pci_dev *pdev)
 		mem_region2 = PCI_ACX111_REGION2;
 	}
 
-	acx_proc_unregister_entries(ndev);
-
-	/* find our PCI device in the global acx list and remove it */
-	acxpci_s_device_chain_remove(ndev);
-
-	if (adev->dev_state_mask & ACX_STATE_IFACE_UP)
-		acxpci_s_down(ndev);
-
-	CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
-
-	acxpci_s_delete_dma_regions(adev);
-
 	/* finally, clean up PCI bus state */
+	acxpci_s_delete_dma_regions(adev);
 	if (adev->iobase) iounmap(adev->iobase);
 	if (adev->iobase2) iounmap(adev->iobase2);
-
 	release_mem_region(pci_resource_start(pdev, mem_region1),
 			   pci_resource_len(pdev, mem_region1));
-
 	release_mem_region(pci_resource_start(pdev, mem_region2),
 			   pci_resource_len(pdev, mem_region2));
-
 	pci_disable_device(pdev);
 
 	/* remove dev registration */
 	pci_set_drvdata(pdev, NULL);
 
+	acx_sem_unlock(adev);
+
 	/* Free netdev (quite late,
 	 * since otherwise we might get caught off-guard
 	 * by a netdev timeout handler execution
@@ -2008,10 +2017,10 @@ acxpci_s_up(struct net_device *ndev)
 /***********************************************************************
 ** acxpci_s_down
 **
-** This disables the netdevice
+** NB: device may be already hot unplugged if called from acxpci_e_remove()
 **
-** Side effects:
-** - disables on-card interrupt request
+** Disables on-card interrupt request, stops softirq and timer, stops queue,
+** sets status == STOPPED
 */
 
 static void
@@ -2298,7 +2307,7 @@ static void
 acxpci_l_process_rxdesc(acx_device_t *adev)
 {
 	register rxhostdesc_t *hostdesc;
-	int count, tail;
+	unsigned count, tail;
 
 	FN_ENTER;
 
@@ -3026,11 +3035,11 @@ acx100pci_ioctl_set_phy_amp_bias(
 ** after figuring out how many we need and whether we still have
 ** sufficiently many.
 */
-tx_t*
+static tx_t*
 acxpci_l_alloc_tx(acx_device_t *adev)
 {
 	struct txdesc *txdesc;
-	int head;
+	unsigned head;
 	u8 ctl8;
 
 	FN_ENTER;
@@ -3078,10 +3087,15 @@ end:
 	return (tx_t*)txdesc;
 }
 
+/* Dummy function. */
+static void
+acxpci_l_dealloc_tx(tx_t *tx_opaque)
+{
+}
 
 /***********************************************************************
 */
-void*
+static void*
 acxpci_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque)
 {
 	return get_txhostdesc(adev, (txdesc_t*)tx_opaque)->data;
@@ -3098,7 +3112,7 @@ acxpci_l_get_txbuf(acx_device_t *adev, t
 ** pre-allocated tx descrs, properly setting up transfer data and
 ** CTL_xxx flags according to fragment number.
 */
-void
+static void
 acxpci_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int len)
 {
 	txdesc_t *txdesc = (txdesc_t*)tx_opaque;
@@ -3391,7 +3405,7 @@ unsigned int
 acxpci_l_clean_txdesc(acx_device_t *adev)
 {
 	txdesc_t *txdesc;
-	int finger;
+	unsigned finger;
 	int num_cleaned;
 	u16 r111;
 	u8 error, ack_failures, rts_failures, rts_ok, r100;
@@ -4213,70 +4227,12 @@ acxpci_e_init_module(void)
 void __exit
 acxpci_e_cleanup_module(void)
 {
-	struct net_device *ndev;
-	unsigned long flags;
-
 	FN_ENTER;
 
-	/* Since the whole module is about to be unloaded,
-	 * we recursively shutdown all cards we handled instead
-	 * of doing it in acxpci_e_remove() (which will be activated by us
-	 * via pci_unregister_driver at the end).
-	 * acxpci_e_remove() might just get called after a card eject,
-	 * that's why hardware operations have to be done here instead
-	 * when the hardware is available. */
-
-	down(&root_adev_sem);
-
-	ndev = root_adev_newest;
-	while (ndev) {
-		acx_device_t *adev = ndev2adev(ndev);
-
-		acx_sem_lock(adev);
-
-		/* disable both Tx and Rx to shut radio down properly */
-		acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
-		acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
-
-#ifdef REDUNDANT
-		/* put the eCPU to sleep to save power
-		 * Halting is not possible currently,
-		 * since not supported by all firmware versions */
-		acx_s_issue_cmd(adev, ACX100_CMD_SLEEP, NULL, 0);
-#endif
-		acx_lock(adev, flags);
-
-		/* disable power LED to save power :-) */
-		log(L_INIT, "switching off power LED to save power\n");
-		acxpci_l_power_led(adev, 0);
-
-		/* stop our eCPU */
-		if (IS_ACX111(adev)) {
-			/* FIXME: does this actually keep halting the eCPU?
-			 * I don't think so...
-			 */
-			acxpci_l_reset_mac(adev);
-		} else {
-			u16 temp;
-
-			/* halt eCPU */
-			temp = read_reg16(adev, IO_ACX_ECPU_CTRL) | 0x1;
-			write_reg16(adev, IO_ACX_ECPU_CTRL, temp);
-			write_flush(adev);
-		}
-
-		acx_unlock(adev, flags);
-
-		acx_sem_unlock(adev);
-
-		ndev = adev->prev_nd;
-	}
-
-	up(&root_adev_sem);
-
-	/* now let the PCI layer recursively remove
-	 * all PCI related things (acxpci_e_remove()) */
 	pci_unregister_driver(&acxpci_drv_id);
 
 	FN_EXIT0;
 }
+
+module_init(acxpci_e_init_module);
+module_exit(acxpci_e_cleanup_module);
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/usb.c wireless-2.6.git.acx/drivers/net/wireless/tiacx/usb.c
--- wireless-2.6.git/drivers/net/wireless/tiacx/usb.c	Wed Mar  1 07:56:14 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/usb.c	Wed Mar  1 12:05:04 2006
@@ -123,10 +123,30 @@ static void acxusb_l_poll_rx(acx_device_
 
 static void acxusb_i_tx_timeout(struct net_device *);
 
+#if ACX_DEBUG
+static int acxusb_s_issue_cmd_timeo_debug(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout, const char* cmdstr);
+#else
+static int acxusb_s_issue_cmd_timeo(acx_device_t *adev, unsigned cmd, void *param, unsigned len, unsigned timeout);
+#endif
+static int acxusb_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf);
+static int acxusb_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value);
+static tx_t* acxusb_l_alloc_tx(acx_device_t *adev);
+static void acxusb_l_dealloc_tx(tx_t *tx_opaque);
+static void* acxusb_l_get_txbuf(acx_device_t *adev, tx_t *tx_opaque);
+static void acxusb_l_tx_data(acx_device_t *adev, tx_t *tx_opaque, int len);
+
 /* static void dump_device(struct usb_device *); */
 /* static void dump_device_descriptor(struct usb_device_descriptor *); */
 /* static void dump_config_descriptor(struct usb_config_descriptor *); */
 
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("Dual MPL/GPL");
+#endif
+/* USB had this: MODULE_AUTHOR("Martin Wawro <martin.wawro AT uni-dortmund.de>"); */
+MODULE_AUTHOR("ACX100 Open Source Driver development team");
+MODULE_DESCRIPTION("Driver for TI ACX1xx based wireless cards (USB)");
+
+
 /***********************************************************************
 ** Module Data
 */
@@ -150,6 +170,7 @@ acxusb_ids[] = {
 	{}
 };
 
+MODULE_DEVICE_TABLE(usb, acxusb_ids);
 
 /* USB driver data structure as required by the kernel's USB core */
 static struct usb_driver
@@ -211,7 +232,7 @@ acxusb_unlink_urb(struct urb* urb)
 /***********************************************************************
 ** acxusb_s_read_phy_reg
 */
-int
+static int
 acxusb_s_read_phy_reg(acx_device_t *adev, u32 reg, u8 *charbuf)
 {
 	/* mem_read_write_t mem; */
@@ -236,7 +257,7 @@ acxusb_s_read_phy_reg(acx_device_t *adev
 
 /***********************************************************************
 */
-int
+static int
 acxusb_s_write_phy_reg(acx_device_t *adev, u32 reg, u8 value)
 {
 	mem_read_write_t mem;
@@ -270,17 +291,15 @@ acxusb_s_write_phy_reg(acx_device_t *ade
 #undef FUNC
 #define FUNC "issue_cmd"
 
+static int
 #if !ACX_DEBUG
-int
 acxusb_s_issue_cmd_timeo(
 	acx_device_t *adev,
 	unsigned cmd,
 	void *buffer,
 	unsigned buflen,
 	unsigned timeout)
-{
 #else
-int
 acxusb_s_issue_cmd_timeo_debug(
 	acx_device_t *adev,
 	unsigned cmd,
@@ -288,8 +307,8 @@ acxusb_s_issue_cmd_timeo_debug(
 	unsigned buflen,
 	unsigned timeout,
 	const char* cmdstr)
-{
 #endif
+{
 	/* USB ignores timeout param */
 
 	struct usb_device *usbdev;
@@ -754,6 +773,11 @@ acxusb_s_fill_configoption(acx_device_t 
 	return OK;
 }
 
+/* Dummy function. */
+static void
+acxusb_s_delete_dma_regions(acx_device_t *adev)
+{
+}
 
 /***********************************************************************
 ** acxusb_e_probe()
@@ -882,6 +906,20 @@ acxusb_e_probe(struct usb_interface *int
 	adev->ieee->sec.encrypt = 0;
 	adev->ieee->sec.auth_mode = WLAN_AUTH_OPEN;
 
+	adev->ops.create_dma_regions = acx100_s_create_dma_regions;
+	adev->ops.delete_dma_regions = acxusb_s_delete_dma_regions;
+#if ACX_DEBUG
+	adev->ops.issue_cmd = acxusb_s_issue_cmd_timeo_debug;
+#else
+	adev->ops.issue_cmd  = acxusb_s_issue_cmd_timeo;
+#endif /* ACX_DEBUG */
+	adev->ops.alloc_tx = acxusb_l_alloc_tx;
+	adev->ops.dealloc_tx = acxusb_l_dealloc_tx;
+	adev->ops.get_txbuf = acxusb_l_get_txbuf;
+	adev->ops.tx_data = acxusb_l_tx_data;
+	adev->ops.write_phy_reg = acxusb_s_write_phy_reg;
+	adev->ops.read_phy_reg = acxusb_s_read_phy_reg;
+
 	/* Check that this is really the hardware we know about.
 	** If not sure, at least notify the user that he
 	** may be in trouble...
@@ -1582,11 +1620,11 @@ end_unlock:
 ** acxusb_l_alloc_tx
 ** Actually returns a usb_tx_t* ptr
 */
-tx_t*
+static tx_t*
 acxusb_l_alloc_tx(acx_device_t *adev)
 {
 	usb_tx_t *tx;
-	int head;
+	unsigned head;
 
 	FN_ENTER;
 
@@ -1620,7 +1658,7 @@ end:
 /***************************************************************
 ** Used if alloc_tx()'ed buffer needs to be cancelled without doing tx
 */
-void
+static void
 acxusb_l_dealloc_tx(tx_t *tx_opaque)
 {
 	usb_tx_t* tx = (usb_tx_t*)tx_opaque;
@@ -1630,7 +1668,7 @@ acxusb_l_dealloc_tx(tx_t *tx_opaque)
 
 /***************************************************************
 */
-void*
+static void*
 acxusb_l_get_txbuf(acx_device_t *adev, tx_t* tx_opaque)
 {
 	usb_tx_t* tx = (usb_tx_t*)tx_opaque;
@@ -1644,7 +1682,7 @@ acxusb_l_get_txbuf(acx_device_t *adev, t
 ** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx).
 ** Can be called from acx_i_start_xmit (data frames from net core).
 */
-void
+static void
 acxusb_l_tx_data(acx_device_t *adev, tx_t* tx_opaque, int wlanpkt_len)
 {
 	struct usb_device *usbdev;
@@ -1810,7 +1848,8 @@ acxusb_e_cleanup_module()
 	usb_deregister(&acxusb_driver);
 }
 
-
+module_init(acxusb_e_init_module);
+module_exit(acxusb_e_cleanup_module);
 /***********************************************************************
 ** DEBUG STUFF
 */

^ permalink raw reply

* [PATCH] pktgen: Convert thread lock to mutexes.
From: Luiz Fernando Capitulino @ 2006-03-01 13:52 UTC (permalink / raw)
  To: davem; +Cc: lkml, netdev, robert.olsson


 Hi!

 pktgen's thread semaphores are strict mutexes, convert them to the mutex
implementation.

Signed-off-by: Luiz Capitulino <lcapitulino@mandriva.com.br>

---

 net/core/pktgen.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

1185abd5dacbca3052ccd93e059c497bbc8869b2
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 2221b86..2618a7b 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -113,6 +113,7 @@
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
@@ -153,7 +154,7 @@
 #include <asm/div64.h>		/* do_div */
 #include <asm/timex.h>
 
-#define VERSION  "pktgen v2.65: Packet Generator for packet performance testing.\n"
+#define VERSION  "pktgen v2.66: Packet Generator for packet performance testing.\n"
 
 /* #define PG_DEBUG(a) a */
 #define PG_DEBUG(a)
@@ -180,8 +181,8 @@
 #define T_REMDEV      (1<<4)	/* Remove one dev */
 
 /* Locks */
-#define   thread_lock()        down(&pktgen_sem)
-#define   thread_unlock()      up(&pktgen_sem)
+#define   thread_lock()        mutex_lock(&pktgen_mutex)
+#define   thread_unlock()      mutex_unlock(&pktgen_mutex)
 
 /* If lock -- can be removed after some work */
 #define   if_lock(t)           spin_lock(&(t->if_lock));
@@ -493,7 +494,7 @@ static int pg_delay_d;
 static int pg_clone_skb_d;
 static int debug;
 
-static DECLARE_MUTEX(pktgen_sem);
+static DEFINE_MUTEX(pktgen_mutex);
 static LIST_HEAD(pktgen_threads);
 
 static struct notifier_block pktgen_notifier_block = {
-- 
1.2.3.g8fcf1

-- 
Luiz Fernando N. Capitulino

^ permalink raw reply related

* [git patches] net driver fixes
From: Jeff Garzik @ 2006-02-28 23:10 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: netdev, linux-kernel


Please pull from 'upstream-fixes' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git

to receive the following updates:

 drivers/net/8139cp.c         |   37 +++++++++++---------
 drivers/net/sky2.c           |   77 -------------------------------------------
 drivers/net/sky2.h           |    1 
 drivers/net/via-velocity.c   |    3 +
 net/ieee80211/ieee80211_rx.c |   16 ++------
 5 files changed, 29 insertions(+), 105 deletions(-)

Francois Romieu:
      via-velocity: fix memory corruption when changing the mtu
      8139cp: fix broken suspend/resume

Pete Zaitcev:
      ieee80211_rx.c: is_beacon

Stephen Hemminger:
      sky2: remove MSI support

diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index f822cd3..dd41049 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1118,13 +1118,18 @@ err_out:
 	return -ENOMEM;
 }
 
+static void cp_init_rings_index (struct cp_private *cp)
+{
+	cp->rx_tail = 0;
+	cp->tx_head = cp->tx_tail = 0;
+}
+
 static int cp_init_rings (struct cp_private *cp)
 {
 	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
 	cp->tx_ring[CP_TX_RING_SIZE - 1].opts1 = cpu_to_le32(RingEnd);
 
-	cp->rx_tail = 0;
-	cp->tx_head = cp->tx_tail = 0;
+	cp_init_rings_index(cp);
 
 	return cp_refill_rx (cp);
 }
@@ -1886,30 +1891,30 @@ static int cp_suspend (struct pci_dev *p
 
 	spin_unlock_irqrestore (&cp->lock, flags);
 
-	if (cp->pdev && cp->wol_enabled) {
-		pci_save_state (cp->pdev);
-		cp_set_d3_state (cp);
-	}
+	pci_save_state(pdev);
+	pci_enable_wake(pdev, pci_choose_state(pdev, state), cp->wol_enabled);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
 	return 0;
 }
 
 static int cp_resume (struct pci_dev *pdev)
 {
-	struct net_device *dev;
-	struct cp_private *cp;
+	struct net_device *dev = pci_get_drvdata (pdev);
+	struct cp_private *cp = netdev_priv(dev);
 	unsigned long flags;
 
-	dev = pci_get_drvdata (pdev);
-	cp  = netdev_priv(dev);
+	if (!netif_running(dev))
+		return 0;
 
 	netif_device_attach (dev);
-	
-	if (cp->pdev && cp->wol_enabled) {
-		pci_set_power_state (cp->pdev, PCI_D0);
-		pci_restore_state (cp->pdev);
-	}
-	
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_enable_wake(pdev, PCI_D0, 0);
+
+	/* FIXME: sh*t may happen if the Rx ring buffer is depleted */
+	cp_init_rings_index (cp);
 	cp_init_hw (cp);
 	netif_start_queue (dev);
 
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index ca8160d..72c1630 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -96,10 +96,6 @@ static int copybreak __read_mostly = 256
 module_param(copybreak, int, 0);
 MODULE_PARM_DESC(copybreak, "Receive copy threshold");
 
-static int disable_msi = 0;
-module_param(disable_msi, int, 0);
-MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
-
 static const struct pci_device_id sky2_id_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
@@ -3126,61 +3122,6 @@ static void __devinit sky2_show_addr(str
 		       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 }
 
-/* Handle software interrupt used during MSI test */
-static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id,
-					    struct pt_regs *regs)
-{
-	struct sky2_hw *hw = dev_id;
-	u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2);
-
-	if (status == 0)
-		return IRQ_NONE;
-
-	if (status & Y2_IS_IRQ_SW) {
-		sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
-		hw->msi = 1;
-	}
-	sky2_write32(hw, B0_Y2_SP_ICR, 2);
-
-	sky2_read32(hw, B0_IMSK);
-	return IRQ_HANDLED;
-}
-
-/* Test interrupt path by forcing a a software IRQ */
-static int __devinit sky2_test_msi(struct sky2_hw *hw)
-{
-	struct pci_dev *pdev = hw->pdev;
-	int i, err;
-
-	sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW);
-
-	err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw);
-	if (err) {
-		printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
-		       pci_name(pdev), pdev->irq);
-		return err;
-	}
-
-	sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
-	wmb();
-
-	for (i = 0; i < 10; i++) {
-		barrier();
-		if (hw->msi)
-			goto found;
-		mdelay(1);
-	}
-
-	err = -EOPNOTSUPP;
-	sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
- found:
-	sky2_write32(hw, B0_IMSK, 0);
-
-	free_irq(pdev->irq, hw);
-
-	return err;
-}
-
 static int __devinit sky2_probe(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
@@ -3302,20 +3243,6 @@ static int __devinit sky2_probe(struct p
 		}
 	}
 
-	if (!disable_msi && pci_enable_msi(pdev) == 0) {
-		err = sky2_test_msi(hw);
-		if (err == -EOPNOTSUPP) {
-			/* MSI test failed, go back to INTx mode */
-			printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, "
-			       "switching to INTx mode. Please report this failure to "
-			       "the PCI maintainer and include system chipset information.\n",
-			       pci_name(pdev));
-			pci_disable_msi(pdev);
-		}
-		else if (err)
-			goto err_out_unregister;
-	}
-
 	err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ | SA_SAMPLE_RANDOM,
 			  DRV_NAME, hw);
 	if (err) {
@@ -3332,8 +3259,6 @@ static int __devinit sky2_probe(struct p
 	return 0;
 
 err_out_unregister:
-	if (hw->msi)
-		pci_disable_msi(pdev);
 	if (dev1) {
 		unregister_netdev(dev1);
 		free_netdev(dev1);
@@ -3376,8 +3301,6 @@ static void __devexit sky2_remove(struct
 	sky2_read8(hw, B0_CTST);
 
 	free_irq(pdev->irq, hw);
-	if (hw->msi)
-		pci_disable_msi(pdev);
 	pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 3edb980..dce955c 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1881,7 +1881,6 @@ struct sky2_hw {
 	u32		     intr_mask;
 
 	int		     pm_cap;
-	int		     msi;
 	u8	     	     chip_id;
 	u8		     chip_rev;
 	u8		     copper;
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index c2d5907..ed1f837 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -1106,6 +1106,9 @@ static void velocity_free_rd_ring(struct
 
 	for (i = 0; i < vptr->options.numrx; i++) {
 		struct velocity_rd_info *rd_info = &(vptr->rd_info[i]);
+		struct rx_desc *rd = vptr->rd_ring + i;
+
+		memset(rd, 0, sizeof(*rd));
 
 		if (!rd_info->skb)
 			continue;
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 960aa78..b410ab8 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -1301,7 +1301,7 @@ static void update_network(struct ieee80
 	/* dst->last_associate is not overwritten */
 }
 
-static inline int is_beacon(int fc)
+static inline int is_beacon(__le16 fc)
 {
 	return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
 }
@@ -1348,9 +1348,7 @@ static void ieee80211_process_probe_resp
 				     escape_essid(info_element->data,
 						  info_element->len),
 				     MAC_ARG(beacon->header.addr3),
-				     is_beacon(le16_to_cpu
-					       (beacon->header.
-						frame_ctl)) ?
+				     is_beacon(beacon->header.frame_ctl) ?
 				     "BEACON" : "PROBE RESPONSE");
 		return;
 	}
@@ -1400,9 +1398,7 @@ static void ieee80211_process_probe_resp
 				     escape_essid(network.ssid,
 						  network.ssid_len),
 				     MAC_ARG(network.bssid),
-				     is_beacon(le16_to_cpu
-					       (beacon->header.
-						frame_ctl)) ?
+				     is_beacon(beacon->header.frame_ctl) ?
 				     "BEACON" : "PROBE RESPONSE");
 #endif
 		memcpy(target, &network, sizeof(*target));
@@ -1412,16 +1408,14 @@ static void ieee80211_process_probe_resp
 				     escape_essid(target->ssid,
 						  target->ssid_len),
 				     MAC_ARG(target->bssid),
-				     is_beacon(le16_to_cpu
-					       (beacon->header.
-						frame_ctl)) ?
+				     is_beacon(beacon->header.frame_ctl) ?
 				     "BEACON" : "PROBE RESPONSE");
 		update_network(target, &network);
 	}
 
 	spin_unlock_irqrestore(&ieee->lock, flags);
 
-	if (is_beacon(le16_to_cpu(beacon->header.frame_ctl))) {
+	if (is_beacon(beacon->header.frame_ctl)) {
 		if (ieee->handle_beacon != NULL)
 			ieee->handle_beacon(dev, beacon, &network);
 	} else {

^ permalink raw reply related

* Re: [PATCH 0/6] pktgen: refinements and small fixes (V3).
From: David S. Miller @ 2006-02-28 20:45 UTC (permalink / raw)
  To: lcapitulino; +Cc: linux-kernel, netdev, robert.olsson
In-Reply-To: <20060225160734.020bba3b@home.brethil>

From: Luiz Fernando Capitulino <lcapitulino@mandriva.com.br>
Date: Sat, 25 Feb 2006 16:07:34 -0300

>  As you've asked, I'm sending again my patches for pktgen:
> 
> [PATCH 1/6] pktgen: Lindent run.
> [PATCH 2/6] pktgen: Ports thread list to Kernel list implementation.
> [PATCH 3/6] pktgen: Fix kernel_thread() fail leak.
> [PATCH 4/6] pktgen: Fix Initialization fail leak.
> [PATCH 5/6] pktgen: Ports if_list to the in-kernel implementation.
> [PATCH 6/6] pktgen: Updates version.

All applied, thanks a lot Luiz.

^ permalink raw reply

* [PATCH 3/7] acxsm: Create struct acx_ops
From: Carlos Martin @ 2006-02-28 16:30 UTC (permalink / raw)
  To: netdev
  Cc: Denis Vlasenko, acx100-devel, Christoph Hellwig, Carlos Martin,
	Carlos Martin
In-Reply-To: <1141144213577-git-send-email-carlos@cmartin.tk>

struct acx_ops is where the device-specific functions go. This allows
us to call these functions from the acx-common.ko module without
creating recursive dependencies.

Signed-off-by: Carlos Martin <carlos@cmartin.tk>

---

 acx_struct.h |   32 ++++++++++++++++++++++++++++----
 1 files changed, 28 insertions(+), 4 deletions(-)

fe7e63091292e78cb523c8060b267c0faeb3b898
diff --git a/acx_struct.h b/acx_struct.h
index 93495e0..227b6e3 100644
--- a/acx_struct.h
+++ b/acx_struct.h
@@ -87,6 +87,31 @@ enum { acx_debug = 0 };
 #define SCHEDULE_WORK schedule_work
 #define FLUSH_SCHEDULED_WORK flush_scheduled_work
 
+/***********************************************************************
+** Chip-specific functions get set here.
+*/
+
+struct acx_ops {
+	int (*create_dma_regions)(acx_device_t *);
+	void (*delete_dma_regions)(acx_device_t *);
+
+#if ACX_DEBUG
+	int (*issue_cmd)(acx_device_t *adev, unsigned cmd, void *param,
+			 unsigned len, unsigned cmd_timeout, const char *cmdstr);
+#else
+	int (*issue_cmd)(acx_device_t *adev, unsigned cmd, void *param,
+			 unsigned len, unsigned cmd_timeout);
+#endif /* ACX_DEBUG */
+	tx_t* (*alloc_tx)(acx_device_t *adev);
+	void (*dealloc_tx)(tx_t *tx_opaque);
+
+	void* (*get_txbuf)(acx_device_t *adev, tx_t *tx_opaque);
+	void (*tx_data)(acx_device_t *adev, tx_t *tx_opaque, int len);
+
+	int (*write_phy_reg)(acx_device_t *adev, u32 reg, u8 value);
+	int (*read_phy_reg)(acx_device_t *adev, u32 reg, u8 *charbuf);
+};
+
 
 /***********************************************************************
 ** Constants
@@ -105,10 +130,6 @@ enum { acx_debug = 0 };
 #define DEVTYPE_PCI		0
 #define DEVTYPE_USB		1
 
-#if !defined(CONFIG_ACX_PCI) && !defined(CONFIG_ACX_USB)
-#error Driver must include PCI and/or USB support. You selected neither.
-#endif
-
 #if defined(CONFIG_ACX_PCI)
  #if !defined(CONFIG_ACX_USB)
   #define IS_PCI(adev)	1
@@ -1198,6 +1219,9 @@ struct acx_device {
 	/*** Linux network device ***/
 	struct net_device	*ndev;		/* pointer to linux netdevice */
 
+	/* Chip-specific functions */
+	struct acx_ops		ops;
+
 	/*** Device statistics ***/
 	struct net_device_stats	stats;		/* net device statistics */
 #ifdef WIRELESS_EXT
-- 
1.2.1.g62a4




-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid\x110944&bid$1720&dat\x121642

^ permalink raw reply related


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